diff options
20 files changed, 298 insertions, 109 deletions
diff --git a/system/core/Security.php b/system/core/Security.php index 36dea4cf2..e79bf8aff 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -593,6 +593,22 @@ class CI_Security { return FALSE; } + if (function_exists('random_bytes')) + { + try + { + // The cast is required to avoid TypeError + return random_bytes((int) $length); + } + catch (Exception $e) + { + // If random_bytes() can't do the job, we can't either ... + // There's no point in using fallbacks. + log_message('error', $e->getMessage()); + return FALSE; + } + } + // Unfortunately, none of the following PRNGs is guaranteed to exist ... if (defined('MCRYPT_DEV_URANDOM') && ($output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== FALSE) { diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index 418de27c8..885a814be 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -499,6 +499,18 @@ abstract class CI_DB_driver { // -------------------------------------------------------------------- /** + * Last error + * + * @return array + */ + public function error() + { + return array('code' => NULL, 'message' => NULL); + } + + // -------------------------------------------------------------------- + + /** * Set client character set * * @param string diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index f9cf76a14..1546e40c0 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -780,10 +780,6 @@ abstract class CI_DB_forge { case 'ENUM': case 'SET': $attributes['CONSTRAINT'] = $this->db->escape($attributes['CONSTRAINT']); - $field['length'] = is_array($attributes['CONSTRAINT']) - ? "('".implode("','", $attributes['CONSTRAINT'])."')" - : '('.$attributes['CONSTRAINT'].')'; - break; default: $field['length'] = is_array($attributes['CONSTRAINT']) ? '('.implode(',', $attributes['CONSTRAINT']).')' diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index cf1100d27..7a3d2f594 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -1379,7 +1379,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->from($table); } - $result = ($this->qb_distinct === TRUE) + $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_orderby)) ? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results") : $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows'))); diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 883973ae1..b9e310a3a 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -267,7 +267,7 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _version() { - return 'SELECT @@VERSION AS ver'; + return "SELECT SERVERPROPERTY('ProductVersion') AS ver"; } // -------------------------------------------------------------------- diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php index 916ddeb90..206924d06 100644 --- a/system/database/drivers/oci8/oci8_driver.php +++ b/system/database/drivers/oci8/oci8_driver.php @@ -252,12 +252,16 @@ class CI_DB_oci8_driver extends CI_DB { return $this->data_cache['version']; } - if ( ! $this->conn_id OR ($version = oci_server_version($this->conn_id)) === FALSE) + if ( ! $this->conn_id OR ($version_string = oci_server_version($this->conn_id)) === FALSE) { return FALSE; } + elseif (preg_match('#Release\s(\d+(?:\.\d+)+)#', $version_string, $match)) + { + return $this->data_cache['version'] = $match[1]; + } - return $this->data_cache['version'] = $version; + return FALSE; } // -------------------------------------------------------------------- diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php index d17e311f7..4791ab157 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php @@ -130,6 +130,29 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** + * Database version number + * + * @return string + */ + public function version() + { + if (isset($this->data_cache['version'])) + { + return $this->data_cache['version']; + } + + $version_string = parent::version(); + if (preg_match('#Release\s(?<version>\d+(?:\.\d+)+)#', $version_string, $match)) + { + return $this->data_cache['version'] = $match[1]; + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** * Show table query * * Generates a platform-specific query string so that the table names can be fetched diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php index 85bcfb5a0..03c1dd852 100644 --- a/system/helpers/captcha_helper.php +++ b/system/helpers/captcha_helper.php @@ -171,7 +171,8 @@ if ( ! function_exists('create_captcha')) $byte_index = $word_index = 0; while ($word_index < $word_length) { - if (($rand_index = unpack('C', $bytes[$byte_index++])) > $rand_max) + list(, $rand_index) = unpack('C', $bytes[$byte_index++]); + if ($rand_index > $rand_max) { // Was this the last byte we have? // If so, try to fetch more. diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index fd807769a..37dafd913 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -769,12 +769,11 @@ if ( ! function_exists('set_checkbox')) { return $CI->form_validation->set_checkbox($field, $value, $default); } - elseif (($input = $CI->input->post($field, FALSE)) === NULL) - { - return ($default === TRUE) ? ' checked="checked"' : ''; - } + // Form inputs are always strings ... $value = (string) $value; + $input = $CI->input->post($field, FALSE); + if (is_array($input)) { // Note: in_array('', array(0)) returns TRUE, do not use it @@ -789,7 +788,13 @@ if ( ! function_exists('set_checkbox')) return ''; } - return ($input === $value) ? ' checked="checked"' : ''; + // Unchecked checkbox and radio inputs are not even submitted by browsers ... + if ($CI->input->method() === 'post') + { + return ($input === 'value') ? ' checked="checked"' : ''; + } + + return ($default === TRUE) ? ' checked="checked"' : ''; } } @@ -816,12 +821,32 @@ if ( ! function_exists('set_radio')) { return $CI->form_validation->set_radio($field, $value, $default); } - elseif (($input = $CI->input->post($field, FALSE)) === NULL) + + // Form inputs are always strings ... + $value = (string) $value; + $input = $CI->input->post($field, FALSE); + + if (is_array($input)) + { + // Note: in_array('', array(0)) returns TRUE, do not use it + foreach ($input as &$v) + { + if ($value === $v) + { + return ' checked="checked"'; + } + } + + return ''; + } + + // Unchecked checkbox and radio inputs are not even submitted by browsers ... + if ($CI->input->method() === 'post') { - return ($default === TRUE) ? ' checked="checked"' : ''; + return ($input === 'value') ? ' checked="checked"' : ''; } - return ($input === (string) $value) ? ' checked="checked"' : ''; + return ($default === TRUE) ? ' checked="checked"' : ''; } } diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php index 637835160..3138a04b3 100644 --- a/system/helpers/string_helper.php +++ b/system/helpers/string_helper.php @@ -270,7 +270,7 @@ if ( ! function_exists('alternator')) * @param string (as many parameters as needed) * @return string */ - function alternator($args) + function alternator() { static $i; @@ -279,6 +279,7 @@ if ( ! function_exists('alternator')) $i = 0; return ''; } + $args = func_get_args(); return $args[($i++ % count($args))]; } diff --git a/system/libraries/Email.php b/system/libraries/Email.php index ebff7567a..034586ac9 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -1469,6 +1469,20 @@ class CI_Email { */ protected function _prep_quoted_printable($str) { + // ASCII code numbers for "safe" characters that can always be + // used literally, without encoding, as described in RFC 2049. + // http://www.ietf.org/rfc/rfc2049.txt + static $ascii_safe_chars = array( + // ' ( ) + , - . / : = ? + 39, 40, 41, 43, 44, 45, 46, 47, 58, 61, 63, + // numbers + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + // upper-case letters + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + // lower-case letters + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122 + ); + // We are intentionally wrapping so mail servers will encode characters // properly and MUAs will behave, so {unwrap} must go! $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str); @@ -1516,14 +1530,25 @@ class CI_Email { $ascii = ord($char); // Convert spaces and tabs but only if it's the end of the line - if ($i === ($length - 1) && ($ascii === 32 OR $ascii === 9)) + if ($ascii === 32 OR $ascii === 9) { - $char = $escape.sprintf('%02s', dechex($ascii)); + if ($i === ($length - 1)) + { + $char = $escape.sprintf('%02s', dechex($ascii)); + } } - elseif ($ascii === 61) // encode = signs + // DO NOT move this below the $ascii_safe_chars line! + // + // = (equals) signs are allowed by RFC2049, but must be encoded + // as they are the encoding delimiter! + elseif ($ascii === 61) { $char = $escape.strtoupper(sprintf('%02s', dechex($ascii))); // =3D } + elseif ( ! in_array($ascii, $ascii_safe_chars, TRUE)) + { + $char = $escape.strtoupper(sprintf('%02s', dechex($ascii))); + } // If we're at the character limit, add the line to the output, // reset our temp variable, and keep on chuggin' diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php index f3e039881..151ce8dec 100644 --- a/system/libraries/Encryption.php +++ b/system/libraries/Encryption.php @@ -337,6 +337,11 @@ class CI_Encryption { */ public function create_key($length) { + if (function_exists('random_bytes')) + { + return random_bytes((int) $length); + } + return ($this->_driver === 'mcrypt') ? mcrypt_create_iv($length, MCRYPT_DEV_URANDOM) : openssl_random_pseudo_bytes($length); diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index a158225ee..c2212585d 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -415,12 +415,9 @@ class CI_Form_validation { */ public function run($group = '') { - // Do we even have any data to process? Mm? - $validation_array = empty($this->validation_data) ? $_POST : $this->validation_data; - if (count($validation_array) === 0) - { - return FALSE; - } + $validation_array = empty($this->validation_data) + ? $_POST + : $this->validation_data; // Does the _field_data array containing the validation rules exist? // If not, we look to see if they were assigned via a config file diff --git a/system/libraries/Session/Session_driver.php b/system/libraries/Session/Session_driver.php index 47376da5b..64b4bb511 100644 --- a/system/libraries/Session/Session_driver.php +++ b/system/libraries/Session/Session_driver.php @@ -74,6 +74,18 @@ abstract class CI_Session_driver implements SessionHandlerInterface { */ protected $_session_id; + /** + * Success and failure return values + * + * Necessary due to a bug in all PHP 5 versions where return values + * from userspace handlers are not handled properly. PHP 7 fixes the + * bug, so we need to return different values depending on the version. + * + * @see https://wiki.php.net/rfc/session.user.return-value + * @var mixed + */ + protected $_success, $_failure; + // ------------------------------------------------------------------------ /** @@ -85,6 +97,17 @@ abstract class CI_Session_driver implements SessionHandlerInterface { public function __construct(&$params) { $this->_config =& $params; + + if (is_php('7')) + { + $this->_success = TRUE; + $this->_failure = FALSE; + } + else + { + $this->_success = 0; + $this->_failure = -1; + } } // ------------------------------------------------------------------------ diff --git a/system/libraries/Session/drivers/Session_database_driver.php b/system/libraries/Session/drivers/Session_database_driver.php index 72b39d12d..40a358fb8 100644 --- a/system/libraries/Session/drivers/Session_database_driver.php +++ b/system/libraries/Session/drivers/Session_database_driver.php @@ -125,9 +125,12 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan */ public function open($save_path, $name) { - return empty($this->_db->conn_id) - ? (bool) $this->_db->db_connect() - : TRUE; + if (empty($this->_db->conn_id) && ! $this->_db->db_connect()) + { + return $this->_failure; + } + + return $this->_success; } // ------------------------------------------------------------------------ @@ -201,7 +204,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return FALSE; + return $this->_failure; } $this->_row_exists = FALSE; @@ -209,7 +212,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan } elseif ($this->_lock === FALSE) { - return FALSE; + return $this->_failure; } if ($this->_row_exists === FALSE) @@ -224,10 +227,11 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan if ($this->_db->insert($this->_config['save_path'], $insert_data)) { $this->_fingerprint = md5($session_data); - return $this->_row_exists = TRUE; + $this->_row_exists = TRUE; + return $this->_success; } - return FALSE; + return $this->_failure; } $this->_db->where('id', $session_id); @@ -247,10 +251,10 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan if ($this->_db->update($this->_config['save_path'], $update_data)) { $this->_fingerprint = md5($session_data); - return TRUE; + return $this->_success; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -264,9 +268,9 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan */ public function close() { - return ($this->_lock) - ? $this->_release_lock() - : TRUE; + return ($this->_lock && ! $this->_release_lock()) + ? $this->_failure + : $this->_success; } // ------------------------------------------------------------------------ @@ -289,12 +293,19 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']); } - return $this->_db->delete($this->_config['save_path']) - ? ($this->close() && $this->_cookie_destroy()) - : FALSE; + if ( ! $this->_db->delete($this->_config['save_path'])) + { + return $this->_failure; + } + } + + if ($this->close()) + { + $this->_cookie_destroy(); + return $this->_success; } - return ($this->close() && $this->_cookie_destroy()); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -309,7 +320,9 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan */ public function gc($maxlifetime) { - return $this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime)); + return ($this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime))) + ? $this->_success + : $this->_failure; } // ------------------------------------------------------------------------ @@ -390,4 +403,4 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return parent::_release_lock(); } -} +}
\ No newline at end of file diff --git a/system/libraries/Session/drivers/Session_files_driver.php b/system/libraries/Session/drivers/Session_files_driver.php index 45da91c46..f0f055f87 100644 --- a/system/libraries/Session/drivers/Session_files_driver.php +++ b/system/libraries/Session/drivers/Session_files_driver.php @@ -129,7 +129,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle .$name // we'll use the session cookie name as a prefix to avoid collisions .($this->_config['match_ip'] ? md5($_SERVER['REMOTE_ADDR']) : ''); - return TRUE; + return $this->_success; } // ------------------------------------------------------------------------ @@ -156,13 +156,13 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle if (($this->_file_handle = fopen($this->_file_path.$session_id, 'w+b')) === FALSE) { log_message('error', "Session: File '".$this->_file_path.$session_id."' doesn't exist and cannot be created."); - return FALSE; + return $this->_failure; } } elseif (($this->_file_handle = fopen($this->_file_path.$session_id, 'r+b')) === FALSE) { log_message('error', "Session: Unable to open file '".$this->_file_path.$session_id."'."); - return FALSE; + return $this->_failure; } if (flock($this->_file_handle, LOCK_EX) === FALSE) @@ -170,7 +170,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle log_message('error', "Session: Unable to obtain lock for file '".$this->_file_path.$session_id."'."); fclose($this->_file_handle); $this->_file_handle = NULL; - return FALSE; + return $this->_failure; } // Needed by write() to detect session_regenerate_id() calls @@ -183,6 +183,12 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle return ''; } } + // We shouldn't need this, but apparently we do ... + // See https://github.com/bcit-ci/CodeIgniter/issues/4039 + elseif ($this->_file_handler === FALSE) + { + return $this->_failure; + } else { rewind($this->_file_handle); @@ -220,18 +226,18 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle // and we need to close the old handle and open a new one if ($session_id !== $this->_session_id && ( ! $this->close() OR $this->read($session_id) === FALSE)) { - return FALSE; + return $this->_failure; } if ( ! is_resource($this->_file_handle)) { - return FALSE; + return $this->_failure; } elseif ($this->_fingerprint === md5($session_data)) { - return ($this->_file_new) - ? TRUE - : touch($this->_file_path.$session_id); + return ( ! $this->_file_new && ! touch($this->_file_path.$session_id)) + ? $this->_failure + : $this->_success; } if ( ! $this->_file_new) @@ -254,12 +260,12 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle { $this->_fingerprint = md5(substr($session_data, 0, $written)); log_message('error', 'Session: Unable to write data.'); - return FALSE; + return $this->_failure; } } $this->_fingerprint = md5($session_data); - return TRUE; + return $this->_success; } // ------------------------------------------------------------------------ @@ -279,10 +285,9 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle fclose($this->_file_handle); $this->_file_handle = $this->_file_new = $this->_session_id = NULL; - return TRUE; } - return TRUE; + return $this->_success; } // ------------------------------------------------------------------------ @@ -299,19 +304,31 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle { if ($this->close()) { - return file_exists($this->_file_path.$session_id) - ? (unlink($this->_file_path.$session_id) && $this->_cookie_destroy()) - : TRUE; + if (file_exists($this->_file_path.$session_id)) + { + $this->_cookie_destroy(); + return unlink($this->_file_path.$session_id) + ? $this->_success + : $this->_failure; + } + + return $this->_success; } elseif ($this->_file_path !== NULL) { clearstatcache(); - return file_exists($this->_file_path.$session_id) - ? (unlink($this->_file_path.$session_id) && $this->_cookie_destroy()) - : TRUE; + if (file_exists($this->_file_path.$session_id)) + { + $this->_cookie_destroy(); + return unlink($this->_file_path.$session_id) + ? $this->_success + : $this->_failure; + } + + return $this->_success; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -329,7 +346,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle if ( ! is_dir($this->_config['save_path']) OR ($directory = opendir($this->_config['save_path'])) === FALSE) { log_message('debug', "Session: Garbage collector couldn't list files under directory '".$this->_config['save_path']."'."); - return FALSE; + return $this->_failure; } $ts = time() - $maxlifetime; @@ -356,7 +373,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle closedir($directory); - return TRUE; + return $this->_success; } -} +}
\ No newline at end of file diff --git a/system/libraries/Session/drivers/Session_memcached_driver.php b/system/libraries/Session/drivers/Session_memcached_driver.php index 97b860588..760239dfb 100644 --- a/system/libraries/Session/drivers/Session_memcached_driver.php +++ b/system/libraries/Session/drivers/Session_memcached_driver.php @@ -117,7 +117,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa { $this->_memcached = NULL; log_message('error', 'Session: Invalid Memcached save path format: '.$this->_config['save_path']); - return FALSE; + return $this->_failure; } foreach ($matches as $match) @@ -142,10 +142,10 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if (empty($server_list)) { log_message('error', 'Session: Memcached server pool is empty.'); - return FALSE; + return $this->_failure; } - return TRUE; + return $this->_success; } // ------------------------------------------------------------------------ @@ -170,7 +170,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa return $session_data; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -188,14 +188,14 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa { if ( ! isset($this->_memcached)) { - return FALSE; + return $this->_failure; } // Was the ID regenerated? elseif ($session_id !== $this->_session_id) { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return FALSE; + return $this->_failure; } $this->_fingerprint = md5(''); @@ -210,16 +210,18 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if ($this->_memcached->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration'])) { $this->_fingerprint = $fingerprint; - return TRUE; + return $this->_success; } - return FALSE; + return $this->_failure; } - return $this->_memcached->touch($this->_key_prefix.$session_id, $this->_config['expiration']); + return $this->_memcached->touch($this->_key_prefix.$session_id, $this->_config['expiration']) + ? $this->_success + : $this->_failure; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -238,14 +240,14 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa isset($this->_lock_key) && $this->_memcached->delete($this->_lock_key); if ( ! $this->_memcached->quit()) { - return FALSE; + return $this->_failure; } $this->_memcached = NULL; - return TRUE; + return $this->_success; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -263,10 +265,11 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if (isset($this->_memcached, $this->_lock_key)) { $this->_memcached->delete($this->_key_prefix.$session_id); - return $this->_cookie_destroy(); + $this->_cookie_destroy(); + return $this->_success; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -282,7 +285,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa public function gc($maxlifetime) { // Not necessary, Memcached takes care of that. - return TRUE; + return $this->_success; } // ------------------------------------------------------------------------ @@ -299,7 +302,9 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa { if (isset($this->_lock_key)) { - return $this->_memcached->replace($this->_lock_key, time(), 300); + return ($this->_memcached->replace($this->_lock_key, time(), 300)) + ? $this->_success + : $this->_failure; } // 30 attempts to obtain a lock, in case another request already has it @@ -316,7 +321,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if ( ! $this->_memcached->set($lock_key, time(), 300)) { log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id); - return FALSE; + return $this->_failure; } $this->_lock_key = $lock_key; @@ -327,11 +332,11 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if ($attempt === 30) { log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.'); - return FALSE; + return $this->_failure; } $this->_lock = TRUE; - return TRUE; + return $this->_success; } // ------------------------------------------------------------------------ diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php index 4fa6c28b3..2395df1b5 100644 --- a/system/libraries/Session/drivers/Session_redis_driver.php +++ b/system/libraries/Session/drivers/Session_redis_driver.php @@ -136,7 +136,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { if (empty($this->_config['save_path'])) { - return FALSE; + return $this->_failure; } $redis = new Redis(); @@ -161,7 +161,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle else { $this->_redis = $redis; - return TRUE; + return $this->_success; } } else @@ -169,7 +169,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle log_message('error', 'Session: Unable to connect to Redis with the configured settings.'); } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -194,7 +194,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle return $session_data; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -212,14 +212,14 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { if ( ! isset($this->_redis)) { - return FALSE; + return $this->_failure; } // Was the ID regenerated? elseif ($session_id !== $this->_session_id) { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return FALSE; + return $this->_failure; } $this->_fingerprint = md5(''); @@ -234,16 +234,18 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle if ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration'])) { $this->_fingerprint = $fingerprint; - return TRUE; + return $this->_success; } - return FALSE; + return $this->_failure; } - return $this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration']); + return ($this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration'])) + ? $this->_success + : $this->_failure; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -265,7 +267,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle isset($this->_lock_key) && $this->_redis->delete($this->_lock_key); if ( ! $this->_redis->close()) { - return FALSE; + return $this->_failure; } } } @@ -275,10 +277,10 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle } $this->_redis = NULL; - return TRUE; + return $this->_success; } - return TRUE; + return $this->_success; } // ------------------------------------------------------------------------ @@ -300,10 +302,11 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle log_message('debug', 'Session: Redis::delete() expected to return 1, got '.var_export($result, TRUE).' instead.'); } - return $this->_cookie_destroy(); + $this->_cookie_destroy(); + return $this->_success; } - return FALSE; + return $this->_failure; } // ------------------------------------------------------------------------ @@ -319,7 +322,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle public function gc($maxlifetime) { // Not necessary, Redis takes care of that. - return TRUE; + return $this->_success; } // ------------------------------------------------------------------------ diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 1ea34eee6..6d7474765 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -21,6 +21,28 @@ Version 3.0.4 Release Date: Not Released +- General Changes + + - Updated :doc:`Security Library <libraries/security>` method ``get_random_bytes()`` to use PHP7's ``random_bytes()`` function when possible. + - Updated :doc:`Encryption Library <libraries/security>` method ``create_key()`` to use PHP7's ``random_bytes()`` function when possible. + +Bug fixes for 3.0.4 +------------------- + +- Fixed a bug (#4212) - :doc:`Query Builder <database/query_builder>` method ``count_all_results()`` could fail if an ``ORDER BY`` condition is used. +- Fixed a bug where :doc:`Form Helper <helpers/form_helper>` functions :php:func:`set_checkbox()`, :php:func:`set_radio()` didn't "uncheck" inputs on a submitted form if the default state is "checked". +- Fixed a bug (#4217) - :doc:`Config Library <libraries/config>` method ``base_url()`` didn't use proper formatting for IPv6 when it falls back to ``$_SERVER['SERVER_ADDR']``. +- Fixed a bug where :doc:`CAPTCHA Helper <helpers/captcha_helper>` entered an infinite loop while generating a random string. +- Fixed a bug (#4223) - :doc:`Database <database/method>` method ``simple_query()`` blindly executes queries without checking if the connection was initialized properly. +- Fixed a bug (#4244) - :doc:`Email Library <libraries/email>` could improperly use "unsafe" US-ASCII characters during Quoted-printable encoding. +- Fixed a bug (#4245) - :doc:`Database Forge <database/forge>` couldn't properly handle ``SET`` and ``ENUM`` type fields with string values. +- Fixed a bug (#4283) - :doc:`String Helper <helpers/string_helper>` function :php:func:`alternator()` couldn't be called without arguments. +- Fixed a bug (#4306) - :doc:`Database <database/index>` method ``version()`` didn't work properly with the 'mssql' driver. +- Fixed a bug (#4039) - :doc:`Session Library <libraries/sessions>` could generate multiple (redundant) warnings in case of a read failure with the 'files' driver, due to a bug in PHP. +- Fixed a bug where :doc:`Session Library <libraries/sessions>` didn't have proper error handling on PHP 5 (due to a PHP bug). +- Fixed a bug (#4312) - :doc:`Form Validation Library <libraries/form_validation>` didn't provide error feedback for failed validation on empty requests. +- Fixed a bug where :doc:`Database <database/index>` method `version()` returned banner text instead of only the version number with the 'oci8' and 'pdo/oci' drivers. + Version 3.0.3 ============= diff --git a/user_guide_src/source/general/routing.rst b/user_guide_src/source/general/routing.rst index b2c9873ab..515368099 100644 --- a/user_guide_src/source/general/routing.rst +++ b/user_guide_src/source/general/routing.rst @@ -113,18 +113,19 @@ A typical RegEx route might look something like this:: In the above example, a URI similar to products/shirts/123 would instead call the "shirts" controller class and the "id_123" method. -With regular expressions, you can also catch a segment containing a -forward slash ('/'), which would usually represent the delimiter between -multiple segments. - +With regular expressions, you can also catch multiple segments at once. For example, if a user accesses a password protected area of your web application and you wish to be able to redirect them back to the same page after they log in, you may find this example useful:: $route['login/(.+)'] = 'auth/login/$1'; +.. note:: In the above example, if the ``$1`` placeholder contains a + slash, it will still be split into multiple parameters when + passed to ``Auth::login()``. + For those of you who don't know regular expressions and want to learn -more about them, `regular-expressions.info <http://www.regular-expressions.info/>` +more about them, `regular-expressions.info <http://www.regular-expressions.info/>`_ might be a good starting point. .. note:: You can also mix and match wildcards with regular expressions. |