1 <?php defined('SYSPATH') OR die('No direct access allowed.');
5 * $Id: Session.php 4073 2009-03-13 17:53:58Z Shadowhand $
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
15 protected static $instance;
17 // Protected key names (cannot be set by the user)
18 protected static $protect = array('session_id', 'user_agent', 'last_activity', 'ip_address', 'total_hits', '_kf_flash_');
20 // Configuration and driver
21 protected static $config;
22 protected static $driver;
25 protected static $flash;
31 * Singleton instance of Session.
33 public static function instance()
35 if (Session::$instance == NULL)
37 // Create a new instance
41 return Session::$instance;
45 * On first session instance creation, sets up the driver and creates session.
47 public function __construct()
49 $this->input = Input::instance();
51 // This part only needs to be run once
52 if (Session::$instance === NULL)
55 Session::$config = Kohana::config('session');
57 // Makes a mirrored array, eg: foo=foo
58 Session::$protect = array_combine(Session::$protect, Session::$protect);
60 // Configure garbage collection
61 ini_set('session.gc_probability', (int) Session::$config['gc_probability']);
62 ini_set('session.gc_divisor', 100);
63 ini_set('session.gc_maxlifetime', (Session::$config['expiration'] == 0) ? 86400 : Session::$config['expiration']);
65 // Create a new session
68 if (Session::$config['regenerate'] > 0 AND ($_SESSION['total_hits'] % Session::$config['regenerate']) === 0)
70 // Regenerate session id and update session cookie
75 // Always update session cookie to keep the session alive
76 cookie::set(Session::$config['name'], $_SESSION['session_id'], Session::$config['expiration']);
79 // Close the session just before sending the headers, so that
80 // the session cookie(s) can be written.
81 Event::add('system.send_headers', array($this, 'write_close'));
83 // Make sure that sessions are closed before exiting
84 register_shutdown_function(array($this, 'write_close'));
87 Session::$instance = $this;
90 Kohana::log('debug', 'Session Library initialized');
100 return $_SESSION['session_id'];
104 * Create a new session.
106 * @param array variables to set after creation
109 public function create($vars = NULL)
111 // Destroy any current sessions
114 if (Session::$config['driver'] !== 'native')
117 $driver = 'Session_'.ucfirst(Session::$config['driver']).'_Driver';
120 if ( ! Kohana::auto_load($driver))
121 throw new Kohana_Exception('core.driver_not_found', Session::$config['driver'], get_class($this));
123 // Initialize the driver
124 Session::$driver = new $driver();
126 // Validate the driver
127 if ( ! (Session::$driver instanceof Session_Driver))
128 throw new Kohana_Exception('core.driver_implements', Session::$config['driver'], get_class($this), 'Session_Driver');
130 // Register non-native driver as the session handler
131 session_set_save_handler
133 array(Session::$driver, 'open'),
134 array(Session::$driver, 'close'),
135 array(Session::$driver, 'read'),
136 array(Session::$driver, 'write'),
137 array(Session::$driver, 'destroy'),
138 array(Session::$driver, 'gc')
142 // Validate the session name
143 if ( ! preg_match('~^(?=.*[a-z])[a-z0-9_]++$~iD', Session::$config['name']))
144 throw new Kohana_Exception('session.invalid_session_name', Session::$config['name']);
146 // Name the session, this will also be the name of the cookie
147 session_name(Session::$config['name']);
149 // Set the session cookie parameters
150 session_set_cookie_params
152 Session::$config['expiration'],
153 Kohana::config('cookie.path'),
154 Kohana::config('cookie.domain'),
155 Kohana::config('cookie.secure'),
156 Kohana::config('cookie.httponly')
159 // Start the session!
162 // Put session_id in the session variable
163 $_SESSION['session_id'] = session_id();
166 if ( ! isset($_SESSION['_kf_flash_']))
168 $_SESSION['total_hits'] = 0;
169 $_SESSION['_kf_flash_'] = array();
171 $_SESSION['user_agent'] = Kohana::$user_agent;
172 $_SESSION['ip_address'] = $this->input->ip_address();
175 // Set up flash variables
176 Session::$flash =& $_SESSION['_kf_flash_'];
178 // Increase total hits
179 $_SESSION['total_hits'] += 1;
181 // Validate data only on hits after one
182 if ($_SESSION['total_hits'] > 1)
184 // Validate the session
185 foreach (Session::$config['validate'] as $valid)
189 // Check user agent for consistency
191 if ($_SESSION[$valid] !== Kohana::$user_agent)
192 return $this->create();
195 // Check ip address for consistency
197 if ($_SESSION[$valid] !== $this->input->$valid())
198 return $this->create();
201 // Check expiration time to prevent users from manually modifying it
203 if (time() - $_SESSION['last_activity'] > ini_get('session.gc_maxlifetime'))
204 return $this->create();
211 $this->expire_flash();
213 // Update last activity
214 $_SESSION['last_activity'] = time();
221 * Regenerates the global session id.
225 public function regenerate()
227 if (Session::$config['driver'] === 'native')
229 // Generate a new session id
230 // Note: also sets a new session cookie with the updated id
231 session_regenerate_id(TRUE);
233 // Update session with new id
234 $_SESSION['session_id'] = session_id();
238 // Pass the regenerating off to the driver in case it wants to do anything special
239 $_SESSION['session_id'] = Session::$driver->regenerate();
242 // Get the session name
243 $name = session_name();
245 if (isset($_COOKIE[$name]))
247 // Change the cookie value to match the new session id to prevent "lag"
248 $_COOKIE[$name] = $_SESSION['session_id'];
253 * Destroys the current session.
257 public function destroy()
259 if (session_id() !== '')
261 // Get the session name
262 $name = session_name();
264 // Destroy the session
267 // Re-initialize the array
270 // Delete the session cookie
271 cookie::delete($name);
276 * Runs the system.session_write event, then calls session_write_close.
280 public function write_close()
288 // Run the events that depend on the session being open
289 Event::run('system.session_write');
292 $this->expire_flash();
295 session_write_close();
300 * Set a session variable.
302 * @param string|array key, or array of values
303 * @param mixed value (if keys is not an array)
306 public function set($keys, $val = FALSE)
311 if ( ! is_array($keys))
313 $keys = array($keys => $val);
316 foreach ($keys as $key => $val)
318 if (isset(Session::$protect[$key]))
322 $_SESSION[$key] = $val;
327 * Set a flash variable.
329 * @param string|array key, or array of values
330 * @param mixed value (if keys is not an array)
333 public function set_flash($keys, $val = FALSE)
338 if ( ! is_array($keys))
340 $keys = array($keys => $val);
343 foreach ($keys as $key => $val)
348 Session::$flash[$key] = 'new';
349 Session::set($key, $val);
354 * Freshen one, multiple or all flash variables.
356 * @param string variable key(s)
359 public function keep_flash($keys = NULL)
361 $keys = ($keys === NULL) ? array_keys(Session::$flash) : func_get_args();
363 foreach ($keys as $key)
365 if (isset(Session::$flash[$key]))
367 Session::$flash[$key] = 'new';
373 * Expires old flash data and removes it from the session.
377 public function expire_flash()
381 // Method can only be run once
385 if ( ! empty(Session::$flash))
387 foreach (Session::$flash as $key => $state)
389 if ($state === 'old')
392 unset(Session::$flash[$key], $_SESSION[$key]);
397 Session::$flash[$key] = 'old';
402 // Method has been run
407 * Get a variable. Access to sub-arrays is supported with key.subkey.
409 * @param string variable key
410 * @param mixed default value returned if variable does not exist
411 * @return mixed Variable data if key specified, otherwise array containing all session data.
413 public function get($key = FALSE, $default = FALSE)
418 $result = isset($_SESSION[$key]) ? $_SESSION[$key] : Kohana::key_string($_SESSION, $key);
420 return ($result === NULL) ? $default : $result;
424 * Get a variable, and delete it.
426 * @param string variable key
427 * @param mixed default value returned if variable does not exist
430 public function get_once($key, $default = FALSE)
432 $return = Session::get($key, $default);
433 Session::delete($key);
439 * Delete one or more variables.
441 * @param string variable key(s)
444 public function delete($keys)
446 $args = func_get_args();
448 foreach ($args as $key)
450 if (isset(Session::$protect[$key]))
454 unset($_SESSION[$key]);
458 } // End Session Class