2014-04-23 10:51:50 +08:00
< ? php
/**
* Session class for CakePHP .
*
* CakePHP abstracts the handling of sessions .
* There are several convenient methods to access session information .
* This class is the implementation of those methods .
* They are mostly used by the Session Component .
*
2018-03-18 09:24:15 +08:00
* CakePHP ( tm ) : Rapid Development Framework ( https :// cakephp . org )
* Copyright ( c ) Cake Software Foundation , Inc . ( https :// cakefoundation . org )
2014-04-23 10:51:50 +08:00
*
* Licensed under The MIT License
* For full copyright and license information , please see the LICENSE . txt
* Redistributions of files must retain the above copyright notice .
*
2018-03-18 09:24:15 +08:00
* @ copyright Copyright ( c ) Cake Software Foundation , Inc . ( https :// cakefoundation . org )
* @ link https :// cakephp . org CakePHP ( tm ) Project
2014-04-23 10:51:50 +08:00
* @ package Cake . Model . Datasource
* @ since CakePHP ( tm ) v . 0.10 . 0.1222
2018-03-18 09:24:15 +08:00
* @ license https :// opensource . org / licenses / mit - license . php MIT License
2014-04-23 10:51:50 +08:00
*/
App :: uses ( 'Hash' , 'Utility' );
App :: uses ( 'Security' , 'Utility' );
/**
* Session class for CakePHP .
*
* CakePHP abstracts the handling of sessions . There are several convenient methods to access session information .
* This class is the implementation of those methods . They are mostly used by the Session Component .
*
* @ package Cake . Model . Datasource
*/
class CakeSession {
/**
* True if the Session is still valid
*
2016-02-25 20:25:24 +08:00
* @ var bool
2014-04-23 10:51:50 +08:00
*/
public static $valid = false ;
/**
* Error messages for this session
*
* @ var array
*/
public static $error = false ;
/**
* User agent string
*
* @ var string
*/
protected static $_userAgent = '' ;
/**
* Path to where the session is active .
*
* @ var string
*/
public static $path = '/' ;
/**
* Error number of last occurred error
*
2016-02-25 20:25:24 +08:00
* @ var int
2014-04-23 10:51:50 +08:00
*/
public static $lastError = null ;
/**
* Start time for this session .
*
2016-02-25 20:25:24 +08:00
* @ var int
2014-04-23 10:51:50 +08:00
*/
public static $time = false ;
/**
* Cookie lifetime
*
2016-02-25 20:25:24 +08:00
* @ var int
2014-04-23 10:51:50 +08:00
*/
public static $cookieLifeTime ;
/**
* Time when this session becomes invalid .
*
2016-02-25 20:25:24 +08:00
* @ var int
2014-04-23 10:51:50 +08:00
*/
public static $sessionTime = false ;
/**
* Current Session id
*
* @ var string
*/
public static $id = null ;
/**
* Hostname
*
* @ var string
*/
public static $host = null ;
/**
* Session timeout multiplier factor
*
2016-02-25 20:25:24 +08:00
* @ var int
2014-04-23 10:51:50 +08:00
*/
public static $timeout = null ;
/**
* Number of requests that can occur during a session time without the session being renewed .
* This feature is only used when config value `Session.autoRegenerate` is set to true .
*
2016-02-25 20:25:24 +08:00
* @ var int
2014-04-23 10:51:50 +08:00
* @ see CakeSession :: _checkValid ()
*/
public static $requestCountdown = 10 ;
/**
* Whether or not the init function in this class was already called
*
2016-02-25 20:25:24 +08:00
* @ var bool
2014-04-23 10:51:50 +08:00
*/
protected static $_initialized = false ;
/**
* Session cookie name
*
* @ var string
*/
protected static $_cookieName = null ;
2018-03-18 09:24:15 +08:00
/**
* Whether or not to make `_validAgentAndTime` 3. x compatible .
*
* @ var bool
*/
protected static $_useForwardsCompatibleTimeout = false ;
/**
* Whether this session is running under a CLI environment
*
* @ var bool
*/
protected static $_isCLI = false ;
2014-04-23 10:51:50 +08:00
/**
* Pseudo constructor .
*
2016-02-25 20:25:24 +08:00
* @ param string | null $base The base path for the Session
2014-04-23 10:51:50 +08:00
* @ return void
*/
public static function init ( $base = null ) {
2016-02-25 20:25:24 +08:00
static :: $time = time ();
2014-04-23 10:51:50 +08:00
2016-02-25 20:25:24 +08:00
if ( env ( 'HTTP_USER_AGENT' ) && ! static :: $_userAgent ) {
static :: $_userAgent = md5 ( env ( 'HTTP_USER_AGENT' ) . Configure :: read ( 'Security.salt' ));
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
static :: _setPath ( $base );
static :: _setHost ( env ( 'HTTP_HOST' ));
2014-04-23 10:51:50 +08:00
2016-02-25 20:25:24 +08:00
if ( ! static :: $_initialized ) {
2014-04-23 10:51:50 +08:00
register_shutdown_function ( 'session_write_close' );
}
2016-02-25 20:25:24 +08:00
static :: $_initialized = true ;
2018-03-18 09:24:15 +08:00
static :: $_isCLI = ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' );
2014-04-23 10:51:50 +08:00
}
/**
* Setup the Path variable
*
2016-02-25 20:25:24 +08:00
* @ param string | null $base base path
2014-04-23 10:51:50 +08:00
* @ return void
*/
protected static function _setPath ( $base = null ) {
if ( empty ( $base )) {
2016-02-25 20:25:24 +08:00
static :: $path = '/' ;
2014-04-23 10:51:50 +08:00
return ;
}
if ( strpos ( $base , 'index.php' ) !== false ) {
$base = str_replace ( 'index.php' , '' , $base );
}
if ( strpos ( $base , '?' ) !== false ) {
$base = str_replace ( '?' , '' , $base );
}
2016-02-25 20:25:24 +08:00
static :: $path = $base ;
2014-04-23 10:51:50 +08:00
}
/**
* Set the host name
*
* @ param string $host Hostname
* @ return void
*/
protected static function _setHost ( $host ) {
2016-02-25 20:25:24 +08:00
static :: $host = $host ;
if ( strpos ( static :: $host , ':' ) !== false ) {
static :: $host = substr ( static :: $host , 0 , strpos ( static :: $host , ':' ));
2014-04-23 10:51:50 +08:00
}
}
/**
* Starts the Session .
*
2016-02-25 20:25:24 +08:00
* @ return bool True if session was started
2014-04-23 10:51:50 +08:00
*/
public static function start () {
2016-02-25 20:25:24 +08:00
if ( static :: started ()) {
2014-04-23 10:51:50 +08:00
return true ;
}
2016-02-25 20:25:24 +08:00
$id = static :: id ();
static :: _startSession ();
if ( ! $id && static :: started ()) {
static :: _checkValid ();
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
static :: $error = false ;
static :: $valid = true ;
return static :: started ();
2014-04-23 10:51:50 +08:00
}
/**
* Determine if Session has been started .
*
2016-02-25 20:25:24 +08:00
* @ return bool True if session has been started .
2014-04-23 10:51:50 +08:00
*/
public static function started () {
2016-02-25 20:25:24 +08:00
if ( function_exists ( 'session_status' )) {
return isset ( $_SESSION ) && ( session_status () === PHP_SESSION_ACTIVE );
}
2014-04-23 10:51:50 +08:00
return isset ( $_SESSION ) && session_id ();
}
/**
* Returns true if given variable is set in session .
*
* @ param string $name Variable name to check for
2016-02-25 20:25:24 +08:00
* @ return bool True if variable is there
2014-04-23 10:51:50 +08:00
*/
2016-02-25 20:25:24 +08:00
public static function check ( $name ) {
2018-03-18 09:24:15 +08:00
if ( ! static :: _hasSession () || ! static :: start ()) {
2014-04-23 10:51:50 +08:00
return false ;
}
2018-03-18 09:24:15 +08:00
if ( isset ( $_SESSION [ $name ])) {
return true ;
}
2014-04-23 10:51:50 +08:00
return Hash :: get ( $_SESSION , $name ) !== null ;
}
/**
* Returns the session id .
* Calling this method will not auto start the session . You might have to manually
* assert a started session .
*
* Passing an id into it , you can also replace the session id if the session
* has not already been started .
* Note that depending on the session handler , not all characters are allowed
* within the session id . For example , the file session handler only allows
* characters in the range a - z A - Z 0 - 9 , ( comma ) and - ( minus ) .
*
2016-02-25 20:25:24 +08:00
* @ param string | null $id Id to replace the current session id
2014-04-23 10:51:50 +08:00
* @ return string Session id
*/
public static function id ( $id = null ) {
if ( $id ) {
2016-02-25 20:25:24 +08:00
static :: $id = $id ;
session_id ( static :: $id );
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
if ( static :: started ()) {
2014-04-23 10:51:50 +08:00
return session_id ();
}
2016-02-25 20:25:24 +08:00
return static :: $id ;
2014-04-23 10:51:50 +08:00
}
/**
* Removes a variable from session .
*
* @ param string $name Session variable to remove
2016-02-25 20:25:24 +08:00
* @ return bool Success
2014-04-23 10:51:50 +08:00
*/
public static function delete ( $name ) {
2016-02-25 20:25:24 +08:00
if ( static :: check ( $name )) {
static :: _overwrite ( $_SESSION , Hash :: remove ( $_SESSION , $name ));
return ! static :: check ( $name );
2014-04-23 10:51:50 +08:00
}
return false ;
}
/**
* Used to write new data to _SESSION , since PHP doesn ' t like us setting the _SESSION var itself .
*
2016-02-25 20:25:24 +08:00
* @ param array & $old Set of old variables => values
2014-04-23 10:51:50 +08:00
* @ param array $new New set of variable => value
* @ return void
*/
protected static function _overwrite ( & $old , $new ) {
if ( ! empty ( $old )) {
foreach ( $old as $key => $var ) {
if ( ! isset ( $new [ $key ])) {
unset ( $old [ $key ]);
}
}
}
foreach ( $new as $key => $var ) {
$old [ $key ] = $var ;
}
}
/**
* Return error description for given error number .
*
2016-02-25 20:25:24 +08:00
* @ param int $errorNumber Error to set
2014-04-23 10:51:50 +08:00
* @ return string Error as string
*/
protected static function _error ( $errorNumber ) {
2016-02-25 20:25:24 +08:00
if ( ! is_array ( static :: $error ) || ! array_key_exists ( $errorNumber , static :: $error )) {
2014-04-23 10:51:50 +08:00
return false ;
}
2016-02-25 20:25:24 +08:00
return static :: $error [ $errorNumber ];
2014-04-23 10:51:50 +08:00
}
/**
* Returns last occurred error as a string , if any .
*
* @ return mixed Error description as a string , or false .
*/
public static function error () {
2016-02-25 20:25:24 +08:00
if ( static :: $lastError ) {
return static :: _error ( static :: $lastError );
2014-04-23 10:51:50 +08:00
}
return false ;
}
/**
* Returns true if session is valid .
*
2016-02-25 20:25:24 +08:00
* @ return bool Success
2014-04-23 10:51:50 +08:00
*/
public static function valid () {
2016-02-25 20:25:24 +08:00
if ( static :: start () && static :: read ( 'Config' )) {
if ( static :: _validAgentAndTime () && static :: $error === false ) {
static :: $valid = true ;
2014-04-23 10:51:50 +08:00
} else {
2016-02-25 20:25:24 +08:00
static :: $valid = false ;
static :: _setError ( 1 , 'Session Highjacking Attempted !!!' );
2014-04-23 10:51:50 +08:00
}
}
2016-02-25 20:25:24 +08:00
return static :: $valid ;
2014-04-23 10:51:50 +08:00
}
/**
* Tests that the user agent is valid and that the session hasn 't ' timed out ' .
2016-02-25 20:25:24 +08:00
* Since timeouts are implemented in CakeSession it checks the current static :: $time
2014-04-23 10:51:50 +08:00
* against the time the session is set to expire . The User agent is only checked
* if Session . checkAgent == true .
*
2016-02-25 20:25:24 +08:00
* @ return bool
2014-04-23 10:51:50 +08:00
*/
protected static function _validAgentAndTime () {
2016-02-25 20:25:24 +08:00
$userAgent = static :: read ( 'Config.userAgent' );
$time = static :: read ( 'Config.time' );
2018-03-18 09:24:15 +08:00
if ( static :: $_useForwardsCompatibleTimeout ) {
$time += ( Configure :: read ( 'Session.timeout' ) * 60 );
}
2014-04-23 10:51:50 +08:00
$validAgent = (
Configure :: read ( 'Session.checkAgent' ) === false ||
2016-02-25 20:25:24 +08:00
isset ( $userAgent ) && static :: $_userAgent === $userAgent
2014-04-23 10:51:50 +08:00
);
2016-02-25 20:25:24 +08:00
return ( $validAgent && static :: $time <= $time );
2014-04-23 10:51:50 +08:00
}
/**
* Get / Set the user agent
*
2016-02-25 20:25:24 +08:00
* @ param string | null $userAgent Set the user agent
* @ return string Current user agent .
2014-04-23 10:51:50 +08:00
*/
public static function userAgent ( $userAgent = null ) {
if ( $userAgent ) {
2016-02-25 20:25:24 +08:00
static :: $_userAgent = $userAgent ;
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
if ( empty ( static :: $_userAgent )) {
CakeSession :: init ( static :: $path );
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
return static :: $_userAgent ;
2014-04-23 10:51:50 +08:00
}
/**
* Returns given session variable , or all of them , if no parameters given .
*
2016-02-25 20:25:24 +08:00
* @ param string | null $name The name of the session variable ( or a path as sent to Set . extract )
2014-04-23 10:51:50 +08:00
* @ return mixed The value of the session variable , null if session not available ,
2016-02-25 20:25:24 +08:00
* session not started , or provided name not found in the session , false on failure .
2014-04-23 10:51:50 +08:00
*/
public static function read ( $name = null ) {
2016-02-25 20:25:24 +08:00
if ( ! static :: _hasSession () || ! static :: start ()) {
2014-04-23 10:51:50 +08:00
return null ;
}
if ( $name === null ) {
2016-02-25 20:25:24 +08:00
return static :: _returnSessionVars ();
2014-04-23 10:51:50 +08:00
}
$result = Hash :: get ( $_SESSION , $name );
if ( isset ( $result )) {
return $result ;
}
return null ;
}
/**
* Returns all session variables .
*
* @ return mixed Full $_SESSION array , or false on error .
*/
protected static function _returnSessionVars () {
if ( ! empty ( $_SESSION )) {
return $_SESSION ;
}
2016-02-25 20:25:24 +08:00
static :: _setError ( 2 , 'No Session vars set' );
2014-04-23 10:51:50 +08:00
return false ;
}
/**
* Writes value to given session variable name .
*
* @ param string | array $name Name of variable
* @ param string $value Value to write
2016-02-25 20:25:24 +08:00
* @ return bool True if the write was successful , false if the write failed
2014-04-23 10:51:50 +08:00
*/
public static function write ( $name , $value = null ) {
2018-03-18 09:24:15 +08:00
if ( ! static :: start ()) {
2014-04-23 10:51:50 +08:00
return false ;
}
$write = $name ;
if ( ! is_array ( $name )) {
$write = array ( $name => $value );
}
foreach ( $write as $key => $val ) {
2016-02-25 20:25:24 +08:00
static :: _overwrite ( $_SESSION , Hash :: insert ( $_SESSION , $key , $val ));
2014-04-23 10:51:50 +08:00
if ( Hash :: get ( $_SESSION , $key ) !== $val ) {
return false ;
}
}
return true ;
}
2016-02-25 20:25:24 +08:00
/**
* Reads and deletes a variable from session .
*
* @ param string $name The key to read and remove ( or a path as sent to Hash . extract ) .
* @ return mixed The value of the session variable , null if session not available ,
* session not started , or provided name not found in the session .
*/
public static function consume ( $name ) {
if ( empty ( $name )) {
return null ;
}
$value = static :: read ( $name );
if ( $value !== null ) {
static :: _overwrite ( $_SESSION , Hash :: remove ( $_SESSION , $name ));
}
return $value ;
}
2014-04-23 10:51:50 +08:00
/**
* Helper method to destroy invalid sessions .
*
* @ return void
*/
public static function destroy () {
2016-02-25 20:25:24 +08:00
if ( ! static :: started ()) {
static :: _startSession ();
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
if ( static :: started ()) {
if ( session_id () && static :: _hasSession ()) {
session_write_close ();
session_start ();
}
session_destroy ();
unset ( $_COOKIE [ static :: _cookieName ()]);
}
2014-04-23 10:51:50 +08:00
$_SESSION = null ;
2016-02-25 20:25:24 +08:00
static :: $id = null ;
static :: $_cookieName = null ;
2014-04-23 10:51:50 +08:00
}
/**
2016-02-25 20:25:24 +08:00
* Clears the session .
*
* Optionally also clears the session id and renews the session .
2014-04-23 10:51:50 +08:00
*
2016-02-25 20:25:24 +08:00
* @ param bool $renew If the session should also be renewed . Defaults to true .
2014-04-23 10:51:50 +08:00
* @ return void
*/
2016-02-25 20:25:24 +08:00
public static function clear ( $renew = true ) {
if ( ! $renew ) {
$_SESSION = array ();
return ;
}
2014-04-23 10:51:50 +08:00
$_SESSION = null ;
2016-02-25 20:25:24 +08:00
static :: $id = null ;
static :: renew ();
2014-04-23 10:51:50 +08:00
}
/**
* Helper method to initialize a session , based on CakePHP core settings .
*
* Sessions can be configured with a few shortcut names as well as have any number of ini settings declared .
*
* @ return void
* @ throws CakeSessionException Throws exceptions when ini_set () fails .
*/
protected static function _configureSession () {
$sessionConfig = Configure :: read ( 'Session' );
if ( isset ( $sessionConfig [ 'defaults' ])) {
2016-02-25 20:25:24 +08:00
$defaults = static :: _defaultConfig ( $sessionConfig [ 'defaults' ]);
2014-04-23 10:51:50 +08:00
if ( $defaults ) {
$sessionConfig = Hash :: merge ( $defaults , $sessionConfig );
}
}
if ( ! isset ( $sessionConfig [ 'ini' ][ 'session.cookie_secure' ]) && env ( 'HTTPS' )) {
$sessionConfig [ 'ini' ][ 'session.cookie_secure' ] = 1 ;
}
if ( isset ( $sessionConfig [ 'timeout' ]) && ! isset ( $sessionConfig [ 'cookieTimeout' ])) {
$sessionConfig [ 'cookieTimeout' ] = $sessionConfig [ 'timeout' ];
}
2018-03-18 09:24:15 +08:00
if ( isset ( $sessionConfig [ 'useForwardsCompatibleTimeout' ]) && $sessionConfig [ 'useForwardsCompatibleTimeout' ]) {
static :: $_useForwardsCompatibleTimeout = true ;
}
2014-04-23 10:51:50 +08:00
if ( ! isset ( $sessionConfig [ 'ini' ][ 'session.cookie_lifetime' ])) {
$sessionConfig [ 'ini' ][ 'session.cookie_lifetime' ] = $sessionConfig [ 'cookieTimeout' ] * 60 ;
}
if ( ! isset ( $sessionConfig [ 'ini' ][ 'session.name' ])) {
$sessionConfig [ 'ini' ][ 'session.name' ] = $sessionConfig [ 'cookie' ];
}
2016-02-25 20:25:24 +08:00
static :: $_cookieName = $sessionConfig [ 'ini' ][ 'session.name' ];
2014-04-23 10:51:50 +08:00
if ( ! empty ( $sessionConfig [ 'handler' ])) {
$sessionConfig [ 'ini' ][ 'session.save_handler' ] = 'user' ;
2018-03-18 09:24:15 +08:00
// In PHP7.2.0+ session.save_handler can't be set to 'user' by the user.
// https://github.com/php/php-src/commit/a93a51c3bf4ea1638ce0adc4a899cb93531b9f0d
if ( version_compare ( PHP_VERSION , '7.2.0' , '>=' )) {
unset ( $sessionConfig [ 'ini' ][ 'session.save_handler' ]);
}
2016-02-25 20:25:24 +08:00
} elseif ( ! empty ( $sessionConfig [ 'session.save_path' ]) && Configure :: read ( 'debug' )) {
if ( ! is_dir ( $sessionConfig [ 'session.save_path' ])) {
mkdir ( $sessionConfig [ 'session.save_path' ], 0775 , true );
}
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
2014-04-23 10:51:50 +08:00
if ( ! isset ( $sessionConfig [ 'ini' ][ 'session.gc_maxlifetime' ])) {
$sessionConfig [ 'ini' ][ 'session.gc_maxlifetime' ] = $sessionConfig [ 'timeout' ] * 60 ;
}
if ( ! isset ( $sessionConfig [ 'ini' ][ 'session.cookie_httponly' ])) {
$sessionConfig [ 'ini' ][ 'session.cookie_httponly' ] = 1 ;
}
2016-02-25 20:25:24 +08:00
// For IE<=8
if ( ! isset ( $sessionConfig [ 'cacheLimiter' ])) {
$sessionConfig [ 'cacheLimiter' ] = 'must-revalidate' ;
}
2014-04-23 10:51:50 +08:00
if ( empty ( $_SESSION )) {
if ( ! empty ( $sessionConfig [ 'ini' ]) && is_array ( $sessionConfig [ 'ini' ])) {
foreach ( $sessionConfig [ 'ini' ] as $setting => $value ) {
if ( ini_set ( $setting , $value ) === false ) {
throw new CakeSessionException ( __d ( 'cake_dev' , 'Unable to configure the session, setting %s failed.' , $setting ));
}
}
}
}
if ( ! empty ( $sessionConfig [ 'handler' ]) && ! isset ( $sessionConfig [ 'handler' ][ 'engine' ])) {
call_user_func_array ( 'session_set_save_handler' , $sessionConfig [ 'handler' ]);
}
if ( ! empty ( $sessionConfig [ 'handler' ][ 'engine' ])) {
2016-02-25 20:25:24 +08:00
$handler = static :: _getHandler ( $sessionConfig [ 'handler' ][ 'engine' ]);
2014-04-23 10:51:50 +08:00
session_set_save_handler (
array ( $handler , 'open' ),
array ( $handler , 'close' ),
array ( $handler , 'read' ),
array ( $handler , 'write' ),
array ( $handler , 'destroy' ),
array ( $handler , 'gc' )
);
}
Configure :: write ( 'Session' , $sessionConfig );
2018-03-18 09:24:15 +08:00
static :: $sessionTime = static :: $time ;
if ( ! static :: $_useForwardsCompatibleTimeout ) {
static :: $sessionTime += ( $sessionConfig [ 'timeout' ] * 60 );
}
2014-04-23 10:51:50 +08:00
}
/**
* Get session cookie name .
*
* @ return string
*/
protected static function _cookieName () {
2016-02-25 20:25:24 +08:00
if ( static :: $_cookieName !== null ) {
return static :: $_cookieName ;
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
static :: init ();
static :: _configureSession ();
2014-04-23 10:51:50 +08:00
2016-02-25 20:25:24 +08:00
return static :: $_cookieName = session_name ();
2014-04-23 10:51:50 +08:00
}
/**
* Returns whether a session exists
2016-02-25 20:25:24 +08:00
*
* @ return bool
2014-04-23 10:51:50 +08:00
*/
protected static function _hasSession () {
2018-03-18 09:24:15 +08:00
return static :: started ()
|| ! ini_get ( 'session.use_cookies' )
|| isset ( $_COOKIE [ static :: _cookieName ()])
|| static :: $_isCLI
|| ( ini_get ( 'session.use_trans_sid' ) && isset ( $_GET [ session_name ()]));
2014-04-23 10:51:50 +08:00
}
/**
* Find the handler class and make sure it implements the correct interface .
*
2016-02-25 20:25:24 +08:00
* @ param string $handler Handler name .
2018-03-18 09:24:15 +08:00
* @ return CakeSessionHandlerInterface
2014-04-23 10:51:50 +08:00
* @ throws CakeSessionException
*/
protected static function _getHandler ( $handler ) {
list ( $plugin , $class ) = pluginSplit ( $handler , true );
App :: uses ( $class , $plugin . 'Model/Datasource/Session' );
if ( ! class_exists ( $class )) {
throw new CakeSessionException ( __d ( 'cake_dev' , 'Could not load %s to handle the session.' , $class ));
}
$handler = new $class ();
if ( $handler instanceof CakeSessionHandlerInterface ) {
return $handler ;
}
throw new CakeSessionException ( __d ( 'cake_dev' , 'Chosen SessionHandler does not implement CakeSessionHandlerInterface it cannot be used with an engine key.' ));
}
/**
* Get one of the prebaked default session configurations .
*
2016-02-25 20:25:24 +08:00
* @ param string $name Config name .
* @ return bool | array
2014-04-23 10:51:50 +08:00
*/
protected static function _defaultConfig ( $name ) {
$defaults = array (
'php' => array (
'cookie' => 'CAKEPHP' ,
'timeout' => 240 ,
'ini' => array (
'session.use_trans_sid' => 0 ,
2016-02-25 20:25:24 +08:00
'session.cookie_path' => static :: $path
2014-04-23 10:51:50 +08:00
)
),
'cake' => array (
'cookie' => 'CAKEPHP' ,
'timeout' => 240 ,
'ini' => array (
'session.use_trans_sid' => 0 ,
'url_rewriter.tags' => '' ,
'session.serialize_handler' => 'php' ,
'session.use_cookies' => 1 ,
2016-02-25 20:25:24 +08:00
'session.cookie_path' => static :: $path ,
2014-04-23 10:51:50 +08:00
'session.save_path' => TMP . 'sessions' ,
'session.save_handler' => 'files'
)
),
'cache' => array (
'cookie' => 'CAKEPHP' ,
'timeout' => 240 ,
'ini' => array (
'session.use_trans_sid' => 0 ,
'url_rewriter.tags' => '' ,
'session.use_cookies' => 1 ,
2016-02-25 20:25:24 +08:00
'session.cookie_path' => static :: $path ,
2014-04-23 10:51:50 +08:00
'session.save_handler' => 'user' ,
),
'handler' => array (
'engine' => 'CacheSession' ,
'config' => 'default'
)
),
'database' => array (
'cookie' => 'CAKEPHP' ,
'timeout' => 240 ,
'ini' => array (
'session.use_trans_sid' => 0 ,
'url_rewriter.tags' => '' ,
'session.use_cookies' => 1 ,
2016-02-25 20:25:24 +08:00
'session.cookie_path' => static :: $path ,
2014-04-23 10:51:50 +08:00
'session.save_handler' => 'user' ,
'session.serialize_handler' => 'php' ,
),
'handler' => array (
'engine' => 'DatabaseSession' ,
'model' => 'Session'
)
)
);
if ( isset ( $defaults [ $name ])) {
return $defaults [ $name ];
}
return false ;
}
/**
* Helper method to start a session
*
2016-02-25 20:25:24 +08:00
* @ return bool Success
2014-04-23 10:51:50 +08:00
*/
protected static function _startSession () {
2016-02-25 20:25:24 +08:00
static :: init ();
2014-04-23 10:51:50 +08:00
session_write_close ();
2016-02-25 20:25:24 +08:00
static :: _configureSession ();
2014-04-23 10:51:50 +08:00
if ( headers_sent ()) {
if ( empty ( $_SESSION )) {
$_SESSION = array ();
}
} else {
2016-02-25 20:25:24 +08:00
$limit = Configure :: read ( 'Session.cacheLimiter' );
if ( ! empty ( $limit )) {
session_cache_limiter ( $limit );
}
2014-04-23 10:51:50 +08:00
session_start ();
}
return true ;
}
/**
* Helper method to create a new session .
*
* @ return void
*/
protected static function _checkValid () {
2016-02-25 20:25:24 +08:00
$config = static :: read ( 'Config' );
2014-04-23 10:51:50 +08:00
if ( $config ) {
$sessionConfig = Configure :: read ( 'Session' );
2016-02-25 20:25:24 +08:00
if ( static :: valid ()) {
static :: write ( 'Config.time' , static :: $sessionTime );
2014-04-23 10:51:50 +08:00
if ( isset ( $sessionConfig [ 'autoRegenerate' ]) && $sessionConfig [ 'autoRegenerate' ] === true ) {
$check = $config [ 'countdown' ];
$check -= 1 ;
2016-02-25 20:25:24 +08:00
static :: write ( 'Config.countdown' , $check );
2014-04-23 10:51:50 +08:00
if ( $check < 1 ) {
2016-02-25 20:25:24 +08:00
static :: renew ();
static :: write ( 'Config.countdown' , static :: $requestCountdown );
2014-04-23 10:51:50 +08:00
}
}
} else {
$_SESSION = array ();
2016-02-25 20:25:24 +08:00
static :: destroy ();
static :: _setError ( 1 , 'Session Highjacking Attempted !!!' );
static :: _startSession ();
static :: _writeConfig ();
2014-04-23 10:51:50 +08:00
}
} else {
2016-02-25 20:25:24 +08:00
static :: _writeConfig ();
2014-04-23 10:51:50 +08:00
}
}
/**
* Writes configuration variables to the session
*
* @ return void
*/
protected static function _writeConfig () {
2016-02-25 20:25:24 +08:00
static :: write ( 'Config.userAgent' , static :: $_userAgent );
static :: write ( 'Config.time' , static :: $sessionTime );
static :: write ( 'Config.countdown' , static :: $requestCountdown );
2014-04-23 10:51:50 +08:00
}
/**
* Restarts this session .
*
* @ return void
*/
public static function renew () {
2016-02-25 20:25:24 +08:00
if ( session_id () === '' ) {
return ;
}
if ( isset ( $_COOKIE [ static :: _cookieName ()])) {
setcookie ( Configure :: read ( 'Session.cookie' ), '' , time () - 42000 , static :: $path );
}
if ( ! headers_sent ()) {
session_write_close ();
session_start ();
2014-04-23 10:51:50 +08:00
session_regenerate_id ( true );
}
}
/**
* Helper method to set an internal error message .
*
2016-02-25 20:25:24 +08:00
* @ param int $errorNumber Number of the error
2014-04-23 10:51:50 +08:00
* @ param string $errorMessage Description of the error
* @ return void
*/
protected static function _setError ( $errorNumber , $errorMessage ) {
2016-02-25 20:25:24 +08:00
if ( static :: $error === false ) {
static :: $error = array ();
2014-04-23 10:51:50 +08:00
}
2016-02-25 20:25:24 +08:00
static :: $error [ $errorNumber ] = $errorMessage ;
static :: $lastError = $errorNumber ;
2014-04-23 10:51:50 +08:00
}
}