diff options
25 files changed, 225 insertions, 118 deletions
diff --git a/.travis.yml b/.travis.yml index 963d2cd2f..8525d5f6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: php -dist: precise +dist: trusty php: - 5.4 @@ -9,8 +9,9 @@ php: - 7.1 - 7.2 - 7.3 - - master - - hhvm + - 7.4snapshot + - nightly + - hhvm-3.30 env: - DB=mysql @@ -33,12 +34,13 @@ script: php -d zend.enable_gc=0 -d date.timezone=UTC -d mbstring.func_overload=7 matrix: allow_failures: - - php: hhvm - - php: master + - php: 7.4snapshot + - php: nightly + - php: hhvm-3.30 exclude: - - php: hhvm + - php: hhvm-3.30 env: DB=pgsql - - php: hhvm + - php: hhvm-3.30 env: DB=pdo/pgsql - php: 7.0 env: DB=mysql @@ -48,7 +50,9 @@ matrix: env: DB=mysql - php: 7.3 env: DB=mysql - - php: master + - php: 7.4snapshot + env: DB=mysql + - php: nightly env: DB=mysql branches: diff --git a/composer.json b/composer.json index 6769e9545..39c7e77c4 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +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.*" } } diff --git a/system/core/Controller.php b/system/core/Controller.php index 2bb157802..e25b8472c 100644 --- a/system/core/Controller.php +++ b/system/core/Controller.php @@ -59,6 +59,13 @@ class CI_Controller { private static $instance; /** + * CI_Loader + * + * @var CI_Loader + */ + public $load; + + /** * Class constructor * * @return void diff --git a/system/core/Security.php b/system/core/Security.php index 27b4db69d..5edb67f4e 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -229,6 +229,7 @@ class CI_Security { // Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate $valid = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]) + && is_string($_POST[$this->_csrf_token_name]) && is_string($_COOKIE[$this->_csrf_cookie_name]) && hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]); // We kill this since we're done and we don't want to pollute the _POST array diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 12949c7dc..78e8018c7 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -1484,7 +1484,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $qb_cache_orderby = $this->qb_cache_orderby; $this->qb_orderby = $this->qb_cache_orderby = array(); - $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby) OR ! empty($this->qb_cache_groupby) OR $this->qb_limit OR $this->qb_offset) + $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby) OR ! empty($this->qb_cache_groupby) OR ! empty($this->qb_having) OR $this->qb_limit OR $this->qb_offset) ? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results") : $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows'))); diff --git a/system/database/DB_result.php b/system/database/DB_result.php index 0dbac1633..ed5252d49 100644 --- a/system/database/DB_result.php +++ b/system/database/DB_result.php @@ -381,7 +381,7 @@ class CI_DB_result { */ public function custom_row_object($n, $type) { - isset($this->custom_result_object[$type]) OR $this->custom_result_object($type); + isset($this->custom_result_object[$type]) OR $this->custom_result_object[$type] = $this->custom_result_object($type); if (count($this->custom_result_object[$type]) === 0) { diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php index 388a46c82..bdd80092c 100644 --- a/system/database/drivers/mysql/mysql_driver.php +++ b/system/database/drivers/mysql/mysql_driver.php @@ -382,7 +382,7 @@ class CI_DB_mysql_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database); + $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char; if ($prefix_limit !== FALSE && $this->dbprefix !== '') { diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php index 4f0c28e78..6553a271f 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -423,7 +423,7 @@ class CI_DB_mysqli_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database); + $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char; if ($prefix_limit !== FALSE && $this->dbprefix !== '') { diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php index 03c0f9f9d..b3973da46 100644 --- a/system/database/drivers/pdo/pdo_result.php +++ b/system/database/drivers/pdo/pdo_result.php @@ -133,7 +133,7 @@ class CI_DB_pdo_result extends CI_DB_result { $retval[$i] = new stdClass(); $retval[$i]->name = $field['name']; - $retval[$i]->type = $field['native_type']; + $retval[$i]->type = isset($field['native_type']) ? $field['native_type'] : null; $retval[$i]->max_length = ($field['len'] > 0) ? $field['len'] : NULL; $retval[$i]->primary_key = (int) ( ! empty($field['flags']) && in_array('primary_key', $field['flags'], TRUE)); } diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php index 26bc30e14..73b88bcfd 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php @@ -279,7 +279,7 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SHOW TABLES'; + $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char; if ($prefix_limit === TRUE && $this->dbprefix !== '') { diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php index b05d473ee..2d0c74b2e 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php @@ -98,7 +98,7 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { if ( ! empty($this->username)) { - $this->dsn .= ';username='.$this->username; + $this->dsn .= ';user='.$this->username; empty($this->password) OR $this->dsn .= ';password='.$this->password; } } diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php index 3bc3ccd6c..3c4c23d3b 100644 --- a/system/libraries/Cache/drivers/Cache_redis.php +++ b/system/libraries/Cache/drivers/Cache_redis.php @@ -69,6 +69,14 @@ class CI_Cache_redis extends CI_Driver */ protected $_redis; + + /** + * del()/delete() method name depending on phpRedis version + * + * @var string + */ + protected static $_delete_name; + // ------------------------------------------------------------------------ /** @@ -90,6 +98,10 @@ class CI_Cache_redis extends CI_Driver return; } + isset(static::$_delete_name) OR static::$_delete_name = version_compare(phpversion('phpredis'), '5', '>=') + ? 'del' + : 'delete'; + $CI =& get_instance(); if ($CI->config->load('redis', TRUE, TRUE)) @@ -138,7 +150,7 @@ class CI_Cache_redis extends CI_Driver { $data = $this->_redis->hMGet($key, array('__ci_type', '__ci_value')); - if ( ! isset($data['__ci_type'], $data['__ci_value']) OR $data['__ci_value'] === FALSE) + if ($value !== FALSE && $this->_redis->sIsMember('_ci_redis_serialized', $key)) { return FALSE; } @@ -196,9 +208,9 @@ class CI_Cache_redis extends CI_Driver { return FALSE; } - elseif ($ttl) + else { - $this->_redis->expireAt($id, time() + $ttl); + $this->_redis->sRemove('_ci_redis_serialized', $id); } return TRUE; @@ -214,7 +226,14 @@ class CI_Cache_redis extends CI_Driver */ public function delete($key) { - return ($this->_redis->delete($key) === 1); + if ($this->_redis->{static::$_delete_name}($key) !== 1) + { + return FALSE; + } + + $this->_redis->sRemove('_ci_redis_serialized', $key); + + return TRUE; } // ------------------------------------------------------------------------ @@ -228,7 +247,7 @@ class CI_Cache_redis extends CI_Driver */ public function increment($id, $offset = 1) { - return $this->_redis->hIncrBy($id, 'data', $offset); + return $this->_redis->incrBy($id, $offset); } // ------------------------------------------------------------------------ @@ -242,7 +261,7 @@ class CI_Cache_redis extends CI_Driver */ public function decrement($id, $offset = 1) { - return $this->_redis->hIncrBy($id, 'data', -$offset); + return $this->_redis->decrBy($id, $offset); } // ------------------------------------------------------------------------ diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index e38c44277..de59ef9f7 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -1214,6 +1214,13 @@ class CI_Form_validation { $str = $matches[2]; } + // Apparently, FILTER_VALIDATE_URL doesn't reject digit-only names for some reason ... + // See https://github.com/bcit-ci/CodeIgniter/issues/5755 + if (ctype_digit($str)) + { + return FALSE; + } + // PHP 7 accepts IPv6 addresses within square brackets as hostnames, // but it appears that the PR that came in with https://bugs.php.net/bug.php?id=68039 // was never merged into a PHP 5 branch ... https://3v4l.org/8PsSN diff --git a/system/libraries/Session/Session_driver.php b/system/libraries/Session/Session_driver.php index 14ebdb09f..dbc833739 100644 --- a/system/libraries/Session/Session_driver.php +++ b/system/libraries/Session/Session_driver.php @@ -184,25 +184,4 @@ abstract class CI_Session_driver implements SessionHandlerInterface { return TRUE; } - - // ------------------------------------------------------------------------ - - /** - * Fail - * - * Drivers other than the 'files' one don't (need to) use the - * session.save_path INI setting, but that leads to confusing - * error messages emitted by PHP when open() or write() fail, - * as the message contains session.save_path ... - * To work around the problem, the drivers will call this method - * so that the INI is set just in time for the error message to - * be properly generated. - * - * @return mixed - */ - protected function _fail() - { - ini_set('session.save_path', config_item('sess_save_path')); - return $this->_failure; - } } diff --git a/system/libraries/Session/drivers/Session_database_driver.php b/system/libraries/Session/drivers/Session_database_driver.php index 734fe624f..89afe3455 100644 --- a/system/libraries/Session/drivers/Session_database_driver.php +++ b/system/libraries/Session/drivers/Session_database_driver.php @@ -130,7 +130,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan { if (empty($this->_db->conn_id) && ! $this->_db->db_connect()) { - return $this->_fail(); + return $this->_failure; } $this->php5_validate_id(); @@ -150,48 +150,47 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan */ public function read($session_id) { - if ($this->_get_lock($session_id) !== FALSE) + if ($this->_get_lock($session_id) === FALSE) { - // Prevent previous QB calls from messing with our queries - $this->_db->reset_query(); - - // Needed by write() to detect session_regenerate_id() calls - $this->_session_id = $session_id; + return $this->_failure; + } - $this->_db - ->select('data') - ->from($this->_config['save_path']) - ->where('id', $session_id); + // Prevent previous QB calls from messing with our queries + $this->_db->reset_query(); - if ($this->_config['match_ip']) - { - $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']); - } + // Needed by write() to detect session_regenerate_id() calls + $this->_session_id = $session_id; - if ( ! ($result = $this->_db->get()) OR ($result = $result->row()) === NULL) - { - // PHP7 will reuse the same SessionHandler object after - // ID regeneration, so we need to explicitly set this to - // FALSE instead of relying on the default ... - $this->_row_exists = FALSE; - $this->_fingerprint = md5(''); - return ''; - } + $this->_db + ->select('data') + ->from($this->_config['save_path']) + ->where('id', $session_id); - // PostgreSQL's variant of a BLOB datatype is Bytea, which is a - // PITA to work with, so we use base64-encoded data in a TEXT - // field instead. - $result = ($this->_platform === 'postgre') - ? base64_decode(rtrim($result->data)) - : $result->data; + if ($this->_config['match_ip']) + { + $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']); + } - $this->_fingerprint = md5($result); - $this->_row_exists = TRUE; - return $result; + if ( ! ($result = $this->_db->get()) OR ($result = $result->row()) === NULL) + { + // PHP7 will reuse the same SessionHandler object after + // ID regeneration, so we need to explicitly set this to + // FALSE instead of relying on the default ... + $this->_row_exists = FALSE; + $this->_fingerprint = md5(''); + return ''; } - $this->_fingerprint = md5(''); - return ''; + // PostgreSQL's variant of a BLOB datatype is Bytea, which is a + // PITA to work with, so we use base64-encoded data in a TEXT + // field instead. + $result = ($this->_platform === 'postgre') + ? base64_decode(rtrim($result->data)) + : $result->data; + + $this->_fingerprint = md5($result); + $this->_row_exists = TRUE; + return $result; } // ------------------------------------------------------------------------ @@ -215,7 +214,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return $this->_fail(); + return $this->_failure; } $this->_row_exists = FALSE; @@ -223,7 +222,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan } elseif ($this->_lock === FALSE) { - return $this->_fail(); + return $this->_failure; } if ($this->_row_exists === FALSE) @@ -242,7 +241,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return $this->_success; } - return $this->_fail(); + return $this->_failure; } $this->_db->where('id', $session_id); @@ -265,7 +264,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return $this->_success; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -280,7 +279,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan public function close() { return ($this->_lock && ! $this->_release_lock()) - ? $this->_fail() + ? $this->_failure : $this->_success; } @@ -309,7 +308,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan if ( ! $this->_db->delete($this->_config['save_path'])) { - return $this->_fail(); + return $this->_failure; } } @@ -319,7 +318,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return $this->_success; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -339,7 +338,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return ($this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime))) ? $this->_success - : $this->_fail(); + : $this->_failure; } // -------------------------------------------------------------------- diff --git a/system/libraries/Session/drivers/Session_memcached_driver.php b/system/libraries/Session/drivers/Session_memcached_driver.php index ab54f029f..854adf821 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 $this->_fail(); + return $this->_failure; } foreach ($matches as $match) @@ -142,7 +142,7 @@ 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 $this->_fail(); + return $this->_failure; } $this->php5_validate_id(); @@ -172,7 +172,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa return $session_data; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -190,14 +190,14 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa { if ( ! isset($this->_memcached, $this->_lock_key)) { - return $this->_fail(); + return $this->_failure; } // Was the ID regenerated? elseif ($session_id !== $this->_session_id) { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return $this->_fail(); + return $this->_failure; } $this->_fingerprint = md5(''); @@ -215,7 +215,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa return $this->_success; } - return $this->_fail(); + return $this->_failure; } elseif ( $this->_memcached->touch($key, $this->_config['expiration']) @@ -225,7 +225,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa return $this->_success; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -244,14 +244,14 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa $this->_release_lock(); if ( ! $this->_memcached->quit()) { - return $this->_fail(); + return $this->_failure; } $this->_memcached = NULL; return $this->_success; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -273,7 +273,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa return $this->_success; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php index 9ff6a0e1f..1bbb13db5 100644 --- a/system/libraries/Session/drivers/Session_redis_driver.php +++ b/system/libraries/Session/drivers/Session_redis_driver.php @@ -76,6 +76,33 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle */ protected $_key_exists = FALSE; + /** + * Name of setTimeout() method in phpRedis + * + * Due to some deprecated methods in phpRedis, we need to call the + * specific methods depending on the version of phpRedis. + * + * @var string + */ + protected $_setTimeout_name; + + /** + * Name of delete() method in phpRedis + * + * Due to some deprecated methods in phpRedis, we need to call the + * specific methods depending on the version of phpRedis. + * + * @var string + */ + protected $_delete_name; + + /** + * Success return value of ping() method in phpRedis + * + * @var mixed + */ + protected $_ping_success; + // ------------------------------------------------------------------------ /** @@ -88,6 +115,20 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { parent::__construct($params); + // Detect the names of some methods in phpRedis instance + if (version_compare(phpversion('redis'), '5', '>=')) + { + $this->_setTimeout_name = 'expire'; + $this->_delete_name = 'del'; + $this->_ping_success = TRUE; + } + else + { + $this->_setTimeout_name = 'setTimeout'; + $this->_delete_name = 'delete'; + $this->_ping_success = '+PONG'; + } + if (empty($this->_config['save_path'])) { log_message('error', 'Session: No Redis save path configured.'); @@ -144,7 +185,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { if (empty($this->_config['save_path'])) { - return $this->_fail(); + return $this->_failure; } $redis = new Redis(); @@ -168,17 +209,19 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle } else { - $this->php5_validate_id(); $this->_redis = $redis; + $this->php5_validate_id(); return $this->_success; } } else { - log_message('error', 'Session: Unable to connect to Redis with the configured settings.'); + $this->_redis = $redis; + $this->php5_validate_id(); + return $this->_success; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -208,7 +251,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle return $session_data; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -226,21 +269,21 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { if ( ! isset($this->_redis, $this->_lock_key)) { - return $this->_fail(); + return $this->_failure; } // Was the ID regenerated? elseif ($session_id !== $this->_session_id) { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return $this->_fail(); + return $this->_failure; } $this->_key_exists = FALSE; $this->_session_id = $session_id; } - $this->_redis->setTimeout($this->_lock_key, 300); + $this->_redis->{$this->_setTimeout_name}($this->_lock_key, 300); if ($this->_fingerprint !== ($fingerprint = md5($session_data)) OR $this->_key_exists === FALSE) { if ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration'])) @@ -250,12 +293,12 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle return $this->_success; } - return $this->_fail(); + return $this->_failure; } - return ($this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration'])) + return ($this->_redis->{$this->_setTimeout_name}($this->_key_prefix.$session_id, $this->_config['expiration'])) ? $this->_success - : $this->_fail(); + : $this->_failure; } // ------------------------------------------------------------------------ @@ -272,12 +315,12 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle if (isset($this->_redis)) { try { - if ($this->_redis->ping() === '+PONG') + if ($this->_redis->ping() === $this->_ping_success) { $this->_release_lock(); if ($this->_redis->close() === FALSE) { - return $this->_fail(); + return $this->_failure; } } } @@ -307,16 +350,16 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { if (isset($this->_redis, $this->_lock_key)) { - if (($result = $this->_redis->delete($this->_key_prefix.$session_id)) !== 1) + if (($result = $this->_redis->{$this->_delete_name}($this->_key_prefix.$session_id)) !== 1) { - log_message('debug', 'Session: Redis::delete() expected to return 1, got '.var_export($result, TRUE).' instead.'); + log_message('debug', 'Session: Redis::'.$this->_delete_name.'() expected to return 1, got '.var_export($result, TRUE).' instead.'); } $this->_cookie_destroy(); return $this->_success; } - return $this->_fail(); + return $this->_failure; } // ------------------------------------------------------------------------ @@ -368,7 +411,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle // correct session ID. if ($this->_lock_key === $this->_key_prefix.$session_id.':lock') { - return $this->_redis->setTimeout($this->_lock_key, 300); + return $this->_redis->{$this->_setTimeout_name}($this->_lock_key, 300); } // 30 attempts to obtain a lock, in case another request already has it @@ -426,7 +469,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { if (isset($this->_redis, $this->_lock_key) && $this->_lock) { - if ( ! $this->_redis->delete($this->_lock_key)) + if ( ! $this->_redis->{$this->_delete_name}($this->_lock_key)) { log_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key); return FALSE; diff --git a/tests/codeigniter/libraries/Form_validation_test.php b/tests/codeigniter/libraries/Form_validation_test.php index 04bd670ad..1bafd50c3 100644 --- a/tests/codeigniter/libraries/Form_validation_test.php +++ b/tests/codeigniter/libraries/Form_validation_test.php @@ -266,6 +266,9 @@ class Form_validation_test extends CI_TestCase { // URI scheme case-sensitivity: https://github.com/bcit-ci/CodeIgniter/pull/4758 $this->assertTrue($this->form_validation->valid_url('HtTp://127.0.0.1/')); + // https://github.com/bcit-ci/CodeIgniter/issues/5755 + $this->assertFalse($this->form_validation->valid_url('1')); + $this->assertFalse($this->form_validation->valid_url('htt://www.codeIgniter.com')); $this->assertFalse($this->form_validation->valid_url('')); $this->assertFalse($this->form_validation->valid_url('code igniter')); diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 7fcd72e8a..08bcec7f7 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -129,17 +129,40 @@ Release Date: Not Released - Added ability to generate ``data:image/png;base64`` URIs instead of writing image files to disk. - Updated to always create PNG images instead of JPEG. -Version 3.1.11 +Version 3.1.12 ============== Release Date: Not Released +Version 3.1.11 +============== + +Release Date: Sep 19, 2019 + +- General Changes + + - Changed ``CI_Log`` to append ``PHP_EOL`` instead of ``\n`` at the end of log messages. + - Improved performance in :doc:`Cache Library <libraries/caching>` 'redis' driver with non-scalar variables. + - Altered the :doc:`Session Library <libraries/sessions>` 'files' driver to log error and trigger a session start failure instead of throwing an ``Exception`` in case of unusable ``$config['sess_save_path']``. + - Updated the :doc:`Session <libraries/sessions>` and :doc:`Cache <libraries/caching>` libraries' 'redis' driver to work with phpRedis 5. + Bug fixes for 3.1.11 ==================== - Fixed a bug (#5681) - :doc:`Database Forge <database/forge>` method ``modify_column()`` produced erroneous SQL for ``DEFAULT`` attribute changes under PostgreSQL, Firebird. - Fixed a bug (#5692) - :doc:`Database Forge <database/forge>` didn't handle column nullability with the 'oci8', 'pdo/oci' drivers. +- Fixed a bug (#5701) - :doc:`Database <database/index>` driver 'pdo/pgsql' produced incorrect DSNs when constructing from a configuration array. +- Fixed a bug (#5708) - :doc:`Session Library <libraries/sessions>` 'redis' driver too often failed with locking-related errors that could've been avoided. +- Fixed a bug (#5703) - :doc:`Session Library <libraries/sessions>` triggered an ``E_WARNING`` message about changing ``session.save_path`` during an active session when it fails to obtain a lock. +- Fixed a bug where :doc:`Session Library <libraries/sessions>` 'database' driver didn't trigger a failure if it can't obtain a lock. +- Fixed a bug (#5755) - :doc:`Form Validation Library <libraries/form_validation>` rule **valid_url** accepted digit-only domains due to a PHP bug. +- Fixed a bug (#5753) - :doc:`Cache Library <libraries/caching>` 'redis' driver methods ``increment()``, ``decrement()`` ignored their ``$offset`` parameter. +- Fixed a bug (#5779) - :doc:`Session Library <libraries/sessions>` 'redis' only attempted to validate session IDs in case the connection to Redis failed. +- Fixed a bug (#5774) - :doc:`Database Results <database/results>` method ``custom_result_object()`` didn't properly handle empty result sets, triggering ``E_WARNING`` messages on PHP 7.2+. +- Fixed a bug (#5788) - :doc:`Database Results <database/results>` method ``field_data()`` triggered an ``E_NOTICE`` error with PDO when a field type is not recognized by PHP. +- Fixed a bug (#5796) - :doc:`Query Builder <database/query_builder>` method ``list_tables()`` triggered an SQL syntax error under MySQL when the database schema is a numeric string. +- Fixed a bug where :doc:`Security Class <libraries/security>` would trigger an ``E_WARNING`` if CSRF inputs are arrays instead of strings. Version 3.1.10 ============== diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst index 428ae3ab2..de9a22a58 100644 --- a/user_guide_src/source/installation/downloads.rst +++ b/user_guide_src/source/installation/downloads.rst @@ -3,7 +3,8 @@ Downloading CodeIgniter ####################### - `CodeIgniter v3.2.0-dev (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/develop>`_ -- `CodeIgniter v3.1.11-dev <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1-stable>`_ +- `CodeIgniter v3.1.12-dev <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1-stable>`_ +- `CodeIgniter v3.1.11 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.11>`_ - `CodeIgniter v3.1.10 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.10>`_ - `CodeIgniter v3.1.9 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.9>`_ - `CodeIgniter v3.1.8 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.8>`_ diff --git a/user_guide_src/source/installation/upgrade_3111.rst b/user_guide_src/source/installation/upgrade_3111.rst index 5463e40c1..5dd02efdc 100644 --- a/user_guide_src/source/installation/upgrade_3111.rst +++ b/user_guide_src/source/installation/upgrade_3111.rst @@ -12,3 +12,9 @@ Replace all files and directories in your *system/* directory. .. note:: If you have any custom developed files in these directories, please make copies of them first. + +Step 2: Replace config/mimes.php +================================ + +This config file has received some updates. Please copy it to +*application/config/mimes.php*. diff --git a/user_guide_src/source/installation/upgrade_3112.rst b/user_guide_src/source/installation/upgrade_3112.rst new file mode 100644 index 000000000..9c849d878 --- /dev/null +++ b/user_guide_src/source/installation/upgrade_3112.rst @@ -0,0 +1,14 @@ +############################### +Upgrading from 3.1.11 to 3.1.12 +############################### + +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 98f49ecac..789c9b32e 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -9,6 +9,7 @@ upgrading from. :titlesonly: Upgrading from 3.1.10+ to 3.2.x <upgrade_320> + Upgrading from 3.1.11 to 3.1.12 <upgrade_3112> Upgrading from 3.1.10 to 3.1.11 <upgrade_3111> Upgrading from 3.1.9 to 3.1.10 <upgrade_3110> Upgrading from 3.1.8 to 3.1.9 <upgrade_319> diff --git a/user_guide_src/source/libraries/typography.rst b/user_guide_src/source/libraries/typography.rst index 9e1386835..321b064ba 100644 --- a/user_guide_src/source/libraries/typography.rst +++ b/user_guide_src/source/libraries/typography.rst @@ -47,7 +47,7 @@ Class Reference .. php:method:: auto_typography($str[, $reduce_linebreaks = FALSE]) :param string $str: Input string - :param bool $reduce_linebreaks: Whether to reduce consequitive linebreaks + :param bool $reduce_linebreaks: Whether to reduce consecutive linebreaks :returns: HTML typography-safe string :rtype: string diff --git a/user_guide_src/source/tutorial/create_news_items.rst b/user_guide_src/source/tutorial/create_news_items.rst index cde52fde8..b53ef2d68 100644 --- a/user_guide_src/source/tutorial/create_news_items.rst +++ b/user_guide_src/source/tutorial/create_news_items.rst @@ -25,7 +25,7 @@ the slug from our title in the model. Create the new view at <?php echo form_open('news/create'); ?> <label for="title">Title</label> - <input type="input" name="title" /><br /> + <input type="text" name="title" /><br /> <label for="text">Text</label> <textarea name="text"></textarea><br /> |