| <?php |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| class Zend_Session extends Zend_Session_Abstract |
| { |
| |
| |
| |
| |
| |
| |
| public static $_unitTestEnabled = false; |
|
|
| |
| |
| |
| |
| |
| protected static $_throwStartupExceptions = true; |
|
|
| |
| |
| |
| |
| |
| private static $_sessionStarted = false; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private static $_regenerateIdState = 0; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| private static $_defaultOptions = array( |
| 'save_path' => null, |
| 'name' => null, |
| 'save_handler' => null, |
| |
| '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 |
| ); |
|
|
| |
| |
| |
| |
| |
| |
| |
| private static $_localOptions = array( |
| 'strict' => '_strict', |
| 'remember_me_seconds' => '_rememberMeSeconds', |
| 'throw_startup_exceptions' => '_throwStartupExceptions' |
| ); |
|
|
| |
| |
| |
| |
| |
| private static $_writeClosed = false; |
|
|
| |
| |
| |
| |
| |
| private static $_sessionCookieDeleted = false; |
|
|
| |
| |
| |
| |
| |
| private static $_destroyed = false; |
|
|
| |
| |
| |
| |
| |
| private static $_strict = false; |
|
|
| |
| |
| |
| |
| |
| private static $_rememberMeSeconds = 1209600; |
|
|
| |
| |
| |
| |
| |
| private static $_defaultOptionsSet = false; |
|
|
| |
| |
| |
| |
| |
| private static $_saveHandler = null; |
|
|
|
|
| |
| |
| |
| protected function __construct() |
| { |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function setOptions(array $userOptions = array()) |
| { |
| |
| if (!self::$_defaultOptionsSet) { |
| foreach (self::$_defaultOptions as $defaultOptionName => $defaultOptionValue) { |
| if (isset(self::$_defaultOptions[$defaultOptionName])) { |
| @ini_set("session.$defaultOptionName", $defaultOptionValue); |
| } |
| } |
|
|
| self::$_defaultOptionsSet = true; |
| } |
|
|
| |
| foreach ($userOptions as $userOptionName => $userOptionValue) { |
|
|
| $userOptionName = strtolower($userOptionName); |
|
|
| |
| if (array_key_exists($userOptionName, self::$_defaultOptions)) { |
| @ini_set("session.$userOptionName", $userOptionValue); |
| } |
| elseif (isset(self::$_localOptions[$userOptionName])) { |
| self::${self::$_localOptions[$userOptionName]} = $userOptionValue; |
| } |
| else { |
| |
| |
| throw new Zend_Session_Exception("Unknown option: $userOptionName = $userOptionValue"); |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| 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; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public static function setSaveHandler(\SessionHandlerInterface $saveHandler) |
| { |
| self::$_saveHandler = $saveHandler; |
|
|
| if (self::$_unitTestEnabled) { |
| return; |
| } |
|
|
| session_set_save_handler($saveHandler, false); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static function getSaveHandler() |
| { |
| return self::$_saveHandler; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public static function regenerateId() |
| { |
| if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) { |
| |
| |
| 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::rewriteSessionCookieWithSameSiteDirective(); |
| } |
| self::$_regenerateIdState = 1; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| private static function rewriteSessionCookieWithSameSiteDirective() |
| { |
| $headers = headers_list(); |
| $cookieHeader = ''; |
| foreach ($headers as $header) { |
| if (strpos($header, 'Set-Cookie: ' . \Piwik\Session::SESSION_NAME) === 0) { |
| $cookieHeader = $header; |
| break; |
| } |
| } |
|
|
| if (! $cookieHeader) { |
| return; |
| } |
|
|
| if (stripos($cookieHeader, 'SameSite') === false) { |
| $cookieHeader .= '; SameSite=' . \Piwik\Session::getSameSiteCookieValue(); |
| header($cookieHeader); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public static function rememberMe($seconds = null) |
| { |
| $seconds = (int) $seconds; |
| $seconds = ($seconds > 0) ? $seconds : self::$_rememberMeSeconds; |
|
|
| self::rememberUntil($seconds); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| public static function forgetMe() |
| { |
| self::rememberUntil(0); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| 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'] |
| ); |
|
|
| |
| self::regenerateId(); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| 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; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static function isDestroyed() |
| { |
| return self::$_destroyed; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function start($options = false) |
| { |
| 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; |
| } |
|
|
| if (session_status() === PHP_SESSION_ACTIVE) { |
| parent::$_readable = true; |
| parent::$_writable = true; |
| self::$_sessionStarted = true; |
| return; |
| } |
|
|
| |
| if (!self::$_defaultOptionsSet) { |
| self::setOptions(is_array($options) ? $options : array()); |
| } |
|
|
| |
| if (self::$_strict && $options === true) { |
| |
| |
| 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)) { |
| |
| |
| throw new Zend_Session_Exception("Session must be started before any output has been sent to the browser;" |
| . " output started in {$filename}/{$linenum}"); |
| } |
|
|
| |
| |
| |
| |
|
|
| $errorLevel = (is_int(self::$_throwStartupExceptions)) ? self::$_throwStartupExceptions : E_ALL; |
|
|
| |
| 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 || !empty(Zend_Session_Exception::$sessionStartError)) { |
| 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 . ' Warnings: ' . Zend_Session_Exception::$sessionStartWarning); |
| } |
| } |
| } |
|
|
| parent::$_readable = true; |
| parent::$_writable = true; |
| self::$_sessionStarted = true; |
| if (self::$_regenerateIdState === -1) { |
| self::regenerateId(); |
| } else { |
| self::rewriteSessionCookieWithSameSiteDirective(); |
| } |
|
|
| if (isset($_SESSION['data']) && is_string($_SESSION['data'])) { |
| $_SESSION = \Piwik\Common::safe_unserialize(base64_decode($_SESSION['data']), [ |
| \Piwik\Notification::class |
| ]); |
| } |
|
|
| |
| if (isset($_SESSION['__ZF']['VALID'])) { |
| self::_processValidators(); |
| } |
|
|
| self::_processStartupMetadataGlobal(); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| private static function _processStartupMetadataGlobal() |
| { |
| |
| if (isset($_SESSION['__ZF'])) { |
|
|
| |
| foreach ($_SESSION['__ZF'] as $namespace => $namespace_metadata) { |
|
|
| |
| if (isset($namespace_metadata['ENT']) && ($namespace_metadata['ENT'] > 0) && (time() > $namespace_metadata['ENT']) ) { |
| unset($_SESSION[$namespace]); |
| unset($_SESSION['__ZF'][$namespace]); |
| } |
|
|
| |
| 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]); |
| } |
| } |
|
|
| |
| 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']); |
| } |
| } |
|
|
| |
| 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']); |
| } |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static function isStarted() |
| { |
| return self::$_sessionStarted; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| public static function isRegenerated() |
| { |
| return ( (self::$_regenerateIdState > 0) ? true : false ); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static function getId() |
| { |
| return session_id(); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function setId($id) |
| { |
| if (!self::$_unitTestEnabled && defined('SID')) { |
| |
| |
| 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)) { |
| |
| |
| 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 === '') { |
| |
| |
| throw new Zend_Session_Exception('You must provide a non-empty string as a session identifier.'); |
| } |
|
|
| session_id($id); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function registerValidator(Zend_Session_Validator_Interface $validator) |
| { |
| $validator->setup(); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static function stop() |
| { |
| parent::$_writable = false; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function writeClose($readonly = true) |
| { |
| if (self::$_unitTestEnabled) { |
| return; |
| } |
|
|
| if (self::$_writeClosed) { |
| return; |
| } |
|
|
| if ($readonly) { |
| parent::$_writable = false; |
| } |
|
|
| if (isset($_SESSION)) { |
| $sessionBkp = $_SESSION; |
| $_SESSION = self::buildSessionData($_SESSION); |
| } |
|
|
| session_write_close(); |
| self::$_writeClosed = true; |
|
|
| if (isset($sessionBkp)) { |
| $_SESSION = $sessionBkp; |
| } |
| } |
|
|
| public static function buildSessionData(array $data): array |
| { |
| return ['data' => base64_encode(serialize($data))]; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| 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(); |
| } |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| 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(); |
|
|
| \Piwik\Session::writeCookie( |
| session_name(), |
| false, |
| 315554400, // strtotime('1980-01-01'), |
| $cookie_params['path'], |
| $cookie_params['domain'], |
| $cookie_params['secure'], |
| false, |
| \Piwik\Session::getSameSiteCookieValue() |
| ); |
| } |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| 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) { |
| |
| |
| throw new Zend_Session_Exception("This session is not valid according to {$validator_name}."); |
| } |
| } |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| public static function namespaceIsset($namespace) |
| { |
| return parent::_namespaceIsset($namespace); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function namespaceUnset($namespace) |
| { |
| parent::_namespaceUnset($namespace); |
| Zend_Session_Namespace::resetSingleInstance($namespace); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function namespaceGet($namespace) |
| { |
| return parent::_namespaceGetAll($namespace); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function getIterator() |
| { |
| if (parent::$_readable === false) { |
| |
| |
| 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))); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static function isWritable() |
| { |
| return parent::$_writable; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static function isReadable() |
| { |
| return parent::$_readable; |
| } |
|
|
| } |
|
|