/lib/vendor/symfony/lib/storage/sfCacheSessionStorage.class.php

https://github.com/proyectoalba/alba · PHP · 258 lines · 143 code · 30 blank · 85 comment · 14 complexity · ea7ffc65f692badd34194f7a4c125b29 MD5 · raw file

  1. <?php
  2. /**
  3. * sfCacheSessionStorage manages session storage via a signed cookie and cache backend.
  4. *
  5. * This class stores the session data in via sfCache instance and with an id issued in a
  6. * signed cookie. Useful when you don't want to store the session.
  7. *
  8. * @package symfony
  9. * @subpackage storage
  10. * @author Dustin Whittle <dustin.whittle@symfony-project.com>
  11. */
  12. class sfCacheSessionStorage extends sfStorage
  13. {
  14. protected
  15. $id = null,
  16. $context = null,
  17. $dispatcher = null,
  18. $request = null,
  19. $response = null,
  20. $cache = null,
  21. $data = array(),
  22. $dataChanged = false;
  23. /**
  24. * Initialize this Storage.
  25. *
  26. * @param array $options An associative array of initialization parameters.
  27. * session_name [required] name of session to use
  28. * session_cookie_path [required] cookie path
  29. * session_cookie_domain [required] cookie domain
  30. * session_cookie_lifetime [required] liftime of cookie
  31. * session_cookie_secure [required] send only if secure connection
  32. * session_cookie_http_only [required] accessible only via http protocol
  33. *
  34. * @return bool true, when initialization completes successfully, otherwise false.
  35. *
  36. * @throws <b>sfInitializationException</b> If an error occurs while initializing this Storage.
  37. */
  38. public function initialize($options = array())
  39. {
  40. // initialize parent
  41. parent::initialize(array_merge(array('session_name' => 'sfproject',
  42. 'session_cookie_lifetime' => '+30 days',
  43. 'session_cookie_path' => '/',
  44. 'session_cookie_domain' => null,
  45. 'session_cookie_secure' => false,
  46. 'session_cookie_http_only' => true,
  47. 'session_cookie_secret' => 'sf$ecret'), $options));
  48. // create cache instance
  49. if (isset($this->options['cache']) && $this->options['cache']['class'])
  50. {
  51. $this->cache = new $this->options['cache']['class'](is_array($this->options['cache']['param']) ? $this->options['cache']['param'] : array());
  52. }
  53. else
  54. {
  55. throw new InvalidArgumentException('sfCacheSessionStorage requires cache option.');
  56. }
  57. $this->context = sfContext::getInstance();
  58. $this->dispatcher = $this->context->getEventDispatcher();
  59. $this->request = $this->context->getRequest();
  60. $this->response = $this->context->getResponse();
  61. $cookie = $this->request->getCookie($this->options['session_name']);
  62. if(strpos($cookie, ':') !== false)
  63. {
  64. // split cookie data id:signature(id+secret)
  65. list($id, $signature) = explode(':', $cookie, 2);
  66. if($signature == sha1($id.':'.$this->options['session_cookie_secret']))
  67. {
  68. // cookie is valid
  69. $this->id = $id;
  70. }
  71. else
  72. {
  73. // cookie signature broken
  74. $this->id = null;
  75. }
  76. }
  77. else
  78. {
  79. // cookie format wrong
  80. $this->id = null;
  81. }
  82. if(empty($this->id))
  83. {
  84. $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'localhost';
  85. $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'ua';
  86. // generate new id based on random # / ip / user agent / secret
  87. $this->id = md5(rand(0, 999999).$ip.$ua.$this->options['session_cookie_secret']);
  88. if(sfConfig::get('sf_logging_enabled'))
  89. {
  90. $this->dispatcher->notify(new sfEvent($this, 'application.log', array('New session created')));
  91. }
  92. // only send cookie when id is issued
  93. $this->response->setCookie($this->options['session_name'],
  94. $this->id.':'.sha1($this->id.':'.$this->options['session_cookie_secret']),
  95. $this->options['session_cookie_lifetime'],
  96. $this->options['session_cookie_path'],
  97. $this->options['session_cookie_domain'],
  98. $this->options['session_cookie_secure'],
  99. $this->options['session_cookie_http_only']);
  100. $this->data = array();
  101. }
  102. else
  103. {
  104. // load data from cache
  105. $this->data = $this->cache->get($this->id, array());
  106. if(sfConfig::get('sf_logging_enabled'))
  107. {
  108. $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Restored previous session')));
  109. }
  110. }
  111. session_id($this->id);
  112. return true;
  113. }
  114. /**
  115. * Write data to this storage.
  116. *
  117. * The preferred format for a key is directory style so naming conflicts can be avoided.
  118. *
  119. * @param string $key A unique key identifying your data.
  120. * @param mixed $data Data associated with your key.
  121. *
  122. * @return void
  123. */
  124. public function write($key, $data)
  125. {
  126. $this->dataChanged = true;
  127. $this->data[$key] =& $data;
  128. }
  129. /**
  130. * Read data from this storage.
  131. *
  132. * The preferred format for a key is directory style so naming conflicts can be avoided.
  133. *
  134. * @param string $key A unique key identifying your data.
  135. *
  136. * @return mixed Data associated with the key.
  137. */
  138. public function read($key)
  139. {
  140. $retval = null;
  141. if (isset($this->data[$key]))
  142. {
  143. $retval =& $this->data[$key];
  144. }
  145. return $retval;
  146. }
  147. /**
  148. * Remove data from this storage.
  149. *
  150. * The preferred format for a key is directory style so naming conflicts can be avoided.
  151. *
  152. * @param string $key A unique key identifying your data.
  153. *
  154. * @return mixed Data associated with the key.
  155. */
  156. public function remove($key)
  157. {
  158. $retval = null;
  159. if (isset($this->data[$key]))
  160. {
  161. $this->dataChanged = true;
  162. $retval =& $this->data[$key];
  163. unset($this->data[$key]);
  164. }
  165. return $retval;
  166. }
  167. /**
  168. * Regenerates id that represents this storage.
  169. *
  170. * @param boolean $destroy Destroy session when regenerating?
  171. *
  172. * @return boolean True if session regenerated, false if error
  173. *
  174. * @throws <b>sfStorageException</b> If an error occurs while regenerating this storage
  175. */
  176. public function regenerate($destroy = false)
  177. {
  178. if($destroy)
  179. {
  180. $this->data = array();
  181. $this->cache->remove($this->id);
  182. }
  183. // generate session id
  184. $this->id = md5(rand(0, 999999).$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'].$this->options['session_cookie_secret']);
  185. // save data to cache
  186. $this->cache->set($this->id, $this->data);
  187. // update session id in signed cookie
  188. $this->response->setCookie($this->options['session_name'],
  189. $this->id.':'.sha1($this->id.':'.$this->options['session_cookie_secret']),
  190. $this->options['session_cookie_lifetime'],
  191. $this->options['session_cookie_path'],
  192. $this->options['session_cookie_domain'],
  193. $this->options['session_cookie_secure'],
  194. $this->options['session_cookie_http_only']);
  195. session_id($this->id);
  196. return true;
  197. }
  198. /**
  199. * Expires the session storage instance.
  200. */
  201. public function expire()
  202. {
  203. // destroy data and regenerate id
  204. $this->regenerate(true);
  205. if(sfConfig::get('sf_logging_enabled'))
  206. {
  207. $this->dispatcher->notify(new sfEvent($this, 'application.log', array('new session created due to expiraton')));
  208. }
  209. }
  210. /**
  211. * Executes the shutdown procedure.
  212. *
  213. * @throws <b>sfStorageException</b> If an error occurs while shutting down this storage
  214. */
  215. public function shutdown()
  216. {
  217. // only update cache if session has changed
  218. if($this->dataChanged === true)
  219. {
  220. $this->cache->set($this->id, $this->data);
  221. if(sfConfig::get('sf_logging_enabled'))
  222. {
  223. $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Storing session to cache')));
  224. // $this->dispatcher->notify(new sfEvent($this, 'application.log', array(var_export($this->data, true))));
  225. }
  226. }
  227. }
  228. }