blob: dd50a91e1e94c14ae79413199d8f926f2786a3ce [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
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
Andrey Andreev57ffbbb2011-12-25 04:48:47 +020039 public $sess_encrypt_cookie = FALSE;
40 public $sess_use_database = FALSE;
41 public $sess_table_name = '';
42 public $sess_expiration = 7200;
43 public $sess_expire_on_close = FALSE;
44 public $sess_match_ip = FALSE;
45 public $sess_match_useragent = TRUE;
46 public $sess_cookie_name = 'ci_session';
47 public $cookie_prefix = '';
48 public $cookie_path = '';
49 public $cookie_domain = '';
50 public $cookie_secure = FALSE;
51 public $sess_time_to_update = 300;
52 public $encryption_key = '';
53 public $flashdata_key = 'flash';
54 public $time_reference = 'time';
55 public $gc_probability = 5;
56 public $userdata = array();
57 public $CI;
58 public $now;
Derek Allard2067d1a2008-11-13 22:59:24 +000059
60 /**
61 * Session Constructor
62 *
63 * The constructor runs the session routines automatically
64 * whenever the class is instantiated.
65 */
Greg Akera9263282010-11-10 15:26:43 -060066 public function __construct($params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000067 {
Andrey Andreeveea2ff52012-01-19 13:21:53 +020068 log_message('debug', 'Session Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +000069
70 // Set the super object to a local variable for use throughout the class
71 $this->CI =& get_instance();
72
73 // Set all the session preferences, which can either be set
74 // manually via the $params array above or via the config file
tobiasbgba6432c2011-02-18 21:58:48 +010075 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 +000076 {
77 $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
78 }
79
Derek Jones5485db52010-08-30 21:31:08 -050080 if ($this->encryption_key == '')
81 {
82 show_error('In order to use the Session class you are required to set an encryption key in your config file.');
83 }
84
Derek Allard2067d1a2008-11-13 22:59:24 +000085 // Load the string helper so we can use the strip_slashes() function
86 $this->CI->load->helper('string');
87
88 // Do we need encryption? If so, load the encryption class
89 if ($this->sess_encrypt_cookie == TRUE)
90 {
91 $this->CI->load->library('encrypt');
92 }
93
Andrey Andreeveea2ff52012-01-19 13:21:53 +020094 // Are we using a database? If so, load it
Andrey Andreevf8868182012-01-20 13:14:53 +020095 if ($this->sess_use_database === TRUE && $this->sess_table_name != '')
Derek Allard2067d1a2008-11-13 22:59:24 +000096 {
97 $this->CI->load->database();
98 }
99
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200100 // Set the "now" time. Can either be GMT or server time, based on the
101 // config prefs. We use this to set the "last activity" time
Derek Allard2067d1a2008-11-13 22:59:24 +0000102 $this->now = $this->_get_time();
103
104 // Set the session length. If the session expiration is
105 // set to zero we'll set the expiration two years from now.
106 if ($this->sess_expiration == 0)
107 {
108 $this->sess_expiration = (60*60*24*365*2);
109 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200110
Derek Allard2067d1a2008-11-13 22:59:24 +0000111 // Set the cookie name
112 $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
113
114 // Run the Session routine. If a session doesn't exist we'll
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200115 // create a new one. If it does, we'll update it.
Derek Allard2067d1a2008-11-13 22:59:24 +0000116 if ( ! $this->sess_read())
117 {
118 $this->sess_create();
119 }
120 else
121 {
122 $this->sess_update();
123 }
124
125 // Delete 'old' flashdata (from last request)
Barry Mienydd671972010-10-04 16:33:58 +0200126 $this->_flashdata_sweep();
Derek Allard2067d1a2008-11-13 22:59:24 +0000127
128 // Mark all new flashdata as old (data will be deleted before next request)
Barry Mienydd671972010-10-04 16:33:58 +0200129 $this->_flashdata_mark();
Derek Allard2067d1a2008-11-13 22:59:24 +0000130
131 // Delete expired sessions if necessary
132 $this->_sess_gc();
133
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200134 log_message('debug', 'Session routines successfully run');
Derek Allard2067d1a2008-11-13 22:59:24 +0000135 }
136
137 // --------------------------------------------------------------------
138
139 /**
140 * Fetch the current session data if it exists
141 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000142 * @return bool
143 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200144 public function sess_read()
Derek Allard2067d1a2008-11-13 22:59:24 +0000145 {
146 // Fetch the cookie
147 $session = $this->CI->input->cookie($this->sess_cookie_name);
148
Derek Jones4b9c6292011-07-01 17:40:48 -0500149 // No cookie? Goodbye cruel world!...
Derek Allard2067d1a2008-11-13 22:59:24 +0000150 if ($session === FALSE)
151 {
152 log_message('debug', 'A session cookie was not found.');
153 return FALSE;
154 }
155
156 // Decrypt the cookie data
157 if ($this->sess_encrypt_cookie == TRUE)
158 {
159 $session = $this->CI->encrypt->decode($session);
160 }
161 else
162 {
163 // encryption was not used, so we need to check the md5 hash
164 $hash = substr($session, strlen($session)-32); // get last 32 chars
165 $session = substr($session, 0, strlen($session)-32);
166
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200167 // Does the md5 hash match? This is to prevent manipulation of session data in userspace
Derek Jones4b9c6292011-07-01 17:40:48 -0500168 if ($hash !== md5($session.$this->encryption_key))
Derek Allard2067d1a2008-11-13 22:59:24 +0000169 {
170 log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
171 $this->sess_destroy();
172 return FALSE;
173 }
174 }
175
176 // Unserialize the session array
177 $session = $this->_unserialize($session);
178
179 // Is the session data we unserialized an array with the correct format?
Andrey Andreev7e087f52012-01-20 11:46:27 +0200180 if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity']))
181 {
182 $this->sess_destroy();
183 return FALSE;
184 }
185
186 // Is the session current?
187 if (($session['last_activity'] + $this->sess_expiration) < $this->now)
188 {
189 $this->sess_destroy();
190 return FALSE;
191 }
192
193 // Does the IP match?
194 if ($this->sess_match_ip == TRUE && $session['ip_address'] !== $this->CI->input->ip_address())
195 {
196 $this->sess_destroy();
197 return FALSE;
198 }
199
200 // Does the User Agent Match?
201 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 +0000202 {
203 $this->sess_destroy();
204 return FALSE;
205 }
206
207 // Is there a corresponding session in the DB?
208 if ($this->sess_use_database === TRUE)
209 {
210 $this->CI->db->where('session_id', $session['session_id']);
211
212 if ($this->sess_match_ip == TRUE)
213 {
214 $this->CI->db->where('ip_address', $session['ip_address']);
215 }
216
217 if ($this->sess_match_useragent == TRUE)
218 {
219 $this->CI->db->where('user_agent', $session['user_agent']);
220 }
221
Timothy Warrenf1421922012-03-02 11:51:42 -0500222 $query = $this->CI->db->limit(1)->get($this->sess_table_name);
Derek Allard2067d1a2008-11-13 22:59:24 +0000223
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200224 // No result? Kill it!
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200225 if ($query->num_rows() === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000226 {
227 $this->sess_destroy();
228 return FALSE;
229 }
230
Derek Jones4b9c6292011-07-01 17:40:48 -0500231 // Is there custom data? If so, add it to the main session array
Derek Allard2067d1a2008-11-13 22:59:24 +0000232 $row = $query->row();
Andrey Andreevf8868182012-01-20 13:14:53 +0200233 if (isset($row->user_data) && $row->user_data != '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000234 {
235 $custom_data = $this->_unserialize($row->user_data);
236
237 if (is_array($custom_data))
238 {
239 foreach ($custom_data as $key => $val)
240 {
241 $session[$key] = $val;
242 }
243 }
244 }
245 }
246
247 // Session is valid!
248 $this->userdata = $session;
249 unset($session);
250
251 return TRUE;
252 }
253
254 // --------------------------------------------------------------------
255
256 /**
257 * Write the session data
258 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000259 * @return void
260 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200261 public function sess_write()
Derek Allard2067d1a2008-11-13 22:59:24 +0000262 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500263 // Are we saving custom data to the DB? If not, all we do is update the cookie
Derek Allard2067d1a2008-11-13 22:59:24 +0000264 if ($this->sess_use_database === FALSE)
265 {
266 $this->_set_cookie();
267 return;
268 }
269
270 // set the custom userdata, the session data we will set in a second
271 $custom_userdata = $this->userdata;
272 $cookie_userdata = array();
273
274 // Before continuing, we need to determine if there is any custom data to deal with.
275 // Let's determine this by removing the default indexes to see if there's anything left in the array
276 // and set the session data while we're at it
277 foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
278 {
279 unset($custom_userdata[$val]);
280 $cookie_userdata[$val] = $this->userdata[$val];
281 }
282
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200283 // Did we find any custom data? If not, we turn the empty array into a string
Derek Allard2067d1a2008-11-13 22:59:24 +0000284 // since there's no reason to serialize and store an empty array in the DB
285 if (count($custom_userdata) === 0)
286 {
287 $custom_userdata = '';
288 }
289 else
290 {
291 // Serialize the custom data array so we can store it
292 $custom_userdata = $this->_serialize($custom_userdata);
293 }
294
295 // Run the update query
296 $this->CI->db->where('session_id', $this->userdata['session_id']);
297 $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
298
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200299 // Write the cookie. Notice that we manually pass the cookie data array to the
Derek Allard2067d1a2008-11-13 22:59:24 +0000300 // _set_cookie() function. Normally that function will store $this->userdata, but
301 // in this case that array contains custom data, which we do not want in the cookie.
302 $this->_set_cookie($cookie_userdata);
303 }
304
305 // --------------------------------------------------------------------
306
307 /**
308 * Create a new session
309 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000310 * @return void
311 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200312 public function sess_create()
Derek Allard2067d1a2008-11-13 22:59:24 +0000313 {
314 $sessid = '';
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200315 do
Derek Allard2067d1a2008-11-13 22:59:24 +0000316 {
317 $sessid .= mt_rand(0, mt_getrandmax());
318 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200319 while (strlen($sessid) < 32);
Derek Allard2067d1a2008-11-13 22:59:24 +0000320
321 // To make the session ID even more secure we'll combine it with the user's IP
322 $sessid .= $this->CI->input->ip_address();
323
324 $this->userdata = array(
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200325 'session_id' => md5(uniqid($sessid, TRUE)),
326 'ip_address' => $this->CI->input->ip_address(),
327 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
328 'last_activity' => $this->now,
329 'user_data' => ''
330 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000331
332 // Save the data to the DB if needed
333 if ($this->sess_use_database === TRUE)
334 {
335 $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
336 }
337
338 // Write the cookie
339 $this->_set_cookie();
340 }
341
342 // --------------------------------------------------------------------
343
344 /**
345 * Update an existing session
346 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000347 * @return void
348 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200349 public function sess_update()
Derek Allard2067d1a2008-11-13 22:59:24 +0000350 {
351 // We only update the session every five minutes by default
Andrey Andreev9c622f32012-01-19 14:12:54 +0200352 if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
Derek Allard2067d1a2008-11-13 22:59:24 +0000353 {
354 return;
355 }
356
Andrey Andreev9c622f32012-01-19 14:12:54 +0200357 // _set_cookie() will handle this for us if we aren't using database sessions
358 // by pushing all userdata to the cookie.
359 $cookie_data = NULL;
360
361 /* Changing the session ID during an AJAX call causes problems,
362 * so we'll only update our last_activity
363 */
364 if ($this->CI->input->is_ajax_request())
365 {
366 $this->userdata['last_activity'] = $this->now;
367
368 // Update the session ID and last_activity field in the DB if needed
369 if ($this->sess_use_database === TRUE)
370 {
371 // set cookie explicitly to only have our session data
372 $cookie_data = array();
373 foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
374 {
375 $cookie_data[$val] = $this->userdata[$val];
376 }
377
378 $this->CI->db->query($this->CI->db->update_string($this->sess_table_name,
379 array('last_activity' => $this->userdata['last_activity']),
380 array('session_id' => $this->userdata['session_id'])));
381 }
382
383 return $this->_set_cookie($cookie_data);
384 }
385
Derek Allard2067d1a2008-11-13 22:59:24 +0000386 // Save the old session id so we know which record to
387 // update in the database if we need it
388 $old_sessid = $this->userdata['session_id'];
389 $new_sessid = '';
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200390 do
Derek Allard2067d1a2008-11-13 22:59:24 +0000391 {
392 $new_sessid .= mt_rand(0, mt_getrandmax());
393 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200394 while (strlen($new_sessid) < 32);
Derek Allard2067d1a2008-11-13 22:59:24 +0000395
396 // To make the session ID even more secure we'll combine it with the user's IP
397 $new_sessid .= $this->CI->input->ip_address();
398
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200399 // Turn it into a hash and update the session data array
400 $this->userdata['session_id'] = $new_sessid = md5(uniqid($new_sessid, TRUE));
Derek Allard2067d1a2008-11-13 22:59:24 +0000401 $this->userdata['last_activity'] = $this->now;
402
Derek Allard2067d1a2008-11-13 22:59:24 +0000403 // Update the session ID and last_activity field in the DB if needed
404 if ($this->sess_use_database === TRUE)
405 {
406 // set cookie explicitly to only have our session data
407 $cookie_data = array();
408 foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
409 {
410 $cookie_data[$val] = $this->userdata[$val];
411 }
412
413 $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)));
414 }
415
416 // Write the cookie
417 $this->_set_cookie($cookie_data);
418 }
419
420 // --------------------------------------------------------------------
421
422 /**
423 * Destroy the current session
424 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000425 * @return void
426 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200427 public function sess_destroy()
Derek Allard2067d1a2008-11-13 22:59:24 +0000428 {
429 // Kill the session DB row
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200430 if ($this->sess_use_database === TRUE && isset($this->userdata['session_id']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000431 {
432 $this->CI->db->where('session_id', $this->userdata['session_id']);
433 $this->CI->db->delete($this->sess_table_name);
434 }
435
436 // Kill the cookie
437 setcookie(
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200438 $this->sess_cookie_name,
439 addslashes(serialize(array())),
440 ($this->now - 31500000),
441 $this->cookie_path,
442 $this->cookie_domain,
443 0
444 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000445 }
446
447 // --------------------------------------------------------------------
448
449 /**
450 * Fetch a specific item from the session array
451 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000452 * @param string
453 * @return string
454 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200455 public function userdata($item)
Derek Allard2067d1a2008-11-13 22:59:24 +0000456 {
457 return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
458 }
459
460 // --------------------------------------------------------------------
461
462 /**
463 * Fetch all session data
464 *
Greg Aker34033662011-04-18 11:18:09 -0500465 * @return array
Derek Allard2067d1a2008-11-13 22:59:24 +0000466 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200467 public function all_userdata()
Derek Allard2067d1a2008-11-13 22:59:24 +0000468 {
Greg Aker34033662011-04-18 11:18:09 -0500469 return $this->userdata;
Derek Allard2067d1a2008-11-13 22:59:24 +0000470 }
471
472 // --------------------------------------------------------------------
473
474 /**
475 * Add or change data in the "userdata" array
476 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000477 * @param mixed
478 * @param string
479 * @return void
480 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200481 public function set_userdata($newdata = array(), $newval = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000482 {
483 if (is_string($newdata))
484 {
485 $newdata = array($newdata => $newval);
486 }
487
488 if (count($newdata) > 0)
489 {
490 foreach ($newdata as $key => $val)
491 {
492 $this->userdata[$key] = $val;
493 }
494 }
495
496 $this->sess_write();
497 }
498
499 // --------------------------------------------------------------------
500
501 /**
502 * Delete a session variable from the "userdata" array
503 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000504 * @return void
505 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200506 public function unset_userdata($newdata = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000507 {
508 if (is_string($newdata))
509 {
510 $newdata = array($newdata => '');
511 }
512
513 if (count($newdata) > 0)
514 {
515 foreach ($newdata as $key => $val)
516 {
517 unset($this->userdata[$key]);
518 }
519 }
520
521 $this->sess_write();
522 }
523
524 // ------------------------------------------------------------------------
525
526 /**
527 * Add or change flashdata, only available
528 * until the next request
529 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000530 * @param mixed
531 * @param string
532 * @return void
533 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200534 public function set_flashdata($newdata = array(), $newval = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000535 {
536 if (is_string($newdata))
537 {
538 $newdata = array($newdata => $newval);
539 }
540
541 if (count($newdata) > 0)
542 {
543 foreach ($newdata as $key => $val)
544 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200545 $this->set_userdata($this->flashdata_key.':new:'.$key, $val);
Derek Allard2067d1a2008-11-13 22:59:24 +0000546 }
547 }
548 }
549
550 // ------------------------------------------------------------------------
551
552 /**
553 * Keeps existing flashdata available to next request.
554 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000555 * @param string
556 * @return void
557 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200558 public function keep_flashdata($key)
Derek Allard2067d1a2008-11-13 22:59:24 +0000559 {
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200560 // 'old' flashdata gets removed. Here we mark all
Derek Allard2067d1a2008-11-13 22:59:24 +0000561 // flashdata as 'new' to preserve it from _flashdata_sweep()
562 // Note the function will return FALSE if the $key
563 // provided cannot be found
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200564 $value = $this->userdata($this->flashdata_key.':old:'.$key);
Derek Allard2067d1a2008-11-13 22:59:24 +0000565
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200566 $this->set_userdata($this->flashdata_key.':new:'.$key, $value);
Derek Allard2067d1a2008-11-13 22:59:24 +0000567 }
568
569 // ------------------------------------------------------------------------
570
571 /**
572 * Fetch a specific flashdata item from the session array
573 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000574 * @param string
575 * @return string
576 */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200577 public function flashdata($key)
Derek Allard2067d1a2008-11-13 22:59:24 +0000578 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200579 return $this->userdata($this->flashdata_key.':old:'.$key);
Derek Allard2067d1a2008-11-13 22:59:24 +0000580 }
581
582 // ------------------------------------------------------------------------
583
584 /**
585 * Identifies flashdata as 'old' for removal
586 * when _flashdata_sweep() runs.
587 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000588 * @return void
589 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200590 protected function _flashdata_mark()
Derek Allard2067d1a2008-11-13 22:59:24 +0000591 {
592 $userdata = $this->all_userdata();
593 foreach ($userdata as $name => $value)
594 {
595 $parts = explode(':new:', $name);
596 if (is_array($parts) && count($parts) === 2)
597 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200598 $this->set_userdata($this->flashdata_key.':old:'.$parts[1], $value);
Derek Allard2067d1a2008-11-13 22:59:24 +0000599 $this->unset_userdata($name);
600 }
601 }
602 }
603
604 // ------------------------------------------------------------------------
605
606 /**
607 * Removes all flashdata marked as 'old'
608 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000609 * @return void
610 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200611 protected function _flashdata_sweep()
Derek Allard2067d1a2008-11-13 22:59:24 +0000612 {
613 $userdata = $this->all_userdata();
614 foreach ($userdata as $key => $value)
615 {
616 if (strpos($key, ':old:'))
617 {
618 $this->unset_userdata($key);
619 }
620 }
621
622 }
623
624 // --------------------------------------------------------------------
625
626 /**
627 * Get the "now" time
628 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000629 * @return string
630 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200631 protected function _get_time()
Derek Allard2067d1a2008-11-13 22:59:24 +0000632 {
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200633 return (strtolower($this->time_reference) === 'gmt')
634 ? mktime(gmdate('H'), gmdate('i'), gmdate('s'), gmdate('m'), gmdate('d'), gmdate('Y'))
635 : time();
Derek Allard2067d1a2008-11-13 22:59:24 +0000636 }
637
638 // --------------------------------------------------------------------
639
640 /**
641 * Write the session cookie
642 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000643 * @return void
644 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200645 protected function _set_cookie($cookie_data = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000646 {
647 if (is_null($cookie_data))
648 {
649 $cookie_data = $this->userdata;
650 }
651
652 // Serialize the userdata for the cookie
653 $cookie_data = $this->_serialize($cookie_data);
654
655 if ($this->sess_encrypt_cookie == TRUE)
656 {
657 $cookie_data = $this->CI->encrypt->encode($cookie_data);
658 }
659 else
660 {
661 // if encryption is not used, we provide an md5 hash to prevent userside tampering
662 $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
663 }
Barry Mienydd671972010-10-04 16:33:58 +0200664
Derek Joneseaa71ba2010-09-02 10:32:07 -0500665 $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
Barry Mienydd671972010-10-04 16:33:58 +0200666
Derek Allard2067d1a2008-11-13 22:59:24 +0000667 // Set the cookie
668 setcookie(
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200669 $this->sess_cookie_name,
670 $cookie_data,
671 $expire,
672 $this->cookie_path,
673 $this->cookie_domain,
674 $this->cookie_secure
675 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000676 }
677
678 // --------------------------------------------------------------------
679
680 /**
681 * Serialize an array
682 *
683 * This function first converts any slashes found in the array to a temporary
684 * marker, so when it gets unserialized the slashes will be preserved
685 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000686 * @param array
687 * @return string
688 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200689 protected function _serialize($data)
Derek Allard2067d1a2008-11-13 22:59:24 +0000690 {
691 if (is_array($data))
692 {
Chris Muench95933492011-10-16 14:14:04 -0400693 array_walk_recursive($data, array(&$this, '_escape_slashes'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000694 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200695 elseif (is_string($data))
Derek Allard2067d1a2008-11-13 22:59:24 +0000696 {
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200697 $data = str_replace('\\', '{{slash}}', $data);
Derek Allard2067d1a2008-11-13 22:59:24 +0000698 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000699 return serialize($data);
700 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200701
Chris Muench95933492011-10-16 14:14:04 -0400702 /**
703 * Escape slashes
704 *
705 * This function converts any slashes found into a temporary marker
706 *
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200707 * @param string
708 * @param string
709 * @return void
Chris Muench95933492011-10-16 14:14:04 -0400710 */
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200711 protected function _escape_slashes(&$val, $key)
Chris Muench95933492011-10-16 14:14:04 -0400712 {
713 if (is_string($val))
714 {
715 $val = str_replace('\\', '{{slash}}', $val);
716 }
717 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000718
719 // --------------------------------------------------------------------
720
721 /**
722 * Unserialize
723 *
724 * This function unserializes a data string, then converts any
725 * temporary slash markers back to actual slashes
726 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000727 * @param array
728 * @return string
729 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200730 protected function _unserialize($data)
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 {
732 $data = @unserialize(strip_slashes($data));
733
734 if (is_array($data))
735 {
Chris Muench95933492011-10-16 14:14:04 -0400736 array_walk_recursive($data, array(&$this, '_unescape_slashes'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000737 return $data;
738 }
739
Derek Jones133e6662010-03-29 11:36:42 -0500740 return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data;
Derek Allard2067d1a2008-11-13 22:59:24 +0000741 }
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200742
Chris Muench95933492011-10-16 14:14:04 -0400743 /**
744 * Unescape slashes
745 *
746 * This function converts any slash markers back into actual slashes
747 *
Andrey Andreeveea2ff52012-01-19 13:21:53 +0200748 * @param string
749 * @param string
750 * @return void
Chris Muench95933492011-10-16 14:14:04 -0400751 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200752 protected function _unescape_slashes(&$val, $key)
Chris Muench95933492011-10-16 14:14:04 -0400753 {
Chris Muench3e414f92011-10-16 23:03:55 -0400754 if (is_string($val))
755 {
756 $val= str_replace('{{slash}}', '\\', $val);
757 }
Chris Muench95933492011-10-16 14:14:04 -0400758 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000759
760 // --------------------------------------------------------------------
761
762 /**
763 * Garbage collection
764 *
765 * This deletes expired session rows from database
766 * if the probability percentage is met
767 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000768 * @return void
769 */
Andrey Andreev2c79b762011-12-26 16:54:44 +0200770 protected function _sess_gc()
Derek Allard2067d1a2008-11-13 22:59:24 +0000771 {
772 if ($this->sess_use_database != TRUE)
773 {
774 return;
775 }
776
777 srand(time());
778 if ((rand() % 100) < $this->gc_probability)
779 {
780 $expire = $this->now - $this->sess_expiration;
781
782 $this->CI->db->where("last_activity < {$expire}");
783 $this->CI->db->delete($this->sess_table_name);
784
785 log_message('debug', 'Session garbage collection performed.');
786 }
787 }
788
Derek Allard2067d1a2008-11-13 22:59:24 +0000789}
Derek Allard2067d1a2008-11-13 22:59:24 +0000790
791/* End of file Session.php */
Andrey Andreev57ffbbb2011-12-25 04:48:47 +0200792/* Location: ./system/libraries/Session.php */