Session.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Session
  17. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  20. * @since Preview Release 0.2
  21. */
  22. /**
  23. * @see Zend_Session_Abstract
  24. */
  25. require_once 'Zend/Session/Abstract.php';
  26. /**
  27. * @see Zend_Session_Namespace
  28. */
  29. require_once 'Zend/Session/Namespace.php';
  30. /**
  31. * @see Zend_Session_SaveHandler_Interface
  32. */
  33. require_once 'Zend/Session/SaveHandler/Interface.php';
  34. /**
  35. * Zend_Session
  36. *
  37. * @category Zend
  38. * @package Zend_Session
  39. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  40. * @license http://framework.zend.com/license/new-bsd New BSD License
  41. */
  42. class Zend_Session extends Zend_Session_Abstract
  43. {
  44. /**
  45. * Whether or not Zend_Session is being used with unit tests
  46. *
  47. * @internal
  48. * @var bool
  49. */
  50. public static $_unitTestEnabled = false;
  51. /**
  52. * Check whether or not the session was started
  53. *
  54. * @var bool
  55. */
  56. private static $_sessionStarted = false;
  57. /**
  58. * Whether or not the session id has been regenerated this request.
  59. *
  60. * Id regeneration state
  61. * <0 - regenerate requested when session is started
  62. * 0 - do nothing
  63. * >0 - already called session_regenerate_id()
  64. *
  65. * @var int
  66. */
  67. private static $_regenerateIdState = 0;
  68. /**
  69. * Private list of php's ini values for ext/session
  70. * null values will default to the php.ini value, otherwise
  71. * the value below will overwrite the default ini value, unless
  72. * the user has set an option explicity with setOptions()
  73. *
  74. * @var array
  75. */
  76. private static $_defaultOptions = array(
  77. 'save_path' => null,
  78. 'name' => null, /* this should be set to a unique value for each application */
  79. 'save_handler' => null,
  80. //'auto_start' => null, /* intentionally excluded (see manual) */
  81. 'gc_probability' => null,
  82. 'gc_divisor' => null,
  83. 'gc_maxlifetime' => null,
  84. 'serialize_handler' => null,
  85. 'cookie_lifetime' => null,
  86. 'cookie_path' => null,
  87. 'cookie_domain' => null,
  88. 'cookie_secure' => null,
  89. 'cookie_httponly' => null,
  90. 'use_cookies' => null,
  91. 'use_only_cookies' => 'on',
  92. 'referer_check' => null,
  93. 'entropy_file' => null,
  94. 'entropy_length' => null,
  95. 'cache_limiter' => null,
  96. 'cache_expire' => null,
  97. 'use_trans_sid' => null,
  98. 'bug_compat_42' => null,
  99. 'bug_compat_warn' => null,
  100. 'hash_function' => null,
  101. 'hash_bits_per_character' => null
  102. );
  103. /**
  104. * List of options pertaining to Zend_Session that can be set by developers
  105. * using Zend_Session::setOptions(). This list intentionally duplicates
  106. * the individual declaration of static "class" variables by the same names.
  107. *
  108. * @var array
  109. */
  110. private static $_localOptions = array(
  111. 'strict' => '_strict',
  112. 'remember_me_seconds' => '_rememberMeSeconds'
  113. );
  114. /**
  115. * Whether or not write close has been performed.
  116. *
  117. * @var bool
  118. */
  119. private static $_writeClosed = false;
  120. /**
  121. * Whether or not session id cookie has been deleted
  122. *
  123. * @var bool
  124. */
  125. private static $_sessionCookieDeleted = false;
  126. /**
  127. * Whether or not session has been destroyed via session_destroy()
  128. *
  129. * @var bool
  130. */
  131. private static $_destroyed = false;
  132. /**
  133. * Whether or not session must be initiated before usage
  134. *
  135. * @var bool
  136. */
  137. private static $_strict = false;
  138. /**
  139. * Default number of seconds the session will be remembered for when asked to be remembered
  140. *
  141. * @var int
  142. */
  143. private static $_rememberMeSeconds = 1209600; // 2 weeks
  144. /**
  145. * Whether the default options listed in Zend_Session::$_localOptions have been set
  146. *
  147. * @var bool
  148. */
  149. private static $_defaultOptionsSet = false;
  150. /**
  151. * A reference to the set session save handler
  152. *
  153. * @var Zend_Session_SaveHandler_Interface
  154. */
  155. private static $_saveHandler = null;
  156. /**
  157. * Constructor overriding - make sure that a developer cannot instantiate
  158. */
  159. protected function __construct()
  160. {
  161. }
  162. /**
  163. * setOptions - set both the class specified
  164. *
  165. * @param array $userOptions - pass-by-keyword style array of <option name, option value> pairs
  166. * @throws Zend_Session_Exception
  167. * @return void
  168. */
  169. public static function setOptions(array $userOptions = array())
  170. {
  171. // set default options on first run only (before applying user settings)
  172. if (!self::$_defaultOptionsSet) {
  173. foreach (self::$_defaultOptions as $defaultOptionName => $defaultOptionValue) {
  174. if (isset(self::$_defaultOptions[$defaultOptionName])) {
  175. ini_set("session.$defaultOptionName", $defaultOptionValue);
  176. }
  177. }
  178. self::$_defaultOptionsSet = true;
  179. }
  180. // set the options the user has requested to set
  181. foreach ($userOptions as $userOptionName => $userOptionValue) {
  182. $userOptionName = strtolower($userOptionName);
  183. // set the ini based values
  184. if (array_key_exists($userOptionName, self::$_defaultOptions)) {
  185. ini_set("session.$userOptionName", $userOptionValue);
  186. }
  187. elseif (isset(self::$_localOptions[$userOptionName])) {
  188. self::${self::$_localOptions[$userOptionName]} = $userOptionValue;
  189. }
  190. else {
  191. /** @see Zend_Session_Exception */
  192. require_once 'Zend/Session/Exception.php';
  193. throw new Zend_Session_Exception("Unknown option: $userOptionName = $userOptionValue");
  194. }
  195. }
  196. }
  197. /**
  198. * setSaveHandler() - Session Save Handler assignment
  199. *
  200. * @param Zend_Session_SaveHandler_Interface $interface
  201. * @return void
  202. */
  203. public static function setSaveHandler(Zend_Session_SaveHandler_Interface $saveHandler)
  204. {
  205. if (self::$_unitTestEnabled) {
  206. return;
  207. }
  208. session_set_save_handler(
  209. array(&$saveHandler, 'open'),
  210. array(&$saveHandler, 'close'),
  211. array(&$saveHandler, 'read'),
  212. array(&$saveHandler, 'write'),
  213. array(&$saveHandler, 'destroy'),
  214. array(&$saveHandler, 'gc')
  215. );
  216. self::$_saveHandler = $saveHandler;
  217. }
  218. /**
  219. * getSaveHandler() - Get the session Save Handler
  220. *
  221. * @return Zend_Session_SaveHandler_Interface
  222. */
  223. public static function getSaveHandler()
  224. {
  225. return self::$_saveHandler;
  226. }
  227. /**
  228. * regenerateId() - Regenerate the session id. Best practice is to call this after
  229. * session is started. If called prior to session starting, session id will be regenerated
  230. * at start time.
  231. *
  232. * @throws Zend_Session_Exception
  233. * @return void
  234. */
  235. public static function regenerateId()
  236. {
  237. if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
  238. /** @see Zend_Session_Exception */
  239. require_once 'Zend/Session/Exception.php';
  240. throw new Zend_Session_Exception("You must call " . __CLASS__ . '::' . __FUNCTION__ .
  241. "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
  242. }
  243. if (self::$_sessionStarted && self::$_regenerateIdState <= 0) {
  244. if (!self::$_unitTestEnabled) {
  245. session_regenerate_id(true);
  246. }
  247. self::$_regenerateIdState = 1;
  248. } else {
  249. /**
  250. * @todo If we can detect that this requester had no session previously,
  251. * then why regenerate the id before the session has started?
  252. * Feedback wanted for:
  253. //
  254. if (isset($_COOKIE[session_name()]) || (!use only cookies && isset($_REQUEST[session_name()]))) {
  255. self::$_regenerateIdState = 1;
  256. } else {
  257. self::$_regenerateIdState = -1;
  258. }
  259. //*/
  260. self::$_regenerateIdState = -1;
  261. }
  262. }
  263. /**
  264. * rememberMe() - Write a persistent cookie that expires after a number of seconds in the future. If no number of
  265. * seconds is specified, then this defaults to self::$_rememberMeSeconds. Due to clock errors on end users' systems,
  266. * large values are recommended to avoid undesirable expiration of session cookies.
  267. *
  268. * @param $seconds integer - OPTIONAL specifies TTL for cookie in seconds from present time
  269. * @return void
  270. */
  271. public static function rememberMe($seconds = null)
  272. {
  273. $seconds = (int) $seconds;
  274. $seconds = ($seconds > 0) ? $seconds : self::$_rememberMeSeconds;
  275. self::rememberUntil($seconds);
  276. }
  277. /**
  278. * forgetMe() - Write a volatile session cookie, removing any persistent cookie that may have existed. The session
  279. * would end upon, for example, termination of a web browser program.
  280. *
  281. * @return void
  282. */
  283. public static function forgetMe()
  284. {
  285. self::rememberUntil(0);
  286. }
  287. /**
  288. * rememberUntil() - This method does the work of changing the state of the session cookie and making
  289. * sure that it gets resent to the browser via regenerateId()
  290. *
  291. * @param int $seconds
  292. * @return void
  293. */
  294. public static function rememberUntil($seconds = 0)
  295. {
  296. if (self::$_unitTestEnabled) {
  297. self::regenerateId();
  298. return;
  299. }
  300. $cookieParams = session_get_cookie_params();
  301. session_set_cookie_params(
  302. $seconds,
  303. $cookieParams['path'],
  304. $cookieParams['domain'],
  305. $cookieParams['secure']
  306. );
  307. // normally "rememberMe()" represents a security context change, so should use new session id
  308. self::regenerateId();
  309. }
  310. /**
  311. * sessionExists() - whether or not a session exists for the current request
  312. *
  313. * @return bool
  314. */
  315. public static function sessionExists()
  316. {
  317. if (ini_get('session.use_cookies') == '1' && isset($_COOKIE[session_name()])) {
  318. return true;
  319. } elseif (!empty($_REQUEST[session_name()])) {
  320. return true;
  321. } elseif (self::$_unitTestEnabled) {
  322. return true;
  323. }
  324. return false;
  325. }
  326. /**
  327. * Whether or not session has been destroyed via session_destroy()
  328. *
  329. * @return bool
  330. */
  331. public static function isDestroyed()
  332. {
  333. return self::$_destroyed;
  334. }
  335. /**
  336. * start() - Start the session.
  337. *
  338. * @param bool|array $options OPTIONAL Either user supplied options, or flag indicating if start initiated automatically
  339. * @throws Zend_Session_Exception
  340. * @return void
  341. */
  342. public static function start($options = false)
  343. {
  344. if (self::$_sessionStarted && self::$_destroyed) {
  345. require_once 'Zend/Session/Exception.php';
  346. throw new Zend_Session_Exception('The session was explicitly destroyed during this request, attempting to re-start is not allowed.');
  347. }
  348. if (self::$_sessionStarted) {
  349. return; // already started
  350. }
  351. // make sure our default options (at the least) have been set
  352. if (!self::$_defaultOptionsSet) {
  353. self::setOptions(is_array($options) ? $options : array());
  354. }
  355. // In strict mode, do not allow auto-starting Zend_Session, such as via "new Zend_Session_Namespace()"
  356. if (self::$_strict && $options === true) {
  357. /** @see Zend_Session_Exception */
  358. require_once 'Zend/Session/Exception.php';
  359. throw new Zend_Session_Exception('You must explicitly start the session with Zend_Session::start() when session options are set to strict.');
  360. }
  361. if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
  362. /** @see Zend_Session_Exception */
  363. require_once 'Zend/Session/Exception.php';
  364. throw new Zend_Session_Exception("Session must be started before any output has been sent to the browser;"
  365. . " output started in {$filename}/{$linenum}");
  366. }
  367. // See http://www.php.net/manual/en/ref.session.php for explanation
  368. if (!self::$_unitTestEnabled && defined('SID')) {
  369. /** @see Zend_Session_Exception */
  370. require_once 'Zend/Session/Exception.php';
  371. throw new Zend_Session_Exception('session has already been started by session.auto-start or session_start()');
  372. }
  373. /**
  374. * Hack to throw exceptions on start instead of php errors
  375. * @see http://framework.zend.com/issues/browse/ZF-1325
  376. */
  377. /** @see Zend_Session_Exception */
  378. if (!self::$_unitTestEnabled) {
  379. require_once 'Zend/Session/Exception.php';
  380. set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), E_ALL);
  381. session_start();
  382. restore_error_handler();
  383. if (Zend_Session_Exception::$sessionStartError !== null) {
  384. set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), E_ALL);
  385. session_write_close();
  386. restore_error_handler();
  387. throw new Zend_Session_Exception(__CLASS__ . '::' . __FUNCTION__ . '() - ' . Zend_Session_Exception::$sessionStartError);
  388. }
  389. }
  390. parent::$_readable = true;
  391. parent::$_writable = true;
  392. self::$_sessionStarted = true;
  393. if (self::$_regenerateIdState === -1) {
  394. self::regenerateId();
  395. }
  396. // run validators if they exist
  397. if (isset($_SESSION['__ZF']['VALID'])) {
  398. self::_processValidators();
  399. }
  400. self::_processStartupMetadataGlobal();
  401. }
  402. /**
  403. * _processGlobalMetadata() - this method initizes the sessions GLOBAL
  404. * metadata, mostly global data expiration calculations.
  405. *
  406. * @return void
  407. */
  408. private static function _processStartupMetadataGlobal()
  409. {
  410. // process global metadata
  411. if (isset($_SESSION['__ZF'])) {
  412. // expire globally expired values
  413. foreach ($_SESSION['__ZF'] as $namespace => $namespace_metadata) {
  414. // Expire Namespace by Time (ENT)
  415. if (isset($namespace_metadata['ENT']) && ($namespace_metadata['ENT'] > 0) && (time() > $namespace_metadata['ENT']) ) {
  416. unset($_SESSION[$namespace]);
  417. unset($_SESSION['__ZF'][$namespace]['ENT']);
  418. }
  419. // Expire Namespace by Global Hop (ENGH)
  420. if (isset($namespace_metadata['ENGH']) && $namespace_metadata['ENGH'] >= 1) {
  421. $_SESSION['__ZF'][$namespace]['ENGH']--;
  422. if ($_SESSION['__ZF'][$namespace]['ENGH'] === 0) {
  423. if (isset($_SESSION[$namespace])) {
  424. parent::$_expiringData[$namespace] = $_SESSION[$namespace];
  425. unset($_SESSION[$namespace]);
  426. }
  427. unset($_SESSION['__ZF'][$namespace]['ENGH']);
  428. }
  429. }
  430. // Expire Namespace Variables by Time (ENVT)
  431. if (isset($namespace_metadata['ENVT'])) {
  432. foreach ($namespace_metadata['ENVT'] as $variable => $time) {
  433. if (time() > $time) {
  434. unset($_SESSION[$namespace][$variable]);
  435. unset($_SESSION['__ZF'][$namespace]['ENVT'][$variable]);
  436. if (empty($_SESSION['__ZF'][$namespace]['ENVT'])) {
  437. unset($_SESSION['__ZF'][$namespace]['ENVT']);
  438. }
  439. }
  440. }
  441. }
  442. // Expire Namespace Variables by Global Hop (ENVGH)
  443. if (isset($namespace_metadata['ENVGH'])) {
  444. foreach ($namespace_metadata['ENVGH'] as $variable => $hops) {
  445. $_SESSION['__ZF'][$namespace]['ENVGH'][$variable]--;
  446. if ($_SESSION['__ZF'][$namespace]['ENVGH'][$variable] === 0) {
  447. if (isset($_SESSION[$namespace][$variable])) {
  448. parent::$_expiringData[$namespace][$variable] = $_SESSION[$namespace][$variable];
  449. unset($_SESSION[$namespace][$variable]);
  450. }
  451. unset($_SESSION['__ZF'][$namespace]['ENVGH'][$variable]);
  452. }
  453. }
  454. }
  455. }
  456. if (isset($namespace) && empty($_SESSION['__ZF'][$namespace])) {
  457. unset($_SESSION['__ZF'][$namespace]);
  458. }
  459. }
  460. if (isset($_SESSION['__ZF']) && empty($_SESSION['__ZF'])) {
  461. unset($_SESSION['__ZF']);
  462. }
  463. }
  464. /**
  465. * isStarted() - convenience method to determine if the session is already started.
  466. *
  467. * @return bool
  468. */
  469. public static function isStarted()
  470. {
  471. return self::$_sessionStarted;
  472. }
  473. /**
  474. * isRegenerated() - convenience method to determine if session_regenerate_id()
  475. * has been called during this request by Zend_Session.
  476. *
  477. * @return bool
  478. */
  479. public static function isRegenerated()
  480. {
  481. return ( (self::$_regenerateIdState > 0) ? true : false );
  482. }
  483. /**
  484. * getId() - get the current session id
  485. *
  486. * @return string
  487. */
  488. public static function getId()
  489. {
  490. return session_id();
  491. }
  492. /**
  493. * setId() - set an id to a user specified id
  494. *
  495. * @throws Zend_Session_Exception
  496. * @param string $id
  497. * @return void
  498. */
  499. public static function setId($id)
  500. {
  501. if (!self::$_unitTestEnabled && defined('SID')) {
  502. /** @see Zend_Session_Exception */
  503. require_once 'Zend/Session/Exception.php';
  504. throw new Zend_Session_Exception('The session has already been started. The session id must be set first.');
  505. }
  506. if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
  507. /** @see Zend_Session_Exception */
  508. require_once 'Zend/Session/Exception.php';
  509. throw new Zend_Session_Exception("You must call ".__CLASS__.'::'.__FUNCTION__.
  510. "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
  511. }
  512. if (!is_string($id) || $id === '') {
  513. /** @see Zend_Session_Exception */
  514. require_once 'Zend/Session/Exception.php';
  515. throw new Zend_Session_Exception('You must provide a non-empty string as a session identifier.');
  516. }
  517. session_id($id);
  518. }
  519. /**
  520. * registerValidator() - register a validator that will attempt to validate this session for
  521. * every future request
  522. *
  523. * @param Zend_Session_Validator_Interface $validator
  524. * @return void
  525. */
  526. public static function registerValidator(Zend_Session_Validator_Interface $validator)
  527. {
  528. $validator->setup();
  529. }
  530. /**
  531. * stop() - Disable write access. Optionally disable read (not implemented).
  532. *
  533. * @return void
  534. */
  535. public static function stop()
  536. {
  537. parent::$_writable = false;
  538. }
  539. /**
  540. * writeClose() - Shutdown the sesssion, close writing and detach $_SESSION from the back-end storage mechanism.
  541. * This will complete the internal data transformation on this request.
  542. *
  543. * @param bool $readonly - OPTIONAL remove write access (i.e. throw error if Zend_Session's attempt writes)
  544. * @return void
  545. */
  546. public static function writeClose($readonly = true)
  547. {
  548. if (self::$_unitTestEnabled) {
  549. return;
  550. }
  551. if (self::$_writeClosed) {
  552. return;
  553. }
  554. if ($readonly) {
  555. parent::$_writable = false;
  556. }
  557. session_write_close();
  558. self::$_writeClosed = true;
  559. }
  560. /**
  561. * destroy() - This is used to destroy session data, and optionally, the session cookie itself
  562. *
  563. * @param bool $remove_cookie - OPTIONAL remove session id cookie, defaults to true (remove cookie)
  564. * @param bool $readonly - OPTIONAL remove write access (i.e. throw error if Zend_Session's attempt writes)
  565. * @return void
  566. */
  567. public static function destroy($remove_cookie = true, $readonly = true)
  568. {
  569. if (self::$_unitTestEnabled) {
  570. return;
  571. }
  572. if (self::$_destroyed) {
  573. return;
  574. }
  575. if ($readonly) {
  576. parent::$_writable = false;
  577. }
  578. session_destroy();
  579. self::$_destroyed = true;
  580. if ($remove_cookie) {
  581. self::expireSessionCookie();
  582. }
  583. }
  584. /**
  585. * expireSessionCookie() - Sends an expired session id cookie, causing the client to delete the session cookie
  586. *
  587. * @return void
  588. */
  589. public static function expireSessionCookie()
  590. {
  591. if (self::$_unitTestEnabled) {
  592. return;
  593. }
  594. if (self::$_sessionCookieDeleted) {
  595. return;
  596. }
  597. self::$_sessionCookieDeleted = true;
  598. if (isset($_COOKIE[session_name()])) {
  599. $cookie_params = session_get_cookie_params();
  600. setcookie(
  601. session_name(),
  602. false,
  603. 315554400, // strtotime('1980-01-01'),
  604. $cookie_params['path'],
  605. $cookie_params['domain'],
  606. $cookie_params['secure']
  607. );
  608. }
  609. }
  610. /**
  611. * _processValidator() - internal function that is called in the existence of VALID metadata
  612. *
  613. * @throws Zend_Session_Exception
  614. * @return void
  615. */
  616. private static function _processValidators()
  617. {
  618. if (count($_SESSION['__ZF']['VALID']) > 0) {
  619. /**
  620. * @see Zend_Loader
  621. */
  622. require_once 'Zend/Loader.php';
  623. }
  624. foreach ($_SESSION['__ZF']['VALID'] as $validator_name => $valid_data) {
  625. Zend_Loader::loadClass($validator_name);
  626. $validator = new $validator_name;
  627. if ($validator->validate() === false) {
  628. /** @see Zend_Session_Exception */
  629. require_once 'Zend/Session/Exception.php';
  630. throw new Zend_Session_Exception("This session is not valid according to {$validator_name}.");
  631. }
  632. }
  633. }
  634. /**
  635. * namespaceIsset() - check to see if a namespace is set
  636. *
  637. * @param string $namespace
  638. * @return bool
  639. */
  640. public static function namespaceIsset($namespace)
  641. {
  642. return parent::_namespaceIsset($namespace);
  643. }
  644. /**
  645. * namespaceUnset() - unset a namespace or a variable within a namespace
  646. *
  647. * @param string $namespace
  648. * @throws Zend_Session_Exception
  649. * @return void
  650. */
  651. public static function namespaceUnset($namespace)
  652. {
  653. parent::_namespaceUnset($namespace);
  654. }
  655. /**
  656. * namespaceGet() - get all variables in a namespace
  657. * Deprecated: Use getIterator() in Zend_Session_Namespace.
  658. *
  659. * @param string $namespace
  660. * @return array
  661. */
  662. public static function namespaceGet($namespace)
  663. {
  664. return parent::_namespaceGetAll($namespace);
  665. }
  666. /**
  667. * getIterator() - return an iteratable object for use in foreach and the like,
  668. * this completes the IteratorAggregate interface
  669. *
  670. * @throws Zend_Session_Exception
  671. * @return ArrayObject
  672. */
  673. public static function getIterator()
  674. {
  675. if (parent::$_readable === false) {
  676. /** @see Zend_Session_Exception */
  677. require_once 'Zend/Session/Exception.php';
  678. throw new Zend_Session_Exception(parent::_THROW_NOT_READABLE_MSG);
  679. }
  680. $spaces = array();
  681. if (isset($_SESSION)) {
  682. $spaces = array_keys($_SESSION);
  683. foreach($spaces as $key => $space) {
  684. if (!strncmp($space, '__', 2) || !is_array($_SESSION[$space])) {
  685. unset($spaces[$key]);
  686. }
  687. }
  688. }
  689. return new ArrayObject(array_merge($spaces, array_keys(parent::$_expiringData)));
  690. }
  691. /**
  692. * isWritable() - returns a boolean indicating if namespaces can write (use setters)
  693. *
  694. * @return bool
  695. */
  696. public static function isWritable()
  697. {
  698. return parent::$_writable;
  699. }
  700. /**
  701. * isReadable() - returns a boolean indicating if namespaces can write (use setters)
  702. *
  703. * @return bool
  704. */
  705. public static function isReadable()
  706. {
  707. return parent::$_readable;
  708. }
  709. }