PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/fuel/core/classes/session/db.php

https://gitlab.com/lttu1620/TEPPAN-API
PHP | 337 lines | 192 code | 50 blank | 95 comment | 21 complexity | 823d34b80680bde57acf275c69e21bba MD5 | raw file
  1. <?php
  2. /**
  3. * Part of the Fuel framework.
  4. *
  5. * @package Fuel
  6. * @version 1.7
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2014 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. // --------------------------------------------------------------------
  14. class Session_Db extends \Session_Driver
  15. {
  16. /*
  17. * @var session database result object
  18. */
  19. protected $record = null;
  20. /**
  21. * array of driver config defaults
  22. */
  23. protected static $_defaults = array(
  24. 'cookie_name' => 'fueldid', // name of the session cookie for database based sessions
  25. 'table' => 'sessions', // name of the sessions table
  26. 'gc_probability' => 5 // probability % (between 0 and 100) for garbage collection
  27. );
  28. // --------------------------------------------------------------------
  29. public function __construct($config = array())
  30. {
  31. // merge the driver config with the global config
  32. $this->config = array_merge($config, is_array($config['db']) ? $config['db'] : static::$_defaults);
  33. $this->config = $this->_validate_config($this->config);
  34. }
  35. // --------------------------------------------------------------------
  36. /**
  37. * create a new session
  38. *
  39. * @access public
  40. * @return Fuel\Core\Session_Db
  41. */
  42. public function create($payload = '')
  43. {
  44. // create a new session
  45. $this->keys['session_id'] = $this->_new_session_id();
  46. $this->keys['previous_id'] = $this->keys['session_id']; // prevents errors if previous_id has a unique index
  47. $this->keys['ip_hash'] = md5(\Input::ip().\Input::real_ip());
  48. $this->keys['user_agent'] = \Input::user_agent();
  49. $this->keys['created'] = $this->time->get_timestamp();
  50. $this->keys['updated'] = $this->keys['created'];
  51. // add the payload
  52. $this->keys['payload'] = $payload;
  53. return $this;
  54. }
  55. // --------------------------------------------------------------------
  56. /**
  57. * read the session
  58. *
  59. * @access public
  60. * @param boolean, set to true if we want to force a new session to be created
  61. * @return Fuel\Core\Session_Driver
  62. */
  63. public function read($force = false)
  64. {
  65. // initialize the session
  66. $this->data = array();
  67. $this->keys = array();
  68. $this->flash = array();
  69. $this->record = null;
  70. // get the session cookie
  71. $cookie = $this->_get_cookie();
  72. // if a cookie was present, find the session record
  73. if ($cookie and ! $force and isset($cookie[0]))
  74. {
  75. // read the session record
  76. $this->record = \DB::select()->where('session_id', '=', $cookie[0])->from($this->config['table'])->execute($this->config['database']);
  77. // record found?
  78. if ($this->record->count())
  79. {
  80. $payload = $this->_unserialize($this->record->get('payload'));
  81. }
  82. else
  83. {
  84. // try to find the session on previous id
  85. $this->record = \DB::select()->where('previous_id', '=', $cookie[0])->from($this->config['table'])->execute($this->config['database']);
  86. // record found?
  87. if ($this->record->count())
  88. {
  89. $payload = $this->_unserialize($this->record->get('payload'));
  90. }
  91. else
  92. {
  93. // cookie present, but session record missing. force creation of a new session
  94. logger('DEBUG', 'Error: Session cookie with ID "'.$cookie[0].'" present but corresponding record is missing');
  95. return $this->read(true);
  96. }
  97. }
  98. if ( ! isset($payload[0]) or ! is_array($payload[0]))
  99. {
  100. logger('DEBUG', 'Error: not a valid db session payload!');
  101. }
  102. elseif ($payload[0]['updated'] + $this->config['expiration_time'] <= $this->time->get_timestamp())
  103. {
  104. logger('DEBUG', 'Error: session id has expired!');
  105. }
  106. elseif ($this->config['match_ip'] and $payload[0]['ip_hash'] !== md5(\Input::ip().\Input::real_ip()))
  107. {
  108. logger('DEBUG', 'Error: IP address in the session doesn\'t match this requests source IP!');
  109. }
  110. elseif ($this->config['match_ua'] and $payload[0]['user_agent'] !== \Input::user_agent())
  111. {
  112. logger('DEBUG', 'Error: User agent in the session doesn\'t match the browsers user agent string!');
  113. }
  114. else
  115. {
  116. // session is valid, retrieve the payload
  117. if (isset($payload[0]) and is_array($payload[0])) $this->keys = $payload[0];
  118. if (isset($payload[1]) and is_array($payload[1])) $this->data = $payload[1];
  119. if (isset($payload[2]) and is_array($payload[2])) $this->flash = $payload[2];
  120. }
  121. }
  122. return parent::read();
  123. }
  124. // --------------------------------------------------------------------
  125. /**
  126. * write the current session
  127. *
  128. * @access public
  129. * @return Fuel\Core\Session_Db
  130. */
  131. public function write()
  132. {
  133. // do we have something to write?
  134. if ( ! empty($this->keys) or ! empty($this->data) or ! empty($this->flash))
  135. {
  136. parent::write();
  137. // rotate the session id if needed
  138. $this->rotate(false);
  139. // record the last update time of the session
  140. $this->keys['updated'] = $this->time->get_timestamp();
  141. // add a random identifier, we need the payload to be absolutely unique
  142. $this->flash[$this->config['flash_id'].'::__session_identifier__'] = array('state' => 'expire', 'value' => sha1(uniqid(rand(), true)));
  143. // create the session record, and add the session payload
  144. $session = $this->keys;
  145. $session['payload'] = $this->_serialize(array($this->keys, $this->data, $this->flash));
  146. try
  147. {
  148. // do we need to create a new session?
  149. if (is_null($this->record))
  150. {
  151. // create the new session record
  152. list($notused, $result) = \DB::insert($this->config['table'], array_keys($session))->values($session)->execute($this->config['database']);
  153. }
  154. else
  155. {
  156. // update the database
  157. $result = \DB::update($this->config['table'])->set($session)->where('session_id', '=', $this->record->get('session_id'))->execute($this->config['database']);
  158. // if it failed, perhaps we have lost a session id due to rotation?
  159. if ($result === 0)
  160. {
  161. // if so, there must be a session record with our session_id as previous_id
  162. $result = \DB::select()->where('previous_id', '=', $this->record->get('session_id'))->from($this->config['table'])->execute($this->config['database']);
  163. if ($result->count())
  164. {
  165. logger(\Fuel::L_WARNING, 'Session update failed, session record recovered using previous id. Lost rotation data?');
  166. // update the session data
  167. $this->keys['session_id'] = $result->get('session_id');
  168. $this->keys['previous_id'] = $result->get('previous_id');
  169. // and recreate the payload
  170. $session = $this->keys;
  171. $session['payload'] = $this->_serialize(array($this->keys, $this->data, $this->flash));
  172. // and update the database
  173. $result = \DB::update($this->config['table'])->set($session)->where('session_id', '=', $this->keys['session_id'])->execute($this->config['database']);
  174. }
  175. else
  176. {
  177. logger(\Fuel::L_ERROR, 'Session update failed, session record could not be recovered using the previous id');
  178. $result = false;
  179. }
  180. }
  181. }
  182. // update went well?
  183. if ($result !== 0)
  184. {
  185. // then update the cookie
  186. $this->_set_cookie(array($this->keys['session_id']));
  187. }
  188. // do some garbage collection
  189. if (mt_rand(0,100) < $this->config['gc_probability'])
  190. {
  191. $expired = $this->time->get_timestamp() - $this->config['expiration_time'];
  192. $result = \DB::delete($this->config['table'])->where('updated', '<', $expired)->execute($this->config['database']);
  193. }
  194. }
  195. catch (Database_Exception $e)
  196. {
  197. // strip the actual query from the message
  198. $msg = $e->getMessage();
  199. $msg = substr($msg, 0, strlen($msg) - strlen(strrchr($msg, ':')));
  200. // and rethrow it
  201. throw new \Database_Exception($msg);
  202. }
  203. }
  204. return $this;
  205. }
  206. // --------------------------------------------------------------------
  207. /**
  208. * destroy the current session
  209. *
  210. * @access public
  211. * @return Fuel\Core\Session_Db
  212. */
  213. public function destroy()
  214. {
  215. // do we have something to destroy?
  216. if ( ! empty($this->keys) and ! empty($this->record))
  217. {
  218. // delete the session record
  219. $result = \DB::delete($this->config['table'])->where('session_id', '=', $this->keys['session_id'])->execute($this->config['database']);
  220. }
  221. // reset the stored session data
  222. $this->record = null;
  223. parent::destroy();
  224. return $this;
  225. }
  226. // --------------------------------------------------------------------
  227. /**
  228. * validate a driver config value
  229. *
  230. * @param array array with configuration values
  231. * @access public
  232. * @return array validated and consolidated config
  233. */
  234. public function _validate_config($config)
  235. {
  236. $validated = array();
  237. foreach ($config as $name => $item)
  238. {
  239. // filter out any driver config
  240. if (!is_array($item))
  241. {
  242. switch ($name)
  243. {
  244. case 'cookie_name':
  245. if ( empty($item) or ! is_string($item))
  246. {
  247. $item = 'fueldid';
  248. }
  249. break;
  250. case 'database':
  251. // do we have a database?
  252. if ( empty($item) or ! is_string($item))
  253. {
  254. \Config::load('db', true);
  255. $item = \Config::get('db.active', false);
  256. }
  257. if ($item === false)
  258. {
  259. throw new \FuelException('You have specify a database to use database backed sessions.');
  260. }
  261. break;
  262. case 'table':
  263. // and a table name?
  264. if ( empty($item) or ! is_string($item))
  265. {
  266. throw new \FuelException('You have specify a database table name to use database backed sessions.');
  267. }
  268. break;
  269. case 'gc_probability':
  270. // do we have a path?
  271. if ( ! is_numeric($item) or $item < 0 or $item > 100)
  272. {
  273. // default value: 5%
  274. $item = 5;
  275. }
  276. break;
  277. default:
  278. break;
  279. }
  280. // global config, was validated in the driver
  281. $validated[$name] = $item;
  282. }
  283. }
  284. // validate all global settings as well
  285. return parent::_validate_config($validated);
  286. }
  287. }