From 1fb6958272b569c9f111f04375b90662726a92b8 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Tue, 10 Jan 2017 15:03:14 +0200 Subject: Disallow Travis failures for PHP 7.1 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ba2d6b31d..6b90a5f64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,6 @@ matrix: allow_failures: - php: 5.3 - php: hhvm - - php: 7.1 exclude: - php: hhvm env: DB=pgsql -- cgit v1.2.3-24-g4f1b From 37226c036a52ae857b13109774b1cdfc4b1d4db9 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 11 Jan 2017 12:05:32 +0200 Subject: [ci skip] Fix an error with DB sessions triggered with regenerate + destroy --- system/libraries/Session/drivers/Session_database_driver.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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) { -- cgit v1.2.3-24-g4f1b From 99d05f0aaffa1750b74b1be4d3654bec95323517 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 11 Jan 2017 17:04:06 +0200 Subject: [ci skip] Merge pull request #4977 from fabiospampinato/fabiospampinato-loader-helper-regex-fix Fixed regex used for loading helpers --- system/core/Loader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/core/Loader.php b/system/core/Loader.php index acfc739dd..5ed6adb48 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -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])) -- cgit v1.2.3-24-g4f1b From 167c295813c9e5dc6c412bad8c9375dae89005ce Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 11 Jan 2017 17:07:02 +0200 Subject: [ci skip] Add changelog entry for #4977 --- user_guide_src/source/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 64ebd61a1..ab94d6760 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -15,6 +15,7 @@ Bug fixes for 3.1.4 ------------------- - Fixed a regression (#4975) - :doc:`Loader Library ` couldn't handle objects passed as view variables. +- Fixed a bug (#4977) - :doc:`Loader Library ` method ``helper()`` could accept any character as a filename extension separator. Version 3.1.3 ============= -- cgit v1.2.3-24-g4f1b From f44c93f7a3b35b84fe47a70d8b3fd786d0536845 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 11 Jan 2017 21:47:21 +0200 Subject: [ci skip] Add a changelog entry for 37226c036a52ae857b13109774b1cdfc4b1d4db9 --- user_guide_src/source/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index ab94d6760..b2d00345f 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -16,6 +16,7 @@ Bug fixes for 3.1.4 - Fixed a regression (#4975) - :doc:`Loader Library ` couldn't handle objects passed as view variables. - Fixed a bug (#4977) - :doc:`Loader Library ` method ``helper()`` could accept any character as a filename extension separator. +- Fixed a regression where the :doc:`Session Library ` would fail on a ``session_regenerate_id(TRUE)`` call with the 'database' driver. Version 3.1.3 ============= -- cgit v1.2.3-24-g4f1b From 33cc3e10b24811aa3658d46cf8679207b166950b Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 16 Jan 2017 16:01:58 +0200 Subject: Address #4980 --- system/database/DB_query_builder.php | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index ab19d97a2..56d2c0c1e 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -2485,26 +2485,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); } // -------------------------------------------------------------------- -- cgit v1.2.3-24-g4f1b From 71d8f72ffc48a7f46747b3b6b1a554533cc1cbc5 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Tue, 17 Jan 2017 12:01:00 +0200 Subject: [ci skip] Merge pull request #4986 from ka7/feature/spelling Spelling fixes in comment blocks and docs --- system/core/Common.php | 2 +- system/core/Security.php | 2 +- system/database/DB_driver.php | 2 +- system/database/DB_query_builder.php | 4 ++-- system/database/drivers/cubrid/cubrid_driver.php | 4 ++-- system/database/drivers/ibase/ibase_driver.php | 2 +- system/database/drivers/mssql/mssql_driver.php | 2 +- system/database/drivers/mysql/mysql_driver.php | 4 ++-- system/database/drivers/mysqli/mysqli_driver.php | 2 +- system/database/drivers/oci8/oci8_driver.php | 2 +- system/database/drivers/odbc/odbc_driver.php | 4 ++-- system/database/drivers/pdo/pdo_driver.php | 4 ++-- system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php | 2 +- system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php | 2 +- system/database/drivers/postgre/postgre_driver.php | 4 ++-- system/database/drivers/postgre/postgre_forge.php | 2 +- system/database/drivers/sqlite3/sqlite3_driver.php | 4 ++-- system/database/drivers/sqlsrv/sqlsrv_driver.php | 2 +- system/libraries/Cache/drivers/Cache_memcached.php | 2 +- system/libraries/Ftp.php | 2 +- system/libraries/Pagination.php | 2 +- system/libraries/Typography.php | 2 +- system/libraries/Xmlrpc.php | 2 +- tests/codeigniter/helpers/date_helper_test.php | 2 +- user_guide_src/source/database/queries.rst | 2 +- user_guide_src/source/database/transactions.rst | 2 +- user_guide_src/source/general/common_functions.rst | 2 +- user_guide_src/source/helpers/date_helper.rst | 2 +- user_guide_src/source/helpers/string_helper.rst | 2 +- user_guide_src/source/installation/upgrade_300.rst | 2 +- user_guide_src/source/installation/upgrade_313.rst | 2 +- user_guide_src/source/libraries/config.rst | 2 +- user_guide_src/source/libraries/email.rst | 4 ++-- user_guide_src/source/libraries/encryption.rst | 2 +- user_guide_src/source/libraries/ftp.rst | 2 +- user_guide_src/source/libraries/input.rst | 4 ++-- user_guide_src/source/libraries/pagination.rst | 2 +- user_guide_src/source/libraries/sessions.rst | 2 +- user_guide_src/source/libraries/trackback.rst | 2 +- 39 files changed, 48 insertions(+), 48 deletions(-) diff --git a/system/core/Common.php b/system/core/Common.php index 7b3eb6a4e..0c6e2272e 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -827,7 +827,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/Security.php b/system/core/Security.php index 585ed90ec..bacbb78d0 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -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/database/DB_driver.php b/system/database/DB_driver.php index 19afdd492..e52eb5c06 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -1173,7 +1173,7 @@ abstract class CI_DB_driver { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 56d2c0c1e..6b0e03274 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -2441,7 +2441,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 +2477,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. * 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..fea3bfe52 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 */ diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index f0cfb2ff9..f76d127b9 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 */ 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..567e0da49 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -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/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/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php index 9f5a86fa0..ed44412c1 100644 --- a/system/database/drivers/odbc/odbc_driver.php +++ b/system/database/drivers/odbc/odbc_driver.php @@ -309,7 +309,7 @@ class CI_DB_odbc_driver extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string @@ -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_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php index f4a2f08f3..5a492d881 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php @@ -161,7 +161,7 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * Platform-dependant string escape + * Platform-dependent string escape * * @param string * @return string 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/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php index cef464af4..718fee7f5 100644 --- a/system/database/drivers/postgre/postgre_driver.php +++ b/system/database/drivers/postgre/postgre_driver.php @@ -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..e4f403180 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 */ 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/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/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/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 '#

<('.$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/Xmlrpc.php b/system/libraries/Xmlrpc.php index f043e0f90..fc5abe5c4 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 */ 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/user_guide_src/source/database/queries.rst b/user_guide_src/source/database/queries.rst index d4ffd16cf..f626f1e83 100644 --- a/user_guide_src/source/database/queries.rst +++ b/user_guide_src/source/database/queries.rst @@ -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/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/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/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/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/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/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..01099a955 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. :: 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/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) -- cgit v1.2.3-24-g4f1b From 437ffe035f6715d97983908d6a761ae0a23767f1 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Tue, 17 Jan 2017 12:44:19 +0200 Subject: Merge pull request #4987 from tianhe1986/develop_qb_alias_table_cache Add aliased tables cache in query_builder. --- system/database/DB_query_builder.php | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 6b0e03274..0abf2a260 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -214,6 +214,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 * @@ -2281,9 +2288,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'; + } } } } @@ -2626,7 +2638,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; @@ -2677,13 +2690,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); - } } // -------------------------------------------------------------------- -- cgit v1.2.3-24-g4f1b From 2649e6e3f3d2a44fd09a25e6f8f70848a75dbed5 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Tue, 17 Jan 2017 12:47:50 +0200 Subject: [ci skip] Add changelog entry for #4987 --- user_guide_src/source/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index b2d00345f..2769990f8 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -17,6 +17,7 @@ Bug fixes for 3.1.4 - Fixed a regression (#4975) - :doc:`Loader Library ` couldn't handle objects passed as view variables. - Fixed a bug (#4977) - :doc:`Loader Library ` method ``helper()`` could accept any character as a filename extension separator. - Fixed a regression where the :doc:`Session Library ` would fail on a ``session_regenerate_id(TRUE)`` call with the 'database' driver. +- Fixed a bug (#4987) - :doc:`Query Builder ` caching didn't keep track of table aliases. Version 3.1.3 ============= -- cgit v1.2.3-24-g4f1b From f565212c5aa07a8016394a3bc66874be83c73d4d Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 19 Jan 2017 15:17:00 +0200 Subject: Fix byte-safety issues & actually test for them --- .gitignore | 2 + .travis.yml | 3 +- composer.json | 5 ++- system/helpers/text_helper.php | 7 ++- system/libraries/Encrypt.php | 59 +++++++++++++++++++++---- system/libraries/Encryption.php | 10 ++--- tests/codeigniter/libraries/Encryption_test.php | 16 ++++++- tests/phpunit.xml | 10 ++--- user_guide_src/source/changelog.rst | 11 ++++- 9 files changed, 93 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 5982f9bad..eb45390e9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ application/logs/* !application/logs/index.html !application/logs/.htaccess +composer.lock + user_guide_src/build/* user_guide_src/cilexer/build/* user_guide_src/cilexer/dist/* diff --git a/.travis.yml b/.travis.yml index 6b90a5f64..2a0be4ddc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,11 +26,10 @@ 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: phpunit -d zend.enable_gc=0 -d date.timezone=UTF -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 exclude: - php: hhvm diff --git a/composer.json b/composer.json index 64d1be155..0a898d2c1 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "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/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/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/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/phpunit.xml b/tests/phpunit.xml index 96c3af9bb..875198c4e 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -17,10 +17,8 @@ - - PEAR_INSTALL_DIR - PHP_LIBDIR - ../vendor - + + ../system/ + - \ No newline at end of file + diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 2769990f8..17069ca32 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -7,6 +7,12 @@ Version 3.1.4 Release Date: Not Released +- **Security** + + - Updated :doc:`Encrypt Library ` (DEPRECATED) to call ``mcrypt_create_iv()`` with ``MCRYPT_DEV_URANDOM``. + - Fixed byte-safety issues in :doc:`Encrypt Library ` (DEPRECATED) when ``mbstring.func_overload`` is enabled. + - Fixed byte-safety issues in :doc:`Encryption Library ` when ``mbstring.func_overload`` is enabled. + - General Changes - Updated the :doc:`Image Manipulation Library ` to work-around an issue with some JPEGs when using GD. @@ -18,6 +24,7 @@ Bug fixes for 3.1.4 - Fixed a bug (#4977) - :doc:`Loader Library ` method ``helper()`` could accept any character as a filename extension separator. - Fixed a regression where the :doc:`Session Library ` would fail on a ``session_regenerate_id(TRUE)`` call with the 'database' driver. - Fixed a bug (#4987) - :doc:`Query Builder ` caching didn't keep track of table aliases. +- Fixed a bug where :doc:`Text Helper ` function ``ascii_to_entities()`` wasn't byte-safe when ``mbstring.func_overload`` is enabled. Version 3.1.3 ============= @@ -82,7 +89,7 @@ Bug fixes for 3.1.2 - Fixed a regression (#4874) - :doc:`Session Library ` didn't take into account ``session.hash_bits_per_character`` when validating session IDs. - Fixed a bug (#4871) - :doc:`Query Builder ` method ``update_batch()`` didn't properly handle identifier escaping. - Fixed a bug (#4884) - :doc:`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 ============= @@ -119,7 +126,7 @@ Bug fixes for 3.1.1 - Fixed a bug where :doc:`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 ` driver 'pdo/mysql' didn't turn off ``AUTOCOMMIT`` when starting a transaction. - Fixed a bug (#4822) - :doc:`CAPTCHA Helper ` didn't clear expired PNG images. -- Fixed a bug (#4823) - :doc:`Session Library ` 'files' driver could enter an infinite loop if ``mbstring.func_override`` is enabled. +- Fixed a bug (#4823) - :doc:`Session Library ` 'files' driver could enter an infinite loop if ``mbstring.func_overload`` is enabled. - Fixed a bug (#4851) - :doc:`Database Forge ` didn't quote schema names passed to its ``create_database()`` method. - Fixed a bug (#4863) - :doc:`HTML Table Library ` method ``set_caption()`` was missing method chaining support. - Fixed a bug (#4843) - :doc:`XML-RPC Library ` client class didn't set a read/write socket timeout. -- cgit v1.2.3-24-g4f1b From c0c74d5201c171cd6d0cdc2133e63077ebe1a407 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 19 Jan 2017 15:26:35 +0200 Subject: More byte-safety --- system/core/Log.php | 10 +++++----- system/core/Output.php | 10 +++++----- system/core/compat/password.php | 8 ++++---- system/libraries/Email.php | 10 +++++----- system/libraries/Session/drivers/Session_files_driver.php | 8 ++++---- system/libraries/Zip.php | 10 +++++----- user_guide_src/source/changelog.rst | 3 +++ 7 files changed, 31 insertions(+), 28 deletions(-) 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..6ddded22a 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(); @@ -817,7 +817,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 +834,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/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/libraries/Email.php b/system/libraries/Email.php index 117c4845f..955787d28 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'); } @@ -2442,7 +2442,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 +2459,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/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/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/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 17069ca32..7d1302b3a 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -12,6 +12,7 @@ Release Date: Not Released - Updated :doc:`Encrypt Library ` (DEPRECATED) to call ``mcrypt_create_iv()`` with ``MCRYPT_DEV_URANDOM``. - Fixed byte-safety issues in :doc:`Encrypt Library ` (DEPRECATED) when ``mbstring.func_overload`` is enabled. - Fixed byte-safety issues in :doc:`Encryption Library ` when ``mbstring.func_overload`` is enabled. + - Fixed byte-safety issues in :doc:`compatibility function ` ``password_hash()`` when ``mbstring.func_overload`` is enabled. - General Changes @@ -25,6 +26,8 @@ Bug fixes for 3.1.4 - Fixed a regression where the :doc:`Session Library ` would fail on a ``session_regenerate_id(TRUE)`` call with the 'database' driver. - Fixed a bug (#4987) - :doc:`Query Builder ` caching didn't keep track of table aliases. - Fixed a bug where :doc:`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 ` didn't read session data in a byte-safe manner when ``mbstring.func_overload`` is enabled. Version 3.1.3 ============= -- cgit v1.2.3-24-g4f1b From ea7c00863474b70c19c12592cdd1c9fb8f783a98 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 19 Jan 2017 15:29:23 +0200 Subject: Fix Travis tests script line --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2a0be4ddc..cfdad6479 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ 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=UTF -d mbstring.func_overload=7 -d mbstring.internal_encoding=UTF-8 vendor/bin/phpunit --coverage-text --configuration tests/travis/$DB.phpunit.xml +script: php -d zend.enable_gc=0 -d date.timezone=UTF -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: -- cgit v1.2.3-24-g4f1b From edbe791919dd1a526915828575ba18791c3fe764 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 19 Jan 2017 15:35:51 +0200 Subject: Again the Travis script line ... a typo --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cfdad6479..71ebec3da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ 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: php -d zend.enable_gc=0 -d date.timezone=UTF -d mbstring.func_overload=7 -d mbstring.internal_encoding=UTF-8 vendor/bin/phpunit --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: -- cgit v1.2.3-24-g4f1b From 25461d8eac80c0f1242150f7316ec58ac14c5d39 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 19 Jan 2017 15:42:43 +0200 Subject: hash_pbkdf2() byte-safety --- system/core/compat/hash.php | 17 +++++++++++++---- user_guide_src/source/changelog.rst | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/system/core/compat/hash.php b/system/core/compat/hash.php index ba0198e10..7eb292188 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)) + : 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) + : substr($hash, 0, $length); } } diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 7d1302b3a..ce82f071c 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -12,7 +12,7 @@ Release Date: Not Released - Updated :doc:`Encrypt Library ` (DEPRECATED) to call ``mcrypt_create_iv()`` with ``MCRYPT_DEV_URANDOM``. - Fixed byte-safety issues in :doc:`Encrypt Library ` (DEPRECATED) when ``mbstring.func_overload`` is enabled. - Fixed byte-safety issues in :doc:`Encryption Library ` when ``mbstring.func_overload`` is enabled. - - Fixed byte-safety issues in :doc:`compatibility function ` ``password_hash()`` when ``mbstring.func_overload`` is enabled. + - Fixed byte-safety issues in :doc:`compatibility functions ` ``password_hash()``, ``hash_pbkdf2()`` when ``mbstring.func_overload`` is enabled. - General Changes -- cgit v1.2.3-24-g4f1b From 93141a13e77a88be044e4c7f51ba3c2a35bf0ccc Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 19 Jan 2017 15:46:32 +0200 Subject: hash_pbkdf2() byte-safety again ... actually tell mbstring to use 8bit --- system/core/compat/hash.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/core/compat/hash.php b/system/core/compat/hash.php index 7eb292188..c65203aaf 100644 --- a/system/core/compat/hash.php +++ b/system/core/compat/hash.php @@ -174,7 +174,7 @@ if ( ! function_exists('hash_pbkdf2')) } $hash_length = defined('MB_OVERLOAD_STRING') - ? mb_strlen(hash($algo, NULL, TRUE)) + ? mb_strlen(hash($algo, NULL, TRUE), '8bit') : strlen(hash($algo, NULL, TRUE)); empty($length) && $length = $hash_length; @@ -248,7 +248,7 @@ if ( ! function_exists('hash_pbkdf2')) } return defined('MB_OVERLOAD_STRING') - ? mb_substr($hash, 0, $length) + ? mb_substr($hash, 0, $length, '8bit') : substr($hash, 0, $length); } } -- cgit v1.2.3-24-g4f1b From 4316a157c27a3721dbfd8a817bf8cbffb1fe371f Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Fri, 20 Jan 2017 15:46:17 +0200 Subject: Don't use each() Will be deprecated in PHP 7.2 --- system/core/Security.php | 4 ++-- system/libraries/Xmlrpc.php | 36 +++++++++++++++++------------------- system/libraries/Xmlrpcs.php | 4 ++-- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/system/core/Security.php b/system/core/Security.php index bacbb78d0..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; diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index fc5abe5c4..c766a89c8 100644 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -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 .= "\n"; reset($val); - while (list($key2, $val2) = each($val)) + foreach ($val as $key2 => &$val2) { $rs .= "\n{$key2}\n".$this->serializeval($val2)."\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 "\n".$this->serializedata($typ, $val)."\n"; + $array = $o->me; + list($value, $type) = array(reset($ar), key($array)); + return "\n".$this->serializedata($type, $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++) -- cgit v1.2.3-24-g4f1b From 56f59bdd609b58f3f3826d41b6286882cb26665b Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 23 Jan 2017 11:39:57 +0200 Subject: Merge pull request #4991 from verkhoumov/develop Removed dead code from show_error() --- system/core/Common.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/system/core/Common.php b/system/core/Common.php index 0c6e2272e..8437f7926 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -410,11 +410,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 -- cgit v1.2.3-24-g4f1b From cd8d52807854657cca365e40f6191c6ef2817341 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 23 Jan 2017 11:42:47 +0200 Subject: Merge pull request #4990 from tianhe1986/develop_profiler Two small changes with CI_Profiler --- system/libraries/Profiler.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php index e9e03cfe0..9ea09a529 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)) - ? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))
+					? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')).'
' : htmlspecialchars($val, ENT_QUOTES, config_item('charset')); $output .= '$_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)) - ? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))
+					? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')).'
' : htmlspecialchars($val, ENT_QUOTES, config_item('charset')); $output .= '$_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)) - ? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))
+					? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset')).'
' : htmlspecialchars($val, ENT_QUOTES, config_item('charset')); $output .= '$_FILES[' @@ -490,7 +490,7 @@ class CI_Profiler { } $output .= '' - .$config.'  '.htmlspecialchars($val)."\n"; + .$config.'  '.htmlspecialchars($val, ENT_QUOTES, config_item('charset'))."\n"; } return $output."\n"; @@ -522,7 +522,7 @@ class CI_Profiler { } $output .= '' - .$key.'  '.htmlspecialchars($val)."\n"; + .$key.'  '.htmlspecialchars($val, ENT_QUOTES, config_item('charset'))."\n"; } return $output."\n"; -- cgit v1.2.3-24-g4f1b From dba035db1cee163e6c3d9de9903125ed239386d7 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 23 Jan 2017 12:01:32 +0200 Subject: [ci skip] Add changelog entries for PR #4990 --- user_guide_src/source/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index ce82f071c..b1dadb14b 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -28,6 +28,8 @@ Bug fixes for 3.1.4 - Fixed a bug where :doc:`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 ` didn't read session data in a byte-safe manner when ``mbstring.func_overload`` is enabled. +- Fixed a bug (#4990) - :doc:`Profiler ` didn't close ``
`` tags it generated.
+-  Fixed a bug (#4990) - :doc:`Profiler ` didn't HTML-escape quotes for ``$_SESSION`` variables.
 
 Version 3.1.3
 =============
-- 
cgit v1.2.3-24-g4f1b


From b1780fc79e1b24ecc51b5448642a84d4022cbadc Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 30 Jan 2017 15:35:07 +0200
Subject: [ci skip] Fix #5002

---
 user_guide_src/source/libraries/typography.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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);
-- 
cgit v1.2.3-24-g4f1b


From 422b8890e8b41a9ecf6644bff169c8c82fa2c82d Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Wed, 1 Feb 2017 14:36:49 +0200
Subject: Fix a CI_Input::set_cookie() bug

Found on StackOverflow: https://stackoverflow.com/questions/41925028/codeigniter-config-overrides-set-cookie-parameters
---
 system/core/Input.php                           | 16 +++++++---------
 system/helpers/cookie_helper.php                |  2 +-
 user_guide_src/source/changelog.rst             |  1 +
 user_guide_src/source/helpers/cookie_helper.rst |  2 +-
 user_guide_src/source/libraries/input.rst       |  6 +++---
 5 files changed, 13 insertions(+), 14 deletions(-)

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/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/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index b1dadb14b..28a862126 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -30,6 +30,7 @@ Bug fixes for 3.1.4
 -  Fixed a bug where :doc:`Session Library ` didn't read session data in a byte-safe manner when ``mbstring.func_overload`` is enabled.
 -  Fixed a bug (#4990) - :doc:`Profiler ` didn't close ``
`` tags it generated.
 -  Fixed a bug (#4990) - :doc:`Profiler ` didn't HTML-escape quotes for ``$_SESSION`` variables.
+-  Fixed a bug where :doc:`Input Library ` method ``set_cookie()`` didn't allow its *httponly* and *secure* parameters to be overriden to ``FALSE``.
 
 Version 3.1.3
 =============
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/libraries/input.rst b/user_guide_src/source/libraries/input.rst
index 01099a955..e7107fa06 100644
--- a/user_guide_src/source/libraries/input.rst
+++ b/user_guide_src/source/libraries/input.rst
@@ -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**
 
-- 
cgit v1.2.3-24-g4f1b


From d60e51ba3bc542ead57d9d7b3b5f11e5c26a72e4 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 6 Feb 2017 10:28:36 +0200
Subject: Merge pull request #5006 from tianhe1986/develop_common

Fix two bugs with Common Functions
---
 system/core/Common.php | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/system/core/Common.php b/system/core/Common.php
index 8437f7926..8b74db0a3 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -319,17 +319,16 @@ if ( ! function_exists('get_mimes'))
 
 		if (empty($_mimes))
 		{
-			if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
-			{
-				$_mimes = include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
-			}
-			elseif (file_exists(APPPATH.'config/mimes.php'))
+			$_mimes = array();
+
+			if (file_exists(APPPATH.'config/mimes.php'))
 			{
-				$_mimes = include(APPPATH.'config/mimes.php');
+				$_mimes = array_merge($_mimes, include(APPPATH.'config/mimes.php'));
 			}
-			else
+
+			if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
 			{
-				$_mimes = array();
+				$_mimes = array_merge($_mimes, include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'));
 			}
 		}
 
@@ -719,6 +718,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
-- 
cgit v1.2.3-24-g4f1b


From 8057d79e54e9f7f577089eecdc2c33be801d3e3f Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 6 Feb 2017 10:34:33 +0200
Subject: [ci skip] Eliminate a needless array_merge() call from PR #5006 patch

---
 system/core/Common.php | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/system/core/Common.php b/system/core/Common.php
index 8b74db0a3..f7bd42600 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -319,12 +319,9 @@ if ( ! function_exists('get_mimes'))
 
 		if (empty($_mimes))
 		{
-			$_mimes = array();
-
-			if (file_exists(APPPATH.'config/mimes.php'))
-			{
-				$_mimes = array_merge($_mimes, include(APPPATH.'config/mimes.php'));
-			}
+			$_mimes = file_exists(APPPATH.'config/mimes.php')
+				? include(APPPATH.'config/mimes.php')
+				: array();
 
 			if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
 			{
-- 
cgit v1.2.3-24-g4f1b


From 7173c9641df9b39a5f07d3b57a8c05cabefcfa52 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 6 Feb 2017 10:37:50 +0200
Subject: [ci skip] Add changelog entries for PR #5006

---
 user_guide_src/source/changelog.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 28a862126..ed1f18666 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -31,6 +31,8 @@ Bug fixes for 3.1.4
 -  Fixed a bug (#4990) - :doc:`Profiler ` didn't close ``
`` tags it generated.
 -  Fixed a bug (#4990) - :doc:`Profiler ` didn't HTML-escape quotes for ``$_SESSION`` variables.
 -  Fixed a bug where :doc:`Input Library ` method ``set_cookie()`` didn't allow its *httponly* and *secure* parameters to be overriden to ``FALSE``.
+-  Fixed a bug (#5006) - :doc:`common function ` :php:func:`get_mimes()` didn't load *application/config/mimes.php* if an environment specific config exists.
+-  Fixed a bug (#5006) - :doc:`common function ` :php:func:`remove_invisible_characters()` didn't remove URL-encoded ``0x7F``.
 
 Version 3.1.3
 =============
-- 
cgit v1.2.3-24-g4f1b


From d072d449ffa2912f5d922f23e0bc9cac4712a337 Mon Sep 17 00:00:00 2001
From: Zach Ploskey 
Date: Sat, 11 Feb 2017 01:45:46 -0800
Subject: Increase version in userguide to 3.1.4-dev

The version number was not increased after the 3.1.3 release.
---
 user_guide_src/source/conf.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py
index 5c447b722..2df5f9eb2 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-dev'
+version = '3.1.4-dev'
 # The full version, including alpha/beta/rc tags.
-release = '3.1.3-dev'
+release = '3.1.4-dev'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
-- 
cgit v1.2.3-24-g4f1b


From 56d1a70e8149529058e442f4876e90ff963c533a Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 20 Feb 2017 11:35:24 +0200
Subject: [ci skip] Add a note on xss_clean() and HTML attributes

---
 user_guide_src/source/libraries/security.rst | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst
index f7604ef00..fc5cba19d 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 vales!
+			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.
-- 
cgit v1.2.3-24-g4f1b


From f0093f99762098231f6f707d2f87fdbd02eb3dca Mon Sep 17 00:00:00 2001
From: vlakoff 
Date: Thu, 16 Feb 2017 01:31:59 +0100
Subject: Do not strip substrings looking like URL encode sequences

---
 system/database/DB_driver.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index e52eb5c06..3eb51f734 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -1180,7 +1180,7 @@ abstract class CI_DB_driver {
 	 */
 	protected function _escape_str($str)
 	{
-		return str_replace("'", "''", remove_invisible_characters($str));
+		return str_replace("'", "''", remove_invisible_characters($str, FALSE));
 	}
 
 	// --------------------------------------------------------------------
-- 
cgit v1.2.3-24-g4f1b


From cdf1bfb73f9d7aec0eeb7e3a0299fee25b48d6ef Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 20 Feb 2017 11:50:12 +0200
Subject: [ci skip] Add a changelog entry for #4815, PR #5023

---
 user_guide_src/source/changelog.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index ed1f18666..8283f530c 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -33,6 +33,7 @@ Bug fixes for 3.1.4
 -  Fixed a bug where :doc:`Input Library ` method ``set_cookie()`` didn't allow its *httponly* and *secure* parameters to be overriden to ``FALSE``.
 -  Fixed a bug (#5006) - :doc:`common function ` :php:func:`get_mimes()` didn't load *application/config/mimes.php* if an environment specific config exists.
 -  Fixed a bug (#5006) - :doc:`common function ` :php:func:`remove_invisible_characters()` didn't remove URL-encoded ``0x7F``.
+-  Fixed a bug (#4815) - :doc:`Database Library ` stripped URL-encoded sequences while escaping strings with the 'mssql' driver.
 
 Version 3.1.3
 =============
-- 
cgit v1.2.3-24-g4f1b


From 618870f9f70148944599c1db64babec09e7424bc Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Wed, 1 Mar 2017 14:09:26 +0200
Subject: [ci skip] Remove a misleading comment from the docblock for
 random_string()

---
 system/helpers/string_helper.php | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

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
-- 
cgit v1.2.3-24-g4f1b


From 356bc66ebcd6a4d48c28fd119233e9d0bb12375f Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 6 Mar 2017 14:39:28 +0200
Subject: Fix #5044; add unit tests for img() HTML helper

---
 system/helpers/html_helper.php                 |  2 +-
 tests/codeigniter/helpers/html_helper_test.php | 16 +++++++++++++++-
 tests/mocks/ci_testconfig.php                  |  8 ++++----
 user_guide_src/source/changelog.rst            |  1 +
 4 files changed, 21 insertions(+), 6 deletions(-)

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]+:)?(?ci_set_config('base_url', 'http://localhost/');
+		$this->assertEquals('', img("test"));
+		$this->assertEquals('', img("data:foo/bar,baz"));
+		$this->assertEquals('', img("data://foo"));
+		$this->assertEquals('', img("//foo.bar/baz"));
+		$this->assertEquals('', img("http://foo.bar/baz"));
+		$this->assertEquals('', img("https://foo.bar/baz"));
+		$this->assertEquals('', img("ftp://foo.bar/baz"));
+	}
+
+	// ------------------------------------------------------------------------
+
 	public function test_Ul()
 	{
 		$expect = <<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/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 8283f530c..8d2beb74f 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -34,6 +34,7 @@ Bug fixes for 3.1.4
 -  Fixed a bug (#5006) - :doc:`common function ` :php:func:`get_mimes()` didn't load *application/config/mimes.php* if an environment specific config exists.
 -  Fixed a bug (#5006) - :doc:`common function ` :php:func:`remove_invisible_characters()` didn't remove URL-encoded ``0x7F``.
 -  Fixed a bug (#4815) - :doc:`Database Library ` stripped URL-encoded sequences while escaping strings with the 'mssql' driver.
+-  Fixed a bug (#5044) - :doc:`HTML Helper ` function :php:func:`img()` didn't accept ``data:`` URI schemes for the image source.
 
 Version 3.1.3
 =============
-- 
cgit v1.2.3-24-g4f1b


From e9d68ab58f01e15bb344a015fcce8444ea8cc247 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Wed, 8 Mar 2017 11:56:09 +0200
Subject: [ci skip] Remove an obsolete note from routing docs

---
 user_guide_src/source/general/routing.rst | 3 ---
 1 file changed, 3 deletions(-)

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
-- 
cgit v1.2.3-24-g4f1b


From ea0735264dfebd64858933e03a3b33323b14178e Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Tue, 14 Mar 2017 18:42:12 +0200
Subject: Fix #5050

---
 system/database/drivers/ibase/ibase_driver.php                 | 2 +-
 system/database/drivers/mssql/mssql_driver.php                 | 2 +-
 system/database/drivers/mysqli/mysqli_driver.php               | 2 +-
 system/database/drivers/odbc/odbc_driver.php                   | 4 ++--
 system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php    | 2 +-
 system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php | 2 +-
 system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php    | 2 +-
 system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php     | 2 +-
 system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php   | 2 +-
 system/database/drivers/sqlsrv/sqlsrv_driver.php               | 2 +-
 user_guide_src/source/changelog.rst                            | 1 +
 11 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php
index fea3bfe52..3069d6699 100644
--- a/system/database/drivers/ibase/ibase_driver.php
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -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/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index f76d127b9..a2ccd1c80 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -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/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index 567e0da49..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;
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index ed44412c1..ef982fc63 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -316,7 +316,7 @@ class CI_DB_odbc_driver extends CI_DB_driver {
 	 */
 	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;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
index 3249a1d7f..08243232e 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
@@ -331,7 +331,7 @@ 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;
 	}
 
 }
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_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
index 5a492d881..066dd9614 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
@@ -168,7 +168,7 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {
 	 */
 	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_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
index 1cf6c614d..07c429eec 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
@@ -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/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index e4f403180..a43e2539a 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -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/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 8d2beb74f..fd6c1c790 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -35,6 +35,7 @@ Bug fixes for 3.1.4
 -  Fixed a bug (#5006) - :doc:`common function ` :php:func:`remove_invisible_characters()` didn't remove URL-encoded ``0x7F``.
 -  Fixed a bug (#4815) - :doc:`Database Library ` stripped URL-encoded sequences while escaping strings with the 'mssql' driver.
 -  Fixed a bug (#5044) - :doc:`HTML Helper ` function :php:func:`img()` didn't accept ``data:`` URI schemes for the image source.
+-  Fixed a bug (#5050) - :doc:`Database Library ` tried to access an undefined property in a number of error handling cases.
 
 Version 3.1.3
 =============
-- 
cgit v1.2.3-24-g4f1b


From 62b655b92667f1e417a4f260a34ff447ddeee2c2 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 20 Mar 2017 09:14:14 +0200
Subject: Fix #5057

---
 system/database/drivers/postgre/postgre_driver.php | 4 ++--
 user_guide_src/source/changelog.rst                | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 718fee7f5..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."' ";
 			}
 		}
 
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index fd6c1c790..32f2b81e6 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -36,6 +36,7 @@ Bug fixes for 3.1.4
 -  Fixed a bug (#4815) - :doc:`Database Library ` stripped URL-encoded sequences while escaping strings with the 'mssql' driver.
 -  Fixed a bug (#5044) - :doc:`HTML Helper ` function :php:func:`img()` didn't accept ``data:`` URI schemes for the image source.
 -  Fixed a bug (#5050) - :doc:`Database Library ` tried to access an undefined property in a number of error handling cases.
+-  Fixed a bug (#5057) - :doc:`Database ` driver 'postgre' didn't actually apply extra options (such as 'connect_timeout') to its DSN.
 
 Version 3.1.3
 =============
-- 
cgit v1.2.3-24-g4f1b


From df33ec2e45356895c5aec0a1ebfc325c2af4f74a Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 20 Mar 2017 17:43:58 +0200
Subject: Fix Apache header injection vulnerability in set_status_header()

---
 system/core/Common.php              | 10 +++++-----
 user_guide_src/source/changelog.rst |  3 ++-
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/system/core/Common.php b/system/core/Common.php
index f7bd42600..2fd5c5809 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -562,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);
 	}
 }
 
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 32f2b81e6..d891b786b 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -9,10 +9,11 @@ Release Date: Not Released
 
 -  **Security**
 
-   -  Updated :doc:`Encrypt Library ` (DEPRECATED) to call ``mcrypt_create_iv()`` with ``MCRYPT_DEV_URANDOM``.
+   -  Fixed a header injection vulnerability in :doc:`common function ` :php:func:`set_status_header()` under Apache (thanks to Guillermo Caminer from `Flowgate `_).
    -  Fixed byte-safety issues in :doc:`Encrypt Library ` (DEPRECATED) when ``mbstring.func_overload`` is enabled.
    -  Fixed byte-safety issues in :doc:`Encryption Library ` when ``mbstring.func_overload`` is enabled.
    -  Fixed byte-safety issues in :doc:`compatibility functions ` ``password_hash()``, ``hash_pbkdf2()`` when ``mbstring.func_overload`` is enabled.
+   -  Updated :doc:`Encrypt Library ` (DEPRECATED) to call ``mcrypt_create_iv()`` with ``MCRYPT_DEV_URANDOM``.
 
 -  General Changes
 
-- 
cgit v1.2.3-24-g4f1b


From f58643bab5e5a868aabdaa64668cdb67a9b82fbb Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 20 Mar 2017 17:46:23 +0200
Subject: [ci skip] Prepare 3.1.4 release

---
 system/core/CodeIgniter.php                      | 2 +-
 user_guide_src/source/changelog.rst              | 2 +-
 user_guide_src/source/conf.py                    | 4 ++--
 user_guide_src/source/installation/downloads.rst | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 63e9563a1..880abab57 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.4-dev';
+	const CI_VERSION = '3.1.4';
 
 /*
  * ------------------------------------------------------
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index d891b786b..1369eab96 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -5,7 +5,7 @@ Change Log
 Version 3.1.4
 =============
 
-Release Date: Not Released
+Release Date: March 23, 2017
 
 -  **Security**
 
diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py
index 2df5f9eb2..41eaa609d 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.4-dev'
+version = '3.1.4'
 # The full version, including alpha/beta/rc tags.
-release = '3.1.4-dev'
+release = '3.1.4'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst
index a614e164a..0b0b89707 100644
--- a/user_guide_src/source/installation/downloads.rst
+++ b/user_guide_src/source/installation/downloads.rst
@@ -2,7 +2,7 @@
 Downloading CodeIgniter
 #######################
 
--  `CodeIgniter v3.1.4 (Current version) `_
+-  `CodeIgniter v3.1.4 (Current version) `_
 -  `CodeIgniter v3.1.3 `_
 -  `CodeIgniter v3.1.2 `_
 -  `CodeIgniter v3.1.1 `_
-- 
cgit v1.2.3-24-g4f1b


From f83d10b375bd028480a47ec3c0bbb2b07dcabfee Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 20 Mar 2017 17:55:38 +0200
Subject: [ci skip] Mark the start of 3.1.5-dev

---
 system/core/CodeIgniter.php                        |  2 +-
 user_guide_src/source/changelog.rst                |  6 ++++++
 user_guide_src/source/conf.py                      |  4 ++--
 user_guide_src/source/installation/downloads.rst   |  3 ++-
 user_guide_src/source/installation/upgrade_315.rst | 14 ++++++++++++++
 user_guide_src/source/installation/upgrading.rst   |  1 +
 6 files changed, 26 insertions(+), 4 deletions(-)
 create mode 100644 user_guide_src/source/installation/upgrade_315.rst

diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 880abab57..b5c2bedf4 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.4';
+	const CI_VERSION = '3.1.5-dev';
 
 /*
  * ------------------------------------------------------
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 1369eab96..d7418ffa2 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -2,6 +2,12 @@
 Change Log
 ##########
 
+Version 3.1.5
+=============
+
+Release Date: Not Released
+
+
 Version 3.1.4
 =============
 
diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py
index 41eaa609d..f3d477591 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.4'
+version = '3.1.5-dev'
 # The full version, including alpha/beta/rc tags.
-release = '3.1.4'
+release = '3.1.5-dev'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst
index 0b0b89707..fd4f90753 100644
--- a/user_guide_src/source/installation/downloads.rst
+++ b/user_guide_src/source/installation/downloads.rst
@@ -2,7 +2,8 @@
 Downloading CodeIgniter
 #######################
 
--  `CodeIgniter v3.1.4 (Current version) `_
+-  `CodeIgniter v3.1.5-dev (Current version) `_
+-  `CodeIgniter v3.1.4 `_
 -  `CodeIgniter v3.1.3 `_
 -  `CodeIgniter v3.1.2 `_
 -  `CodeIgniter v3.1.1 `_
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/upgrading.rst b/user_guide_src/source/installation/upgrading.rst
index 8c68fc868..8f30e1a01 100644
--- a/user_guide_src/source/installation/upgrading.rst
+++ b/user_guide_src/source/installation/upgrading.rst
@@ -8,6 +8,7 @@ upgrading from.
 .. toctree::
 	:titlesonly:
 
+	Upgrading from 3.1.4 to 3.1.5 
 	Upgrading from 3.1.3 to 3.1.4 
 	Upgrading from 3.1.2 to 3.1.3 
 	Upgrading from 3.1.1 to 3.1.2 
-- 
cgit v1.2.3-24-g4f1b


From 0eb38af2eaf1127b9b82261b7ec3bf4d4b847318 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 20 Mar 2017 19:38:59 +0200
Subject: [ci skip] Fix 3.1.4 release date ...

Apparently, I'm from the future.
---
 user_guide_src/source/changelog.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index d7418ffa2..209193bb0 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -11,7 +11,7 @@ Release Date: Not Released
 Version 3.1.4
 =============
 
-Release Date: March 23, 2017
+Release Date: March 20, 2017
 
 -  **Security**
 
-- 
cgit v1.2.3-24-g4f1b