blob: 9e762745f2e86062cd4167946a6e8c97b37a3849 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Darren Hillc4e266b2011-08-30 15:40:27 -04002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Andrey Andreev9ffcee62012-09-05 16:25:16 +03006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Andrey Andreev9ffcee62012-09-05 16:25:16 +03008 *
Andrey Andreevcce6bd12018-01-09 11:32:02 +02009 * Copyright (c) 2014 - 2018, British Columbia Institute of Technology
Andrey Andreev9ffcee62012-09-05 16:25:16 +030010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Darren Hillc4e266b2011-08-30 15:40:27 -040017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Andrey Andreevcce6bd12018-01-09 11:32:02 +020032 * @copyright Copyright (c) 2014 - 2018, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 2.0.0
Darren Hillc4e266b2011-08-30 15:40:27 -040036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Darren Hillc4e266b2011-08-30 15:40:27 -040039
Darren Hillc4e266b2011-08-30 15:40:27 -040040/**
Andrey Andreev9ffcee62012-09-05 16:25:16 +030041 * CodeIgniter Session Class
Darren Hillc4e266b2011-08-30 15:40:27 -040042 *
Darren Hillc4e266b2011-08-30 15:40:27 -040043 * @package CodeIgniter
44 * @subpackage Libraries
45 * @category Sessions
Andrey Andreev47a47fb2014-05-31 16:08:30 +030046 * @author Andrey Andreev
Andrey Andreevbd202c92016-01-11 12:50:18 +020047 * @link https://codeigniter.com/user_guide/libraries/sessions.html
Darren Hillc4e266b2011-08-30 15:40:27 -040048 */
Andrey Andreev47a47fb2014-05-31 16:08:30 +030049class CI_Session {
Andrey Andreev9ffcee62012-09-05 16:25:16 +030050
Andrey Andreevb4b215e2015-01-19 11:59:11 +020051 /**
52 * Userdata array
53 *
54 * Just a reference to $_SESSION, for BC purposes.
55 */
56 public $userdata;
57
Andrey Andreev47a47fb2014-05-31 16:08:30 +030058 protected $_driver = 'files';
Andrey Andreevdfb39be2014-10-06 01:50:14 +030059 protected $_config;
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +030060 protected $_sid_regexp;
Darren Hillc4e266b2011-08-30 15:40:27 -040061
Andrey Andreev0fa95bd2012-11-01 23:33:14 +020062 // ------------------------------------------------------------------------
63
Darren Hillc4e266b2011-08-30 15:40:27 -040064 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +030065 * Class constructor
Darren Hillc4e266b2011-08-30 15:40:27 -040066 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +030067 * @param array $params Configuration parameters
Andrey Andreev2e3e2302012-10-09 15:52:34 +030068 * @return void
Darren Hillc4e266b2011-08-30 15:40:27 -040069 */
70 public function __construct(array $params = array())
71 {
Andrey Andreev2e3e2302012-10-09 15:52:34 +030072 // No sessions under CLI
Andrey Andreevf964b162013-11-12 17:04:55 +020073 if (is_cli())
Andrey Andreev2e3e2302012-10-09 15:52:34 +030074 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +030075 log_message('debug', 'Session: Initialization under CLI aborted.');
76 return;
77 }
78 elseif ((bool) ini_get('session.auto_start'))
79 {
80 log_message('error', 'Session: session.auto_start is enabled in php.ini. Aborting.');
81 return;
82 }
83 elseif ( ! empty($params['driver']))
84 {
85 $this->_driver = $params['driver'];
86 unset($params['driver']);
87 }
Andrey Andreevdfb39be2014-10-06 01:50:14 +030088 elseif ($driver = config_item('sess_driver'))
Andrey Andreev34b1ef52014-05-31 21:23:41 +030089 {
90 $this->_driver = $driver;
91 }
Andrey Andreevac4f4722014-06-02 11:16:32 +030092 // Note: BC workaround
93 elseif (config_item('sess_use_database'))
94 {
Andrey Andreev85dfc2a2016-04-01 22:54:15 +030095 log_message('debug', 'Session: "sess_driver" is empty; using BC fallback to "sess_use_database".');
Andrey Andreevac4f4722014-06-02 11:16:32 +030096 $this->_driver = 'database';
97 }
Andrey Andreev47a47fb2014-05-31 16:08:30 +030098
Andrey Andreev34b92c62015-03-12 12:42:00 +020099 $class = $this->_ci_load_classes($this->_driver);
Andrey Andreev2e3e2302012-10-09 15:52:34 +0300100
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300101 // Configuration ...
102 $this->_configure($params);
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300103 $this->_config['_sid_regexp'] = $this->_sid_regexp;
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300104
105 $class = new $class($this->_config);
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300106 if ($class instanceof SessionHandlerInterface)
Darren Hillc4e266b2011-08-30 15:40:27 -0400107 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300108 if (is_php('5.4'))
Darren Hillc4e266b2011-08-30 15:40:27 -0400109 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300110 session_set_save_handler($class, TRUE);
Darren Hillc4e266b2011-08-30 15:40:27 -0400111 }
112 else
113 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300114 session_set_save_handler(
115 array($class, 'open'),
116 array($class, 'close'),
117 array($class, 'read'),
118 array($class, 'write'),
119 array($class, 'destroy'),
120 array($class, 'gc')
121 );
122
123 register_shutdown_function('session_write_close');
124 }
125 }
126 else
127 {
128 log_message('error', "Session: Driver '".$this->_driver."' doesn't implement SessionHandlerInterface. Aborting.");
129 return;
130 }
131
Andrey Andreev562e39b2014-11-12 15:38:58 +0200132 // Sanitize the cookie, because apparently PHP doesn't do that for userspace handlers
133 if (isset($_COOKIE[$this->_config['cookie_name']])
134 && (
135 ! is_string($_COOKIE[$this->_config['cookie_name']])
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300136 OR ! preg_match('#\A'.$this->_sid_regexp.'\z#', $_COOKIE[$this->_config['cookie_name']])
Andrey Andreev562e39b2014-11-12 15:38:58 +0200137 )
138 )
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300139 {
Andrey Andreev562e39b2014-11-12 15:38:58 +0200140 unset($_COOKIE[$this->_config['cookie_name']]);
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300141 }
142
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300143 session_start();
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300144
Andrey Andreevff37ffe2014-11-04 12:28:57 +0200145 // Is session ID auto-regeneration configured? (ignoring ajax requests)
Andrey Andreev395f9282015-02-05 13:29:56 +0200146 if ((empty($_SERVER['HTTP_X_REQUESTED_WITH']) OR strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest')
Andrey Andreevde5c2462014-11-04 12:31:03 +0200147 && ($regenerate_time = config_item('sess_time_to_update')) > 0
Andrey Andreevff37ffe2014-11-04 12:28:57 +0200148 )
Andrey Andreev8e60b9a2014-11-04 11:08:06 +0200149 {
150 if ( ! isset($_SESSION['__ci_last_regenerate']))
151 {
152 $_SESSION['__ci_last_regenerate'] = time();
153 }
154 elseif ($_SESSION['__ci_last_regenerate'] < (time() - $regenerate_time))
155 {
Andrey Andreev789b1fe2015-02-07 19:30:30 +0200156 $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
Andrey Andreev8e60b9a2014-11-04 11:08:06 +0200157 }
158 }
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300159 // Another work-around ... PHP doesn't seem to send the session cookie
160 // unless it is being currently created or regenerated
Andrey Andreev8e60b9a2014-11-04 11:08:06 +0200161 elseif (isset($_COOKIE[$this->_config['cookie_name']]) && $_COOKIE[$this->_config['cookie_name']] === session_id())
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300162 {
163 setcookie(
164 $this->_config['cookie_name'],
165 session_id(),
166 (empty($this->_config['cookie_lifetime']) ? 0 : time() + $this->_config['cookie_lifetime']),
167 $this->_config['cookie_path'],
168 $this->_config['cookie_domain'],
169 $this->_config['cookie_secure'],
170 TRUE
171 );
172 }
173
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300174 $this->_ci_init_vars();
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300175
Andrey Andreev90726b82015-01-20 12:39:22 +0200176 log_message('info', "Session: Class initialized using '".$this->_driver."' driver.");
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300177 }
178
179 // ------------------------------------------------------------------------
180
Andrey Andreev10411fc2015-01-19 13:54:53 +0200181 /**
182 * CI Load Classes
183 *
184 * An internal method to load all possible dependency and extension
185 * classes. It kind of emulates the CI_Driver library, but is
186 * self-sufficient.
187 *
188 * @param string $driver Driver name
189 * @return string Driver class name
190 */
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300191 protected function _ci_load_classes($driver)
192 {
193 // PHP 5.4 compatibility
194 interface_exists('SessionHandlerInterface', FALSE) OR require_once(BASEPATH.'libraries/Session/SessionHandlerInterface.php');
195
196 $prefix = config_item('subclass_prefix');
197
198 if ( ! class_exists('CI_Session_driver', FALSE))
199 {
Andrey Andreeve86603f2014-06-11 14:03:36 +0300200 require_once(
201 file_exists(APPPATH.'libraries/Session/Session_driver.php')
202 ? APPPATH.'libraries/Session/Session_driver.php'
203 : BASEPATH.'libraries/Session/Session_driver.php'
204 );
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300205
206 if (file_exists($file_path = APPPATH.'libraries/Session/'.$prefix.'Session_driver.php'))
207 {
208 require_once($file_path);
209 }
210 }
211
212 $class = 'Session_'.$driver.'_driver';
Andrey Andreevcd94dd72014-12-09 17:38:56 +0200213
214 // Allow custom drivers without the CI_ or MY_ prefix
215 if ( ! class_exists($class, FALSE) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$class.'.php'))
216 {
217 require_once($file_path);
218 if (class_exists($class, FALSE))
219 {
220 return $class;
221 }
222 }
223
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300224 if ( ! class_exists('CI_'.$class, FALSE))
225 {
226 if (file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$class.'.php') OR file_exists($file_path = BASEPATH.'libraries/Session/drivers/'.$class.'.php'))
227 {
228 require_once($file_path);
229 }
230
Andrey Andreevcd94dd72014-12-09 17:38:56 +0200231 if ( ! class_exists('CI_'.$class, FALSE) && ! class_exists($class, FALSE))
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300232 {
Andrey Andreev1d195202015-03-13 11:25:29 +0200233 throw new UnexpectedValueException("Session: Configured driver '".$driver."' was not found. Aborting.");
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300234 }
235 }
236
Andrey Andreev738b9e32016-02-24 12:14:10 +0200237 if ( ! class_exists($prefix.$class, FALSE) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$prefix.$class.'.php'))
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300238 {
239 require_once($file_path);
240 if (class_exists($prefix.$class, FALSE))
241 {
242 return $prefix.$class;
243 }
Andrey Andreevfbe4d792017-12-27 19:49:03 +0200244
245 log_message('debug', 'Session: '.$prefix.$class.".php found but it doesn't declare class ".$prefix.$class.'.');
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300246 }
247
248 return 'CI_'.$class;
249 }
250
251 // ------------------------------------------------------------------------
252
253 /**
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300254 * Configuration
255 *
256 * Handle input parameters and configuration defaults
257 *
258 * @param array &$params Input parameters
259 * @return void
260 */
261 protected function _configure(&$params)
262 {
263 $expiration = config_item('sess_expiration');
264
265 if (isset($params['cookie_lifetime']))
266 {
267 $params['cookie_lifetime'] = (int) $params['cookie_lifetime'];
268 }
269 else
270 {
271 $params['cookie_lifetime'] = ( ! isset($expiration) && config_item('sess_expire_on_close'))
272 ? 0 : (int) $expiration;
273 }
274
275 isset($params['cookie_name']) OR $params['cookie_name'] = config_item('sess_cookie_name');
276 if (empty($params['cookie_name']))
277 {
278 $params['cookie_name'] = ini_get('session.name');
279 }
280 else
281 {
282 ini_set('session.name', $params['cookie_name']);
283 }
284
285 isset($params['cookie_path']) OR $params['cookie_path'] = config_item('cookie_path');
Andrey Andreev41b546d2014-10-06 03:01:22 +0300286 isset($params['cookie_domain']) OR $params['cookie_domain'] = config_item('cookie_domain');
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300287 isset($params['cookie_secure']) OR $params['cookie_secure'] = (bool) config_item('cookie_secure');
288
289 session_set_cookie_params(
290 $params['cookie_lifetime'],
291 $params['cookie_path'],
292 $params['cookie_domain'],
293 $params['cookie_secure'],
294 TRUE // HttpOnly; Yes, this is intentional and not configurable for security reasons
295 );
296
297 if (empty($expiration))
298 {
299 $params['expiration'] = (int) ini_get('session.gc_maxlifetime');
300 }
301 else
302 {
303 $params['expiration'] = (int) $expiration;
304 ini_set('session.gc_maxlifetime', $expiration);
305 }
306
307 $params['match_ip'] = (bool) (isset($params['match_ip']) ? $params['match_ip'] : config_item('sess_match_ip'));
308
309 isset($params['save_path']) OR $params['save_path'] = config_item('sess_save_path');
310
311 $this->_config = $params;
312
313 // Security is king
Andrey Andreevc02952d2015-02-13 13:04:38 +0200314 ini_set('session.use_trans_sid', 0);
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300315 ini_set('session.use_strict_mode', 1);
316 ini_set('session.use_cookies', 1);
317 ini_set('session.use_only_cookies', 1);
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300318
Andrey Andreev2f760872016-10-27 16:39:12 +0300319 $this->_configure_sid_length();
320 }
321
322 // ------------------------------------------------------------------------
323
324 /**
325 * Configure session ID length
326 *
327 * To make life easier, we used to force SHA-1 and 4 bits per
328 * character on everyone. And of course, someone was unhappy.
329 *
330 * Then PHP 7.1 broke backwards-compatibility because ext/session
331 * is such a mess that nobody wants to touch it with a pole stick,
332 * and the one guy who does, nobody has the energy to argue with.
333 *
334 * So we were forced to make changes, and OF COURSE something was
335 * going to break and now we have this pile of shit. -- Narf
336 *
337 * @return void
338 */
339 protected function _configure_sid_length()
340 {
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300341 if (PHP_VERSION_ID < 70100)
342 {
Andrey Andreev2f760872016-10-27 16:39:12 +0300343 $hash_function = ini_get('session.hash_function');
344 if (ctype_digit($hash_function))
345 {
346 if ($hash_function !== '1')
347 {
348 ini_set('session.hash_function', 1);
Andrey Andreev2f760872016-10-27 16:39:12 +0300349 }
Andrey Andreevdbc025b2016-10-27 17:37:25 +0300350
351 $bits = 160;
Andrey Andreev2f760872016-10-27 16:39:12 +0300352 }
353 elseif ( ! in_array($hash_function, hash_algos(), TRUE))
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300354 {
355 ini_set('session.hash_function', 1);
Andrey Andreev2f760872016-10-27 16:39:12 +0300356 $bits = 160;
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300357 }
Andrey Andreev2f760872016-10-27 16:39:12 +0300358 elseif (($bits = strlen(hash($hash_function, 'dummy', false)) * 4) < 160)
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300359 {
Andrey Andreev2f760872016-10-27 16:39:12 +0300360 ini_set('session.hash_function', 1);
361 $bits = 160;
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300362 }
Andrey Andreev2f760872016-10-27 16:39:12 +0300363
364 $bits_per_character = (int) ini_get('session.hash_bits_per_character');
Andrey Andreevdbc025b2016-10-27 17:37:25 +0300365 $sid_length = (int) ceil($bits / $bits_per_character);
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300366 }
Andrey Andreev2f760872016-10-27 16:39:12 +0300367 else
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300368 {
Andrey Andreev2f760872016-10-27 16:39:12 +0300369 $bits_per_character = (int) ini_get('session.sid_bits_per_character');
370 $sid_length = (int) ini_get('session.sid_length');
371 if (($bits = $sid_length * $bits_per_character) < 160)
372 {
373 // Add as many more characters as necessary to reach at least 160 bits
374 $sid_length += (int) ceil((160 % $bits) / $bits_per_character);
375 ini_set('session.sid_length', $sid_length);
376 }
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300377 }
378
Andrey Andreev2f760872016-10-27 16:39:12 +0300379 // Yes, 4,5,6 are the only known possible values as of 2016-10-27
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300380 switch ($bits_per_character)
381 {
382 case 4:
Andrey Andreev2f760872016-10-27 16:39:12 +0300383 $this->_sid_regexp = '[0-9a-f]';
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300384 break;
385 case 5:
Andrey Andreev2f760872016-10-27 16:39:12 +0300386 $this->_sid_regexp = '[0-9a-v]';
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300387 break;
388 case 6:
Andrey Andreev2f760872016-10-27 16:39:12 +0300389 $this->_sid_regexp = '[0-9a-zA-Z,-]';
Andrey Andreev6c6ee1a2016-10-22 16:33:06 +0300390 break;
391 }
Andrey Andreev2f760872016-10-27 16:39:12 +0300392
393 $this->_sid_regexp .= '{'.$sid_length.'}';
Andrey Andreevdfb39be2014-10-06 01:50:14 +0300394 }
395
396 // ------------------------------------------------------------------------
397
398 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300399 * Handle temporary variables
400 *
401 * Clears old "flash" data, marks the new one for deletion and handles
402 * "temp" data deletion.
403 *
404 * @return void
405 */
406 protected function _ci_init_vars()
407 {
408 if ( ! empty($_SESSION['__ci_vars']))
409 {
410 $current_time = time();
411
412 foreach ($_SESSION['__ci_vars'] as $key => &$value)
413 {
414 if ($value === 'new')
415 {
416 $_SESSION['__ci_vars'][$key] = 'old';
417 }
418 // Hacky, but 'old' will (implicitly) always be less than time() ;)
419 // DO NOT move this above the 'new' check!
420 elseif ($value < $current_time)
421 {
422 unset($_SESSION[$key], $_SESSION['__ci_vars'][$key]);
423 }
424 }
425
426 if (empty($_SESSION['__ci_vars']))
427 {
428 unset($_SESSION['__ci_vars']);
Darren Hillc4e266b2011-08-30 15:40:27 -0400429 }
430 }
Andrey Andreevb4b215e2015-01-19 11:59:11 +0200431
432 $this->userdata =& $_SESSION;
Darren Hillc4e266b2011-08-30 15:40:27 -0400433 }
434
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300435 // ------------------------------------------------------------------------
436
Darren Hillc4e266b2011-08-30 15:40:27 -0400437 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300438 * Mark as flash
439 *
440 * @param mixed $key Session data key(s)
441 * @return bool
442 */
443 public function mark_as_flash($key)
444 {
445 if (is_array($key))
446 {
447 for ($i = 0, $c = count($key); $i < $c; $i++)
448 {
449 if ( ! isset($_SESSION[$key[$i]]))
450 {
451 return FALSE;
452 }
453 }
454
455 $new = array_fill_keys($key, 'new');
456
457 $_SESSION['__ci_vars'] = isset($_SESSION['__ci_vars'])
458 ? array_merge($_SESSION['__ci_vars'], $new)
459 : $new;
460
461 return TRUE;
462 }
463
464 if ( ! isset($_SESSION[$key]))
465 {
466 return FALSE;
467 }
468
469 $_SESSION['__ci_vars'][$key] = 'new';
470 return TRUE;
471 }
472
473 // ------------------------------------------------------------------------
474
475 /**
476 * Get flash keys
477 *
478 * @return array
479 */
480 public function get_flash_keys()
481 {
482 if ( ! isset($_SESSION['__ci_vars']))
483 {
484 return array();
485 }
486
487 $keys = array();
488 foreach (array_keys($_SESSION['__ci_vars']) as $key)
489 {
490 is_int($_SESSION['__ci_vars'][$key]) OR $keys[] = $key;
491 }
492
493 return $keys;
494 }
495
496 // ------------------------------------------------------------------------
497
498 /**
499 * Unmark flash
500 *
501 * @param mixed $key Session data key(s)
502 * @return void
503 */
504 public function unmark_flash($key)
505 {
506 if (empty($_SESSION['__ci_vars']))
507 {
508 return;
509 }
510
511 is_array($key) OR $key = array($key);
512
513 foreach ($key as $k)
514 {
515 if (isset($_SESSION['__ci_vars'][$k]) && ! is_int($_SESSION['__ci_vars'][$k]))
516 {
517 unset($_SESSION['__ci_vars'][$k]);
518 }
519 }
520
521 if (empty($_SESSION['__ci_vars']))
522 {
523 unset($_SESSION['__ci_vars']);
524 }
525 }
526
527 // ------------------------------------------------------------------------
528
529 /**
530 * Mark as temp
531 *
532 * @param mixed $key Session data key(s)
533 * @param int $ttl Time-to-live in seconds
534 * @return bool
535 */
536 public function mark_as_temp($key, $ttl = 300)
537 {
538 $ttl += time();
539
540 if (is_array($key))
541 {
542 $temp = array();
543
544 foreach ($key as $k => $v)
545 {
546 // Do we have a key => ttl pair, or just a key?
547 if (is_int($k))
548 {
549 $k = $v;
550 $v = $ttl;
551 }
552 else
553 {
554 $v += time();
555 }
556
557 if ( ! isset($_SESSION[$k]))
558 {
559 return FALSE;
560 }
561
Andrey Andreev43df7bd2015-02-02 23:22:29 +0200562 $temp[$k] = $v;
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300563 }
564
565 $_SESSION['__ci_vars'] = isset($_SESSION['__ci_vars'])
566 ? array_merge($_SESSION['__ci_vars'], $temp)
567 : $temp;
568
569 return TRUE;
570 }
571
572 if ( ! isset($_SESSION[$key]))
573 {
574 return FALSE;
575 }
576
577 $_SESSION['__ci_vars'][$key] = $ttl;
578 return TRUE;
579 }
580
581 // ------------------------------------------------------------------------
582
583 /**
584 * Get temp keys
585 *
586 * @return array
587 */
588 public function get_temp_keys()
589 {
590 if ( ! isset($_SESSION['__ci_vars']))
591 {
592 return array();
593 }
594
595 $keys = array();
596 foreach (array_keys($_SESSION['__ci_vars']) as $key)
597 {
598 is_int($_SESSION['__ci_vars'][$key]) && $keys[] = $key;
599 }
600
601 return $keys;
602 }
603
604 // ------------------------------------------------------------------------
605
606 /**
607 * Unmark flash
608 *
609 * @param mixed $key Session data key(s)
610 * @return void
611 */
612 public function unmark_temp($key)
613 {
614 if (empty($_SESSION['__ci_vars']))
615 {
616 return;
617 }
618
619 is_array($key) OR $key = array($key);
620
621 foreach ($key as $k)
622 {
623 if (isset($_SESSION['__ci_vars'][$k]) && is_int($_SESSION['__ci_vars'][$k]))
624 {
625 unset($_SESSION['__ci_vars'][$k]);
626 }
627 }
628
629 if (empty($_SESSION['__ci_vars']))
630 {
631 unset($_SESSION['__ci_vars']);
632 }
633 }
634
635 // ------------------------------------------------------------------------
636
637 /**
638 * __get()
639 *
640 * @param string $key 'session_id' or a session data key
641 * @return mixed
642 */
643 public function __get($key)
644 {
645 // Note: Keep this order the same, just in case somebody wants to
646 // use 'session_id' as a session data key, for whatever reason
647 if (isset($_SESSION[$key]))
648 {
649 return $_SESSION[$key];
650 }
651 elseif ($key === 'session_id')
652 {
653 return session_id();
654 }
655
656 return NULL;
657 }
658
659 // ------------------------------------------------------------------------
660
661 /**
Andrey Andreev2c10f602016-03-15 14:39:02 +0200662 * __isset()
663 *
664 * @param string $key 'session_id' or a session data key
665 * @return bool
666 */
667 public function __isset($key)
668 {
669 if ($key === 'session_id')
670 {
671 return (session_status() === PHP_SESSION_ACTIVE);
672 }
673
674 return isset($_SESSION[$key]);
675 }
676
677 // ------------------------------------------------------------------------
678
679 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300680 * __set()
681 *
682 * @param string $key Session data key
683 * @param mixed $value Session data value
684 * @return void
685 */
686 public function __set($key, $value)
687 {
688 $_SESSION[$key] = $value;
689 }
690
691 // ------------------------------------------------------------------------
692
693 /**
694 * Session destroy
695 *
696 * Legacy CI_Session compatibility method
Darren Hillc4e266b2011-08-30 15:40:27 -0400697 *
Darren Hill5073a372011-08-31 13:54:19 -0400698 * @return void
Darren Hillc4e266b2011-08-30 15:40:27 -0400699 */
700 public function sess_destroy()
701 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300702 session_destroy();
Darren Hillc4e266b2011-08-30 15:40:27 -0400703 }
704
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300705 // ------------------------------------------------------------------------
706
Darren Hillc4e266b2011-08-30 15:40:27 -0400707 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300708 * Session regenerate
Darren Hillc4e266b2011-08-30 15:40:27 -0400709 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300710 * Legacy CI_Session compatibility method
711 *
712 * @param bool $destroy Destroy old session data flag
Darren Hill5073a372011-08-31 13:54:19 -0400713 * @return void
Darren Hillc4e266b2011-08-30 15:40:27 -0400714 */
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300715 public function sess_regenerate($destroy = FALSE)
Darren Hillc4e266b2011-08-30 15:40:27 -0400716 {
Andrey Andreev8e60b9a2014-11-04 11:08:06 +0200717 $_SESSION['__ci_last_regenerate'] = time();
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300718 session_regenerate_id($destroy);
Darren Hillc4e266b2011-08-30 15:40:27 -0400719 }
720
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300721 // ------------------------------------------------------------------------
722
Darren Hillc4e266b2011-08-30 15:40:27 -0400723 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300724 * Get userdata reference
Darren Hillc4e266b2011-08-30 15:40:27 -0400725 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300726 * Legacy CI_Session compatibility method
727 *
728 * @returns array
Darren Hillc4e266b2011-08-30 15:40:27 -0400729 */
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300730 public function &get_userdata()
Darren Hillc4e266b2011-08-30 15:40:27 -0400731 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300732 return $_SESSION;
733 }
734
735 // ------------------------------------------------------------------------
736
737 /**
738 * Userdata (fetch)
739 *
740 * Legacy CI_Session compatibility method
741 *
742 * @param string $key Session data key
743 * @return mixed Session data value or NULL if not found
744 */
745 public function userdata($key = NULL)
746 {
747 if (isset($key))
Andrey Andreevecc260e2014-01-24 14:20:13 +0200748 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300749 return isset($_SESSION[$key]) ? $_SESSION[$key] : NULL;
750 }
751 elseif (empty($_SESSION))
752 {
753 return array();
Andrey Andreevecc260e2014-01-24 14:20:13 +0200754 }
755
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300756 $userdata = array();
757 $_exclude = array_merge(
Andrey Andreevef417862014-06-04 21:28:13 +0300758 array('__ci_vars'),
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300759 $this->get_flash_keys(),
760 $this->get_temp_keys()
761 );
Darren Hillc4e266b2011-08-30 15:40:27 -0400762
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300763 foreach (array_keys($_SESSION) as $key)
Darren Hillc4e266b2011-08-30 15:40:27 -0400764 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300765 if ( ! in_array($key, $_exclude, TRUE))
Darren Hillc4e266b2011-08-30 15:40:27 -0400766 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300767 $userdata[$key] = $_SESSION[$key];
Darren Hillc4e266b2011-08-30 15:40:27 -0400768 }
769 }
770
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300771 return $userdata;
Darren Hillc4e266b2011-08-30 15:40:27 -0400772 }
773
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300774 // ------------------------------------------------------------------------
775
Darren Hillc4e266b2011-08-30 15:40:27 -0400776 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300777 * Set userdata
Darren Hillc4e266b2011-08-30 15:40:27 -0400778 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300779 * Legacy CI_Session compatibility method
780 *
781 * @param mixed $data Session data key or an associative array
782 * @param mixed $value Value to store
Darren Hill5073a372011-08-31 13:54:19 -0400783 * @return void
Darren Hillc4e266b2011-08-30 15:40:27 -0400784 */
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300785 public function set_userdata($data, $value = NULL)
Darren Hillc4e266b2011-08-30 15:40:27 -0400786 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300787 if (is_array($data))
Darren Hillc4e266b2011-08-30 15:40:27 -0400788 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300789 foreach ($data as $key => &$value)
Darren Hillc4e266b2011-08-30 15:40:27 -0400790 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300791 $_SESSION[$key] = $value;
Johnathan Croom8d8543d2012-11-25 10:36:57 -0700792 }
793
794 return;
Johnathan Croom4beca5c2012-11-23 18:32:46 -0700795 }
Darren Hillc4e266b2011-08-30 15:40:27 -0400796
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300797 $_SESSION[$data] = $value;
Darren Hillc4e266b2011-08-30 15:40:27 -0400798 }
799
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300800 // ------------------------------------------------------------------------
801
Darren Hillc4e266b2011-08-30 15:40:27 -0400802 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300803 * Unset userdata
Darren Hillc4e266b2011-08-30 15:40:27 -0400804 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300805 * Legacy CI_Session compatibility method
806 *
Andrey Andreeve13fa9f2016-05-20 17:30:07 +0300807 * @param mixed $key Session data key(s)
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300808 * @return void
809 */
810 public function unset_userdata($key)
811 {
812 if (is_array($key))
813 {
814 foreach ($key as $k)
815 {
Andrey Andreevd069b9b2014-09-16 10:18:16 +0300816 unset($_SESSION[$k]);
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300817 }
818
819 return;
820 }
821
822 unset($_SESSION[$key]);
823 }
824
825 // ------------------------------------------------------------------------
826
827 /**
828 * All userdata (fetch)
829 *
830 * Legacy CI_Session compatibility method
831 *
832 * @return array $_SESSION, excluding flash data items
833 */
834 public function all_userdata()
835 {
836 return $this->userdata();
837 }
838
839 // ------------------------------------------------------------------------
840
841 /**
842 * Has userdata
843 *
844 * Legacy CI_Session compatibility method
845 *
846 * @param string $key Session data key
847 * @return bool
848 */
849 public function has_userdata($key)
850 {
851 return isset($_SESSION[$key]);
852 }
853
854 // ------------------------------------------------------------------------
855
856 /**
857 * Flashdata (fetch)
858 *
859 * Legacy CI_Session compatibility method
860 *
861 * @param string $key Session data key
862 * @return mixed Session data value or NULL if not found
Darren Hillc4e266b2011-08-30 15:40:27 -0400863 */
Andrey Andreevecc260e2014-01-24 14:20:13 +0200864 public function flashdata($key = NULL)
Darren Hillc4e266b2011-08-30 15:40:27 -0400865 {
Andrey Andreevecc260e2014-01-24 14:20:13 +0200866 if (isset($key))
867 {
Andrey Andreevef417862014-06-04 21:28:13 +0300868 return (isset($_SESSION['__ci_vars'], $_SESSION['__ci_vars'][$key], $_SESSION[$key]) && ! is_int($_SESSION['__ci_vars'][$key]))
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300869 ? $_SESSION[$key]
870 : NULL;
Andrey Andreevecc260e2014-01-24 14:20:13 +0200871 }
872
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300873 $flashdata = array();
874
Andrey Andreevef417862014-06-04 21:28:13 +0300875 if ( ! empty($_SESSION['__ci_vars']))
Andrey Andreevecc260e2014-01-24 14:20:13 +0200876 {
Andrey Andreevef417862014-06-04 21:28:13 +0300877 foreach ($_SESSION['__ci_vars'] as $key => &$value)
Andrey Andreevecc260e2014-01-24 14:20:13 +0200878 {
Andrey Andreevef417862014-06-04 21:28:13 +0300879 is_int($value) OR $flashdata[$key] = $_SESSION[$key];
Andrey Andreevecc260e2014-01-24 14:20:13 +0200880 }
881 }
882
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300883 return $flashdata;
Darren Hillc4e266b2011-08-30 15:40:27 -0400884 }
885
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300886 // ------------------------------------------------------------------------
887
Darren Hillc4e266b2011-08-30 15:40:27 -0400888 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300889 * Set flashdata
Darren Hillc4e266b2011-08-30 15:40:27 -0400890 *
Calvin Tam55bc5052015-07-24 02:27:24 -0700891 * Legacy CI_Session compatibility method
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300892 *
893 * @param mixed $data Session data key or an associative array
894 * @param mixed $value Value to store
Darren Hill5073a372011-08-31 13:54:19 -0400895 * @return void
Darren Hillc4e266b2011-08-30 15:40:27 -0400896 */
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300897 public function set_flashdata($data, $value = NULL)
Darren Hillc4e266b2011-08-30 15:40:27 -0400898 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300899 $this->set_userdata($data, $value);
Andrey Andreevc6e50982014-10-26 21:27:28 +0200900 $this->mark_as_flash(is_array($data) ? array_keys($data) : $data);
Darren Hillc4e266b2011-08-30 15:40:27 -0400901 }
902
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300903 // ------------------------------------------------------------------------
904
Darren Hillc4e266b2011-08-30 15:40:27 -0400905 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300906 * Keep flashdata
Darren Hillc4e266b2011-08-30 15:40:27 -0400907 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300908 * Legacy CI_Session compatibility method
909 *
910 * @param mixed $key Session data key(s)
Darren Hill5073a372011-08-31 13:54:19 -0400911 * @return void
Darren Hillc4e266b2011-08-30 15:40:27 -0400912 */
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300913 public function keep_flashdata($key)
Darren Hillc4e266b2011-08-30 15:40:27 -0400914 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300915 $this->mark_as_flash($key);
Darren Hillc4e266b2011-08-30 15:40:27 -0400916 }
917
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300918 // ------------------------------------------------------------------------
919
Darren Hillc4e266b2011-08-30 15:40:27 -0400920 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300921 * Temp data (fetch)
Darren Hillc4e266b2011-08-30 15:40:27 -0400922 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300923 * Legacy CI_Session compatibility method
924 *
925 * @param string $key Session data key
926 * @return mixed Session data value or NULL if not found
Darren Hillc4e266b2011-08-30 15:40:27 -0400927 */
Andrey Andreevecc260e2014-01-24 14:20:13 +0200928 public function tempdata($key = NULL)
Darren Hillc4e266b2011-08-30 15:40:27 -0400929 {
Andrey Andreevecc260e2014-01-24 14:20:13 +0200930 if (isset($key))
931 {
Andrey Andreevef417862014-06-04 21:28:13 +0300932 return (isset($_SESSION['__ci_vars'], $_SESSION['__ci_vars'][$key], $_SESSION[$key]) && is_int($_SESSION['__ci_vars'][$key]))
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300933 ? $_SESSION[$key]
934 : NULL;
Andrey Andreevecc260e2014-01-24 14:20:13 +0200935 }
936
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300937 $tempdata = array();
938
Andrey Andreevef417862014-06-04 21:28:13 +0300939 if ( ! empty($_SESSION['__ci_vars']))
Andrey Andreevecc260e2014-01-24 14:20:13 +0200940 {
Andrey Andreevef417862014-06-04 21:28:13 +0300941 foreach ($_SESSION['__ci_vars'] as $key => &$value)
Andrey Andreevecc260e2014-01-24 14:20:13 +0200942 {
Andrey Andreevef417862014-06-04 21:28:13 +0300943 is_int($value) && $tempdata[$key] = $_SESSION[$key];
Andrey Andreevecc260e2014-01-24 14:20:13 +0200944 }
945 }
946
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300947 return $tempdata;
Darren Hillc4e266b2011-08-30 15:40:27 -0400948 }
949
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300950 // ------------------------------------------------------------------------
951
Darren Hillc4e266b2011-08-30 15:40:27 -0400952 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300953 * Set tempdata
Darren Hillc4e266b2011-08-30 15:40:27 -0400954 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300955 * Legacy CI_Session compatibility method
956 *
957 * @param mixed $data Session data key or an associative array of items
958 * @param mixed $value Value to store
959 * @param int $ttl Time-to-live in seconds
Darren Hillc4e266b2011-08-30 15:40:27 -0400960 * @return void
961 */
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300962 public function set_tempdata($data, $value = NULL, $ttl = 300)
Darren Hillc4e266b2011-08-30 15:40:27 -0400963 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300964 $this->set_userdata($data, $value);
Andrey Andreevfd310572015-03-30 17:19:26 +0300965 $this->mark_as_temp(is_array($data) ? array_keys($data) : $data, $ttl);
Darren Hillc4e266b2011-08-30 15:40:27 -0400966 }
967
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300968 // ------------------------------------------------------------------------
969
Darren Hillc4e266b2011-08-30 15:40:27 -0400970 /**
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300971 * Unset tempdata
Darren Hillc4e266b2011-08-30 15:40:27 -0400972 *
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300973 * Legacy CI_Session compatibility method
974 *
975 * @param mixed $data Session data key(s)
Darren Hillc4e266b2011-08-30 15:40:27 -0400976 * @return void
977 */
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300978 public function unset_tempdata($key)
Darren Hillc4e266b2011-08-30 15:40:27 -0400979 {
Andrey Andreev47a47fb2014-05-31 16:08:30 +0300980 $this->unmark_temp($key);
Darren Hillc4e266b2011-08-30 15:40:27 -0400981 }
982
Andrey Andreev9ffcee62012-09-05 16:25:16 +0300983}