PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.0.5
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.0.5
5.12.0 5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / libs / Zend / Session.php
matomo / app / libs / Zend Last commit date
Db 6 years ago Mail 6 years ago Mime 6 years ago Session 6 years ago Validate 6 years ago Config.php 6 years ago Db.php 6 years ago Exception.php 6 years ago LICENSE.txt 6 years ago Mail.php 6 years ago Mime.php 6 years ago Registry.php 6 years ago Session.php 6 years ago Validate.php 6 years ago Version.php 6 years ago
Session.php
922 lines
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-2011 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 24196 2011-07-05 15:58:11Z matthew $
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-2011 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 self::rewriteSessionCookieWithSameSiteDirective();
317 }
318 self::$_regenerateIdState = 1;
319 }
320 }
321
322 /**
323 * Check if there is a Set-Cookie header present - if so, overwrite it with
324 * a similar header which also includes a SameSite directive. This workaround
325 * is needed because the SameSite property on the session cookie is not supported
326 * by PHP until 7.3.
327 */
328 private static function rewriteSessionCookieWithSameSiteDirective()
329 {
330 $headers = headers_list();
331 $cookieHeader = '';
332 foreach ($headers as $header) {
333 if (strpos($header, 'Set-Cookie: ' . \Piwik\Session::SESSION_NAME) === 0) {
334 $cookieHeader = $header;
335 break;
336 }
337 }
338
339 if (! $cookieHeader) {
340 return;
341 }
342
343 if (stripos($cookieHeader, 'SameSite') === false) {
344 $cookieHeader .= '; SameSite=' . \Piwik\Session::getSameSiteCookieValue();
345 header($cookieHeader);
346 }
347 }
348
349 /**
350 * rememberMe() - Write a persistent cookie that expires after a number of seconds in the future. If no number of
351 * seconds is specified, then this defaults to self::$_rememberMeSeconds. Due to clock errors on end users' systems,
352 * large values are recommended to avoid undesirable expiration of session cookies.
353 *
354 * @param int $seconds OPTIONAL specifies TTL for cookie in seconds from present time
355 * @return void
356 */
357 public static function rememberMe($seconds = null)
358 {
359 $seconds = (int) $seconds;
360 $seconds = ($seconds > 0) ? $seconds : self::$_rememberMeSeconds;
361
362 self::rememberUntil($seconds);
363 }
364
365
366 /**
367 * forgetMe() - Write a volatile session cookie, removing any persistent cookie that may have existed. The session
368 * would end upon, for example, termination of a web browser program.
369 *
370 * @return void
371 */
372 public static function forgetMe()
373 {
374 self::rememberUntil(0);
375 }
376
377
378 /**
379 * rememberUntil() - This method does the work of changing the state of the session cookie and making
380 * sure that it gets resent to the browser via regenerateId()
381 *
382 * @param int $seconds
383 * @return void
384 */
385 public static function rememberUntil($seconds = 0)
386 {
387 if (self::$_unitTestEnabled) {
388 self::regenerateId();
389 return;
390 }
391
392 $cookieParams = session_get_cookie_params();
393
394 session_set_cookie_params(
395 $seconds,
396 $cookieParams['path'],
397 $cookieParams['domain'],
398 $cookieParams['secure']
399 );
400
401 // normally "rememberMe()" represents a security context change, so should use new session id
402 self::regenerateId();
403 }
404
405
406 /**
407 * sessionExists() - whether or not a session exists for the current request
408 *
409 * @return bool
410 */
411 public static function sessionExists()
412 {
413 if (ini_get('session.use_cookies') == '1' && isset($_COOKIE[session_name()])) {
414 return true;
415 } elseif (!empty($_REQUEST[session_name()])) {
416 return true;
417 } elseif (self::$_unitTestEnabled) {
418 return true;
419 }
420
421 return false;
422 }
423
424
425 /**
426 * Whether or not session has been destroyed via session_destroy()
427 *
428 * @return bool
429 */
430 public static function isDestroyed()
431 {
432 return self::$_destroyed;
433 }
434
435
436 /**
437 * start() - Start the session.
438 *
439 * @param bool|array $options OPTIONAL Either user supplied options, or flag indicating if start initiated automatically
440 * @throws Zend_Session_Exception
441 * @return void
442 */
443 public static function start($options = false)
444 {
445 if (self::$_sessionStarted && self::$_destroyed) {
446 // require_once 'Zend/Session/Exception.php';
447 throw new Zend_Session_Exception('The session was explicitly destroyed during this request, attempting to re-start is not allowed.');
448 }
449
450 if (self::$_sessionStarted) {
451 return; // already started
452 }
453
454 if (session_status() === PHP_SESSION_ACTIVE) {
455 parent::$_readable = true;
456 parent::$_writable = true;
457 self::$_sessionStarted = true;
458 return;
459 }
460
461 // make sure our default options (at the least) have been set
462 if (!self::$_defaultOptionsSet) {
463 self::setOptions(is_array($options) ? $options : array());
464 }
465
466 // In strict mode, do not allow auto-starting Zend_Session, such as via "new Zend_Session_Namespace()"
467 if (self::$_strict && $options === true) {
468 /** @see Zend_Session_Exception */
469 // require_once 'Zend/Session/Exception.php';
470 throw new Zend_Session_Exception('You must explicitly start the session with Zend_Session::start() when session options are set to strict.');
471 }
472
473 $filename = $linenum = null;
474 if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
475 /** @see Zend_Session_Exception */
476 // require_once 'Zend/Session/Exception.php';
477 throw new Zend_Session_Exception("Session must be started before any output has been sent to the browser;"
478 . " output started in {$filename}/{$linenum}");
479 }
480
481 // See http://www.php.net/manual/en/ref.session.php for explanation
482 if (!self::$_unitTestEnabled && defined('SID')) {
483 /** @see Zend_Session_Exception */
484 // require_once 'Zend/Session/Exception.php';
485 throw new Zend_Session_Exception('session has already been started by session.auto-start or session_start()');
486 }
487
488 /**
489 * Hack to throw exceptions on start instead of php errors
490 * @see http://framework.zend.com/issues/browse/ZF-1325
491 */
492
493 $errorLevel = (is_int(self::$_throwStartupExceptions)) ? self::$_throwStartupExceptions : E_ALL;
494
495 /** @see Zend_Session_Exception */
496 if (!self::$_unitTestEnabled) {
497
498 if (self::$_throwStartupExceptions) {
499 // require_once 'Zend/Session/Exception.php';
500 set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), $errorLevel);
501 }
502
503 $startedCleanly = session_start();
504
505 if (self::$_throwStartupExceptions) {
506 restore_error_handler();
507 }
508
509 if (!$startedCleanly || !empty(Zend_Session_Exception::$sessionStartError)) {
510 if (self::$_throwStartupExceptions) {
511 set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), $errorLevel);
512 }
513 session_write_close();
514 if (self::$_throwStartupExceptions) {
515 restore_error_handler();
516 throw new Zend_Session_Exception(__CLASS__ . '::' . __FUNCTION__ . '() - ' . Zend_Session_Exception::$sessionStartError . ' Warnings: ' . Zend_Session_Exception::$sessionStartWarning);
517 }
518 }
519 }
520
521 parent::$_readable = true;
522 parent::$_writable = true;
523 self::$_sessionStarted = true;
524 if (self::$_regenerateIdState === -1) {
525 self::regenerateId();
526 } else {
527 self::rewriteSessionCookieWithSameSiteDirective();
528 }
529
530 if (isset($_SESSION['data']) && is_string($_SESSION['data'])) {
531 $_SESSION = unserialize(base64_decode($_SESSION['data']));
532 }
533
534 // run validators if they exist
535 if (isset($_SESSION['__ZF']['VALID'])) {
536 self::_processValidators();
537 }
538
539 self::_processStartupMetadataGlobal();
540 }
541
542
543 /**
544 * _processGlobalMetadata() - this method initizes the sessions GLOBAL
545 * metadata, mostly global data expiration calculations.
546 *
547 * @return void
548 */
549 private static function _processStartupMetadataGlobal()
550 {
551 // process global metadata
552 if (isset($_SESSION['__ZF'])) {
553
554 // expire globally expired values
555 foreach ($_SESSION['__ZF'] as $namespace => $namespace_metadata) {
556
557 // Expire Namespace by Time (ENT)
558 if (isset($namespace_metadata['ENT']) && ($namespace_metadata['ENT'] > 0) && (time() > $namespace_metadata['ENT']) ) {
559 unset($_SESSION[$namespace]);
560 unset($_SESSION['__ZF'][$namespace]);
561 }
562
563 // Expire Namespace by Global Hop (ENGH) if it wasnt expired above
564 if (isset($_SESSION['__ZF'][$namespace]) && isset($namespace_metadata['ENGH']) && $namespace_metadata['ENGH'] >= 1) {
565
566 $_SESSION['__ZF'][$namespace]['ENGH']--;
567
568 if ($_SESSION['__ZF'][$namespace]['ENGH'] === 0) {
569 if (isset($_SESSION[$namespace])) {
570 parent::$_expiringData[$namespace] = $_SESSION[$namespace];
571 unset($_SESSION[$namespace]);
572 }
573 unset($_SESSION['__ZF'][$namespace]);
574 }
575 }
576
577 // Expire Namespace Variables by Time (ENVT)
578 if (isset($namespace_metadata['ENVT'])) {
579 foreach ($namespace_metadata['ENVT'] as $variable => $time) {
580 if (time() > $time) {
581 unset($_SESSION[$namespace][$variable]);
582 unset($_SESSION['__ZF'][$namespace]['ENVT'][$variable]);
583 }
584 }
585 if (empty($_SESSION['__ZF'][$namespace]['ENVT'])) {
586 unset($_SESSION['__ZF'][$namespace]['ENVT']);
587 }
588 }
589
590 // Expire Namespace Variables by Global Hop (ENVGH)
591 if (isset($namespace_metadata['ENVGH'])) {
592 foreach ($namespace_metadata['ENVGH'] as $variable => $hops) {
593 $_SESSION['__ZF'][$namespace]['ENVGH'][$variable]--;
594
595 if ($_SESSION['__ZF'][$namespace]['ENVGH'][$variable] === 0) {
596 if (isset($_SESSION[$namespace][$variable])) {
597 parent::$_expiringData[$namespace][$variable] = $_SESSION[$namespace][$variable];
598 unset($_SESSION[$namespace][$variable]);
599 }
600 unset($_SESSION['__ZF'][$namespace]['ENVGH'][$variable]);
601 }
602 }
603 if (empty($_SESSION['__ZF'][$namespace]['ENVGH'])) {
604 unset($_SESSION['__ZF'][$namespace]['ENVGH']);
605 }
606 }
607
608 if (isset($namespace) && empty($_SESSION['__ZF'][$namespace])) {
609 unset($_SESSION['__ZF'][$namespace]);
610 }
611 }
612 }
613
614 if (isset($_SESSION['__ZF']) && empty($_SESSION['__ZF'])) {
615 unset($_SESSION['__ZF']);
616 }
617 }
618
619
620 /**
621 * isStarted() - convenience method to determine if the session is already started.
622 *
623 * @return bool
624 */
625 public static function isStarted()
626 {
627 return self::$_sessionStarted;
628 }
629
630
631 /**
632 * isRegenerated() - convenience method to determine if session_regenerate_id()
633 * has been called during this request by Zend_Session.
634 *
635 * @return bool
636 */
637 public static function isRegenerated()
638 {
639 return ( (self::$_regenerateIdState > 0) ? true : false );
640 }
641
642
643 /**
644 * getId() - get the current session id
645 *
646 * @return string
647 */
648 public static function getId()
649 {
650 return session_id();
651 }
652
653
654 /**
655 * setId() - set an id to a user specified id
656 *
657 * @throws Zend_Session_Exception
658 * @param string $id
659 * @return void
660 */
661 public static function setId($id)
662 {
663 if (!self::$_unitTestEnabled && defined('SID')) {
664 /** @see Zend_Session_Exception */
665 // require_once 'Zend/Session/Exception.php';
666 throw new Zend_Session_Exception('The session has already been started. The session id must be set first.');
667 }
668
669 if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
670 /** @see Zend_Session_Exception */
671 // require_once 'Zend/Session/Exception.php';
672 throw new Zend_Session_Exception("You must call ".__CLASS__.'::'.__FUNCTION__.
673 "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
674 }
675
676 if (!is_string($id) || $id === '') {
677 /** @see Zend_Session_Exception */
678 // require_once 'Zend/Session/Exception.php';
679 throw new Zend_Session_Exception('You must provide a non-empty string as a session identifier.');
680 }
681
682 session_id($id);
683 }
684
685
686 /**
687 * registerValidator() - register a validator that will attempt to validate this session for
688 * every future request
689 *
690 * @param Zend_Session_Validator_Interface $validator
691 * @return void
692 */
693 public static function registerValidator(Zend_Session_Validator_Interface $validator)
694 {
695 $validator->setup();
696 }
697
698
699 /**
700 * stop() - Disable write access. Optionally disable read (not implemented).
701 *
702 * @return void
703 */
704 public static function stop()
705 {
706 parent::$_writable = false;
707 }
708
709
710 /**
711 * writeClose() - Shutdown the sesssion, close writing and detach $_SESSION from the back-end storage mechanism.
712 * This will complete the internal data transformation on this request.
713 *
714 * @param bool $readonly - OPTIONAL remove write access (i.e. throw error if Zend_Session's attempt writes)
715 * @return void
716 */
717 public static function writeClose($readonly = true)
718 {
719 if (self::$_unitTestEnabled) {
720 return;
721 }
722
723 if (self::$_writeClosed) {
724 return;
725 }
726
727 if ($readonly) {
728 parent::$_writable = false;
729 }
730
731 if (isset($_SESSION)) {
732 $sessionBkp = $_SESSION;
733 $_SESSION = array('data' => base64_encode(serialize($_SESSION)));
734 }
735
736 session_write_close();
737 self::$_writeClosed = true;
738
739 if (isset($sessionBkp)) {
740 $_SESSION = $sessionBkp;
741 }
742 }
743
744
745 /**
746 * destroy() - This is used to destroy session data, and optionally, the session cookie itself
747 *
748 * @param bool $remove_cookie - OPTIONAL remove session id cookie, defaults to true (remove cookie)
749 * @param bool $readonly - OPTIONAL remove write access (i.e. throw error if Zend_Session's attempt writes)
750 * @return void
751 */
752 public static function destroy($remove_cookie = true, $readonly = true)
753 {
754 if (self::$_unitTestEnabled) {
755 return;
756 }
757
758 if (self::$_destroyed) {
759 return;
760 }
761
762 if ($readonly) {
763 parent::$_writable = false;
764 }
765
766 session_destroy();
767 self::$_destroyed = true;
768
769 if ($remove_cookie) {
770 self::expireSessionCookie();
771 }
772 }
773
774
775 /**
776 * expireSessionCookie() - Sends an expired session id cookie, causing the client to delete the session cookie
777 *
778 * @return void
779 */
780 public static function expireSessionCookie()
781 {
782 if (self::$_unitTestEnabled) {
783 return;
784 }
785
786 if (self::$_sessionCookieDeleted) {
787 return;
788 }
789
790 self::$_sessionCookieDeleted = true;
791
792 if (isset($_COOKIE[session_name()])) {
793 $cookie_params = session_get_cookie_params();
794
795 \Piwik\Session::writeCookie(
796 session_name(),
797 false,
798 315554400, // strtotime('1980-01-01'),
799 $cookie_params['path'],
800 $cookie_params['domain'],
801 $cookie_params['secure'],
802 false,
803 \Piwik\Session::getSameSiteCookieValue()
804 );
805 }
806 }
807
808
809 /**
810 * _processValidator() - internal function that is called in the existence of VALID metadata
811 *
812 * @throws Zend_Session_Exception
813 * @return void
814 */
815 private static function _processValidators()
816 {
817 foreach ($_SESSION['__ZF']['VALID'] as $validator_name => $valid_data) {
818 if (!class_exists($validator_name)) {
819 // require_once 'Zend/Loader.php';
820 Zend_Loader::loadClass($validator_name);
821 }
822 $validator = new $validator_name;
823 if ($validator->validate() === false) {
824 /** @see Zend_Session_Exception */
825 // require_once 'Zend/Session/Exception.php';
826 throw new Zend_Session_Exception("This session is not valid according to {$validator_name}.");
827 }
828 }
829 }
830
831
832 /**
833 * namespaceIsset() - check to see if a namespace is set
834 *
835 * @param string $namespace
836 * @return bool
837 */
838 public static function namespaceIsset($namespace)
839 {
840 return parent::_namespaceIsset($namespace);
841 }
842
843
844 /**
845 * namespaceUnset() - unset a namespace or a variable within a namespace
846 *
847 * @param string $namespace
848 * @throws Zend_Session_Exception
849 * @return void
850 */
851 public static function namespaceUnset($namespace)
852 {
853 parent::_namespaceUnset($namespace);
854 Zend_Session_Namespace::resetSingleInstance($namespace);
855 }
856
857
858 /**
859 * namespaceGet() - get all variables in a namespace
860 * Deprecated: Use getIterator() in Zend_Session_Namespace.
861 *
862 * @param string $namespace
863 * @return array
864 */
865 public static function namespaceGet($namespace)
866 {
867 return parent::_namespaceGetAll($namespace);
868 }
869
870
871 /**
872 * getIterator() - return an iteratable object for use in foreach and the like,
873 * this completes the IteratorAggregate interface
874 *
875 * @throws Zend_Session_Exception
876 * @return ArrayObject
877 */
878 public static function getIterator()
879 {
880 if (parent::$_readable === false) {
881 /** @see Zend_Session_Exception */
882 // require_once 'Zend/Session/Exception.php';
883 throw new Zend_Session_Exception(parent::_THROW_NOT_READABLE_MSG);
884 }
885
886 $spaces = array();
887 if (isset($_SESSION)) {
888 $spaces = array_keys($_SESSION);
889 foreach($spaces as $key => $space) {
890 if (!strncmp($space, '__', 2) || !is_array($_SESSION[$space])) {
891 unset($spaces[$key]);
892 }
893 }
894 }
895
896 return new ArrayObject(array_merge($spaces, array_keys(parent::$_expiringData)));
897 }
898
899
900 /**
901 * isWritable() - returns a boolean indicating if namespaces can write (use setters)
902 *
903 * @return bool
904 */
905 public static function isWritable()
906 {
907 return parent::$_writable;
908 }
909
910
911 /**
912 * isReadable() - returns a boolean indicating if namespaces can write (use setters)
913 *
914 * @return bool
915 */
916 public static function isReadable()
917 {
918 return parent::$_readable;
919 }
920
921 }
922