PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/core/classes/session/file.php

https://github.com/akutaktau/feedmalaya
PHP | 351 lines | 179 code | 60 blank | 112 comment | 27 complexity | 9e264fcff891af309e4fdc53874e04f8 MD5 | raw file
  1. <?php
  2. /**
  3. * Fuel
  4. *
  5. * Fuel is a fast, lightweight, community driven PHP5 framework.
  6. *
  7. * @package Fuel
  8. * @version 1.0
  9. * @author Fuel Development Team
  10. * @license MIT License
  11. * @copyright 2010 - 2011 Fuel Development Team
  12. * @link http://fuelphp.com
  13. */
  14. namespace Fuel\Core;
  15. // --------------------------------------------------------------------
  16. class Session_File extends Session_Driver {
  17. /**
  18. * array of driver config defaults
  19. */
  20. protected static $_defaults = array(
  21. 'cookie_name' => 'fuelfid', // name of the session cookie for file based sessions
  22. 'path' => '/tmp', // path where the session files should be stored
  23. 'gc_probability' => 5 // probability % (between 0 and 100) for garbage collection
  24. );
  25. // --------------------------------------------------------------------
  26. public function __construct($config = array())
  27. {
  28. // merge the driver config with the global config
  29. $this->config = array_merge($config, is_array($config['file']) ? $config['file'] : static::$_defaults);
  30. $this->config = $this->_validate_config($this->config);
  31. }
  32. // --------------------------------------------------------------------
  33. /**
  34. * create a new session
  35. *
  36. * @access public
  37. * @return void
  38. */
  39. public function create()
  40. {
  41. // create a new session
  42. $this->keys['session_id'] = $this->_new_session_id();
  43. $this->keys['previous_id'] = $this->keys['session_id']; // prevents errors if previous_id has a unique index
  44. $this->keys['ip_address'] = \Input::real_ip();
  45. $this->keys['user_agent'] = \Input::user_agent();
  46. $this->keys['created'] = $this->time->get_timestamp();
  47. $this->keys['updated'] = $this->keys['created'];
  48. // create the session record
  49. $this->_write_file($this->keys['session_id'], serialize(array()));
  50. // and set the session cookie
  51. $this->_set_cookie();
  52. }
  53. // --------------------------------------------------------------------
  54. /**
  55. * read the session
  56. *
  57. * @access public
  58. * @param boolean, set to true if we want to force a new session to be created
  59. * @return void
  60. */
  61. public function read($force = false)
  62. {
  63. // get the session cookie
  64. $cookie = $this->_get_cookie();
  65. // if no session cookie was present, create it
  66. if ($cookie === false or $force)
  67. {
  68. $this->create();
  69. }
  70. // read the session file
  71. $payload = $this->_read_file($this->keys['session_id']);
  72. if ($payload === false)
  73. {
  74. // try to find the previous one
  75. $payload = $this->_read_file($this->keys['previous_id']);
  76. if ($payload === false)
  77. {
  78. // cookie present, but session record missing. force creation of a new session
  79. $this->read(true);
  80. return;
  81. }
  82. }
  83. // unpack the payload
  84. $payload = $this->_unserialize($payload);
  85. // session referral?
  86. if (isset($payload['rotated_session_id']))
  87. {
  88. $payload = $this->_read_file($payload['rotated_session_id']);
  89. if ($payload === false)
  90. {
  91. // cookie present, but session record missing. force creation of a new session
  92. $this->read(true);
  93. return;
  94. }
  95. else
  96. {
  97. // update the session
  98. $this->keys['previous_id'] = $this->keys['session_id'];
  99. $this->keys['session_id'] = $payload['rotated_session_id'];
  100. // unpack the payload
  101. $payload = $this->_unserialize($payload);
  102. }
  103. }
  104. if (isset($payload[0])) $this->data = $payload[0];
  105. if (isset($payload[1])) $this->flash = $payload[1];
  106. parent::read();
  107. }
  108. // --------------------------------------------------------------------
  109. /**
  110. * write the session
  111. *
  112. * @access public
  113. * @return void
  114. */
  115. public function write()
  116. {
  117. // do we have something to write?
  118. if ( ! empty($this->keys))
  119. {
  120. parent::write();
  121. // rotate the session id if needed
  122. $this->rotate(false);
  123. // session payload
  124. $payload = $this->_serialize(array($this->data, $this->flash));
  125. // create the session file
  126. $this->_write_file($this->keys['session_id'], $payload);
  127. // was the session id rotated?
  128. if ( isset($this->keys['previous_id']) && $this->keys['previous_id'] != $this->keys['session_id'])
  129. {
  130. // point the old session file to the new one, we don't want to lose the session
  131. $payload = $this->_serialize(array('rotated_session_id' => $this->keys['session_id']));
  132. $this->_write_file($this->keys['previous_id'], $payload);
  133. }
  134. $this->_set_cookie();
  135. // do some garbage collection
  136. if (mt_rand(0,100) < $this->config['gc_probability'])
  137. {
  138. if ($handle = opendir($this->config['path']))
  139. {
  140. $expire = $this->time->get_timestamp() - $this->config['expiration_time'];
  141. while (($file = readdir($handle)) !== false)
  142. {
  143. if (filetype($this->config['path'] . $file) == 'file' &&
  144. strpos($file, $this->config['cookie_name'].'_') === 0 &&
  145. filemtime($this->config['path'] . $file) < $expire)
  146. {
  147. @unlink($this->config['path'] . $file);
  148. }
  149. }
  150. closedir($handle);
  151. }
  152. }
  153. }
  154. }
  155. // --------------------------------------------------------------------
  156. /**
  157. * destroy the current session
  158. *
  159. * @access public
  160. * @return void
  161. */
  162. public function destroy()
  163. {
  164. // do we have something to destroy?
  165. if ( ! empty($this->keys))
  166. {
  167. // delete the session file
  168. $file = $this->config['path'].$this->config['cookie_name'].'_'.$this->keys['session_id'];
  169. if (file_exists($file))
  170. {
  171. unlink($file);
  172. }
  173. }
  174. // reset the stored session data
  175. $this->keys = $this->flash = $this->data = array();
  176. }
  177. // --------------------------------------------------------------------
  178. /**
  179. * Writes the session file
  180. *
  181. * @access private
  182. * @return boolean, true if it was an existing session, false if not
  183. */
  184. protected function _write_file($session_id, $payload)
  185. {
  186. // create the session file
  187. $file = $this->config['path'].$this->config['cookie_name'].'_'.$session_id;
  188. $exists = file_exists($file);
  189. $handle = fopen($file,'c');
  190. if ($handle)
  191. {
  192. // wait for a lock
  193. while(!flock($handle, LOCK_EX));
  194. // erase existing contents
  195. ftruncate($handle, 0);
  196. // write the session data
  197. fwrite($handle, $payload);
  198. //release the lock
  199. flock($handle, LOCK_UN);
  200. // close the file
  201. fclose($handle);
  202. }
  203. return $exists;
  204. }
  205. // --------------------------------------------------------------------
  206. /**
  207. * Reads the session file
  208. *
  209. * @access private
  210. * @return mixed, the payload if the file exists, or false if not
  211. */
  212. protected function _read_file($session_id)
  213. {
  214. $payload = false;
  215. $file = $this->config['path'].$this->config['cookie_name'].'_'.$session_id;
  216. if (file_exists($file))
  217. {
  218. $handle = fopen($file,'r');
  219. if ($handle)
  220. {
  221. // wait for a lock
  222. while(!flock($handle, LOCK_EX));
  223. // read the session data
  224. $payload = fread($handle, filesize($file));
  225. //release the lock
  226. flock($handle, LOCK_UN);
  227. // close the file
  228. fclose($handle);
  229. }
  230. }
  231. return $payload;
  232. }
  233. // --------------------------------------------------------------------
  234. /**
  235. * validate a driver config value
  236. *
  237. * @param array array with configuration values
  238. * @access public
  239. * @return array validated and consolidated config
  240. */
  241. public function _validate_config($config)
  242. {
  243. $validated = array();
  244. foreach ($config as $name => $item)
  245. {
  246. // filter out any driver config
  247. if (!is_array($item))
  248. {
  249. switch ($name)
  250. {
  251. case 'cookie_name':
  252. if ( empty($item) OR ! is_string($item))
  253. {
  254. $item = 'fuelfid';
  255. }
  256. break;
  257. case 'path':
  258. // do we have a path?
  259. if ( empty($item) OR ! is_dir($item))
  260. {
  261. throw new \Fuel_Exception('You have specify a valid path to store the session data files.');
  262. }
  263. // and can we write to it?
  264. if ( ! is_writable($item))
  265. {
  266. throw new \Fuel_Exception('The webserver doesn\'t have write access to the path to store the session data files.');
  267. }
  268. // update the path, and add the trailing slash
  269. $item = realpath($item).'/';
  270. break;
  271. case 'gc_probability':
  272. // do we have a path?
  273. if ( ! is_numeric($item) OR $item < 0 OR $item > 100)
  274. {
  275. // default value: 5%
  276. $item = 5;
  277. }
  278. break;
  279. default:
  280. // no config item for this driver
  281. break;
  282. }
  283. // global config, was validated in the driver
  284. $validated[$name] = $item;
  285. }
  286. }
  287. // validate all global settings as well
  288. return parent::_validate_config($validated);
  289. }
  290. }
  291. /* End of file file.php */