summaryrefslogtreecommitdiffstats
path: root/system/libraries/Session
diff options
context:
space:
mode:
authorDiederikLascaris <info@runesa.nl>2017-01-22 21:45:15 +0100
committerDiederikLascaris <info@runesa.nl>2017-01-22 21:45:15 +0100
commit312efeba32d532878c536fd28e75f39d61a9dade (patch)
tree71ae4aaca33a9d34a789d6d375acd2594160123a /system/libraries/Session
parent947f1a06093a52a32b703ee795e52c22cd66363a (diff)
parent44c7af639ac1726780b64fb5a6cb6fca2df8b651 (diff)
Merge branch 'develop' of git://github.com/bcit-ci/CodeIgniter into develop
Diffstat (limited to 'system/libraries/Session')
-rw-r--r--system/libraries/Session/Session.php136
-rw-r--r--system/libraries/Session/SessionHandlerInterface.php59
-rw-r--r--system/libraries/Session/Session_driver.php53
-rw-r--r--system/libraries/Session/drivers/Session_database_driver.php91
-rw-r--r--system/libraries/Session/drivers/Session_files_driver.php132
-rw-r--r--system/libraries/Session/drivers/Session_memcached_driver.php80
-rw-r--r--system/libraries/Session/drivers/Session_redis_driver.php154
7 files changed, 445 insertions, 260 deletions
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index 05a470d86..3e4865cd1 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
- * @link http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 2.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Sessions
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ * @link https://codeigniter.com/user_guide/libraries/sessions.html
*/
class CI_Session {
@@ -57,6 +57,7 @@ class CI_Session {
protected $_driver = 'files';
protected $_config;
+ protected $_sid_regexp;
// ------------------------------------------------------------------------
@@ -91,6 +92,7 @@ class CI_Session {
// Note: BC workaround
elseif (config_item('sess_use_database'))
{
+ log_message('debug', 'Session: "sess_driver" is empty; using BC fallback to "sess_use_database".');
$this->_driver = 'database';
}
@@ -98,27 +100,12 @@ class CI_Session {
// Configuration ...
$this->_configure($params);
+ $this->_config['_sid_regexp'] = $this->_sid_regexp;
$class = new $class($this->_config);
if ($class instanceof SessionHandlerInterface)
{
- if (is_php('5.4'))
- {
- session_set_save_handler($class, TRUE);
- }
- else
- {
- session_set_save_handler(
- array($class, 'open'),
- array($class, 'close'),
- array($class, 'read'),
- array($class, 'write'),
- array($class, 'destroy'),
- array($class, 'gc')
- );
-
- register_shutdown_function('session_write_close');
- }
+ session_set_save_handler($class, TRUE);
}
else
{
@@ -130,7 +117,7 @@ class CI_Session {
if (isset($_COOKIE[$this->_config['cookie_name']])
&& (
! is_string($_COOKIE[$this->_config['cookie_name']])
- OR ! preg_match('/^[0-9a-f]{40}$/', $_COOKIE[$this->_config['cookie_name']])
+ OR ! preg_match('#\A'.$this->_sid_regexp.'\z#', $_COOKIE[$this->_config['cookie_name']])
)
)
{
@@ -187,9 +174,6 @@ class CI_Session {
*/
protected function _ci_load_classes($driver)
{
- // PHP 5.4 compatibility
- interface_exists('SessionHandlerInterface', FALSE) OR require_once(BASEPATH.'libraries/Session/SessionHandlerInterface.php');
-
$prefix = config_item('subclass_prefix');
if ( ! class_exists('CI_Session_driver', FALSE))
@@ -231,7 +215,7 @@ class CI_Session {
}
}
- if ( ! class_exists($prefix.$class) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$prefix.$class.'.php'))
+ if ( ! class_exists($prefix.$class, FALSE) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$prefix.$class.'.php'))
{
require_once($file_path);
if (class_exists($prefix.$class, FALSE))
@@ -314,8 +298,82 @@ class CI_Session {
ini_set('session.use_strict_mode', 1);
ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);
- ini_set('session.hash_function', 1);
- ini_set('session.hash_bits_per_character', 4);
+
+ $this->_configure_sid_length();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Configure session ID length
+ *
+ * To make life easier, we used to force SHA-1 and 4 bits per
+ * character on everyone. And of course, someone was unhappy.
+ *
+ * Then PHP 7.1 broke backwards-compatibility because ext/session
+ * is such a mess that nobody wants to touch it with a pole stick,
+ * and the one guy who does, nobody has the energy to argue with.
+ *
+ * So we were forced to make changes, and OF COURSE something was
+ * going to break and now we have this pile of shit. -- Narf
+ *
+ * @return void
+ */
+ protected function _configure_sid_length()
+ {
+ if (PHP_VERSION_ID < 70100)
+ {
+ $hash_function = ini_get('session.hash_function');
+ if (ctype_digit($hash_function))
+ {
+ if ($hash_function !== '1')
+ {
+ ini_set('session.hash_function', 1);
+ }
+
+ $bits = 160;
+ }
+ elseif ( ! in_array($hash_function, hash_algos(), TRUE))
+ {
+ ini_set('session.hash_function', 1);
+ $bits = 160;
+ }
+ elseif (($bits = strlen(hash($hash_function, 'dummy', false)) * 4) < 160)
+ {
+ ini_set('session.hash_function', 1);
+ $bits = 160;
+ }
+
+ $bits_per_character = (int) ini_get('session.hash_bits_per_character');
+ $sid_length = (int) ceil($bits / $bits_per_character);
+ }
+ else
+ {
+ $bits_per_character = (int) ini_get('session.sid_bits_per_character');
+ $sid_length = (int) ini_get('session.sid_length');
+ if (($bits = $sid_length * $bits_per_character) < 160)
+ {
+ // Add as many more characters as necessary to reach at least 160 bits
+ $sid_length += (int) ceil((160 % $bits) / $bits_per_character);
+ ini_set('session.sid_length', $sid_length);
+ }
+ }
+
+ // Yes, 4,5,6 are the only known possible values as of 2016-10-27
+ switch ($bits_per_character)
+ {
+ case 4:
+ $this->_sid_regexp = '[0-9a-f]';
+ break;
+ case 5:
+ $this->_sid_regexp = '[0-9a-v]';
+ break;
+ case 6:
+ $this->_sid_regexp = '[0-9a-zA-Z,-]';
+ break;
+ }
+
+ $this->_sid_regexp .= '{'.$sid_length.'}';
}
// ------------------------------------------------------------------------
@@ -584,6 +642,24 @@ class CI_Session {
// ------------------------------------------------------------------------
/**
+ * __isset()
+ *
+ * @param string $key 'session_id' or a session data key
+ * @return bool
+ */
+ public function __isset($key)
+ {
+ if ($key === 'session_id')
+ {
+ return (session_status() === PHP_SESSION_ACTIVE);
+ }
+
+ return isset($_SESSION[$key]);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* __set()
*
* @param string $key Session data key
@@ -711,7 +787,7 @@ class CI_Session {
*
* Legacy CI_Session compatibility method
*
- * @param mixed $data Session data key(s)
+ * @param mixed $key Session data key(s)
* @return void
*/
public function unset_userdata($key)
diff --git a/system/libraries/Session/SessionHandlerInterface.php b/system/libraries/Session/SessionHandlerInterface.php
deleted file mode 100644
index 9dab5ac07..000000000
--- a/system/libraries/Session/SessionHandlerInterface.php
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-/**
- * CodeIgniter
- *
- * An open source application development framework for PHP
- *
- * This content is released under the MIT License (MIT)
- *
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @package CodeIgniter
- * @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
- * @license http://opensource.org/licenses/MIT MIT License
- * @link http://codeigniter.com
- * @since Version 3.0.0
- * @filesource
- */
-defined('BASEPATH') OR exit('No direct script access allowed');
-
-/**
- * SessionHandlerInterface
- *
- * PHP 5.4 compatibility interface
- *
- * @package CodeIgniter
- * @subpackage Libraries
- * @category Sessions
- * @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
- */
-interface SessionHandlerInterface {
-
- public function open($save_path, $name);
- public function close();
- public function read($session_id);
- public function write($session_id, $session_data);
- public function destroy($session_id);
- public function gc($maxlifetime);
-}
diff --git a/system/libraries/Session/Session_driver.php b/system/libraries/Session/Session_driver.php
index 47376da5b..f32f14ae0 100644
--- a/system/libraries/Session/Session_driver.php
+++ b/system/libraries/Session/Session_driver.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
- * @link http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Sessions
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ * @link https://codeigniter.com/user_guide/libraries/sessions.html
*/
abstract class CI_Session_driver implements SessionHandlerInterface {
@@ -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;
+ }
}
// ------------------------------------------------------------------------
@@ -145,4 +168,24 @@ 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 1d01c2923..31f5a4663 100644
--- a/system/libraries/Session/drivers/Session_database_driver.php
+++ b/system/libraries/Session/drivers/Session_database_driver.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
- * @link http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Sessions
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ * @link https://codeigniter.com/user_guide/libraries/sessions.html
*/
class CI_Session_database_driver extends CI_Session_driver implements SessionHandlerInterface {
@@ -109,7 +109,10 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
}
// Note: BC work-around for the old 'sess_table_name' setting, should be removed in the future.
- isset($this->_config['save_path']) OR $this->_config['save_path'] = config_item('sess_table_name');
+ if ( ! isset($this->_config['save_path']) && ($this->_config['save_path'] = config_item('sess_table_name')))
+ {
+ log_message('debug', 'Session: "sess_save_path" is empty; using BC fallback to "sess_table_name".');
+ }
}
// ------------------------------------------------------------------------
@@ -125,9 +128,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->_fail();
+ }
+
+ return $this->_success;
}
// ------------------------------------------------------------------------
@@ -144,6 +150,9 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
{
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;
@@ -157,8 +166,12 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
$this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);
}
- if (($result = $this->_db->get()->row()) === NULL)
+ 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 '';
}
@@ -192,21 +205,24 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
*/
public function write($session_id, $session_data)
{
+ // Prevent previous QB calls from messing with our queries
+ $this->_db->reset_query();
+
+ if ($this->_lock === FALSE)
+ {
+ return $this->_fail();
+ }
// Was the ID regenerated?
- if ($session_id !== $this->_session_id)
+ elseif ($session_id !== $this->_session_id)
{
if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))
{
- return FALSE;
+ return $this->_fail();
}
$this->_row_exists = FALSE;
$this->_session_id = $session_id;
}
- elseif ($this->_lock === FALSE)
- {
- return FALSE;
- }
if ($this->_row_exists === FALSE)
{
@@ -220,10 +236,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->_fail();
}
$this->_db->where('id', $session_id);
@@ -243,10 +260,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->_fail();
}
// ------------------------------------------------------------------------
@@ -260,9 +277,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->_fail()
+ : $this->_success;
}
// ------------------------------------------------------------------------
@@ -279,18 +296,28 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
{
if ($this->_lock)
{
+ // Prevent previous QB calls from messing with our queries
+ $this->_db->reset_query();
+
$this->_db->where('id', $session_id);
if ($this->_config['match_ip'])
{
$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->_fail();
+ }
}
- return ($this->close() && $this->_cookie_destroy());
+ if ($this->close() === $this->_success)
+ {
+ $this->_cookie_destroy();
+ return $this->_success;
+ }
+
+ return $this->_fail();
}
// ------------------------------------------------------------------------
@@ -305,7 +332,12 @@ 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));
+ // Prevent previous QB calls from messing with our queries
+ $this->_db->reset_query();
+
+ return ($this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime)))
+ ? $this->_success
+ : $this->_fail();
}
// ------------------------------------------------------------------------
@@ -322,7 +354,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
{
if ($this->_platform === 'mysql')
{
- $arg = $session_id.($this->_config['match_ip'] ? '_'.$_SERVER['REMOTE_ADDR'] : '');
+ $arg = md5($session_id.($this->_config['match_ip'] ? '_'.$_SERVER['REMOTE_ADDR'] : ''));
if ($this->_db->query("SELECT GET_LOCK('".$arg."', 300) AS ci_session_lock")->row()->ci_session_lock)
{
$this->_lock = $arg;
@@ -385,5 +417,4 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
return parent::_release_lock();
}
-
}
diff --git a/system/libraries/Session/drivers/Session_files_driver.php b/system/libraries/Session/drivers/Session_files_driver.php
index 45da91c46..6016e094e 100644
--- a/system/libraries/Session/drivers/Session_files_driver.php
+++ b/system/libraries/Session/drivers/Session_files_driver.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
- * @link http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Sessions
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ * @link https://codeigniter.com/user_guide/libraries/sessions.html
*/
class CI_Session_files_driver extends CI_Session_driver implements SessionHandlerInterface {
@@ -76,6 +76,20 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
*/
protected $_file_new;
+ /**
+ * Validate SID regular expression
+ *
+ * @var string
+ */
+ protected $_sid_regexp;
+
+ /**
+ * mbstring.func_override flag
+ *
+ * @var bool
+ */
+ protected static $func_override;
+
// ------------------------------------------------------------------------
/**
@@ -95,8 +109,13 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
}
else
{
+ log_message('debug', 'Session: "sess_save_path" is empty; using "session.save_path" value from php.ini.');
$this->_config['save_path'] = rtrim(ini_get('session.save_path'), '/\\');
}
+
+ $this->_sid_regexp = $this->_config['_sid_regexp'];
+
+ isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
}
// ------------------------------------------------------------------------
@@ -129,7 +148,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;
}
// ------------------------------------------------------------------------
@@ -148,21 +167,12 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
// which re-reads session data
if ($this->_file_handle === NULL)
{
- // Just using fopen() with 'c+b' mode would be perfect, but it is only
- // available since PHP 5.2.6 and we have to set permissions for new files,
- // so we'd have to hack around this ...
- if (($this->_file_new = ! file_exists($this->_file_path.$session_id)) === TRUE)
- {
- 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;
- }
- }
- elseif (($this->_file_handle = fopen($this->_file_path.$session_id, 'r+b')) === FALSE)
+ $this->_file_new = ! file_exists($this->_file_path.$session_id);
+
+ if (($this->_file_handle = fopen($this->_file_path.$session_id, 'c+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 +180,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,13 +193,19 @@ 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_handle === FALSE)
+ {
+ return $this->_failure;
+ }
else
{
rewind($this->_file_handle);
}
$session_data = '';
- for ($read = 0, $length = filesize($this->_file_path.$session_id); $read < $length; $read += strlen($buffer))
+ for ($read = 0, $length = filesize($this->_file_path.$session_id); $read < $length; $read += self::strlen($buffer))
{
if (($buffer = fread($this->_file_handle, $length - $read)) === FALSE)
{
@@ -218,20 +234,20 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
{
// If the two IDs don't match, we have a session_regenerate_id() call
// 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))
+ if ($session_id !== $this->_session_id && ($this->close() === $this->_failure OR $this->read($session_id) === $this->_failure))
{
- 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 +270,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 +295,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;
}
// ------------------------------------------------------------------------
@@ -297,21 +312,33 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
*/
public function destroy($session_id)
{
- if ($this->close())
+ if ($this->close() === $this->_success)
{
- 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,15 +356,18 @@ 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;
+ $pattern = ($this->_config['match_ip'] === TRUE)
+ ? '[0-9a-f]{32}'
+ : '';
+
$pattern = sprintf(
- '/^%s[0-9a-f]{%d}$/',
- preg_quote($this->_config['cookie_name'], '/'),
- ($this->_config['match_ip'] === TRUE ? 72 : 40)
+ '#\A%s'.$pattern.$this->_sid_regexp.'\z#',
+ preg_quote($this->_config['cookie_name'])
);
while (($file = readdir($directory)) !== FALSE)
@@ -356,7 +386,21 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
closedir($directory);
- return TRUE;
+ return $this->_success;
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe strlen()
+ *
+ * @param string $str
+ * @return int
+ */
+ protected static function strlen($str)
+ {
+ return (self::$func_override)
+ ? mb_strlen($str, '8bit')
+ : strlen($str);
+ }
}
diff --git a/system/libraries/Session/drivers/Session_memcached_driver.php b/system/libraries/Session/drivers/Session_memcached_driver.php
index 97b860588..2556bf0f7 100644
--- a/system/libraries/Session/drivers/Session_memcached_driver.php
+++ b/system/libraries/Session/drivers/Session_memcached_driver.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
- * @link http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Sessions
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ * @link https://codeigniter.com/user_guide/libraries/sessions.html
*/
class CI_Session_memcached_driver extends CI_Session_driver implements SessionHandlerInterface {
@@ -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->_fail();
}
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->_fail();
}
- 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->_fail();
}
// ------------------------------------------------------------------------
@@ -186,40 +186,44 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
*/
public function write($session_id, $session_data)
{
- if ( ! isset($this->_memcached))
+ if ( ! isset($this->_memcached, $this->_lock_key))
{
- return FALSE;
+ return $this->_fail();
}
// Was the ID regenerated?
elseif ($session_id !== $this->_session_id)
{
if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))
{
- return FALSE;
+ return $this->_fail();
}
$this->_fingerprint = md5('');
$this->_session_id = $session_id;
}
- if (isset($this->_lock_key))
+ $key = $this->_key_prefix.$session_id;
+
+ $this->_memcached->replace($this->_lock_key, time(), 300);
+ if ($this->_fingerprint !== ($fingerprint = md5($session_data)))
{
- $this->_memcached->replace($this->_lock_key, time(), 300);
- if ($this->_fingerprint !== ($fingerprint = md5($session_data)))
+ if ($this->_memcached->set($key, $session_data, $this->_config['expiration']))
{
- if ($this->_memcached->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))
- {
- $this->_fingerprint = $fingerprint;
- return TRUE;
- }
-
- return FALSE;
+ $this->_fingerprint = $fingerprint;
+ return $this->_success;
}
- return $this->_memcached->touch($this->_key_prefix.$session_id, $this->_config['expiration']);
+ return $this->_fail();
+ }
+ elseif (
+ $this->_memcached->touch($key, $this->_config['expiration'])
+ OR ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND && $this->_memcached->set($key, $session_data, $this->_config['expiration']))
+ )
+ {
+ return $this->_success;
}
- return FALSE;
+ return $this->_fail();
}
// ------------------------------------------------------------------------
@@ -235,17 +239,17 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
{
if (isset($this->_memcached))
{
- isset($this->_lock_key) && $this->_memcached->delete($this->_lock_key);
+ $this->_release_lock();
if ( ! $this->_memcached->quit())
{
- return FALSE;
+ return $this->_fail();
}
$this->_memcached = NULL;
- return TRUE;
+ return $this->_success;
}
- return FALSE;
+ return $this->_fail();
}
// ------------------------------------------------------------------------
@@ -263,10 +267,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->_fail();
}
// ------------------------------------------------------------------------
@@ -282,7 +287,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;
}
// ------------------------------------------------------------------------
@@ -297,9 +302,17 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
*/
protected function _get_lock($session_id)
{
- if (isset($this->_lock_key))
+ // PHP 7 reuses the SessionHandler object on regeneration,
+ // so we need to check here if the lock key is for the
+ // correct session ID.
+ if ($this->_lock_key === $this->_key_prefix.$session_id.':lock')
{
- return $this->_memcached->replace($this->_lock_key, time(), 300);
+ if ( ! $this->_memcached->replace($this->_lock_key, time(), 300))
+ {
+ return ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND)
+ ? $this->_memcached->set($this->_lock_key, time(), 300)
+ : FALSE;
+ }
}
// 30 attempts to obtain a lock, in case another request already has it
@@ -359,5 +372,4 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
return TRUE;
}
-
}
diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php
index b098cc441..5313de04c 100644
--- a/system/libraries/Session/drivers/Session_redis_driver.php
+++ b/system/libraries/Session/drivers/Session_redis_driver.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
- * @link http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Sessions
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ * @link https://codeigniter.com/user_guide/libraries/sessions.html
*/
class CI_Session_redis_driver extends CI_Session_driver implements SessionHandlerInterface {
@@ -69,6 +69,13 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
*/
protected $_lock_key;
+ /**
+ * Key exists flag
+ *
+ * @var bool
+ */
+ protected $_key_exists = FALSE;
+
// ------------------------------------------------------------------------
/**
@@ -85,27 +92,40 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
{
log_message('error', 'Session: No Redis save path configured.');
}
- elseif (preg_match('#(?:tcp://)?([^:?]+)(?:\:(\d+))?(\?.+)?#', $this->_config['save_path'], $matches))
+ elseif (preg_match('#^unix://([^\?]+)(?<options>\?.+)?$#', $this->_config['save_path'], $matches))
+ {
+ $save_path = array('path' => $matches[1]);
+ }
+ elseif (preg_match('#(?:tcp://)?([^:?]+)(?:\:(\d+))?(?<options>\?.+)?#', $this->_config['save_path'], $matches))
{
- isset($matches[3]) OR $matches[3] = ''; // Just to avoid undefined index notices below
- $this->_config['save_path'] = array(
- 'host' => $matches[1],
- 'port' => empty($matches[2]) ? NULL : $matches[2],
- 'password' => preg_match('#auth=([^\s&]+)#', $matches[3], $match) ? $match[1] : NULL,
- 'database' => preg_match('#database=(\d+)#', $matches[3], $match) ? (int) $match[1] : NULL,
- 'timeout' => preg_match('#timeout=(\d+\.\d+)#', $matches[3], $match) ? (float) $match[1] : NULL
+ $save_path = array(
+ 'host' => $matches[1],
+ 'port' => empty($matches[2]) ? NULL : $matches[2],
+ 'timeout' => NULL // We always pass this to Redis::connect(), so it needs to exist
);
-
- preg_match('#prefix=([^\s&]+)#', $matches[3], $match) && $this->_key_prefix = $match[1];
}
else
{
log_message('error', 'Session: Invalid Redis save path format: '.$this->_config['save_path']);
}
- if ($this->_config['match_ip'] === TRUE)
+ if (isset($save_path))
{
- $this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';
+ if (isset($matches['options']))
+ {
+ $save_path['password'] = preg_match('#auth=([^\s&]+)#', $matches['options'], $match) ? $match[1] : NULL;
+ $save_path['database'] = preg_match('#database=(\d+)#', $matches['options'], $match) ? (int) $match[1] : NULL;
+ $save_path['timeout'] = preg_match('#timeout=(\d+\.\d+)#', $matches['options'], $match) ? (float) $match[1] : NULL;
+
+ preg_match('#prefix=([^\s&]+)#', $matches['options'], $match) && $this->_key_prefix = $match[1];
+ }
+
+ $this->_config['save_path'] = $save_path;
+
+ if ($this->_config['match_ip'] === TRUE)
+ {
+ $this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';
+ }
}
}
@@ -124,29 +144,40 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
{
if (empty($this->_config['save_path']))
{
- return FALSE;
+ return $this->_fail();
}
$redis = new Redis();
- if ( ! $redis->connect($this->_config['save_path']['host'], $this->_config['save_path']['port'], $this->_config['save_path']['timeout']))
- {
- log_message('error', 'Session: Unable to connect to Redis with the configured settings.');
- }
- elseif (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password']))
- {
- log_message('error', 'Session: Unable to authenticate to Redis instance.');
- }
- elseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database']))
+ $connected = isset($this->_config['save_path']['path'])
+ ? $redis->connect($this->_config['save_path']['path'])
+ : $redis->connect(
+ $this->_config['save_path']['host'],
+ $this->_config['save_path']['port'],
+ $this->_config['save_path']['timeout']
+ );
+
+ if ($connected)
{
- log_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']);
+ if (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password']))
+ {
+ log_message('error', 'Session: Unable to authenticate to Redis instance.');
+ }
+ elseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database']))
+ {
+ log_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']);
+ }
+ else
+ {
+ $this->_redis = $redis;
+ return $this->_success;
+ }
}
else
{
- $this->_redis = $redis;
- return TRUE;
+ log_message('error', 'Session: Unable to connect to Redis with the configured settings.');
}
- return FALSE;
+ return $this->_fail();
}
// ------------------------------------------------------------------------
@@ -166,12 +197,17 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
// Needed by write() to detect session_regenerate_id() calls
$this->_session_id = $session_id;
- $session_data = (string) $this->_redis->get($this->_key_prefix.$session_id);
+ $session_data = $this->_redis->get($this->_key_prefix.$session_id);
+
+ is_string($session_data)
+ ? $this->_key_exists = TRUE
+ : $session_data = '';
+
$this->_fingerprint = md5($session_data);
return $session_data;
}
- return FALSE;
+ return $this->_fail();
}
// ------------------------------------------------------------------------
@@ -187,40 +223,38 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
*/
public function write($session_id, $session_data)
{
- if ( ! isset($this->_redis))
+ if ( ! isset($this->_redis, $this->_lock_key))
{
- return FALSE;
+ return $this->_fail();
}
// Was the ID regenerated?
elseif ($session_id !== $this->_session_id)
{
if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))
{
- return FALSE;
+ return $this->_fail();
}
- $this->_fingerprint = md5('');
+ $this->_key_exists = FALSE;
$this->_session_id = $session_id;
}
- if (isset($this->_lock_key))
+ $this->_redis->setTimeout($this->_lock_key, 300);
+ if ($this->_fingerprint !== ($fingerprint = md5($session_data)) OR $this->_key_exists === FALSE)
{
- $this->_redis->setTimeout($this->_lock_key, 300);
- if ($this->_fingerprint !== ($fingerprint = md5($session_data)))
+ if ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))
{
- if ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))
- {
- $this->_fingerprint = $fingerprint;
- return TRUE;
- }
-
- return FALSE;
+ $this->_fingerprint = $fingerprint;
+ $this->_key_exists = TRUE;
+ return $this->_success;
}
- return $this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration']);
+ return $this->_fail();
}
- return FALSE;
+ return ($this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration']))
+ ? $this->_success
+ : $this->_fail();
}
// ------------------------------------------------------------------------
@@ -239,10 +273,10 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
try {
if ($this->_redis->ping() === '+PONG')
{
- isset($this->_lock_key) && $this->_redis->delete($this->_lock_key);
- if ( ! $this->_redis->close())
+ $this->_release_lock();
+ if ($this->_redis->close() === FALSE)
{
- return FALSE;
+ return $this->_fail();
}
}
}
@@ -252,10 +286,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;
}
// ------------------------------------------------------------------------
@@ -277,10 +311,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->_fail();
}
// ------------------------------------------------------------------------
@@ -296,7 +331,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;
}
// ------------------------------------------------------------------------
@@ -311,7 +346,10 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
*/
protected function _get_lock($session_id)
{
- if (isset($this->_lock_key))
+ // PHP 7 reuses the SessionHandler object on regeneration,
+ // so we need to check here if the lock key is for the
+ // correct session ID.
+ if ($this->_lock_key === $this->_key_prefix.$session_id.':lock')
{
return $this->_redis->setTimeout($this->_lock_key, 300);
}