payload.php 6.5 KB

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