Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/site/cake/libs/session.php
diff options
context:
space:
mode:
Diffstat (limited to 'site/cake/libs/session.php')
-rw-r--r--site/cake/libs/session.php777
1 files changed, 777 insertions, 0 deletions
diff --git a/site/cake/libs/session.php b/site/cake/libs/session.php
new file mode 100644
index 0000000..cab0498
--- /dev/null
+++ b/site/cake/libs/session.php
@@ -0,0 +1,777 @@
+<?php
+/* SVN FILE: $Id: session.php 6305 2008-01-02 02:33:56Z phpnut $ */
+/**
+ * Session class for Cake.
+ *
+ * Cake abstracts the handling of sessions.
+ * There are several convenient methods to access session information.
+ * This class is the implementation of those methods.
+ * They are mostly used by the Session Component.
+ *
+ * PHP versions 4 and 5
+ *
+ * CakePHP(tm) : Rapid Development Framework <http://www.cakephp.org/>
+ * Copyright 2005-2008, Cake Software Foundation, Inc.
+ * 1785 E. Sahara Avenue, Suite 490-204
+ * Las Vegas, Nevada 89104
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @filesource
+ * @copyright Copyright 2005-2008, Cake Software Foundation, Inc.
+ * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
+ * @package cake
+ * @subpackage cake.cake.libs
+ * @since CakePHP(tm) v .0.10.0.1222
+ * @version $Revision: 6305 $
+ * @modifiedby $LastChangedBy: phpnut $
+ * @lastmodified $Date: 2008-01-01 20:33:56 -0600 (Tue, 01 Jan 2008) $
+ * @license http://www.opensource.org/licenses/mit-license.php The MIT License
+ */
+/**
+ * Database name for cake sessions.
+ *
+ */
+ if (!defined('CAKE_SESSION_TABLE')) {
+ define('CAKE_SESSION_TABLE', 'cake_sessions');
+ }
+
+ if (CAKE_SESSION_SAVE === 'database') {
+ uses('model' . DS . 'connection_manager');
+ }
+ uses('set');
+/**
+ * Session class for Cake.
+ *
+ * Cake abstracts the handling of sessions. There are several convenient methods to access session information.
+ * This class is the implementation of those methods. They are mostly used by the Session Component.
+ *
+ * @package cake
+ * @subpackage cake.cake.libs
+ */
+class CakeSession extends Object {
+/**
+ * True if the Session is still valid
+ *
+ * @var boolean
+ * @access public
+ */
+ var $valid = false;
+/**
+ * Error messages for this session
+ *
+ * @var array
+ * @access public
+ */
+ var $error = false;
+/**
+ * User agent string
+ *
+ * @var string
+ * @access protected
+ */
+ var $_userAgent = '';
+/**
+ * Path to where the session is active.
+ *
+ * @var string
+ * @access public
+ */
+ var $path = false;
+/**
+ * Error number of last occurred error
+ *
+ * @var integer
+ * @access public
+ */
+ var $lastError = null;
+/**
+ * CAKE_SECURITY setting, "high", "medium", or "low".
+ *
+ * @var string
+ * @access public
+ */
+ var $security = null;
+/**
+ * Start time for this session.
+ *
+ * @var integer
+ * @access public
+ */
+ var $time = false;
+/**
+ * Time when this session becomes invalid.
+ *
+ * @var integer
+ * @access public
+ */
+ var $sessionTime = false;
+/**
+ * Keeps track of keys to watch for writes on
+ *
+ * @var array
+ * @access public
+ */
+ var $watchKeys = array();
+/**
+ * Current Session id
+ *
+ * @var string
+ * @access public
+ */
+ var $id = null;
+/**
+ * Constructor.
+ *
+ * @param string $base The base path for the Session
+ * @param boolean $start Should session be started right now
+ * @access public
+ */
+ function __construct($base = null, $start = true) {
+ if (Configure::read('Session.checkAgent') === true) {
+ if (env('HTTP_USER_AGENT') != null) {
+ $this->_userAgent = md5(env('HTTP_USER_AGENT') . CAKE_SESSION_STRING);
+ }
+ }
+ $this->time = time();
+
+ if ($start === true) {
+ $this->host = env('HTTP_HOST');
+
+ if (empty($base) || strpos($base, '?') === 0 || strpos($base, 'index.php') === 0) {
+ $this->path = '/';
+ } else {
+ $this->path = $base;
+ }
+
+ if (strpos($this->host, ':') !== false) {
+ $this->host = substr($this->host, 0, strpos($this->host, ':'));
+ }
+
+ $this->sessionTime = $this->time + (Security::inactiveMins() * CAKE_SESSION_TIMEOUT);
+ $this->security = CAKE_SECURITY;
+ }
+ parent::__construct();
+ }
+/**
+ * Starts the Session.
+ *
+ * @param string $cookieLifeTime How long for the cookie
+ * @return boolean True if variable is there
+ * @access public
+ */
+ /** BEGIN MOZILLA PATCH (@author rdoherty@mozilla.com)**/
+ function start($cookieLifeTime = null) {
+ if (function_exists('session_write_close')) {
+ session_write_close();
+ }
+
+ $this->__initSession($cookieLifeTime);
+ /** END MOZILLA PATCH **/
+ return $this->__startSession();
+ }
+/**
+ * Determine if Session has been started.
+ *
+ * @access public
+ */
+ function started(){
+ if (isset($_SESSION)) {
+ return true;
+ }
+ return false;
+ }
+/**
+ * Returns true if given variable is set in session.
+ *
+ * @param string $name Variable name to check for
+ * @return boolean True if variable is there
+ * @access public
+ */
+ function check($name) {
+ $var = $this->__validateKeys($name);
+ if (empty($var)) {
+ return false;
+ }
+ $result = Set::extract($_SESSION, $var);
+ return isset($result);
+ }
+/**
+ *
+ * @param id $name string
+ * @return string Session id
+ * @access public
+ */
+ function id($id = null) {
+ if ($id) {
+ $this->id = $id;
+ session_id($this->id);
+ }
+ if (isset($_SESSION)) {
+ return session_id();
+ } else {
+ return $this->id;
+ }
+ }
+/**
+ * Temp method until we are able to remove the last eval().
+ * Builds an expression to fetch a session variable with specified name.
+ *
+ * @param string $name Name of variable (in dot notation)
+ * @access private
+ */
+ function __sessionVarNames($name) {
+ if (is_string($name) && preg_match("/^[ 0-9a-zA-Z._-]*$/", $name)) {
+ if (strpos($name, ".")) {
+ $names = explode(".", $name);
+ } else {
+ $names = array($name);
+ }
+ $expression = "\$_SESSION";
+ foreach ($names as $item) {
+ $expression .= is_numeric($item) ? "[$item]" : "['$item']";
+ }
+ return $expression;
+ }
+ $this->__setError(3, "$name is not a string");
+ return false;
+ }
+/**
+ * Removes a variable from session.
+ *
+ * @param string $name Session variable to remove
+ * @return boolean Success
+ * @access public
+ */
+ function del($name) {
+ if ($this->check($name)) {
+ if ($var = $this->__validateKeys($name)) {
+ if (in_array($var, $this->watchKeys)) {
+ trigger_error('Deleting session key {' . $var . '}', E_USER_NOTICE);
+ }
+ $this->__overwrite($_SESSION, Set::remove($_SESSION, $var));
+ return ($this->check($var) == false);
+ }
+ }
+ $this->__setError(2, "$name doesn't exist");
+ return false;
+ }
+/**
+ * Used to write new data to _SESSION, since PHP doesn't like us setting the _SESSION var itself
+ *
+ * @param array $old Set of old variables => values
+ * @param array $new New set of variable => value
+ * @access private
+ */
+ function __overwrite(&$old, $new) {
+ if(!empty($old)) {
+ foreach ($old as $key => $var) {
+ if (!isset($new[$key])) {
+ unset($old[$key]);
+ }
+ }
+ }
+ foreach ($new as $key => $var) {
+ $old[$key] = $var;
+ }
+ }
+/**
+ * Return error description for given error number.
+ *
+ * @param integer $errorNumber Error to set
+ * @return string Error as string
+ * @access private
+ */
+ function __error($errorNumber) {
+ if (!is_array($this->error) || !array_key_exists($errorNumber, $this->error)) {
+ return false;
+ } else {
+ return $this->error[$errorNumber];
+ }
+ }
+/**
+ * Returns last occurred error as a string, if any.
+ *
+ * @return mixed Error description as a string, or false.
+ * @access public
+ */
+ function error() {
+ if ($this->lastError) {
+ return $this->__error($this->lastError);
+ } else {
+ return false;
+ }
+ }
+/**
+ * Returns true if session is valid.
+ *
+ * @return boolean Success
+ * @access public
+ */
+ function valid() {
+ if ($this->read('Config')) {
+ if (Configure::read('Session.checkAgent') === false || $this->_userAgent == $this->read("Config.userAgent") && $this->time <= $this->read("Config.time")) {
+ if ($this->error === false) {
+ $this->valid = true;
+ }
+ } else {
+ $this->valid = false;
+ $this->__setError(1, "Session Highjacking Attempted !!!");
+ }
+ }
+ return $this->valid;
+ }
+/**
+ * Returns given session variable, or all of them, if no parameters given.
+ *
+ * @param mixed $name The name of the session variable (or a path as sent to Set.extract)
+ * @return mixed The value of the session variable
+ * @access public
+ */
+ function read($name = null) {
+ if (is_null($name)) {
+ return $this->__returnSessionVars();
+ }
+ if (empty($name)) {
+ return false;
+ }
+ $result = Set::extract($_SESSION, $name);
+
+ if (!is_null($result)) {
+ return $result;
+ }
+ $this->__setError(2, "$name doesn't exist");
+ return null;
+ }
+/**
+ * Returns all session variables.
+ *
+ * @return mixed Full $_SESSION array, or false on error.
+ * @access private
+ */
+ function __returnSessionVars() {
+ if (!empty($_SESSION)) {
+ return $_SESSION;
+ }
+ $this->__setError(2, "No Session vars set");
+ return false;
+ }
+/**
+ * Tells Session to write a notification when a certain session path or subpath is written to
+ *
+ * @param mixed $var The variable path to watch
+ * @access public
+ */
+ function watch($var) {
+ $var = $this->__validateKeys($var);
+ if (empty($var)) {
+ return false;
+ }
+ $this->watchKeys[] = $var;
+ }
+/**
+ * Tells Session to stop watching a given key path
+ *
+ * @param mixed $var The variable path to watch
+ * @access public
+ */
+ function ignore($var) {
+ $var = $this->__validateKeys($var);
+ if (!in_array($var, $this->watchKeys)) {
+ return;
+ }
+ foreach ($this->watchKeys as $i => $key) {
+ if ($key == $var) {
+ unset($this->watchKeys[$i]);
+ $this->watchKeys = array_values($this->watchKeys);
+ return;
+ }
+ }
+ }
+/**
+ * Writes value to given session variable name.
+ *
+ * @param mixed $name Name of variable
+ * @param string $value Value to write
+ * @return boolean True if the write was successful, false if the write failed
+ * @access public
+ */
+ function write($name, $value) {
+ $var = $this->__validateKeys($name);
+
+ if (empty($var)) {
+ return false;
+ }
+ if (in_array($var, $this->watchKeys)) {
+ trigger_error('Writing session key {' . $var . '}: ' . print_r($value), E_USER_NOTICE);
+ }
+ $this->__overwrite($_SESSION, Set::insert($_SESSION, $var, $value));
+ return (Set::extract($_SESSION, $var) === $value);
+ }
+/**
+ * Helper method to destroy invalid sessions.
+ *
+ * @access public
+ */
+ function destroy() {
+ $sessionpath = session_save_path();
+ if (empty($sessionpath)) {
+ $sessionpath = "/tmp";
+ }
+
+ if (isset($_COOKIE[session_name()])) {
+ setcookie(CAKE_SESSION_COOKIE, '', time() - 42000, $this->path);
+ }
+
+ $_SESSION = array();
+ $file = $sessionpath . DS . "sess_" . session_id();
+ @session_destroy();
+ @unlink ($file);
+ $this->__construct($this->path);
+ $this->renew();
+ }
+/**
+ * Helper method to initialize a session, based on Cake core settings.
+ *
+ * @param int $cookieLifeTime how long the cookie should live in seconds
+ * @access private
+ */
+ /** BEGIN MOZILLA PATCH (@author rdoherty@mozilla.com)**/
+ function __initSession($cookieLifeTime = null) {
+ /** END MOZILLA PATCH (@author clouserw@mozilla.com)**/
+ switch($this->security) {
+ case 'high':
+ $this->cookieLifeTime = 0;
+ if (function_exists('ini_set')) {
+ ini_set('session.referer_check', $this->host);
+ }
+ break;
+ case 'medium':
+ $this->cookieLifeTime = 7 * 86400;
+ if (function_exists('ini_set')) {
+ ini_set('session.referer_check', $this->host);
+ }
+ break;
+ case 'low':
+ default:
+ $this->cookieLifeTime = 788940000;
+ break;
+ }
+
+ /** BEGIN MOZILLA PATCH (@author rdoherty@mozilla.com)**/
+ if($cookieLifeTime) {
+ $this->cookieLifeTime = $cookieLifeTime;
+ }
+ /** END MOZILLA PATCH **/
+
+ switch(CAKE_SESSION_SAVE) {
+ case 'cake':
+ if (!isset($_SESSION)) {
+ if (function_exists('ini_set')) {
+ ini_set('session.use_trans_sid', 0);
+ ini_set('url_rewriter.tags', '');
+ ini_set('session.serialize_handler', 'php');
+ ini_set('session.use_cookies', 1);
+ ini_set('session.name', CAKE_SESSION_COOKIE);
+ ini_set('session.cookie_lifetime', $this->cookieLifeTime);
+ ini_set('session.cookie_path', $this->path);
+ ini_set('session.auto_start', 0);
+ ini_set('session.save_path', TMP . 'sessions');
+ }
+ }
+ break;
+ case 'database':
+ if (!isset($_SESSION)) {
+ if (function_exists('ini_set')) {
+ ini_set('session.use_trans_sid', 0);
+ ini_set('url_rewriter.tags', '');
+ ini_set('session.save_handler', 'user');
+ ini_set('session.serialize_handler', 'php');
+ ini_set('session.use_cookies', 1);
+ ini_set('session.name', CAKE_SESSION_COOKIE);
+ ini_set('session.cookie_lifetime', $this->cookieLifeTime);
+ ini_set('session.cookie_path', $this->path);
+ ini_set('session.auto_start', 0);
+ }
+ }
+ session_set_save_handler(array('CakeSession','__open'),
+ array('CakeSession', '__close'),
+ array('CakeSession', '__read'),
+ array('CakeSession', '__write'),
+ array('CakeSession', '__destroy'),
+ array('CakeSession', '__gc'));
+ break;
+ case 'php':
+ if (!isset($_SESSION)) {
+ if (function_exists('ini_set')) {
+ ini_set('session.use_trans_sid', 0);
+ ini_set('session.name', CAKE_SESSION_COOKIE);
+ ini_set('session.cookie_lifetime', $this->cookieLifeTime);
+ ini_set('session.cookie_path', $this->path);
+ }
+ }
+ break;
+ default:
+ if (!isset($_SESSION)) {
+ $config = CONFIGS . CAKE_SESSION_SAVE . '.php';
+
+ if (is_file($config)) {
+ require_once ($config);
+ }
+ }
+ break;
+ }
+ }
+/**
+ * Helper method to start a session
+ *
+ * @access private
+ */
+ function __startSession() {
+ if (headers_sent()) {
+ if (!isset($_SESSION)) {
+ $_SESSION = array();
+ }
+ return false;
+ } elseif (!isset($_SESSION)) {
+ session_cache_limiter ("must-revalidate");
+ session_start();
+ header ('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
+ return true;
+ } else {
+ return true;
+ }
+ }
+/**
+ * Helper method to create a new session.
+ *
+ * @access protected
+ */
+ function _checkValid() {
+ if ($this->read('Config')) {
+ if (Configure::read('Session.checkAgent') === false || $this->_userAgent == $this->read("Config.userAgent") && $this->time <= $this->read("Config.time")) {
+ $time = $this->read("Config.time");
+ $this->write("Config.time", $this->sessionTime);
+
+ if ($this->security === 'high') {
+ $check = $this->read("Config.timeout");
+ $check = $check - 1;
+ $this->write("Config.timeout", $check);
+
+ if (time() > ($time - (Security::inactiveMins() * CAKE_SESSION_TIMEOUT) + 2) || $check < 1) {
+ $this->renew();
+ $this->write('Config.timeout', 10);
+ }
+ }
+ $this->valid = true;
+ } else {
+ $this->destroy();
+ $this->valid = false;
+ $this->__setError(1, "Session Highjacking Attempted !!!");
+ }
+ } else {
+ srand ((double)microtime() * 1000000);
+ $this->write("Config.userAgent", $this->_userAgent);
+ $this->write("Config.time", $this->sessionTime);
+ $this->write('Config.rand', rand());
+ $this->write('Config.timeout', 10);
+ $this->valid = true;
+ $this->__setError(1, "Session is valid");
+ }
+ }
+/**
+ * Helper method to restart a session.
+ *
+ * @access private
+ */
+ function __regenerateId() {
+ $oldSessionId = session_id();
+ if ($oldSessionId) {
+ $sessionpath = session_save_path();
+ if (empty($sessionpath)) {
+ $sessionpath = "/tmp";
+ }
+
+ if (isset($_COOKIE[session_name()])) {
+ setcookie(CAKE_SESSION_COOKIE, '', time() - 42000, $this->path);
+ }
+ session_regenerate_id();
+ $newSessid = session_id();
+
+ if (function_exists('session_write_close')) {
+ session_write_close();
+ }
+ $this->__initSession();
+ session_id($oldSessionId);
+ session_start();
+ session_destroy();
+ $file = $sessionpath . DS . "sess_$oldSessionId";
+ @unlink($file);
+ $this->__initSession();
+ session_id($newSessid);
+ session_start();
+ }
+ }
+/**
+ * Restarts this session.
+ *
+ * @access public
+ */
+ function renew() {
+ /** BEGIN MOZILLA PATCH (@author fwenzel@mozilla.com) **/
+ // if we (legitimately) regenerate the session ID during a POST request,
+ // we need to remember the old ID, so we can check the secret submitted
+ // by the user against it.
+ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ global $csrf_old_session_id;
+ $csrf_old_session_id = session_id();
+ }
+ /** END MOZILLA PATCH **/
+ $this->__regenerateId();
+ }
+/**
+ * Validate that the $name is in correct dot notation
+ * example: $name = 'ControllerName.key';
+ *
+ * @param string $name Session key names as string.
+ * @return mixed false is $name is not correct format, or $name if it is correct
+ * @access private
+ */
+ function __validateKeys($name) {
+ if (is_string($name) && preg_match("/^[ 0-9a-zA-Z._-]*$/", $name)) {
+ return $name;
+ }
+ $this->__setError(3, "$name is not a string");
+ return false;
+ }
+/**
+ * Helper method to set an internal error message.
+ *
+ * @param integer $errorNumber Number of the error
+ * @param string $errorMessage Description of the error
+ * @access private
+ */
+ function __setError($errorNumber, $errorMessage) {
+ if ($this->error === false) {
+ $this->error = array();
+ }
+ $this->error[$errorNumber] = $errorMessage;
+ $this->lastError = $errorNumber;
+ }
+/**
+ * Method called on open of a database session.
+ *
+ * @return boolean Success
+ * @access private
+ */
+ function __open() {
+ return true;
+ }
+/**
+ * Method called on close of a database session.
+ *
+ * @return boolean Success
+ * @access private
+ */
+ function __close() {
+ $probability = mt_rand(1, 150);
+ if ($probability <= 3) {
+ CakeSession::__gc();
+ }
+ return true;
+ }
+/**
+ * Method used to read from a database session.
+ *
+ * @param mixed $key The key of the value to read
+ * @return mixed The value of the key or false if it does not exist
+ * @access private
+ */
+ function __read($key) {
+ $db =& ConnectionManager::getDataSource('default');
+ $table = $db->fullTableName(CAKE_SESSION_TABLE, false);
+ $row = $db->query("SELECT " . $db->name($table.'.data') . " FROM " . $db->name($table) . " WHERE " . $db->name($table.'.id') . " = " . $db->value($key), false);
+
+ if ($row && !isset($row[0][$table]) && isset($row[0][0])) {
+ $table = 0;
+ }
+
+ if ($row && $row[0][$table]['data']) {
+ return $row[0][$table]['data'];
+ } else {
+ return false;
+ }
+ }
+/**
+ * Helper function called on write for database sessions.
+ *
+ * @param mixed $key The name of the var
+ * @param mixed $value The value of the var
+ * @return boolean Success
+ * @access private
+ */
+ function __write($key, $value) {
+ $db =& ConnectionManager::getDataSource('default');
+ $table = $db->fullTableName(CAKE_SESSION_TABLE);
+
+ switch(CAKE_SECURITY) {
+ case 'high':
+ $factor = 10;
+ break;
+ case 'medium':
+ $factor = 100;
+ break;
+ case 'low':
+ $factor = 300;
+ break;
+ default:
+ $factor = 10;
+ break;
+ }
+ $expires = time() + CAKE_SESSION_TIMEOUT * $factor;
+ $row = $db->query("SELECT COUNT(id) AS count FROM " . $db->name($table) . " WHERE "
+ . $db->name('id') . " = "
+ . $db->value($key), false);
+
+ if ($row[0][0]['count'] > 0) {
+ $db->execute("UPDATE " . $db->name($table) . " SET " . $db->name('data') . " = "
+ . $db->value($value) . ", " . $db->name('expires') . " = "
+ . $db->value($expires) . " WHERE " . $db->name('id') . " = "
+ . $db->value($key));
+ } else {
+ $db->execute("INSERT INTO " . $db->name($table) . " (" . $db->name('data') . ","
+ . $db->name('expires') . "," . $db->name('id')
+ . ") VALUES (" . $db->value($value) . ", " . $db->value($expires) . ", "
+ . $db->value($key) . ")");
+ }
+ return true;
+ }
+/**
+ * Method called on the destruction of a database session.
+ *
+ * @param int $key Key that uniquely identifies session in database
+ * @return boolean Success
+ * @access private
+ */
+ function __destroy($key) {
+ $db =& ConnectionManager::getDataSource('default');
+ $table = $db->fullTableName(CAKE_SESSION_TABLE);
+ $db->execute("DELETE FROM " . $db->name($table) . " WHERE " . $db->name($table.'.id') . " = " . $db->value($key, 'integer'));
+ return true;
+ }
+/**
+ * Helper function called on gc for database sessions.
+ *
+ * @param int $expires Timestamp (defaults to current time)
+ * @return boolean Success
+ * @access private
+ */
+ function __gc($expires = null) {
+ $db =& ConnectionManager::getDataSource('default');
+ $table = $db->fullTableName(CAKE_SESSION_TABLE);
+ $db->execute("DELETE FROM " . $db->name($table) . " WHERE " . $db->name($table.'.expires') . " < ". $db->value(time()));
+ return true;
+ }
+}
+?>