[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/symfony/http-foundation/Session/Storage/ -> NativeSessionStorage.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\HttpFoundation\Session\Storage;
  13  
  14  use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  15  use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
  16  use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
  17  use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
  18  use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
  19  
  20  /**
  21   * This provides a base class for session attribute storage.
  22   *
  23   * @author Drak <drak@zikula.org>
  24   */
  25  class NativeSessionStorage implements SessionStorageInterface
  26  {
  27      /**
  28       * Array of SessionBagInterface.
  29       *
  30       * @var SessionBagInterface[]
  31       */
  32      protected $bags;
  33  
  34      /**
  35       * @var bool
  36       */
  37      protected $started = false;
  38  
  39      /**
  40       * @var bool
  41       */
  42      protected $closed = false;
  43  
  44      /**
  45       * @var AbstractProxy
  46       */
  47      protected $saveHandler;
  48  
  49      /**
  50       * @var MetadataBag
  51       */
  52      protected $metadataBag;
  53  
  54      /**
  55       * Depending on how you want the storage driver to behave you probably
  56       * want to override this constructor entirely.
  57       *
  58       * List of options for $options array with their defaults.
  59       *
  60       * @see http://php.net/session.configuration for options
  61       * but we omit 'session.' from the beginning of the keys for convenience.
  62       *
  63       * ("auto_start", is not supported as it tells PHP to start a session before
  64       * PHP starts to execute user-land code. Setting during runtime has no effect).
  65       *
  66       * cache_limiter, "" (use "0" to prevent headers from being sent entirely).
  67       * cookie_domain, ""
  68       * cookie_httponly, ""
  69       * cookie_lifetime, "0"
  70       * cookie_path, "/"
  71       * cookie_secure, ""
  72       * entropy_file, ""
  73       * entropy_length, "0"
  74       * gc_divisor, "100"
  75       * gc_maxlifetime, "1440"
  76       * gc_probability, "1"
  77       * hash_bits_per_character, "4"
  78       * hash_function, "0"
  79       * lazy_write, "1"
  80       * name, "PHPSESSID"
  81       * referer_check, ""
  82       * serialize_handler, "php"
  83       * use_strict_mode, "0"
  84       * use_cookies, "1"
  85       * use_only_cookies, "1"
  86       * use_trans_sid, "0"
  87       * upload_progress.enabled, "1"
  88       * upload_progress.cleanup, "1"
  89       * upload_progress.prefix, "upload_progress_"
  90       * upload_progress.name, "PHP_SESSION_UPLOAD_PROGRESS"
  91       * upload_progress.freq, "1%"
  92       * upload_progress.min-freq, "1"
  93       * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
  94       * sid_length, "32"
  95       * sid_bits_per_character, "5"
  96       * trans_sid_hosts, $_SERVER['HTTP_HOST']
  97       * trans_sid_tags, "a=href,area=href,frame=src,form="
  98       *
  99       * @param array                                                            $options Session configuration options
 100       * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
 101       * @param MetadataBag                                                      $metaBag MetadataBag
 102       */
 103      public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
 104      {
 105          $options += array(
 106              // disable by default because it's managed by HeaderBag (if used)
 107              'cache_limiter' => '',
 108              'use_cookies' => 1,
 109          );
 110  
 111          if (\PHP_VERSION_ID >= 50400) {
 112              session_register_shutdown();
 113          } else {
 114              register_shutdown_function('session_write_close');
 115          }
 116  
 117          $this->setMetadataBag($metaBag);
 118          $this->setOptions($options);
 119          $this->setSaveHandler($handler);
 120      }
 121  
 122      /**
 123       * Gets the save handler instance.
 124       *
 125       * @return AbstractProxy
 126       */
 127      public function getSaveHandler()
 128      {
 129          return $this->saveHandler;
 130      }
 131  
 132      /**
 133       * {@inheritdoc}
 134       */
 135      public function start()
 136      {
 137          if ($this->started) {
 138              return true;
 139          }
 140  
 141          if (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status()) {
 142              throw new \RuntimeException('Failed to start the session: already started by PHP.');
 143          }
 144  
 145          if (\PHP_VERSION_ID < 50400 && !$this->closed && isset($_SESSION) && session_id()) {
 146              // not 100% fool-proof, but is the most reliable way to determine if a session is active in PHP 5.3
 147              throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).');
 148          }
 149  
 150          if (ini_get('session.use_cookies') && headers_sent($file, $line)) {
 151              throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
 152          }
 153  
 154          // ok to try and start the session
 155          if (!session_start()) {
 156              throw new \RuntimeException('Failed to start the session');
 157          }
 158  
 159          $this->loadSession();
 160          if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
 161              // This condition matches only PHP 5.3 with internal save handlers
 162              $this->saveHandler->setActive(true);
 163          }
 164  
 165          return true;
 166      }
 167  
 168      /**
 169       * {@inheritdoc}
 170       */
 171      public function getId()
 172      {
 173          return $this->saveHandler->getId();
 174      }
 175  
 176      /**
 177       * {@inheritdoc}
 178       */
 179      public function setId($id)
 180      {
 181          $this->saveHandler->setId($id);
 182      }
 183  
 184      /**
 185       * {@inheritdoc}
 186       */
 187      public function getName()
 188      {
 189          return $this->saveHandler->getName();
 190      }
 191  
 192      /**
 193       * {@inheritdoc}
 194       */
 195      public function setName($name)
 196      {
 197          $this->saveHandler->setName($name);
 198      }
 199  
 200      /**
 201       * {@inheritdoc}
 202       */
 203      public function regenerate($destroy = false, $lifetime = null)
 204      {
 205          // Cannot regenerate the session ID for non-active sessions.
 206          if (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE !== session_status()) {
 207              return false;
 208          }
 209  
 210          // Check if session ID exists in PHP 5.3
 211          if (\PHP_VERSION_ID < 50400 && '' === session_id()) {
 212              return false;
 213          }
 214  
 215          if (headers_sent()) {
 216              return false;
 217          }
 218  
 219          if (null !== $lifetime) {
 220              ini_set('session.cookie_lifetime', $lifetime);
 221          }
 222  
 223          if ($destroy) {
 224              $this->metadataBag->stampNew();
 225          }
 226  
 227          $isRegenerated = session_regenerate_id($destroy);
 228  
 229          // The reference to $_SESSION in session bags is lost in PHP7 and we need to re-create it.
 230          // @see https://bugs.php.net/bug.php?id=70013
 231          $this->loadSession();
 232  
 233          return $isRegenerated;
 234      }
 235  
 236      /**
 237       * {@inheritdoc}
 238       */
 239      public function save()
 240      {
 241          session_write_close();
 242  
 243          if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
 244              // This condition matches only PHP 5.3 with internal save handlers
 245              $this->saveHandler->setActive(false);
 246          }
 247  
 248          $this->closed = true;
 249          $this->started = false;
 250      }
 251  
 252      /**
 253       * {@inheritdoc}
 254       */
 255      public function clear()
 256      {
 257          // clear out the bags
 258          foreach ($this->bags as $bag) {
 259              $bag->clear();
 260          }
 261  
 262          // clear out the session
 263          $_SESSION = array();
 264  
 265          // reconnect the bags to the session
 266          $this->loadSession();
 267      }
 268  
 269      /**
 270       * {@inheritdoc}
 271       */
 272      public function registerBag(SessionBagInterface $bag)
 273      {
 274          if ($this->started) {
 275              throw new \LogicException('Cannot register a bag when the session is already started.');
 276          }
 277  
 278          $this->bags[$bag->getName()] = $bag;
 279      }
 280  
 281      /**
 282       * {@inheritdoc}
 283       */
 284      public function getBag($name)
 285      {
 286          if (!isset($this->bags[$name])) {
 287              throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
 288          }
 289  
 290          if (!$this->started && $this->saveHandler->isActive()) {
 291              $this->loadSession();
 292          } elseif (!$this->started) {
 293              $this->start();
 294          }
 295  
 296          return $this->bags[$name];
 297      }
 298  
 299      public function setMetadataBag(MetadataBag $metaBag = null)
 300      {
 301          if (null === $metaBag) {
 302              $metaBag = new MetadataBag();
 303          }
 304  
 305          $this->metadataBag = $metaBag;
 306      }
 307  
 308      /**
 309       * Gets the MetadataBag.
 310       *
 311       * @return MetadataBag
 312       */
 313      public function getMetadataBag()
 314      {
 315          return $this->metadataBag;
 316      }
 317  
 318      /**
 319       * {@inheritdoc}
 320       */
 321      public function isStarted()
 322      {
 323          return $this->started;
 324      }
 325  
 326      /**
 327       * Sets session.* ini variables.
 328       *
 329       * For convenience we omit 'session.' from the beginning of the keys.
 330       * Explicitly ignores other ini keys.
 331       *
 332       * @param array $options Session ini directives array(key => value)
 333       *
 334       * @see http://php.net/session.configuration
 335       */
 336      public function setOptions(array $options)
 337      {
 338          if (headers_sent() || (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status())) {
 339              return;
 340          }
 341  
 342          $validOptions = array_flip(array(
 343              'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly',
 344              'cookie_lifetime', 'cookie_path', 'cookie_secure',
 345              'entropy_file', 'entropy_length', 'gc_divisor',
 346              'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
 347              'hash_function', 'lazy_write', 'name', 'referer_check',
 348              'serialize_handler', 'use_strict_mode', 'use_cookies',
 349              'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
 350              'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
 351              'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags',
 352              'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags',
 353          ));
 354  
 355          foreach ($options as $key => $value) {
 356              if (isset($validOptions[$key])) {
 357                  ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value);
 358              }
 359          }
 360      }
 361  
 362      /**
 363       * Registers session save handler as a PHP session handler.
 364       *
 365       * To use internal PHP session save handlers, override this method using ini_set with
 366       * session.save_handler and session.save_path e.g.
 367       *
 368       *     ini_set('session.save_handler', 'files');
 369       *     ini_set('session.save_path', '/tmp');
 370       *
 371       * or pass in a NativeSessionHandler instance which configures session.save_handler in the
 372       * constructor, for a template see NativeFileSessionHandler or use handlers in
 373       * composer package drak/native-session
 374       *
 375       * @see http://php.net/session-set-save-handler
 376       * @see http://php.net/sessionhandlerinterface
 377       * @see http://php.net/sessionhandler
 378       * @see http://github.com/drak/NativeSession
 379       *
 380       * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $saveHandler
 381       *
 382       * @throws \InvalidArgumentException
 383       */
 384      public function setSaveHandler($saveHandler = null)
 385      {
 386          if (!$saveHandler instanceof AbstractProxy &&
 387              !$saveHandler instanceof NativeSessionHandler &&
 388              !$saveHandler instanceof \SessionHandlerInterface &&
 389              null !== $saveHandler) {
 390              throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.');
 391          }
 392  
 393          // Wrap $saveHandler in proxy and prevent double wrapping of proxy
 394          if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
 395              $saveHandler = new SessionHandlerProxy($saveHandler);
 396          } elseif (!$saveHandler instanceof AbstractProxy) {
 397              $saveHandler = \PHP_VERSION_ID >= 50400 ?
 398                  new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy();
 399          }
 400          $this->saveHandler = $saveHandler;
 401  
 402          if (headers_sent() || (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status())) {
 403              return;
 404          }
 405  
 406          if ($this->saveHandler instanceof \SessionHandlerInterface) {
 407              if (\PHP_VERSION_ID >= 50400) {
 408                  session_set_save_handler($this->saveHandler, false);
 409              } else {
 410                  session_set_save_handler(
 411                      array($this->saveHandler, 'open'),
 412                      array($this->saveHandler, 'close'),
 413                      array($this->saveHandler, 'read'),
 414                      array($this->saveHandler, 'write'),
 415                      array($this->saveHandler, 'destroy'),
 416                      array($this->saveHandler, 'gc')
 417                  );
 418              }
 419          }
 420      }
 421  
 422      /**
 423       * Load the session with attributes.
 424       *
 425       * After starting the session, PHP retrieves the session from whatever handlers
 426       * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()).
 427       * PHP takes the return value from the read() handler, unserializes it
 428       * and populates $_SESSION with the result automatically.
 429       */
 430      protected function loadSession(array &$session = null)
 431      {
 432          if (null === $session) {
 433              $session = &$_SESSION;
 434          }
 435  
 436          $bags = array_merge($this->bags, array($this->metadataBag));
 437  
 438          foreach ($bags as $bag) {
 439              $key = $bag->getStorageKey();
 440              $session[$key] = isset($session[$key]) ? $session[$key] : array();
 441              $bag->initialize($session[$key]);
 442          }
 443  
 444          $this->started = true;
 445          $this->closed = false;
 446      }
 447  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1