Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | 7a779792577d |
children | c2387f117808 |
comparison
equal
deleted
inserted
replaced
13:5fb285c0d0e3 | 14:1fec387a4317 |
---|---|
10 */ | 10 */ |
11 | 11 |
12 namespace Symfony\Component\HttpFoundation\Session\Storage; | 12 namespace Symfony\Component\HttpFoundation\Session\Storage; |
13 | 13 |
14 use Symfony\Component\HttpFoundation\Session\SessionBagInterface; | 14 use Symfony\Component\HttpFoundation\Session\SessionBagInterface; |
15 use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; | 15 use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; |
16 use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; | 16 use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; |
17 use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; | 17 use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; |
18 | 18 |
19 /** | 19 /** |
20 * This provides a base class for session attribute storage. | 20 * This provides a base class for session attribute storage. |
22 * @author Drak <drak@zikula.org> | 22 * @author Drak <drak@zikula.org> |
23 */ | 23 */ |
24 class NativeSessionStorage implements SessionStorageInterface | 24 class NativeSessionStorage implements SessionStorageInterface |
25 { | 25 { |
26 /** | 26 /** |
27 * Array of SessionBagInterface. | |
28 * | |
29 * @var SessionBagInterface[] | 27 * @var SessionBagInterface[] |
30 */ | 28 */ |
31 protected $bags; | 29 protected $bags = array(); |
32 | 30 |
33 /** | 31 /** |
34 * @var bool | 32 * @var bool |
35 */ | 33 */ |
36 protected $started = false; | 34 protected $started = false; |
39 * @var bool | 37 * @var bool |
40 */ | 38 */ |
41 protected $closed = false; | 39 protected $closed = false; |
42 | 40 |
43 /** | 41 /** |
44 * @var AbstractProxy | 42 * @var AbstractProxy|\SessionHandlerInterface |
45 */ | 43 */ |
46 protected $saveHandler; | 44 protected $saveHandler; |
47 | 45 |
48 /** | 46 /** |
49 * @var MetadataBag | 47 * @var MetadataBag |
50 */ | 48 */ |
51 protected $metadataBag; | 49 protected $metadataBag; |
52 | 50 |
53 /** | 51 /** |
54 * Constructor. | |
55 * | |
56 * Depending on how you want the storage driver to behave you probably | 52 * Depending on how you want the storage driver to behave you probably |
57 * want to override this constructor entirely. | 53 * want to override this constructor entirely. |
58 * | 54 * |
59 * List of options for $options array with their defaults. | 55 * List of options for $options array with their defaults. |
60 * | 56 * |
63 * | 59 * |
64 * ("auto_start", is not supported as it tells PHP to start a session before | 60 * ("auto_start", is not supported as it tells PHP to start a session before |
65 * PHP starts to execute user-land code. Setting during runtime has no effect). | 61 * PHP starts to execute user-land code. Setting during runtime has no effect). |
66 * | 62 * |
67 * cache_limiter, "" (use "0" to prevent headers from being sent entirely). | 63 * cache_limiter, "" (use "0" to prevent headers from being sent entirely). |
64 * cache_expire, "0" | |
68 * cookie_domain, "" | 65 * cookie_domain, "" |
69 * cookie_httponly, "" | 66 * cookie_httponly, "" |
70 * cookie_lifetime, "0" | 67 * cookie_lifetime, "0" |
71 * cookie_path, "/" | 68 * cookie_path, "/" |
72 * cookie_secure, "" | 69 * cookie_secure, "" |
75 * gc_divisor, "100" | 72 * gc_divisor, "100" |
76 * gc_maxlifetime, "1440" | 73 * gc_maxlifetime, "1440" |
77 * gc_probability, "1" | 74 * gc_probability, "1" |
78 * hash_bits_per_character, "4" | 75 * hash_bits_per_character, "4" |
79 * hash_function, "0" | 76 * hash_function, "0" |
77 * lazy_write, "1" | |
80 * name, "PHPSESSID" | 78 * name, "PHPSESSID" |
81 * referer_check, "" | 79 * referer_check, "" |
82 * serialize_handler, "php" | 80 * serialize_handler, "php" |
83 * use_strict_mode, "0" | 81 * use_strict_mode, "0" |
84 * use_cookies, "1" | 82 * use_cookies, "1" |
94 * sid_length, "32" | 92 * sid_length, "32" |
95 * sid_bits_per_character, "5" | 93 * sid_bits_per_character, "5" |
96 * trans_sid_hosts, $_SERVER['HTTP_HOST'] | 94 * trans_sid_hosts, $_SERVER['HTTP_HOST'] |
97 * trans_sid_tags, "a=href,area=href,frame=src,form=" | 95 * trans_sid_tags, "a=href,area=href,frame=src,form=" |
98 * | 96 * |
99 * @param array $options Session configuration options | 97 * @param array $options Session configuration options |
100 * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler | 98 * @param \SessionHandlerInterface|null $handler |
101 * @param MetadataBag $metaBag MetadataBag | 99 * @param MetadataBag $metaBag MetadataBag |
102 */ | 100 */ |
103 public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) | 101 public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) |
104 { | 102 { |
105 session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used) | 103 $options += array( |
106 ini_set('session.use_cookies', 1); | 104 'cache_limiter' => '', |
105 'cache_expire' => 0, | |
106 'use_cookies' => 1, | |
107 'lazy_write' => 1, | |
108 ); | |
107 | 109 |
108 session_register_shutdown(); | 110 session_register_shutdown(); |
109 | 111 |
110 $this->setMetadataBag($metaBag); | 112 $this->setMetadataBag($metaBag); |
111 $this->setOptions($options); | 113 $this->setOptions($options); |
113 } | 115 } |
114 | 116 |
115 /** | 117 /** |
116 * Gets the save handler instance. | 118 * Gets the save handler instance. |
117 * | 119 * |
118 * @return AbstractProxy | 120 * @return AbstractProxy|\SessionHandlerInterface |
119 */ | 121 */ |
120 public function getSaveHandler() | 122 public function getSaveHandler() |
121 { | 123 { |
122 return $this->saveHandler; | 124 return $this->saveHandler; |
123 } | 125 } |
189 // Cannot regenerate the session ID for non-active sessions. | 191 // Cannot regenerate the session ID for non-active sessions. |
190 if (\PHP_SESSION_ACTIVE !== session_status()) { | 192 if (\PHP_SESSION_ACTIVE !== session_status()) { |
191 return false; | 193 return false; |
192 } | 194 } |
193 | 195 |
196 if (headers_sent()) { | |
197 return false; | |
198 } | |
199 | |
194 if (null !== $lifetime) { | 200 if (null !== $lifetime) { |
195 ini_set('session.cookie_lifetime', $lifetime); | 201 ini_set('session.cookie_lifetime', $lifetime); |
196 } | 202 } |
197 | 203 |
198 if ($destroy) { | 204 if ($destroy) { |
211 /** | 217 /** |
212 * {@inheritdoc} | 218 * {@inheritdoc} |
213 */ | 219 */ |
214 public function save() | 220 public function save() |
215 { | 221 { |
216 session_write_close(); | 222 $session = $_SESSION; |
223 | |
224 foreach ($this->bags as $bag) { | |
225 if (empty($_SESSION[$key = $bag->getStorageKey()])) { | |
226 unset($_SESSION[$key]); | |
227 } | |
228 } | |
229 if (array($key = $this->metadataBag->getStorageKey()) === array_keys($_SESSION)) { | |
230 unset($_SESSION[$key]); | |
231 } | |
232 | |
233 // Register custom error handler to catch a possible failure warning during session write | |
234 set_error_handler(function ($errno, $errstr, $errfile, $errline) { | |
235 throw new \ErrorException($errstr, $errno, E_WARNING, $errfile, $errline); | |
236 }, E_WARNING); | |
237 | |
238 try { | |
239 $e = null; | |
240 session_write_close(); | |
241 } catch (\ErrorException $e) { | |
242 } finally { | |
243 restore_error_handler(); | |
244 $_SESSION = $session; | |
245 } | |
246 if (null !== $e) { | |
247 // The default PHP error message is not very helpful, as it does not give any information on the current save handler. | |
248 // Therefore, we catch this error and trigger a warning with a better error message | |
249 $handler = $this->getSaveHandler(); | |
250 if ($handler instanceof SessionHandlerProxy) { | |
251 $handler = $handler->getHandler(); | |
252 } | |
253 | |
254 trigger_error(sprintf('session_write_close(): Failed to write session data with %s handler', get_class($handler)), E_USER_WARNING); | |
255 } | |
217 | 256 |
218 $this->closed = true; | 257 $this->closed = true; |
219 $this->started = false; | 258 $this->started = false; |
220 } | 259 } |
221 | 260 |
255 { | 294 { |
256 if (!isset($this->bags[$name])) { | 295 if (!isset($this->bags[$name])) { |
257 throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); | 296 throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); |
258 } | 297 } |
259 | 298 |
260 if ($this->saveHandler->isActive() && !$this->started) { | 299 if (!$this->started && $this->saveHandler->isActive()) { |
261 $this->loadSession(); | 300 $this->loadSession(); |
262 } elseif (!$this->started) { | 301 } elseif (!$this->started) { |
263 $this->start(); | 302 $this->start(); |
264 } | 303 } |
265 | 304 |
266 return $this->bags[$name]; | 305 return $this->bags[$name]; |
267 } | 306 } |
268 | 307 |
269 /** | |
270 * Sets the MetadataBag. | |
271 * | |
272 * @param MetadataBag $metaBag | |
273 */ | |
274 public function setMetadataBag(MetadataBag $metaBag = null) | 308 public function setMetadataBag(MetadataBag $metaBag = null) |
275 { | 309 { |
276 if (null === $metaBag) { | 310 if (null === $metaBag) { |
277 $metaBag = new MetadataBag(); | 311 $metaBag = new MetadataBag(); |
278 } | 312 } |
308 * | 342 * |
309 * @see http://php.net/session.configuration | 343 * @see http://php.net/session.configuration |
310 */ | 344 */ |
311 public function setOptions(array $options) | 345 public function setOptions(array $options) |
312 { | 346 { |
347 if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { | |
348 return; | |
349 } | |
350 | |
313 $validOptions = array_flip(array( | 351 $validOptions = array_flip(array( |
314 'cache_limiter', 'cookie_domain', 'cookie_httponly', | 352 'cache_limiter', 'cache_expire', 'cookie_domain', 'cookie_httponly', |
315 'cookie_lifetime', 'cookie_path', 'cookie_secure', | 353 'cookie_lifetime', 'cookie_path', 'cookie_secure', |
316 'entropy_file', 'entropy_length', 'gc_divisor', | 354 'entropy_file', 'entropy_length', 'gc_divisor', |
317 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', | 355 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', |
318 'hash_function', 'name', 'referer_check', | 356 'hash_function', 'lazy_write', 'name', 'referer_check', |
319 'serialize_handler', 'use_strict_mode', 'use_cookies', | 357 'serialize_handler', 'use_strict_mode', 'use_cookies', |
320 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', | 358 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', |
321 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', | 359 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', |
322 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', | 360 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', |
323 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', | 361 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', |
337 * session.save_handler and session.save_path e.g. | 375 * session.save_handler and session.save_path e.g. |
338 * | 376 * |
339 * ini_set('session.save_handler', 'files'); | 377 * ini_set('session.save_handler', 'files'); |
340 * ini_set('session.save_path', '/tmp'); | 378 * ini_set('session.save_path', '/tmp'); |
341 * | 379 * |
342 * or pass in a NativeSessionHandler instance which configures session.save_handler in the | 380 * or pass in a \SessionHandler instance which configures session.save_handler in the |
343 * constructor, for a template see NativeFileSessionHandler or use handlers in | 381 * constructor, for a template see NativeFileSessionHandler or use handlers in |
344 * composer package drak/native-session | 382 * composer package drak/native-session |
345 * | 383 * |
346 * @see http://php.net/session-set-save-handler | 384 * @see http://php.net/session-set-save-handler |
347 * @see http://php.net/sessionhandlerinterface | 385 * @see http://php.net/sessionhandlerinterface |
348 * @see http://php.net/sessionhandler | 386 * @see http://php.net/sessionhandler |
349 * @see http://github.com/drak/NativeSession | 387 * @see http://github.com/drak/NativeSession |
350 * | 388 * |
351 * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $saveHandler | 389 * @param \SessionHandlerInterface|null $saveHandler |
352 * | 390 * |
353 * @throws \InvalidArgumentException | 391 * @throws \InvalidArgumentException |
354 */ | 392 */ |
355 public function setSaveHandler($saveHandler = null) | 393 public function setSaveHandler($saveHandler = null) |
356 { | 394 { |
357 if (!$saveHandler instanceof AbstractProxy && | 395 if (!$saveHandler instanceof AbstractProxy && |
358 !$saveHandler instanceof NativeSessionHandler && | |
359 !$saveHandler instanceof \SessionHandlerInterface && | 396 !$saveHandler instanceof \SessionHandlerInterface && |
360 null !== $saveHandler) { | 397 null !== $saveHandler) { |
361 throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.'); | 398 throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); |
362 } | 399 } |
363 | 400 |
364 // Wrap $saveHandler in proxy and prevent double wrapping of proxy | 401 // Wrap $saveHandler in proxy and prevent double wrapping of proxy |
365 if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { | 402 if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { |
366 $saveHandler = new SessionHandlerProxy($saveHandler); | 403 $saveHandler = new SessionHandlerProxy($saveHandler); |
367 } elseif (!$saveHandler instanceof AbstractProxy) { | 404 } elseif (!$saveHandler instanceof AbstractProxy) { |
368 $saveHandler = new SessionHandlerProxy(new \SessionHandler()); | 405 $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler())); |
369 } | 406 } |
370 $this->saveHandler = $saveHandler; | 407 $this->saveHandler = $saveHandler; |
371 | 408 |
372 if ($this->saveHandler instanceof \SessionHandlerInterface) { | 409 if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { |
410 return; | |
411 } | |
412 | |
413 if ($this->saveHandler instanceof SessionHandlerProxy) { | |
414 session_set_save_handler($this->saveHandler->getHandler(), false); | |
415 } elseif ($this->saveHandler instanceof \SessionHandlerInterface) { | |
373 session_set_save_handler($this->saveHandler, false); | 416 session_set_save_handler($this->saveHandler, false); |
374 } | 417 } |
375 } | 418 } |
376 | 419 |
377 /** | 420 /** |
379 * | 422 * |
380 * After starting the session, PHP retrieves the session from whatever handlers | 423 * After starting the session, PHP retrieves the session from whatever handlers |
381 * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). | 424 * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). |
382 * PHP takes the return value from the read() handler, unserializes it | 425 * PHP takes the return value from the read() handler, unserializes it |
383 * and populates $_SESSION with the result automatically. | 426 * and populates $_SESSION with the result automatically. |
384 * | |
385 * @param array|null $session | |
386 */ | 427 */ |
387 protected function loadSession(array &$session = null) | 428 protected function loadSession(array &$session = null) |
388 { | 429 { |
389 if (null === $session) { | 430 if (null === $session) { |
390 $session = &$_SESSION; | 431 $session = &$_SESSION; |