payload.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <?php namespace Laravel\Session;
  2. use Closure;
  3. use Laravel\Arr;
  4. use Laravel\Str;
  5. use Laravel\Config;
  6. use Laravel\Cookie;
  7. use Laravel\Session\Drivers\Driver;
  8. use Laravel\Session\Drivers\Sweeper;
  9. if (Config::$items['application']['key'] === '')
  10. {
  11. throw new \LogicException("An application key is required to use sessions.");
  12. }
  13. class Payload {
  14. /**
  15. * The session array that is stored by the driver.
  16. *
  17. * @var array
  18. */
  19. public $session;
  20. /**
  21. * Indicates if the session already exists in storage.
  22. *
  23. * @var bool
  24. */
  25. protected $exists = true;
  26. /**
  27. * The session driver used to retrieve and store the session payload.
  28. *
  29. * @var Driver
  30. */
  31. protected $driver;
  32. /**
  33. * Create a new session payload instance.
  34. *
  35. * @param Driver $driver
  36. * @return void
  37. */
  38. public function __construct(Driver $driver)
  39. {
  40. $this->driver = $driver;
  41. }
  42. /**
  43. * Load the session for the current request.
  44. *
  45. * @param string $id
  46. * @return void
  47. */
  48. public function load($id)
  49. {
  50. if ( ! is_null($id)) $this->session = $this->driver->load($id);
  51. // If the session doesn't exist or is invalid, we will create a new session
  52. // array and mark the session as being non-existent. Some drivers, such as
  53. // the database driver, need to know whether the session exists in storage
  54. // so they can know whether to "insert" or "update" the session.
  55. if (is_null($this->session) or $this->invalid())
  56. {
  57. $this->exists = false;
  58. $this->session = array('id' => Str::random(40), 'data' => array(
  59. ':new:' => array(),
  60. ':old:' => array(),
  61. ));
  62. }
  63. // A CSRF token is stored in every session. The token is used by the Form
  64. // class and the "csrf" filter to protect the application from cross-site
  65. // request forgery attacks. The token is simply a long, random string
  66. // which should be posted with each request.
  67. if ( ! $this->has('csrf_token'))
  68. {
  69. $this->put('csrf_token', Str::random(40));
  70. }
  71. }
  72. /**
  73. * Deteremine if the session payload instance is valid.
  74. *
  75. * The session is considered valid if it exists and has not expired.
  76. *
  77. * @return bool
  78. */
  79. protected function invalid()
  80. {
  81. $lifetime = Config::$items['session']['lifetime'];
  82. return (time() - $this->session['last_activity']) > ($lifetime * 60);
  83. }
  84. /**
  85. * Determine if session handling has been started for the request.
  86. *
  87. * @return bool
  88. */
  89. public function started()
  90. {
  91. return is_array($this->session);
  92. }
  93. /**
  94. * Determine if the session or flash data contains an item.
  95. *
  96. * @param string $key
  97. * @return bool
  98. */
  99. public function has($key)
  100. {
  101. return ( ! is_null($this->get($key)));
  102. }
  103. /**
  104. * Get an item from the session.
  105. *
  106. * The session flash data will also be checked for the requested item.
  107. *
  108. * <code>
  109. * // Get an item from the session
  110. * $name = Session::get('name');
  111. *
  112. * // Return a default value if the item doesn't exist
  113. * $name = Session::get('name', 'Taylor');
  114. * </code>
  115. *
  116. * @param string $key
  117. * @param mixed $default
  118. * @return mixed
  119. */
  120. public function get($key, $default = null)
  121. {
  122. if (isset($this->session['data'][$key]))
  123. {
  124. return $this->session['data'][$key];
  125. }
  126. elseif (isset($this->session['data'][':new:'][$key]))
  127. {
  128. return $this->session['data'][':new:'][$key];
  129. }
  130. elseif (isset($this->session['data'][':old:'][$key]))
  131. {
  132. return $this->session['data'][':old:'][$key];
  133. }
  134. return ($default instanceof Closure) ? call_user_func($default) : $default;
  135. }
  136. /**
  137. * Write an item to the session.
  138. *
  139. * @param string $key
  140. * @param mixed $value
  141. * @return void
  142. */
  143. public function put($key, $value)
  144. {
  145. Arr::set($this->session['data'], $key, $value);
  146. }
  147. /**
  148. * Write an item to the session flash data.
  149. *
  150. * Flash data only exists for the next request to the application, and is
  151. * useful for storing temporary data such as error or status messages.
  152. *
  153. * @param string $key
  154. * @param mixed $value
  155. * @return void
  156. */
  157. public function flash($key, $value)
  158. {
  159. Arr::set($this->session['data'][':new:'], $key, $value);
  160. }
  161. /**
  162. * Keep the session flash data from expiring at the end of the request.
  163. *
  164. * @return void
  165. */
  166. public function reflash()
  167. {
  168. $old = $this->session['data'][':old:'];
  169. $this->session['data'][':new:'] = array_merge($this->session['data'][':new:'], $old);
  170. }
  171. /**
  172. * Keep a session flash item from expiring at the end of the request.
  173. *
  174. * @param string|array $key
  175. * @return void
  176. */
  177. public function keep($keys)
  178. {
  179. foreach ((array) $keys as $key)
  180. {
  181. $this->flash($key, $this->get($key));
  182. }
  183. }
  184. /**
  185. * Remove an item from the session data.
  186. *
  187. * @param string $key
  188. * @return void
  189. */
  190. public function forget($key)
  191. {
  192. Arr::forget($this->session['data'], $key);
  193. }
  194. /**
  195. * Remove all of the items from the session.
  196. *
  197. * @return void
  198. */
  199. public function flush()
  200. {
  201. $this->session['data'] = array();
  202. }
  203. /**
  204. * Assign a new, random ID to the session.
  205. *
  206. * @return void
  207. */
  208. public function regenerate()
  209. {
  210. $this->session['id'] = Str::random(40);
  211. $this->exists = false;
  212. }
  213. /**
  214. * Get the CSRF token that is stored in the session data.
  215. *
  216. * @return string
  217. */
  218. public function token()
  219. {
  220. return $this->get('csrf_token');
  221. }
  222. /**
  223. * Store the session payload in storage.
  224. *
  225. * @return void
  226. */
  227. public function save()
  228. {
  229. $this->session['last_activity'] = time();
  230. $this->age();
  231. $config = Config::$items['session'];
  232. $this->driver->save($this->session, $config, $this->exists);
  233. $this->cookie();
  234. // Some session drivers implement the Sweeper interface, meaning that they
  235. // must clean up expired sessions manually. If the driver is a sweeper, we
  236. // need to determine if garbage collection should be run for the request.
  237. // Since garbage collection can be expensive, the probability of it
  238. // occuring is controlled by the "sweepage" configuration option.
  239. $sweepage = $config['sweepage'];
  240. if ($this->driver instanceof Sweeper and (mt_rand(1, $sweepage[1]) <= $sweepage[0]))
  241. {
  242. $this->driver->sweep(time() - ($config['lifetime'] * 60));
  243. }
  244. }
  245. /**
  246. * Age the session flash data.
  247. *
  248. * Session flash data is only available during the request in which it
  249. * was flashed, and the request after that. To "age" the data, we will
  250. * remove all of the :old: items and re-address the new items.
  251. *
  252. * @return void
  253. */
  254. protected function age()
  255. {
  256. $this->session['data'][':old:'] = $this->session['data'][':new:'];
  257. $this->session['data'][':new:'] = array();
  258. }
  259. /**
  260. * Send the session ID cookie to the browser.
  261. *
  262. * @return void
  263. */
  264. protected function cookie()
  265. {
  266. $config = Config::$items['session'];
  267. extract($config, EXTR_SKIP);
  268. $minutes = ( ! $expire_on_close) ? $lifetime : 0;
  269. Cookie::put($cookie, $this->session['id'], $minutes, $path, $domain, $secure);
  270. }
  271. }