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