blob: ada97a0323309aba0b17b236503b7ea2ecd6fe5b [file] [log] [blame]
Andrey Andreev57ffbbb2011-12-25 04:48:47 +02001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Greg Aker741de1c2010-11-10 14:52:57 -06005 * An open source application development framework for PHP 5.1.6 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Andrey Andreev57ffbbb2011-12-25 04:48:47 +02008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
21 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. (http://ellislab.com/)
22 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
25 * @filesource
26 */
27
28// ------------------------------------------------------------------------
29
30/**
31 * Session Class
32 *
33 * @package CodeIgniter
34 * @subpackage Libraries
35 * @category Sessions
Derek Jonesf4a4bd82011-10-20 12:18:42 -050036 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000037 * @link http://codeigniter.com/user_guide/libraries/sessions.html
38 */
39class CI_Session {
40
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020041 public $sess_encrypt_cookie = FALSE;
42 public $sess_use_database = FALSE;
43 public $sess_table_name = '';
44 public $sess_expiration = 7200;
45 public $sess_expire_on_close = FALSE;
46 public $sess_match_ip = FALSE;
47 public $sess_match_useragent = TRUE;
48 public $sess_cookie_name = 'ci_session';
49 public $cookie_prefix = '';
50 public $cookie_path = '';
51 public $cookie_domain = '';
52 public $cookie_secure = FALSE;
53 public $sess_time_to_update = 300;
54 public $encryption_key = '';
55 public $flashdata_key = 'flash';
56 public $time_reference = 'time';
57 public $gc_probability = 5;
58 public $userdata = array();
59 public $CI;
60 public $now;
Derek Allard2067d1a2008-11-13 22:59:24 +000061
62 /**
63 * Session Constructor
64 *
65 * The constructor runs the session routines automatically
66 * whenever the class is instantiated.
67 */
Greg Akera9263282010-11-10 15:26:43 -060068 public function __construct($params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000069 {
70 log_message('debug', "Session Class Initialized");
71
72 // Set the super object to a local variable for use throughout the class
73 $this->CI =& get_instance();
74
75 // Set all the session preferences, which can either be set
76 // manually via the $params array above or via the config file
tobiasbgba6432c2011-02-18 21:58:48 +010077 foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'cookie_secure', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
Derek Allard2067d1a2008-11-13 22:59:24 +000078 {
79 $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
80 }
81
Derek Jones5485db52010-08-30 21:31:08 -050082 if ($this->encryption_key == '')
83 {
84 show_error('In order to use the Session class you are required to set an encryption key in your config file.');
85 }
86
Derek Allard2067d1a2008-11-13 22:59:24 +000087 // Load the string helper so we can use the strip_slashes() function
88 $this->CI->load->helper('string');
89
90 // Do we need encryption? If so, load the encryption class
91 if ($this->sess_encrypt_cookie == TRUE)
92 {
93 $this->CI->load->library('encrypt');
94 }
95
Derek Jones4b9c6292011-07-01 17:40:48 -050096 // Are we using a database? If so, load it
Derek Allard2067d1a2008-11-13 22:59:24 +000097 if ($this->sess_use_database === TRUE AND $this->sess_table_name != '')
98 {
99 $this->CI->load->database();
100 }
101
Derek Jones4b9c6292011-07-01 17:40:48 -0500102 // Set the "now" time. Can either be GMT or server time, based on the
103 // config prefs. We use this to set the "last activity" time
Derek Allard2067d1a2008-11-13 22:59:24 +0000104 $this->now = $this->_get_time();
105
106 // Set the session length. If the session expiration is
107 // set to zero we'll set the expiration two years from now.
108 if ($this->sess_expiration == 0)
109 {
110 $this->sess_expiration = (60*60*24*365*2);
111 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200112
Derek Allard2067d1a2008-11-13 22:59:24 +0000113 // Set the cookie name
114 $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
115
116 // Run the Session routine. If a session doesn't exist we'll
Derek Jones4b9c6292011-07-01 17:40:48 -0500117 // create a new one. If it does, we'll update it.
Derek Allard2067d1a2008-11-13 22:59:24 +0000118 if ( ! $this->sess_read())
119 {
120 $this->sess_create();
121 }
122 else
123 {
124 $this->sess_update();
125 }
126
127 // Delete 'old' flashdata (from last request)
Barry Mienydd671972010-10-04 16:33:58 +0200128 $this->_flashdata_sweep();
Derek Allard2067d1a2008-11-13 22:59:24 +0000129
130 // Mark all new flashdata as old (data will be deleted before next request)
Barry Mienydd671972010-10-04 16:33:58 +0200131 $this->_flashdata_mark();
Derek Allard2067d1a2008-11-13 22:59:24 +0000132
133 // Delete expired sessions if necessary
134 $this->_sess_gc();
135
136 log_message('debug', "Session routines successfully run");
137 }
138
139 // --------------------------------------------------------------------
140
141 /**
142 * Fetch the current session data if it exists
143 *
144 * @access public
145 * @return bool
146 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200147 public function sess_read()
Derek Allard2067d1a2008-11-13 22:59:24 +0000148 {
149 // Fetch the cookie
150 $session = $this->CI->input->cookie($this->sess_cookie_name);
151
Derek Jones4b9c6292011-07-01 17:40:48 -0500152 // No cookie? Goodbye cruel world!...
Derek Allard2067d1a2008-11-13 22:59:24 +0000153 if ($session === FALSE)
154 {
155 log_message('debug', 'A session cookie was not found.');
156 return FALSE;
157 }
158
159 // Decrypt the cookie data
160 if ($this->sess_encrypt_cookie == TRUE)
161 {
162 $session = $this->CI->encrypt->decode($session);
163 }
164 else
165 {
166 // encryption was not used, so we need to check the md5 hash
167 $hash = substr($session, strlen($session)-32); // get last 32 chars
168 $session = substr($session, 0, strlen($session)-32);
169
Derek Jones4b9c6292011-07-01 17:40:48 -0500170 // Does the md5 hash match? This is to prevent manipulation of session data in userspace
171 if ($hash !== md5($session.$this->encryption_key))
Derek Allard2067d1a2008-11-13 22:59:24 +0000172 {
173 log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
174 $this->sess_destroy();
175 return FALSE;
176 }
177 }
178
179 // Unserialize the session array
180 $session = $this->_unserialize($session);
181
182 // Is the session data we unserialized an array with the correct format?
183 if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']))
184 {
185 $this->sess_destroy();
186 return FALSE;
187 }
188
189 // Is the session current?
190 if (($session['last_activity'] + $this->sess_expiration) < $this->now)
191 {
192 $this->sess_destroy();
193 return FALSE;
194 }
195
196 // Does the IP Match?
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200197 if ($this->sess_match_ip == TRUE AND $session['ip_address'] !== $this->CI->input->ip_address())
Derek Allard2067d1a2008-11-13 22:59:24 +0000198 {
199 $this->sess_destroy();
200 return FALSE;
201 }
202
203 // Does the User Agent Match?
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200204 if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000205 {
206 $this->sess_destroy();
207 return FALSE;
208 }
209
210 // Is there a corresponding session in the DB?
211 if ($this->sess_use_database === TRUE)
212 {
213 $this->CI->db->where('session_id', $session['session_id']);
214
215 if ($this->sess_match_ip == TRUE)
216 {
217 $this->CI->db->where('ip_address', $session['ip_address']);
218 }
219
220 if ($this->sess_match_useragent == TRUE)
221 {
222 $this->CI->db->where('user_agent', $session['user_agent']);
223 }
224
225 $query = $this->CI->db->get($this->sess_table_name);
226
Derek Jones4b9c6292011-07-01 17:40:48 -0500227 // No result? Kill it!
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200228 if ($query->num_rows() === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000229 {
230 $this->sess_destroy();
231 return FALSE;
232 }
233
Derek Jones4b9c6292011-07-01 17:40:48 -0500234 // Is there custom data? If so, add it to the main session array
Derek Allard2067d1a2008-11-13 22:59:24 +0000235 $row = $query->row();
236 if (isset($row->user_data) AND $row->user_data != '')
237 {
238 $custom_data = $this->_unserialize($row->user_data);
239
240 if (is_array($custom_data))
241 {
242 foreach ($custom_data as $key => $val)
243 {
244 $session[$key] = $val;
245 }
246 }
247 }
248 }
249
250 // Session is valid!
251 $this->userdata = $session;
252 unset($session);
253
254 return TRUE;
255 }
256
257 // --------------------------------------------------------------------
258
259 /**
260 * Write the session data
261 *
262 * @access public
263 * @return void
264 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200265 public function sess_write()
Derek Allard2067d1a2008-11-13 22:59:24 +0000266 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500267 // Are we saving custom data to the DB? If not, all we do is update the cookie
Derek Allard2067d1a2008-11-13 22:59:24 +0000268 if ($this->sess_use_database === FALSE)
269 {
270 $this->_set_cookie();
271 return;
272 }
273
274 // set the custom userdata, the session data we will set in a second
275 $custom_userdata = $this->userdata;
276 $cookie_userdata = array();
277
278 // Before continuing, we need to determine if there is any custom data to deal with.
279 // Let's determine this by removing the default indexes to see if there's anything left in the array
280 // and set the session data while we're at it
281 foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
282 {
283 unset($custom_userdata[$val]);
284 $cookie_userdata[$val] = $this->userdata[$val];
285 }
286
Derek Jones4b9c6292011-07-01 17:40:48 -0500287 // Did we find any custom data? If not, we turn the empty array into a string
Derek Allard2067d1a2008-11-13 22:59:24 +0000288 // since there's no reason to serialize and store an empty array in the DB
289 if (count($custom_userdata) === 0)
290 {
291 $custom_userdata = '';
292 }
293 else
294 {
295 // Serialize the custom data array so we can store it
296 $custom_userdata = $this->_serialize($custom_userdata);
297 }
298
299 // Run the update query
300 $this->CI->db->where('session_id', $this->userdata['session_id']);
301 $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
302
Derek Jones4b9c6292011-07-01 17:40:48 -0500303 // Write the cookie. Notice that we manually pass the cookie data array to the
Derek Allard2067d1a2008-11-13 22:59:24 +0000304 // _set_cookie() function. Normally that function will store $this->userdata, but
305 // in this case that array contains custom data, which we do not want in the cookie.
306 $this->_set_cookie($cookie_userdata);
307 }
308
309 // --------------------------------------------------------------------
310
311 /**
312 * Create a new session
313 *
314 * @access public
315 * @return void
316 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200317 public function sess_create()
Derek Allard2067d1a2008-11-13 22:59:24 +0000318 {
319 $sessid = '';
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200320 do
Derek Allard2067d1a2008-11-13 22:59:24 +0000321 {
322 $sessid .= mt_rand(0, mt_getrandmax());
323 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200324 while (strlen($sessid) < 32);
Derek Allard2067d1a2008-11-13 22:59:24 +0000325
326 // To make the session ID even more secure we'll combine it with the user's IP
327 $sessid .= $this->CI->input->ip_address();
328
329 $this->userdata = array(
Barry Mienydd671972010-10-04 16:33:58 +0200330 'session_id' => md5(uniqid($sessid, TRUE)),
331 'ip_address' => $this->CI->input->ip_address(),
Greg Aker50671cf2011-04-20 11:36:45 -0500332 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
Kyle Farrisf57a46b2011-08-29 23:26:07 -0300333 'last_activity' => $this->now,
334 'user_data' => ''
Derek Allard2067d1a2008-11-13 22:59:24 +0000335 );
336
337
338 // Save the data to the DB if needed
339 if ($this->sess_use_database === TRUE)
340 {
341 $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
342 }
343
344 // Write the cookie
345 $this->_set_cookie();
346 }
347
348 // --------------------------------------------------------------------
349
350 /**
351 * Update an existing session
352 *
353 * @access public
354 * @return void
355 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200356 public function sess_update()
Derek Allard2067d1a2008-11-13 22:59:24 +0000357 {
358 // We only update the session every five minutes by default
359 if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
360 {
361 return;
362 }
363
364 // Save the old session id so we know which record to
365 // update in the database if we need it
366 $old_sessid = $this->userdata['session_id'];
367 $new_sessid = '';
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200368 do
Derek Allard2067d1a2008-11-13 22:59:24 +0000369 {
370 $new_sessid .= mt_rand(0, mt_getrandmax());
371 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200372 while (strlen($new_sessid) < 32);
Derek Allard2067d1a2008-11-13 22:59:24 +0000373
374 // To make the session ID even more secure we'll combine it with the user's IP
375 $new_sessid .= $this->CI->input->ip_address();
376
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200377 // Turn it into a hash and update the session data array
378 $this->userdata['session_id'] = $new_sessid = md5(uniqid($new_sessid, TRUE));
Derek Allard2067d1a2008-11-13 22:59:24 +0000379 $this->userdata['last_activity'] = $this->now;
380
381 // _set_cookie() will handle this for us if we aren't using database sessions
382 // by pushing all userdata to the cookie.
383 $cookie_data = NULL;
384
385 // Update the session ID and last_activity field in the DB if needed
386 if ($this->sess_use_database === TRUE)
387 {
388 // set cookie explicitly to only have our session data
389 $cookie_data = array();
390 foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
391 {
392 $cookie_data[$val] = $this->userdata[$val];
393 }
394
395 $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
396 }
397
398 // Write the cookie
399 $this->_set_cookie($cookie_data);
400 }
401
402 // --------------------------------------------------------------------
403
404 /**
405 * Destroy the current session
406 *
407 * @access public
408 * @return void
409 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200410 public function sess_destroy()
Derek Allard2067d1a2008-11-13 22:59:24 +0000411 {
412 // Kill the session DB row
413 if ($this->sess_use_database === TRUE AND isset($this->userdata['session_id']))
414 {
415 $this->CI->db->where('session_id', $this->userdata['session_id']);
416 $this->CI->db->delete($this->sess_table_name);
417 }
418
419 // Kill the cookie
420 setcookie(
421 $this->sess_cookie_name,
422 addslashes(serialize(array())),
423 ($this->now - 31500000),
424 $this->cookie_path,
425 $this->cookie_domain,
426 0
427 );
428 }
429
430 // --------------------------------------------------------------------
431
432 /**
433 * Fetch a specific item from the session array
434 *
435 * @access public
436 * @param string
437 * @return string
438 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200439 public function userdata($item)
Derek Allard2067d1a2008-11-13 22:59:24 +0000440 {
441 return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
442 }
443
444 // --------------------------------------------------------------------
445
446 /**
447 * Fetch all session data
448 *
449 * @access public
Greg Aker34033662011-04-18 11:18:09 -0500450 * @return array
Derek Allard2067d1a2008-11-13 22:59:24 +0000451 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200452 public function all_userdata()
Derek Allard2067d1a2008-11-13 22:59:24 +0000453 {
Greg Aker34033662011-04-18 11:18:09 -0500454 return $this->userdata;
Derek Allard2067d1a2008-11-13 22:59:24 +0000455 }
456
457 // --------------------------------------------------------------------
458
459 /**
460 * Add or change data in the "userdata" array
461 *
462 * @access public
463 * @param mixed
464 * @param string
465 * @return void
466 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200467 public function set_userdata($newdata = array(), $newval = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000468 {
469 if (is_string($newdata))
470 {
471 $newdata = array($newdata => $newval);
472 }
473
474 if (count($newdata) > 0)
475 {
476 foreach ($newdata as $key => $val)
477 {
478 $this->userdata[$key] = $val;
479 }
480 }
481
482 $this->sess_write();
483 }
484
485 // --------------------------------------------------------------------
486
487 /**
488 * Delete a session variable from the "userdata" array
489 *
490 * @access array
491 * @return void
492 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200493 public function unset_userdata($newdata = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000494 {
495 if (is_string($newdata))
496 {
497 $newdata = array($newdata => '');
498 }
499
500 if (count($newdata) > 0)
501 {
502 foreach ($newdata as $key => $val)
503 {
504 unset($this->userdata[$key]);
505 }
506 }
507
508 $this->sess_write();
509 }
510
511 // ------------------------------------------------------------------------
512
513 /**
514 * Add or change flashdata, only available
515 * until the next request
516 *
517 * @access public
518 * @param mixed
519 * @param string
520 * @return void
521 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200522 public function set_flashdata($newdata = array(), $newval = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000523 {
524 if (is_string($newdata))
525 {
526 $newdata = array($newdata => $newval);
527 }
528
529 if (count($newdata) > 0)
530 {
531 foreach ($newdata as $key => $val)
532 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200533 $this->set_userdata($this->flashdata_key.':new:'.$key, $val);
Derek Allard2067d1a2008-11-13 22:59:24 +0000534 }
535 }
536 }
537
538 // ------------------------------------------------------------------------
539
540 /**
541 * Keeps existing flashdata available to next request.
542 *
543 * @access public
544 * @param string
545 * @return void
546 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200547 public function keep_flashdata($key)
Derek Allard2067d1a2008-11-13 22:59:24 +0000548 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500549 // 'old' flashdata gets removed. Here we mark all
Derek Allard2067d1a2008-11-13 22:59:24 +0000550 // flashdata as 'new' to preserve it from _flashdata_sweep()
551 // Note the function will return FALSE if the $key
552 // provided cannot be found
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200553 $value = $this->userdata($this->flashdata_key.':old:'.$key);
Derek Allard2067d1a2008-11-13 22:59:24 +0000554
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200555 $this->set_userdata($this->flashdata_key.':new:'.$key, $value);
Derek Allard2067d1a2008-11-13 22:59:24 +0000556 }
557
558 // ------------------------------------------------------------------------
559
560 /**
561 * Fetch a specific flashdata item from the session array
562 *
563 * @access public
564 * @param string
565 * @return string
566 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200567 public function flashdata($key)
Derek Allard2067d1a2008-11-13 22:59:24 +0000568 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200569 return $this->userdata($this->flashdata_key.':old:'.$key);
Derek Allard2067d1a2008-11-13 22:59:24 +0000570 }
571
572 // ------------------------------------------------------------------------
573
574 /**
575 * Identifies flashdata as 'old' for removal
576 * when _flashdata_sweep() runs.
577 *
578 * @access private
579 * @return void
580 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200581 private function _flashdata_mark()
Derek Allard2067d1a2008-11-13 22:59:24 +0000582 {
583 $userdata = $this->all_userdata();
584 foreach ($userdata as $name => $value)
585 {
586 $parts = explode(':new:', $name);
587 if (is_array($parts) && count($parts) === 2)
588 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200589 $this->set_userdata($this->flashdata_key.':old:'.$parts[1], $value);
Derek Allard2067d1a2008-11-13 22:59:24 +0000590 $this->unset_userdata($name);
591 }
592 }
593 }
594
595 // ------------------------------------------------------------------------
596
597 /**
598 * Removes all flashdata marked as 'old'
599 *
600 * @access private
601 * @return void
602 */
603
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200604 private function _flashdata_sweep()
Derek Allard2067d1a2008-11-13 22:59:24 +0000605 {
606 $userdata = $this->all_userdata();
607 foreach ($userdata as $key => $value)
608 {
609 if (strpos($key, ':old:'))
610 {
611 $this->unset_userdata($key);
612 }
613 }
614
615 }
616
617 // --------------------------------------------------------------------
618
619 /**
620 * Get the "now" time
621 *
622 * @access private
623 * @return string
624 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200625 private function _get_time()
Derek Allard2067d1a2008-11-13 22:59:24 +0000626 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200627 $now = time();
628 return (strtolower($this->time_reference) === 'gmt') ?
629 mktime(gmdate('H', $now), gmdate('i', $now), gmdate('s', $now), gmdate('m', $now), gmdate('d', $now), gmdate('Y', $now)) : $now;
Derek Allard2067d1a2008-11-13 22:59:24 +0000630 }
631
632 // --------------------------------------------------------------------
633
634 /**
635 * Write the session cookie
636 *
637 * @access public
638 * @return void
639 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200640 private function _set_cookie($cookie_data = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000641 {
642 if (is_null($cookie_data))
643 {
644 $cookie_data = $this->userdata;
645 }
646
647 // Serialize the userdata for the cookie
648 $cookie_data = $this->_serialize($cookie_data);
649
650 if ($this->sess_encrypt_cookie == TRUE)
651 {
652 $cookie_data = $this->CI->encrypt->encode($cookie_data);
653 }
654 else
655 {
656 // if encryption is not used, we provide an md5 hash to prevent userside tampering
657 $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
658 }
Barry Mienydd671972010-10-04 16:33:58 +0200659
Derek Joneseaa71ba2010-09-02 10:32:07 -0500660 $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
Barry Mienydd671972010-10-04 16:33:58 +0200661
Derek Allard2067d1a2008-11-13 22:59:24 +0000662 // Set the cookie
663 setcookie(
664 $this->sess_cookie_name,
665 $cookie_data,
Derek Joneseaa71ba2010-09-02 10:32:07 -0500666 $expire,
Derek Allard2067d1a2008-11-13 22:59:24 +0000667 $this->cookie_path,
668 $this->cookie_domain,
tobiasbgba6432c2011-02-18 21:58:48 +0100669 $this->cookie_secure
Derek Allard2067d1a2008-11-13 22:59:24 +0000670 );
671 }
672
673 // --------------------------------------------------------------------
674
675 /**
676 * Serialize an array
677 *
678 * This function first converts any slashes found in the array to a temporary
679 * marker, so when it gets unserialized the slashes will be preserved
680 *
681 * @access private
682 * @param array
683 * @return string
684 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200685 private function _serialize($data)
Derek Allard2067d1a2008-11-13 22:59:24 +0000686 {
687 if (is_array($data))
688 {
Chris Muench95933492011-10-16 14:14:04 -0400689 array_walk_recursive($data, array(&$this, '_escape_slashes'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000690 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200691 elseif (is_string($data))
Derek Allard2067d1a2008-11-13 22:59:24 +0000692 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200693 $data = str_replace('\\', '{{slash}}', $data);
Derek Allard2067d1a2008-11-13 22:59:24 +0000694 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000695 return serialize($data);
696 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200697
Chris Muench95933492011-10-16 14:14:04 -0400698 /**
699 * Escape slashes
700 *
701 * This function converts any slashes found into a temporary marker
702 *
703 * @access private
704 */
705 function _escape_slashes(&$val, $key)
706 {
707 if (is_string($val))
708 {
709 $val = str_replace('\\', '{{slash}}', $val);
710 }
711 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000712
713 // --------------------------------------------------------------------
714
715 /**
716 * Unserialize
717 *
718 * This function unserializes a data string, then converts any
719 * temporary slash markers back to actual slashes
720 *
721 * @access private
722 * @param array
723 * @return string
724 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200725 private function _unserialize($data)
Derek Allard2067d1a2008-11-13 22:59:24 +0000726 {
727 $data = @unserialize(strip_slashes($data));
728
729 if (is_array($data))
730 {
Chris Muench95933492011-10-16 14:14:04 -0400731 array_walk_recursive($data, array(&$this, '_unescape_slashes'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000732 return $data;
733 }
734
Derek Jones133e6662010-03-29 11:36:42 -0500735 return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data;
Derek Allard2067d1a2008-11-13 22:59:24 +0000736 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200737
Chris Muench95933492011-10-16 14:14:04 -0400738 /**
739 * Unescape slashes
740 *
741 * This function converts any slash markers back into actual slashes
742 *
743 * @access private
744 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200745 private function _unescape_slashes(&$val, $key)
Chris Muench95933492011-10-16 14:14:04 -0400746 {
Chris Muench3e414f92011-10-16 23:03:55 -0400747 if (is_string($val))
748 {
749 $val= str_replace('{{slash}}', '\\', $val);
750 }
Chris Muench95933492011-10-16 14:14:04 -0400751 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000752
753 // --------------------------------------------------------------------
754
755 /**
756 * Garbage collection
757 *
758 * This deletes expired session rows from database
759 * if the probability percentage is met
760 *
761 * @access public
762 * @return void
763 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200764 private function _sess_gc()
Derek Allard2067d1a2008-11-13 22:59:24 +0000765 {
766 if ($this->sess_use_database != TRUE)
767 {
768 return;
769 }
770
771 srand(time());
772 if ((rand() % 100) < $this->gc_probability)
773 {
774 $expire = $this->now - $this->sess_expiration;
775
776 $this->CI->db->where("last_activity < {$expire}");
777 $this->CI->db->delete($this->sess_table_name);
778
779 log_message('debug', 'Session garbage collection performed.');
780 }
781 }
782
783
784}
785// END Session Class
786
787/* End of file Session.php */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200788/* Location: ./system/libraries/Session.php */