This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php defined('SYSPATH') or die('No direct access allowed.'); |
||
2 | /** |
||
3 | * Session library. |
||
4 | * |
||
5 | * $Id: Session.php 4073 2009-03-13 17:53:58Z Shadowhand $ |
||
6 | * |
||
7 | * @package Core |
||
8 | * @author Kohana Team |
||
9 | * @copyright (c) 2007-2008 Kohana Team |
||
10 | * @license http://kohanaphp.com/license.html |
||
11 | */ |
||
12 | class Session_Core |
||
13 | { |
||
14 | |||
15 | // Session singleton |
||
16 | protected static $instance; |
||
17 | |||
18 | // Protected key names (cannot be set by the user) |
||
19 | protected static $protect = array('session_id', 'user_agent', 'last_activity', 'ip_address', 'total_hits', '_kf_flash_'); |
||
20 | |||
21 | // Configuration and driver |
||
22 | protected static $config; |
||
23 | protected static $driver; |
||
24 | |||
25 | // Flash variables |
||
26 | protected static $flash; |
||
27 | |||
28 | // Input library |
||
29 | protected $input; |
||
30 | |||
31 | /** |
||
32 | * Singleton instance of Session. |
||
33 | */ |
||
34 | public static function instance() |
||
0 ignored issues
–
show
|
|||
35 | { |
||
36 | if (Session::$instance == null) { |
||
37 | // Create a new instance |
||
38 | new Session; |
||
39 | } |
||
40 | |||
41 | return Session::$instance; |
||
42 | } |
||
43 | |||
44 | /** |
||
45 | * On first session instance creation, sets up the driver and creates session. |
||
46 | */ |
||
47 | public function __construct() |
||
0 ignored issues
–
show
__construct uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
48 | { |
||
49 | $this->input = Input::instance(); |
||
50 | |||
51 | // This part only needs to be run once |
||
52 | if (Session::$instance === null) { |
||
53 | // Load config |
||
54 | Session::$config = Kohana::config('session'); |
||
55 | |||
56 | // Makes a mirrored array, eg: foo=foo |
||
57 | Session::$protect = array_combine(Session::$protect, Session::$protect); |
||
58 | |||
59 | // Configure garbage collection |
||
60 | ini_set('session.gc_probability', (int) Session::$config['gc_probability']); |
||
61 | ini_set('session.gc_divisor', 100); |
||
62 | ini_set('session.gc_maxlifetime', (Session::$config['expiration'] == 0) ? 86400 : Session::$config['expiration']); |
||
63 | |||
64 | // Create a new session |
||
65 | $this->create(); |
||
66 | |||
67 | if (Session::$config['regenerate'] > 0 and ($_SESSION['total_hits'] % Session::$config['regenerate']) === 0) { |
||
68 | // Regenerate session id and update session cookie |
||
69 | $this->regenerate(); |
||
70 | } else { |
||
71 | // Always update session cookie to keep the session alive |
||
72 | cookie::set(Session::$config['name'], $_SESSION['session_id'], Session::$config['expiration']); |
||
73 | } |
||
74 | |||
75 | // Close the session just before sending the headers, so that |
||
76 | // the session cookie(s) can be written. |
||
77 | Event::add('system.send_headers', array($this, 'write_close')); |
||
78 | |||
79 | // Make sure that sessions are closed before exiting |
||
80 | register_shutdown_function(array($this, 'write_close')); |
||
81 | |||
82 | // Singleton instance |
||
83 | Session::$instance = $this; |
||
84 | } |
||
85 | |||
86 | Kohana::log('debug', 'Session Library initialized'); |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * Get the session id. |
||
91 | * |
||
92 | * @return string |
||
93 | */ |
||
94 | public function id() |
||
0 ignored issues
–
show
id uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
95 | { |
||
96 | return $_SESSION['session_id']; |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Create a new session. |
||
101 | * |
||
102 | * @param array variables to set after creation |
||
103 | * @return void |
||
104 | */ |
||
105 | public function create($vars = null) |
||
0 ignored issues
–
show
create uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
106 | { |
||
107 | // Destroy any current sessions |
||
108 | $this->destroy(); |
||
109 | |||
110 | if (Session::$config['driver'] !== 'native') { |
||
111 | // Set driver name |
||
112 | $driver = 'Session_'.ucfirst(Session::$config['driver']).'_Driver'; |
||
113 | |||
114 | // Load the driver |
||
115 | View Code Duplication | if (! Kohana::auto_load($driver)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
116 | throw new Kohana_Exception('core.driver_not_found', Session::$config['driver'], get_class($this)); |
||
117 | } |
||
118 | |||
119 | // Initialize the driver |
||
120 | Session::$driver = new $driver(); |
||
121 | |||
122 | // Validate the driver |
||
123 | if (! (Session::$driver instanceof Session_Driver)) { |
||
124 | throw new Kohana_Exception('core.driver_implements', Session::$config['driver'], get_class($this), 'Session_Driver'); |
||
125 | } |
||
126 | |||
127 | // Register non-native driver as the session handler |
||
128 | session_set_save_handler( |
||
129 | array(Session::$driver, 'open'), |
||
130 | array(Session::$driver, 'close'), |
||
131 | array(Session::$driver, 'read'), |
||
132 | array(Session::$driver, 'write'), |
||
133 | array(Session::$driver, 'destroy'), |
||
134 | array(Session::$driver, 'gc') |
||
135 | ); |
||
136 | } |
||
137 | |||
138 | // Validate the session name |
||
139 | if (! preg_match('~^(?=.*[a-z])[a-z0-9_]++$~iD', Session::$config['name'])) { |
||
140 | throw new Kohana_Exception('session.invalid_session_name', Session::$config['name']); |
||
141 | } |
||
142 | |||
143 | // Name the session, this will also be the name of the cookie |
||
144 | session_name(Session::$config['name']); |
||
145 | |||
146 | // Set the session cookie parameters |
||
147 | session_set_cookie_params( |
||
148 | Session::$config['expiration'], |
||
149 | Kohana::config('cookie.path'), |
||
150 | Kohana::config('cookie.domain'), |
||
151 | Kohana::config('cookie.secure'), |
||
152 | Kohana::config('cookie.httponly') |
||
153 | ); |
||
154 | |||
155 | // Start the session! |
||
156 | session_start(); |
||
157 | |||
158 | // Put session_id in the session variable |
||
159 | $_SESSION['session_id'] = session_id(); |
||
160 | |||
161 | // Set defaults |
||
162 | if (! isset($_SESSION['_kf_flash_'])) { |
||
163 | $_SESSION['total_hits'] = 0; |
||
164 | $_SESSION['_kf_flash_'] = array(); |
||
165 | |||
166 | $_SESSION['user_agent'] = Kohana::$user_agent; |
||
167 | $_SESSION['ip_address'] = $this->input->ip_address(); |
||
168 | } |
||
169 | |||
170 | // Set up flash variables |
||
171 | Session::$flash =& $_SESSION['_kf_flash_']; |
||
172 | |||
173 | // Increase total hits |
||
174 | $_SESSION['total_hits'] += 1; |
||
175 | |||
176 | // Validate data only on hits after one |
||
177 | if ($_SESSION['total_hits'] > 1) { |
||
178 | // Validate the session |
||
179 | foreach (Session::$config['validate'] as $valid) { |
||
180 | switch ($valid) { |
||
181 | // Check user agent for consistency |
||
182 | case 'user_agent': |
||
183 | if ($_SESSION[$valid] !== Kohana::$user_agent) { |
||
184 | return $this->create(); |
||
185 | } |
||
186 | break; |
||
187 | |||
188 | // Check ip address for consistency |
||
189 | case 'ip_address': |
||
190 | if ($_SESSION[$valid] !== $this->input->$valid()) { |
||
191 | return $this->create(); |
||
192 | } |
||
193 | break; |
||
194 | |||
195 | // Check expiration time to prevent users from manually modifying it |
||
196 | case 'expiration': |
||
197 | if (time() - $_SESSION['last_activity'] > ini_get('session.gc_maxlifetime')) { |
||
198 | return $this->create(); |
||
199 | } |
||
200 | break; |
||
201 | } |
||
202 | } |
||
203 | } |
||
204 | |||
205 | // Expire flash keys |
||
206 | $this->expire_flash(); |
||
207 | |||
208 | // Update last activity |
||
209 | $_SESSION['last_activity'] = time(); |
||
210 | |||
211 | // Set the new data |
||
212 | Session::set($vars); |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * Regenerates the global session id. |
||
217 | * |
||
218 | * @return void |
||
219 | */ |
||
220 | public function regenerate() |
||
0 ignored issues
–
show
regenerate uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() regenerate uses the super-global variable $_COOKIE which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
221 | { |
||
222 | if (Session::$config['driver'] === 'native') { |
||
223 | // Generate a new session id |
||
224 | // Note: also sets a new session cookie with the updated id |
||
225 | session_regenerate_id(true); |
||
226 | |||
227 | // Update session with new id |
||
228 | $_SESSION['session_id'] = session_id(); |
||
229 | } else { |
||
230 | // Pass the regenerating off to the driver in case it wants to do anything special |
||
231 | $_SESSION['session_id'] = Session::$driver->regenerate(); |
||
232 | } |
||
233 | |||
234 | // Get the session name |
||
235 | $name = session_name(); |
||
236 | |||
237 | if (isset($_COOKIE[$name])) { |
||
238 | // Change the cookie value to match the new session id to prevent "lag" |
||
239 | $_COOKIE[$name] = $_SESSION['session_id']; |
||
240 | } |
||
241 | } |
||
242 | |||
243 | /** |
||
244 | * Destroys the current session. |
||
245 | * |
||
246 | * @return void |
||
247 | */ |
||
248 | public function destroy() |
||
0 ignored issues
–
show
destroy uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
249 | { |
||
250 | if (session_id() !== '') { |
||
251 | // Get the session name |
||
252 | $name = session_name(); |
||
253 | |||
254 | // Destroy the session |
||
255 | session_destroy(); |
||
256 | |||
257 | // Re-initialize the array |
||
258 | $_SESSION = array(); |
||
259 | |||
260 | // Delete the session cookie |
||
261 | cookie::delete($name); |
||
262 | } |
||
263 | } |
||
264 | |||
265 | /** |
||
266 | * Runs the system.session_write event, then calls session_write_close. |
||
267 | * |
||
268 | * @return void |
||
269 | */ |
||
270 | public function write_close() |
||
271 | { |
||
272 | static $run; |
||
273 | |||
274 | if ($run === null) { |
||
275 | $run = true; |
||
276 | |||
277 | // Run the events that depend on the session being open |
||
278 | Event::run('system.session_write'); |
||
279 | |||
280 | // Expire flash keys |
||
281 | $this->expire_flash(); |
||
282 | |||
283 | // Close the session |
||
284 | session_write_close(); |
||
285 | } |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * Set a session variable. |
||
290 | * |
||
291 | * @param string|array key, or array of values |
||
292 | * @param mixed value (if keys is not an array) |
||
293 | * @return false|null |
||
294 | */ |
||
295 | public function set($keys, $val = false) |
||
0 ignored issues
–
show
set uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
296 | { |
||
297 | if (empty($keys)) { |
||
298 | return false; |
||
299 | } |
||
300 | |||
301 | if (! is_array($keys)) { |
||
302 | $keys = array($keys => $val); |
||
303 | } |
||
304 | |||
305 | foreach ($keys as $key => $val) { |
||
306 | if (isset(Session::$protect[$key])) { |
||
307 | continue; |
||
308 | } |
||
309 | |||
310 | // Set the key |
||
311 | $_SESSION[$key] = $val; |
||
312 | } |
||
313 | } |
||
314 | |||
315 | /** |
||
316 | * Set a flash variable. |
||
317 | * |
||
318 | * @param string|array key, or array of values |
||
319 | * @param mixed value (if keys is not an array) |
||
320 | * @return false|null |
||
321 | */ |
||
322 | public function set_flash($keys, $val = false) |
||
323 | { |
||
324 | if (empty($keys)) { |
||
325 | return false; |
||
326 | } |
||
327 | |||
328 | if (! is_array($keys)) { |
||
329 | $keys = array($keys => $val); |
||
330 | } |
||
331 | |||
332 | foreach ($keys as $key => $val) { |
||
333 | if ($key == false) { |
||
334 | continue; |
||
335 | } |
||
336 | |||
337 | Session::$flash[$key] = 'new'; |
||
338 | Session::set($key, $val); |
||
339 | } |
||
340 | } |
||
341 | |||
342 | /** |
||
343 | * Freshen one, multiple or all flash variables. |
||
344 | * |
||
345 | * @param string variable key(s) |
||
346 | * @return void |
||
347 | */ |
||
348 | public function keep_flash($keys = null) |
||
349 | { |
||
350 | $keys = ($keys === null) ? array_keys(Session::$flash) : func_get_args(); |
||
351 | |||
352 | foreach ($keys as $key) { |
||
353 | if (isset(Session::$flash[$key])) { |
||
354 | Session::$flash[$key] = 'new'; |
||
355 | } |
||
356 | } |
||
357 | } |
||
358 | |||
359 | /** |
||
360 | * Expires old flash data and removes it from the session. |
||
361 | * |
||
362 | * @return void |
||
363 | */ |
||
364 | public function expire_flash() |
||
0 ignored issues
–
show
expire_flash uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
365 | { |
||
366 | static $run; |
||
367 | |||
368 | // Method can only be run once |
||
369 | if ($run === true) { |
||
370 | return; |
||
371 | } |
||
372 | |||
373 | if (! empty(Session::$flash)) { |
||
374 | foreach (Session::$flash as $key => $state) { |
||
375 | if ($state === 'old') { |
||
376 | // Flash has expired |
||
377 | unset(Session::$flash[$key], $_SESSION[$key]); |
||
378 | } else { |
||
379 | // Flash will expire |
||
380 | Session::$flash[$key] = 'old'; |
||
381 | } |
||
382 | } |
||
383 | } |
||
384 | |||
385 | // Method has been run |
||
386 | $run = true; |
||
387 | } |
||
388 | |||
389 | /** |
||
390 | * Get a variable. Access to sub-arrays is supported with key.subkey. |
||
391 | * |
||
392 | * @param string variable key |
||
393 | * @param mixed default value returned if variable does not exist |
||
394 | * @return mixed Variable data if key specified, otherwise array containing all session data. |
||
395 | */ |
||
396 | public function get($key = false, $default = false) |
||
0 ignored issues
–
show
get uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
397 | { |
||
398 | if (empty($key)) { |
||
399 | return $_SESSION; |
||
400 | } |
||
401 | |||
402 | $result = isset($_SESSION[$key]) ? $_SESSION[$key] : Kohana::key_string($_SESSION, $key); |
||
403 | |||
404 | return ($result === null) ? $default : $result; |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * Get a variable, and delete it. |
||
409 | * |
||
410 | * @param string variable key |
||
411 | * @param mixed default value returned if variable does not exist |
||
412 | * @return mixed |
||
413 | */ |
||
414 | public function get_once($key, $default = false) |
||
415 | { |
||
416 | $return = Session::get($key, $default); |
||
417 | Session::delete($key); |
||
418 | |||
419 | return $return; |
||
420 | } |
||
421 | |||
422 | /** |
||
423 | * Delete one or more variables. |
||
424 | * |
||
425 | * @param string variable key(s) |
||
426 | * @return void |
||
427 | */ |
||
428 | public function delete($keys) |
||
0 ignored issues
–
show
delete uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
429 | { |
||
430 | $args = func_get_args(); |
||
431 | |||
432 | foreach ($args as $key) { |
||
433 | if (isset(Session::$protect[$key])) { |
||
434 | continue; |
||
435 | } |
||
436 | |||
437 | // Unset the key |
||
438 | unset($_SESSION[$key]); |
||
439 | } |
||
440 | } |
||
441 | } // End Session Class |
||
442 |
Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a
@return
annotation as described here.