summaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/core/Loader.php11
-rw-r--r--system/libraries/Driver.php22
-rwxr-xr-xsystem/libraries/Session/Session.php621
-rwxr-xr-x[-rw-r--r--]system/libraries/Session/drivers/Session_cookie.php (renamed from system/libraries/Session.php)579
-rwxr-xr-xsystem/libraries/Session/drivers/Session_native.php187
5 files changed, 1037 insertions, 383 deletions
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 0bc6e844a..ea81c6f26 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -1193,6 +1193,15 @@ class CI_Loader {
}
}
+ // Autoload drivers
+ if (isset($autoload['drivers']))
+ {
+ foreach ($autoload['drivers'] as $item)
+ {
+ $this->driver($item);
+ }
+ }
+
// Autoload models
if (isset($autoload['model']))
{
@@ -1260,4 +1269,4 @@ class CI_Loader {
}
/* End of file Loader.php */
-/* Location: ./system/core/Loader.php */ \ No newline at end of file
+/* Location: ./system/core/Loader.php */
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index d67ee2549..1d084c8e4 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -54,13 +54,29 @@ class CI_Driver_Library {
protected $lib_name;
/**
+ * Get magic method
+ *
* The first time a child is used it won't exist, so we instantiate it
* subsequents calls will go straight to the proper child.
*
- * @param mixed $child
- * @return mixed
+ * @param string Child class name
+ * @return object Child class
*/
public function __get($child)
+ {
+ // Try to load the driver
+ return $this->load_driver($child);
+ }
+
+ /**
+ * Load driver
+ *
+ * Separate load_driver call to support explicit driver load by library or user
+ *
+ * @param string Child class name
+ * @return object Child class
+ */
+ public function load_driver($child)
{
if ( ! isset($this->lib_name))
{
@@ -268,4 +284,4 @@ class CI_Driver {
}
/* End of file Driver.php */
-/* Location: ./system/libraries/Driver.php */ \ No newline at end of file
+/* Location: ./system/libraries/Driver.php */
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
new file mode 100755
index 000000000..68819a665
--- /dev/null
+++ b/system/libraries/Session/Session.php
@@ -0,0 +1,621 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author ExpressionEngine Dev Team
+ * @copyright Copyright (c) 2008 - 2010, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 2.0
+ * @filesource
+ */
+
+
+/**
+ * CI_Session Class
+ *
+ * The user interface defined by EllisLabs, now with puggable drivers to manage different storage mechanisms.
+ * By default, the native PHP session driver will load, but the 'sess_driver' config/param item (see above) can be
+ * used to specify the 'cookie' driver, or any other you might create.
+ * Once loaded, this driver setup is a drop-in replacement for the former CI_Session library, taking its place as the
+ * 'session' member of the global controller framework (e.g.: $CI->session or $this->session).
+ * In keeping with the CI_Driver methodology, multiple drivers may be loaded, although this might be a bit confusing.
+ * The CI_Session library class keeps track of the most recently loaded driver as "current" to call for driver methods.
+ * Ideally, one driver is loaded and all calls go directly through the main library interface. However, any methods
+ * called through the specific driver will switch the "current" driver to itself before invoking the library method
+ * (which will then call back into the driver for low-level operations). So, alternation between two drivers can be
+ * achieved by specifying which driver to use for each call (e.g.: $this->session->native->set_userdata('foo', 'bar');
+ * $this->session->cookie->userdata('foo'); $this->session->native->unset_userdata('foo');). Notice in the previous
+ * example that the _native_ userdata value 'foo' would be set to 'bar', which would NOT be returned by the call for
+ * the _cookie_ userdata 'foo', nor would the _cookie_ value be unset by the call to unset the _native_ 'foo' value.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author ExpressionEngine Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ */
+class CI_Session extends CI_Driver_Library {
+ public $params = array();
+ protected $current = null;
+ protected $userdata = array();
+
+ const FLASHDATA_KEY = 'flash';
+ const FLASHDATA_NEW = ':new:';
+ const FLASHDATA_OLD = ':old:';
+ const FLASHDATA_EXP = ':exp:';
+ const EXPIRATION_KEY = '__expirations';
+ const TEMP_EXP_DEF = 300;
+
+ /**
+ * CI_Session constructor
+ *
+ * The constructor loads the configured driver ('sess_driver' in config.php or as a parameter), running
+ * routines in its constructor, and manages flashdata aging.
+ *
+ * @param array Configuration parameters
+ */
+ public function __construct(array $params = array())
+ {
+ log_message('debug', 'CI_Session Class Initialized');
+
+ // Get valid drivers list
+ $CI =& get_instance();
+ $this->valid_drivers = array('Session_native', 'Session_cookie');
+ $key = 'sess_valid_drivers';
+ $drivers = (isset($params[$key])) ? $params[$key] : $CI->config->item($key);
+ if ($drivers)
+ {
+ if ( ! is_array($drivers)) $drivers = array($drivers);
+
+ // Add driver names to valid list
+ foreach ($drivers as $driver)
+ {
+ if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+ {
+ $this->valid_drivers[] = $driver;
+ }
+ }
+ }
+
+ // Get driver to load
+ $key = 'sess_driver';
+ $driver = (isset($params[$key])) ? $params[$key] : $CI->config->item($key);
+ if ( ! $driver) $driver = 'cookie';
+ if ( ! in_array('session_'.strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+ {
+ $this->valid_drivers[] = 'Session_'.$driver;
+ }
+
+ // Save a copy of parameters in case drivers need access
+ $this->params = $params;
+
+ // Load driver and get array reference
+ $this->load_driver($driver);
+
+ // Delete 'old' flashdata (from last request)
+ $this->_flashdata_sweep();
+
+ // Mark all new flashdata as old (data will be deleted before next request)
+ $this->_flashdata_mark();
+
+ // Delete expired tempdata
+ $this->_tempdata_sweep();
+
+ log_message('debug', 'CI_Session routines successfully run');
+ }
+
+ /**
+ * Loads session storage driver
+ *
+ * @param string Driver classname
+ * @return object Loaded driver object
+ */
+ public function load_driver($driver)
+ {
+ // Save reference to most recently loaded driver as library default
+ $this->current = parent::load_driver($driver);
+ $this->userdata =& $this->current->get_userdata();
+ return $this->current;
+ }
+
+ /**
+ * Select default session storage driver
+ *
+ * @param string Driver classname
+ * @return void
+ */
+ public function select_driver($driver)
+ {
+ // Validate driver name
+ $lowername = strtolower(str_replace('CI_', '', $driver));
+ if (in_array($lowername, array_map('strtolower', $this->valid_drivers)))
+ {
+ // See if driver is loaded
+ $child = str_replace($this->lib_name.'_', '', $driver);
+ if (isset($this->$child))
+ {
+ $this->current = $this->$child;
+ $this->userdata =& $this->current->get_userdata();
+ }
+ else
+ {
+ $this->load_driver($driver);
+ }
+ }
+ }
+
+ /**
+ * Destroy the current session
+ *
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Just call destroy on driver
+ $this->current->sess_destroy();
+ }
+
+ /**
+ * Regenerate the current session
+ *
+ * @param boolean Destroy session data flag (default: false)
+ * @return void
+ */
+ public function sess_regenerate($destroy = false)
+ {
+ // Just call regenerate on driver
+ $this->current->sess_regenerate($destroy);
+ }
+
+ /**
+ * Fetch a specific item from the session array
+ *
+ * @param string Item key
+ * @return string Item value or NULL if not found
+ */
+ public function userdata($item)
+ {
+ // Return value or NULL if not found
+ return ( ! isset($this->userdata[$item])) ? NULL : $this->userdata[$item];
+ }
+
+ /**
+ * Fetch all session data
+ *
+ * @return array User data array
+ */
+ public function all_userdata()
+ {
+ // Return entire array
+ return ( ! isset($this->userdata)) ? NULL : $this->userdata;
+ }
+
+ /**
+ * Fetch all flashdata
+ *
+ * @return array Flash data array
+ */
+ public function all_flashdata()
+ {
+ $out = array();
+
+ // loop through all userdata
+ foreach ($this->all_userdata() as $key => $val)
+ {
+ // if it contains flashdata, add it
+ if (strpos($key, self::FLASHDATA_KEY.self::FLASHDATA_OLD) !== FALSE)
+ {
+ $key = str_replace(self::FLASHDATA_KEY.self::FLASHDATA_OLD, '', $key);
+ $out[$key] = $val;
+ }
+ }
+ return $out;
+ }
+
+ /**
+ * Add or change data in the "userdata" array
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @return void
+ */
+ public function set_userdata($newdata = array(), $newval = '')
+ {
+ // Wrap params as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Set each name/value pair
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $this->userdata[$key] = $val;
+ }
+ }
+
+ // Tell driver data changed
+ $this->current->sess_save();
+ }
+
+ /**
+ * Delete a session variable from the "userdata" array
+ *
+ * @param mixed Item name or array of item names
+ * @return void
+ */
+ public function unset_userdata($newdata = array())
+ {
+ // Wrap single name as array
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => '');
+ }
+
+ // Unset each item name
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ unset($this->userdata[$key]);
+ }
+ }
+
+ // Tell driver data changed
+ $this->current->sess_save();
+ }
+
+ /**
+ * Determine if an item exists
+ *
+ * @param string Item name
+ * @return boolean
+ */
+ public function has_userdata($item)
+ {
+ // Check for item name
+ return isset($this->userdata[$item]);
+ }
+
+ /**
+ * Add or change flashdata, only available until the next request
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @return void
+ */
+ public function set_flashdata($newdata = array(), $newval = '')
+ {
+ // Wrap item as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Prepend each key name and set value
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_NEW.$key;
+ $this->set_userdata($flashdata_key, $val);
+ }
+ }
+ }
+
+ /**
+ * Keeps existing flashdata available to next request.
+ *
+ * @param string Item key
+ * @return void
+ */
+ public function keep_flashdata($key)
+ {
+ // 'old' flashdata gets removed. Here we mark all flashdata as 'new' to preserve it from _flashdata_sweep()
+ // Note the function will return NULL if the $key provided cannot be found
+ $old_flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$key;
+ $value = $this->userdata($old_flashdata_key);
+
+ $new_flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_NEW.$key;
+ $this->set_userdata($new_flashdata_key, $value);
+ }
+
+ /**
+ * Fetch a specific flashdata item from the session array
+ *
+ * @param string Item key
+ * @return string
+ */
+ public function flashdata($key)
+ {
+ // Prepend key and retrieve value
+ $flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$key;
+ return $this->userdata($flashdata_key);
+ }
+
+ /**
+ * Add or change tempdata, only available
+ * until expiration
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @param int Item lifetime in seconds or 0 for default
+ * @return void
+ */
+ public function set_tempdata($newdata = array(), $newval = '', $expire = 0)
+ {
+ // Set expiration time
+ $expire = time() + ($expire ? $expire : self::TEMP_EXP_DEF);
+
+ // Wrap item as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Get or create expiration list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if ( ! $expirations)
+ {
+ $expirations = array();
+ }
+
+ // Prepend each key name and set value
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ $expirations[$tempdata_key] = $expire;
+ $this->set_userdata($tempdata_key, $val);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+
+ /**
+ * Delete a temporary session variable from the "userdata" array
+ *
+ * @param mixed Item name or array of item names
+ * @return void
+ */
+ public function unset_tempdata($newdata = array())
+ {
+ // Get expirations list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if ( ! $expirations || ! count($expirations))
+ {
+ // Nothing to do
+ return;
+ }
+
+ // Wrap single name as array
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => '');
+ }
+
+ // Prepend each item name and unset
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ unset($expirations[$tempdata_key]);
+ $this->unset_userdata($tempdata_key);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+
+ /**
+ * Fetch a specific tempdata item from the session array
+ *
+ * @param string Item key
+ * @return string
+ */
+ public function tempdata($key)
+ {
+ // Prepend key and return value
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ return $this->userdata($tempdata_key);
+ }
+
+ /**
+ * Identifies flashdata as 'old' for removal
+ * when _flashdata_sweep() runs.
+ *
+ * @access protected
+ * @return void
+ */
+ protected function _flashdata_mark()
+ {
+ $userdata = $this->all_userdata();
+ foreach ($userdata as $name => $value)
+ {
+ $parts = explode(self::FLASHDATA_NEW, $name);
+ if (is_array($parts) && count($parts) === 2)
+ {
+ $new_name = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$parts[1];
+ $this->set_userdata($new_name, $value);
+ $this->unset_userdata($name);
+ }
+ }
+ }
+
+ /**
+ * Removes all flashdata marked as 'old'
+ *
+ * @access protected
+ * @return void
+ */
+ protected function _flashdata_sweep()
+ {
+ $userdata = $this->all_userdata();
+ foreach ($userdata as $key => $value)
+ {
+ if (strpos($key, self::FLASHDATA_OLD))
+ {
+ $this->unset_userdata($key);
+ }
+ }
+ }
+
+ /**
+ * Removes all expired tempdata
+ *
+ * @access protected
+ * @return void
+ */
+ protected function _tempdata_sweep()
+ {
+ // Get expirations list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if ( ! $expirations || ! count($expirations))
+ {
+ // Nothing to do
+ return;
+ }
+
+ // Unset expired elements
+ $now = time();
+ $userdata = $this->all_userdata();
+ foreach ($userdata as $key => $value)
+ {
+ if (strpos($key, self::FLASHDATA_EXP) && $expirations[$key] < $now)
+ {
+ unset($expirations[$key]);
+ $this->unset_userdata($key);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+}
+// END CI_Session Class
+
+
+/**
+ * CI_Session_driver Class
+ *
+ * Extend this class to make a new CI_Session driver.
+ * A CI_Session driver basically manages an array of name/value pairs with some sort of storage mechanism.
+ * To make a new driver, derive from (extend) CI_Session_driver. Overload the initialize method and read or create
+ * session data. Then implement a save handler to write changed data to storage (sess_save), a destroy handler
+ * to remove deleted data (sess_destroy), and an access handler to expose the data (get_userdata).
+ * Put your driver in the libraries/Session/drivers folder anywhere in the loader paths. This includes the
+ * application directory, the system directory, or any path you add with $CI->load->add_package_path().
+ * Your driver must be named CI_Session_<name>, and your filename must be Session_<name>.php,
+ * preferably also capitalized. (e.g.: CI_Session_foo in libraries/Session/drivers/Session_foo.php)
+ * Then specify the driver by setting 'sess_driver' in your config file or as a parameter when loading the CI_Session
+ * object. (e.g.: $config['sess_driver'] = 'foo'; OR $CI->load->driver('session', array('sess_driver' => 'foo')); )
+ * Already provided are the Native driver, which manages the native PHP $_SESSION array, and
+ * the Cookie driver, which manages the data in a browser cookie, with optional extra storage in a database table.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author ExpressionEngine Dev Team
+ */
+abstract class CI_Session_driver extends CI_Driver {
+ /**
+ * Decorate
+ *
+ * Decorates the child with the parent driver lib's methods and properties
+ *
+ * @param object Parent library object
+ * @return void
+ */
+ public function decorate($parent)
+ {
+ // Call base class decorate first
+ parent::decorate($parent);
+
+ // Call initialize method now that driver has access to $this->_parent
+ $this->initialize();
+ }
+
+ /**
+ * __call magic method
+ *
+ * Handles access to the parent driver library's methods
+ *
+ * @param string Library method name
+ * @param array Method arguments (default: none)
+ * @return mixed
+ */
+ public function __call($method, $args = array())
+ {
+ // Make sure the parent library uses this driver
+ $this->_parent->select_driver(get_class($this));
+ return parent::__call($method, $args);
+ }
+
+ /**
+ * Initialize driver
+ *
+ * @return void
+ */
+ protected function initialize()
+ {
+ // Overload this method to implement initialization
+ }
+
+ /**
+ * Save the session data
+ *
+ * Data in the array has changed - perform any storage synchronization necessary
+ * The child class MUST implement this abstract method!
+ *
+ * @return void
+ */
+ abstract public function sess_save();
+
+ /**
+ * Destroy the current session
+ *
+ * Clean up storage for this session - it has been terminated
+ * The child class MUST implement this abstract method!
+ *
+ * @return void
+ */
+ abstract public function sess_destroy();
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session id
+ * The child class MUST implement this abstract method!
+ *
+ * @param boolean Destroy session data flag (default: false)
+ * @return void
+ */
+ abstract public function sess_regenerate($destroy = false);
+
+ /**
+ * Get a reference to user data array
+ *
+ * Give array access to the main CI_Session object
+ * The child class MUST implement this abstract method!
+ *
+ * @return array Reference to userdata
+ */
+ abstract public function &get_userdata();
+}
+// END CI_Session_driver Class
+
+
+/* End of file Session.php */
+/* Location: ./system/libraries/Session/Session.php */
+?>
diff --git a/system/libraries/Session.php b/system/libraries/Session/drivers/Session_cookie.php
index af38dc366..19ccd417d 100644..100755
--- a/system/libraries/Session.php
+++ b/system/libraries/Session/drivers/Session_cookie.php
@@ -9,7 +9,7 @@
* Licensed under the Open Software License version 3.0
*
* This source file is subject to the Open Software License (OSL 3.0) that is
- * bundled with this package in the files license.txt / license.rst. It is
+ * bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
* http://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to obtain it
@@ -26,7 +26,11 @@
*/
/**
- * Session Class
+ * Cookie-based session management driver
+ *
+ * This is the CI_Session functionality, as written by EllisLab, abstracted out to a driver.
+ * I have done a little updating for PHP5, and made minor changes to extract this functionality from
+ * the public interface (now in the Session Library), but effectively this code is unchanged.
*
* @package CodeIgniter
* @subpackage Libraries
@@ -34,8 +38,7 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/sessions.html
*/
-class CI_Session {
-
+class CI_Session_cookie extends CI_Session_driver {
/**
* Whether to encrypt the session cookie
*
@@ -142,20 +145,12 @@ class CI_Session {
public $encryption_key = '';
/**
- * String to indicate flash data cookies
- *
- * @var string
- */
- public $flashdata_key = 'flash';
-
- /**
* Timezone to use for the current time
*
* @var string
*/
public $time_reference = 'local';
-
/**
* Session data
*
@@ -178,31 +173,31 @@ class CI_Session {
public $now;
/**
- * Session Constructor
+ * Initialize session driver object
*
- * The constructor runs the session routines automatically
- * whenever the class is instantiated.
- *
- * @param array
+ * @access protected
* @return void
*/
- public function __construct($params = array())
+ protected function initialize()
{
- log_message('debug', 'Session Class Initialized');
-
// Set the super object to a local variable for use throughout the class
$this->CI =& get_instance();
// Set all the session preferences, which can either be set
- // manually via the $params array above or via the config file
- foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
+ // manually via the $params array or via the config file
+ foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration',
+ 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path',
+ 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'sess_time_to_update', 'time_reference', 'cookie_prefix',
+ 'encryption_key') as $key)
{
- $this->$key = isset($params[$key]) ? $params[$key] : $this->CI->config->item($key);
+ $this->$key = isset($this->_parent->params[$key]) ? $this->_parent->params[$key] :
+ $this->CI->config->item($key);
}
if ($this->encryption_key === '')
{
- show_error('In order to use the Session class you are required to set an encryption key in your config file.');
+ show_error('In order to use the Cookie Session driver you are required to set an encryption key '.
+ 'in your config file.');
}
// Load the string helper so we can use the strip_slashes() function
@@ -220,8 +215,8 @@ class CI_Session {
$this->CI->load->database();
}
- // Set the "now" time. Can either be GMT or server time, based on the
- // config prefs. We use this to set the "last activity" time
+ // Set the "now" time. Can either be GMT or server time, based on the config prefs.
+ // We use this to set the "last activity" time
$this->now = $this->_get_time();
// Set the session length. If the session expiration is
@@ -236,40 +231,138 @@ class CI_Session {
// Run the Session routine. If a session doesn't exist we'll
// create a new one. If it does, we'll update it.
- if ( ! $this->sess_read())
+ if ( ! $this->_sess_read())
{
- $this->sess_create();
+ $this->_sess_create();
}
else
{
- $this->sess_update();
+ $this->_sess_update();
}
- // Delete 'old' flashdata (from last request)
- $this->_flashdata_sweep();
-
- // Mark all new flashdata as old (data will be deleted before next request)
- $this->_flashdata_mark();
-
// Delete expired sessions if necessary
$this->_sess_gc();
+ }
+
+ /**
+ * Write the session data
+ *
+ * @return void
+ */
+ public function sess_save()
+ {
+ // Are we saving custom data to the DB? If not, all we do is update the cookie
+ if ($this->sess_use_database === FALSE)
+ {
+ $this->_set_cookie();
+ return;
+ }
+
+ // set the custom userdata, the session data we will set in a second
+ $custom_userdata = $this->all_userdata();
+ $cookie_userdata = array();
+
+ // Before continuing, we need to determine if there is any custom data to deal with.
+ // Let's determine this by removing the default indexes to see if there's anything left in the array
+ // and set the session data while we're at it
+ foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
+ {
+ unset($custom_userdata[$val]);
+ $cookie_userdata[$val] = $this->userdata[$val];
+ }
- log_message('debug', 'Session routines successfully run');
+ // Did we find any custom data? If not, we turn the empty array into a string
+ // since there's no reason to serialize and store an empty array in the DB
+ if (count($custom_userdata) === 0)
+ {
+ $custom_userdata = '';
+ }
+ else
+ {
+ // Serialize the custom data array so we can store it
+ $custom_userdata = $this->_serialize($custom_userdata);
+ }
+
+ // Run the update query
+ $this->CI->db->where('session_id', $this->userdata['session_id']);
+ $this->CI->db->update($this->sess_table_name,
+ array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
+
+ // Write the cookie. Notice that we manually pass the cookie data array to the
+ // _set_cookie() function. Normally that function will store $this->userdata, but
+ // in this case that array contains custom data, which we do not want in the cookie.
+ $this->_set_cookie($cookie_userdata);
}
- // --------------------------------------------------------------------
+ /**
+ * Destroy the current session
+ *
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Kill the session DB row
+ if ($this->sess_use_database === TRUE && $this->has_userdata('session_id'))
+ {
+ $this->CI->db->where('session_id', $this->userdata['session_id']);
+ $this->CI->db->delete($this->sess_table_name);
+ }
+
+ // Kill the cookie
+ $this->_setcookie($this->sess_cookie_name, addslashes(serialize(array())), ($this->now - 31500000),
+ $this->cookie_path, $this->cookie_domain, 0);
+
+ // Kill session data
+ $this->userdata = array();
+ }
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session id
+ *
+ * @param boolean Destroy session data flag (default: false)
+ * @return void
+ */
+ public function sess_regenerate($destroy = false)
+ {
+ // Check destroy flag
+ if ($destroy)
+ {
+ // Destroy old session and create new one
+ $this->sess_destroy();
+ $this->_sess_create();
+ }
+ else
+ {
+ // Just force an update to recreate the id
+ $this->_sess_update(true);
+ }
+ }
+
+ /**
+ * Get a reference to user data array
+ *
+ * @return array - Reference to userdata
+ */
+ public function &get_userdata()
+ {
+ // Return reference to array
+ return $this->userdata;
+ }
/**
* Fetch the current session data if it exists
*
+ * @access protected
* @return bool
*/
- public function sess_read()
+ protected function _sess_read()
{
// Fetch the cookie
$session = $this->CI->input->cookie($this->sess_cookie_name);
- // No cookie? Goodbye cruel world!...
+ // No cookie? Goodbye cruel world!...
if ($session === NULL)
{
log_message('debug', 'A session cookie was not found.');
@@ -288,9 +381,10 @@ class CI_Session {
$session = substr($session, 0, strlen($session)-32);
// Does the md5 hash match? This is to prevent manipulation of session data in userspace
- if ($hash !== md5($session.$this->encryption_key))
+ if ($hash !== md5($session.$this->encryption_key))
{
- log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
+ log_message('error', 'The session cookie data did not match what was expected. '.
+ 'This could be a possible hacking attempt.');
$this->sess_destroy();
return FALSE;
}
@@ -300,7 +394,8 @@ class CI_Session {
$session = $this->_unserialize($session);
// Is the session data we unserialized an array with the correct format?
- if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity']))
+ if ( ! is_array($session) || ! isset($session['session_id'], $session['ip_address'], $session['user_agent'],
+ $session['last_activity']))
{
$this->sess_destroy();
return FALSE;
@@ -321,7 +416,8 @@ class CI_Session {
}
// Does the User Agent Match?
- if ($this->sess_match_useragent === TRUE && trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120)))
+ if ($this->sess_match_useragent === TRUE &&
+ trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120)))
{
$this->sess_destroy();
return FALSE;
@@ -351,7 +447,7 @@ class CI_Session {
return FALSE;
}
- // Is there custom data? If so, add it to the main session array
+ // Is there custom data? If so, add it to the main session array
$row = $query->row();
if ( ! empty($row->user_data))
{
@@ -374,65 +470,13 @@ class CI_Session {
return TRUE;
}
- // --------------------------------------------------------------------
-
- /**
- * Write the session data
- *
- * @return void
- */
- public function sess_write()
- {
- // Are we saving custom data to the DB? If not, all we do is update the cookie
- if ($this->sess_use_database === FALSE)
- {
- $this->_set_cookie();
- return;
- }
-
- // set the custom userdata, the session data we will set in a second
- $custom_userdata = $this->userdata;
- $cookie_userdata = array();
-
- // Before continuing, we need to determine if there is any custom data to deal with.
- // Let's determine this by removing the default indexes to see if there's anything left in the array
- // and set the session data while we're at it
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- unset($custom_userdata[$val]);
- $cookie_userdata[$val] = $this->userdata[$val];
- }
-
- // Did we find any custom data? If not, we turn the empty array into a string
- // since there's no reason to serialize and store an empty array in the DB
- if (count($custom_userdata) === 0)
- {
- $custom_userdata = '';
- }
- else
- {
- // Serialize the custom data array so we can store it
- $custom_userdata = $this->_serialize($custom_userdata);
- }
-
- // Run the update query
- $this->CI->db->where('session_id', $this->userdata['session_id']);
- $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
-
- // Write the cookie. Notice that we manually pass the cookie data array to the
- // _set_cookie() function. Normally that function will store $this->userdata, but
- // in this case that array contains custom data, which we do not want in the cookie.
- $this->_set_cookie($cookie_userdata);
- }
-
- // --------------------------------------------------------------------
-
/**
* Create a new session
*
+ * @access protected
* @return void
*/
- public function sess_create()
+ protected function _sess_create()
{
$sessid = '';
do
@@ -445,12 +489,12 @@ class CI_Session {
$sessid .= $this->CI->input->ip_address();
$this->userdata = array(
- 'session_id' => md5(uniqid($sessid, TRUE)),
- 'ip_address' => $this->CI->input->ip_address(),
- 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
- 'last_activity' => $this->now,
- 'user_data' => ''
- );
+ 'session_id' => md5(uniqid($sessid, TRUE)),
+ 'ip_address' => $this->CI->input->ip_address(),
+ 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
+ 'last_activity' => $this->now,
+ 'user_data' => ''
+ );
// Save the data to the DB if needed
if ($this->sess_use_database === TRUE)
@@ -462,17 +506,17 @@ class CI_Session {
$this->_set_cookie();
}
- // --------------------------------------------------------------------
-
/**
* Update an existing session
*
+ * @access protected
+ * @param boolean Force update flag (default: false)
* @return void
*/
- public function sess_update()
+ protected function _sess_update($force = FALSE)
{
- // We only update the session every five minutes by default
- if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
+ // We only update the session every five minutes by default (unless forced)
+ if ( ! $force && ($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
{
return;
}
@@ -481,9 +525,7 @@ class CI_Session {
// by pushing all userdata to the cookie.
$cookie_data = NULL;
- /* Changing the session ID during an AJAX call causes problems,
- * so we'll only update our last_activity
- */
+ // Changing the session ID during an AJAX call causes problems, so we'll only update our last_activity
if ($this->CI->input->is_ajax_request())
{
$this->userdata['last_activity'] = $this->now;
@@ -533,254 +575,23 @@ class CI_Session {
$cookie_data[$val] = $this->userdata[$val];
}
- $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
+ $this->CI->db->query($this->CI->db->update_string($this->sess_table_name,
+ array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
}
// Write the cookie
$this->_set_cookie($cookie_data);
}
- // --------------------------------------------------------------------
-
- /**
- * Destroy the current session
- *
- * @return void
- */
- public function sess_destroy()
- {
- // Kill the session DB row
- if ($this->sess_use_database === TRUE && isset($this->userdata['session_id']))
- {
- $this->CI->db->where('session_id', $this->userdata['session_id']);
- $this->CI->db->delete($this->sess_table_name);
- }
-
- // Kill the cookie
- setcookie(
- $this->sess_cookie_name,
- addslashes(serialize(array())),
- ($this->now - 31500000),
- $this->cookie_path,
- $this->cookie_domain,
- 0
- );
-
- // Kill session data
- $this->userdata = array();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch a specific item from the session array
- *
- * @param string
- * @return string
- */
- public function userdata($item)
- {
- return isset($this->userdata[$item]) ? $this->userdata[$item] : NULL;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch all session data
- *
- * @return array
- */
- public function all_userdata()
- {
- return $this->userdata;
- }
-
- // --------------------------------------------------------------------------
-
- /**
- * Fetch all flashdata
- *
- * @return array
- */
- public function all_flashdata()
- {
- $out = array();
-
- // loop through all userdata
- foreach ($this->all_userdata() as $key => $val)
- {
- // if it contains flashdata, add it
- if (strpos($key, 'flash:old:') !== FALSE)
- {
- $out[$key] = $val;
- }
- }
- return $out;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Add or change data in the "userdata" array
- *
- * @param mixed
- * @param string
- * @return void
- */
- public function set_userdata($newdata = array(), $newval = '')
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => $newval);
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- $this->userdata[$key] = $val;
- }
- }
-
- $this->sess_write();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete a session variable from the "userdata" array
- *
- * @param array
- * @return void
- */
- public function unset_userdata($newdata = array())
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => '');
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- unset($this->userdata[$key]);
- }
- }
-
- $this->sess_write();
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Add or change flashdata, only available
- * until the next request
- *
- * @param mixed
- * @param string
- * @return void
- */
- public function set_flashdata($newdata = array(), $newval = '')
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => $newval);
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- $this->set_userdata($this->flashdata_key.':new:'.$key, $val);
- }
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Keeps existing flashdata available to next request.
- *
- * @param string
- * @return void
- */
- public function keep_flashdata($key)
- {
- // 'old' flashdata gets removed. Here we mark all
- // flashdata as 'new' to preserve it from _flashdata_sweep()
- // Note the function will return NULL if the $key
- // provided cannot be found
- $value = $this->userdata($this->flashdata_key.':old:'.$key);
-
- $this->set_userdata($this->flashdata_key.':new:'.$key, $value);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Fetch a specific flashdata item from the session array
- *
- * @param string
- * @return string
- */
- public function flashdata($key)
- {
- return $this->userdata($this->flashdata_key.':old:'.$key);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Identifies flashdata as 'old' for removal
- * when _flashdata_sweep() runs.
- *
- * @return void
- */
- protected function _flashdata_mark()
- {
- $userdata = $this->all_userdata();
- foreach ($userdata as $name => $value)
- {
- $parts = explode(':new:', $name);
- if (is_array($parts) && count($parts) === 2)
- {
- $this->set_userdata($this->flashdata_key.':old:'.$parts[1], $value);
- $this->unset_userdata($name);
- }
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Removes all flashdata marked as 'old'
- *
- * @return void
- */
- protected function _flashdata_sweep()
- {
- $userdata = $this->all_userdata();
- foreach ($userdata as $key => $value)
- {
- if (strpos($key, ':old:'))
- {
- $this->unset_userdata($key);
- }
- }
-
- }
-
- // --------------------------------------------------------------------
-
/**
* Get the "now" time
*
- * @return string
+ * @access protected
+ * @return int Time
*/
protected function _get_time()
{
- if ($this->time_reference === 'local' OR $this->time_reference === date_default_timezone_get())
+ if ($this->time_reference === 'local' || $this->time_reference === date_default_timezone_get())
{
return time();
}
@@ -791,15 +602,14 @@ class CI_Session {
return mktime($hour, $minute, $second, $month, $day, $year);
}
- // --------------------------------------------------------------------
-
/**
* Write the session cookie
*
- * @param mixed
+ * @access protected
+ * @param array Cookie name/value pairs
* @return void
*/
- protected function _set_cookie($cookie_data = NULL)
+ protected function _set_cookie(array $cookie_data = NULL)
{
if (is_null($cookie_data))
{
@@ -822,18 +632,31 @@ class CI_Session {
$expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
// Set the cookie
- setcookie(
- $this->sess_cookie_name,
- $cookie_data,
- $expire,
- $this->cookie_path,
- $this->cookie_domain,
- $this->cookie_secure,
- $this->cookie_httponly
- );
+ $this->_setcookie($this->sess_cookie_name, $cookie_data, $expire, $this->cookie_path, $this->cookie_domain,
+ $this->cookie_secure, $this->cookie_httponly);
}
- // --------------------------------------------------------------------
+ /**
+ * Set a cookie with the system
+ *
+ * This abstraction of the setcookie call allows overriding for unit testing
+ *
+ * @access protected
+ * @param string Cookie name
+ * @param string Cookie value
+ * @param int Expiration time
+ * @param string Cookie path
+ * @param string Cookie domain
+ * @param bool Secure connection flag
+ * @param bool HTTP protocol only flag
+ * @return void
+ */
+ protected function _setcookie($name, $value = '', $expire = 0, $path = '', $domain = '', $secure = false,
+ $httponly = false)
+ {
+ // Set the cookie
+ setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
+ }
/**
* Serialize an array
@@ -841,8 +664,9 @@ class CI_Session {
* This function first converts any slashes found in the array to a temporary
* marker, so when it gets unserialized the slashes will be preserved
*
- * @param array
- * @return string
+ * @access protected
+ * @param mixed Data to serialize
+ * @return string Serialized data
*/
protected function _serialize($data)
{
@@ -862,8 +686,9 @@ class CI_Session {
*
* This function converts any slashes found into a temporary marker
*
- * @param string
- * @param string
+ * @access protected
+ * @param string Value
+ * @param string Key
* @return void
*/
protected function _escape_slashes(&$val, $key)
@@ -874,16 +699,15 @@ class CI_Session {
}
}
- // --------------------------------------------------------------------
-
/**
* Unserialize
*
* This function unserializes a data string, then converts any
* temporary slash markers back to actual slashes
*
- * @param array
- * @return string
+ * @access protected
+ * @param mixed Data to unserialize
+ * @return mixed Unserialized data
*/
protected function _unserialize($data)
{
@@ -898,15 +722,14 @@ class CI_Session {
return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data;
}
- // --------------------------------------------------------------------
-
/**
* Unescape slashes
*
* This function converts any slash markers back into actual slashes
*
- * @param string
- * @param string
+ * @access protected
+ * @param string Value
+ * @param string Key
* @return void
*/
protected function _unescape_slashes(&$val, $key)
@@ -917,14 +740,13 @@ class CI_Session {
}
}
- // --------------------------------------------------------------------
-
/**
* Garbage collection
*
* This deletes expired session rows from database
* if the probability percentage is met
*
+ * @access protected
* @return void
*/
protected function _sess_gc()
@@ -948,8 +770,7 @@ class CI_Session {
log_message('debug', 'Session garbage collection performed.');
}
}
-
}
-/* End of file Session.php */
-/* Location: ./system/libraries/Session.php */ \ No newline at end of file
+/* End of file Session_cookie.php */
+/* Location: ./system/libraries/Session/drivers/Session_cookie.php */
diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php
new file mode 100755
index 000000000..27db942eb
--- /dev/null
+++ b/system/libraries/Session/drivers/Session_native.php
@@ -0,0 +1,187 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author ExpressionEngine Dev Team
+ * @copyright Copyright (c) 2008 - 2010, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 2.0
+ * @filesource
+ */
+
+
+/**
+ * Native PHP session management driver
+ *
+ * This is the driver that uses the native PHP $_SESSION array through the Session driver library.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author ExpressionEngine Dev Team
+ */
+class CI_Session_native extends CI_Session_driver {
+ /**
+ * Initialize session driver object
+ *
+ * @access protected
+ * @return void
+ */
+ protected function initialize()
+ {
+ // Get config parameters
+ $config = array();
+ $CI =& get_instance();
+ foreach (array('sess_cookie_name', 'sess_expire_on_close', 'sess_expiration', 'sess_match_ip',
+ 'sess_match_useragent', 'cookie_prefix', 'cookie_path', 'cookie_domain') as $key)
+ {
+ $config[$key] = isset($this->_parent->params[$key]) ? $this->_parent->params[$key] : $CI->config->item($key);
+ }
+
+ // Set session name, if specified
+ if ($config['sess_cookie_name'])
+ {
+ $name = $config['sess_cookie_name'];
+ if ($config['cookie_prefix'])
+ {
+ // Prepend cookie prefix
+ $name = $config['cookie_prefix'].$name;
+ }
+ session_name($name);
+ }
+
+ // Set expiration, path, and domain
+ $expire = 7200;
+ $path = '/';
+ $domain = '';
+ if ($config['sess_expiration'] !== FALSE)
+ {
+ // Default to 2 years if expiration is "0"
+ $expire = ($config['sess_expiration'] == 0) ? (60*60*24*365*2) : $config['sess_expiration'];
+ }
+ if ($config['cookie_path'])
+ {
+ // Use specified path
+ $path = $config['cookie_path'];
+ }
+ if ($config['cookie_domain'])
+ {
+ // Use specified domain
+ $domain = $config['cookie_domain'];
+ }
+ session_set_cookie_params($config['sess_expire_on_close'] ? 0 : $expire, $path, $domain);
+
+ // Start session
+ session_start();
+
+ // Check session expiration, ip, and agent
+ $now = time();
+ $destroy = FALSE;
+ if (isset($_SESSION['last_activity']) && ($_SESSION['last_activity'] + $expire) < $now)
+ {
+ // Expired - destroy
+ $destroy = TRUE;
+ }
+ else if ($config['sess_match_ip'] == TRUE && isset($_SESSION['ip_address']) &&
+ $_SESSION['ip_address'] != $CI->input->ip_address())
+ {
+ // IP doesn't match - destroy
+ $destroy = TRUE;
+ }
+ else if ($config['sess_match_useragent'] == TRUE && isset($_SESSION['user_agent']) &&
+ $_SESSION['user_agent'] != trim(substr($CI->input->user_agent(), 0, 50)))
+ {
+ // Agent doesn't match - destroy
+ $destroy = TRUE;
+ }
+
+ // Destroy expired or invalid session
+ if ($destroy)
+ {
+ // Clear old session and start new
+ $this->sess_destroy();
+ session_start();
+ }
+
+ // Set activity time
+ $_SESSION['last_activity'] = $now;
+
+ // Set matching values as required
+ if ($config['sess_match_ip'] == TRUE && !isset($_SESSION['ip_address']))
+ {
+ // Store user IP address
+ $_SESSION['ip_address'] = $CI->input->ip_address();
+ }
+ if ($config['sess_match_useragent'] == TRUE && !isset($_SESSION['user_agent']))
+ {
+ // Store user agent string
+ $_SESSION['user_agent'] = trim(substr($CI->input->user_agent(), 0, 50));
+ }
+ }
+
+ /**
+ * Save the session data
+ *
+ * @access public
+ * @return void
+ */
+ public function sess_save()
+ {
+ // Nothing to do - changes to $_SESSION are automatically saved
+ }
+
+ /**
+ * Destroy the current session
+ *
+ * @access public
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Cleanup session
+ $_SESSION = array();
+ $name = session_name();
+ if (isset($_COOKIE[$name]))
+ {
+ // Clear session cookie
+ $params = session_get_cookie_params();
+ setcookie($name, '', time() - 42000, $params['path'], $params['domain']);
+ unset($_COOKIE[$name]);
+ }
+ session_destroy();
+ }
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session id
+ *
+ * @access public
+ * @param boolean Destroy session data flag (default: FALSE)
+ * @return void
+ */
+ public function sess_regenerate($destroy = FALSE)
+ {
+ // Just regenerate id, passing destroy flag
+ session_regenerate_id($destroy);
+ }
+
+ /**
+ * Get a reference to user data array
+ *
+ * @access public
+ * @return array Reference to userdata
+ */
+ public function &get_userdata()
+ {
+ // Just return reference to $_SESSION
+ return $_SESSION;
+ }
+}
+
+/* End of file Session_native.php */
+/* Location: ./system/libraries/Session/drivers/Session_native.php */