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