PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/system/libraries/Session.php

https://github.com/holsinger/openfloor
PHP | 488 lines | 264 code | 68 blank | 156 comment | 46 complexity | de61040216b6b30f0846b6d47ef8840c MD5 | raw file
  1. <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 4.3.2 or newer
  6. *
  7. * @package CodeIgniter
  8. * @author Rick Ellis
  9. * @copyright Copyright (c) 2006, EllisLab, Inc.
  10. * @license http://www.codeignitor.com/user_guide/license.html
  11. * @link http://www.codeigniter.com
  12. * @since Version 1.0
  13. * @filesource
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * Session Class
  18. *
  19. * @package CodeIgniter
  20. * @subpackage Libraries
  21. * @category Sessions
  22. * @author Rick Ellis
  23. * @link http://www.codeigniter.com/user_guide/libraries/sessions.html
  24. */
  25. class CI_Session {
  26. var $CI;
  27. var $now;
  28. var $encryption = TRUE;
  29. var $use_database = FALSE;
  30. var $session_table = FALSE;
  31. var $sess_length = 7200;
  32. var $sess_cookie = 'ci_session';
  33. var $userdata = array();
  34. var $gc_probability = 5;
  35. /**
  36. * Session Constructor
  37. *
  38. * The constructor runs the session routines automatically
  39. * whenever the class is instantiated.
  40. */
  41. function CI_Session()
  42. {
  43. $this->CI =& get_instance();
  44. log_message('debug', "Session Class Initialized");
  45. $this->sess_run();
  46. }
  47. // --------------------------------------------------------------------
  48. /**
  49. * Run the session routines
  50. *
  51. * @access public
  52. * @return void
  53. */
  54. function sess_run()
  55. {
  56. /*
  57. * Set the "now" time
  58. *
  59. * It can either set to GMT or time(). The pref
  60. * is set in the config file. If the developer
  61. * is doing any sort of time localization they
  62. * might want to set the session time to GMT so
  63. * they can offset the "last_activity" and
  64. * "last_visit" times based on each user's locale.
  65. *
  66. */
  67. if (strtolower($this->CI->config->item('time_reference')) == 'gmt')
  68. {
  69. $now = time();
  70. $this->now = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
  71. if (strlen($this->now) < 10)
  72. {
  73. $this->now = time();
  74. log_message('error', 'The session class could not set a proper GMT timestamp so the local time() value was used.');
  75. }
  76. }
  77. else
  78. {
  79. $this->now = time();
  80. }
  81. /*
  82. * Set the session length
  83. *
  84. * If the session expiration is set to zero in
  85. * the config file we'll set the expiration
  86. * two years from now.
  87. *
  88. */
  89. $expiration = $this->CI->config->item('sess_expiration');
  90. if (is_numeric($expiration))
  91. {
  92. if ($expiration > 0)
  93. {
  94. $this->sess_length = $this->CI->config->item('sess_expiration');
  95. }
  96. else
  97. {
  98. $this->sess_length = (60*60*24*365*2);
  99. }
  100. }
  101. // Do we need encryption?
  102. $this->encryption = $this->CI->config->item('sess_encrypt_cookie');
  103. if ($this->encryption == TRUE)
  104. {
  105. $this->CI->load->library('encrypt');
  106. }
  107. // Are we using a database?
  108. if ($this->CI->config->item('sess_use_database') === TRUE AND $this->CI->config->item('sess_table_name') != '')
  109. {
  110. $this->use_database = TRUE;
  111. $this->session_table = $this->CI->config->item('sess_table_name');
  112. $this->CI->load->database();
  113. }
  114. // Set the cookie name
  115. if ($this->CI->config->item('sess_cookie_name') != FALSE)
  116. {
  117. $this->sess_cookie = $this->CI->config->item('cookie_prefix').$this->CI->config->item('sess_cookie_name');
  118. }
  119. /*
  120. * Fetch the current session
  121. *
  122. * If a session doesn't exist we'll create
  123. * a new one. If it does, we'll update it.
  124. *
  125. */
  126. if ( ! $this->sess_read())
  127. {
  128. $this->sess_create();
  129. }
  130. else
  131. {
  132. // We only update the session every five minutes
  133. if (($this->userdata['last_activity'] + 300) < $this->now)
  134. {
  135. $this->sess_update();
  136. }
  137. }
  138. // Delete expired sessions if necessary
  139. if ($this->use_database === TRUE)
  140. {
  141. $this->sess_gc();
  142. }
  143. }
  144. // --------------------------------------------------------------------
  145. /**
  146. * Fetch the current session data if it exists
  147. *
  148. * @access public
  149. * @return void
  150. */
  151. function sess_read()
  152. {
  153. // Fetch the cookie
  154. $session = $this->CI->input->cookie($this->sess_cookie);
  155. if ($session === FALSE)
  156. {
  157. log_message('debug', 'A session cookie was not found.');
  158. return FALSE;
  159. }
  160. // Decrypt and unserialize the data
  161. if ($this->encryption == TRUE)
  162. {
  163. $session = $this->CI->encrypt->decode($session);
  164. }
  165. $session = @unserialize($this->strip_slashes($session));
  166. if ( ! is_array($session) OR ! isset($session['last_activity']))
  167. {
  168. log_message('error', 'The session cookie data did not contain a valid array. This could be a possible hacking attempt.');
  169. return FALSE;
  170. }
  171. // Is the session current?
  172. if (($session['last_activity'] + $this->sess_length) < $this->now)
  173. {
  174. $this->sess_destroy();
  175. return FALSE;
  176. }
  177. // Does the IP Match?
  178. if ($this->CI->config->item('sess_match_ip') == TRUE AND $session['ip_address'] != $this->CI->input->ip_address())
  179. {
  180. $this->sess_destroy();
  181. return FALSE;
  182. }
  183. // Does the User Agent Match?
  184. if ($this->CI->config->item('sess_match_useragent') == TRUE AND $session['user_agent'] != substr($this->CI->input->user_agent(), 0, 50))
  185. {
  186. $this->sess_destroy();
  187. return FALSE;
  188. }
  189. // Is there a corresponding session in the DB?
  190. if ($this->use_database === TRUE)
  191. {
  192. $this->CI->db->where('session_id', $session['session_id']);
  193. if ($this->CI->config->item('sess_match_ip') == TRUE)
  194. {
  195. $this->CI->db->where('ip_address', $session['ip_address']);
  196. }
  197. if ($this->CI->config->item('sess_match_useragent') == TRUE)
  198. {
  199. $this->CI->db->where('user_agent', $session['user_agent']);
  200. }
  201. $query = $this->CI->db->get($this->session_table);
  202. if ($query->num_rows() == 0)
  203. {
  204. $this->sess_destroy();
  205. return FALSE;
  206. }
  207. else
  208. {
  209. $row = $query->row();
  210. if (($row->last_activity + $this->sess_length) < $this->now)
  211. {
  212. $this->CI->db->where('session_id', $session['session_id']);
  213. $this->CI->db->delete($this->session_table);
  214. $this->sess_destroy();
  215. return FALSE;
  216. }
  217. }
  218. }
  219. // Session is valid!
  220. $this->userdata = $session;
  221. unset($session);
  222. return TRUE;
  223. }
  224. // --------------------------------------------------------------------
  225. /**
  226. * Write the session cookie
  227. *
  228. * @access public
  229. * @return void
  230. */
  231. function sess_write()
  232. {
  233. $cookie_data = serialize($this->userdata);
  234. if ($this->encryption == TRUE)
  235. {
  236. $cookie_data = $this->CI->encrypt->encode($cookie_data);
  237. }
  238. setcookie(
  239. $this->sess_cookie,
  240. $cookie_data,
  241. $this->sess_length + time(),
  242. $this->CI->config->item('cookie_path'),
  243. $this->CI->config->item('cookie_domain'),
  244. 0
  245. );
  246. }
  247. // --------------------------------------------------------------------
  248. /**
  249. * Create a new session
  250. *
  251. * @access public
  252. * @return void
  253. */
  254. function sess_create()
  255. {
  256. $sessid = '';
  257. while (strlen($sessid) < 32)
  258. {
  259. $sessid .= mt_rand(0, mt_getrandmax());
  260. }
  261. $this->userdata = array(
  262. 'session_id' => md5(uniqid($sessid, TRUE)),
  263. 'ip_address' => $this->CI->input->ip_address(),
  264. 'user_agent' => substr($this->CI->input->user_agent(), 0, 50),
  265. 'last_activity' => $this->now
  266. );
  267. // Save the session in the DB if needed
  268. if ($this->use_database === TRUE)
  269. {
  270. $this->CI->db->query($this->CI->db->insert_string($this->session_table, $this->userdata));
  271. }
  272. // Write the cookie
  273. $this->userdata['last_visit'] = 0;
  274. $this->sess_write();
  275. }
  276. // --------------------------------------------------------------------
  277. /**
  278. * Update an existing session
  279. *
  280. * @access public
  281. * @return void
  282. */
  283. function sess_update()
  284. {
  285. if (($this->userdata['last_activity'] + $this->sess_length) < $this->now)
  286. {
  287. $this->userdata['last_visit'] = $this->userdata['last_activity'];
  288. }
  289. $this->userdata['last_activity'] = $this->now;
  290. // Update the session in the DB if needed
  291. if ($this->use_database === TRUE)
  292. {
  293. $this->CI->db->query($this->CI->db->update_string($this->session_table, array('last_activity' => $this->now), array('session_id' => $this->userdata['session_id'])));
  294. }
  295. // Write the cookie
  296. $this->sess_write();
  297. }
  298. // --------------------------------------------------------------------
  299. /**
  300. * Destroy the current session
  301. *
  302. * @access public
  303. * @return void
  304. */
  305. function sess_destroy()
  306. {
  307. setcookie(
  308. $this->sess_cookie,
  309. addslashes(serialize(array())),
  310. ($this->now - 31500000),
  311. $this->CI->config->item('cookie_path'),
  312. $this->CI->config->item('cookie_domain'),
  313. 0
  314. );
  315. }
  316. // --------------------------------------------------------------------
  317. /**
  318. * Garbage collection
  319. *
  320. * This deletes expired session rows from database
  321. * if the probability percentage is met
  322. *
  323. * @access public
  324. * @return void
  325. */
  326. function sess_gc()
  327. {
  328. srand(time());
  329. if ((rand() % 100) < $this->gc_probability)
  330. {
  331. $expire = $this->now - $this->sess_length;
  332. $this->CI->db->where("last_activity < {$expire}");
  333. $this->CI->db->delete($this->session_table);
  334. log_message('debug', 'Session garbage collection performed.');
  335. }
  336. }
  337. // --------------------------------------------------------------------
  338. /**
  339. * Fetch a specific item form the session array
  340. *
  341. * @access public
  342. * @param string
  343. * @return string
  344. */
  345. function userdata($item)
  346. {
  347. return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
  348. }
  349. // --------------------------------------------------------------------
  350. /**
  351. * Add or change data in the "userdata" array
  352. *
  353. * @access public
  354. * @param mixed
  355. * @param string
  356. * @return void
  357. */
  358. function set_userdata($newdata = array(), $newval = '')
  359. {
  360. if (is_string($newdata))
  361. {
  362. $newdata = array($newdata => $newval);
  363. }
  364. if (count($newdata) > 0)
  365. {
  366. foreach ($newdata as $key => $val)
  367. {
  368. $this->userdata[$key] = $val;
  369. }
  370. }
  371. $this->sess_write();
  372. }
  373. // --------------------------------------------------------------------
  374. /**
  375. * Delete a session variable from the "userdata" array
  376. *
  377. * @access array
  378. * @return void
  379. */
  380. function unset_userdata($newdata = array())
  381. {
  382. if (is_string($newdata))
  383. {
  384. $newdata = array($newdata => '');
  385. }
  386. if (count($newdata) > 0)
  387. {
  388. foreach ($newdata as $key => $val)
  389. {
  390. unset($this->userdata[$key]);
  391. }
  392. }
  393. $this->sess_write();
  394. }
  395. // --------------------------------------------------------------------
  396. /**
  397. * Strip slashes
  398. *
  399. * @access public
  400. * @param mixed
  401. * @return mixed
  402. */
  403. function strip_slashes($vals)
  404. {
  405. if (is_array($vals))
  406. {
  407. foreach ($vals as $key=>$val)
  408. {
  409. $vals[$key] = $this->strip_slashes($val);
  410. }
  411. }
  412. else
  413. {
  414. $vals = stripslashes($vals);
  415. }
  416. return $vals;
  417. }
  418. }
  419. // END Session Class
  420. ?>