1 <?php
defined('SYSPATH') OR die('No direct access allowed.');
5 * $Id: Session.php 3917 2009-01-21 03:06:22Z zombor $
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
15 private 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 (self
::$instance == NULL)
37 // Create a new instance
41 return self
::$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 (self
::$instance === NULL)
55 self
::$config = Kohana
::config('session');
57 // Makes a mirrored array, eg: foo=foo
58 self
::$protect = array_combine(self
::$protect, self
::$protect);
60 // Configure garbage collection
61 ini_set('session.gc_probability', (int) self
::$config['gc_probability']);
62 ini_set('session.gc_divisor', 100);
63 ini_set('session.gc_maxlifetime', (self
::$config['expiration'] == 0) ?
86400 : self
::$config['expiration']);
65 // Create a new session
68 // Close the session just before sending the headers, so that
69 // the session cookie(s) can be written.
70 Event
::add('system.send_headers', array($this, 'write_close'));
72 // Make sure that sessions are closed before exiting
73 register_shutdown_function(array($this, 'write_close'));
76 self
::$instance = $this;
87 return $_SESSION['session_id'];
91 * Create a new session.
93 * @param array variables to set after creation
96 public function create($vars = NULL)
98 // Destroy any current sessions
101 if (self
::$config['driver'] !== 'native')
104 $driver = 'Session_'.ucfirst(self
::$config['driver']).'_Driver';
107 if ( ! Kohana
::auto_load($driver))
108 throw new Kohana_Exception('core.driver_not_found', self
::$config['driver'], get_class($this));
110 // Initialize the driver
111 self
::$driver = new $driver();
113 // Validate the driver
114 if ( ! (self
::$driver instanceof Session_Driver
))
115 throw new Kohana_Exception('core.driver_implements', self
::$config['driver'], get_class($this), 'Session_Driver');
117 // Register non-native driver as the session handler
118 session_set_save_handler
120 array(self
::$driver, 'open'),
121 array(self
::$driver, 'close'),
122 array(self
::$driver, 'read'),
123 array(self
::$driver, 'write'),
124 array(self
::$driver, 'destroy'),
125 array(self
::$driver, 'gc')
129 // Validate the session name
130 if ( ! preg_match('~^(?=.*[a-z])[a-z0-9_]++$~iD', self
::$config['name']))
131 throw new Kohana_Exception('session.invalid_session_name', self
::$config['name']);
133 // Name the session, this will also be the name of the cookie
134 session_name(self
::$config['name']);
136 $secure = Kohana
::config('cookie.secure');
137 if(!isset($_SERVER['HTTPS']) ||
!$_SERVER['HTTPS']) {
141 // Set the session cookie parameters
142 session_set_cookie_params
144 self
::$config['expiration'],
145 Kohana
::config('cookie.path'),
146 Kohana
::config('cookie.domain'),
148 Kohana
::config('cookie.httponly')
151 // Start the session!
154 // Put session_id in the session variable
155 $_SESSION['session_id'] = session_id();
158 if ( ! isset($_SESSION['_kf_flash_']))
160 $_SESSION['total_hits'] = 0;
161 $_SESSION['_kf_flash_'] = array();
163 $_SESSION['user_agent'] = Kohana
::$user_agent;
164 $_SESSION['ip_address'] = $this->input
->ip_address();
167 // Set up flash variables
168 self
::$flash =& $_SESSION['_kf_flash_'];
170 // Increase total hits
171 $_SESSION['total_hits'] +
= 1;
173 // Validate data only on hits after one
174 if ($_SESSION['total_hits'] > 1)
176 // Validate the session
177 foreach (self
::$config['validate'] as $valid)
181 // Check user agent for consistency
183 if ($_SESSION[$valid] !== Kohana
::$user_agent)
184 return $this->create();
187 // Check ip address for consistency
189 if ($_SESSION[$valid] !== $this->input
->$valid())
190 return $this->create();
193 // Check expiration time to prevent users from manually modifying it
195 if (time() - $_SESSION['last_activity'] > ini_get('session.gc_maxlifetime'))
196 return $this->create();
203 $this->expire_flash();
205 // Update last activity
206 $_SESSION['last_activity'] = time();
213 * Destroys the current session.
217 public function destroy()
219 if (session_id() !== '')
221 // Get the session name
222 $name = session_name();
224 // Destroy the session
227 // Re-initialize the array
230 // Delete the session cookie
231 cookie
::delete($name);
236 * Runs the system.session_write event, then calls session_write_close.
240 public function write_close()
248 // Run the events that depend on the session being open
249 Event
::run('system.session_write');
252 $this->expire_flash();
255 session_write_close();
260 * Set a session variable.
262 * @param string|array key, or array of values
263 * @param mixed value (if keys is not an array)
266 public function set($keys, $val = FALSE)
271 if ( ! is_array($keys))
273 $keys = array($keys => $val);
276 foreach ($keys as $key => $val)
278 if (isset(self
::$protect[$key]))
282 $_SESSION[$key] = $val;
287 * Set a flash variable.
289 * @param string|array key, or array of values
290 * @param mixed value (if keys is not an array)
293 public function set_flash($keys, $val = FALSE)
298 if ( ! is_array($keys))
300 $keys = array($keys => $val);
303 foreach ($keys as $key => $val)
308 self
::$flash[$key] = 'new';
309 self
::set($key, $val);
314 * Freshen one, multiple or all flash variables.
316 * @param string variable key(s)
319 public function keep_flash($keys = NULL)
321 $keys = ($keys === NULL) ?
array_keys(self
::$flash) : func_get_args();
323 foreach ($keys as $key)
325 if (isset(self
::$flash[$key]))
327 self
::$flash[$key] = 'new';
333 * Expires old flash data and removes it from the session.
337 public function expire_flash()
341 // Method can only be run once
345 if ( ! empty(self
::$flash))
347 foreach (self
::$flash as $key => $state)
349 if ($state === 'old')
352 unset(self
::$flash[$key], $_SESSION[$key]);
357 self
::$flash[$key] = 'old';
362 // Method has been run
367 * Get a variable. Access to sub-arrays is supported with key.subkey.
369 * @param string variable key
370 * @param mixed default value returned if variable does not exist
371 * @return mixed Variable data if key specified, otherwise array containing all session data.
373 public function get($key = FALSE, $default = FALSE)
378 $result = isset($_SESSION[$key]) ?
$_SESSION[$key] : Kohana
::key_string($_SESSION, $key);
380 return ($result === NULL) ?
$default : $result;
384 * Get a variable, and delete it.
386 * @param string variable key
387 * @param mixed default value returned if variable does not exist
390 public function get_once($key, $default = FALSE)
392 $return = self
::get($key, $default);
399 * Delete one or more variables.
401 * @param string variable key(s)
404 public function delete($keys)
406 $args = func_get_args();
408 foreach ($args as $key)
410 if (isset(self
::$protect[$key]))
414 unset($_SESSION[$key]);
418 } // End Session Class