Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Session.php
Go to the documentation of this file.
1 <?php
2 
28 #require_once 'Zend/Session/Abstract.php';
29 
33 #require_once 'Zend/Session/Namespace.php';
34 
38 #require_once 'Zend/Session/SaveHandler/Interface.php';
39 
40 
50 {
57  public static $_unitTestEnabled = false;
58 
64  protected static $_throwStartupExceptions = true;
65 
71  private static $_sessionStarted = false;
72 
83  private static $_regenerateIdState = 0;
84 
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 
128  private static $_localOptions = array(
129  'strict' => '_strict',
130  'remember_me_seconds' => '_rememberMeSeconds',
131  'throw_startup_exceptions' => '_throwStartupExceptions'
132  );
133 
139  private static $_writeClosed = false;
140 
146  private static $_sessionCookieDeleted = false;
147 
153  private static $_destroyed = false;
154 
160  private static $_strict = false;
161 
167  private static $_rememberMeSeconds = 1209600; // 2 weeks
168 
174  private static $_defaultOptionsSet = false;
175 
181  private static $_saveHandler = null;
182 
183 
187  protected function __construct()
188  {
189  }
190 
191 
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 {
226  #require_once 'Zend/Session/Exception.php';
227  throw new Zend_Session_Exception("Unknown option: $userOptionName = $userOptionValue");
228  }
229  }
230  }
231 
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 
265  public static function setSaveHandler(Zend_Session_SaveHandler_Interface $saveHandler)
266  {
267  self::$_saveHandler = $saveHandler;
268 
269  if (self::$_unitTestEnabled) {
270  return;
271  }
272 
274  array(&$saveHandler, 'open'),
275  array(&$saveHandler, 'close'),
276  array(&$saveHandler, 'read'),
277  array(&$saveHandler, 'write'),
278  array(&$saveHandler, 'destroy'),
279  array(&$saveHandler, 'gc')
280  );
281 
282  if (!$result) {
283  throw new Zend_Session_Exception('Unable to set session handler');
284  }
285  }
286 
287 
293  public static function getSaveHandler()
294  {
295  return self::$_saveHandler;
296  }
297 
298 
307  public static function regenerateId()
308  {
309  if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
311  #require_once 'Zend/Session/Exception.php';
312  throw new Zend_Session_Exception("You must call " . __CLASS__ . '::' . __FUNCTION__ .
313  "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
314  }
315 
316  if ( !self::$_sessionStarted ) {
317  self::$_regenerateIdState = -1;
318  } else {
319  if (!self::$_unitTestEnabled) {
320  session_regenerate_id(true);
321  }
322  self::$_regenerateIdState = 1;
323  }
324  }
325 
326 
335  public static function rememberMe($seconds = null)
336  {
337  $seconds = (int) $seconds;
338  $seconds = ($seconds > 0) ? $seconds : self::$_rememberMeSeconds;
339 
340  self::rememberUntil($seconds);
341  }
342 
343 
350  public static function forgetMe()
351  {
353  }
354 
355 
363  public static function rememberUntil($seconds = 0)
364  {
365  if (self::$_unitTestEnabled) {
367  return;
368  }
369 
370  $cookieParams = session_get_cookie_params();
371 
372  session_set_cookie_params(
373  $seconds,
374  $cookieParams['path'],
375  $cookieParams['domain'],
376  $cookieParams['secure']
377  );
378 
379  // normally "rememberMe()" represents a security context change, so should use new session id
381  }
382 
383 
389  public static function sessionExists()
390  {
391  if ((bool)ini_get('session.use_cookies') == true && isset($_COOKIE[session_name()])) {
392  return true;
393  } elseif ((bool)ini_get('session.use_only_cookies') == false && isset($_REQUEST[session_name()])) {
394  return true;
395  } elseif (self::$_unitTestEnabled) {
396  return true;
397  }
398 
399  return false;
400  }
401 
402 
408  public static function isDestroyed()
409  {
410  return self::$_destroyed;
411  }
412 
413 
421  public static function start($options = false)
422  {
423  // Check to see if we've been passed an invalid session ID
424  if ( self::getId() && !self::_checkId(self::getId()) ) {
425  // Generate a valid, temporary replacement
426  self::setId(md5(self::getId()));
427  // Force a regenerate after session is started
428  self::$_regenerateIdState = -1;
429  }
430 
431  if (self::$_sessionStarted && self::$_destroyed) {
432  #require_once 'Zend/Session/Exception.php';
433  throw new Zend_Session_Exception('The session was explicitly destroyed during this request, attempting to re-start is not allowed.');
434  }
435 
436  if (self::$_sessionStarted) {
437  return; // already started
438  }
439 
440  // make sure our default options (at the least) have been set
441  if (!self::$_defaultOptionsSet) {
442  self::setOptions(is_array($options) ? $options : array());
443  }
444 
445  // In strict mode, do not allow auto-starting Zend_Session, such as via "new Zend_Session_Namespace()"
446  if (self::$_strict && $options === true) {
448  #require_once 'Zend/Session/Exception.php';
449  throw new Zend_Session_Exception('You must explicitly start the session with Zend_Session::start() when session options are set to strict.');
450  }
451 
452  $filename = $linenum = null;
453  if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
455  #require_once 'Zend/Session/Exception.php';
456  throw new Zend_Session_Exception("Session must be started before any output has been sent to the browser;"
457  . " output started in {$filename}/{$linenum}");
458  }
459 
460  // See http://www.php.net/manual/en/ref.session.php for explanation
461  if (!self::$_unitTestEnabled && defined('SID')) {
463  #require_once 'Zend/Session/Exception.php';
464  throw new Zend_Session_Exception('session has already been started by session.auto-start or session_start()');
465  }
466 
472  $errorLevel = (is_int(self::$_throwStartupExceptions)) ? self::$_throwStartupExceptions : E_ALL;
473 
475  if (!self::$_unitTestEnabled) {
476 
477  if (self::$_throwStartupExceptions) {
478  #require_once 'Zend/Session/Exception.php';
479  set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), $errorLevel);
480  }
481 
482  $startedCleanly = session_start();
483 
484  if (self::$_throwStartupExceptions) {
485  restore_error_handler();
486  }
487 
488  if (!$startedCleanly || Zend_Session_Exception::$sessionStartError != null) {
489  if (self::$_throwStartupExceptions) {
490  set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), $errorLevel);
491  }
492  session_write_close();
493  if (self::$_throwStartupExceptions) {
494  restore_error_handler();
495  throw new Zend_Session_Exception(__CLASS__ . '::' . __FUNCTION__ . '() - ' . Zend_Session_Exception::$sessionStartError);
496  }
497  }
498  }
499 
500  parent::$_readable = true;
501  parent::$_writable = true;
502  self::$_sessionStarted = true;
503  if (self::$_regenerateIdState === -1) {
505  }
506 
507  // run validators if they exist
508  if (isset($_SESSION['__ZF']['VALID'])) {
509  self::_processValidators();
510  }
511 
512  self::_processStartupMetadataGlobal();
513  }
514 
521  protected static function _checkId($id)
522  {
523  $saveHandler = ini_get('session.save_handler');
524  if ($saveHandler == 'cluster') { // Zend Server SC, validate only after last dash
525  $dashPos = strrpos($id, '-');
526  if ($dashPos) {
527  $id = substr($id, $dashPos + 1);
528  }
529  }
530 
531  $hashBitsPerChar = ini_get('session.hash_bits_per_character');
532  if (!$hashBitsPerChar) {
533  $hashBitsPerChar = 5; // the default value
534  }
535  switch($hashBitsPerChar) {
536  case 4: $pattern = '^[0-9a-f]*$'; break;
537  case 5: $pattern = '^[0-9a-v]*$'; break;
538  case 6: $pattern = '^[0-9a-zA-Z-,]*$'; break;
539  }
540  return preg_match('#'.$pattern.'#', $id);
541  }
542 
543 
550  private static function _processStartupMetadataGlobal()
551  {
552  // process global metadata
553  if (isset($_SESSION['__ZF'])) {
554 
555  // expire globally expired values
556  foreach ($_SESSION['__ZF'] as $namespace => $namespace_metadata) {
557 
558  // Expire Namespace by Time (ENT)
559  if (isset($namespace_metadata['ENT']) && ($namespace_metadata['ENT'] > 0) && (time() > $namespace_metadata['ENT']) ) {
560  unset($_SESSION[$namespace]);
561  unset($_SESSION['__ZF'][$namespace]);
562  }
563 
564  // Expire Namespace by Global Hop (ENGH) if it wasnt expired above
565  if (isset($_SESSION['__ZF'][$namespace]) && isset($namespace_metadata['ENGH']) && $namespace_metadata['ENGH'] >= 1) {
566 
567  $_SESSION['__ZF'][$namespace]['ENGH']--;
568 
569  if ($_SESSION['__ZF'][$namespace]['ENGH'] === 0) {
570  if (isset($_SESSION[$namespace])) {
571  parent::$_expiringData[$namespace] = $_SESSION[$namespace];
572  unset($_SESSION[$namespace]);
573  }
574  unset($_SESSION['__ZF'][$namespace]);
575  }
576  }
577 
578  // Expire Namespace Variables by Time (ENVT)
579  if (isset($namespace_metadata['ENVT'])) {
580  foreach ($namespace_metadata['ENVT'] as $variable => $time) {
581  if (time() > $time) {
582  unset($_SESSION[$namespace][$variable]);
583  unset($_SESSION['__ZF'][$namespace]['ENVT'][$variable]);
584  }
585  }
586  if (empty($_SESSION['__ZF'][$namespace]['ENVT'])) {
587  unset($_SESSION['__ZF'][$namespace]['ENVT']);
588  }
589  }
590 
591  // Expire Namespace Variables by Global Hop (ENVGH)
592  if (isset($namespace_metadata['ENVGH'])) {
593  foreach ($namespace_metadata['ENVGH'] as $variable => $hops) {
594  $_SESSION['__ZF'][$namespace]['ENVGH'][$variable]--;
595 
596  if ($_SESSION['__ZF'][$namespace]['ENVGH'][$variable] === 0) {
597  if (isset($_SESSION[$namespace][$variable])) {
598  parent::$_expiringData[$namespace][$variable] = $_SESSION[$namespace][$variable];
599  unset($_SESSION[$namespace][$variable]);
600  }
601  unset($_SESSION['__ZF'][$namespace]['ENVGH'][$variable]);
602  }
603  }
604  if (empty($_SESSION['__ZF'][$namespace]['ENVGH'])) {
605  unset($_SESSION['__ZF'][$namespace]['ENVGH']);
606  }
607  }
608 
609  if (isset($namespace) && empty($_SESSION['__ZF'][$namespace])) {
610  unset($_SESSION['__ZF'][$namespace]);
611  }
612  }
613  }
614 
615  if (isset($_SESSION['__ZF']) && empty($_SESSION['__ZF'])) {
616  unset($_SESSION['__ZF']);
617  }
618  }
619 
620 
626  public static function isStarted()
627  {
628  return self::$_sessionStarted;
629  }
630 
631 
638  public static function isRegenerated()
639  {
640  return ( (self::$_regenerateIdState > 0) ? true : false );
641  }
642 
643 
649  public static function getId()
650  {
651  return session_id();
652  }
653 
654 
662  public static function setId($id)
663  {
664  if (!self::$_unitTestEnabled && defined('SID')) {
666  #require_once 'Zend/Session/Exception.php';
667  throw new Zend_Session_Exception('The session has already been started. The session id must be set first.');
668  }
669 
670  if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
672  #require_once 'Zend/Session/Exception.php';
673  throw new Zend_Session_Exception("You must call ".__CLASS__.'::'.__FUNCTION__.
674  "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
675  }
676 
677  if (!is_string($id) || $id === '') {
679  #require_once 'Zend/Session/Exception.php';
680  throw new Zend_Session_Exception('You must provide a non-empty string as a session identifier.');
681  }
682 
683  session_id($id);
684  }
685 
686 
694  public static function registerValidator(Zend_Session_Validator_Interface $validator)
695  {
696  $validator->setup();
697  }
698 
699 
705  public static function stop()
706  {
707  parent::$_writable = false;
708  }
709 
710 
718  public static function writeClose($readonly = true)
719  {
720  if (self::$_unitTestEnabled) {
721  return;
722  }
723 
724  if (self::$_writeClosed) {
725  return;
726  }
727 
728  if ($readonly) {
729  parent::$_writable = false;
730  }
731 
732  session_write_close();
733  self::$_writeClosed = true;
734  }
735 
736 
744  public static function destroy($remove_cookie = true, $readonly = true)
745  {
746  if (self::$_unitTestEnabled) {
747  return;
748  }
749 
750  if (self::$_destroyed) {
751  return;
752  }
753 
754  if ($readonly) {
755  parent::$_writable = false;
756  }
757 
758  session_destroy();
759  self::$_destroyed = true;
760 
761  if ($remove_cookie) {
763  }
764  }
765 
766 
772  public static function expireSessionCookie()
773  {
774  if (self::$_unitTestEnabled) {
775  return;
776  }
777 
778  if (self::$_sessionCookieDeleted) {
779  return;
780  }
781 
782  self::$_sessionCookieDeleted = true;
783 
784  if (isset($_COOKIE[session_name()])) {
785  $cookie_params = session_get_cookie_params();
786 
787  setcookie(
788  session_name(),
789  false,
790  315554400, // strtotime('1980-01-01'),
791  $cookie_params['path'],
792  $cookie_params['domain'],
793  $cookie_params['secure']
794  );
795  }
796  }
797 
798 
805  private static function _processValidators()
806  {
807  foreach ($_SESSION['__ZF']['VALID'] as $validator_name => $valid_data) {
808  if (!class_exists($validator_name)) {
809  #require_once 'Zend/Loader.php';
810  Zend_Loader::loadClass($validator_name);
811  }
812  $validator = new $validator_name;
813  if ($validator->validate() === false) {
815  #require_once 'Zend/Session/Validator/Exception.php';
816  throw new Zend_Session_Validator_Exception("This session is not valid according to {$validator_name}.");
817  }
818  }
819  }
820 
821 
828  public static function namespaceIsset($namespace)
829  {
830  return parent::_namespaceIsset($namespace);
831  }
832 
833 
841  public static function namespaceUnset($namespace)
842  {
843  parent::_namespaceUnset($namespace);
845  }
846 
847 
855  public static function namespaceGet($namespace)
856  {
857  return parent::_namespaceGetAll($namespace);
858  }
859 
860 
868  public static function getIterator()
869  {
870  if (parent::$_readable === false) {
872  #require_once 'Zend/Session/Exception.php';
873  throw new Zend_Session_Exception(parent::_THROW_NOT_READABLE_MSG);
874  }
875 
876  $spaces = array();
877  if (isset($_SESSION)) {
878  $spaces = array_keys($_SESSION);
879  foreach($spaces as $key => $space) {
880  if (!strncmp($space, '__', 2) || !is_array($_SESSION[$space])) {
881  unset($spaces[$key]);
882  }
883  }
884  }
885 
886  return new ArrayObject(array_merge($spaces, array_keys(parent::$_expiringData)));
887  }
888 
889 
895  public static function isWritable()
896  {
897  return parent::$_writable;
898  }
899 
900 
906  public static function isReadable()
907  {
908  return parent::$_readable;
909  }
910 
911 }
static setSaveHandler(Zend_Session_SaveHandler_Interface $saveHandler)
Definition: Session.php:265
static rememberUntil($seconds=0)
Definition: Session.php:363
static isReadable()
Definition: Session.php:906
static $_throwStartupExceptions
Definition: Session.php:64
static _checkId($id)
Definition: Session.php:521
static namespaceGet($namespace)
Definition: Session.php:855
static registerValidator(Zend_Session_Validator_Interface $validator)
Definition: Session.php:694
ini_set($varName, $newValue)
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
static getId()
Definition: Session.php:649
static loadClass($class, $dirs=null)
Definition: Loader.php:52
$pattern
Definition: website.php:22
$id
Definition: fieldset.phtml:14
static writeClose($readonly=true)
Definition: Session.php:718
static regenerateId()
Definition: Session.php:307
static expireSessionCookie()
Definition: Session.php:772
static getSaveHandler()
Definition: Session.php:293
$variable
Definition: variable.php:7
static namespaceIsset($namespace)
Definition: Session.php:828
static sessionExists()
Definition: Session.php:389
static rememberMe($seconds=null)
Definition: Session.php:335
static isRegenerated()
Definition: Session.php:638
static getOptions($optionName=null)
Definition: Session.php:238
static forgetMe()
Definition: Session.php:350
static getIterator()
Definition: Session.php:868
static isWritable()
Definition: Session.php:895
static isDestroyed()
Definition: Session.php:408
static $_unitTestEnabled
Definition: Session.php:57
static setId($id)
Definition: Session.php:662
static start($options=false)
Definition: Session.php:421
static stop()
Definition: Session.php:705
static setOptions(array $userOptions=array())
Definition: Session.php:199
static destroy($remove_cookie=true, $readonly=true)
Definition: Session.php:744
static namespaceUnset($namespace)
Definition: Session.php:841
static isStarted()
Definition: Session.php:626
static resetSingleInstance($namespaceName=null)
Definition: Namespace.php:79