blob: 3fa446d848c7e59f0badaa1ca8262875b1fa5a16 [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 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 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
Andrey Andreevf863a022012-01-24 15:31:54 +020012 * bundled with this package in the files license.txt / license.rst. It is
Derek Jonesf4a4bd82011-10-20 12:18:42 -050013 * 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
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @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
Derek Allard2067d1a2008-11-13 22:59:24 +000028/**
29 * Session Class
30 *
31 * @package CodeIgniter
32 * @subpackage Libraries
33 * @category Sessions
Derek Jonesf4a4bd82011-10-20 12:18:42 -050034 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000035 * @link http://codeigniter.com/user_guide/libraries/sessions.html
36 */
37class CI_Session {
38
Timothy Warren68f09812012-04-27 10:38:32 -040039 /**
40 * Whether to encrypt the session cookie
41 *
42 * @var bool
43 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020044 public $sess_encrypt_cookie = FALSE;
Timothy Warren68f09812012-04-27 10:38:32 -040045
46 /**
47 * Whether to use to the database for session storage
48 *
49 * @var bool
50 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020051 public $sess_use_database = FALSE;
Timothy Warren68f09812012-04-27 10:38:32 -040052
53 /**
54 * Name of the database table in which to store sessions
55 *
56 * @var string
57 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020058 public $sess_table_name = '';
Timothy Warren68f09812012-04-27 10:38:32 -040059
60 /**
61 * Length of time (in seconds) for sessions to expire
62 *
63 * @var int
64 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020065 public $sess_expiration = 7200;
Timothy Warren68f09812012-04-27 10:38:32 -040066
67 /**
68 * Whether to kill session on close of browser window
69 *
70 * @var bool
71 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020072 public $sess_expire_on_close = FALSE;
Timothy Warren68f09812012-04-27 10:38:32 -040073
74 /**
75 * Whether to match session on ip address
76 *
77 * @var bool
78 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020079 public $sess_match_ip = FALSE;
Timothy Warren68f09812012-04-27 10:38:32 -040080
81 /**
82 * Whether to match session on user-agent
83 *
84 * @var bool
85 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020086 public $sess_match_useragent = TRUE;
Timothy Warren68f09812012-04-27 10:38:32 -040087
88 /**
89 * Name of session cookie
90 *
91 * @var string
92 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020093 public $sess_cookie_name = 'ci_session';
Timothy Warren68f09812012-04-27 10:38:32 -040094
95 /**
96 * Session cookie prefix
97 *
98 * @var string
99 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200100 public $cookie_prefix = '';
Timothy Warren68f09812012-04-27 10:38:32 -0400101
102 /**
103 * Session cookie path
104 *
105 * @var string
106 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200107 public $cookie_path = '';
Timothy Warren68f09812012-04-27 10:38:32 -0400108
109 /**
110 * Session cookie domain
111 *
112 * @var string
113 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200114 public $cookie_domain = '';
Timothy Warren68f09812012-04-27 10:38:32 -0400115
116 /**
117 * Whether to set the cookie only on HTTPS connections
118 *
119 * @var bool
120 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200121 public $cookie_secure = FALSE;
Timothy Warren68f09812012-04-27 10:38:32 -0400122
123 /**
124 * Whether cookie should be allowed only to be sent by the server
125 *
126 * @var bool
127 */
freewil4ad0fd82012-03-13 22:37:42 -0400128 public $cookie_httponly = FALSE;
Timothy Warren68f09812012-04-27 10:38:32 -0400129
130 /**
131 * Interval at which to update session
132 *
133 * @var int
134 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200135 public $sess_time_to_update = 300;
Timothy Warren68f09812012-04-27 10:38:32 -0400136
137 /**
138 * Key with which to encrypt the session cookie
139 *
140 * @var string
141 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200142 public $encryption_key = '';
Timothy Warren68f09812012-04-27 10:38:32 -0400143
144 /**
145 * String to indicate flash data cookies
146 *
147 * @var string
148 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200149 public $flashdata_key = 'flash';
Timothy Warren68f09812012-04-27 10:38:32 -0400150
151 /**
152 * Function to use to get the current time
153 *
154 * @var string
155 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200156 public $time_reference = 'time';
Timothy Warren68f09812012-04-27 10:38:32 -0400157
158 /**
159 * Probablity level of garbage collection of old sessions
160 *
161 * @var int
162 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200163 public $gc_probability = 5;
Timothy Warren68f09812012-04-27 10:38:32 -0400164
165 /**
166 * Session data
167 *
168 * @var array
169 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200170 public $userdata = array();
Timothy Warren68f09812012-04-27 10:38:32 -0400171
172 /**
173 * Reference to CodeIgniter instance
174 *
175 * @var object
176 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200177 public $CI;
Timothy Warren68f09812012-04-27 10:38:32 -0400178
179 /**
180 * Current time
181 *
182 * @var int
183 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200184 public $now;
Derek Allard2067d1a2008-11-13 22:59:24 +0000185
186 /**
187 * Session Constructor
188 *
189 * The constructor runs the session routines automatically
190 * whenever the class is instantiated.
Timothy Warren68f09812012-04-27 10:38:32 -0400191 *
192 * @param array
Derek Allard2067d1a2008-11-13 22:59:24 +0000193 */
Greg Akera9263282010-11-10 15:26:43 -0600194 public function __construct($params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000195 {
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200196 log_message('debug', 'Session Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000197
198 // Set the super object to a local variable for use throughout the class
199 $this->CI =& get_instance();
200
201 // Set all the session preferences, which can either be set
202 // manually via the $params array above or via the config file
freewil4ad0fd82012-03-13 22:37:42 -0400203 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', 'cookie_httponly', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
Derek Allard2067d1a2008-11-13 22:59:24 +0000204 {
205 $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
206 }
207
Derek Jones5485db52010-08-30 21:31:08 -0500208 if ($this->encryption_key == '')
209 {
210 show_error('In order to use the Session class you are required to set an encryption key in your config file.');
211 }
212
Derek Allard2067d1a2008-11-13 22:59:24 +0000213 // Load the string helper so we can use the strip_slashes() function
214 $this->CI->load->helper('string');
215
216 // Do we need encryption? If so, load the encryption class
217 if ($this->sess_encrypt_cookie == TRUE)
218 {
219 $this->CI->load->library('encrypt');
220 }
221
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200222 // Are we using a database? If so, load it
Andrey Andreevf8868182012-01-20 13:14:53 +0200223 if ($this->sess_use_database === TRUE && $this->sess_table_name != '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000224 {
225 $this->CI->load->database();
226 }
227
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200228 // Set the "now" time. Can either be GMT or server time, based on the
229 // config prefs. We use this to set the "last activity" time
Derek Allard2067d1a2008-11-13 22:59:24 +0000230 $this->now = $this->_get_time();
231
232 // Set the session length. If the session expiration is
233 // set to zero we'll set the expiration two years from now.
234 if ($this->sess_expiration == 0)
235 {
236 $this->sess_expiration = (60*60*24*365*2);
237 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200238
Derek Allard2067d1a2008-11-13 22:59:24 +0000239 // Set the cookie name
240 $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
241
242 // Run the Session routine. If a session doesn't exist we'll
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200243 // create a new one. If it does, we'll update it.
Derek Allard2067d1a2008-11-13 22:59:24 +0000244 if ( ! $this->sess_read())
245 {
246 $this->sess_create();
247 }
248 else
249 {
250 $this->sess_update();
251 }
252
253 // Delete 'old' flashdata (from last request)
Barry Mienydd671972010-10-04 16:33:58 +0200254 $this->_flashdata_sweep();
Derek Allard2067d1a2008-11-13 22:59:24 +0000255
256 // Mark all new flashdata as old (data will be deleted before next request)
Barry Mienydd671972010-10-04 16:33:58 +0200257 $this->_flashdata_mark();
Derek Allard2067d1a2008-11-13 22:59:24 +0000258
259 // Delete expired sessions if necessary
260 $this->_sess_gc();
261
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200262 log_message('debug', 'Session routines successfully run');
Derek Allard2067d1a2008-11-13 22:59:24 +0000263 }
264
265 // --------------------------------------------------------------------
266
267 /**
268 * Fetch the current session data if it exists
269 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000270 * @return bool
271 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200272 public function sess_read()
Derek Allard2067d1a2008-11-13 22:59:24 +0000273 {
274 // Fetch the cookie
275 $session = $this->CI->input->cookie($this->sess_cookie_name);
276
Derek Jones4b9c6292011-07-01 17:40:48 -0500277 // No cookie? Goodbye cruel world!...
Derek Allard2067d1a2008-11-13 22:59:24 +0000278 if ($session === FALSE)
279 {
280 log_message('debug', 'A session cookie was not found.');
281 return FALSE;
282 }
283
284 // Decrypt the cookie data
285 if ($this->sess_encrypt_cookie == TRUE)
286 {
287 $session = $this->CI->encrypt->decode($session);
288 }
289 else
290 {
291 // encryption was not used, so we need to check the md5 hash
292 $hash = substr($session, strlen($session)-32); // get last 32 chars
293 $session = substr($session, 0, strlen($session)-32);
294
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200295 // Does the md5 hash match? This is to prevent manipulation of session data in userspace
Derek Jones4b9c6292011-07-01 17:40:48 -0500296 if ($hash !== md5($session.$this->encryption_key))
Derek Allard2067d1a2008-11-13 22:59:24 +0000297 {
298 log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
299 $this->sess_destroy();
300 return FALSE;
301 }
302 }
303
304 // Unserialize the session array
305 $session = $this->_unserialize($session);
306
307 // Is the session data we unserialized an array with the correct format?
Andrey Andreev7e087f52012-01-20 11:46:27 +0200308 if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity']))
309 {
310 $this->sess_destroy();
311 return FALSE;
312 }
313
314 // Is the session current?
315 if (($session['last_activity'] + $this->sess_expiration) < $this->now)
316 {
317 $this->sess_destroy();
318 return FALSE;
319 }
320
321 // Does the IP match?
322 if ($this->sess_match_ip == TRUE && $session['ip_address'] !== $this->CI->input->ip_address())
323 {
324 $this->sess_destroy();
325 return FALSE;
326 }
327
328 // Does the User Agent Match?
329 if ($this->sess_match_useragent == TRUE && trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000330 {
331 $this->sess_destroy();
332 return FALSE;
333 }
334
335 // Is there a corresponding session in the DB?
336 if ($this->sess_use_database === TRUE)
337 {
338 $this->CI->db->where('session_id', $session['session_id']);
339
340 if ($this->sess_match_ip == TRUE)
341 {
342 $this->CI->db->where('ip_address', $session['ip_address']);
343 }
344
345 if ($this->sess_match_useragent == TRUE)
346 {
347 $this->CI->db->where('user_agent', $session['user_agent']);
348 }
349
Timothy Warrenf1421922012-03-02 11:51:42 -0500350 $query = $this->CI->db->limit(1)->get($this->sess_table_name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000351
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200352 // No result? Kill it!
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200353 if ($query->num_rows() === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000354 {
355 $this->sess_destroy();
356 return FALSE;
357 }
358
Derek Jones4b9c6292011-07-01 17:40:48 -0500359 // Is there custom data? If so, add it to the main session array
Derek Allard2067d1a2008-11-13 22:59:24 +0000360 $row = $query->row();
Andrey Andreevf8868182012-01-20 13:14:53 +0200361 if (isset($row->user_data) && $row->user_data != '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000362 {
363 $custom_data = $this->_unserialize($row->user_data);
364
365 if (is_array($custom_data))
366 {
367 foreach ($custom_data as $key => $val)
368 {
369 $session[$key] = $val;
370 }
371 }
372 }
373 }
374
375 // Session is valid!
376 $this->userdata = $session;
377 unset($session);
378
379 return TRUE;
380 }
381
382 // --------------------------------------------------------------------
383
384 /**
385 * Write the session data
386 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000387 * @return void
388 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200389 public function sess_write()
Derek Allard2067d1a2008-11-13 22:59:24 +0000390 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500391 // Are we saving custom data to the DB? If not, all we do is update the cookie
Derek Allard2067d1a2008-11-13 22:59:24 +0000392 if ($this->sess_use_database === FALSE)
393 {
394 $this->_set_cookie();
395 return;
396 }
397
398 // set the custom userdata, the session data we will set in a second
399 $custom_userdata = $this->userdata;
400 $cookie_userdata = array();
401
402 // Before continuing, we need to determine if there is any custom data to deal with.
403 // Let's determine this by removing the default indexes to see if there's anything left in the array
404 // and set the session data while we're at it
405 foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
406 {
407 unset($custom_userdata[$val]);
408 $cookie_userdata[$val] = $this->userdata[$val];
409 }
410
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200411 // Did we find any custom data? If not, we turn the empty array into a string
Derek Allard2067d1a2008-11-13 22:59:24 +0000412 // since there's no reason to serialize and store an empty array in the DB
413 if (count($custom_userdata) === 0)
414 {
415 $custom_userdata = '';
416 }
417 else
418 {
419 // Serialize the custom data array so we can store it
420 $custom_userdata = $this->_serialize($custom_userdata);
421 }
422
423 // Run the update query
424 $this->CI->db->where('session_id', $this->userdata['session_id']);
425 $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
426
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200427 // Write the cookie. Notice that we manually pass the cookie data array to the
Derek Allard2067d1a2008-11-13 22:59:24 +0000428 // _set_cookie() function. Normally that function will store $this->userdata, but
429 // in this case that array contains custom data, which we do not want in the cookie.
430 $this->_set_cookie($cookie_userdata);
431 }
432
433 // --------------------------------------------------------------------
434
435 /**
436 * Create a new session
437 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000438 * @return void
439 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200440 public function sess_create()
Derek Allard2067d1a2008-11-13 22:59:24 +0000441 {
442 $sessid = '';
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200443 do
Derek Allard2067d1a2008-11-13 22:59:24 +0000444 {
445 $sessid .= mt_rand(0, mt_getrandmax());
446 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200447 while (strlen($sessid) < 32);
Derek Allard2067d1a2008-11-13 22:59:24 +0000448
449 // To make the session ID even more secure we'll combine it with the user's IP
450 $sessid .= $this->CI->input->ip_address();
451
452 $this->userdata = array(
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200453 'session_id' => md5(uniqid($sessid, TRUE)),
454 'ip_address' => $this->CI->input->ip_address(),
455 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
456 'last_activity' => $this->now,
457 'user_data' => ''
458 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000459
460 // Save the data to the DB if needed
461 if ($this->sess_use_database === TRUE)
462 {
463 $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
464 }
465
466 // Write the cookie
467 $this->_set_cookie();
468 }
469
470 // --------------------------------------------------------------------
471
472 /**
473 * Update an existing session
474 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000475 * @return void
476 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200477 public function sess_update()
Derek Allard2067d1a2008-11-13 22:59:24 +0000478 {
479 // We only update the session every five minutes by default
Andrey Andreev9c622f32012-01-19 14:12:54 +0200480 if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
Derek Allard2067d1a2008-11-13 22:59:24 +0000481 {
482 return;
483 }
484
Andrey Andreev9c622f32012-01-19 14:12:54 +0200485 // _set_cookie() will handle this for us if we aren't using database sessions
486 // by pushing all userdata to the cookie.
487 $cookie_data = NULL;
488
489 /* Changing the session ID during an AJAX call causes problems,
490 * so we'll only update our last_activity
491 */
492 if ($this->CI->input->is_ajax_request())
493 {
494 $this->userdata['last_activity'] = $this->now;
495
496 // Update the session ID and last_activity field in the DB if needed
497 if ($this->sess_use_database === TRUE)
498 {
499 // set cookie explicitly to only have our session data
500 $cookie_data = array();
501 foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
502 {
503 $cookie_data[$val] = $this->userdata[$val];
504 }
505
506 $this->CI->db->query($this->CI->db->update_string($this->sess_table_name,
507 array('last_activity' => $this->userdata['last_activity']),
508 array('session_id' => $this->userdata['session_id'])));
509 }
510
511 return $this->_set_cookie($cookie_data);
512 }
513
Derek Allard2067d1a2008-11-13 22:59:24 +0000514 // Save the old session id so we know which record to
515 // update in the database if we need it
516 $old_sessid = $this->userdata['session_id'];
517 $new_sessid = '';
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200518 do
Derek Allard2067d1a2008-11-13 22:59:24 +0000519 {
520 $new_sessid .= mt_rand(0, mt_getrandmax());
521 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200522 while (strlen($new_sessid) < 32);
Derek Allard2067d1a2008-11-13 22:59:24 +0000523
524 // To make the session ID even more secure we'll combine it with the user's IP
525 $new_sessid .= $this->CI->input->ip_address();
526
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200527 // Turn it into a hash and update the session data array
528 $this->userdata['session_id'] = $new_sessid = md5(uniqid($new_sessid, TRUE));
Derek Allard2067d1a2008-11-13 22:59:24 +0000529 $this->userdata['last_activity'] = $this->now;
530
Derek Allard2067d1a2008-11-13 22:59:24 +0000531 // Update the session ID and last_activity field in the DB if needed
532 if ($this->sess_use_database === TRUE)
533 {
534 // set cookie explicitly to only have our session data
535 $cookie_data = array();
536 foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
537 {
538 $cookie_data[$val] = $this->userdata[$val];
539 }
540
541 $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)));
542 }
543
544 // Write the cookie
545 $this->_set_cookie($cookie_data);
546 }
547
548 // --------------------------------------------------------------------
549
550 /**
551 * Destroy the current session
552 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000553 * @return void
554 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200555 public function sess_destroy()
Derek Allard2067d1a2008-11-13 22:59:24 +0000556 {
557 // Kill the session DB row
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200558 if ($this->sess_use_database === TRUE && isset($this->userdata['session_id']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000559 {
560 $this->CI->db->where('session_id', $this->userdata['session_id']);
561 $this->CI->db->delete($this->sess_table_name);
562 }
563
564 // Kill the cookie
565 setcookie(
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200566 $this->sess_cookie_name,
567 addslashes(serialize(array())),
568 ($this->now - 31500000),
569 $this->cookie_path,
570 $this->cookie_domain,
571 0
572 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000573 }
574
575 // --------------------------------------------------------------------
576
577 /**
578 * Fetch a specific item from the session array
579 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000580 * @param string
581 * @return string
582 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200583 public function userdata($item)
Derek Allard2067d1a2008-11-13 22:59:24 +0000584 {
Andrey Andreev6b831232012-03-06 11:16:57 +0200585 return isset($this->userdata[$item]) ? $this->userdata[$item] : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000586 }
587
588 // --------------------------------------------------------------------
589
590 /**
591 * Fetch all session data
592 *
Greg Aker34033662011-04-18 11:18:09 -0500593 * @return array
Derek Allard2067d1a2008-11-13 22:59:24 +0000594 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200595 public function all_userdata()
Derek Allard2067d1a2008-11-13 22:59:24 +0000596 {
Greg Aker34033662011-04-18 11:18:09 -0500597 return $this->userdata;
Derek Allard2067d1a2008-11-13 22:59:24 +0000598 }
Andrey Andreev38d0e932012-04-03 19:27:45 +0300599
Mike Funkc15e17c2012-02-23 14:56:18 -0500600 // --------------------------------------------------------------------------
Andrey Andreev38d0e932012-04-03 19:27:45 +0300601
Mike Funkc15e17c2012-02-23 14:56:18 -0500602 /**
603 * Fetch all flashdata
Andrey Andreev38d0e932012-04-03 19:27:45 +0300604 *
Mike Funkc91a66c2012-02-28 13:46:00 -0500605 * @return array
Mike Funkc15e17c2012-02-23 14:56:18 -0500606 */
607 public function all_flashdata()
608 {
609 $out = array();
Andrey Andreev38d0e932012-04-03 19:27:45 +0300610
Mike Funkc15e17c2012-02-23 14:56:18 -0500611 // loop through all userdata
612 foreach ($this->all_userdata() as $key => $val)
Andrey Andreev38d0e932012-04-03 19:27:45 +0300613 {
Mike Funkc15e17c2012-02-23 14:56:18 -0500614 // if it contains flashdata, add it
615 if (strpos($key, 'flash:old:') !== FALSE)
616 {
617 $out[$key] = $val;
618 }
619 }
620 return $out;
621 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000622
623 // --------------------------------------------------------------------
624
625 /**
626 * Add or change data in the "userdata" array
627 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000628 * @param mixed
629 * @param string
630 * @return void
631 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200632 public function set_userdata($newdata = array(), $newval = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000633 {
634 if (is_string($newdata))
635 {
636 $newdata = array($newdata => $newval);
637 }
638
639 if (count($newdata) > 0)
640 {
641 foreach ($newdata as $key => $val)
642 {
643 $this->userdata[$key] = $val;
644 }
645 }
646
647 $this->sess_write();
648 }
649
650 // --------------------------------------------------------------------
651
652 /**
653 * Delete a session variable from the "userdata" array
654 *
Timothy Warren68f09812012-04-27 10:38:32 -0400655 * @param array
Derek Allard2067d1a2008-11-13 22:59:24 +0000656 * @return void
657 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200658 public function unset_userdata($newdata = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000659 {
660 if (is_string($newdata))
661 {
662 $newdata = array($newdata => '');
663 }
664
665 if (count($newdata) > 0)
666 {
667 foreach ($newdata as $key => $val)
668 {
669 unset($this->userdata[$key]);
670 }
671 }
672
673 $this->sess_write();
674 }
675
676 // ------------------------------------------------------------------------
677
678 /**
679 * Add or change flashdata, only available
680 * until the next request
681 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000682 * @param mixed
683 * @param string
684 * @return void
685 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200686 public function set_flashdata($newdata = array(), $newval = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000687 {
688 if (is_string($newdata))
689 {
690 $newdata = array($newdata => $newval);
691 }
692
693 if (count($newdata) > 0)
694 {
695 foreach ($newdata as $key => $val)
696 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200697 $this->set_userdata($this->flashdata_key.':new:'.$key, $val);
Derek Allard2067d1a2008-11-13 22:59:24 +0000698 }
699 }
700 }
701
702 // ------------------------------------------------------------------------
703
704 /**
705 * Keeps existing flashdata available to next request.
706 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000707 * @param string
708 * @return void
709 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200710 public function keep_flashdata($key)
Derek Allard2067d1a2008-11-13 22:59:24 +0000711 {
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200712 // 'old' flashdata gets removed. Here we mark all
Derek Allard2067d1a2008-11-13 22:59:24 +0000713 // flashdata as 'new' to preserve it from _flashdata_sweep()
714 // Note the function will return FALSE if the $key
715 // provided cannot be found
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200716 $value = $this->userdata($this->flashdata_key.':old:'.$key);
Derek Allard2067d1a2008-11-13 22:59:24 +0000717
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200718 $this->set_userdata($this->flashdata_key.':new:'.$key, $value);
Derek Allard2067d1a2008-11-13 22:59:24 +0000719 }
720
721 // ------------------------------------------------------------------------
722
723 /**
724 * Fetch a specific flashdata item from the session array
725 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000726 * @param string
727 * @return string
728 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200729 public function flashdata($key)
Derek Allard2067d1a2008-11-13 22:59:24 +0000730 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200731 return $this->userdata($this->flashdata_key.':old:'.$key);
Derek Allard2067d1a2008-11-13 22:59:24 +0000732 }
733
734 // ------------------------------------------------------------------------
735
736 /**
737 * Identifies flashdata as 'old' for removal
738 * when _flashdata_sweep() runs.
739 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000740 * @return void
741 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200742 protected function _flashdata_mark()
Derek Allard2067d1a2008-11-13 22:59:24 +0000743 {
744 $userdata = $this->all_userdata();
745 foreach ($userdata as $name => $value)
746 {
747 $parts = explode(':new:', $name);
748 if (is_array($parts) && count($parts) === 2)
749 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200750 $this->set_userdata($this->flashdata_key.':old:'.$parts[1], $value);
Derek Allard2067d1a2008-11-13 22:59:24 +0000751 $this->unset_userdata($name);
752 }
753 }
754 }
755
756 // ------------------------------------------------------------------------
757
758 /**
759 * Removes all flashdata marked as 'old'
760 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000761 * @return void
762 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200763 protected function _flashdata_sweep()
Derek Allard2067d1a2008-11-13 22:59:24 +0000764 {
765 $userdata = $this->all_userdata();
766 foreach ($userdata as $key => $value)
767 {
768 if (strpos($key, ':old:'))
769 {
770 $this->unset_userdata($key);
771 }
772 }
773
774 }
775
776 // --------------------------------------------------------------------
777
778 /**
779 * Get the "now" time
780 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000781 * @return string
782 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200783 protected function _get_time()
Derek Allard2067d1a2008-11-13 22:59:24 +0000784 {
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200785 return (strtolower($this->time_reference) === 'gmt')
786 ? mktime(gmdate('H'), gmdate('i'), gmdate('s'), gmdate('m'), gmdate('d'), gmdate('Y'))
787 : time();
Derek Allard2067d1a2008-11-13 22:59:24 +0000788 }
789
790 // --------------------------------------------------------------------
791
792 /**
793 * Write the session cookie
794 *
Timothy Warren68f09812012-04-27 10:38:32 -0400795 * @param mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000796 * @return void
797 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200798 protected function _set_cookie($cookie_data = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000799 {
800 if (is_null($cookie_data))
801 {
802 $cookie_data = $this->userdata;
803 }
804
805 // Serialize the userdata for the cookie
806 $cookie_data = $this->_serialize($cookie_data);
807
808 if ($this->sess_encrypt_cookie == TRUE)
809 {
810 $cookie_data = $this->CI->encrypt->encode($cookie_data);
811 }
812 else
813 {
814 // if encryption is not used, we provide an md5 hash to prevent userside tampering
815 $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
816 }
Barry Mienydd671972010-10-04 16:33:58 +0200817
Derek Joneseaa71ba2010-09-02 10:32:07 -0500818 $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
Barry Mienydd671972010-10-04 16:33:58 +0200819
Derek Allard2067d1a2008-11-13 22:59:24 +0000820 // Set the cookie
821 setcookie(
freewil4ad0fd82012-03-13 22:37:42 -0400822 $this->sess_cookie_name,
823 $cookie_data,
824 $expire,
825 $this->cookie_path,
826 $this->cookie_domain,
827 $this->cookie_secure,
828 $this->cookie_httponly
829 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000830 }
831
832 // --------------------------------------------------------------------
833
834 /**
835 * Serialize an array
836 *
837 * This function first converts any slashes found in the array to a temporary
838 * marker, so when it gets unserialized the slashes will be preserved
839 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000840 * @param array
841 * @return string
842 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200843 protected function _serialize($data)
Derek Allard2067d1a2008-11-13 22:59:24 +0000844 {
845 if (is_array($data))
846 {
Chris Muench95933492011-10-16 14:14:04 -0400847 array_walk_recursive($data, array(&$this, '_escape_slashes'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000848 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200849 elseif (is_string($data))
Derek Allard2067d1a2008-11-13 22:59:24 +0000850 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200851 $data = str_replace('\\', '{{slash}}', $data);
Derek Allard2067d1a2008-11-13 22:59:24 +0000852 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000853 return serialize($data);
854 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200855
Chris Muench95933492011-10-16 14:14:04 -0400856 /**
857 * Escape slashes
858 *
859 * This function converts any slashes found into a temporary marker
860 *
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200861 * @param string
862 * @param string
863 * @return void
Chris Muench95933492011-10-16 14:14:04 -0400864 */
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200865 protected function _escape_slashes(&$val, $key)
Chris Muench95933492011-10-16 14:14:04 -0400866 {
867 if (is_string($val))
868 {
869 $val = str_replace('\\', '{{slash}}', $val);
870 }
871 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000872
873 // --------------------------------------------------------------------
874
875 /**
876 * Unserialize
877 *
878 * This function unserializes a data string, then converts any
879 * temporary slash markers back to actual slashes
880 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000881 * @param array
882 * @return string
883 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200884 protected function _unserialize($data)
Derek Allard2067d1a2008-11-13 22:59:24 +0000885 {
Andrey Andreev6b831232012-03-06 11:16:57 +0200886 $data = @unserialize(strip_slashes(trim($data)));
Derek Allard2067d1a2008-11-13 22:59:24 +0000887
888 if (is_array($data))
889 {
Chris Muench95933492011-10-16 14:14:04 -0400890 array_walk_recursive($data, array(&$this, '_unescape_slashes'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000891 return $data;
892 }
893
Andrey Andreev6b831232012-03-06 11:16:57 +0200894 return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data;
Derek Allard2067d1a2008-11-13 22:59:24 +0000895 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200896
Andrey Andreev6b831232012-03-06 11:16:57 +0200897 // --------------------------------------------------------------------
898
Chris Muench95933492011-10-16 14:14:04 -0400899 /**
900 * Unescape slashes
901 *
902 * This function converts any slash markers back into actual slashes
903 *
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200904 * @param string
905 * @param string
906 * @return void
Chris Muench95933492011-10-16 14:14:04 -0400907 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200908 protected function _unescape_slashes(&$val, $key)
Chris Muench95933492011-10-16 14:14:04 -0400909 {
Chris Muench3e414f92011-10-16 23:03:55 -0400910 if (is_string($val))
911 {
912 $val= str_replace('{{slash}}', '\\', $val);
913 }
Chris Muench95933492011-10-16 14:14:04 -0400914 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000915
916 // --------------------------------------------------------------------
917
918 /**
919 * Garbage collection
920 *
921 * This deletes expired session rows from database
922 * if the probability percentage is met
923 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000924 * @return void
925 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200926 protected function _sess_gc()
Derek Allard2067d1a2008-11-13 22:59:24 +0000927 {
928 if ($this->sess_use_database != TRUE)
929 {
930 return;
931 }
932
933 srand(time());
934 if ((rand() % 100) < $this->gc_probability)
935 {
936 $expire = $this->now - $this->sess_expiration;
937
Andrey Andreev6b831232012-03-06 11:16:57 +0200938 $this->CI->db->where('last_activity < '.$expire);
Derek Allard2067d1a2008-11-13 22:59:24 +0000939 $this->CI->db->delete($this->sess_table_name);
940
941 log_message('debug', 'Session garbage collection performed.');
942 }
943 }
944
Derek Allard2067d1a2008-11-13 22:59:24 +0000945}
Derek Allard2067d1a2008-11-13 22:59:24 +0000946
947/* End of file Session.php */
Andrey Andreev38d0e932012-04-03 19:27:45 +0300948/* Location: ./system/libraries/Session.php */