00001 <?php
00002
00028 require_once 'Zend/Session/Abstract.php';
00029
00033 require_once 'Zend/Session/Namespace.php';
00034
00038 require_once 'Zend/Session/SaveHandler/Interface.php';
00039
00040
00049 class Zend_Session extends Zend_Session_Abstract
00050 {
00057 public static $_unitTestEnabled = false;
00058
00064 protected static $_throwStartupExceptions = true;
00065
00071 private static $_sessionStarted = false;
00072
00083 private static $_regenerateIdState = 0;
00084
00093 private static $_defaultOptions = array(
00094 'save_path' => null,
00095 'name' => null,
00096 'save_handler' => null,
00097
00098 'gc_probability' => null,
00099 'gc_divisor' => null,
00100 'gc_maxlifetime' => null,
00101 'serialize_handler' => null,
00102 'cookie_lifetime' => null,
00103 'cookie_path' => null,
00104 'cookie_domain' => null,
00105 'cookie_secure' => null,
00106 'cookie_httponly' => null,
00107 'use_cookies' => null,
00108 'use_only_cookies' => 'on',
00109 'referer_check' => null,
00110 'entropy_file' => null,
00111 'entropy_length' => null,
00112 'cache_limiter' => null,
00113 'cache_expire' => null,
00114 'use_trans_sid' => null,
00115 'bug_compat_42' => null,
00116 'bug_compat_warn' => null,
00117 'hash_function' => null,
00118 'hash_bits_per_character' => null
00119 );
00120
00128 private static $_localOptions = array(
00129 'strict' => '_strict',
00130 'remember_me_seconds' => '_rememberMeSeconds',
00131 'throw_startup_exceptions' => '_throwStartupExceptions'
00132 );
00133
00139 private static $_writeClosed = false;
00140
00146 private static $_sessionCookieDeleted = false;
00147
00153 private static $_destroyed = false;
00154
00160 private static $_strict = false;
00161
00167 private static $_rememberMeSeconds = 1209600;
00168
00174 private static $_defaultOptionsSet = false;
00175
00181 private static $_saveHandler = null;
00182
00183
00187 protected function __construct()
00188 {
00189 }
00190
00191
00199 public static function setOptions(array $userOptions = array())
00200 {
00201
00202 if (!self::$_defaultOptionsSet) {
00203 foreach (self::$_defaultOptions as $defaultOptionName => $defaultOptionValue) {
00204 if (isset(self::$_defaultOptions[$defaultOptionName])) {
00205 ini_set("session.$defaultOptionName", $defaultOptionValue);
00206 }
00207 }
00208
00209 self::$_defaultOptionsSet = true;
00210 }
00211
00212
00213 foreach ($userOptions as $userOptionName => $userOptionValue) {
00214
00215 $userOptionName = strtolower($userOptionName);
00216
00217
00218 if (array_key_exists($userOptionName, self::$_defaultOptions)) {
00219 ini_set("session.$userOptionName", $userOptionValue);
00220 }
00221 elseif (isset(self::$_localOptions[$userOptionName])) {
00222 self::${self::$_localOptions[$userOptionName]} = $userOptionValue;
00223 }
00224 else {
00226 require_once 'Zend/Session/Exception.php';
00227 throw new Zend_Session_Exception("Unknown option: $userOptionName = $userOptionValue");
00228 }
00229 }
00230 }
00231
00238 public static function getOptions($optionName = null)
00239 {
00240 $options = array();
00241 foreach (ini_get_all('session') as $sysOptionName => $sysOptionValues) {
00242 $options[substr($sysOptionName, 8)] = $sysOptionValues['local_value'];
00243 }
00244 foreach (self::$_localOptions as $localOptionName => $localOptionMemberName) {
00245 $options[$localOptionName] = self::${$localOptionMemberName};
00246 }
00247
00248 if ($optionName) {
00249 if (array_key_exists($optionName, $options)) {
00250 return $options[$optionName];
00251 }
00252 return null;
00253 }
00254
00255 return $options;
00256 }
00257
00264 public static function setSaveHandler(Zend_Session_SaveHandler_Interface $saveHandler)
00265 {
00266 self::$_saveHandler = $saveHandler;
00267
00268 if (self::$_unitTestEnabled) {
00269 return;
00270 }
00271
00272 session_set_save_handler(
00273 array(&$saveHandler, 'open'),
00274 array(&$saveHandler, 'close'),
00275 array(&$saveHandler, 'read'),
00276 array(&$saveHandler, 'write'),
00277 array(&$saveHandler, 'destroy'),
00278 array(&$saveHandler, 'gc')
00279 );
00280 }
00281
00282
00288 public static function getSaveHandler()
00289 {
00290 return self::$_saveHandler;
00291 }
00292
00293
00302 public static function regenerateId()
00303 {
00304 if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
00306 require_once 'Zend/Session/Exception.php';
00307 throw new Zend_Session_Exception("You must call " . __CLASS__ . '::' . __FUNCTION__ .
00308 "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
00309 }
00310
00311 if (self::$_sessionStarted && self::$_regenerateIdState <= 0) {
00312 if (!self::$_unitTestEnabled) {
00313 session_regenerate_id(true);
00314 }
00315 self::$_regenerateIdState = 1;
00316 } else {
00328 self::$_regenerateIdState = -1;
00329 }
00330 }
00331
00332
00341 public static function rememberMe($seconds = null)
00342 {
00343 $seconds = (int) $seconds;
00344 $seconds = ($seconds > 0) ? $seconds : self::$_rememberMeSeconds;
00345
00346 self::rememberUntil($seconds);
00347 }
00348
00349
00356 public static function forgetMe()
00357 {
00358 self::rememberUntil(0);
00359 }
00360
00361
00369 public static function rememberUntil($seconds = 0)
00370 {
00371 if (self::$_unitTestEnabled) {
00372 self::regenerateId();
00373 return;
00374 }
00375
00376 $cookieParams = session_get_cookie_params();
00377
00378 session_set_cookie_params(
00379 $seconds,
00380 $cookieParams['path'],
00381 $cookieParams['domain'],
00382 $cookieParams['secure']
00383 );
00384
00385
00386 self::regenerateId();
00387 }
00388
00389
00395 public static function sessionExists()
00396 {
00397 if (ini_get('session.use_cookies') == '1' && isset($_COOKIE[session_name()])) {
00398 return true;
00399 } elseif (!empty($_REQUEST[session_name()])) {
00400 return true;
00401 } elseif (self::$_unitTestEnabled) {
00402 return true;
00403 }
00404
00405 return false;
00406 }
00407
00408
00414 public static function isDestroyed()
00415 {
00416 return self::$_destroyed;
00417 }
00418
00419
00427 public static function start($options = false)
00428 {
00429 if (self::$_sessionStarted && self::$_destroyed) {
00430 require_once 'Zend/Session/Exception.php';
00431 throw new Zend_Session_Exception('The session was explicitly destroyed during this request, attempting to re-start is not allowed.');
00432 }
00433
00434 if (self::$_sessionStarted) {
00435 return;
00436 }
00437
00438
00439 if (!self::$_defaultOptionsSet) {
00440 self::setOptions(is_array($options) ? $options : array());
00441 }
00442
00443
00444 if (self::$_strict && $options === true) {
00446 require_once 'Zend/Session/Exception.php';
00447 throw new Zend_Session_Exception('You must explicitly start the session with Zend_Session::start() when session options are set to strict.');
00448 }
00449
00450 $filename = $linenum = null;
00451 if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
00453 require_once 'Zend/Session/Exception.php';
00454 throw new Zend_Session_Exception("Session must be started before any output has been sent to the browser;"
00455 . " output started in {$filename}/{$linenum}");
00456 }
00457
00458
00459 if (!self::$_unitTestEnabled && defined('SID')) {
00461 require_once 'Zend/Session/Exception.php';
00462 throw new Zend_Session_Exception('session has already been started by session.auto-start or session_start()');
00463 }
00464
00470 $errorLevel = (is_int(self::$_throwStartupExceptions)) ? self::$_throwStartupExceptions : E_ALL;
00471
00473 if (!self::$_unitTestEnabled) {
00474
00475 if (self::$_throwStartupExceptions) {
00476 require_once 'Zend/Session/Exception.php';
00477 set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), $errorLevel);
00478 }
00479
00480 $startedCleanly = session_start();
00481
00482 if (self::$_throwStartupExceptions) {
00483 restore_error_handler();
00484 }
00485
00486 if (!$startedCleanly || Zend_Session_Exception::$sessionStartError != null) {
00487 if (self::$_throwStartupExceptions) {
00488 set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), $errorLevel);
00489 }
00490 session_write_close();
00491 if (self::$_throwStartupExceptions) {
00492 restore_error_handler();
00493 throw new Zend_Session_Exception(__CLASS__ . '::' . __FUNCTION__ . '() - ' . Zend_Session_Exception::$sessionStartError);
00494 }
00495 }
00496 }
00497
00498 parent::$_readable = true;
00499 parent::$_writable = true;
00500 self::$_sessionStarted = true;
00501 if (self::$_regenerateIdState === -1) {
00502 self::regenerateId();
00503 }
00504
00505
00506 if (isset($_SESSION['__ZF']['VALID'])) {
00507 self::_processValidators();
00508 }
00509
00510 self::_processStartupMetadataGlobal();
00511 }
00512
00513
00520 private static function _processStartupMetadataGlobal()
00521 {
00522
00523 if (isset($_SESSION['__ZF'])) {
00524
00525
00526 foreach ($_SESSION['__ZF'] as $namespace => $namespace_metadata) {
00527
00528
00529 if (isset($namespace_metadata['ENT']) && ($namespace_metadata['ENT'] > 0) && (time() > $namespace_metadata['ENT']) ) {
00530 unset($_SESSION[$namespace]);
00531 unset($_SESSION['__ZF'][$namespace]['ENT']);
00532 }
00533
00534
00535 if (isset($namespace_metadata['ENGH']) && $namespace_metadata['ENGH'] >= 1) {
00536 $_SESSION['__ZF'][$namespace]['ENGH']--;
00537
00538 if ($_SESSION['__ZF'][$namespace]['ENGH'] === 0) {
00539 if (isset($_SESSION[$namespace])) {
00540 parent::$_expiringData[$namespace] = $_SESSION[$namespace];
00541 unset($_SESSION[$namespace]);
00542 }
00543 unset($_SESSION['__ZF'][$namespace]['ENGH']);
00544 }
00545 }
00546
00547
00548 if (isset($namespace_metadata['ENVT'])) {
00549 foreach ($namespace_metadata['ENVT'] as $variable => $time) {
00550 if (time() > $time) {
00551 unset($_SESSION[$namespace][$variable]);
00552 unset($_SESSION['__ZF'][$namespace]['ENVT'][$variable]);
00553
00554 if (empty($_SESSION['__ZF'][$namespace]['ENVT'])) {
00555 unset($_SESSION['__ZF'][$namespace]['ENVT']);
00556 }
00557 }
00558 }
00559 }
00560
00561
00562 if (isset($namespace_metadata['ENVGH'])) {
00563 foreach ($namespace_metadata['ENVGH'] as $variable => $hops) {
00564 $_SESSION['__ZF'][$namespace]['ENVGH'][$variable]--;
00565
00566 if ($_SESSION['__ZF'][$namespace]['ENVGH'][$variable] === 0) {
00567 if (isset($_SESSION[$namespace][$variable])) {
00568 parent::$_expiringData[$namespace][$variable] = $_SESSION[$namespace][$variable];
00569 unset($_SESSION[$namespace][$variable]);
00570 }
00571 unset($_SESSION['__ZF'][$namespace]['ENVGH'][$variable]);
00572 }
00573 }
00574 }
00575 }
00576
00577 if (isset($namespace) && empty($_SESSION['__ZF'][$namespace])) {
00578 unset($_SESSION['__ZF'][$namespace]);
00579 }
00580 }
00581
00582 if (isset($_SESSION['__ZF']) && empty($_SESSION['__ZF'])) {
00583 unset($_SESSION['__ZF']);
00584 }
00585 }
00586
00587
00593 public static function isStarted()
00594 {
00595 return self::$_sessionStarted;
00596 }
00597
00598
00605 public static function isRegenerated()
00606 {
00607 return ( (self::$_regenerateIdState > 0) ? true : false );
00608 }
00609
00610
00616 public static function getId()
00617 {
00618 return session_id();
00619 }
00620
00621
00629 public static function setId($id)
00630 {
00631 if (!self::$_unitTestEnabled && defined('SID')) {
00633 require_once 'Zend/Session/Exception.php';
00634 throw new Zend_Session_Exception('The session has already been started. The session id must be set first.');
00635 }
00636
00637 if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
00639 require_once 'Zend/Session/Exception.php';
00640 throw new Zend_Session_Exception("You must call ".__CLASS__.'::'.__FUNCTION__.
00641 "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
00642 }
00643
00644 if (!is_string($id) || $id === '') {
00646 require_once 'Zend/Session/Exception.php';
00647 throw new Zend_Session_Exception('You must provide a non-empty string as a session identifier.');
00648 }
00649
00650 session_id($id);
00651 }
00652
00653
00661 public static function registerValidator(Zend_Session_Validator_Interface $validator)
00662 {
00663 $validator->setup();
00664 }
00665
00666
00672 public static function stop()
00673 {
00674 parent::$_writable = false;
00675 }
00676
00677
00685 public static function writeClose($readonly = true)
00686 {
00687 if (self::$_unitTestEnabled) {
00688 return;
00689 }
00690
00691 if (self::$_writeClosed) {
00692 return;
00693 }
00694
00695 if ($readonly) {
00696 parent::$_writable = false;
00697 }
00698
00699 session_write_close();
00700 self::$_writeClosed = true;
00701 }
00702
00703
00711 public static function destroy($remove_cookie = true, $readonly = true)
00712 {
00713 if (self::$_unitTestEnabled) {
00714 return;
00715 }
00716
00717 if (self::$_destroyed) {
00718 return;
00719 }
00720
00721 if ($readonly) {
00722 parent::$_writable = false;
00723 }
00724
00725 session_destroy();
00726 self::$_destroyed = true;
00727
00728 if ($remove_cookie) {
00729 self::expireSessionCookie();
00730 }
00731 }
00732
00733
00739 public static function expireSessionCookie()
00740 {
00741 if (self::$_unitTestEnabled) {
00742 return;
00743 }
00744
00745 if (self::$_sessionCookieDeleted) {
00746 return;
00747 }
00748
00749 self::$_sessionCookieDeleted = true;
00750
00751 if (isset($_COOKIE[session_name()])) {
00752 $cookie_params = session_get_cookie_params();
00753
00754 setcookie(
00755 session_name(),
00756 false,
00757 315554400,
00758 $cookie_params['path'],
00759 $cookie_params['domain'],
00760 $cookie_params['secure']
00761 );
00762 }
00763 }
00764
00765
00772 private static function _processValidators()
00773 {
00774 foreach ($_SESSION['__ZF']['VALID'] as $validator_name => $valid_data) {
00775 if (!class_exists($validator_name)) {
00776 require_once 'Zend/Loader.php';
00777 Zend_Loader::loadClass($validator_name);
00778 }
00779 $validator = new $validator_name;
00780 if ($validator->validate() === false) {
00782 require_once 'Zend/Session/Exception.php';
00783 throw new Zend_Session_Exception("This session is not valid according to {$validator_name}.");
00784 }
00785 }
00786 }
00787
00788
00795 public static function namespaceIsset($namespace)
00796 {
00797 return parent::_namespaceIsset($namespace);
00798 }
00799
00800
00808 public static function namespaceUnset($namespace)
00809 {
00810 parent::_namespaceUnset($namespace);
00811 Zend_Session_Namespace::resetSingleInstance($namespace);
00812 }
00813
00814
00822 public static function namespaceGet($namespace)
00823 {
00824 return parent::_namespaceGetAll($namespace);
00825 }
00826
00827
00835 public static function getIterator()
00836 {
00837 if (parent::$_readable === false) {
00839 require_once 'Zend/Session/Exception.php';
00840 throw new Zend_Session_Exception(parent::_THROW_NOT_READABLE_MSG);
00841 }
00842
00843 $spaces = array();
00844 if (isset($_SESSION)) {
00845 $spaces = array_keys($_SESSION);
00846 foreach($spaces as $key => $space) {
00847 if (!strncmp($space, '__', 2) || !is_array($_SESSION[$space])) {
00848 unset($spaces[$key]);
00849 }
00850 }
00851 }
00852
00853 return new ArrayObject(array_merge($spaces, array_keys(parent::$_expiringData)));
00854 }
00855
00856
00862 public static function isWritable()
00863 {
00864 return parent::$_writable;
00865 }
00866
00867
00873 public static function isReadable()
00874 {
00875 return parent::$_readable;
00876 }
00877
00878 }