PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php

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