diff options
109 files changed, 750 insertions, 441 deletions
diff --git a/.gitignore b/.gitignore index 5982f9bad..269044ea9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,13 @@ application/cache/* !application/cache/index.html -!application/cache/.htaccess application/logs/* !application/logs/index.html -!application/logs/.htaccess + +!application/*/.htaccess + +composer.lock user_guide_src/build/* user_guide_src/cilexer/build/* @@ -25,3 +27,5 @@ user_guide_src/cilexer/pycilexer.egg-info/* *.stTheme.cache *.sublime-workspace *.sublime-project +/tests/tests/ +/tests/results/ diff --git a/.travis.yml b/.travis.yml index ba2d6b31d..a7e5cdaeb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: php +dist: precise php: - 5.3 @@ -26,13 +27,11 @@ before_script: - sh -c "if [ '$DB' = 'pgsql' ] || [ '$DB' = 'pdo/pgsql' ]; then psql -c 'create database ci_test;' -U postgres; fi" - sh -c "if [ '$DB' = 'mysql' ] || [ '$DB' = 'mysqli' ] || [ '$DB' = 'pdo/mysql' ]; then mysql -e 'create database IF NOT EXISTS ci_test;'; fi" -script: phpunit -d zend.enable_gc=0 -d date.timezone=UTC --coverage-text --configuration tests/travis/$DB.phpunit.xml +script: php -d zend.enable_gc=0 -d date.timezone=UTC -d mbstring.func_overload=7 -d mbstring.internal_encoding=UTF-8 vendor/bin/phpunit --coverage-text --configuration tests/travis/$DB.phpunit.xml matrix: allow_failures: - - php: 5.3 - php: hhvm - - php: 7.1 exclude: - php: hhvm env: DB=pgsql diff --git a/application/cache/.htaccess b/application/cache/.htaccess deleted file mode 100644 index 6c63ed4c4..000000000 --- a/application/cache/.htaccess +++ /dev/null @@ -1,6 +0,0 @@ -<IfModule authz_core_module> - Require all denied -</IfModule> -<IfModule !authz_core_module> - Deny from all -</IfModule>
\ No newline at end of file diff --git a/composer.json b/composer.json index 64d1be155..30630e224 100644 --- a/composer.json +++ b/composer.json @@ -7,16 +7,17 @@ "support": { "forum": "http://forum.codeigniter.com/", "wiki": "https://github.com/bcit-ci/CodeIgniter/wiki", - "irc": "irc://irc.freenode.net/codeigniter", + "slack": "https://codeigniterchat.slack.com", "source": "https://github.com/bcit-ci/CodeIgniter" }, "require": { - "php": ">=5.2.4" + "php": ">=5.3.7" }, "suggest": { "paragonie/random_compat": "Provides better randomness in PHP 5.x" }, "require-dev": { - "mikey179/vfsStream": "1.1.*" + "mikey179/vfsStream": "1.1.*", + "phpunit/phpunit": "4.* || 5.*" } -}
\ No newline at end of file +} diff --git a/readme.rst b/readme.rst index f5d737028..b6520080e 100644 --- a/readme.rst +++ b/readme.rst @@ -57,7 +57,7 @@ Resources - `Language File Translations <https://github.com/bcit-ci/codeigniter3-translations>`_ - `Community Forums <http://forum.codeigniter.com/>`_ - `Community Wiki <https://github.com/bcit-ci/CodeIgniter/wiki>`_ -- `Community IRC <https://webchat.freenode.net/?channels=%23codeigniter>`_ +- `Community Slack Channel <https://codeigniterchat.slack.com>`_ Report security issues to our `Security Panel <mailto:security@codeigniter.com>`_ or via our `page on HackerOne <https://hackerone.com/codeigniter>`_, thank you. diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 0edcf972d..0d03293f6 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 * */ - const CI_VERSION = '3.1.3'; + const CI_VERSION = '3.1.6'; /* * ------------------------------------------------------ @@ -434,7 +434,7 @@ if ( ! is_php('5.4')) * ReflectionMethod::isConstructor() is the ONLY reliable check, * knowing which method will be executed as a constructor. */ - elseif ( ! is_callable(array($class, $method)) && strcasecmp($class, $method) === 0) + elseif ( ! is_callable(array($class, $method))) { $reflection = new ReflectionMethod($class, $method); if ( ! $reflection->isPublic() OR $reflection->isConstructor()) diff --git a/system/core/Common.php b/system/core/Common.php index 7b3eb6a4e..d6a1fdb4e 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -135,7 +135,7 @@ if ( ! function_exists('load_class')) * * @param string the class name being requested * @param string the directory where the class should be found - * @param string an optional argument to pass to the class constructor + * @param mixed an optional argument to pass to the class constructor * @return object */ function &load_class($class, $directory = 'libraries', $param = NULL) @@ -319,17 +319,13 @@ if ( ! function_exists('get_mimes')) if (empty($_mimes)) { + $_mimes = file_exists(APPPATH.'config/mimes.php') + ? include(APPPATH.'config/mimes.php') + : array(); + if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) { - $_mimes = include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'); - } - elseif (file_exists(APPPATH.'config/mimes.php')) - { - $_mimes = include(APPPATH.'config/mimes.php'); - } - else - { - $_mimes = array(); + $_mimes = array_merge($_mimes, include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')); } } @@ -410,11 +406,6 @@ if ( ! function_exists('show_error')) if ($status_code < 100) { $exit_status = $status_code + 9; // 9 is EXIT__AUTO_MIN - if ($exit_status > 125) // 125 is EXIT__AUTO_MAX - { - $exit_status = 1; // EXIT_ERROR - } - $status_code = 500; } else @@ -571,12 +562,12 @@ if ( ! function_exists('set_status_header')) if (strpos(PHP_SAPI, 'cgi') === 0) { header('Status: '.$code.' '.$text, TRUE); + return; } - else - { - $server_protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; - header($server_protocol.' '.$code.' '.$text, TRUE, $code); - } + + $server_protocol = (isset($_SERVER['SERVER_PROTOCOL']) && in_array($_SERVER['SERVER_PROTOCOL'], array('HTTP/1.0', 'HTTP/1.1', 'HTTP/2'), TRUE)) + ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; + header($server_protocol.' '.$code.' '.$text, TRUE, $code); } } @@ -724,6 +715,7 @@ if ( ! function_exists('remove_invisible_characters')) { $non_displayables[] = '/%0[0-8bcef]/i'; // url encoded 00-08, 11, 12, 14, 15 $non_displayables[] = '/%1[0-9a-f]/i'; // url encoded 16-31 + $non_displayables[] = '/%7f/i'; // url encoded 127 } $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127 @@ -827,7 +819,7 @@ if ( ! function_exists('function_usable')) * terminate script execution if a disabled function is executed. * * The above described behavior turned out to be a bug in Suhosin, - * but even though a fix was commited for 0.9.34 on 2012-02-12, + * but even though a fix was committed for 0.9.34 on 2012-02-12, * that version is yet to be released. This function will therefore * be just temporary, but would probably be kept for a few years. * diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index 47d153f49..526909602 100644 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php @@ -231,7 +231,7 @@ class CI_Exceptions { * @param string $message Error message * @param string $filepath File path * @param int $line Line number - * @return string Error page output + * @return void */ public function show_php_error($severity, $message, $filepath, $line) { diff --git a/system/core/Input.php b/system/core/Input.php index d7cd29261..af4f87c1f 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -359,7 +359,7 @@ class CI_Input { * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript) * @return void */ - public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE) + public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL) { if (is_array($name)) { @@ -388,15 +388,13 @@ class CI_Input { $path = config_item('cookie_path'); } - if ($secure === FALSE && config_item('cookie_secure') === TRUE) - { - $secure = config_item('cookie_secure'); - } + $secure = ($secure === NULL && config_item('cookie_secure') !== NULL) + ? (bool) config_item('cookie_secure') + : (bool) $secure; - if ($httponly === FALSE && config_item('cookie_httponly') !== FALSE) - { - $httponly = config_item('cookie_httponly'); - } + $httponly = ($httponly === NULL && config_item('cookie_httponly') !== NULL) + ? (bool) config_item('cookie_httponly') + : (bool) $httponly; if ( ! is_numeric($expire)) { diff --git a/system/core/Loader.php b/system/core/Loader.php index acfc739dd..085c5b51d 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -182,7 +182,7 @@ class CI_Loader { * Loads and instantiates libraries. * Designed to be called from application controllers. * - * @param string $library Library name + * @param mixed $library Library name * @param array $params Optional parameters to pass to the library class constructor * @param string $object_name An optional object name to assign to * @return object @@ -590,7 +590,7 @@ class CI_Loader { { $filename = basename($helper); $filepath = ($filename === $helper) ? '' : substr($helper, 0, strlen($helper) - strlen($filename)); - $filename = strtolower(preg_replace('#(_helper)?(.php)?$#i', '', $filename)).'_helper'; + $filename = strtolower(preg_replace('#(_helper)?(\.php)?$#i', '', $filename)).'_helper'; $helper = $filepath.$filename; if (isset($this->_ci_helpers[$helper])) @@ -1037,6 +1037,26 @@ class CI_Loader { return $this->_ci_load_stock_library($class, $subdir, $params, $object_name); } + // Safety: Was the class already loaded by a previous call? + if (class_exists($class, FALSE)) + { + $property = $object_name; + if (empty($property)) + { + $property = strtolower($class); + isset($this->_ci_varmap[$property]) && $property = $this->_ci_varmap[$property]; + } + + $CI =& get_instance(); + if (isset($CI->$property)) + { + log_message('debug', $class.' class already loaded. Second attempt ignored.'); + return; + } + + return $this->_ci_init_library($class, '', $params, $object_name); + } + // Let's search for the requested library file and load it. foreach ($this->_ci_library_paths as $path) { @@ -1047,27 +1067,8 @@ class CI_Loader { } $filepath = $path.'libraries/'.$subdir.$class.'.php'; - - // Safety: Was the class already loaded by a previous call? - if (class_exists($class, FALSE)) - { - // Before we deem this to be a duplicate request, let's see - // if a custom object name is being supplied. If so, we'll - // return a new instance of the object - if ($object_name !== NULL) - { - $CI =& get_instance(); - if ( ! isset($CI->$object_name)) - { - return $this->_ci_init_library($class, '', $params, $object_name); - } - } - - log_message('debug', $class.' class already loaded. Second attempt ignored.'); - return; - } // Does the file exist? No? Bummer... - elseif ( ! file_exists($filepath)) + if ( ! file_exists($filepath)) { continue; } @@ -1112,16 +1113,17 @@ class CI_Loader { $prefix = config_item('subclass_prefix'); } - // Before we deem this to be a duplicate request, let's see - // if a custom object name is being supplied. If so, we'll - // return a new instance of the object - if ($object_name !== NULL) + $property = $object_name; + if (empty($property)) { - $CI =& get_instance(); - if ( ! isset($CI->$object_name)) - { - return $this->_ci_init_library($library_name, $prefix, $params, $object_name); - } + $property = strtolower($library_name); + isset($this->_ci_varmap[$property]) && $property = $this->_ci_varmap[$property]; + } + + $CI =& get_instance(); + if ( ! isset($CI->$property)) + { + return $this->_ci_init_library($library_name, $prefix, $params, $object_name); } log_message('debug', $library_name.' class already loaded. Second attempt ignored.'); @@ -1143,10 +1145,8 @@ class CI_Loader { { return $this->_ci_init_library($library_name, $prefix, $params, $object_name); } - else - { - log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name); - } + + log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name); } } @@ -1164,10 +1164,8 @@ class CI_Loader { $prefix = config_item('subclass_prefix'); break; } - else - { - log_message('debug', $path.' exists, but does not declare '.$subclass); - } + + log_message('debug', $path.' exists, but does not declare '.$subclass); } } diff --git a/system/core/Log.php b/system/core/Log.php index 3e11b35f5..d443aedb8 100644 --- a/system/core/Log.php +++ b/system/core/Log.php @@ -105,11 +105,11 @@ class CI_Log { protected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4); /** - * mbstring.func_override flag + * mbstring.func_overload flag * * @var bool */ - protected static $func_override; + protected static $func_overload; // -------------------------------------------------------------------- @@ -122,7 +122,7 @@ class CI_Log { { $config =& get_config(); - isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); + isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); $this->_log_path = ($config['log_path'] !== '') ? $config['log_path'] : APPPATH.'logs/'; $this->_file_ext = (isset($config['log_file_extension']) && $config['log_file_extension'] !== '') @@ -264,7 +264,7 @@ class CI_Log { */ protected static function strlen($str) { - return (self::$func_override) + return (self::$func_overload) ? mb_strlen($str, '8bit') : strlen($str); } @@ -281,7 +281,7 @@ class CI_Log { */ protected static function substr($str, $start, $length = NULL) { - if (self::$func_override) + if (self::$func_overload) { // mb_substr($str, $start, null, '8bit') returns an empty // string on PHP 5.3 diff --git a/system/core/Output.php b/system/core/Output.php index 349955cd2..a3155fece 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -123,11 +123,11 @@ class CI_Output { public $parse_exec_vars = TRUE; /** - * mbstring.func_override flag + * mbstring.func_overload flag * * @var bool */ - protected static $func_override; + protected static $func_overload; /** * Class constructor @@ -145,7 +145,7 @@ class CI_Output { && extension_loaded('zlib') ); - isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); + isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); // Get mime types for later $this->mimes =& get_mimes(); @@ -586,62 +586,59 @@ class CI_Output { return; } - if (flock($fp, LOCK_EX)) + if ( ! flock($fp, LOCK_EX)) { - // If output compression is enabled, compress the cache - // itself, so that we don't have to do that each time - // we're serving it - if ($this->_compress_output === TRUE) - { - $output = gzencode($output); + log_message('error', 'Unable to secure a file lock for file at: '.$cache_path); + fclose($fp); + return; + } - if ($this->get_header('content-type') === NULL) - { - $this->set_content_type($this->mime_type); - } + // If output compression is enabled, compress the cache + // itself, so that we don't have to do that each time + // we're serving it + if ($this->_compress_output === TRUE) + { + $output = gzencode($output); + + if ($this->get_header('content-type') === NULL) + { + $this->set_content_type($this->mime_type); } + } - $expire = time() + ($this->cache_expiration * 60); + $expire = time() + ($this->cache_expiration * 60); - // Put together our serialized info. - $cache_info = serialize(array( - 'expire' => $expire, - 'headers' => $this->headers - )); + // Put together our serialized info. + $cache_info = serialize(array( + 'expire' => $expire, + 'headers' => $this->headers + )); - $output = $cache_info.'ENDCI--->'.$output; + $output = $cache_info.'ENDCI--->'.$output; - for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result) + for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result) + { + if (($result = fwrite($fp, self::substr($output, $written))) === FALSE) { - if (($result = fwrite($fp, self::substr($output, $written))) === FALSE) - { - break; - } + break; } - - flock($fp, LOCK_UN); - } - else - { - log_message('error', 'Unable to secure a file lock for file at: '.$cache_path); - return; } + flock($fp, LOCK_UN); fclose($fp); - if (is_int($result)) - { - chmod($cache_path, 0640); - log_message('debug', 'Cache file written: '.$cache_path); - - // Send HTTP cache-control headers to browser to match file cache settings. - $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire); - } - else + if ( ! is_int($result)) { @unlink($cache_path); log_message('error', 'Unable to write the complete cache content at: '.$cache_path); + return; } + + chmod($cache_path, 0640); + log_message('debug', 'Cache file written: '.$cache_path); + + // Send HTTP cache-control headers to browser to match file cache settings. + $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire); } // -------------------------------------------------------------------- @@ -708,11 +705,9 @@ class CI_Output { log_message('debug', 'Cache file has expired. File deleted.'); return FALSE; } - else - { - // Or else send the HTTP cache control headers. - $this->set_cache_header($last_modified, $expire); - } + + // Send the HTTP cache control headers + $this->set_cache_header($last_modified, $expire); // Add headers from cache file. foreach ($cache_info['headers'] as $header) @@ -798,13 +793,11 @@ class CI_Output { $this->set_status_header(304); exit; } - else - { - header('Pragma: public'); - header('Cache-Control: max-age='.$max_age.', public'); - header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT'); - header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT'); - } + + header('Pragma: public'); + header('Cache-Control: max-age='.$max_age.', public'); + header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT'); + header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT'); } // -------------------------------------------------------------------- @@ -817,7 +810,7 @@ class CI_Output { */ protected static function strlen($str) { - return (self::$func_override) + return (self::$func_overload) ? mb_strlen($str, '8bit') : strlen($str); } @@ -834,7 +827,7 @@ class CI_Output { */ protected static function substr($str, $start, $length = NULL) { - if (self::$func_override) + if (self::$func_overload) { // mb_substr($str, $start, null, '8bit') returns an empty // string on PHP 5.3 diff --git a/system/core/Security.php b/system/core/Security.php index 585ed90ec..082ffa96b 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -354,9 +354,9 @@ class CI_Security { // Is the string an array? if (is_array($str)) { - while (list($key) = each($str)) + foreach ($str as $key => &$value) { - $str[$key] = $this->xss_clean($str[$key]); + $str[$key] = $this->xss_clean($value); } return $str; @@ -869,7 +869,7 @@ class CI_Security { // Each iteration filters a single attribute do { - // Strip any non-alpha characters that may preceed an attribute. + // Strip any non-alpha characters that may precede an attribute. // Browsers often parse these incorrectly and that has been a // of numerous XSS issues we've had. $matches['attributes'] = preg_replace('#^[^a-z]+#i', '', $matches['attributes']); diff --git a/system/core/compat/hash.php b/system/core/compat/hash.php index ba0198e10..c65203aaf 100644 --- a/system/core/compat/hash.php +++ b/system/core/compat/hash.php @@ -173,7 +173,9 @@ if ( ! function_exists('hash_pbkdf2')) return FALSE; } - $hash_length = strlen(hash($algo, NULL, TRUE)); + $hash_length = defined('MB_OVERLOAD_STRING') + ? mb_strlen(hash($algo, NULL, TRUE), '8bit') + : strlen(hash($algo, NULL, TRUE)); empty($length) && $length = $hash_length; // Pre-hash password inputs longer than the algorithm's block size @@ -221,14 +223,14 @@ if ( ! function_exists('hash_pbkdf2')) 'whirlpool' => 64 ); - if (isset($block_sizes[$algo]) && strlen($password) > $block_sizes[$algo]) + if (isset($block_sizes[$algo], $password[$block_sizes[$algo]])) { $password = hash($algo, $password, TRUE); } $hash = ''; // Note: Blocks are NOT 0-indexed - for ($bc = ceil($length / $hash_length), $bi = 1; $bi <= $bc; $bi++) + for ($bc = (int) ceil($length / $hash_length), $bi = 1; $bi <= $bc; $bi++) { $key = $derived_key = hash_hmac($algo, $salt.pack('N', $bi), $password, TRUE); for ($i = 1; $i < $iterations; $i++) @@ -240,6 +242,13 @@ if ( ! function_exists('hash_pbkdf2')) } // This is not RFC-compatible, but we're aiming for natural PHP compatibility - return substr($raw_output ? $hash : bin2hex($hash), 0, $length); + if ( ! $raw_output) + { + $hash = bin2hex($hash); + } + + return defined('MB_OVERLOAD_STRING') + ? mb_substr($hash, 0, $length, '8bit') + : substr($hash, 0, $length); } } diff --git a/system/core/compat/mbstring.php b/system/core/compat/mbstring.php index f466e1c34..1b2f2c63b 100644 --- a/system/core/compat/mbstring.php +++ b/system/core/compat/mbstring.php @@ -68,7 +68,7 @@ if ( ! function_exists('mb_strlen')) * @link http://php.net/mb_strlen * @param string $str * @param string $encoding - * @return string + * @return int */ function mb_strlen($str, $encoding = NULL) { diff --git a/system/core/compat/password.php b/system/core/compat/password.php index b209cbe70..8176f0088 100644 --- a/system/core/compat/password.php +++ b/system/core/compat/password.php @@ -94,8 +94,8 @@ if ( ! function_exists('password_hash')) */ function password_hash($password, $algo, array $options = array()) { - static $func_override; - isset($func_override) OR $func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); + static $func_overload; + isset($func_overload) OR $func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); if ($algo !== 1) { @@ -109,7 +109,7 @@ if ( ! function_exists('password_hash')) return NULL; } - if (isset($options['salt']) && ($saltlen = ($func_override ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))) < 22) + if (isset($options['salt']) && ($saltlen = ($func_overload ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))) < 22) { trigger_error('password_hash(): Provided salt is too short: '.$saltlen.' expecting 22', E_USER_WARNING); return NULL; @@ -144,7 +144,7 @@ if ( ! function_exists('password_hash')) is_php('5.4') && stream_set_chunk_size($fp, 16); $options['salt'] = ''; - for ($read = 0; $read < 16; $read = ($func_override) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt'])) + for ($read = 0; $read < 16; $read = ($func_overload) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt'])) { if (($read = fread($fp, 16 - $read)) === FALSE) { diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php index b74c31924..7c8ee5fc9 100644 --- a/system/database/DB_cache.php +++ b/system/database/DB_cache.php @@ -143,7 +143,7 @@ class CI_DB_Cache { $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); $filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql); - if (FALSE === ($cachedata = @file_get_contents($filepath))) + if ( ! is_file($filepath) OR FALSE === ($cachedata = file_get_contents($filepath))) { return FALSE; } diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index 19afdd492..0b13a2f82 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -916,6 +916,7 @@ abstract class CI_DB_driver { if ($this->_trans_begin()) { + $this->_trans_status = TRUE; $this->_trans_depth++; return TRUE; } @@ -1044,7 +1045,7 @@ abstract class CI_DB_driver { */ public function is_write_type($sql) { - return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s/i', $sql); + return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX|MERGE)\s/i', $sql); } // -------------------------------------------------------------------- @@ -1173,14 +1174,14 @@ abstract class CI_DB_driver { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string */ protected function _escape_str($str) { - return str_replace("'", "''", remove_invisible_characters($str)); + return str_replace("'", "''", remove_invisible_characters($str, FALSE)); } // -------------------------------------------------------------------- diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index 7289235c8..3cb02ca4e 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -488,7 +488,7 @@ abstract class CI_DB_forge { * * @param string $table Table name * @param bool $if_exists Whether to add an IF EXISTS condition - * @return string + * @return mixed (Returns a platform-specific DROP table string, or TRUE to indicate there's nothing to do) */ protected function _drop_table($table, $if_exists) { @@ -979,8 +979,8 @@ abstract class CI_DB_forge { /** * Process indexes * - * @param string $table - * @return string + * @param string $table Table name + * @return string[] list of SQL statements */ protected function _process_indexes($table) { diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index ab19d97a2..81603bf31 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -215,6 +215,13 @@ abstract class CI_DB_query_builder extends CI_DB_driver { protected $qb_cache_join = array(); /** + * QB Cache aliased tables list + * + * @var array + */ + protected $qb_cache_aliased_tables = array(); + + /** * QB Cache WHERE data * * @var array @@ -1396,13 +1403,11 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // ORDER BY usage is often problematic here (most notably // on Microsoft SQL Server) and ultimately unnecessary // for selecting COUNT(*) ... - if ( ! empty($this->qb_orderby)) - { - $orderby = $this->qb_orderby; - $this->qb_orderby = NULL; - } + $qb_orderby = $this->qb_orderby; + $qb_cache_orderby = $this->qb_cache_orderby; + $this->qb_orderby = $this->qb_cache_orderby = NULL; - $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby) OR ! empty($this->qb_cache_groupby)) + $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby) OR ! empty($this->qb_cache_groupby) OR $this->qb_limit OR $this->qb_offset) ? $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'))); @@ -1410,10 +1415,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { $this->_reset_select(); } - // If we've previously reset the qb_orderby values, get them back - elseif ( ! isset($this->qb_orderby)) + else { - $this->qb_orderby = $orderby; + $this->qb_orderby = $qb_orderby; + $this->qb_cache_orderby = $qb_cache_orderby; } if ($result->num_rows() === 0) @@ -2281,9 +2286,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $table = trim(strrchr($table, ' ')); // Store the alias, if it doesn't already exist - if ( ! in_array($table, $this->qb_aliased_tables)) + if ( ! in_array($table, $this->qb_aliased_tables, TRUE)) { $this->qb_aliased_tables[] = $table; + if ($this->qb_caching === TRUE && ! in_array($table, $this->qb_cache_aliased_tables, TRUE)) + { + $this->qb_cache_aliased_tables[] = $table; + $this->qb_cache_exists[] = 'aliased_tables'; + } } } } @@ -2441,7 +2451,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * Escapes identifiers in GROUP BY statements at execution time. * - * Required so that aliases are tracked properly, regardless of wether + * Required so that aliases are tracked properly, regardless of whether * group_by() is called prior to from(), join() and dbprefix is added * only if needed. * @@ -2477,7 +2487,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * Escapes identifiers in ORDER BY statements at execution time. * - * Required so that aliases are tracked properly, regardless of wether + * Required so that aliases are tracked properly, regardless of whether * order_by() is called prior to from(), join() and dbprefix is added * only if needed. * @@ -2485,26 +2495,27 @@ abstract class CI_DB_query_builder extends CI_DB_driver { */ protected function _compile_order_by() { - if (is_array($this->qb_orderby) && count($this->qb_orderby) > 0) + if (empty($this->qb_orderby)) { - for ($i = 0, $c = count($this->qb_orderby); $i < $c; $i++) + return ''; + } + + for ($i = 0, $c = count($this->qb_orderby); $i < $c; $i++) + { + if (is_string($this->qb_orderby[$i])) { - if ($this->qb_orderby[$i]['escape'] !== FALSE && ! $this->_is_literal($this->qb_orderby[$i]['field'])) - { - $this->qb_orderby[$i]['field'] = $this->protect_identifiers($this->qb_orderby[$i]['field']); - } + continue; + } - $this->qb_orderby[$i] = $this->qb_orderby[$i]['field'].$this->qb_orderby[$i]['direction']; + if ($this->qb_orderby[$i]['escape'] !== FALSE && ! $this->_is_literal($this->qb_orderby[$i]['field'])) + { + $this->qb_orderby[$i]['field'] = $this->protect_identifiers($this->qb_orderby[$i]['field']); } - return $this->qb_orderby = "\nORDER BY ".implode(', ', $this->qb_orderby); - } - elseif (is_string($this->qb_orderby)) - { - return $this->qb_orderby; + $this->qb_orderby[$i] = $this->qb_orderby[$i]['field'].$this->qb_orderby[$i]['direction']; } - return ''; + return "\nORDER BY ".implode(', ', $this->qb_orderby); } // -------------------------------------------------------------------- @@ -2625,7 +2636,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { 'qb_cache_orderby' => array(), 'qb_cache_set' => array(), 'qb_cache_exists' => array(), - 'qb_cache_no_escape' => array() + 'qb_cache_no_escape' => array(), + 'qb_cache_aliased_tables' => array() )); return $this; @@ -2676,13 +2688,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->qb_no_escape = $qb_no_escape; } } - - // If we are "protecting identifiers" we need to examine the "from" - // portion of the query to determine if there are any aliases - if ($this->_protect_identifiers === TRUE && count($this->qb_cache_from) > 0) - { - $this->_track_aliases($this->qb_from); - } } // -------------------------------------------------------------------- diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php index 257925d88..6e8aff7c6 100644 --- a/system/database/drivers/cubrid/cubrid_driver.php +++ b/system/database/drivers/cubrid/cubrid_driver.php @@ -250,7 +250,7 @@ class CI_DB_cubrid_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string @@ -361,7 +361,7 @@ class CI_DB_cubrid_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php index 106d5efac..3069d6699 100644 --- a/system/database/drivers/ibase/ibase_driver.php +++ b/system/database/drivers/ibase/ibase_driver.php @@ -294,7 +294,7 @@ class CI_DB_ibase_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ @@ -395,7 +395,7 @@ class CI_DB_ibase_driver extends CI_DB { */ protected function _insert_batch($table, $keys, $values) { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; } // -------------------------------------------------------------------- diff --git a/system/database/drivers/ibase/ibase_forge.php b/system/database/drivers/ibase/ibase_forge.php index 44bb24e68..31352f128 100644 --- a/system/database/drivers/ibase/ibase_forge.php +++ b/system/database/drivers/ibase/ibase_forge.php @@ -91,7 +91,7 @@ class CI_DB_ibase_forge extends CI_DB_forge { * Create database * * @param string $db_name - * @return string + * @return bool */ public function create_database($db_name) { diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index f0cfb2ff9..cb89f3b3f 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -352,7 +352,7 @@ class CI_DB_mssql_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ @@ -453,7 +453,7 @@ class CI_DB_mssql_driver extends CI_DB { $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results - if (count($this->qb_select) === 0) + if (count($this->qb_select) === 0 OR strpos(implode(',', $this->qb_select), '*') !== FALSE) { $select = '*'; // Inevitable } @@ -500,7 +500,7 @@ class CI_DB_mssql_driver extends CI_DB { return parent::_insert_batch($table, $keys, $values); } - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; } // -------------------------------------------------------------------- diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php index 8f2dd744d..71dad676e 100644 --- a/system/database/drivers/mysql/mysql_driver.php +++ b/system/database/drivers/mysql/mysql_driver.php @@ -337,7 +337,7 @@ class CI_DB_mysql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string @@ -448,7 +448,7 @@ class CI_DB_mysql_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php index 7e4290474..b59e89494 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -210,7 +210,7 @@ class CI_DB_mysqli_driver extends CI_DB { $this->_mysqli->close(); $message = 'MySQLi was configured for an SSL connection, but got an unencrypted connection instead!'; log_message('error', $message); - return ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE; + return ($this->db_debug) ? $this->display_error($message, '', TRUE) : FALSE; } return $this->_mysqli; @@ -381,7 +381,7 @@ class CI_DB_mysqli_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php index 929c2b455..0b3d9c2b4 100644 --- a/system/database/drivers/mysqli/mysqli_result.php +++ b/system/database/drivers/mysqli/mysqli_result.php @@ -112,9 +112,9 @@ class CI_DB_mysqli_result extends CI_DB_result { { $retval[$i] = new stdClass(); $retval[$i]->name = $field_data[$i]->name; - $retval[$i]->type = $field_data[$i]->type; + $retval[$i]->type = static::_get_field_type($field_data[$i]->type); $retval[$i]->max_length = $field_data[$i]->max_length; - $retval[$i]->primary_key = (int) ($field_data[$i]->flags & 2); + $retval[$i]->primary_key = (int) ($field_data[$i]->flags & MYSQLI_PRI_KEY_FLAG); $retval[$i]->default = $field_data[$i]->def; } @@ -124,6 +124,60 @@ class CI_DB_mysqli_result extends CI_DB_result { // -------------------------------------------------------------------- /** + * Get field type + * + * Extracts field type info from the bitflags returned by + * mysqli_result::fetch_fields() + * + * @used-by CI_DB_mysqli_result::field_data() + * @param int $flags + * @return string + */ + private static function _get_field_type($flags) + { + static $map; + isset($map) OR $map = array( + MYSQLI_TYPE_DECIMAL => 'decimal', + MYSQLI_TYPE_BIT => 'bit', + MYSQLI_TYPE_TINY => 'tinyint', + MYSQLI_TYPE_SHORT => 'smallint', + MYSQLI_TYPE_INT24 => 'mediumint', + MYSQLI_TYPE_LONG => 'int', + MYSQLI_TYPE_LONGLONG => 'bigint', + MYSQLI_TYPE_FLOAT => 'float', + MYSQLI_TYPE_DOUBLE => 'double', + MYSQLI_TYPE_TIMESTAMP => 'timestamp', + MYSQLI_TYPE_DATE => 'date', + MYSQLI_TYPE_TIME => 'time', + MYSQLI_TYPE_DATETIME => 'datetime', + MYSQLI_TYPE_YEAR => 'year', + MYSQLI_TYPE_NEWDATE => 'date', + MYSQLI_TYPE_INTERVAL => 'interval', + MYSQLI_TYPE_ENUM => 'enum', + MYSQLI_TYPE_SET => 'set', + MYSQLI_TYPE_TINY_BLOB => 'tinyblob', + MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob', + MYSQLI_TYPE_BLOB => 'blob', + MYSQLI_TYPE_LONG_BLOB => 'longblob', + MYSQLI_TYPE_STRING => 'char', + MYSQLI_TYPE_VAR_STRING => 'varchar', + MYSQLI_TYPE_GEOMETRY => 'geometry' + ); + + foreach ($map as $flag => $name) + { + if ($flags & $flag) + { + return $name; + } + } + + return $flags; + } + + // -------------------------------------------------------------------- + + /** * Free the result * * @return void diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php index 4a3dad4d1..1699b611f 100644 --- a/system/database/drivers/mysqli/mysqli_utility.php +++ b/system/database/drivers/mysqli/mysqli_utility.php @@ -155,9 +155,11 @@ class CI_DB_mysqli_utility extends CI_DB_utility { while ($field = $query->result_id->fetch_field()) { // Most versions of MySQL store timestamp as a string - $is_int[$i] = in_array(strtolower($field->type), - array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'), - TRUE); + $is_int[$i] = ($field->type & MYSQLI_TYPE_TINY) + OR ($field->type & MYSQLI_TYPE_SHORT) + OR ($field->type & MYSQLI_TYPE_INT24) + OR ($field->type & MYSQLI_TYPE_LONG) + OR ($field->type & MYSQLI_TYPE_LONGLONG); // Create a string of field names $field_str .= $this->db->escape_identifiers($field->name).', '; diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php index c7f033019..fb2f6b31b 100644 --- a/system/database/drivers/oci8/oci8_driver.php +++ b/system/database/drivers/oci8/oci8_driver.php @@ -553,7 +553,7 @@ class CI_DB_oci8_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php index 867a94341..724a76df4 100644 --- a/system/database/drivers/oci8/oci8_forge.php +++ b/system/database/drivers/oci8/oci8_forge.php @@ -124,7 +124,7 @@ class CI_DB_oci8_forge extends CI_DB_forge { if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name'])) { $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' '.$this->db->escape_identifiers($field[$i]['new_name']); + .' TO '.$this->db->escape_identifiers($field[$i]['new_name']); } $field[$i] = "\n\t".$field[$i]['_literal']; diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php index 9f5a86fa0..ef982fc63 100644 --- a/system/database/drivers/odbc/odbc_driver.php +++ b/system/database/drivers/odbc/odbc_driver.php @@ -309,14 +309,14 @@ class CI_DB_odbc_driver extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string */ protected function _escape_str($str) { - $this->db->display_error('db_unsupported_feature'); + $this->display_error('db_unsupported_feature'); } // -------------------------------------------------------------------- @@ -340,7 +340,7 @@ class CI_DB_odbc_driver extends CI_DB_driver { */ public function insert_id() { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; } // -------------------------------------------------------------------- @@ -402,7 +402,7 @@ class CI_DB_odbc_driver extends CI_DB_driver { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php index d816dcb64..6afc999c2 100644 --- a/system/database/drivers/pdo/pdo_driver.php +++ b/system/database/drivers/pdo/pdo_driver.php @@ -223,7 +223,7 @@ class CI_DB_pdo_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string @@ -285,7 +285,7 @@ class CI_DB_pdo_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php index 3249a1d7f..b9b86f784 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php @@ -284,7 +284,7 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results - if (count($this->qb_select) === 0) + if (count($this->qb_select) === 0 OR strpos(implode(',', $this->qb_select), '*') !== FALSE) { $select = '*'; // Inevitable } @@ -331,7 +331,23 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { return parent::_insert_batch($table, $keys, $values); } - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; } + // -------------------------------------------------------------------- + + /** + * Database version number + * + * @return string + */ + public function version() + { + if (isset($this->data_cache['version'])) + { + return $this->data_cache['version']; + } + + return $this->data_cache['version'] = $this->conn_id->query("SELECT SERVERPROPERTY('ProductVersion') AS ver")->fetchColumn(0); + } } diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php index aa5e7d6e7..cb93f19b7 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php @@ -274,6 +274,6 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver { */ protected function _insert_batch($table, $keys, $values) { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; } } diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php index 66c15dac6..64b13d827 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php @@ -182,7 +182,7 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { { $message = 'PDO_MYSQL was configured for an SSL connection, but got an unencrypted connection instead!'; log_message('error', $message); - return ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE; + return ($this->db_debug) ? $this->display_error($message, '', TRUE) : FALSE; } return $pdo; diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php index c8983ee56..813207b8e 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php +++ b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php @@ -117,7 +117,7 @@ class CI_DB_pdo_oci_forge extends CI_DB_pdo_forge { if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name'])) { $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' '.$this->db->escape_identifiers($field[$i]['new_name']); + .' TO '.$this->db->escape_identifiers($field[$i]['new_name']); } } } diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php index f4a2f08f3..066dd9614 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php @@ -161,14 +161,14 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string */ protected function _escape_str($str) { - $this->db->display_error('db_unsupported_feature'); + $this->display_error('db_unsupported_feature'); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php index 18e399dac..b00af4ad0 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php +++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php @@ -168,7 +168,7 @@ class CI_DB_pdo_pgsql_forge extends CI_DB_pdo_forge { */ protected function _attr_type(&$attributes) { - // Reset field lenghts for data types that don't support it + // Reset field lengths for data types that don't support it if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE) { $attributes['CONSTRAINT'] = NULL; diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php index 1cf6c614d..a9fb4d14a 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php @@ -316,7 +316,7 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results - if (count($this->qb_select) === 0) + if (count($this->qb_select) === 0 OR strpos(implode(',', $this->qb_select), '*') !== FALSE) { $select = '*'; // Inevitable } @@ -363,7 +363,7 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { return parent::_insert_batch($table, $keys, $values); } - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; } } diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php index cef464af4..bcdfc060a 100644 --- a/system/database/drivers/postgre/postgre_driver.php +++ b/system/database/drivers/postgre/postgre_driver.php @@ -130,9 +130,9 @@ class CI_DB_postgre_driver extends CI_DB { */ foreach (array('connect_timeout', 'options', 'sslmode', 'service') as $key) { - if (isset($this->$key) && is_string($this->key) && $this->key !== '') + if (isset($this->$key) && is_string($this->$key) && $this->$key !== '') { - $this->dsn .= $key."='".$this->key."' "; + $this->dsn .= $key."='".$this->$key."' "; } } @@ -299,7 +299,7 @@ class CI_DB_postgre_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string @@ -471,7 +471,7 @@ class CI_DB_postgre_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php index f7bbf7441..cdbff4c4b 100644 --- a/system/database/drivers/postgre/postgre_forge.php +++ b/system/database/drivers/postgre/postgre_forge.php @@ -163,7 +163,7 @@ class CI_DB_postgre_forge extends CI_DB_forge { */ protected function _attr_type(&$attributes) { - // Reset field lenghts for data types that don't support it + // Reset field lengths for data types that don't support it if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE) { $attributes['CONSTRAINT'] = NULL; diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php index 2d78a0f8a..d131baad7 100644 --- a/system/database/drivers/sqlite3/sqlite3_driver.php +++ b/system/database/drivers/sqlite3/sqlite3_driver.php @@ -168,7 +168,7 @@ class CI_DB_sqlite3_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string @@ -291,7 +291,7 @@ class CI_DB_sqlite3_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php index 10aad115f..4edcc7fb8 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -358,7 +358,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { * Error * * Returns an array containing code and message of the last - * database error that has occured. + * database error that has occurred. * * @return array */ @@ -478,7 +478,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results - if (count($this->qb_select) === 0) + if (count($this->qb_select) === 0 OR strpos(implode(',', $this->qb_select), '*') !== FALSE) { $select = '*'; // Inevitable } @@ -525,7 +525,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { return parent::_insert_batch($table, $keys, $values); } - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; } // -------------------------------------------------------------------- diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php index bb90cba1e..b943edbae 100644 --- a/system/helpers/cookie_helper.php +++ b/system/helpers/cookie_helper.php @@ -67,7 +67,7 @@ if ( ! function_exists('set_cookie')) * @param bool true makes the cookie accessible via http(s) only (no javascript) * @return void */ - function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE) + function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL) { // Set the config file options get_instance()->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httponly); diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index a49eea803..13f196318 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -597,7 +597,7 @@ if ( ! function_exists('form_label')) * * @param string The text to appear onscreen * @param string The id the label applies to - * @param array Additional attributes + * @param mixed Additional attributes * @return string */ function form_label($label_text = '', $id = '', $attributes = array()) @@ -610,13 +610,7 @@ if ( ! function_exists('form_label')) $label .= ' for="'.$id.'"'; } - if (is_array($attributes) && count($attributes) > 0) - { - foreach ($attributes as $key => $val) - { - $label .= ' '.$key.'="'.$val.'"'; - } - } + $label .= _attributes_to_string($attributes); return $label.'>'.$label_text.'</label>'; } diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php index de1b92cde..87a5f9b23 100644 --- a/system/helpers/html_helper.php +++ b/system/helpers/html_helper.php @@ -192,7 +192,7 @@ if ( ! function_exists('img')) foreach ($src as $k => $v) { - if ($k === 'src' && ! preg_match('#^([a-z]+:)?//#i', $v)) + if ($k === 'src' && ! preg_match('#^(data:[a-z,;])|(([a-z]+:)?(?<!data:)//)#i', $v)) { if ($index_page === TRUE) { diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php index 26a5a5ca9..4a6805fbb 100644 --- a/system/helpers/inflector_helper.php +++ b/system/helpers/inflector_helper.php @@ -95,6 +95,7 @@ if ( ! function_exists('singular')) '/(s)tatuses$/' => '\1\2tatus', '/(c)hildren$/' => '\1\2hild', '/(n)ews$/' => '\1\2ews', + '/(quiz)zes$/' => '\1', '/([^us])s$/' => '\1' ); diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php index 23608e5f4..93446b82f 100644 --- a/system/helpers/string_helper.php +++ b/system/helpers/string_helper.php @@ -195,9 +195,7 @@ if ( ! function_exists('reduce_multiples')) if ( ! function_exists('random_string')) { /** - * Create a Random String - * - * Useful for generating passwords or hashes. + * Create a "Random" String * * @param string type of random string. basic, alpha, alnum, numeric, nozero, unique, md5, encrypt and sha1 * @param int number of characters diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php index 07c01c3af..217729b70 100644 --- a/system/helpers/text_helper.php +++ b/system/helpers/text_helper.php @@ -138,7 +138,10 @@ if ( ! function_exists('ascii_to_entities')) function ascii_to_entities($str) { $out = ''; - for ($i = 0, $s = strlen($str) - 1, $count = 1, $temp = array(); $i <= $s; $i++) + $length = defined('MB_OVERLOAD_STRING') + ? mb_strlen($str, '8bit') - 1 + : strlen($str) - 1; + for ($i = 0, $count = 1, $temp = array(); $i <= $length; $i++) { $ordinal = ord($str[$i]); @@ -176,7 +179,7 @@ if ( ! function_exists('ascii_to_entities')) $temp = array(); } // If this is the last iteration, just output whatever we have - elseif ($i === $s) + elseif ($i === $length) { $out .= '&#'.implode(';', $temp).';'; } diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php index f2b61adb1..c873eb640 100644 --- a/system/libraries/Cache/drivers/Cache_apc.php +++ b/system/libraries/Cache/drivers/Cache_apc.php @@ -80,14 +80,7 @@ class CI_Cache_apc extends CI_Driver { $success = FALSE; $data = apc_fetch($id, $success); - if ($success === TRUE) - { - return is_array($data) - ? unserialize($data[0]) - : $data; - } - - return FALSE; + return ($success === TRUE) ? $data : FALSE; } // ------------------------------------------------------------------------ @@ -98,18 +91,12 @@ class CI_Cache_apc extends CI_Driver { * @param string $id Cache ID * @param mixed $data Data to store * @param int $ttl Length of time (in seconds) to cache the data - * @param bool $raw Whether to store the raw value + * @param bool $raw Whether to store the raw value (unused) * @return bool TRUE on success, FALSE on failure */ public function save($id, $data, $ttl = 60, $raw = FALSE) { - $ttl = (int) $ttl; - - return apc_store( - $id, - ($raw === TRUE ? $data : array(serialize($data), time(), $ttl)), - $ttl - ); + return apc_store($id, $data, (int) $ttl); } // ------------------------------------------------------------------------ @@ -188,21 +175,30 @@ class CI_Cache_apc extends CI_Driver { */ public function get_metadata($id) { - $success = FALSE; - $stored = apc_fetch($id, $success); - - if ($success === FALSE OR count($stored) !== 3) + $cache_info = apc_cache_info('user', FALSE); + if (empty($cache_info) OR empty($cache_info['cache_list'])) { return FALSE; } - list($data, $time, $ttl) = $stored; + foreach ($cache_info['cache_list'] as &$entry) + { + if ($entry['info'] !== $id) + { + continue; + } + + $success = FALSE; + $metadata = array( + 'expire' => ($entry['ttl'] ? $entry['mtime'] + $entry['ttl'] : 0), + 'mtime' => $entry['ttl'], + 'data' => apc_fetch($id, $success) + ); + + return ($success === TRUE) ? $metadata : FALSE; + } - return array( - 'expire' => $time + $ttl, - 'mtime' => $time, - 'data' => unserialize($data) - ); + return FALSE; } // ------------------------------------------------------------------------ diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php index 17e361107..b642a2c03 100644 --- a/system/libraries/Cache/drivers/Cache_memcached.php +++ b/system/libraries/Cache/drivers/Cache_memcached.php @@ -110,7 +110,7 @@ class CI_Cache_memcached extends CI_Driver { if ($this->_memcached instanceof Memcache) { - // Third parameter is persistance and defaults to TRUE. + // Third parameter is persistence and defaults to TRUE. $this->_memcached->addServer( $cache_server['hostname'], $cache_server['port'], diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 117c4845f..0e9cf0574 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -375,11 +375,11 @@ class CI_Email { ); /** - * mbstring.func_override flag + * mbstring.func_overload flag * * @var bool */ - protected static $func_override; + protected static $func_overload; // -------------------------------------------------------------------- @@ -397,7 +397,7 @@ class CI_Email { $this->initialize($config); $this->_safe_mode = ( ! is_php('5.4') && ini_get('safe_mode')); - isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); + isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); log_message('info', 'Email Class Initialized'); } @@ -913,18 +913,13 @@ class CI_Email { /** * Get Mail Protocol * - * @param bool * @return mixed */ - protected function _get_protocol($return = TRUE) + protected function _get_protocol() { $this->protocol = strtolower($this->protocol); in_array($this->protocol, $this->_protocols, TRUE) OR $this->protocol = 'mail'; - - if ($return === TRUE) - { - return $this->protocol; - } + return $this->protocol; } // -------------------------------------------------------------------- @@ -932,25 +927,21 @@ class CI_Email { /** * Get Mail Encoding * - * @param bool * @return string */ - protected function _get_encoding($return = TRUE) + protected function _get_encoding() { in_array($this->_encoding, $this->_bit_depths) OR $this->_encoding = '8bit'; foreach ($this->_base_charsets as $charset) { - if (strpos($charset, $this->charset) === 0) + if (strpos($this->charset, $charset) === 0) { $this->_encoding = '7bit'; } } - if ($return === TRUE) - { - return $this->_encoding; - } + return $this->_encoding; } // -------------------------------------------------------------------- @@ -1829,14 +1820,15 @@ class CI_Email { { $this->_unwrap_specials(); - $method = '_send_with_'.$this->_get_protocol(); + $protocol = $this->_get_protocol(); + $method = '_send_with_'.$protocol; if ( ! $this->$method()) { - $this->_set_error_message('lang:email_send_failure_'.($this->_get_protocol() === 'mail' ? 'phpmail' : $this->_get_protocol())); + $this->_set_error_message('lang:email_send_failure_'.($protocol === 'mail' ? 'phpmail' : $protocol)); return FALSE; } - $this->_set_error_message('lang:email_sent', $this->_get_protocol()); + $this->_set_error_message('lang:email_sent', $protocol); return TRUE; } @@ -2442,7 +2434,7 @@ class CI_Email { */ protected static function strlen($str) { - return (self::$func_override) + return (self::$func_overload) ? mb_strlen($str, '8bit') : strlen($str); } @@ -2459,7 +2451,7 @@ class CI_Email { */ protected static function substr($str, $start, $length = NULL) { - if (self::$func_override) + if (self::$func_overload) { // mb_substr($str, $start, null, '8bit') returns an empty // string on PHP 5.3 diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php index 46f374726..ebcc6e8c6 100644 --- a/system/libraries/Encrypt.php +++ b/system/libraries/Encrypt.php @@ -122,7 +122,7 @@ class CI_Encrypt { $key = config_item('encryption_key'); - if ( ! strlen($key)) + if ( ! self::strlen($key)) { show_error('In order to use the encryption class requires that you set an encryption key in your config file.'); } @@ -252,7 +252,7 @@ class CI_Encrypt { $string = $this->_xor_merge($string, $key); $dec = ''; - for ($i = 0, $l = strlen($string); $i < $l; $i++) + for ($i = 0, $l = self::strlen($string); $i < $l; $i++) { $dec .= ($string[$i++] ^ $string[$i]); } @@ -275,7 +275,8 @@ class CI_Encrypt { { $hash = $this->hash($key); $str = ''; - for ($i = 0, $ls = strlen($string), $lh = strlen($hash); $i < $ls; $i++) + + for ($i = 0, $ls = self::strlen($string), $lh = self::strlen($hash); $i < $ls; $i++) { $str .= $string[$i] ^ $hash[($i % $lh)]; } @@ -295,7 +296,7 @@ class CI_Encrypt { public function mcrypt_encode($data, $key) { $init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode()); - $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND); + $init_vect = mcrypt_create_iv($init_size, MCRYPT_DEV_URANDOM); return $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key); } @@ -313,13 +314,14 @@ class CI_Encrypt { $data = $this->_remove_cipher_noise($data, $key); $init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode()); - if ($init_size > strlen($data)) + if ($init_size > self::strlen($data)) { return FALSE; } - $init_vect = substr($data, 0, $init_size); - $data = substr($data, $init_size); + $init_vect = self::substr($data, 0, $init_size); + $data = self::substr($data, $init_size); + return rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), "\0"); } @@ -339,7 +341,7 @@ class CI_Encrypt { $key = $this->hash($key); $str = ''; - for ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j) + for ($i = 0, $j = 0, $ld = self::strlen($data), $lk = self::strlen($key); $i < $ld; ++$i, ++$j) { if ($j >= $lk) { @@ -369,7 +371,7 @@ class CI_Encrypt { $key = $this->hash($key); $str = ''; - for ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j) + for ($i = 0, $j = 0, $ld = self::strlen($data), $lk = self::strlen($key); $i < $ld; ++$i, ++$j) { if ($j >= $lk) { @@ -477,4 +479,43 @@ class CI_Encrypt { return hash($this->_hash_type, $str); } + // -------------------------------------------------------------------- + + /** + * Byte-safe strlen() + * + * @param string $str + * @return int + */ + protected static function strlen($str) + { + return defined('MB_OVERLOAD_STRING') + ? mb_strlen($str, '8bit') + : strlen($str); + } + + // -------------------------------------------------------------------- + + /** + * Byte-safe substr() + * + * @param string $str + * @param int $start + * @param int $length + * @return string + */ + protected static function substr($str, $start, $length = NULL) + { + if (defined('MB_OVERLOAD_STRING')) + { + // mb_substr($str, $start, null, '8bit') returns an empty + // string on PHP 5.3 + isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); + return mb_substr($str, $start, $length, '8bit'); + } + + return isset($length) + ? substr($str, $start, $length) + : substr($str, $start); + } } diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php index 74832ede6..c1e454dda 100644 --- a/system/libraries/Encryption.php +++ b/system/libraries/Encryption.php @@ -135,11 +135,11 @@ class CI_Encryption { ); /** - * mbstring.func_override flag + * mbstring.func_overload flag * * @var bool */ - protected static $func_override; + protected static $func_overload; // -------------------------------------------------------------------- @@ -161,7 +161,7 @@ class CI_Encryption { show_error('Encryption: Unable to find an available encryption driver.'); } - isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); + isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); $this->initialize($params); if ( ! isset($this->_key) && self::strlen($key = config_item('encryption_key')) > 0) @@ -911,7 +911,7 @@ class CI_Encryption { */ protected static function strlen($str) { - return (self::$func_override) + return (self::$func_overload) ? mb_strlen($str, '8bit') : strlen($str); } @@ -928,7 +928,7 @@ class CI_Encryption { */ protected static function substr($str, $start, $length = NULL) { - if (self::$func_override) + if (self::$func_overload) { // mb_substr($str, $start, null, '8bit') returns an empty // string on PHP 5.3 diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index 4f679a17f..71d0e64b1 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -1229,9 +1229,9 @@ class CI_Form_validation { */ public function valid_email($str) { - if (function_exists('idn_to_ascii') && sscanf($str, '%[^@]@%s', $name, $domain) === 2) + if (function_exists('idn_to_ascii') && preg_match('#\A([^@]+)@(.+)\z#', $str, $matches)) { - $str = $name.'@'.idn_to_ascii($domain); + $str = $matches[1].'@'.idn_to_ascii($matches[2]); } return (bool) filter_var($str, FILTER_VALIDATE_EMAIL); diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php index ac960a419..86e5b8f33 100644 --- a/system/libraries/Ftp.php +++ b/system/libraries/Ftp.php @@ -486,7 +486,7 @@ class CI_FTP { { for ($i = 0, $c = count($list); $i < $c; $i++) { - // If we can't delete the item it's probaly a directory, + // If we can't delete the item it's probably a directory, // so we'll recursively call delete_dir() if ( ! preg_match('#/\.\.?$#', $list[$i]) && ! @ftp_delete($this->conn_id, $list[$i])) { diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php index 9ec44da0c..8786d9d02 100644 --- a/system/libraries/Image_lib.php +++ b/system/libraries/Image_lib.php @@ -392,6 +392,16 @@ class CI_Image_lib { $this->initialize($props); } + /** + * A work-around for some improperly formatted, but + * usable JPEGs; known to be produced by Samsung + * smartphones' front-facing cameras. + * + * @see https://github.com/bcit-ci/CodeIgniter/issues/4967 + * @see https://bugs.php.net/bug.php?id=72404 + */ + ini_set('gd.jpeg_ignore_warning', 1); + log_message('info', 'Image Lib Class Initialized'); } @@ -962,7 +972,7 @@ class CI_Image_lib { $cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height; } - $cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp'; + $cmd = $this->library_path.$cmd_in.' '.escapeshellarg($this->full_src_path).' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp'; $retval = 1; // exec() might be disabled diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php index 1df5f9cd5..f26f8a4ed 100644 --- a/system/libraries/Pagination.php +++ b/system/libraries/Pagination.php @@ -428,7 +428,7 @@ class CI_Pagination { { $get = $this->CI->input->get(); - // Unset the controll, method, old-school routing options + // Unset the control, method, old-school routing options unset($get['c'], $get['m'], $get[$this->query_string_segment]); } else diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php index e9e03cfe0..cb3eaed75 100644 --- a/system/libraries/Profiler.php +++ b/system/libraries/Profiler.php @@ -316,7 +316,7 @@ class CI_Profiler { { is_int($key) OR $key = "'".htmlspecialchars($key, ENT_QUOTES, config_item('charset'))."'"; $val = (is_array($val) OR is_object($val)) - ? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')) + ? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')).'</pre>' : htmlspecialchars($val, ENT_QUOTES, config_item('charset')); $output .= '<tr><td style="width:50%;color:#000;background-color:#ddd;padding:5px;">$_GET[' @@ -356,7 +356,7 @@ class CI_Profiler { { is_int($key) OR $key = "'".htmlspecialchars($key, ENT_QUOTES, config_item('charset'))."'"; $val = (is_array($val) OR is_object($val)) - ? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')) + ? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')).'</pre>' : htmlspecialchars($val, ENT_QUOTES, config_item('charset')); $output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">$_POST[' @@ -368,7 +368,7 @@ class CI_Profiler { { is_int($key) OR $key = "'".htmlspecialchars($key, ENT_QUOTES, config_item('charset'))."'"; $val = (is_array($val) OR is_object($val)) - ? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')) + ? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')).'</pre>' : htmlspecialchars($val, ENT_QUOTES, config_item('charset')); $output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">$_FILES[' @@ -484,13 +484,19 @@ class CI_Profiler { foreach ($this->CI->config->config as $config => $val) { + $pre = ''; + $pre_close = ''; + if (is_array($val) OR is_object($val)) { $val = print_r($val, TRUE); + + $pre = '<pre>' ; + $pre_close = '</pre>'; } $output .= '<tr><td style="padding:5px;vertical-align:top;color:#900;background-color:#ddd;">' - .$config.' </td><td style="padding:5px;color:#000;background-color:#ddd;">'.htmlspecialchars($val)."</td></tr>\n"; + .$config.' </td><td style="padding:5px;color:#000;background-color:#ddd;">'.$pre.htmlspecialchars($val, ENT_QUOTES, config_item('charset')).$pre_close."</td></tr>\n"; } return $output."</table>\n</fieldset>"; @@ -516,13 +522,19 @@ class CI_Profiler { foreach ($this->CI->session->userdata() as $key => $val) { + $pre = ''; + $pre_close = ''; + if (is_array($val) OR is_object($val)) { $val = print_r($val, TRUE); + + $pre = '<pre>' ; + $pre_close = '</pre>'; } $output .= '<tr><td style="padding:5px;vertical-align:top;color:#900;background-color:#ddd;">' - .$key.' </td><td style="padding:5px;color:#000;background-color:#ddd;">'.htmlspecialchars($val)."</td></tr>\n"; + .$key.' </td><td style="padding:5px;color:#000;background-color:#ddd;">'.$pre.htmlspecialchars($val, ENT_QUOTES, config_item('charset')).$pre_close."</td></tr>\n"; } return $output."</table>\n</fieldset>"; diff --git a/system/libraries/Session/drivers/Session_database_driver.php b/system/libraries/Session/drivers/Session_database_driver.php index 31f5a4663..b519b782f 100644 --- a/system/libraries/Session/drivers/Session_database_driver.php +++ b/system/libraries/Session/drivers/Session_database_driver.php @@ -208,12 +208,8 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan // Prevent previous QB calls from messing with our queries $this->_db->reset_query(); - if ($this->_lock === FALSE) - { - return $this->_fail(); - } // Was the ID regenerated? - elseif ($session_id !== $this->_session_id) + if (isset($this->_session_id) && $session_id !== $this->_session_id) { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { @@ -223,6 +219,10 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan $this->_row_exists = FALSE; $this->_session_id = $session_id; } + elseif ($this->_lock === FALSE) + { + return $this->_fail(); + } if ($this->_row_exists === FALSE) { diff --git a/system/libraries/Session/drivers/Session_files_driver.php b/system/libraries/Session/drivers/Session_files_driver.php index 6016e094e..8860ef667 100644 --- a/system/libraries/Session/drivers/Session_files_driver.php +++ b/system/libraries/Session/drivers/Session_files_driver.php @@ -84,11 +84,11 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle protected $_sid_regexp; /** - * mbstring.func_override flag + * mbstring.func_overload flag * * @var bool */ - protected static $func_override; + protected static $func_overload; // ------------------------------------------------------------------------ @@ -115,7 +115,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle $this->_sid_regexp = $this->_config['_sid_regexp']; - isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); + isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); } // ------------------------------------------------------------------------ @@ -399,7 +399,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle */ protected static function strlen($str) { - return (self::$func_override) + return (self::$func_overload) ? mb_strlen($str, '8bit') : strlen($str); } diff --git a/system/libraries/Session/drivers/Session_memcached_driver.php b/system/libraries/Session/drivers/Session_memcached_driver.php index 2556bf0f7..5e90539d7 100644 --- a/system/libraries/Session/drivers/Session_memcached_driver.php +++ b/system/libraries/Session/drivers/Session_memcached_driver.php @@ -310,7 +310,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if ( ! $this->_memcached->replace($this->_lock_key, time(), 300)) { return ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND) - ? $this->_memcached->set($this->_lock_key, time(), 300) + ? $this->_memcached->add($this->_lock_key, time(), 300) : FALSE; } } @@ -326,7 +326,8 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa continue; } - if ( ! $this->_memcached->set($lock_key, time(), 300)) + $method = ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND) ? 'add' : 'set'; + if ( ! $this->_memcached->$method($lock_key, time(), 300)) { log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id); return FALSE; diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php index d260f7b82..a9e655a8c 100644 --- a/system/libraries/Session/drivers/Session_redis_driver.php +++ b/system/libraries/Session/drivers/Session_redis_driver.php @@ -51,7 +51,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle /** * phpRedis instance * - * @var resource + * @var Redis */ protected $_redis; @@ -341,7 +341,11 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle continue; } - if ( ! $this->_redis->setex($lock_key, 300, time())) + $result = ($ttl === -2) + ? $this->_redis->set($lock_key, time(), array('nx', 'ex' => 300)) + : $this->_redis->setex($lock_key, 300, time()); + + if ( ! $result) { log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id); return FALSE; diff --git a/system/libraries/Table.php b/system/libraries/Table.php index fef9bb039..50c5e358b 100644 --- a/system/libraries/Table.php +++ b/system/libraries/Table.php @@ -435,7 +435,7 @@ class CI_Table { /** * Set table data from a database result object * - * @param CI_DB_result $db_result Database result object + * @param CI_DB_result $object Database result object * @return void */ protected function _set_from_db_result($object) diff --git a/system/libraries/Typography.php b/system/libraries/Typography.php index ce31ba317..b25d8fdaa 100644 --- a/system/libraries/Typography.php +++ b/system/libraries/Typography.php @@ -241,7 +241,7 @@ class CI_Typography { // Clean up stray paragraph tags that appear before block level elements '#<p></p><('.$this->block_elements.')#' => '<$1', - // Clean up stray non-breaking spaces preceeding block elements + // Clean up stray non-breaking spaces preceding block elements '#( \s*)+<('.$this->block_elements.')#' => ' <$2', // Replace the temporary markers we added earlier diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index b37cc2f59..0ad8dd375 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -1312,7 +1312,7 @@ class CI_Upload { } } - // Fall back to the deprecated mime_content_type(), if available (still better than $_FILES[$field]['type']) + // Fall back to mime_content_type(), if available (still better than $_FILES[$field]['type']) if (function_exists('mime_content_type')) { $this->file_type = @mime_content_type($file['tmp_name']); diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index f043e0f90..6fa791864 100644 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -238,7 +238,7 @@ class CI_Xmlrpc { public $result; /** - * XML-RPC Reponse + * XML-RPC Response * * @var array */ @@ -460,7 +460,7 @@ class CI_Xmlrpc { { if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array')) { - while (list($k) = each($value[0])) + foreach (array_keys($value[0]) as $k) { $value[0][$k] = $this->values_parsing($value[0][$k]); } @@ -931,15 +931,15 @@ class XML_RPC_Response if (is_array($array)) { - while (list($key) = each($array)) + foreach ($array as $key => &$value) { - if (is_array($array[$key])) + if (is_array($value)) { - $array[$key] = $this->decode($array[$key]); + $array[$key] = $this->decode($value); } elseif ($this->xss_clean) { - $array[$key] = $CI->security->xss_clean($array[$key]); + $array[$key] = $CI->security->xss_clean($value); } } @@ -993,10 +993,11 @@ class XML_RPC_Response reset($xmlrpc_val->me['struct']); $arr = array(); - while (list($key,$value) = each($xmlrpc_val->me['struct'])) + foreach ($xmlrpc_val->me['struct'] as $key => &$value) { $arr[$key] = $this->xmlrpc_decoder($value); } + return $arr; } } @@ -1562,17 +1563,17 @@ class XML_RPC_Message extends CI_Xmlrpc if ( ! empty($array)) { - while (list($key) = each($array)) + foreach ($array as $key => &$value) { - if (is_array($array[$key])) + if (is_array($value)) { - $array[$key] = $this->output_parameters($array[$key]); + $array[$key] = $this->output_parameters($value); } elseif ($key !== 'bits' && $this->xss_clean) { // 'bits' is for the MetaWeblog API image bits // @todo - this needs to be made more general purpose - $array[$key] = $CI->security->xss_clean($array[$key]); + $array[$key] = $CI->security->xss_clean($value); } } @@ -1632,7 +1633,7 @@ class XML_RPC_Message extends CI_Xmlrpc reset($param->me['struct']); $arr = array(); - while (list($key,$value) = each($param->me['struct'])) + foreach ($param->me['struct'] as $key => &$value) { $arr[$key] = $this->decode_message($value); } @@ -1823,7 +1824,7 @@ class XML_RPC_Values extends CI_Xmlrpc // struct $rs .= "<struct>\n"; reset($val); - while (list($key2, $val2) = each($val)) + foreach ($val as $key2 => &$val2) { $rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n"; } @@ -1884,11 +1885,9 @@ class XML_RPC_Values extends CI_Xmlrpc */ public function serializeval($o) { - $ar = $o->me; - reset($ar); - - list($typ, $val) = each($ar); - return "<value>\n".$this->serializedata($typ, $val)."</value>\n"; + $array = $o->me; + list($value, $type) = array(reset($array), key($array)); + return "<value>\n".$this->serializedata($type, $value)."</value>\n"; } // -------------------------------------------------------------------- @@ -1900,8 +1899,7 @@ class XML_RPC_Values extends CI_Xmlrpc */ public function scalarval() { - reset($this->me); - return current($this->me); + return reset($this->me); } // -------------------------------------------------------------------- diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php index 21de937c8..0274f13b6 100644 --- a/system/libraries/Xmlrpcs.php +++ b/system/libraries/Xmlrpcs.php @@ -584,7 +584,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc { return $this->multicall_error('nomethod'); } - list($scalar_type, $scalar_value) = each($methName->me); + list($scalar_value, $scalar_type) = array(reset($methName->me), key($methName->me)); $scalar_type = $scalar_type === $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type; if ($methName->kindOf() !== 'scalar' OR $scalar_type !== 'string') @@ -604,7 +604,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc { return $this->multicall_error('notarray'); } - list($a, $b) = each($params->me); + list($b, $a) = array(reset($params->me), key($params->me)); $msg = new XML_RPC_Message($scalar_value); for ($i = 0, $numParams = count($b); $i < $numParams; $i++) diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php index 46f6c145d..2c71e1fbe 100644 --- a/system/libraries/Zip.php +++ b/system/libraries/Zip.php @@ -106,11 +106,11 @@ class CI_Zip { public $compression_level = 2; /** - * mbstring.func_override flag + * mbstring.func_overload flag * * @var bool */ - protected static $func_override; + protected static $func_overload; /** * Initialize zip compression class @@ -119,7 +119,7 @@ class CI_Zip { */ public function __construct() { - isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); + isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); $this->now = time(); log_message('info', 'Zip Compression Class Initialized'); @@ -500,7 +500,7 @@ class CI_Zip { */ protected static function strlen($str) { - return (self::$func_override) + return (self::$func_overload) ? mb_strlen($str, '8bit') : strlen($str); } @@ -517,7 +517,7 @@ class CI_Zip { */ protected static function substr($str, $start, $length = NULL) { - if (self::$func_override) + if (self::$func_overload) { // mb_substr($str, $start, null, '8bit') returns an empty // string on PHP 5.3 diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php index c1c4997c4..8c5bb3021 100644 --- a/tests/codeigniter/core/Loader_test.php +++ b/tests/codeigniter/core/Loader_test.php @@ -99,7 +99,7 @@ class Loader_test extends CI_TestCase { // Test reloading unset($this->ci_obj->$name); $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - $this->assertObjectNotHasAttribute($name, $this->ci_obj); + $this->assertObjectHasAttribute($name, $this->ci_obj); // Create baseless library $name = 'ext_baseless_lib'; @@ -295,8 +295,10 @@ class Loader_test extends CI_TestCase { $output->expects($this->once())->method('append_output')->with($content.$value); $this->ci_instance_var('output', $output); - // Test view output - $this->assertInstanceOf('CI_Loader', $this->load->view($view, array($var => $value))); + // Test view output and $vars as an object + $vars = new stdClass(); + $vars->$var = $value; + $this->assertInstanceOf('CI_Loader', $this->load->view($view, $vars)); } // -------------------------------------------------------------------- diff --git a/tests/codeigniter/database/query_builder/count_test.php b/tests/codeigniter/database/query_builder/count_test.php index 90ac5283e..da312d866 100644 --- a/tests/codeigniter/database/query_builder/count_test.php +++ b/tests/codeigniter/database/query_builder/count_test.php @@ -35,4 +35,14 @@ class Count_test extends CI_TestCase { $this->assertEquals(2, $this->db->like('name', 'ian')->count_all_results('job')); } + // ------------------------------------------------------------------------ + + /** + * @see ./mocks/schema/skeleton.php + */ + public function test_count_all_results_limit() + { + $this->assertEquals(1, $this->db->like('name', 'ian')->limit(1)->count_all_results('job')); + } + }
\ No newline at end of file diff --git a/tests/codeigniter/helpers/date_helper_test.php b/tests/codeigniter/helpers/date_helper_test.php index 8a3502280..b419418bf 100644 --- a/tests/codeigniter/helpers/date_helper_test.php +++ b/tests/codeigniter/helpers/date_helper_test.php @@ -296,7 +296,7 @@ class Date_helper_test extends CI_TestCase { } $this->assertArrayHasKey('UP3', timezones()); - $this->assertEquals(0, timezones('non_existant')); + $this->assertEquals(0, timezones('non_existent')); } // ------------------------------------------------------------------------ diff --git a/tests/codeigniter/helpers/html_helper_test.php b/tests/codeigniter/helpers/html_helper_test.php index d66ad895c..3cf1016ec 100644 --- a/tests/codeigniter/helpers/html_helper_test.php +++ b/tests/codeigniter/helpers/html_helper_test.php @@ -40,6 +40,20 @@ class Html_helper_test extends CI_TestCase { // ------------------------------------------------------------------------ + public function test_img() + { + $this->ci_set_config('base_url', 'http://localhost/'); + $this->assertEquals('<img src="http://localhost/test" alt="" />', img("test")); + $this->assertEquals('<img src="data:foo/bar,baz" alt="" />', img("data:foo/bar,baz")); + $this->assertEquals('<img src="http://localhost/data://foo" alt="" />', img("data://foo")); + $this->assertEquals('<img src="//foo.bar/baz" alt="" />', img("//foo.bar/baz")); + $this->assertEquals('<img src="http://foo.bar/baz" alt="" />', img("http://foo.bar/baz")); + $this->assertEquals('<img src="https://foo.bar/baz" alt="" />', img("https://foo.bar/baz")); + $this->assertEquals('<img src="ftp://foo.bar/baz" alt="" />', img("ftp://foo.bar/baz")); + } + + // ------------------------------------------------------------------------ + public function test_Ul() { $expect = <<<EOH @@ -89,4 +103,4 @@ EOH; } -}
\ No newline at end of file +} diff --git a/tests/codeigniter/libraries/Encryption_test.php b/tests/codeigniter/libraries/Encryption_test.php index 96e52ada8..99c5d4b9d 100644 --- a/tests/codeigniter/libraries/Encryption_test.php +++ b/tests/codeigniter/libraries/Encryption_test.php @@ -94,10 +94,22 @@ class Encryption_test extends CI_TestCase { } // Test default length, it must match the digest size - $this->assertEquals(64, strlen($this->encryption->hkdf('foobar', 'sha512'))); + $hkdf_result = $this->encryption->hkdf('foobar', 'sha512'); + $this->assertEquals( + 64, + defined('MB_OVERLOAD_STRING') + ? mb_strlen($hkdf_result, '8bit') + : strlen($hkdf_result) + ); // Test maximum length (RFC5869 says that it must be up to 255 times the digest size) - $this->assertEquals(12240, strlen($this->encryption->hkdf('foobar', 'sha384', NULL, 48 * 255))); + $hkdf_result = $this->encryption->hkdf('foobar', 'sha384', NULL, 48 * 255); + $this->assertEquals( + 12240, + defined('MB_OVERLOAD_STRING') + ? mb_strlen($hkdf_result, '8bit') + : strlen($hkdf_result) + ); $this->assertFalse($this->encryption->hkdf('foobar', 'sha224', NULL, 28 * 255 + 1)); // CI-specific test for an invalid digest diff --git a/tests/codeigniter/libraries/Form_validation_test.php b/tests/codeigniter/libraries/Form_validation_test.php index 0815300e6..c9c404b43 100644 --- a/tests/codeigniter/libraries/Form_validation_test.php +++ b/tests/codeigniter/libraries/Form_validation_test.php @@ -270,7 +270,7 @@ class Form_validation_test extends CI_TestCase { public function test_rule_valid_email() { $this->assertTrue($this->form_validation->valid_email('email@sample.com')); - + $this->assertFalse($this->form_validation->valid_email('email@sample.com foo bar')); $this->assertFalse($this->form_validation->valid_email('valid_email', '@sample.com')); } diff --git a/tests/mocks/ci_testconfig.php b/tests/mocks/ci_testconfig.php index f80adc5d4..afdb71001 100644 --- a/tests/mocks/ci_testconfig.php +++ b/tests/mocks/ci_testconfig.php @@ -1,20 +1,20 @@ <?php -class CI_TestConfig { +class CI_TestConfig extends CI_Config { public $config = array(); public $_config_paths = array(APPPATH); public $loaded = array(); - public function item($key) + public function item($key, $index = '') { return isset($this->config[$key]) ? $this->config[$key] : FALSE; } - public function load($file, $arg2 = FALSE, $arg3 = FALSE) + public function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) { $this->loaded[] = $file; return TRUE; } -}
\ No newline at end of file +} diff --git a/tests/phpunit.xml b/tests/phpunit.xml index 96c3af9bb..875198c4e 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -17,10 +17,8 @@ </testsuite> </testsuites> <filter> - <blacklist> - <directory suffix=".php">PEAR_INSTALL_DIR</directory> - <directory suffix=".php">PHP_LIBDIR</directory> - <directory suffix=".php">../vendor</directory> - </blacklist> + <whitelist> + <directory suffix=".php">../system/</directory> + </whitelist> </filter> -</phpunit>
\ No newline at end of file +</phpunit> diff --git a/user_guide_src/README.rst b/user_guide_src/README.rst index d645adb73..b31db7cf8 100644 --- a/user_guide_src/README.rst +++ b/user_guide_src/README.rst @@ -13,17 +13,19 @@ output it to various formats. Pages are written in human-readable Prerequisites ============= -Sphinx requires Python, which is already installed if you are running OS X. +Sphinx requires Python 2.7. If you are on OS X, then you already have Python. You can confirm in a Terminal window by executing the ``python`` command without any parameters. It should load up and tell you which version you have -installed. If you're not on 2.7+, go ahead and install 2.7.2 from -http://python.org/download/releases/2.7.2/ +installed. + +Note: If you're not on Python 2.7, then you must upgrade. E.g. Install 2.7.2 +from http://python.org/download/releases/2.7.2/ Installation ============ 1. Install `easy_install <http://peak.telecommunity.com/DevCenter/EasyInstall#installing-easy-install>`_ -2. ``easy_install "sphinx==1.2.3"`` +2. ``easy_install "sphinx==1.6.3"`` 3. ``easy_install "sphinxcontrib-phpdomain==0.1.3.post1"`` 4. Install the CI Lexer which allows PHP, HTML, CSS, and JavaScript syntax highlighting in code examples (see *cilexer/README*) 5. ``cd user_guide_src`` diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index cccef1cda..e5387cc5a 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -2,6 +2,95 @@ Change Log ########## +Version 3.1.6 +============= + +Release Date: Sep 25, 2017 + +- **Security** + + - Fixed a potential object injection in :doc:`Cache Library <libraries/caching>` 'apc' driver when ``save()`` is used with ``$raw = TRUE`` (thanks to Tomas Bortoli). + +- General Changes + + - Deprecated :doc:`Cache Library Library <libraries/caching>` driver 'apc'. + - Updated the :doc:`Session Library <libraries/sessions>` 'redis', 'memcached' drivers to reduce the potential of a locking race conditions. + + +Bug fixes for 3.1.6 +------------------- + +- Fixed a bug (#5164) - :doc:`Loader Library <libraries/loader>` method ``library()`` ignored requests to load libraries previously assigned to super-object properties named differently than the library name. +- Fixed a bug (#5168) - :doc:`Query Builder <database/query_builder>` method ``count_all_results()`` produced erroneous queries on Microsoft SQL Server when ``ORDER BY`` clauses are cached. +- Fixed a bug (#5128) - :doc:`Profiler <general/profiling>` didn't wrap ``$_SESSION`` and configuration arrays in ``<pre>`` tags. +- Fixed a bug (#5183) - :doc:`Database Library <database/index>` method ``is_write_type()`` didn't return TRUE for ``MERGE`` statements. +- Fixed a bug where :doc:`Image Manipulation Library <libraries/image_lib>` didn't escape image source paths passed to NetPBM as shell arguments. +- Fixed a bug (#5236) - :doc:`Query Builder <database/query_builder>` methods ``limit()``, ``offset()`` break SQL Server 2005, 2008 queries with ``"<tablename>".*`` in the ``SELECT`` clause. +- Fixed a bug (#5243) - :doc:`Database Library <database/index>` method ``version()`` didn't work with the 'pdo/dblib' driver. +- Fixed a bug (#5246) - :doc:`Database transactions <database/transactions>` status wasn't reset unless ``trans_complete()`` was called. +- Fixed a bug (#5260) - :doc:`Database Utilities <database/utilities>` method ``backup()`` generated incorrect ``INSERT`` statements with the 'mysqli' driver. +- Fixed a bug where :doc:`Database Results <database/results>` method ``field_data()`` didn't parse field types with the 'mysqli' driver. + +Version 3.1.5 +============= + +Release Date: Jun 19, 2017 + +- **Security** + + - :doc:`Form Validation Library <libraries/form_validation>` rule ``valid_email`` could be bypassed if ``idn_to_ascii()`` is available. + +- General Changes + + - Updated :doc:`Form Helper <helpers/form_helper>` function :php:func:`form_label()` to accept HTML attributes as a string. + +Bug fixes for 3.1.5 +------------------- + +- Fixed a bug (#5070) - :doc:`Email Library <libraries/email>` didn't properly detect 7-bit encoding. +- Fixed a bug (#5084) - :doc:`XML-RPC Library <libraries/xmlrpc>` errored because of a variable name typo. +- Fixed a bug (#5108) - :doc:`Inflector Helper <helpers/inflector_helper>` function :php:func:`singular()` didn't properly handle 'quizzes'. +- Fixed a regression (#5131) - private controller methods triggered PHP errors instead of a 404 response. +- Fixed a bug (#5150) - :doc:`Database Forge <database/forge>` method ``modify_column()`` triggered an error while renaming columns with the 'oci8', 'pdo/oci' drivers. +- Fixed a bug (#5155) - :doc:`Query Builder <database/query_builder>` method ``count_all_results()`` returned incorrect result for queries using ``LIMIT``, ``OFFSET``. + +Version 3.1.4 +============= + +Release Date: Mar 20, 2017 + +- **Security** + + - Fixed a header injection vulnerability in :doc:`common function <general/common_functions>` :php:func:`set_status_header()` under Apache (thanks to Guillermo Caminer from `Flowgate <https://flowgate.net/>`_). + - Fixed byte-safety issues in :doc:`Encrypt Library <libraries/encrypt>` (DEPRECATED) when ``mbstring.func_overload`` is enabled. + - Fixed byte-safety issues in :doc:`Encryption Library <libraries/encryption>` when ``mbstring.func_overload`` is enabled. + - Fixed byte-safety issues in :doc:`compatibility functions <general/compatibility_functions>` ``password_hash()``, ``hash_pbkdf2()`` when ``mbstring.func_overload`` is enabled. + - Updated :doc:`Encrypt Library <libraries/encrypt>` (DEPRECATED) to call ``mcrypt_create_iv()`` with ``MCRYPT_DEV_URANDOM``. + +- General Changes + + - Updated the :doc:`Image Manipulation Library <libraries/image_lib>` to work-around an issue with some JPEGs when using GD. + +Bug fixes for 3.1.4 +------------------- + +- Fixed a regression (#4975) - :doc:`Loader Library <libraries/loader>` couldn't handle objects passed as view variables. +- Fixed a bug (#4977) - :doc:`Loader Library <libraries/loader>` method ``helper()`` could accept any character as a filename extension separator. +- Fixed a regression where the :doc:`Session Library <libraries/sessions>` would fail on a ``session_regenerate_id(TRUE)`` call with the 'database' driver. +- Fixed a bug (#4987) - :doc:`Query Builder <database/query_builder>` caching didn't keep track of table aliases. +- Fixed a bug where :doc:`Text Helper <helpers/text_helper>` function ``ascii_to_entities()`` wasn't byte-safe when ``mbstring.func_overload`` is enabled. +- Fixed a bug where ``CI_Log``, ``CI_Output``, ``CI_Email`` and ``CI_Zip`` didn't handle strings in a byte-safe manner when ``mbstring.func_overload`` is enabled. +- Fixed a bug where :doc:`Session Library <libraries/sessions>` didn't read session data in a byte-safe manner when ``mbstring.func_overload`` is enabled. +- Fixed a bug (#4990) - :doc:`Profiler <general/profiling>` didn't close ``<pre>`` tags it generated. +- Fixed a bug (#4990) - :doc:`Profiler <general/profiling>` didn't HTML-escape quotes for ``$_SESSION`` variables. +- Fixed a bug where :doc:`Input Library <libraries/input>` method ``set_cookie()`` didn't allow its *httponly* and *secure* parameters to be overriden to ``FALSE``. +- Fixed a bug (#5006) - :doc:`common function <general/common_functions>` :php:func:`get_mimes()` didn't load *application/config/mimes.php* if an environment specific config exists. +- Fixed a bug (#5006) - :doc:`common function <general/common_functions>` :php:func:`remove_invisible_characters()` didn't remove URL-encoded ``0x7F``. +- Fixed a bug (#4815) - :doc:`Database Library <database/index>` stripped URL-encoded sequences while escaping strings with the 'mssql' driver. +- Fixed a bug (#5044) - :doc:`HTML Helper <helpers/html_helper>` function :php:func:`img()` didn't accept ``data:`` URI schemes for the image source. +- Fixed a bug (#5050) - :doc:`Database Library <database/index>` tried to access an undefined property in a number of error handling cases. +- Fixed a bug (#5057) - :doc:`Database <database/index>` driver 'postgre' didn't actually apply extra options (such as 'connect_timeout') to its DSN. + Version 3.1.3 ============= @@ -65,7 +154,7 @@ Bug fixes for 3.1.2 - Fixed a regression (#4874) - :doc:`Session Library <libraries/sessions>` didn't take into account ``session.hash_bits_per_character`` when validating session IDs. - Fixed a bug (#4871) - :doc:`Query Builder <database/query_builder>` method ``update_batch()`` didn't properly handle identifier escaping. - Fixed a bug (#4884) - :doc:`Query Builder <database/query_builder>` didn't properly parse field names ending in 'is' when used inside WHERE and HAVING statements. -- Fixed a bug where ``CI_Log``, ``CI_Output``, ``CI_Email`` and ``CI_Zip`` didn't handle strings in a byte-safe manner when ``mbstring.func_override`` is enabled. +- Fixed a bug where ``CI_Log``, ``CI_Output``, ``CI_Email`` and ``CI_Zip`` didn't handle strings in a byte-safe manner when ``mbstring.func_overload`` is enabled. Version 3.1.1 ============= @@ -102,7 +191,7 @@ Bug fixes for 3.1.1 - Fixed a bug where :doc:`Query Builder <database/query_builder>` method ``insert_batch()`` tried to execute an unsupported SQL query with the 'ibase' and 'pdo/firebird' drivers. - Fixed a bug (#4809) - :doc:`Database <database/index>` driver 'pdo/mysql' didn't turn off ``AUTOCOMMIT`` when starting a transaction. - Fixed a bug (#4822) - :doc:`CAPTCHA Helper <helpers/captcha_helper>` didn't clear expired PNG images. -- Fixed a bug (#4823) - :doc:`Session Library <libraries/sessions>` 'files' driver could enter an infinite loop if ``mbstring.func_override`` is enabled. +- Fixed a bug (#4823) - :doc:`Session Library <libraries/sessions>` 'files' driver could enter an infinite loop if ``mbstring.func_overload`` is enabled. - Fixed a bug (#4851) - :doc:`Database Forge <database/forge>` didn't quote schema names passed to its ``create_database()`` method. - Fixed a bug (#4863) - :doc:`HTML Table Library <libraries/table>` method ``set_caption()`` was missing method chaining support. - Fixed a bug (#4843) - :doc:`XML-RPC Library <libraries/xmlrpc>` client class didn't set a read/write socket timeout. diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py index e86f085cf..7929f8ae7 100644 --- a/user_guide_src/source/conf.py +++ b/user_guide_src/source/conf.py @@ -48,9 +48,9 @@ copyright = u'2014 - 2017, British Columbia Institute of Technology' # built documents. # # The short X.Y version. -version = '3.1.3' +version = '3.1.6' # The full version, including alpha/beta/rc tags. -release = '3.1.3' +release = '3.1.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/user_guide_src/source/database/queries.rst b/user_guide_src/source/database/queries.rst index d4ffd16cf..710ababb0 100644 --- a/user_guide_src/source/database/queries.rst +++ b/user_guide_src/source/database/queries.rst @@ -66,7 +66,7 @@ the following:: If for any reason you would like to change the prefix programatically without needing to create a new connection, you can use this method:: - $this->db->set_dbprefix('newprefix'); + $this->db->set_dbprefix('newprefix_'); $this->db->dbprefix('tablename'); // outputs newprefix_tablename @@ -165,7 +165,7 @@ Handling Errors **$this->db->error();** -If you need to get the last error that has occured, the error() method +If you need to get the last error that has occurred, the error() method will return an array containing its code and message. Here's a quick example:: diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst index 3135f76da..1b79c893a 100644 --- a/user_guide_src/source/database/query_builder.rst +++ b/user_guide_src/source/database/query_builder.rst @@ -119,7 +119,7 @@ escaping of fields may break them. :: - $this->db->select('(SELECT SUM(payments.amount) FROM payments WHERE payments.invoice_id=4') AS amount_paid', FALSE); + $this->db->select('(SELECT SUM(payments.amount) FROM payments WHERE payments.invoice_id=4) AS amount_paid', FALSE); $query = $this->db->get('mytable'); **$this->db->select_max()** diff --git a/user_guide_src/source/database/transactions.rst b/user_guide_src/source/database/transactions.rst index e25b8ed14..cfd6a566d 100644 --- a/user_guide_src/source/database/transactions.rst +++ b/user_guide_src/source/database/transactions.rst @@ -87,7 +87,7 @@ If you would like to disable transactions you can do so using $this->db->query('AN SQL QUERY...'); $this->db->trans_complete(); -When transactions are disabled, your queries will be auto-commited, just as +When transactions are disabled, your queries will be auto-committed, just as they are when running queries without transactions, practically ignoring any calls to ``trans_start()``, ``trans_complete()``, etc. diff --git a/user_guide_src/source/general/ancillary_classes.rst b/user_guide_src/source/general/ancillary_classes.rst index f1285d931..4d6528aae 100644 --- a/user_guide_src/source/general/ancillary_classes.rst +++ b/user_guide_src/source/general/ancillary_classes.rst @@ -19,7 +19,7 @@ access CodeIgniter's native resources** simply by using the ``get_instance()`` function. This function returns the main CodeIgniter object. -Normally, to call any of the available CodeIgniter methods requires +Normally, to call any of the available methods, CodeIgniter requires you to use the ``$this`` construct:: $this->load->helper('url'); diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index 6d6744cf7..3e3e42264 100644 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -101,7 +101,7 @@ loading any libraries or helpers. .. php:function:: set_status_header($code[, $text = '']) - :param int $code: HTTP Reponse status code + :param int $code: HTTP Response status code :param string $text: A custom message to set with the status code :rtype: void diff --git a/user_guide_src/source/general/routing.rst b/user_guide_src/source/general/routing.rst index b53a85d31..909289d8d 100644 --- a/user_guide_src/source/general/routing.rst +++ b/user_guide_src/source/general/routing.rst @@ -205,6 +205,3 @@ underscores in the controller and method URI segments, thus saving you additional route entries if you need to do that. This is required, because the dash isn't a valid class or method name character and would cause a fatal error if you try to use it. - -.. important:: The reserved routes must come before any wildcard or - regular expression routes.
\ No newline at end of file diff --git a/user_guide_src/source/general/urls.rst b/user_guide_src/source/general/urls.rst index ca44e2f4c..e23554907 100644 --- a/user_guide_src/source/general/urls.rst +++ b/user_guide_src/source/general/urls.rst @@ -42,10 +42,10 @@ By default, the **index.php** file will be included in your URLs:: If your Apache server has *mod_rewrite* enabled, you can easily remove this file by using a .htaccess file with some simple rules. Here is an example of such a file, using the "negative" method in which everything is redirected -except the specified items: - -:: +except the specified items:: +.. code-block:: console + RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d diff --git a/user_guide_src/source/helpers/cookie_helper.rst b/user_guide_src/source/helpers/cookie_helper.rst index c9d2f419c..2ad51e78c 100644 --- a/user_guide_src/source/helpers/cookie_helper.rst +++ b/user_guide_src/source/helpers/cookie_helper.rst @@ -25,7 +25,7 @@ Available Functions The following functions are available: -.. php:function:: set_cookie($name[, $value = ''[, $expire = ''[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = FALSE[, $httponly = FALSE]]]]]]]) +.. php:function:: set_cookie($name[, $value = ''[, $expire = ''[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = NULL[, $httponly = NULL]]]]]]]) :param mixed $name: Cookie name *or* associative array of all of the parameters available to this function :param string $value: Cookie value diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst index 600a07574..6bc6c2b05 100644 --- a/user_guide_src/source/helpers/date_helper.rst +++ b/user_guide_src/source/helpers/date_helper.rst @@ -31,7 +31,7 @@ The following functions are available: :rtype: int Returns the current time as a UNIX timestamp, referenced either to your server's - local time or any PHP suported timezone, based on the "time reference" setting + local time or any PHP supported timezone, based on the "time reference" setting in your config file. If you do not intend to set your master time reference to any other PHP supported timezone (which you'll typically do if you run a site that lets each user set their own timezone settings) there is no benefit to using diff --git a/user_guide_src/source/helpers/form_helper.rst b/user_guide_src/source/helpers/form_helper.rst index bc30a0e98..8da5d22b5 100644 --- a/user_guide_src/source/helpers/form_helper.rst +++ b/user_guide_src/source/helpers/form_helper.rst @@ -486,7 +486,7 @@ The following functions are available: :param string $label_text: Text to put in the <label> tag :param string $id: ID of the form element that we're making a label for - :param string $attributes: HTML attributes + :param mixed $attributes: HTML attributes :returns: An HTML field label tag :rtype: string diff --git a/user_guide_src/source/helpers/string_helper.rst b/user_guide_src/source/helpers/string_helper.rst index 53052557e..a1fd7ee15 100644 --- a/user_guide_src/source/helpers/string_helper.rst +++ b/user_guide_src/source/helpers/string_helper.rst @@ -186,7 +186,7 @@ The following functions are available: :returns: Reduced string :rtype: string - Reduces multiple instances of a particular character occuring directly + Reduces multiple instances of a particular character occurring directly after each other. Example:: $string = "Fred, Bill,, Joe, Jimmy"; diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst index 652314b60..76335bb67 100644 --- a/user_guide_src/source/installation/downloads.rst +++ b/user_guide_src/source/installation/downloads.rst @@ -2,7 +2,10 @@ Downloading CodeIgniter ####################### -- `CodeIgniter v3.1.3 (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.3>`_ +- `CodeIgniter v3.1.6 (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.6>`_ +- `CodeIgniter v3.1.5 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.5>`_ +- `CodeIgniter v3.1.4 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.4>`_ +- `CodeIgniter v3.1.3 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.3>`_ - `CodeIgniter v3.1.2 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.2>`_ - `CodeIgniter v3.1.1 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.1>`_ - `CodeIgniter v3.1.0 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.0>`_ diff --git a/user_guide_src/source/installation/upgrade_300.rst b/user_guide_src/source/installation/upgrade_300.rst index 0fc211f89..5b2d3947d 100644 --- a/user_guide_src/source/installation/upgrade_300.rst +++ b/user_guide_src/source/installation/upgrade_300.rst @@ -111,7 +111,7 @@ that you should make: - Set your ``$config['sess_driver']`` value - It will default to 'files', unles you've previously used + It will default to 'files', unless you've previously used ``$config['sess_use_database']``, in which case it will be set to 'database'. diff --git a/user_guide_src/source/installation/upgrade_313.rst b/user_guide_src/source/installation/upgrade_313.rst index 76dd159e6..13af775a1 100644 --- a/user_guide_src/source/installation/upgrade_313.rst +++ b/user_guide_src/source/installation/upgrade_313.rst @@ -35,7 +35,7 @@ Step 3: Remove usage of $config['standardize_newlines'] ======================================================= The :doc:`Input Library <../libraries/input>` would optionally replace -occurences of `\r\n`, `\r`, `\n` in input data with whatever the ``PHP_EOL`` +occurrences of `\r\n`, `\r`, `\n` in input data with whatever the ``PHP_EOL`` value is on your system - if you've set ``$config['standardize_newlines']`` to ``TRUE`` in your *application/config/config.php*. diff --git a/user_guide_src/source/installation/upgrade_314.rst b/user_guide_src/source/installation/upgrade_314.rst new file mode 100644 index 000000000..3f2da6564 --- /dev/null +++ b/user_guide_src/source/installation/upgrade_314.rst @@ -0,0 +1,14 @@ +############################# +Upgrading from 3.1.3 to 3.1.4 +############################# + +Before performing an update you should take your site offline by +replacing the index.php file with a static one. + +Step 1: Update your CodeIgniter files +===================================== + +Replace all files and directories in your *system/* directory. + +.. note:: If you have any custom developed files in these directories, + please make copies of them first. diff --git a/user_guide_src/source/installation/upgrade_315.rst b/user_guide_src/source/installation/upgrade_315.rst new file mode 100644 index 000000000..cf673abbb --- /dev/null +++ b/user_guide_src/source/installation/upgrade_315.rst @@ -0,0 +1,14 @@ +############################# +Upgrading from 3.1.4 to 3.1.5 +############################# + +Before performing an update you should take your site offline by +replacing the index.php file with a static one. + +Step 1: Update your CodeIgniter files +===================================== + +Replace all files and directories in your *system/* directory. + +.. note:: If you have any custom developed files in these directories, + please make copies of them first. diff --git a/user_guide_src/source/installation/upgrade_316.rst b/user_guide_src/source/installation/upgrade_316.rst new file mode 100644 index 000000000..1d86b5720 --- /dev/null +++ b/user_guide_src/source/installation/upgrade_316.rst @@ -0,0 +1,28 @@ +############################# +Upgrading from 3.1.5 to 3.1.6 +############################# + +Before performing an update you should take your site offline by +replacing the index.php file with a static one. + +Step 1: Update your CodeIgniter files +===================================== + +Replace all files and directories in your *system/* directory. + +.. note:: If you have any custom developed files in these directories, + please make copies of them first. + +Step 2: Remove usage of the APC Cache driver (deprecation) +========================================================== + +The :doc:`Cache Library <../libraries/caching>` APC driver is now +deprecated, as the APC extension is effectively dead, as explained in its +`PHP Manual page <https://secure.php.net/manual/en/intro.apc.php>`_. + +If your application happens to be using it, you can switch to another +cache driver, as APC support will be removed in a future CodeIgniter +version. + +.. note:: The driver is still available, but you're strongly encouraged + to remove its usage sooner rather than later. diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index bc96e209f..991d5cf4c 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -8,6 +8,9 @@ upgrading from. .. toctree:: :titlesonly: + Upgrading from 3.1.5 to 3.1.6 <upgrade_316> + Upgrading from 3.1.4 to 3.1.5 <upgrade_315> + Upgrading from 3.1.3 to 3.1.4 <upgrade_314> Upgrading from 3.1.2 to 3.1.3 <upgrade_313> Upgrading from 3.1.1 to 3.1.2 <upgrade_312> Upgrading from 3.1.0 to 3.1.1 <upgrade_311> diff --git a/user_guide_src/source/libraries/config.rst b/user_guide_src/source/libraries/config.rst index a45cacdf5..fe2e0a99d 100644 --- a/user_guide_src/source/libraries/config.rst +++ b/user_guide_src/source/libraries/config.rst @@ -211,7 +211,7 @@ Class Reference .. php:method:: load([$file = ''[, $use_sections = FALSE[, $fail_gracefully = FALSE]]]) :param string $file: Configuration file name - :param bool $use_sections: Whether config values shoud be loaded into their own section (index of the main config array) + :param bool $use_sections: Whether config values should be loaded into their own section (index of the main config array) :param bool $fail_gracefully: Whether to return FALSE or to display an error message :returns: TRUE on success, FALSE on failure :rtype: bool diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 0b38737f1..1be6e2adb 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -348,7 +348,7 @@ Class Reference $this->email->attach('http://example.com/filename.pdf'); - If you'd like to use a custom file name, you can use the third paramater:: + If you'd like to use a custom file name, you can use the third parameter:: $this->email->attach('filename.pdf', 'attachment', 'report.pdf'); @@ -387,7 +387,7 @@ Class Reference :rtype: string Returns a string containing any server messages, the email headers, and - the email messsage. Useful for debugging. + the email message. Useful for debugging. You can optionally specify which parts of the message should be printed. Valid options are: **headers**, **subject**, **body**. diff --git a/user_guide_src/source/libraries/encryption.rst b/user_guide_src/source/libraries/encryption.rst index 377e650a9..b16511d4d 100644 --- a/user_guide_src/source/libraries/encryption.rst +++ b/user_guide_src/source/libraries/encryption.rst @@ -382,7 +382,7 @@ the hood: #. Check if the string is long enough, separate the HMAC out of it and validate if it is correct (this is done in a way that - prevents timing attacks agains it). Return FALSE if either of + prevents timing attacks against it). Return FALSE if either of the checks fails. #. Base64-decode the string. diff --git a/user_guide_src/source/libraries/ftp.rst b/user_guide_src/source/libraries/ftp.rst index ddd4442fd..2a015256d 100644 --- a/user_guide_src/source/libraries/ftp.rst +++ b/user_guide_src/source/libraries/ftp.rst @@ -2,7 +2,7 @@ FTP Class ######### -CodeIgniter's FTP Class permits files to be transfered to a remote +CodeIgniter's FTP Class permits files to be transferred to a remote server. Remote files can also be moved, renamed, and deleted. The FTP class also includes a "mirroring" function that permits an entire local directory to be recreated remotely via FTP. diff --git a/user_guide_src/source/libraries/input.rst b/user_guide_src/source/libraries/input.rst index d9c6c2dd1..300f47112 100644 --- a/user_guide_src/source/libraries/input.rst +++ b/user_guide_src/source/libraries/input.rst @@ -167,7 +167,7 @@ Class Reference $this->input->post(array('field1', 'field2')); - Same rule applied here, to retrive the parameters with XSS filtering enabled, set the + Same rule applied here, to retrieve the parameters with XSS filtering enabled, set the second parameter to boolean TRUE. :: @@ -200,7 +200,7 @@ Class Reference $this->input->get(array('field1', 'field2')); - Same rule applied here, to retrive the parameters with XSS filtering enabled, set the + Same rule applied here, to retrieve the parameters with XSS filtering enabled, set the second parameter to boolean TRUE. :: @@ -245,7 +245,7 @@ Class Reference data:: $this->input->cookie('some_cookie'); - $this->input->cookie('some_cookie, TRUE); // with XSS filter + $this->input->cookie('some_cookie', TRUE); // with XSS filter To return an array of multiple cookie values, pass all the required keys as an array. @@ -285,7 +285,7 @@ Class Reference This method is identical to ``get()``, ``post()`` and ``cookie()``, only it fetches the *php://input* stream data. - .. php:method:: set_cookie($name = ''[, $value = ''[, $expire = ''[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = FALSE[, $httponly = FALSE]]]]]]]) + .. php:method:: set_cookie($name = ''[, $value = ''[, $expire = ''[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = NULL[, $httponly = NULL]]]]]]]) :param mixed $name: Cookie name or an array of parameters :param string $value: Cookie value @@ -338,8 +338,8 @@ Class Reference The prefix is only needed if you need to avoid name collisions with other identically named cookies for your server. - The secure boolean is only needed if you want to make it a secure cookie - by setting it to TRUE. + The *httponly* and *secure* flags, when omitted, will default to your + ``$config['cookie_httponly']`` and ``$config['cookie_secure']`` settings. **Discrete Parameters** diff --git a/user_guide_src/source/libraries/loader.rst b/user_guide_src/source/libraries/loader.rst index 228d5e478..22abb4586 100644 --- a/user_guide_src/source/libraries/loader.rst +++ b/user_guide_src/source/libraries/loader.rst @@ -125,7 +125,7 @@ Class Reference $config = array ( 'mailtype' => 'html', - 'charset' => 'utf-8, + 'charset' => 'utf-8', 'priority' => '1' ); diff --git a/user_guide_src/source/libraries/pagination.rst b/user_guide_src/source/libraries/pagination.rst index 913717c67..99b5a80a2 100644 --- a/user_guide_src/source/libraries/pagination.rst +++ b/user_guide_src/source/libraries/pagination.rst @@ -101,7 +101,7 @@ like:: If you have ``$config['enable_query_strings']`` set to TRUE your links will automatically be re-written using Query Strings. This option can -also be explictly set. Using ``$config['page_query_string']`` set to TRUE, +also be explicitly set. Using ``$config['page_query_string']`` set to TRUE, the pagination link will become:: http://example.com/index.php?c=test&m=page&per_page=20 diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index f7604ef00..868112684 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -40,6 +40,9 @@ browser may attempt to execute. // file failed the XSS test } +.. important:: If you want to filter HTML attribute values, use + :php:func:`html_escape()` instead! + ********************************* Cross-site request forgery (CSRF) ********************************* @@ -101,7 +104,11 @@ Class Reference :rtype: mixed Tries to remove XSS exploits from the input data and returns the cleaned string. - If the optional second parameter is set to true, it will return boolean TRUE if the image is safe to use and FALSE if malicious data was detected in it. + If the optional second parameter is set to true, it will return boolean TRUE if + the image is safe to use and FALSE if malicious data was detected in it. + + .. important:: This method is not suitable for filtering HTML attribute values! + Use :php:func:`html_escape()` for that instead. .. php:method:: sanitize_filename($str[, $relative_path = FALSE]) @@ -162,4 +169,4 @@ Class Reference Used for generating CSRF and XSS tokens. .. note:: The output is NOT guaranteed to be cryptographically secure, - just the best attempt at that.
\ No newline at end of file + just the best attempt at that. diff --git a/user_guide_src/source/libraries/sessions.rst b/user_guide_src/source/libraries/sessions.rst index a95cd5a19..b1f658d8f 100644 --- a/user_guide_src/source/libraries/sessions.rst +++ b/user_guide_src/source/libraries/sessions.rst @@ -471,7 +471,7 @@ Preference Default Description .. note:: The 'cookie_httponly' setting doesn't have an effect on sessions. Instead the HttpOnly parameter is always enabled, for security - reasons. Additionaly, the 'cookie_prefix' setting is completely + reasons. Additionally, the 'cookie_prefix' setting is completely ignored. Session Drivers diff --git a/user_guide_src/source/libraries/trackback.rst b/user_guide_src/source/libraries/trackback.rst index bceb515f2..dc4477e9f 100644 --- a/user_guide_src/source/libraries/trackback.rst +++ b/user_guide_src/source/libraries/trackback.rst @@ -262,7 +262,7 @@ Class Reference :returns: Data value or empty string if not found :rtype: string - Returns a single item from the reponse data array. + Returns a single item from the response data array. .. php:method:: process($url, $data) diff --git a/user_guide_src/source/libraries/typography.rst b/user_guide_src/source/libraries/typography.rst index 1d1e4f3c4..9e1386835 100644 --- a/user_guide_src/source/libraries/typography.rst +++ b/user_guide_src/source/libraries/typography.rst @@ -44,7 +44,7 @@ Class Reference $this->load->library('typography'); $this->typography->protect_braced_quotes = TRUE; - .. method auto_typography($str[, $reduce_linebreaks = FALSE]) + .. php:method:: auto_typography($str[, $reduce_linebreaks = FALSE]) :param string $str: Input string :param bool $reduce_linebreaks: Whether to reduce consequitive linebreaks @@ -104,4 +104,4 @@ Class Reference Usage example:: - $string = $this->typography->nl2br_except_pre($string);
\ No newline at end of file + $string = $this->typography->nl2br_except_pre($string); |