diff options
Diffstat (limited to 'library/vendor/Zend/Session.php')
-rw-r--r-- | library/vendor/Zend/Session.php | 895 |
1 files changed, 895 insertions, 0 deletions
diff --git a/library/vendor/Zend/Session.php b/library/vendor/Zend/Session.php new file mode 100644 index 0000000..a1ed797 --- /dev/null +++ b/library/vendor/Zend/Session.php @@ -0,0 +1,895 @@ +<?php + +/** + * Zend Framework + * + * LICENSE + * + * This source file is subject to the new BSD license that is bundled + * with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://framework.zend.com/license/new-bsd + * 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 license@zend.com so we can send you a copy immediately. + * + * @category Zend + * @package Zend_Session + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @version $Id$ + * @since Preview Release 0.2 + */ + + +/** + * @see Zend_Session_Abstract + */ + +/** + * @see Zend_Session_Namespace + */ + +/** + * @see Zend_Session_SaveHandler_Interface + */ + + +/** + * Zend_Session + * + * @category Zend + * @package Zend_Session + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +class Zend_Session extends Zend_Session_Abstract +{ + /** + * Whether or not Zend_Session is being used with unit tests + * + * @internal + * @var bool + */ + public static $_unitTestEnabled = false; + + /** + * $_throwStartupException + * + * @var bool|bitset This could also be a combiniation of error codes to catch + */ + protected static $_throwStartupExceptions = true; + + /** + * Check whether or not the session was started + * + * @var bool + */ + private static $_sessionStarted = false; + + /** + * Whether or not the session id has been regenerated this request. + * + * Id regeneration state + * <0 - regenerate requested when session is started + * 0 - do nothing + * >0 - already called session_regenerate_id() + * + * @var int + */ + private static $_regenerateIdState = 0; + + /** + * Private list of php's ini values for ext/session + * null values will default to the php.ini value, otherwise + * the value below will overwrite the default ini value, unless + * the user has set an option explicity with setOptions() + * + * @var array + */ + private static $_defaultOptions = array( + 'save_path' => null, + 'name' => null, /* this should be set to a unique value for each application */ + 'save_handler' => null, + //'auto_start' => null, /* intentionally excluded (see manual) */ + 'gc_probability' => null, + 'gc_divisor' => null, + 'gc_maxlifetime' => null, + 'serialize_handler' => null, + 'cookie_lifetime' => null, + 'cookie_path' => null, + 'cookie_domain' => null, + 'cookie_secure' => null, + 'cookie_httponly' => null, + 'use_cookies' => null, + 'use_only_cookies' => 'on', + 'referer_check' => null, + 'entropy_file' => null, + 'entropy_length' => null, + 'cache_limiter' => null, + 'cache_expire' => null, + 'use_trans_sid' => null, + 'bug_compat_42' => null, + 'bug_compat_warn' => null, + 'hash_function' => null, + 'hash_bits_per_character' => null + ); + + /** + * List of options pertaining to Zend_Session that can be set by developers + * using Zend_Session::setOptions(). This list intentionally duplicates + * the individual declaration of static "class" variables by the same names. + * + * @var array + */ + private static $_localOptions = array( + 'strict' => '_strict', + 'remember_me_seconds' => '_rememberMeSeconds', + 'throw_startup_exceptions' => '_throwStartupExceptions' + ); + + /** + * Whether or not write close has been performed. + * + * @var bool + */ + private static $_writeClosed = false; + + /** + * Whether or not session id cookie has been deleted + * + * @var bool + */ + private static $_sessionCookieDeleted = false; + + /** + * Whether or not session has been destroyed via session_destroy() + * + * @var bool + */ + private static $_destroyed = false; + + /** + * Whether or not session must be initiated before usage + * + * @var bool + */ + private static $_strict = false; + + /** + * Default number of seconds the session will be remembered for when asked to be remembered + * + * @var int + */ + private static $_rememberMeSeconds = 1209600; // 2 weeks + + /** + * Whether the default options listed in Zend_Session::$_localOptions have been set + * + * @var bool + */ + private static $_defaultOptionsSet = false; + + /** + * A reference to the set session save handler + * + * @var Zend_Session_SaveHandler_Interface + */ + private static $_saveHandler = null; + + + /** + * Constructor overriding - make sure that a developer cannot instantiate + */ + protected function __construct() + { + } + + + /** + * setOptions - set both the class specified + * + * @param array $userOptions - pass-by-keyword style array of <option name, option value> pairs + * @throws Zend_Session_Exception + * @return void + */ + public static function setOptions(array $userOptions = array()) + { + // set default options on first run only (before applying user settings) + if (!self::$_defaultOptionsSet) { + foreach (self::$_defaultOptions as $defaultOptionName => $defaultOptionValue) { + if (isset(self::$_defaultOptions[$defaultOptionName])) { + ini_set("session.$defaultOptionName", $defaultOptionValue); + } + } + + self::$_defaultOptionsSet = true; + } + + // set the options the user has requested to set + foreach ($userOptions as $userOptionName => $userOptionValue) { + + $userOptionName = strtolower($userOptionName); + + // set the ini based values + if (array_key_exists($userOptionName, self::$_defaultOptions)) { + ini_set("session.$userOptionName", $userOptionValue); + } + elseif (isset(self::$_localOptions[$userOptionName])) { + self::${self::$_localOptions[$userOptionName]} = $userOptionValue; + } + else { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception("Unknown option: $userOptionName = $userOptionValue"); + } + } + } + + /** + * getOptions() + * + * @param string $optionName OPTIONAL + * @return array|string + */ + public static function getOptions($optionName = null) + { + $options = array(); + foreach (ini_get_all('session') as $sysOptionName => $sysOptionValues) { + $options[substr($sysOptionName, 8)] = $sysOptionValues['local_value']; + } + foreach (self::$_localOptions as $localOptionName => $localOptionMemberName) { + $options[$localOptionName] = self::${$localOptionMemberName}; + } + + if ($optionName) { + if (array_key_exists($optionName, $options)) { + return $options[$optionName]; + } + return null; + } + + return $options; + } + + /** + * setSaveHandler() - Session Save Handler assignment + * + * @param Zend_Session_SaveHandler_Interface $interface + * @throws Zend_Session_Exception When the session_set_save_handler call fails + * @return void + */ + public static function setSaveHandler(Zend_Session_SaveHandler_Interface $saveHandler) + { + self::$_saveHandler = $saveHandler; + + if (self::$_unitTestEnabled) { + return; + } + + $result = session_set_save_handler( + array(&$saveHandler, 'open'), + array(&$saveHandler, 'close'), + array(&$saveHandler, 'read'), + array(&$saveHandler, 'write'), + array(&$saveHandler, 'destroy'), + array(&$saveHandler, 'gc') + ); + + if (!$result) { + throw new Zend_Session_Exception('Unable to set session handler'); + } + } + + + /** + * getSaveHandler() - Get the session Save Handler + * + * @return Zend_Session_SaveHandler_Interface + */ + public static function getSaveHandler() + { + return self::$_saveHandler; + } + + + /** + * regenerateId() - Regenerate the session id. Best practice is to call this after + * session is started. If called prior to session starting, session id will be regenerated + * at start time. + * + * @throws Zend_Session_Exception + * @return void + */ + public static function regenerateId() + { + if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception("You must call " . __CLASS__ . '::' . __FUNCTION__ . + "() before any output has been sent to the browser; output started in {$filename}/{$linenum}"); + } + + if ( !self::$_sessionStarted ) { + self::$_regenerateIdState = -1; + } else { + if (!self::$_unitTestEnabled) { + session_regenerate_id(true); + } + self::$_regenerateIdState = 1; + } + } + + + /** + * rememberMe() - Write a persistent cookie that expires after a number of seconds in the future. If no number of + * seconds is specified, then this defaults to self::$_rememberMeSeconds. Due to clock errors on end users' systems, + * large values are recommended to avoid undesirable expiration of session cookies. + * + * @param int $seconds OPTIONAL specifies TTL for cookie in seconds from present time + * @return void + */ + public static function rememberMe($seconds = null) + { + $seconds = (int) $seconds; + $seconds = ($seconds > 0) ? $seconds : self::$_rememberMeSeconds; + + self::rememberUntil($seconds); + } + + + /** + * forgetMe() - Write a volatile session cookie, removing any persistent cookie that may have existed. The session + * would end upon, for example, termination of a web browser program. + * + * @return void + */ + public static function forgetMe() + { + self::rememberUntil(0); + } + + + /** + * rememberUntil() - This method does the work of changing the state of the session cookie and making + * sure that it gets resent to the browser via regenerateId() + * + * @param int $seconds + * @return void + */ + public static function rememberUntil($seconds = 0) + { + if (self::$_unitTestEnabled) { + self::regenerateId(); + return; + } + + $cookieParams = session_get_cookie_params(); + + session_set_cookie_params( + $seconds, + $cookieParams['path'], + $cookieParams['domain'], + $cookieParams['secure'] + ); + + // normally "rememberMe()" represents a security context change, so should use new session id + self::regenerateId(); + } + + + /** + * sessionExists() - whether or not a session exists for the current request + * + * @return bool + */ + public static function sessionExists() + { + if ((bool)ini_get('session.use_cookies') == true && isset($_COOKIE[session_name()])) { + return true; + } elseif ((bool)ini_get('session.use_only_cookies') == false && isset($_REQUEST[session_name()])) { + return true; + } elseif (self::$_unitTestEnabled) { + return true; + } + + return false; + } + + + /** + * Whether or not session has been destroyed via session_destroy() + * + * @return bool + */ + public static function isDestroyed() + { + return self::$_destroyed; + } + + + /** + * start() - Start the session. + * + * @param bool|array $options OPTIONAL Either user supplied options, or flag indicating if start initiated automatically + * @throws Zend_Session_Exception + * @return void + */ + public static function start($options = false) + { + // Check to see if we've been passed an invalid session ID + if ( self::getId() && !self::_checkId(self::getId()) ) { + // Generate a valid, temporary replacement + self::setId(md5(self::getId())); + // Force a regenerate after session is started + self::$_regenerateIdState = -1; + } + + if (self::$_sessionStarted && self::$_destroyed) { + throw new Zend_Session_Exception('The session was explicitly destroyed during this request, attempting to re-start is not allowed.'); + } + + if (self::$_sessionStarted) { + return; // already started + } + + // make sure our default options (at the least) have been set + if (!self::$_defaultOptionsSet) { + self::setOptions(is_array($options) ? $options : array()); + } + + // In strict mode, do not allow auto-starting Zend_Session, such as via "new Zend_Session_Namespace()" + if (self::$_strict && $options === true) { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception('You must explicitly start the session with Zend_Session::start() when session options are set to strict.'); + } + + $filename = $linenum = null; + if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception("Session must be started before any output has been sent to the browser;" + . " output started in {$filename}/{$linenum}"); + } + + // See http://www.php.net/manual/en/ref.session.php for explanation + if (!self::$_unitTestEnabled && defined('SID')) { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception('session has already been started by session.auto-start or session_start()'); + } + + /** + * Hack to throw exceptions on start instead of php errors + * @see http://framework.zend.com/issues/browse/ZF-1325 + */ + + $errorLevel = (is_int(self::$_throwStartupExceptions)) ? self::$_throwStartupExceptions : E_ALL; + + /** @see Zend_Session_Exception */ + if (!self::$_unitTestEnabled) { + + if (self::$_throwStartupExceptions) { + set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), $errorLevel); + } + + $startedCleanly = session_start(); + + if (self::$_throwStartupExceptions) { + restore_error_handler(); + } + + if (!$startedCleanly || Zend_Session_Exception::$sessionStartError != null) { + if (self::$_throwStartupExceptions) { + set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), $errorLevel); + } + session_write_close(); + if (self::$_throwStartupExceptions) { + restore_error_handler(); + throw new Zend_Session_Exception(__CLASS__ . '::' . __FUNCTION__ . '() - ' . Zend_Session_Exception::$sessionStartError); + } + } + } + + parent::$_readable = true; + parent::$_writable = true; + self::$_sessionStarted = true; + if (self::$_regenerateIdState === -1) { + self::regenerateId(); + } + + // run validators if they exist + if (isset($_SESSION['__ZF']['VALID'])) { + self::_processValidators(); + } + + self::_processStartupMetadataGlobal(); + } + + /** + * Perform a hash-bits check on the session ID + * + * @param string $id Session ID + * @return bool + */ + protected static function _checkId($id) + { + $saveHandler = ini_get('session.save_handler'); + if ($saveHandler == 'cluster') { // Zend Server SC, validate only after last dash + $dashPos = strrpos($id, '-'); + if ($dashPos) { + $id = substr($id, $dashPos + 1); + } + } + + $hashBitsPerChar = ini_get('session.hash_bits_per_character'); + if (!$hashBitsPerChar) { + $hashBitsPerChar = 5; // the default value + } + switch($hashBitsPerChar) { + case 4: $pattern = '^[0-9a-f]*$'; break; + case 5: $pattern = '^[0-9a-v]*$'; break; + case 6: $pattern = '^[0-9a-zA-Z-,]*$'; break; + } + return preg_match('#'.$pattern.'#', $id); + } + + + /** + * _processGlobalMetadata() - this method initizes the sessions GLOBAL + * metadata, mostly global data expiration calculations. + * + * @return void + */ + private static function _processStartupMetadataGlobal() + { + // process global metadata + if (isset($_SESSION['__ZF'])) { + + // expire globally expired values + foreach ($_SESSION['__ZF'] as $namespace => $namespace_metadata) { + + // Expire Namespace by Time (ENT) + if (isset($namespace_metadata['ENT']) && ($namespace_metadata['ENT'] > 0) && (time() > $namespace_metadata['ENT']) ) { + unset($_SESSION[$namespace]); + unset($_SESSION['__ZF'][$namespace]); + } + + // Expire Namespace by Global Hop (ENGH) if it wasnt expired above + if (isset($_SESSION['__ZF'][$namespace]) && isset($namespace_metadata['ENGH']) && $namespace_metadata['ENGH'] >= 1) { + + $_SESSION['__ZF'][$namespace]['ENGH']--; + + if ($_SESSION['__ZF'][$namespace]['ENGH'] === 0) { + if (isset($_SESSION[$namespace])) { + parent::$_expiringData[$namespace] = $_SESSION[$namespace]; + unset($_SESSION[$namespace]); + } + unset($_SESSION['__ZF'][$namespace]); + } + } + + // Expire Namespace Variables by Time (ENVT) + if (isset($namespace_metadata['ENVT'])) { + foreach ($namespace_metadata['ENVT'] as $variable => $time) { + if (time() > $time) { + unset($_SESSION[$namespace][$variable]); + unset($_SESSION['__ZF'][$namespace]['ENVT'][$variable]); + } + } + if (empty($_SESSION['__ZF'][$namespace]['ENVT'])) { + unset($_SESSION['__ZF'][$namespace]['ENVT']); + } + } + + // Expire Namespace Variables by Global Hop (ENVGH) + if (isset($namespace_metadata['ENVGH'])) { + foreach ($namespace_metadata['ENVGH'] as $variable => $hops) { + $_SESSION['__ZF'][$namespace]['ENVGH'][$variable]--; + + if ($_SESSION['__ZF'][$namespace]['ENVGH'][$variable] === 0) { + if (isset($_SESSION[$namespace][$variable])) { + parent::$_expiringData[$namespace][$variable] = $_SESSION[$namespace][$variable]; + unset($_SESSION[$namespace][$variable]); + } + unset($_SESSION['__ZF'][$namespace]['ENVGH'][$variable]); + } + } + if (empty($_SESSION['__ZF'][$namespace]['ENVGH'])) { + unset($_SESSION['__ZF'][$namespace]['ENVGH']); + } + } + + if (isset($namespace) && empty($_SESSION['__ZF'][$namespace])) { + unset($_SESSION['__ZF'][$namespace]); + } + } + } + + if (isset($_SESSION['__ZF']) && empty($_SESSION['__ZF'])) { + unset($_SESSION['__ZF']); + } + } + + + /** + * isStarted() - convenience method to determine if the session is already started. + * + * @return bool + */ + public static function isStarted() + { + return self::$_sessionStarted; + } + + + /** + * isRegenerated() - convenience method to determine if session_regenerate_id() + * has been called during this request by Zend_Session. + * + * @return bool + */ + public static function isRegenerated() + { + return ( (self::$_regenerateIdState > 0) ? true : false ); + } + + + /** + * getId() - get the current session id + * + * @return string + */ + public static function getId() + { + return session_id(); + } + + + /** + * setId() - set an id to a user specified id + * + * @throws Zend_Session_Exception + * @param string $id + * @return void + */ + public static function setId($id) + { + if (!self::$_unitTestEnabled && defined('SID')) { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception('The session has already been started. The session id must be set first.'); + } + + if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception("You must call ".__CLASS__.'::'.__FUNCTION__. + "() before any output has been sent to the browser; output started in {$filename}/{$linenum}"); + } + + if (!is_string($id) || $id === '') { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception('You must provide a non-empty string as a session identifier.'); + } + + session_id($id); + } + + + /** + * registerValidator() - register a validator that will attempt to validate this session for + * every future request + * + * @param Zend_Session_Validator_Interface $validator + * @return void + */ + public static function registerValidator(Zend_Session_Validator_Interface $validator) + { + $validator->setup(); + } + + + /** + * stop() - Disable write access. Optionally disable read (not implemented). + * + * @return void + */ + public static function stop() + { + parent::$_writable = false; + } + + + /** + * writeClose() - Shutdown the sesssion, close writing and detach $_SESSION from the back-end storage mechanism. + * This will complete the internal data transformation on this request. + * + * @param bool $readonly - OPTIONAL remove write access (i.e. throw error if Zend_Session's attempt writes) + * @return void + */ + public static function writeClose($readonly = true) + { + if (self::$_unitTestEnabled) { + return; + } + + if (self::$_writeClosed) { + return; + } + + if ($readonly) { + parent::$_writable = false; + } + + session_write_close(); + self::$_writeClosed = true; + } + + + /** + * destroy() - This is used to destroy session data, and optionally, the session cookie itself + * + * @param bool $remove_cookie - OPTIONAL remove session id cookie, defaults to true (remove cookie) + * @param bool $readonly - OPTIONAL remove write access (i.e. throw error if Zend_Session's attempt writes) + * @return void + */ + public static function destroy($remove_cookie = true, $readonly = true) + { + if (self::$_unitTestEnabled) { + return; + } + + if (self::$_destroyed) { + return; + } + + if ($readonly) { + parent::$_writable = false; + } + + session_destroy(); + self::$_destroyed = true; + + if ($remove_cookie) { + self::expireSessionCookie(); + } + } + + + /** + * expireSessionCookie() - Sends an expired session id cookie, causing the client to delete the session cookie + * + * @return void + */ + public static function expireSessionCookie() + { + if (self::$_unitTestEnabled) { + return; + } + + if (self::$_sessionCookieDeleted) { + return; + } + + self::$_sessionCookieDeleted = true; + + if (isset($_COOKIE[session_name()])) { + $cookie_params = session_get_cookie_params(); + + setcookie( + session_name(), + false, + 315554400, // strtotime('1980-01-01'), + $cookie_params['path'], + $cookie_params['domain'], + $cookie_params['secure'] + ); + } + } + + + /** + * _processValidator() - internal function that is called in the existence of VALID metadata + * + * @throws Zend_Session_Exception + * @return void + */ + private static function _processValidators() + { + foreach ($_SESSION['__ZF']['VALID'] as $validator_name => $valid_data) { + if (!class_exists($validator_name)) { + Zend_Loader::loadClass($validator_name); + } + $validator = new $validator_name; + if ($validator->validate() === false) { + /** @see Zend_Session_Validator_Exception */ + throw new Zend_Session_Validator_Exception("This session is not valid according to {$validator_name}."); + } + } + } + + + /** + * namespaceIsset() - check to see if a namespace is set + * + * @param string $namespace + * @return bool + */ + public static function namespaceIsset($namespace) + { + return parent::_namespaceIsset($namespace); + } + + + /** + * namespaceUnset() - unset a namespace or a variable within a namespace + * + * @param string $namespace + * @throws Zend_Session_Exception + * @return void + */ + public static function namespaceUnset($namespace) + { + parent::_namespaceUnset($namespace); + Zend_Session_Namespace::resetSingleInstance($namespace); + } + + + /** + * namespaceGet() - get all variables in a namespace + * Deprecated: Use getIterator() in Zend_Session_Namespace. + * + * @param string $namespace + * @return array + */ + public static function namespaceGet($namespace) + { + return parent::_namespaceGetAll($namespace); + } + + + /** + * getIterator() - return an iteratable object for use in foreach and the like, + * this completes the IteratorAggregate interface + * + * @throws Zend_Session_Exception + * @return ArrayObject + */ + public static function getIterator() + { + if (parent::$_readable === false) { + /** @see Zend_Session_Exception */ + throw new Zend_Session_Exception(parent::_THROW_NOT_READABLE_MSG); + } + + $spaces = array(); + if (isset($_SESSION)) { + $spaces = array_keys($_SESSION); + foreach($spaces as $key => $space) { + if (!strncmp($space, '__', 2) || !is_array($_SESSION[$space])) { + unset($spaces[$key]); + } + } + } + + return new ArrayObject(array_merge($spaces, array_keys(parent::$_expiringData))); + } + + + /** + * isWritable() - returns a boolean indicating if namespaces can write (use setters) + * + * @return bool + */ + public static function isWritable() + { + return parent::$_writable; + } + + + /** + * isReadable() - returns a boolean indicating if namespaces can write (use setters) + * + * @return bool + */ + public static function isReadable() + { + return parent::$_readable; + } + +} |