Version 4.6.0
This commit is contained in:
1 parent
f79dcf067a
commit
517a5e1f70
2036 files changed
+110041
-26162
No files matched your search
@@ -52,8 +52,15 @@ class _Admin extends \IPS\Session
|
||||
|
||||
try
|
||||
{
|
||||
$where = array( array( 'session_id=?', $sessionId ) );
|
||||
|
||||
if( !\IPS\IN_DEV OR !\IPS\DEV_DISABLE_ACP_SESSION_TIMEOUT )
|
||||
{
|
||||
$where[] = array( 'session_running_time>=?', ( time() - \IPS\ACP_SESSION_TIMEOUT ) );
|
||||
}
|
||||
|
||||
/* Load session */
|
||||
$session = \IPS\Db::i()->select( '*', 'core_sys_cp_sessions', array( 'session_id=? AND session_running_time>=?', $sessionId, ( time() - \IPS\Session::sessionLifetime() ) ) )->first();
|
||||
$session = \IPS\Db::i()->select( '*', 'core_sys_cp_sessions', $where )->first();
|
||||
$this->logInTime = $session['session_log_in_time'];
|
||||
|
||||
/* Store this so plugins can access */
|
||||
@@ -133,11 +140,14 @@ class _Admin extends \IPS\Session
|
||||
/**
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param int $lifetime Unix timestamp of the oldest session to keep
|
||||
* @param int $lifetime Number of seconds to consider sessions expired beyond
|
||||
* @return bool
|
||||
*/
|
||||
public function gc( $lifetime )
|
||||
{
|
||||
/* We ignore $lifetime because we explicitly control how long sessions are valid for via a constant */
|
||||
$lifetime = \IPS\ACP_SESSION_TIMEOUT;
|
||||
|
||||
\IPS\Db::i()->delete( 'core_sys_cp_sessions', array( 'session_running_time<?', ( time() - $lifetime ) ) );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+22
-64
@@ -67,11 +67,6 @@ class _Front extends \IPS\Session
|
||||
*/
|
||||
protected $save = TRUE;
|
||||
|
||||
/**
|
||||
* @brief No write guest session?
|
||||
*/
|
||||
protected $noWriteGuestSession = FALSE;
|
||||
|
||||
/**
|
||||
* Open Session
|
||||
*
|
||||
@@ -97,12 +92,6 @@ class _Front extends \IPS\Session
|
||||
/* Get user agent info */
|
||||
$this->userAgent = \IPS\Http\Useragent::parse();
|
||||
|
||||
if ( ! static::loggedIn() and isset( \IPS\Request::i()->cookie['guestTime'] ) and ( !isset( \IPS\Request::i()->cookie['noCache'] ) or !\IPS\Request::i()->cookie['noCache'] ) and time() < ( \IPS\Request::i()->cookie['guestTime'] + \IPS\CACHE_PAGE_TIMEOUT ) and \IPS\Request::i()->requestMethod() == 'GET' )
|
||||
{
|
||||
$this->sessionData = $this->setNoWriteGuestSession();
|
||||
return (string) $this->sessionData['data'];
|
||||
}
|
||||
|
||||
$session = \IPS\Session\Store::i()->loadSession( $this->sessionId );
|
||||
|
||||
/* Only use sessions with matching IP address */
|
||||
@@ -183,6 +172,7 @@ class _Front extends \IPS\Session
|
||||
if ( $success )
|
||||
{
|
||||
$this->member = $expectedMember;
|
||||
$expectedMember->achievementAction( 'core', 'SessionStartDaily' );
|
||||
}
|
||||
/* Or if the access token wasn't valid, log it as a fail so that it can't be bruteforced */
|
||||
else
|
||||
@@ -219,6 +209,9 @@ class _Front extends \IPS\Session
|
||||
|
||||
/* Set member in session */
|
||||
$this->member = $member;
|
||||
|
||||
$member->recordLogin();
|
||||
$member->achievementAction( 'core', 'SessionStartDaily' );
|
||||
|
||||
/* Update device */
|
||||
$device->updateAfterAuthentication( TRUE, NULL, FALSE );
|
||||
@@ -262,9 +255,7 @@ class _Front extends \IPS\Session
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'guestTime', time() );
|
||||
|
||||
{
|
||||
$type = $this->userAgent->spider ? static::LOGIN_TYPE_SPIDER : static::LOGIN_TYPE_GUEST;
|
||||
}
|
||||
|
||||
@@ -330,6 +321,9 @@ class _Front extends \IPS\Session
|
||||
{
|
||||
parent::setMember( $member );
|
||||
|
||||
$member->recordLogin();
|
||||
$member->achievementAction( 'core', 'SessionStartDaily' );
|
||||
|
||||
/* Make sure session handler saves during write() */
|
||||
$this->save = TRUE;
|
||||
}
|
||||
@@ -343,22 +337,29 @@ class _Front extends \IPS\Session
|
||||
*/
|
||||
public function write( $sessionId, $data )
|
||||
{
|
||||
if ( $this->noWriteGuestSession and empty( $_SESSION['forcedWrite'] ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ( !isset( $this->data['data'] ) or $data !== $this->data['data'] or $this->data['member_id'] != $this->member->member_id )
|
||||
{
|
||||
$this->save = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Don't update if instant notifications are checking to reduce overhead on the session table */
|
||||
if ( \IPS\Request::i()->isAjax() and isset( \IPS\Request::i()->app ) and \IPS\Request::i()->app === 'core' and isset( \IPS\Request::i()->controller ) and \IPS\Request::i()->controller === 'ajax' and isset( \IPS\Request::i()->do ) and \IPS\Request::i()->do === 'instantNotifications' )
|
||||
{
|
||||
$this->save = FALSE;
|
||||
}
|
||||
|
||||
/* Don't update if there is a hit on the manifest. Why do we use the url()? When page caching grabs and returns, the \IPS\Request::i()->do/controller variables are no populated */
|
||||
if ( isset( \IPS\Request::i()->url()->hiddenQueryString['controller'] ) and \IPS\Request::i()->url()->hiddenQueryString['controller'] === 'metatags' and isset( \IPS\Request::i()->url()->hiddenQueryString['do'] ) and \IPS\Request::i()->url()->hiddenQueryString['do'] === 'manifest' )
|
||||
{
|
||||
$this->save = FALSE;
|
||||
}
|
||||
|
||||
/* Don't update if there is a hit on the serviceworker */
|
||||
if ( isset( \IPS\Request::i()->app ) and \IPS\Request::i()->app === 'core' and isset( \IPS\Request::i()->controller ) and \IPS\Request::i()->controller === 'serviceworker' )
|
||||
{
|
||||
$this->save = FALSE;
|
||||
}
|
||||
|
||||
$this->data['member_name'] = $this->member->member_id ? $this->member->name : '';
|
||||
$this->data['member_id'] = $this->member->member_id ?: NULL;
|
||||
$this->data['data'] = $data;
|
||||
@@ -653,7 +654,7 @@ class _Front extends \IPS\Session
|
||||
/**
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param int $lifetime Unix timestamp of the oldest session to keep
|
||||
* @param int $lifetime Number of seconds to consider sessions expired beyond
|
||||
* @return bool
|
||||
*/
|
||||
public function gc( $lifetime )
|
||||
@@ -661,47 +662,4 @@ class _Front extends \IPS\Session
|
||||
static::clearSessions( $lifetime );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a session that doesn't require a DB read or write
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function setNoWriteGuestSession()
|
||||
{
|
||||
$this->noWriteGuestSession = TRUE;
|
||||
|
||||
$this->member = new \IPS\Member;
|
||||
|
||||
/* Set data */
|
||||
$this->data = array(
|
||||
'id' => $this->sessionId,
|
||||
'member_name' => '',
|
||||
'seo_name' => '',
|
||||
'member_id' => 0,
|
||||
'ip_address' => \IPS\Request::i()->ipAddress(),
|
||||
'browser' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '',
|
||||
'running_time' => time(),
|
||||
'login_type' => $this->userAgent->spider ? static::LOGIN_TYPE_SPIDER : static::LOGIN_TYPE_GUEST,
|
||||
'member_group' => \IPS\Settings::i()->guest_group,
|
||||
'current_appcomponent' => '',
|
||||
'current_module' => '',
|
||||
'current_controller' => NULL,
|
||||
'current_id' => \intval( \IPS\Request::i()->id ),
|
||||
'uagent_key' => $this->userAgent->browser ?: '',
|
||||
'uagent_version' => $this->userAgent->browserVersion ?: '',
|
||||
'uagent_type' => $this->userAgent->spider ? 'search' : 'browser',
|
||||
'search_thread_id' => 0,
|
||||
'search_thread_time' => 0,
|
||||
'data' => '',
|
||||
'location_url' => NULL,
|
||||
'location_lang' => NULL,
|
||||
'location_data' => NULL,
|
||||
'location_permissions' => NULL,
|
||||
'theme_id' => isset( \IPS\Request::i()->cookie['theme'] ) ? \IPS\Request::i()->cookie['theme'] : 0,
|
||||
'in_editor' => 0,
|
||||
);
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,9 @@ abstract class _Session
|
||||
{
|
||||
/* Create class */
|
||||
static::$instance = new $classname;
|
||||
|
||||
/* Remove PHPs own cache headers */
|
||||
session_cache_limiter('');
|
||||
|
||||
/* Name the session */
|
||||
$name = session_name( ( \IPS\COOKIE_PREFIX !== NULL ) ? \IPS\COOKIE_PREFIX . 'IPSSession' . $location : 'IPSSession' . $location );
|
||||
@@ -204,6 +207,14 @@ abstract class _Session
|
||||
$this->member->save();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ensure any loggedIn cookies are removed */
|
||||
if( isset( \IPS\Request::i()->cookie['loggedIn'] ) )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'loggedIn', NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,7 +234,15 @@ abstract class _Session
|
||||
*/
|
||||
public function csrfCheck()
|
||||
{
|
||||
if ( !\IPS\Login::compareHashes( (string) $this->csrfKey, (string) \IPS\Request::i()->csrfKey ) )
|
||||
$token = (string) \IPS\Request::i()->csrfKey;
|
||||
|
||||
/* Guests may provide the csrf token via a header */
|
||||
if ( !\IPS\Member::loggedIn()->member_id && isset( $_SERVER['HTTP_X_CSRF_TOKEN'] ) )
|
||||
{
|
||||
$token = $_SERVER['HTTP_X_CSRF_TOKEN'];
|
||||
}
|
||||
|
||||
if ( !\IPS\Login::compareHashes( (string) $this->csrfKey, $token ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'generic_error', '2S119/1', 403, 'admin_csrf_error' );
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ class _Database extends \IPS\Session\Store
|
||||
* Load the session from the storage engine
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
* @return array
|
||||
* @return array|NULL
|
||||
*/
|
||||
public function loadSession( $sessionId )
|
||||
{
|
||||
@@ -197,13 +197,34 @@ class _Database extends \IPS\Session\Store
|
||||
$memberSubWhere[] = 's.member_id IS NOT NULL';
|
||||
|
||||
/* Ok, this looks odd, but the ONLY_FULL_GROUP_BY bites us here, so selecting max(id) allows us to return a session ID even though we're grouping on member_id */
|
||||
$where = array(
|
||||
array(
|
||||
"( core_sessions.id IN(?) OR core_sessions.id IN(?) )",
|
||||
\IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $memberSubWhere, NULL, NULL, 'member_id' ),
|
||||
\IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $guestSubWhere, NULL, NULL, 'ip_address' )
|
||||
)
|
||||
);
|
||||
if ( $flags AND ! ( $flags & static::ONLINE_GUESTS ) )
|
||||
{
|
||||
$where = array(
|
||||
array(
|
||||
"core_sessions.id IN(?)",
|
||||
\IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $memberSubWhere, NULL, NULL, 'member_id' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
elseif ( $flags AND ! ( $flags & static::ONLINE_MEMBERS ) )
|
||||
{
|
||||
$where = array(
|
||||
array(
|
||||
"core_sessions.id IN(?)",
|
||||
\IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $guestSubWhere, NULL, NULL, 'ip_address' )
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$where = array(
|
||||
array(
|
||||
"( core_sessions.id IN(?) OR core_sessions.id IN(?) )",
|
||||
\IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $memberSubWhere, NULL, NULL, 'member_id' ),
|
||||
\IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $guestSubWhere, NULL, NULL, 'ip_address' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/* Limiting to a user group? */
|
||||
if ( $memberGroup )
|
||||
|
||||
@@ -31,13 +31,17 @@ class _Redis extends \IPS\Session\Store
|
||||
* Load the session from the storage engine
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
* @return array
|
||||
* @return array|NULL
|
||||
*/
|
||||
public function loadSession( $sessionId )
|
||||
{
|
||||
if ( $result = \IPS\Redis::i()->hGetAll( static::_key( 'session_id_' . md5( $sessionId . \IPS\Settings::i()->sql_pass ) ) ) )
|
||||
{
|
||||
return \IPS\Redis::i()->decode( $result['data'] );
|
||||
{
|
||||
try
|
||||
{
|
||||
return \IPS\Redis::i()->decode( $result['data'] );
|
||||
}
|
||||
catch( \RedisException $e ){}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -136,7 +140,11 @@ class _Redis extends \IPS\Session\Store
|
||||
{
|
||||
$session = \IPS\Redis::i()->hMGet( $redisKey, array( 'data' ) );
|
||||
|
||||
$sessionMap[ $index ] = \IPS\Redis::i()->decode( $session['data'] );
|
||||
try
|
||||
{
|
||||
$sessionMap[ $index ] = \IPS\Redis::i()->decode( $session['data'] );
|
||||
}
|
||||
catch( \RedisException $e ){}
|
||||
}
|
||||
|
||||
foreach( $sessionMap as $session )
|
||||
@@ -196,8 +204,12 @@ class _Redis extends \IPS\Session\Store
|
||||
if ( $id == $memberId )
|
||||
{
|
||||
if ( $result = \IPS\Redis::i()->hGetAll( static::_key( $sessionKey ) ) )
|
||||
{
|
||||
return \IPS\Redis::i()->decode( $result['data'] );
|
||||
{
|
||||
try
|
||||
{
|
||||
return \IPS\Redis::i()->decode( $result['data'] );
|
||||
}
|
||||
catch( \RedisException $e ){}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -368,7 +380,14 @@ class _Redis extends \IPS\Session\Store
|
||||
{
|
||||
if ( $field === 'data' )
|
||||
{
|
||||
$data = \IPS\Redis::i()->decode( $results[ $i++ ] );
|
||||
try
|
||||
{
|
||||
$data = \IPS\Redis::i()->decode( $results[ $i++ ] );
|
||||
}
|
||||
catch( \RedisException $e )
|
||||
{
|
||||
$data = NULL;
|
||||
}
|
||||
}
|
||||
/* login_type must be cast as an integer or else anonymous state can be lost when adjustSessions() runs */
|
||||
elseif( $field === 'login_type' )
|
||||
|
||||
Reference in new issue
Block a user