PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.3.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.3.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 5 years ago Session 5 years ago Config.php 6 years ago Db.php 6 years ago Exception.php 6 years ago LICENSE.txt 6 years ago Registry.php 6 years ago Session.php 5 years ago Version.php 6 years ago
Session.php
917 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 /**
482 * Hack to throw exceptions on start instead of php errors
483 * @see http://framework.zend.com/issues/browse/ZF-1325
484 */
485
486 $errorLevel = (is_int(self::$_throwStartupExceptions)) ? self::$_throwStartupExceptions : E_ALL;
487
488 /** @see Zend_Session_Exception */
489 if (!self::$_unitTestEnabled) {
490
491 if (self::$_throwStartupExceptions) {
492 // require_once 'Zend/Session/Exception.php';
493 set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), $errorLevel);
494 }
495
496 $startedCleanly = session_start();
497
498 if (self::$_throwStartupExceptions) {
499 restore_error_handler();
500 }
501
502 if (!$startedCleanly || !empty(Zend_Session_Exception::$sessionStartError)) {
503 if (self::$_throwStartupExceptions) {
504 set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), $errorLevel);
505 }
506 session_write_close();
507 if (self::$_throwStartupExceptions) {
508 restore_error_handler();
509 throw new Zend_Session_Exception(__CLASS__ . '::' . __FUNCTION__ . '() - ' . Zend_Session_Exception::$sessionStartError . ' Warnings: ' . Zend_Session_Exception::$sessionStartWarning);
510 }
511 }
512 }
513
514 parent::$_readable = true;
515 parent::$_writable = true;
516 self::$_sessionStarted = true;
517 if (self::$_regenerateIdState === -1) {
518 self::regenerateId();
519 } else {
520 self::rewriteSessionCookieWithSameSiteDirective();
521 }
522
523 if (isset($_SESSION['data']) && is_string($_SESSION['data'])) {
524 $_SESSION = \Piwik\Common::safe_unserialize(base64_decode($_SESSION['data']), [
525 \Piwik\Notification::class
526 ]);
527 }
528
529 // run validators if they exist
530 if (isset($_SESSION['__ZF']['VALID'])) {
531 self::_processValidators();
532 }
533
534 self::_processStartupMetadataGlobal();
535 }
536
537
538 /**
539 * _processGlobalMetadata() - this method initizes the sessions GLOBAL
540 * metadata, mostly global data expiration calculations.
541 *
542 * @return void
543 */
544 private static function _processStartupMetadataGlobal()
545 {
546 // process global metadata
547 if (isset($_SESSION['__ZF'])) {
548
549 // expire globally expired values
550 foreach ($_SESSION['__ZF'] as $namespace => $namespace_metadata) {
551
552 // Expire Namespace by Time (ENT)
553 if (isset($namespace_metadata['ENT']) && ($namespace_metadata['ENT'] > 0) && (time() > $namespace_metadata['ENT']) ) {
554 unset($_SESSION[$namespace]);
555 unset($_SESSION['__ZF'][$namespace]);
556 }
557
558 // Expire Namespace by Global Hop (ENGH) if it wasnt expired above
559 if (isset($_SESSION['__ZF'][$namespace]) && isset($namespace_metadata['ENGH']) && $namespace_metadata['ENGH'] >= 1) {
560
561 $_SESSION['__ZF'][$namespace]['ENGH']--;
562
563 if ($_SESSION['__ZF'][$namespace]['ENGH'] === 0) {
564 if (isset($_SESSION[$namespace])) {
565 parent::$_expiringData[$namespace] = $_SESSION[$namespace];
566 unset($_SESSION[$namespace]);
567 }
568 unset($_SESSION['__ZF'][$namespace]);
569 }
570 }
571
572 // Expire Namespace Variables by Time (ENVT)
573 if (isset($namespace_metadata['ENVT'])) {
574 foreach ($namespace_metadata['ENVT'] as $variable => $time) {
575 if (time() > $time) {
576 unset($_SESSION[$namespace][$variable]);
577 unset($_SESSION['__ZF'][$namespace]['ENVT'][$variable]);
578 }
579 }
580 if (empty($_SESSION['__ZF'][$namespace]['ENVT'])) {
581 unset($_SESSION['__ZF'][$namespace]['ENVT']);
582 }
583 }
584
585 // Expire Namespace Variables by Global Hop (ENVGH)
586 if (isset($namespace_metadata['ENVGH'])) {
587 foreach ($namespace_metadata['ENVGH'] as $variable => $hops) {
588 $_SESSION['__ZF'][$namespace]['ENVGH'][$variable]--;
589
590 if ($_SESSION['__ZF'][$namespace]['ENVGH'][$variable] === 0) {
591 if (isset($_SESSION[$namespace][$variable])) {
592 parent::$_expiringData[$namespace][$variable] = $_SESSION[$namespace][$variable];
593 unset($_SESSION[$namespace][$variable]);
594 }
595 unset($_SESSION['__ZF'][$namespace]['ENVGH'][$variable]);
596 }
597 }
598 if (empty($_SESSION['__ZF'][$namespace]['ENVGH'])) {
599 unset($_SESSION['__ZF'][$namespace]['ENVGH']);
600 }
601 }
602
603 if (isset($namespace) && empty($_SESSION['__ZF'][$namespace])) {
604 unset($_SESSION['__ZF'][$namespace]);
605 }
606 }
607 }
608
609 if (isset($_SESSION['__ZF']) && empty($_SESSION['__ZF'])) {
610 unset($_SESSION['__ZF']);
611 }
612 }
613
614
615 /**
616 * isStarted() - convenience method to determine if the session is already started.
617 *
618 * @return bool
619 */
620 public static function isStarted()
621 {
622 return self::$_sessionStarted;
623 }
624
625
626 /**
627 * isRegenerated() - convenience method to determine if session_regenerate_id()
628 * has been called during this request by Zend_Session.
629 *
630 * @return bool
631 */
632 public static function isRegenerated()
633 {
634 return ( (self::$_regenerateIdState > 0) ? true : false );
635 }
636
637
638 /**
639 * getId() - get the current session id
640 *
641 * @return string
642 */
643 public static function getId()
644 {
645 return session_id();
646 }
647
648
649 /**
650 * setId() - set an id to a user specified id
651 *
652 * @throws Zend_Session_Exception
653 * @param string $id
654 * @return void
655 */
656 public static function setId($id)
657 {
658 if (!self::$_unitTestEnabled && defined('SID')) {
659 /** @see Zend_Session_Exception */
660 // require_once 'Zend/Session/Exception.php';
661 throw new Zend_Session_Exception('The session has already been started. The session id must be set first.');
662 }
663
664 if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
665 /** @see Zend_Session_Exception */
666 // require_once 'Zend/Session/Exception.php';
667 throw new Zend_Session_Exception("You must call ".__CLASS__.'::'.__FUNCTION__.
668 "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
669 }
670
671 if (!is_string($id) || $id === '') {
672 /** @see Zend_Session_Exception */
673 // require_once 'Zend/Session/Exception.php';
674 throw new Zend_Session_Exception('You must provide a non-empty string as a session identifier.');
675 }
676
677 session_id($id);
678 }
679
680
681 /**
682 * registerValidator() - register a validator that will attempt to validate this session for
683 * every future request
684 *
685 * @param Zend_Session_Validator_Interface $validator
686 * @return void
687 */
688 public static function registerValidator(Zend_Session_Validator_Interface $validator)
689 {
690 $validator->setup();
691 }
692
693
694 /**
695 * stop() - Disable write access. Optionally disable read (not implemented).
696 *
697 * @return void
698 */
699 public static function stop()
700 {
701 parent::$_writable = false;
702 }
703
704
705 /**
706 * writeClose() - Shutdown the sesssion, close writing and detach $_SESSION from the back-end storage mechanism.
707 * This will complete the internal data transformation on this request.
708 *
709 * @param bool $readonly - OPTIONAL remove write access (i.e. throw error if Zend_Session's attempt writes)
710 * @return void
711 */
712 public static function writeClose($readonly = true)
713 {
714 if (self::$_unitTestEnabled) {
715 return;
716 }
717
718 if (self::$_writeClosed) {
719 return;
720 }
721
722 if ($readonly) {
723 parent::$_writable = false;
724 }
725
726 if (isset($_SESSION)) {
727 $sessionBkp = $_SESSION;
728 $_SESSION = array('data' => base64_encode(serialize($_SESSION)));
729 }
730
731 session_write_close();
732 self::$_writeClosed = true;
733
734 if (isset($sessionBkp)) {
735 $_SESSION = $sessionBkp;
736 }
737 }
738
739
740 /**
741 * destroy() - This is used to destroy session data, and optionally, the session cookie itself
742 *
743 * @param bool $remove_cookie - OPTIONAL remove session id cookie, defaults to true (remove cookie)
744 * @param bool $readonly - OPTIONAL remove write access (i.e. throw error if Zend_Session's attempt writes)
745 * @return void
746 */
747 public static function destroy($remove_cookie = true, $readonly = true)
748 {
749 if (self::$_unitTestEnabled) {
750 return;
751 }
752
753 if (self::$_destroyed) {
754 return;
755 }
756
757 if ($readonly) {
758 parent::$_writable = false;
759 }
760
761 session_destroy();
762 self::$_destroyed = true;
763
764 if ($remove_cookie) {
765 self::expireSessionCookie();
766 }
767 }
768
769
770 /**
771 * expireSessionCookie() - Sends an expired session id cookie, causing the client to delete the session cookie
772 *
773 * @return void
774 */
775 public static function expireSessionCookie()
776 {
777 if (self::$_unitTestEnabled) {
778 return;
779 }
780
781 if (self::$_sessionCookieDeleted) {
782 return;
783 }
784
785 self::$_sessionCookieDeleted = true;
786
787 if (isset($_COOKIE[session_name()])) {
788 $cookie_params = session_get_cookie_params();
789
790 \Piwik\Session::writeCookie(
791 session_name(),
792 false,
793 315554400, // strtotime('1980-01-01'),
794 $cookie_params['path'],
795 $cookie_params['domain'],
796 $cookie_params['secure'],
797 false,
798 \Piwik\Session::getSameSiteCookieValue()
799 );
800 }
801 }
802
803
804 /**
805 * _processValidator() - internal function that is called in the existence of VALID metadata
806 *
807 * @throws Zend_Session_Exception
808 * @return void
809 */
810 private static function _processValidators()
811 {
812 foreach ($_SESSION['__ZF']['VALID'] as $validator_name => $valid_data) {
813 if (!class_exists($validator_name)) {
814 // require_once 'Zend/Loader.php';
815 Zend_Loader::loadClass($validator_name);
816 }
817 $validator = new $validator_name;
818 if ($validator->validate() === false) {
819 /** @see Zend_Session_Exception */
820 // require_once 'Zend/Session/Exception.php';
821 throw new Zend_Session_Exception("This session is not valid according to {$validator_name}.");
822 }
823 }
824 }
825
826
827 /**
828 * namespaceIsset() - check to see if a namespace is set
829 *
830 * @param string $namespace
831 * @return bool
832 */
833 public static function namespaceIsset($namespace)
834 {
835 return parent::_namespaceIsset($namespace);
836 }
837
838
839 /**
840 * namespaceUnset() - unset a namespace or a variable within a namespace
841 *
842 * @param string $namespace
843 * @throws Zend_Session_Exception
844 * @return void
845 */
846 public static function namespaceUnset($namespace)
847 {
848 parent::_namespaceUnset($namespace);
849 Zend_Session_Namespace::resetSingleInstance($namespace);
850 }
851
852
853 /**
854 * namespaceGet() - get all variables in a namespace
855 * Deprecated: Use getIterator() in Zend_Session_Namespace.
856 *
857 * @param string $namespace
858 * @return array
859 */
860 public static function namespaceGet($namespace)
861 {
862 return parent::_namespaceGetAll($namespace);
863 }
864
865
866 /**
867 * getIterator() - return an iteratable object for use in foreach and the like,
868 * this completes the IteratorAggregate interface
869 *
870 * @throws Zend_Session_Exception
871 * @return ArrayObject
872 */
873 public static function getIterator()
874 {
875 if (parent::$_readable === false) {
876 /** @see Zend_Session_Exception */
877 // require_once 'Zend/Session/Exception.php';
878 throw new Zend_Session_Exception(parent::_THROW_NOT_READABLE_MSG);
879 }
880
881 $spaces = array();
882 if (isset($_SESSION)) {
883 $spaces = array_keys($_SESSION);
884 foreach($spaces as $key => $space) {
885 if (!strncmp($space, '__', 2) || !is_array($_SESSION[$space])) {
886 unset($spaces[$key]);
887 }
888 }
889 }
890
891 return new ArrayObject(array_merge($spaces, array_keys(parent::$_expiringData)));
892 }
893
894
895 /**
896 * isWritable() - returns a boolean indicating if namespaces can write (use setters)
897 *
898 * @return bool
899 */
900 public static function isWritable()
901 {
902 return parent::$_writable;
903 }
904
905
906 /**
907 * isReadable() - returns a boolean indicating if namespaces can write (use setters)
908 *
909 * @return bool
910 */
911 public static function isReadable()
912 {
913 return parent::$_readable;
914 }
915
916 }
917