diff options
Diffstat (limited to 'applications/core/lib/Zend/Session.php')
| -rw-r--r-- | applications/core/lib/Zend/Session.php | 831 | 
1 files changed, 831 insertions, 0 deletions
| diff --git a/applications/core/lib/Zend/Session.php b/applications/core/lib/Zend/Session.php new file mode 100644 index 0000000..31429de --- /dev/null +++ b/applications/core/lib/Zend/Session.php @@ -0,0 +1,831 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_Session + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Session.php 12722 2008-11-20 20:10:43Z matthew $ + * @since      Preview Release 0.2 + */ + + +/** + * @see Zend_Session_Abstract + */ +require_once 'Zend/Session/Abstract.php'; + +/** + * @see Zend_Session_Namespace + */ +require_once 'Zend/Session/Namespace.php'; + +/** + * @see Zend_Session_SaveHandler_Interface + */ +require_once 'Zend/Session/SaveHandler/Interface.php'; + + +/** + * Zend_Session + * + * @category   Zend + * @package    Zend_Session + * @copyright  Copyright (c) 2005-2008 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; + +    /** +     * 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' +    ); + +    /** +     * 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 */ +                require_once 'Zend/Session/Exception.php'; +                throw new Zend_Session_Exception("Unknown option: $userOptionName = $userOptionValue"); +            } +        } +    } + + +    /** +     * setSaveHandler() - Session Save Handler assignment +     * +     * @param Zend_Session_SaveHandler_Interface $interface +     * @return void +     */ +    public static function setSaveHandler(Zend_Session_SaveHandler_Interface $saveHandler) +    { +        if (self::$_unitTestEnabled) { +            return; +        } + +        session_set_save_handler( +            array(&$saveHandler, 'open'), +            array(&$saveHandler, 'close'), +            array(&$saveHandler, 'read'), +            array(&$saveHandler, 'write'), +            array(&$saveHandler, 'destroy'), +            array(&$saveHandler, 'gc') +            ); +        self::$_saveHandler = $saveHandler; +    } + + +    /** +     * 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 */ +            require_once 'Zend/Session/Exception.php'; +            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 <= 0) { +            if (!self::$_unitTestEnabled) { +                session_regenerate_id(true); +            } +            self::$_regenerateIdState = 1; +        } else { +            /** +             * @todo If we can detect that this requester had no session previously, +             *       then why regenerate the id before the session has started? +             *       Feedback wanted for: +             // +            if (isset($_COOKIE[session_name()]) || (!use only cookies && isset($_REQUEST[session_name()]))) { +                self::$_regenerateIdState = 1; +            } else { +                self::$_regenerateIdState = -1; +            } +            //*/ +            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 $seconds integer - 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 (ini_get('session.use_cookies') == '1' && isset($_COOKIE[session_name()])) { +            return true; +        } elseif (!empty($_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) +    { +        if (self::$_sessionStarted && self::$_destroyed) { +            require_once 'Zend/Session/Exception.php'; +            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 */ +            require_once 'Zend/Session/Exception.php'; +            throw new Zend_Session_Exception('You must explicitly start the session with Zend_Session::start() when session options are set to strict.'); +        } + +        if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) { +            /** @see Zend_Session_Exception */ +            require_once 'Zend/Session/Exception.php'; +            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 */ +            require_once 'Zend/Session/Exception.php'; +            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 +         */ +        /** @see Zend_Session_Exception */ +        if (!self::$_unitTestEnabled) { +            require_once 'Zend/Session/Exception.php'; +            set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), E_ALL); +            session_start(); +            restore_error_handler(); +            if (Zend_Session_Exception::$sessionStartError !== null) { +            set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), E_ALL); +            session_write_close(); +            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(); +    } + + +    /** +     * _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]['ENT']); +                } + +                // Expire Namespace by Global Hop (ENGH) +                if (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]['ENGH']); +                    } +                } + +                // 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 (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 */ +            require_once 'Zend/Session/Exception.php'; +            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 */ +            require_once 'Zend/Session/Exception.php'; +            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 */ +            require_once 'Zend/Session/Exception.php'; +            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() +    { +        if (count($_SESSION['__ZF']['VALID']) > 0) { +            /** +             * @see Zend_Loader +             */ +            require_once 'Zend/Loader.php'; +        } + +        foreach ($_SESSION['__ZF']['VALID'] as $validator_name => $valid_data) { +            Zend_Loader::loadClass($validator_name); +            $validator = new $validator_name; +            if ($validator->validate() === false) { +                /** @see Zend_Session_Exception */ +                require_once 'Zend/Session/Exception.php'; +                throw new Zend_Session_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); +    } + + +    /** +     * 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 */ +            require_once 'Zend/Session/Exception.php'; +            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; +    } + +} | 
