Created
November 24, 2012 00:37
-
-
Save johnathancroom/4137839 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* CodeIgniter | |
* | |
* An open source application development framework for PHP 5.2.4 or newer | |
* | |
* NOTICE OF LICENSE | |
* | |
* 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 | |
* 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 | |
* through the world wide web, please send an email to | |
* [email protected] so we can send you a copy immediately. | |
* | |
* @package CodeIgniter | |
* @author EllisLab Dev Team | |
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) | |
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) | |
* @link http://codeigniter.com | |
* @since Version 2.0 | |
* @filesource | |
*/ | |
defined('BASEPATH') OR exit('No direct script access allowed'); | |
/** | |
* CodeIgniter Session Class | |
* | |
* The user interface defined by EllisLabs, now with puggable drivers to manage different storage mechanisms. | |
* By default, the cookie session driver will load, but the 'sess_driver' config/param item (see above) can be | |
* used to specify the 'native' 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 EllisLab Dev Team | |
* @link http://codeigniter.com/user_guide/libraries/sessions.html | |
*/ | |
class CI_Session extends CI_Driver_Library { | |
/** | |
* Initialization parameters | |
* | |
* @var array | |
*/ | |
public $params = array(); | |
/** | |
* Current driver in use | |
* | |
* @var string | |
*/ | |
protected $current = NULL; | |
/** | |
* User data | |
* | |
* @var array | |
*/ | |
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 | |
* @return void | |
*/ | |
public function __construct(array $params = array()) | |
{ | |
$CI =& get_instance(); | |
// No sessions under CLI | |
if ($CI->input->is_cli_request()) | |
{ | |
return; | |
} | |
log_message('debug', 'CI_Session Class Initialized'); | |
// Get valid drivers list | |
$this->valid_drivers = array( | |
'Session_native', | |
'Session_cookie' | |
); | |
$key = 'sess_valid_drivers'; | |
$drivers = isset($params[$key]) ? $params[$key] : $CI->config->item($key); | |
if ($drivers) | |
{ | |
is_array($drivers) OR $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 and sync userdata | |
$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)) | |
{ | |
// See if driver is already current | |
if ($this->$child !== $this->current) | |
{ | |
// Make driver current and sync userdata | |
$this->current = $this->$child; | |
$this->userdata =& $this->current->get_userdata(); | |
} | |
} | |
else | |
{ | |
// Load new driver | |
$this->load_driver($child); | |
} | |
} | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Destroy the current session | |
* | |
* @return void | |
*/ | |
public function sess_destroy() | |
{ | |
// Just call destroy on driver | |
$this->current->sess_destroy(); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Regenerate the current session | |
* | |
* @param bool Destroy session data flag (default: false) | |
* @return void | |
*/ | |
public function sess_regenerate($destroy = FALSE) | |
{ | |
// Call regenerate on driver and resync userdata | |
$this->current->sess_regenerate($destroy); | |
$this->userdata =& $this->current->get_userdata(); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* 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 isset($this->userdata[$item]) ? $this->userdata[$item] : NULL; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Fetch all session data | |
* | |
* @return array User data array | |
*/ | |
public function all_userdata() | |
{ | |
return isset($this->userdata) ? $this->userdata : NULL; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* 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 (array_keys($newdata) as $key) | |
{ | |
unset($this->userdata[$key]); | |
} | |
} | |
// Tell driver data changed | |
$this->current->sess_save(); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Determine if an item exists | |
* | |
* @param string Item name | |
* @return bool | |
*/ | |
public function has_userdata($item) | |
{ | |
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 mixed Item key | |
* @return void | |
*/ | |
public function keep_flashdata($data) | |
{ | |
// Wrap item as array if singular | |
if (is_string($data)) | |
{ | |
$data = array($data); | |
} | |
foreach($data as $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 (empty($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 (array_keys($newdata) as $key) | |
{ | |
$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. | |
* | |
* @return void | |
*/ | |
protected function _flashdata_mark() | |
{ | |
foreach ($this->all_userdata() as $name => $value) | |
{ | |
$parts = explode(self::FLASHDATA_NEW, $name); | |
if (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' | |
* | |
* @return void | |
*/ | |
protected function _flashdata_sweep() | |
{ | |
$userdata = $this->all_userdata(); | |
foreach (array_keys($userdata) as $key) | |
{ | |
if (strpos($key, self::FLASHDATA_OLD)) | |
{ | |
$this->unset_userdata($key); | |
} | |
} | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Removes all expired tempdata | |
* | |
* @return void | |
*/ | |
protected function _tempdata_sweep() | |
{ | |
// Get expirations list | |
$expirations = $this->userdata(self::EXPIRATION_KEY); | |
if (empty($expirations)) | |
{ | |
// Nothing to do | |
return; | |
} | |
// Unset expired elements | |
$now = time(); | |
$userdata = $this->all_userdata(); | |
foreach (array_keys($userdata) as $key) | |
{ | |
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); | |
} | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* 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 EllisLab Dev Team | |
*/ | |
abstract class CI_Session_driver extends CI_Driver { | |
/** | |
* CI Singleton | |
* | |
* @see get_instance() | |
* @var object | |
*/ | |
protected $CI; | |
// ------------------------------------------------------------------------ | |
/** | |
* Constructor | |
* | |
* Gets the CI singleton, so that individual drivers | |
* don't have to do it separately. | |
* | |
* @return void | |
*/ | |
public function __construct() | |
{ | |
$this->CI =& get_instance(); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* 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 bool 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 of file Session.php */ | |
/* Location: ./system/libraries/Session/Session.php */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment