diff options
author | Andrey Andreev <narf@devilix.net> | 2016-07-26 20:03:12 +0200 |
---|---|---|
committer | Andrey Andreev <narf@devilix.net> | 2016-07-26 20:03:12 +0200 |
commit | 77266bc6a01668b2106b9974da02e2a7ceaf2fe6 (patch) | |
tree | 955346c3278c03a2ff4174b9d078e9416a298ee9 /system | |
parent | a9874a638970ef826f835718e58b197ff3672566 (diff) | |
parent | 0b9540209499fbd0515e13fdc66e85dea4b6baad (diff) |
Merge branch '3.1-stable' into develop
Conflicts resolved:
.travis.yml
system/core/CodeIgniter.php
system/database/drivers/oci8/oci8_forge.php
system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
system/helpers/path_helper.php
system/libraries/Email.php
user_guide_src/source/changelog.rst
user_guide_src/source/conf.py
user_guide_src/source/contributing/index.rst
user_guide_src/source/general/requirements.rst
user_guide_src/source/general/styleguide.rst
user_guide_src/source/installation/downloads.rst
user_guide_src/source/installation/upgrade_310.rst
user_guide_src/source/installation/upgrading.rst
Diffstat (limited to 'system')
35 files changed, 391 insertions, 301 deletions
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index d9ac7efe3..5e60a8d40 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -55,7 +55,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); * @var string * */ - define('CI_VERSION', '3.1.0-dev'); + define('CI_VERSION', '3.2.0-dev'); /* * ------------------------------------------------------ diff --git a/system/core/Config.php b/system/core/Config.php index 5c6ba2a4d..e74751639 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -319,7 +319,7 @@ class CI_Config { } } - return $base_url.ltrim($this->_uri_string($uri), '/'); + return $base_url.$this->_uri_string($uri); } // ------------------------------------------------------------- @@ -337,11 +337,8 @@ class CI_Config { { if ($this->item('enable_query_strings') === FALSE) { - if (is_array($uri)) - { - $uri = implode('/', $uri); - } - return trim($uri, '/'); + is_array($uri) && $uri = implode('/', $uri); + return ltrim($uri, '/'); } elseif (is_array($uri)) { diff --git a/system/core/Input.php b/system/core/Input.php index 59b39620c..f6397e35b 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -519,9 +519,9 @@ class CI_Input { if ($separator === ':') { $netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr)); - for ($i = 0; $i < 8; $i++) + for ($j = 0; $j < 8; $j++) { - $netaddr[$i] = intval($netaddr[$i], 16); + $netaddr[$i] = intval($netaddr[$j], 16); } } else @@ -760,30 +760,32 @@ class CI_Input { // If header is already defined, return it immediately if ( ! empty($this->headers)) { - return $this->headers; + return $this->_fetch_from_array($this->headers, NULL, $xss_clean); } // In Apache, you can simply call apache_request_headers() if (function_exists('apache_request_headers')) { - return $this->headers = apache_request_headers(); + $this->headers = apache_request_headers(); } - - $this->headers['Content-Type'] = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE'); - - foreach ($_SERVER as $key => $val) + else { - if (sscanf($key, 'HTTP_%s', $header) === 1) + isset($_SERVER['CONTENT_TYPE']) && $this->headers['Content-Type'] = $_SERVER['CONTENT_TYPE']; + + foreach ($_SERVER as $key => $val) { - // take SOME_HEADER and turn it into Some-Header - $header = str_replace('_', ' ', strtolower($header)); - $header = str_replace(' ', '-', ucwords($header)); + if (sscanf($key, 'HTTP_%s', $header) === 1) + { + // take SOME_HEADER and turn it into Some-Header + $header = str_replace('_', ' ', strtolower($header)); + $header = str_replace(' ', '-', ucwords($header)); - $this->headers[$header] = $this->_fetch_from_array($_SERVER, $key, $xss_clean); + $this->headers[$header] = $_SERVER[$key]; + } } } - return $this->headers; + return $this->_fetch_from_array($this->headers, NULL, $xss_clean); } // -------------------------------------------------------------------- diff --git a/system/core/compat/password.php b/system/core/compat/password.php index f0c22c780..76dd2cf0a 100644 --- a/system/core/compat/password.php +++ b/system/core/compat/password.php @@ -116,13 +116,21 @@ if ( ! function_exists('password_hash')) } elseif ( ! isset($options['salt'])) { - if (defined('MCRYPT_DEV_URANDOM')) + if (function_exists('random_bytes')) { - $options['salt'] = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); + try + { + $options['salt'] = random_bytes(16); + } + catch (Exception $e) + { + log_message('error', 'compat/password: Error while trying to use random_bytes(): '.$e->getMessage()); + return FALSE; + } } - elseif (function_exists('openssl_random_pseudo_bytes')) + elseif (defined('MCRYPT_DEV_URANDOM')) { - $options['salt'] = openssl_random_pseudo_bytes(16); + $options['salt'] = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); } elseif (DIRECTORY_SEPARATOR === '/' && (is_readable($dev = '/dev/arandom') OR is_readable($dev = '/dev/urandom'))) { @@ -148,6 +156,16 @@ if ( ! function_exists('password_hash')) fclose($fp); } + elseif (function_exists('openssl_random_pseudo_bytes')) + { + $is_secure = NULL; + $options['salt'] = openssl_random_pseudo_bytes(16, $is_secure); + if ($is_secure !== TRUE) + { + log_message('error', 'compat/password: openssl_random_pseudo_bytes() set the $cryto_strong flag to FALSE'); + return FALSE; + } + } else { log_message('error', 'compat/password: No CSPRNG available.'); diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index c862d937d..713bf18f3 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -1395,7 +1395,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->qb_orderby = NULL; } - $result = ($this->qb_distinct === TRUE) + $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby)) ? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results") : $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows'))); @@ -1498,8 +1498,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $affected_rows = 0; for ($i = 0, $total = count($this->qb_set); $i < $total; $i += $batch_size) { - $this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, $batch_size))); - $affected_rows += $this->affected_rows(); + if ($this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, $batch_size)))) + { + $affected_rows += $this->affected_rows(); + } } $this->_reset_write(); @@ -1913,8 +1915,11 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $affected_rows = 0; for ($i = 0, $total = count($this->qb_set); $i < $total; $i += $batch_size) { - $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, $batch_size), $this->protect_identifiers($index))); - $affected_rows += $this->affected_rows(); + if ($this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, $batch_size), $this->protect_identifiers($index)))) + { + $affected_rows += $this->affected_rows(); + } + $this->qb_where = array(); } diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php index 8262beb6b..46a3b2185 100644 --- a/system/database/drivers/cubrid/cubrid_forge.php +++ b/system/database/drivers/cubrid/cubrid_forge.php @@ -178,6 +178,9 @@ class CI_DB_cubrid_forge extends CI_DB_forge { $attributes['TYPE'] = 'INTEGER'; $attributes['UNSIGNED'] = FALSE; return; + case 'LONGTEXT': + $attributes['TYPE'] = 'STRING'; + return; default: return; } } diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 72e31e00d..76f58564b 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -159,6 +159,7 @@ class CI_DB_mssql_driver extends CI_DB { if (mssql_select_db('['.$database.']', $this->conn_id)) { $this->database = $database; + $this->data_cache = array(); return TRUE; } diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php index 24d1fc204..91b5794bc 100644 --- a/system/database/drivers/mssql/mssql_forge.php +++ b/system/database/drivers/mssql/mssql_forge.php @@ -113,6 +113,11 @@ class CI_DB_mssql_forge extends CI_DB_forge { */ protected function _attr_type(&$attributes) { + if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE) + { + unset($attributes['CONSTRAINT']); + } + switch (strtoupper($attributes['TYPE'])) { case 'MEDIUMINT': diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php index d903406d1..70b4f68ba 100644 --- a/system/database/drivers/mysql/mysql_driver.php +++ b/system/database/drivers/mysql/mysql_driver.php @@ -220,6 +220,7 @@ class CI_DB_mysql_driver extends CI_DB { if (mysql_select_db($database, $this->conn_id)) { $this->database = $database; + $this->data_cache = array(); return TRUE; } diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php index 431bce50a..168533240 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -263,6 +263,7 @@ class CI_DB_mysqli_driver extends CI_DB { if ($this->conn_id->select_db($database)) { $this->database = $database; + $this->data_cache = array(); return TRUE; } diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php index 59f0e8456..df7e0848a 100644 --- a/system/database/drivers/oci8/oci8_driver.php +++ b/system/database/drivers/oci8/oci8_driver.php @@ -559,23 +559,29 @@ class CI_DB_oci8_driver extends CI_DB { */ public function error() { - /* oci_error() returns an array that already contains the - * 'code' and 'message' keys, so we can just return it. - */ + // oci_error() returns an array that already contains + // 'code' and 'message' keys, but it can return false + // if there was no error .... if (is_resource($this->curs_id)) { - return oci_error($this->curs_id); + $error = oci_error($this->curs_id); } elseif (is_resource($this->stmt_id)) { - return oci_error($this->stmt_id); + $error = oci_error($this->stmt_id); } elseif (is_resource($this->conn_id)) { - return oci_error($this->conn_id); + $error = oci_error($this->conn_id); + } + else + { + $error = oci_error(); } - return oci_error(); + return is_array($error) + ? $error + : array('code' => '', 'message' => ''); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php index 989c7a8b7..23e025757 100644 --- a/system/database/drivers/oci8/oci8_forge.php +++ b/system/database/drivers/oci8/oci8_forge.php @@ -182,5 +182,4 @@ class CI_DB_oci8_forge extends CI_DB_forge { default: return; } } - } diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php index 19b7b744b..63df2963d 100644 --- a/system/database/drivers/odbc/odbc_driver.php +++ b/system/database/drivers/odbc/odbc_driver.php @@ -50,7 +50,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); * @author EllisLab Dev Team * @link https://codeigniter.com/user_guide/database/ */ -class CI_DB_odbc_driver extends CI_DB { +class CI_DB_odbc_driver extends CI_DB_driver { /** * Database driver @@ -94,6 +94,22 @@ class CI_DB_odbc_driver extends CI_DB { // -------------------------------------------------------------------- /** + * ODBC result ID resource returned from odbc_prepare() + * + * @var resource + */ + private $odbc_result; + + /** + * Values to use with odbc_execute() for prepared statements + * + * @var array + */ + private $binds = array(); + + // -------------------------------------------------------------------- + + /** * Class constructor * * @param array $params @@ -128,6 +144,74 @@ class CI_DB_odbc_driver extends CI_DB { // -------------------------------------------------------------------- /** + * Compile Bindings + * + * @param string $sql SQL statement + * @param array $binds An array of values to bind + * @return string + */ + public function compile_binds($sql, $binds) + { + if (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE) + { + return $sql; + } + elseif ( ! is_array($binds)) + { + $binds = array($binds); + $bind_count = 1; + } + else + { + // Make sure we're using numeric keys + $binds = array_values($binds); + $bind_count = count($binds); + } + + // We'll need the marker length later + $ml = strlen($this->bind_marker); + + // Make sure not to replace a chunk inside a string that happens to match the bind marker + if ($c = preg_match_all("/'[^']*'/i", $sql, $matches)) + { + $c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', + str_replace($matches[0], + str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]), + $sql, $c), + $matches, PREG_OFFSET_CAPTURE); + + // Bind values' count must match the count of markers in the query + if ($bind_count !== $c) + { + return $sql; + } + } + elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count) + { + return $sql; + } + + if ($this->bind_marker !== '?') + { + do + { + $c--; + $sql = substr_replace($sql, '?', $matches[0][$c][1], $ml); + } + while ($c !== 0); + } + + if (FALSE !== ($this->odbc_result = odbc_prepare($this->conn_id, $sql))) + { + $this->binds = array_values($binds); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** * Execute the query * * @param string $sql an SQL query @@ -135,7 +219,25 @@ class CI_DB_odbc_driver extends CI_DB { */ protected function _execute($sql) { - return odbc_exec($this->conn_id, $sql); + if ( ! isset($this->odbc_result)) + { + return odbc_exec($this->conn_id, $sql); + } + elseif ($this->odbc_result === FALSE) + { + return FALSE; + } + + if (TRUE === ($success = odbc_execute($this->odbc_result, $this->binds))) + { + // For queries that return result sets, return the result_id resource on success + $this->is_write_type($sql) OR $success = $this->odbc_result; + } + + $this->odbc_result = NULL; + $this->binds = array(); + + return $success; } // -------------------------------------------------------------------- @@ -214,7 +316,7 @@ class CI_DB_odbc_driver extends CI_DB { */ protected function _escape_str($str) { - return remove_invisible_characters($str); + $this->db->display_error('db_unsupported_feature'); } // -------------------------------------------------------------------- @@ -312,58 +414,6 @@ class CI_DB_odbc_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'DELETE FROM '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** * Close DB Connection * * @return void @@ -372,5 +422,4 @@ class CI_DB_odbc_driver extends CI_DB { { odbc_close($this->conn_id); } - } diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php index c6f84e0f9..c27607e55 100644 --- a/system/database/drivers/pdo/pdo_driver.php +++ b/system/database/drivers/pdo/pdo_driver.php @@ -126,7 +126,10 @@ class CI_DB_pdo_driver extends CI_DB { */ public function db_connect($persistent = FALSE) { - $this->options[PDO::ATTR_PERSISTENT] = $persistent; + if ($persistent === TRUE) + { + $this->options[PDO::ATTR_PERSISTENT] = TRUE; + } try { diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php index 5f854061d..b5b95078e 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php +++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php @@ -178,6 +178,9 @@ class CI_DB_pdo_cubrid_forge extends CI_DB_pdo_forge { $attributes['TYPE'] = 'INTEGER'; $attributes['UNSIGNED'] = FALSE; return; + case 'LONGTEXT': + $attributes['TYPE'] = 'STRING'; + return; default: return; } } diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php index 84695ee9b..9a1cbcaf4 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php @@ -126,7 +126,12 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { */ public function db_connect($persistent = FALSE) { - $this->conn_id = parent::db_connect($persistent); + if ($persistent === TRUE) + { + log_message('debug', "dblib driver doesn't support persistent connections"); + } + + $this->conn_id = parent::db_connect(FALSE); if ( ! is_object($this->conn_id)) { diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php index d5dd9aad1..830200325 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php +++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php @@ -111,6 +111,11 @@ class CI_DB_pdo_dblib_forge extends CI_DB_pdo_forge { */ protected function _attr_type(&$attributes) { + if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE) + { + unset($attributes['CONSTRAINT']); + } + switch (strtoupper($attributes['TYPE'])) { case 'MEDIUMINT': diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php index 70f2bfd4e..38a5a8aff 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php @@ -218,6 +218,7 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { if (FALSE !== $this->simple_query('USE '.$this->escape_identifiers($database))) { $this->database = $database; + $this->data_cache = array(); return TRUE; } diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php index 94a52ffc8..705b1c711 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php +++ b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php @@ -173,5 +173,4 @@ class CI_DB_pdo_oci_forge extends CI_DB_pdo_forge { default: return; } } - } diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php index 333448838..82554ec80 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php @@ -161,6 +161,19 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** + * Platform-dependant string escape + * + * @param string + * @return string + */ + protected function _escape_str($str) + { + $this->db->display_error('db_unsupported_feature'); + } + + // -------------------------------------------------------------------- + + /** * Determines if a query is a "write" type. * * @param string An SQL query string @@ -213,72 +226,4 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { { return 'SELECT column_name FROM information_schema.columns WHERE table_name = '.$this->escape($table); } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'DELETE FROM '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string the table name - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$this->qb_limit.' ', $sql); - } - } diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php index 602f895f1..56bf87f3a 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php +++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php @@ -111,6 +111,11 @@ class CI_DB_pdo_sqlsrv_forge extends CI_DB_pdo_forge { */ protected function _attr_type(&$attributes) { + if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE) + { + unset($attributes['CONSTRAINT']); + } + switch (strtoupper($attributes['TYPE'])) { case 'MEDIUMINT': diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php index 0cd9ce16d..c55d5f7b7 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -171,6 +171,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { if ($this->_execute('USE '.$this->escape_identifiers($database))) { $this->database = $database; + $this->data_cache = array(); return TRUE; } diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php index f915dad3e..4f0ce9d6f 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_forge.php +++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php @@ -111,6 +111,11 @@ class CI_DB_sqlsrv_forge extends CI_DB_forge { */ protected function _attr_type(&$attributes) { + if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE) + { + unset($attributes['CONSTRAINT']); + } + switch (strtoupper($attributes['TYPE'])) { case 'MEDIUMINT': diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php index 0d8d1d0d9..3cb36a551 100644 --- a/system/helpers/file_helper.php +++ b/system/helpers/file_helper.php @@ -138,13 +138,15 @@ if ( ! function_exists('delete_files')) { if ($filename !== '.' && $filename !== '..') { - if (is_dir($path.DIRECTORY_SEPARATOR.$filename) && $filename[0] !== '.') + $filepath = $path.DIRECTORY_SEPARATOR.$filename; + + if (is_dir($filepath) && $filename[0] !== '.' && ! is_link($filepath)) { - delete_files($path.DIRECTORY_SEPARATOR.$filename, $del_dir, $htdocs, $_level + 1); + delete_files($filepath, $del_dir, $htdocs, $_level + 1); } elseif ($htdocs !== TRUE OR ! preg_match('/^(\.htaccess|index\.(html|htm|php)|web\.config)$/i', $filename)) { - @unlink($path.DIRECTORY_SEPARATOR.$filename); + @unlink($filepath); } } } diff --git a/system/helpers/path_helper.php b/system/helpers/path_helper.php index 18e175093..6c846a211 100644 --- a/system/helpers/path_helper.php +++ b/system/helpers/path_helper.php @@ -61,7 +61,7 @@ if ( ! function_exists('set_realpath')) function set_realpath($path, $check_existance = FALSE) { // Security check to make sure the path is NOT a URL. No remote file inclusion! - if (preg_match('#^(http:\/\/|https:\/\/|www\.|ftp|php:\/\/)#i', $path) OR filter_var($path, FILTER_VALIDATE_IP) === $path ) + if (preg_match('#^(http:\/\/|https:\/\/|www\.|ftp|php:\/\/)#i', $path) OR filter_var($path, FILTER_VALIDATE_IP) === $path) { show_error('The path you submitted must be a local server path, not a URL'); } diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php index ca3997ad5..ab8bfab8b 100644 --- a/system/libraries/Cache/drivers/Cache_memcached.php +++ b/system/libraries/Cache/drivers/Cache_memcached.php @@ -307,7 +307,7 @@ class CI_Cache_memcached extends CI_Driver { { $this->_memcached->close(); } - elseif ($this->_memcached instanceof Memcached) + elseif ($this->_memcached instanceof Memcached && method_exists($this->_memcached, 'quit')) { $this->_memcached->quit(); } diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 0a55e1841..e9f69f065 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -387,18 +387,8 @@ class CI_Email { public function __construct(array $config = array()) { $this->charset = config_item('charset'); - - if (count($config) > 0) - { - $this->initialize($config); - } - else - { - $this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === ''); - } - + $this->initialize($config); $this->_safe_mode = ( ! is_php('5.4') && ini_get('safe_mode')); - $this->charset = strtoupper($this->charset); log_message('info', 'Email Class Initialized'); } @@ -406,28 +396,15 @@ class CI_Email { // -------------------------------------------------------------------- /** - * Destructor - Releases Resources - * - * @return void - */ - public function __destruct() - { - if (is_resource($this->_smtp_connect)) - { - $this->_send_command('quit'); - } - } - - // -------------------------------------------------------------------- - - /** * Initialize preferences * - * @param array + * @param array $config * @return CI_Email */ - public function initialize($config = array()) + public function initialize(array $config = array()) { + $this->clear(); + foreach ($config as $key => $val) { if (isset($this->$key)) @@ -444,9 +421,9 @@ class CI_Email { } } } - $this->clear(); - $this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === ''); + $this->charset = strtoupper($this->charset); + $this->_smtp_auth = isset($this->smtp_user[0], $this->smtp_pass[0]); return $this; } @@ -1942,6 +1919,7 @@ class CI_Email { if ( ! $this->_send_command('from', $this->clean_email($this->_headers['From']))) { + $this->_smtp_end(); return FALSE; } @@ -1949,6 +1927,7 @@ class CI_Email { { if ( ! $this->_send_command('to', $val)) { + $this->_smtp_end(); return FALSE; } } @@ -1959,6 +1938,7 @@ class CI_Email { { if ($val !== '' && ! $this->_send_command('to', $val)) { + $this->_smtp_end(); return FALSE; } } @@ -1970,6 +1950,7 @@ class CI_Email { { if ($val !== '' && ! $this->_send_command('to', $val)) { + $this->_smtp_end(); return FALSE; } } @@ -1977,6 +1958,7 @@ class CI_Email { if ( ! $this->_send_command('data')) { + $this->_smtp_end(); return FALSE; } @@ -1986,30 +1968,38 @@ class CI_Email { $this->_send_data('.'); $reply = $this->_get_smtp_data(); - $this->_set_error_message($reply); + $this->_smtp_end(); + if (strpos($reply, '250') !== 0) { $this->_set_error_message('lang:email_smtp_error', $reply); return FALSE; } - if ($this->smtp_keepalive) - { - $this->_send_command('reset'); - } - else - { - $this->_send_command('quit'); - } - return TRUE; } // -------------------------------------------------------------------- /** + * SMTP End + * + * Shortcut to send RSET or QUIT depending on keep-alive + * + * @return void + */ + protected function _smtp_end() + { + ($this->smtp_keepalive) + ? $this->_send_command('reset') + : $this->_send_command('quit'); + } + + // -------------------------------------------------------------------- + + /** * SMTP Connect * * @return string @@ -2193,6 +2183,11 @@ class CI_Email { return FALSE; } + if ($this->smtp_keepalive) + { + $this->_smtp_auth = FALSE; + } + return TRUE; } @@ -2382,4 +2377,15 @@ class CI_Email { return 'application/x-unknown-content-type'; } + // -------------------------------------------------------------------- + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + is_resource($this->_smtp_connect) && $this->_send_command('quit'); + } } diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php index 92c38a0ed..a10a5c20c 100644 --- a/system/libraries/Encryption.php +++ b/system/libraries/Encryption.php @@ -339,12 +339,26 @@ class CI_Encryption { { if (function_exists('random_bytes')) { - return random_bytes((int) $length); + try + { + return random_bytes((int) $length); + } + catch (Exception $e) + { + log_message('error', $e->getMessage()); + return FALSE; + } + } + elseif (defined('MCRYPT_DEV_URANDOM')) + { + return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); } - return ($this->_driver === 'mcrypt') - ? mcrypt_create_iv($length, MCRYPT_DEV_URANDOM) - : openssl_random_pseudo_bytes($length); + $is_secure = NULL; + $key = openssl_random_pseudo_bytes($length, $is_secure); + return ($is_secure === TRUE) + ? $key + : FALSE; } // -------------------------------------------------------------------- @@ -400,7 +414,7 @@ class CI_Encryption { // The greater-than-1 comparison is mostly a work-around for a bug, // where 1 is returned for ARCFour instead of 0. $iv = (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1) - ? mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM) + ? $this->create_key($iv_size) : NULL; if (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0) @@ -463,7 +477,7 @@ class CI_Encryption { } $iv = ($iv_size = openssl_cipher_iv_length($params['handle'])) - ? openssl_random_pseudo_bytes($iv_size) + ? $this->create_key($iv_size) : NULL; $data = openssl_encrypt( diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index e4a518957..04445f5b7 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -494,6 +494,63 @@ class CI_Form_validation { // -------------------------------------------------------------------- /** + * Prepare rules + * + * Re-orders the provided rules in order of importance, so that + * they can easily be executed later without weird checks ... + * + * "Callbacks" are given the highest priority (always called), + * followed by 'required' (called if callbacks didn't fail), + * and then every next rule depends on the previous one passing. + * + * @param array $rules + * @return array + */ + protected function _prepare_rules($rules) + { + $new_rules = array(); + $callbacks = array(); + + foreach ($rules as &$rule) + { + // Let 'required' always be the first (non-callback) rule + if ($rule === 'required') + { + array_unshift($new_rules, 'required'); + } + // 'isset' is a kind of a weird alias for 'required' ... + elseif ($rule === 'isset' && (empty($new_rules) OR $new_rules[0] !== 'required')) + { + array_unshift($new_rules, 'isset'); + } + // The old/classic 'callback_'-prefixed rules + elseif (is_string($rule) && strncmp('callback_', $rule, 9) === 0) + { + $callbacks[] = $rule; + } + // Proper callables + elseif (is_callable($rule)) + { + $callbacks[] = $rule; + } + // "Named" callables; i.e. array('name' => $callable) + elseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1])) + { + $callbacks[] = $rule; + } + // Everything else goes at the end of the queue + else + { + $new_rules[] = $rule; + } + } + + return array_merge($callbacks, $new_rules); + } + + // -------------------------------------------------------------------- + + /** * Traverse a multidimensional $_POST array index until the data is found * * @param array @@ -580,70 +637,7 @@ class CI_Form_validation { return; } - // If the field is blank, but NOT required, no further tests are necessary - $callback = FALSE; - if ( ! in_array('required', $rules) && ($postdata === NULL OR $postdata === '')) - { - // Before we bail out, does the rule contain a callback? - foreach ($rules as &$rule) - { - if (is_string($rule)) - { - if (strncmp($rule, 'callback_', 9) === 0) - { - $callback = TRUE; - $rules = array(1 => $rule); - break; - } - } - elseif (is_callable($rule)) - { - $callback = TRUE; - $rules = array(1 => $rule); - break; - } - elseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1])) - { - $callback = TRUE; - $rules = array(array($rule[0], $rule[1])); - break; - } - } - - if ( ! $callback) - { - return; - } - } - - // Isset Test. Typically this rule will only apply to checkboxes. - if (($postdata === NULL OR $postdata === '') && ! $callback) - { - if (in_array('isset', $rules, TRUE) OR in_array('required', $rules)) - { - // Set the message type - $type = in_array('required', $rules) ? 'required' : 'isset'; - - $line = $this->_get_error_message($type, $row['field']); - - // Build the error message - $message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label'])); - - // Save the error message - $this->_field_data[$row['field']]['error'] = $message; - - if ( ! isset($this->_error_array[$row['field']])) - { - $this->_error_array[$row['field']] = $message; - } - } - - return; - } - - // -------------------------------------------------------------------- - - // Cycle through each rule and run it + $rules = $this->_prepare_rules($rules); foreach ($rules as $rule) { $_in_array = FALSE; @@ -702,6 +696,17 @@ class CI_Form_validation { $param = $match[2]; } + // Ignore empty, non-required inputs with a few exceptions ... + if ( + ($postdata === NULL OR $postdata === '') + && $callback === FALSE + && $callable === FALSE + && ! in_array($rule, array('required', 'isset', 'matches'), TRUE) + ) + { + continue; + } + // Call the function that corresponds to the rule if ($callback OR $callable !== FALSE) { @@ -740,12 +745,6 @@ class CI_Form_validation { { $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result; } - - // If the field isn't required and we just processed a callback we'll move on... - if ( ! in_array('required', $rules, TRUE) && $result !== FALSE) - { - continue; - } } elseif ( ! method_exists($this, $rule)) { @@ -1055,7 +1054,9 @@ class CI_Form_validation { */ public function required($str) { - return is_array($str) ? (bool) count($str) : (trim($str) !== ''); + return is_array($str) + ? (empty($str) === FALSE) + : (trim($str) !== ''); } // -------------------------------------------------------------------- diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php index f594b7125..24fe8c68d 100644 --- a/system/libraries/Image_lib.php +++ b/system/libraries/Image_lib.php @@ -456,7 +456,7 @@ class CI_Image_lib { { if (property_exists($this, $key)) { - if (in_array($key, array('wm_font_color', 'wm_shadow_color'))) + if (in_array($key, array('wm_font_color', 'wm_shadow_color'), TRUE)) { if (preg_match('/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i', $val, $matches)) { @@ -478,6 +478,10 @@ class CI_Image_lib { continue; } } + elseif (in_array($key, array('width', 'height'), TRUE) && ! ctype_digit((string) $val)) + { + continue; + } $this->$key = $val; } @@ -862,27 +866,28 @@ class CI_Image_lib { if ($action === 'crop') { - $cmd .= ' -crop '.$this->width.'x'.$this->height.'+'.$this->x_axis.'+'.$this->y_axis.' "'.$this->full_src_path.'" "'.$this->full_dst_path .'" 2>&1'; + $cmd .= ' -crop '.$this->width.'x'.$this->height.'+'.$this->x_axis.'+'.$this->y_axis; } elseif ($action === 'rotate') { - $angle = ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt') - ? '-flop' : '-rotate '.$this->rotation_angle; - - $cmd .= ' '.$angle.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1'; + $cmd .= ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt') + ? ' -flop' + : ' -rotate '.$this->rotation_angle; } else // Resize { if($this->maintain_ratio === TRUE) { - $cmd .= ' -resize '.$this->width.'x'.$this->height.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1'; + $cmd .= ' -resize '.$this->width.'x'.$this->height; } else { - $cmd .= ' -resize '.$this->width.'x'.$this->height.'\! "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1'; + $cmd .= ' -resize '.$this->width.'x'.$this->height.'\!'; } } + $cmd .= ' "'.escapeshellarg($this->full_src_path).'" "'.escapeshellarg($this->full_dst_path).'" 2>&1'; + $retval = 1; // exec() might be disabled if (function_usable('exec')) diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php index dde84a775..3b391a8ef 100644 --- a/system/libraries/Session/Session.php +++ b/system/libraries/Session/Session.php @@ -91,6 +91,7 @@ class CI_Session { // Note: BC workaround elseif (config_item('sess_use_database')) { + log_message('debug', 'Session: "sess_driver" is empty; using BC fallback to "sess_use_database".'); $this->_driver = 'database'; } diff --git a/system/libraries/Session/drivers/Session_database_driver.php b/system/libraries/Session/drivers/Session_database_driver.php index 317bd7d4d..cb152f91f 100644 --- a/system/libraries/Session/drivers/Session_database_driver.php +++ b/system/libraries/Session/drivers/Session_database_driver.php @@ -109,7 +109,10 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan } // Note: BC work-around for the old 'sess_table_name' setting, should be removed in the future. - isset($this->_config['save_path']) OR $this->_config['save_path'] = config_item('sess_table_name'); + if ( ! isset($this->_config['save_path']) && ($this->_config['save_path'] = config_item('sess_table_name'))) + { + log_message('debug', 'Session: "sess_save_path" is empty; using BC fallback to "sess_table_name".'); + } } // ------------------------------------------------------------------------ diff --git a/system/libraries/Session/drivers/Session_files_driver.php b/system/libraries/Session/drivers/Session_files_driver.php index 119bf6572..57c3777a2 100644 --- a/system/libraries/Session/drivers/Session_files_driver.php +++ b/system/libraries/Session/drivers/Session_files_driver.php @@ -95,6 +95,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle } else { + log_message('debug', 'Session: "sess_save_path" is empty; using "session.save_path" value from php.ini.'); $this->_config['save_path'] = rtrim(ini_get('session.save_path'), '/\\'); } } diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php index d3a265958..592f1ff6c 100644 --- a/system/libraries/Session/drivers/Session_redis_driver.php +++ b/system/libraries/Session/drivers/Session_redis_driver.php @@ -279,7 +279,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle if ($this->_redis->ping() === '+PONG') { $this->_release_lock(); - if ($this->_redis->close() === $this->_failure) + if ($this->_redis->close() === FALSE) { return $this->_fail(); } diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php index c4e11592d..60d159966 100644 --- a/system/libraries/User_agent.php +++ b/system/libraries/User_agent.php @@ -173,13 +173,11 @@ class CI_User_agent { */ public function __construct() { + $this->_load_agent_file(); + if (isset($_SERVER['HTTP_USER_AGENT'])) { $this->agent = trim($_SERVER['HTTP_USER_AGENT']); - } - - if ($this->agent !== NULL && $this->_load_agent_file()) - { $this->_compile_data(); } |