Avail feature updated
[ninja.git] / system / libraries / Session.php
blob2a96d699c4c56241809b940eeaa091c10a276a13
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3 * Session library.
5 * $Id: Session.php 3917 2009-01-21 03:06:22Z zombor $
7 * @package Core
8 * @author Kohana Team
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
12 class Session {
14 // Session singleton
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;
24 // Flash variables
25 protected static $flash;
27 // Input library
28 protected $input;
30 /**
31 * Singleton instance of Session.
33 public static function instance()
35 if (self::$instance == NULL)
37 // Create a new instance
38 new Session;
41 return self::$instance;
44 /**
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)
54 // Load config
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
66 $this->create();
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'));
75 // Singleton instance
76 self::$instance = $this;
80 /**
81 * Get the session id.
83 * @return string
85 public function id()
87 return $_SESSION['session_id'];
90 /**
91 * Create a new session.
93 * @param array variables to set after creation
94 * @return void
96 public function create($vars = NULL)
98 // Destroy any current sessions
99 $this->destroy();
101 if (self::$config['driver'] !== 'native')
103 // Set driver name
104 $driver = 'Session_'.ucfirst(self::$config['driver']).'_Driver';
106 // Load the 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']) {
138 $secure = false;
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'),
147 $secure,
148 Kohana::config('cookie.httponly')
151 // Start the session!
152 session_start();
154 // Put session_id in the session variable
155 $_SESSION['session_id'] = session_id();
157 // Set defaults
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)
179 switch ($valid)
181 // Check user agent for consistency
182 case 'user_agent':
183 if ($_SESSION[$valid] !== Kohana::$user_agent)
184 return $this->create();
185 break;
187 // Check ip address for consistency
188 case 'ip_address':
189 if ($_SESSION[$valid] !== $this->input->$valid())
190 return $this->create();
191 break;
193 // Check expiration time to prevent users from manually modifying it
194 case 'expiration':
195 if (time() - $_SESSION['last_activity'] > ini_get('session.gc_maxlifetime'))
196 return $this->create();
197 break;
202 // Expire flash keys
203 $this->expire_flash();
205 // Update last activity
206 $_SESSION['last_activity'] = time();
208 // Set the new data
209 self::set($vars);
213 * Destroys the current session.
215 * @return void
217 public function destroy()
219 if (session_id() !== '')
221 // Get the session name
222 $name = session_name();
224 // Destroy the session
225 session_destroy();
227 // Re-initialize the array
228 $_SESSION = array();
230 // Delete the session cookie
231 cookie::delete($name);
236 * Runs the system.session_write event, then calls session_write_close.
238 * @return void
240 public function write_close()
242 static $run;
244 if ($run === NULL)
246 $run = TRUE;
248 // Run the events that depend on the session being open
249 Event::run('system.session_write');
251 // Expire flash keys
252 $this->expire_flash();
254 // Close the session
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)
264 * @return void
266 public function set($keys, $val = FALSE)
268 if (empty($keys))
269 return FALSE;
271 if ( ! is_array($keys))
273 $keys = array($keys => $val);
276 foreach ($keys as $key => $val)
278 if (isset(self::$protect[$key]))
279 continue;
281 // Set the 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)
291 * @return void
293 public function set_flash($keys, $val = FALSE)
295 if (empty($keys))
296 return FALSE;
298 if ( ! is_array($keys))
300 $keys = array($keys => $val);
303 foreach ($keys as $key => $val)
305 if ($key == FALSE)
306 continue;
308 self::$flash[$key] = 'new';
309 self::set($key, $val);
314 * Freshen one, multiple or all flash variables.
316 * @param string variable key(s)
317 * @return void
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.
335 * @return void
337 public function expire_flash()
339 static $run;
341 // Method can only be run once
342 if ($run === TRUE)
343 return;
345 if ( ! empty(self::$flash))
347 foreach (self::$flash as $key => $state)
349 if ($state === 'old')
351 // Flash has expired
352 unset(self::$flash[$key], $_SESSION[$key]);
354 else
356 // Flash will expire
357 self::$flash[$key] = 'old';
362 // Method has been run
363 $run = TRUE;
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)
375 if (empty($key))
376 return $_SESSION;
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
388 * @return mixed
390 public function get_once($key, $default = FALSE)
392 $return = self::get($key, $default);
393 self::delete($key);
395 return $return;
399 * Delete one or more variables.
401 * @param string variable key(s)
402 * @return void
404 public function delete($keys)
406 $args = func_get_args();
408 foreach ($args as $key)
410 if (isset(self::$protect[$key]))
411 continue;
413 // Unset the key
414 unset($_SESSION[$key]);
418 } // End Session Class