Файл: admin/sources/classes/session/publicSessions.php
Строк: 1372
<?php
/**
* <pre>
* Invision Power Services
* IP.Board v3.3.3
* Public session handler
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
* </pre>
*
* @author $Author: bfarber $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.invisionpower.com/company/standards.php#license
* @package IP.Board
* @link http://www.invisionpower.com
* @since 26th January 2004
* @version $Revision: 10721 $
*
*/
if ( ! defined( 'IN_IPB' ) )
{
print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.";
exit();
}
class publicSessions extends ips_MemberRegistry
{
/**
* SSO object (if present)
*
* @access protected
* @var object
*/
protected $sso;
/**
* User agent trimmed
*
* @access protected
* @var string
*/
protected $_userAgent;
/**
* Session recorded flag
*
* @var boolean
* @access public
*/
public $session_recorded = FALSE;
/**
* Current time
*
* @var integer
* @access public
*/
public $time_now = 0;
/**
* Dead session id
*
* @var string
* @access public
*/
public $session_dead_id = null;
/**
* Current session id
*
* @var string
* @access public
*/
public $session_id = null;
/**
* Current session data
*
* @var array
* @access public
*/
public $session_data = array();
/**
* Type of session (either url or cookie)
*
* @var string
* @access public
*/
public $session_type = 'cookie';
/**
* Session member id
*
* @var integer
* @access public
*/
public $session_user_id = 0;
/**
* Session member password
*
* @var string
* @access public
*/
public $session_user_pass = "";
/**
* Update the session
*
* @var boolean
* @access public
*/
public $do_update = true;
/**
* Spider ua mapping
*
* @var array
* @access public
*/
public $bot_map = array();
/**
* Current application
*
* @var string
* @access public
*/
public $current_appcomponent;
/**
* Current module
*
* @var string
* @access public
*/
public $current_module;
/**
* Current section
*
* @var string
* @access public
*/
public $current_section;
/**
* Registry object
*
* @access protected
* @var object
*/
protected $registry;
/**
* Database object
*
* @access protected
* @var object
*/
protected $DB;
/**
* Settings object
*
* @access protected
* @var object
*/
protected $settings;
/**
* Request object
*
* @access protected
* @var object
*/
protected $request;
/**
* Language object
*
* @access protected
* @var object
*/
protected $lang;
/**
* Cache object
*
* @access protected
* @var object
*/
protected $cache;
/**
* Sessions to be destroyed
*
* @access protected
* @var array
*/
protected $_sessionsToKill = array();
/**
* Sessions to be updated
*
* @access protected
* @var array
*/
protected $_sessionsToSave = array();
/**
* Session data of the session that didn't authorize
*
* @access protected
* @var array
*/
protected $_failedAuthorizationSessionData = array();
/**
* Delete sessions immediately?
*
* @access protected
* @var boolean
*/
protected $_deleteNow;
/**
* Session Query Override Keys
* Allows one to override a session value
* Useful for overriding variables that are not set up when the session -> _getLocationSettings is run
*
* So to populate 'location_key_1' later in script execution:
* You'd use:
* ipsRegistry::member()->sessionClass()->addQueryKey( 'location_key_1', ipsRegistry::$request['f'] );
*
* @access protected
* @var array
*/
protected $_queryOverride = array();
/**
* Constructor :: Authorizes the session
*
* @param boolean $noAutoParsingSessions No auto parsing of sessions - set as true when using API-like methods
* @return @e mixed Void normally, but can print error message
*/
public function __construct( $noAutoParsingSessions=false )
{
/* Make object */
$this->registry = ipsRegistry::instance();
$this->DB = $this->registry->DB();
$this->settings =& $this->registry->fetchSettings();
$this->request =& $this->registry->fetchRequest();
$this->cache = $this->registry->cache();
$this->caches =& $this->registry->cache()->fetchCaches();
$this->_member = self::instance();
$this->_memberData =& self::instance()->fetchMemberData();
/* Delete immediately */
$this->_deleteNow = true;
/**
* If the sso.php file is present in this folder, we'll load it.
* This file can be used to easily integrate single-sign on in
* situations where you need to check session data
*/
if( is_file( IPS_ROOT_PATH . '/sources/classes/session/sso.php' ) )
{
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . '/sources/classes/session/sso.php', 'ssoSessionExtension' );
if( class_exists( $classToLoad ) )
{
$this->sso = new $classToLoad( $this->registry );
}
}
//-----------------------------------------
// INIT
//-----------------------------------------
$cookie = array();
$this->_userAgent = substr( $this->_member->user_agent, 0, 200 );
//-----------------------------------------
// Fix up app / section / module
//-----------------------------------------
$this->current_appcomponent = IPS_APP_COMPONENT;
$this->current_module = IPSText::alphanumericalClean( $this->request['module'] );
$this->current_section = IPSText::alphanumericalClean( $this->request['section'] );
$this->settings['session_expiration'] = ( $this->settings['session_expiration'] ) ? $this->settings['session_expiration'] : 3600;
//-----------------------------------------
// Return as guest if running a task
//-----------------------------------------
if ( IPS_IS_TASK )
{
self::$data_store = IPSMember::setUpGuest();
self::$data_store['last_activity'] = time();
self::$data_store['last_visit'] = time();
return true;
}
/* Not auto parsing sessions? */
if ( $noAutoParsingSessions === true )
{
return true;
}
//-----------------------------------------
// no new headers if we're simply viewing an attachment..
//-----------------------------------------
if ( $this->request['section'] == 'attach' )
{
$this->settings['no_print_header'] = 1 ;
}
//-----------------------------------------
// no new headers if we're updating chat
//-----------------------------------------
if ( ( IPS_IS_AJAX && ( $this->request['section'] != 'login' && $this->request['section'] != 'skin' ) )
OR $this->request['section'] == 'attach'
OR $this->request['section'] == 'captcha' )
{
$this->settings['no_print_header'] = 1 ;
$this->do_update = 0;
}
//-----------------------------------------
// Continue!
//-----------------------------------------
$cookie['session_id'] = IPSCookie::get('session_id');
$cookie['member_id'] = IPSCookie::get('member_id');
$cookie['pass_hash'] = IPSCookie::get('pass_hash');
if ( $cookie['session_id'] && empty( $this->request['_nsc'] ) )
{
$this->getSession($cookie['session_id']);
$this->session_type = 'cookie';
}
elseif ( !empty( $this->request['s'] ) )
{
$this->getSession($this->request['s']);
$this->session_type = 'url';
}
else
{
$this->session_id = 0;
$this->session_type = 'url';
}
//-----------------------------------------
// Do we have a valid session ID?
//-----------------------------------------
if ( $this->session_id )
{
//-----------------------------------------
// We've checked the IP addy and browser, so we can assume that this is
// a valid session.
//-----------------------------------------
if ( ! empty($this->session_user_id) )
{
//-----------------------------------------
// It's a member session, so load the member.
//-----------------------------------------
self::setMember( $this->session_user_id );
//-----------------------------------------
// Did we get a member?
//-----------------------------------------
if ( ( ! self::$data_store['member_id']) or (self::$data_store['member_id'] == 0) )
{
$this->_updateGuestSession();
/**
* If we have an SSO object, run it for the update guest session call
*/
if( is_object( $this->sso ) AND method_exists( $this->sso, 'checkSSOForGuest' ) )
{
$this->sso->checkSSOForGuest( 'update' );
}
}
else
{
$this->_updateMemberSession();
/**
* If we have an SSO object, run it for the update member call
*/
if( is_object( $this->sso ) AND method_exists( $this->sso, 'checkSSOForMember' ) )
{
$this->sso->checkSSOForMember( 'update' );
}
}
}
else
{
$this->_updateGuestSession();
/**
* If we have an SSO object, run it for the update guest call
*/
if( is_object( $this->sso ) AND method_exists( $this->sso, 'checkSSOForGuest' ) )
{
$this->sso->checkSSOForGuest( 'update' );
}
}
}
else
{
//-----------------------------------------
// We didn't have a session, or the session didn't validate
// Do we have cookies stored?
//-----------------------------------------
if ( $cookie['member_id'] != "" and $cookie['pass_hash'] != "" )
{
//-----------------------------------------
// Load member
//-----------------------------------------
self::setMember( $cookie['member_id'] );
//-----------------------------------------
// INIT log in key stuff
//-----------------------------------------
$_ok = 1;
$_days = 0;
$_sticky = 1;
$_time = ( $this->settings['login_key_expire'] ) ? ( time() + ( intval($this->settings['login_key_expire']) * 86400 ) ) : 0;
if ( ( ! self::$data_store['member_id']) or (self::$data_store['member_id'] == 0) )
{
$this->_createGuestSession();
/**
* If we have an SSO object, run it for the create guest call
*/
if( is_object( $this->sso ) AND method_exists( $this->sso, 'checkSSOForGuest' ) )
{
$this->sso->checkSSOForGuest( 'create' );
}
}
else
{
if ( self::$data_store['member_login_key'] == $cookie['pass_hash'] )
{
//-----------------------------------------
// Key expired?
//-----------------------------------------
if ( $this->settings['login_key_expire'] )
{
$_sticky = 0;
$_days = $this->settings['login_key_expire'];
if ( time() > self::$data_store['member_login_key_expire'] )
{
$_ok = 0;
}
}
if ( $_ok == 1 )
{
$this->_createMemberSession();
/**
* If we have an SSO object, run it for the create member call
*/
if( is_object( $this->sso ) AND method_exists( $this->sso, 'checkSSOForMember' ) )
{
$this->sso->checkSSOForMember( 'create' );
}
}
else
{
self::setMember(0);
$this->_createGuestSession();
/**
* If we have an SSO object, run it for the create guest call
*/
if( is_object( $this->sso ) AND method_exists( $this->sso, 'checkSSOForGuest' ) )
{
$this->sso->checkSSOForGuest( 'create' );
}
}
}
else
{
self::setMember(0);
$this->_createGuestSession();
/**
* If we have an SSO object, run it for the create guest call
*/
if( is_object( $this->sso ) AND method_exists( $this->sso, 'checkSSOForGuest' ) )
{
$this->sso->checkSSOForGuest( 'create');
}
}
}
}
else
{
$this->_createGuestSession();
/**
* If we have an SSO object, run it for the create guest call
*/
if( is_object( $this->sso ) AND method_exists( $this->sso, 'checkSSOForGuest' ) )
{
$this->sso->checkSSOForGuest( 'create' );
}
}
}
//-----------------------------------------
// Knock out Google Web Accelerator
//-----------------------------------------
if( ipsRegistry::$settings['disable_prefetching'] )
{
if ( my_getenv('HTTP_X_MOZ') AND strstr( strtolower(my_getenv('HTTP_X_MOZ')), 'prefetch' ) AND self::$data_store['member_id'] )
{
if ( isset( $_SERVER['SERVER_PROTOCOL'] ) AND strstr( $_SERVER['SERVER_PROTOCOL'], '/1.0' ) )
{
@header('HTTP/1.0 403 Forbidden');
}
else
{
@header('HTTP/1.1 403 Forbidden');
}
@header("Cache-Control: no-cache, must-revalidate, max-age=0");
@header("Expires: 0");
@header("Pragma: no-cache");
print "Прекеширование страниц форума запрещено. Если у вас включен Google Accelerator, пожалуйста отключите его";
exit();
}
}
//-----------------------------------------
// Still no member id and not a bot?
//-----------------------------------------
if ( empty( self::$data_store['member_id'] ) AND ! $this->_member->is_not_human )
{
self::setMember(0);
self::$data_store['last_activity'] = time();
$this->request['last_visit'] = time();
}
//-----------------------------------------
// Set a session ID cookie
//-----------------------------------------
$this->_member->session_type = $this->session_type;
$this->_member->session_id = $this->session_id;
IPSCookie::set("session_id", $this->session_id, -1);
}
/**
* Return current session data to be stored
*
* @return @e array
*/
public function returnCurrentSession()
{
$return = $this->_sessionsToSave[ $this->session_id ];
if( count($this->_queryOverride[ $this->session_id ]) )
{
$return = is_array($return) ? array_merge( $return, $this->_queryOverride[ $this->session_id ] ) : ( is_array($this->_queryOverride[ $this->session_id ]) ? $this->_queryOverride[ $this->session_id ] : array() );
}
return $return;
}
/**
* Assign a key with a value
*
* @access public
* @param string Key
* @param string Value
* @param string [Session ID, will default to current session if none found]
* @return @e void
*/
public function addQueryKey( $key, $value, $sessionID='' )
{
$sessionID = ( $sessionID ) ? substr( IPSText::alphanumericalClean( $sessionID, '_=' ), 0, 32 ) : $this->session_id;
if ( $key )
{
$this->_queryOverride[ $sessionID ][ $key ] = $value;
}
}
/**
* Update a member's session
*
* @access protected
* @return boolean Updated successfully
*/
protected function _updateMemberSession()
{
//-----------------------------------------
// Make sure we have a session id.
//-----------------------------------------
if ( ! $this->session_id )
{
$this->_createMemberSession();
return true;
}
if ( ! self::$data_store['member_id'] )
{
self::setMember(0);
$this->_createGuestSession();
return false;
}
if ( ( time() - self::$data_store['last_activity'] ) > $this->settings['session_expiration'] )
{
// Session is expired - create new session
$this->_createMemberSession();
return true;
}
//-----------------------------------------
// Get module settings
//-----------------------------------------
$vars = $this->_getLocationSettings();
//-----------------------------------------
// Still update?
//-----------------------------------------
if ( ! $this->do_update )
{
return true;
}
IPSDebug::addMessage( "Updating MEMBER session: " . $this->session_data['id'] );
$uAgent = $this->_processUserAgent( 'update' );
IPSCookie::set( "pass_hash", self::$data_store['member_login_key'], ( $this->settings['login_key_expire'] ? 0 : 1 ), $this->settings['login_key_expire'] );
/* Save the last click */
self::$data_store['last_click'] = $this->session_data['running_time'];
//-----------------------------------------
// Set up data
//-----------------------------------------
$sessionData = array(
'member_name' => self::$data_store['members_display_name'],
'seo_name' => IPSMember::fetchSeoName( self::$data_store ),
'member_id' => intval(self::$data_store['member_id']),
'member_group' => self::$data_store['member_group_id'],
'login_type' => IPSMember::isLoggedInAnon( self::$data_store ),
'running_time' => IPS_UNIX_TIME_NOW,
'in_error' => 0,
'current_appcomponent' => $this->current_appcomponent,
'current_module' => $this->current_module,
'current_section' => $this->current_section,
'location_1_type' => isset($vars['location_1_type']) ? $vars['location_1_type'] : '',
'location_1_id' => isset($vars['location_1_id']) ? intval($vars['location_1_id']) : 0,
'location_2_type' => isset($vars['location_2_type']) ? $vars['location_2_type'] : '',
'location_2_id' => isset($vars['location_2_id']) ? intval($vars['location_2_id']) : 0,
'location_3_type' => isset($vars['location_3_type']) ? $vars['location_3_type'] : '',
'location_3_id' => isset($vars['location_3_id']) ? intval($vars['location_3_id']) : 0,
'uagent_key' => $uAgent['uagent_key'],
'uagent_version' => $uAgent['uagent_version'],
'uagent_type' => $uAgent['uagent_type'],
);
/* Before this function is called, a guest is set up via ipsRegistry::setMember(0)
We want to override this now to provide search engine settings for the 'member' */
if ( $uAgent['uagent_type'] == 'search' )
{
self::setSearchEngine( $uAgent );
/* Reset some data */
$this->session_type = 'cookie';
//$this->session_id = "";
}
/* Did the user agent change? */
if ( ! empty( $uAgent['_browser'] ) )
{
$sessionData['browser'] = $uAgent['_browser'];
unset( $uAgent['_browser'] );
foreach( $uAgent as $key => $value )
{
$this->session_data[ $key ] = $value;
}
}
/* Set type */
self::$data_store['_sessionType'] = 'update';
$this->_sessionsToSave[ $this->session_id ] = $sessionData;
return true;
}
/**
* Update a guest's session
*
* @access protected
* @return boolean Updated successfully
*/
protected function _updateGuestSession()
{
//-----------------------------------------
// INIT
//-----------------------------------------
$memberName = '';
$memberGroup = $this->settings['guest_group'];
$loginType = intval($this->caches['group_cache'][ $this->settings['guest_group'] ]['g_hide_online_list']);
//-----------------------------------------
// Make sure we have a session id.
//-----------------------------------------
if ( ! $this->session_id )
{
$this->_createGuestSession();
return false;
}
//-----------------------------------------
// Get module settings
//-----------------------------------------
$vars = $this->_getLocationSettings();
//-----------------------------------------
// Still update?
//-----------------------------------------
if ( ! $this->do_update )
{
return false;
}
$uAgent = $this->_processUserAgent( 'update' );
//-----------------------------------------
// Is it a search engine?
//-----------------------------------------
if ( $uAgent['uagent_type'] == 'search' )
{
$this->session_id = substr( $uAgent['uagent_key'] . '=' . ( md5( uniqid( microtime(), true ) . $this->_member->ip_address . $this->_userAgent ) ) . '_session', 0, 60 );
$memberName = $uAgent['uagent_name'];
$memberGroup = $this->settings['guest_group'];
IPSDebug::addMessage( "Updating SEARCH ENGINE session: " . $this->session_data['id'] );
}
else
{
IPSDebug::addMessage( "Updating GUEST session: " . $this->session_data['id'] );
}
$this->DB->setDataType( 'member_name', 'string' );
$sessionData = array(
'member_name' => $memberName,
'member_id' => 0,
'member_group' => $memberGroup,
'login_type' => IPS_IS_SHELL ? 1 : 0,
'running_time' => IPS_UNIX_TIME_NOW,
'in_error' => 0,
'current_appcomponent' => $this->current_appcomponent,
'current_module' => $this->current_module,
'current_section' => $this->current_section,
'location_1_type' => isset($vars['location_1_type']) ? $vars['location_1_type'] : '',
'location_1_id' => isset($vars['location_1_id']) ? intval($vars['location_1_id']) : 0,
'location_2_type' => isset($vars['location_2_type']) ? $vars['location_2_type'] : '',
'location_2_id' => isset($vars['location_2_id']) ? intval($vars['location_2_id']) : 0,
'location_3_type' => isset($vars['location_3_type']) ? $vars['location_3_type'] : '',
'location_3_id' => isset($vars['location_3_id']) ? intval($vars['location_3_id']) : 0,
'uagent_key' => $uAgent['uagent_key'],
'uagent_version' => $uAgent['uagent_version'],
'uagent_type' => $uAgent['uagent_type'],
);
/* Before this function is called, a guest is set up via ipsRegistry::setMember(0)
We want to override this now to provide search engine settings for the 'member' */
if ( $uAgent['uagent_type'] == 'search' )
{
self::setSearchEngine( $uAgent );
/* Reset some data */
$this->session_type = 'cookie';
$this->session_data['id'] = $this->session_id;
}
/* Did the user agent change? */
if ( ! empty( $uAgent['_browser'] ) )
{
$sessionData['browser'] = $uAgent['_browser'];
unset( $uAgent['_browser'] );
foreach( $uAgent as $key => $value )
{
$this->session_data[ $key ] = $value;
}
}
/* Set type */
self::$data_store['_sessionType'] = 'update';
$this->_sessionsToSave[ $this->session_id ] = $sessionData;
return true;
}
/**
* Create a member session
*
* @access protected
* @return boolean Created successfully
*/
protected function _createMemberSession()
{
if (self::$data_store['member_id'])
{
//-----------------------------------------
// Remove the defunct sessions
//-----------------------------------------
$this->_destroySessions( "member_id=" . self::$data_store['member_id'] );
$this->session_id = md5( uniqid( microtime(), true ) . $this->_member->ip_address . $this->_userAgent );
//-----------------------------------------
// Get module settings
//-----------------------------------------
$vars = $this->_getLocationSettings();
//-----------------------------------------
// Still update?
//-----------------------------------------
if ( ! $this->do_update )
{
return false;
}
IPSDebug::addMessage( "Creating MEMBER session: " . $this->session_id );
//-----------------------------------------
// Get useragent stuff
//-----------------------------------------
$uAgent = $this->_processUserAgent( 'create' );
//-----------------------------------------
// Insert the new session
//-----------------------------------------
$data = array(
'id' => $this->session_id,
'member_name' => self::$data_store['members_display_name'],
'seo_name' => IPSMember::fetchSeoName( self::$data_store ),
'member_id' => intval(self::$data_store['member_id']),
'member_group' => self::$data_store['member_group_id'],
'login_type' => IPSMember::isLoggedInAnon( self::$data_store ),
'running_time' => IPS_UNIX_TIME_NOW,
'ip_address' => $this->_member->ip_address,
'browser' => $this->_userAgent,
'in_error' => 0,
'current_appcomponent' => $this->current_appcomponent,
'current_module' => $this->current_module,
'current_section' => $this->current_section,
'location_1_type' => isset($vars['location_1_type']) ? $vars['location_1_type'] : '',
'location_1_id' => isset($vars['location_1_id']) ? intval($vars['location_1_id']) : 0,
'location_2_type' => isset($vars['location_2_type']) ? $vars['location_2_type'] : '',
'location_2_id' => isset($vars['location_2_id']) ? intval($vars['location_2_id']) : 0,
'location_3_type' => isset($vars['location_3_type']) ? $vars['location_3_type'] : '',
'location_3_id' => isset($vars['location_3_id']) ? intval($vars['location_3_id']) : 0,
'uagent_key' => $uAgent['uagent_key'],
'uagent_version' => $uAgent['uagent_version'],
'uagent_type' => $uAgent['uagent_type'],
'uagent_bypass' => intval( $uAgent['uagent_bypass'] ) );
$this->DB->setDataType( 'member_name', 'string' );
$this->DB->insert( 'sessions', $data, true );
//-----------------------------------------
// Force data
//-----------------------------------------
$this->session_data = array( 'uagent_key' => $uAgent['uagent_key'],
'uagent_version' => $uAgent['uagent_version'],
'uagent_type' => $uAgent['uagent_type'],
'uagent_bypass' => $uAgent['uagent_bypass'],
'id' => $data['id'] );
//-----------------------------------------
// If this is a member, update their last visit times, etc.
//-----------------------------------------
if ( time() - self::$data_store['last_activity'] > $this->settings['session_expiration'] )
{
//-----------------------------------------
// Reset the topics read cookie..
//-----------------------------------------
list( $be_anon, $loggedin ) = explode( '&', self::$data_store['login_anonymous'] );
$update = array( 'login_anonymous' => "{$be_anon}&1",
'last_visit' => self::$data_store['last_activity'],
'last_activity' => IPS_UNIX_TIME_NOW
);
//-----------------------------------------
// Fix up the last visit/activity times.
//-----------------------------------------
self::$data_store['last_visit'] = self::$data_store['last_activity'];
self::$data_store['last_activity'] = time();
}
IPSCookie::set( "pass_hash", self::$data_store['member_login_key'], ( $this->settings['login_key_expire'] ? 0 : 1 ), $this->settings['login_key_expire'] );
$update['member_login_key_expire'] = time() + ( $this->settings['login_key_expire'] * 86400 );
IPSMember::save( self::$data_store['member_id'], array( 'core' => $update ) );
}
else
{
$this->_createGuestSession();
}
/* Before this function is called, a guest is set up via ipsRegistry::setMember(0)
We want to override this now to provide search engine settings for the 'member' */
if ( $uAgent['uagent_type'] == 'search' )
{
self::setSearchEngine( $uAgent );
/* Reset some data */
$this->session_type = 'cookie';
//$this->session_id = "";
}
/* Set type */
self::$data_store['_sessionType'] = 'create';
return true;
}
/**
* Create a guest session
*
* @access protected
* @return boolean Created successfully
*/
protected function _createGuestSession()
{
//-----------------------------------------
// INIT
//-----------------------------------------
$query = array();
$memberName = '';
$memberGroup = $this->settings['guest_group'];
$loginType = 0;
//-----------------------------------------
// Remove the defunct sessions
//-----------------------------------------
if ( $this->session_dead_id )
{
$query[] = "id='" . $this->session_dead_id . "'";
}
if ( $this->settings['match_ipaddress'] == 1 )
{
$query[] = "ip_address='" . $this->_member->ip_address . "'";
}
$this->session_id = md5( uniqid( microtime(), true ) . $this->_member->ip_address . $this->_userAgent );
//-----------------------------------------
// Get module settings
//-----------------------------------------
$vars = $this->_getLocationSettings();
//-----------------------------------------
// Still update?
//-----------------------------------------
if ( ! $this->do_update )
{
return false;
}
$uAgent = $this->_processUserAgent( 'create' );
//-----------------------------------------
// Is it a search engine?
//-----------------------------------------
if ( $uAgent['uagent_type'] == 'search' )
{
$this->session_id = substr( $uAgent['uagent_key'] . '=' . ( md5( uniqid( microtime(), true ) . $this->_member->ip_address . $this->_userAgent ) ) . '_session', 0, 60 );
$memberName = $uAgent['uagent_name'];
$memberGroup = $this->settings['guest_group'];
IPSDebug::addMessage( "Creating SEARCH ENGINE session: " . $this->session_id );
$query[] = "id='" . $this->session_id . "'";
}
else
{
IPSDebug::addMessage( "Creating GUEST session: " . $this->session_id );
}
//-----------------------------------------
// Got anything to remove?
//-----------------------------------------
if ( count( $query ) )
{
$this->_destroySessions( implode( " OR ", $query ) );
}
//-----------------------------------------
// Insert the new session
//-----------------------------------------
$data = array(
'id' => $this->session_id,
'member_name' => $memberName,
'member_id' => 0,
'member_group' => $memberGroup,
'login_type' => IPS_IS_SHELL ? 1 : 0,
'running_time' => IPS_UNIX_TIME_NOW,
'ip_address' => $this->_member->ip_address,
'browser' => substr( $this->_member->user_agent, 0, 200 ),
'in_error' => 0,
'current_appcomponent' => $this->current_appcomponent,
'current_module' => $this->current_module,
'current_section' => $this->current_section,
'location_1_type' => isset($vars['location_1_type']) ? $vars['location_1_type'] : '',
'location_1_id' => isset($vars['location_1_id']) ? intval($vars['location_1_id']) : 0,
'location_2_type' => isset($vars['location_2_type']) ? $vars['location_2_type'] : '',
'location_2_id' => isset($vars['location_2_id']) ? intval($vars['location_2_id']) : 0,
'location_3_type' => isset($vars['location_3_type']) ? $vars['location_3_type'] : '',
'location_3_id' => isset($vars['location_3_id']) ? intval($vars['location_3_id']) : 0,
'uagent_key' => $uAgent['uagent_key'],
'uagent_version' => $uAgent['uagent_version'],
'uagent_type' => $uAgent['uagent_type'],
'uagent_bypass' => intval( $uAgent['uagent_bypass'] ) );
$this->DB->setDataType( 'member_name', 'string' );
$this->DB->insert( 'sessions', $data, true );
//-----------------------------------------
// Force data
//-----------------------------------------
$this->session_data = array( 'uagent_key' => $uAgent['uagent_key'],
'uagent_version' => $uAgent['uagent_version'],
'uagent_type' => $uAgent['uagent_type'],
'uagent_bypass' => $uAgent['uagent_bypass'],
'id' => $data['id'] );
/* Before this function is called, a guest is set up via ipsRegistry::setMember(0)
We want to override this now to provide search engine settings for the 'member' */
if ( $uAgent['uagent_type'] == 'search' )
{
self::setSearchEngine( $uAgent );
/* Reset some data */
$this->session_type = 'cookie';
//$this->session_id = "";
}
/* Set type */
self::$data_store['_sessionType'] = 'create';
return true;
}
/**
* Converts a guest session to a member session
*
* @access public
* @param array Array of incoming data (member_id, member_name, member_group, login_type)
* @param array Optional array of member data (prevents having to reload it)
* @return string Current session ID
*/
public function convertGuestToMember( $data, $member=array() )
{
/* Got a session at all? */
if ( empty( $this->session_id ) )
{
$this->_createGuestSession();
$this->session_id = $this->session_data['id'];
}
/* Delete old sessions */
$this->_destroySessions( "ip_address='" . $this->_member->ip_address . "' AND id != '{$this->session_id}'" );
/* Fetch member */
if ( ! $member['member_id'] )
{
$member = IPSMember::load( $data['member_id'], 'core' );
}
/* Update this session directly */
$this->DB->update( 'sessions', array( 'member_name' => $member['members_display_name'],
'seo_name' => $member['members_seo_name'],
'member_id' => $member['member_id'],
'running_time' => time(),
'member_group' => $member['member_group_id'],
'login_type' => intval($data['login_type']) ), "id='" . $this->session_id . "'", TRUE );
/* Remove from update and delete array */
unset( $this->_sessionsToSave[ $this->session_id ] );
unset( $this->_sessionsToKill[ $this->session_id ] );
$update = array( 'last_activity' => time() );
if ( $member['last_activity'] )
{
$update['last_visit'] = $member['last_activity'];
}
/* Make sure last activity and last visit are up to date */
IPSMember::save( $data['member_id'], array( 'core' => $update ) );
/* Set cookie */
IPSCookie::set( "session_id", $this->session_id, -1 );
IPSDebug::addLogMessage( "convertGuestToMember: {$data['member_id']}, {$this->session_id} " . serialize( $data ), 'sessions-' . $this->_memberData['member_id'] );
/* Set type */
self::$data_store['_sessionType'] = 'update';
return $this->session_id;
}
/**
* Converts a member session to a guest session
*
* @access public
* @return string Current session ID
*/
public function convertMemberToGuest()
{
/* Delete old sessions */
$this->_destroySessions( "ip_address='" . $this->_member->ip_address . "' AND id != '{$this->session_id}'" );
/* Update this session directly */
$data = array( 'member_name' => '',
'seo_name' => '',
'member_id' => 0,
'running_time' => time(),
'member_group' => $this->settings['guest_group'] );
$this->DB->update( 'sessions', $data, "id='" . $this->session_id . "'", TRUE );
/* Remove from update and delete array */
unset( $this->_sessionsToSave[ $this->session_id ] );
unset( $this->_sessionsToKill[ $this->session_id ] );
/* Set cookie */
IPSCookie::set( "session_id", $this->session_id, -1 );
IPSDebug::addLogMessage( "convertMemberToGuest: {$this->session_id} " . serialize( $data ), 'sessions-' . $this->_memberData['member_id'] );
/* Set type */
self::$data_store['_sessionType'] = 'update';
return $this->session_id;
}
/**
* Kill sessions
*
* @access protected
* @param string Any extra WHERE stuff
* @return @e void
*/
protected function _destroySessions( $where='' )
{
if ( ! $where )
{
$where = 'running_time < ' . ( IPS_UNIX_TIME_NOW - $this->settings['session_expiration'] );
}
//-----------------------------------------
// Grab session data to delete on destruct
//-----------------------------------------
if ( $this->_deleteNow )
{
$this->DB->delete( 'sessions', $where );
}
else
{
$this->DB->build( array( 'select' => '*',
'from' => 'sessions',
'where' => $where ) );
$this->DB->execute();
while( $row = $this->DB->fetch() )
{
$this->_sessionsToKill[ $row['id'] ] = $row;
}
IPSDebug::addLogMessage( "_destroySessions: $where", 'sessions-' . $this->_memberData['member_id'] );
}
}
/**
* Retrive a session based on a session id
*
* @access public
* @param string Session id
* @return boolean Retrieved successfully
*/
public function getSession( $session_id="" )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$result = array();
$session_id = substr( IPSText::alphanumericalClean( $session_id, '_=' ), 0, 60 );
if ( $session_id )
{
$_session = $this->DB->buildAndFetch( array( 'select' => '*',
'from' => 'sessions',
'where' => "id='" . $session_id . "'") );
if ( $_session['id'] )
{
/* Kill any long running search thread... */
if( $this->settings['kill_search_after'] )
{
if( $_session['search_thread_id'] AND $_session['search_thread_time'] AND $_session['search_thread_time'] < (time() - $this->settings['kill_search_after']) )
{
$this->DB->return_die = true;
$this->DB->kill( $_session['search_thread_id'] );
$this->DB->return_die = false;
$this->DB->update( 'sessions', array( 'search_thread_id' => 0, 'search_thread_time' => 0 ), "id='" . $session_id . "'" );
}
}
/* Test for browser.... */
if ( $this->settings['match_browser'] AND !$this->request['section'] == 'attach' )
{
if ( $_session['browser'] != $this->_userAgent )
{
return $this->_killAuthorizeAttempt( $session_id, $_session );
}
}
/* Test for IP Address... */
if ( $this->settings['match_ipaddress'] )
{
if ( $_session['ip_address'] != $this->_member->ip_address )
{
return $this->_killAuthorizeAttempt( $session_id, $_session );
}
}
/* Still here? */
return $this->_allowAuthorizeAttempt( $session_id, $_session );
}
else
{
return $this->_killAuthorizeAttempt( $session_id, array() );
}
}
else
{
return $this->_killAuthorizeAttempt( '', array() );
}
}
/**
* Kill This Session
*
* @access protected
* @param string Session ID
* @param bool
*/
protected function _killAuthorizeAttempt( $session_id, $session_data )
{
$this->_failedAuthorizationSessionData = $session_data;
$this->session_dead_id = $session_id;
$this->session_id = 0;
$this->session_user_id = 0;
$this->session_data = array();
IPSDebug::addLogMessage( "Authorization attempt FAILED: Session ID={$session_id}, member ID=0", 'sessions-failed' );
return false;
}
/**
* Allow This Session
*
* @access protected
* @param string Session ID
* @param bool
*/
protected function _allowAuthorizeAttempt( $session_id, $session_data )
{
$this->session_data = $session_data;
$this->session_id = $this->session_data['id'];
$this->session_user_id = $this->session_data['member_id'];
$this->last_click = $this->session_data['running_time'];
IPSDebug::addLogMessage( "Authorization attempt successful: Session ID={$session_id}, member ID={$this->session_data['member_id']} ", 'sessions-' . $this->session_data['member_id'] );
return true;
}
/**
* Grab the user agent from the DB if required
*
* @access protected
* @param string Type of session (update/create)
* @return array Array of user agent info from the DB
*/
protected function _processUserAgent( $type='update' )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$uAgent = array( 'uagent_key' => '__NONE__',
'uagent_version' => 0,
'uagent_name' => '',
'uagent_type' => '',
'uagent_bypass' => 0 );
//-----------------------------------------
// Do we need to update?
//-----------------------------------------
if ( IPSCookie::get('mobileApp') == 'true' )
{
$uAgent = array( 'uagent_id' => -1,
'uagent_key' => 'ipsMobileLegacy',
'uagent_name' => 'IPS Mobile Legacy',
'uagent_type' => 'mobileAppLegacy',
'uagent_version' => 1 );
}
else if ( empty( $this->session_data['uagent_key'] ) OR $this->session_data['uagent_key'] == '__NONE__' OR ( $this->_userAgent != $this->session_data['browser'] ) )
{
IPSDebug::addMessage( "Retreiving user agent information from the DB" );
//-----------------------------------------
// Get useragent stuff
//-----------------------------------------
if ( ! $this->registry->isClassLoaded( 'userAgentFunctions' ) )
{
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/useragents/userAgentFunctions.php', 'userAgentFunctions' );
$this->registry->setClass( 'userAgentFunctions', new $classToLoad( $this->registry ) );
}
$uAgent = $this->registry->getClass( 'userAgentFunctions' )->findUserAgentID( $this->_member->user_agent );
if ( $uAgent['uagent_key'] === NULL )
{
$uAgent = array( 'uagent_key' => '__NONE__',
'uagent_version' => 0,
'uagent_name' => '',
'uagent_type' => '',
'uagent_bypass' => 0 );
}
else
{
$uAgent['uagent_bypass'] = 0;
}
/* Update browser */
$uAgent['_browser'] = $this->_userAgent;
}
else
{
$uAgent['uagent_key'] = $this->session_data['uagent_key'];
$uAgent['uagent_version'] = $this->session_data['uagent_version'];
$uAgent['uagent_type'] = $this->session_data['uagent_type'];
$uAgent['uagent_bypass'] = $this->session_data['uagent_bypass'];
/* For search engines only */
$uAgent['uagent_name'] = $this->session_data['member_name'];
}
return $uAgent;
}
/**
* Retrive session location settings from plugin files
*
* @access protected
* @return array Location settings
*/
protected function _getLocationSettings()
{
/* Init vars */
$return = array();
/* Got an app? */
if ( IPS_APP_COMPONENT )
{
$filename = IPSLib::getAppDir( IPS_APP_COMPONENT ) . '/extensions/coreExtensions.php';
if ( is_file( $filename ) )
{
$toload = IPSLib::loadLibrary( $filename, 'publicSessions__' . IPS_APP_COMPONENT, IPS_APP_COMPONENT );
if ( class_exists( $toload ) )
{
$loader = new $toload;
$return = $loader->getSessionVariables();
}
}
}
if( defined('NO_SESSION_UPDATE') AND NO_SESSION_UPDATE )
{
$this->do_update = 0;
}
return $return;
}
/**
* Fetch session data that is to be destroyed
*
* @access public
* @return array
*/
public function fetchDestroyedSessionsAsArray()
{
return $this->_sessionsToKill;
}
/**
* Store an inline message
* @param string $text
*/
public function setInlineMessage( $text )
{
$this->DB->insert( 'core_inline_messages', array( 'inline_msg_date' => IPS_UNIX_TIME_NOW,
'inline_msg_content' => $text ) );
$inline_msg_id = $this->DB->getInsertId();
$this->addQueryKey( 'session_msg_id', $inline_msg_id );
}
/**
* Get an inline message
* @return string The Message of course.
*/
public function getInlineMessage()
{
if ( ! empty( $this->session_data['session_msg_id'] ) )
{
if ( empty( $this->session_data['_inlineMsg'] ) )
{
$inlineMsg = $this->DB->buildAndFetch( array( 'select' => 'inline_msg_content',
'from' => 'core_inline_messages',
'where' => 'inline_msg_id=' . intval( $this->session_data['session_msg_id'] ) ) );
if ( ! empty( $inlineMsg['inline_msg_content'] ) )
{
$this->session_data['_inlineMsg'] = $inlineMsg['inline_msg_content'];
$this->addQueryKey( 'session_msg_id', 0 );
return $this->session_data['_inlineMsg'];
}
}
}
return false;
}
/**
* Updates a session
*
* @access public
* @param string Session id
* @param int Member ID
* @param array Array of information to update
* @return @e void Updates session_data array and member data array
*/
public function updateSession( $sessionID, $memberID, $data )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$memberID = intval( $memberID );
$sessionID = substr( IPSText::alphanumericalClean( $sessionID, '_=' ), 0, 60 );
$_data = array();
$_ignore = array( 'id',
'member_id',
'ip_address',
'browser' );
$remap = array( 'uagent_bypass' => 'userAgentBypass' );
//-----------------------------------------
// Remove what we can't update...
//-----------------------------------------
foreach( $data as $key => $value )
{
if ( in_array( $key, $_ignore ) )
{
continue;
}
$_data[ $key ] = $value;
/* Update our own session? */
if ( $memberID && ( $memberID == $this->_memberData['member_id'] ) )
{
$this->session_data[ $key ] = $value;
if ( in_array( $key, array_keys( $remap ) ) )
{
$this->_memberData[ $remap[ $key ] ] = $value;
}
else
{
$this->_memberData[ $key ] = $value;
}
}
}
/* Now, do we have a session already saved ready for.. er..saving? */
if ( isset( $this->_sessionsToSave[ $sessionID ] ) AND $this->_sessionsToSave[ $sessionID ]['member_id'] == $memberID )
{
/* Just update the keys, then...*/
foreach( $_data as $k => $v )
{
$this->_sessionsToSave[ $sessionID ][ $k ] = $v;
}
}
else
{
/* Add to the list.. */
$this->_sessionsToSave[ $sessionID ] = $_data;
}
IPSDebug::addLogMessage( "Session updated - " . $sessionID . " - " . serialize( $this->_sessionsToSave ), 'sessions-' . $this->_memberData['member_id'] );
}
/**
* Manual destructor called by ips_MemberRegistry::__myDestruct()
* Gives us a chance to do anything we need to do before other
* classes are culled
*
* @access public
* @return @e void
*/
public function __myDestruct()
{
$_updated = 0;
$_deleted = 0;
/* Update sessions... */
if ( is_array( $this->_sessionsToSave ) AND count( $this->_sessionsToSave ) )
{
foreach( $this->_sessionsToSave as $sessionID => $data )
{
if ( $sessionID )
{
if ( isset( $this->_queryOverride[ $sessionID ] ) AND is_array( $this->_queryOverride[ $sessionID ] ) AND count( $this->_queryOverride[ $sessionID ] ) )
{
foreach( $this->_queryOverride[ $sessionID ] as $field => $value )
{
if ( isset( $this->_queryOverride[ $sessionID ][ $field ] ) )
{
$data[ $field ] = $this->_queryOverride[ $sessionID ][ $field ];
}
}
}
$this->DB->setDataType( 'member_name', 'string' );
$this->DB->update( 'sessions', $data, "id='" . $sessionID . "'", true );
}
}
}
/* Remove sessions */
if ( is_array( $this->_sessionsToKill ) AND count( $this->_sessionsToKill ) )
{
$_c = count( $this->_sessionsToKill );
$this->DB->delete( 'sessions', "id IN('" . implode( "','", array_keys( $this->_sessionsToKill ) ) . "')" );
}
IPSDebug::addLogMessage( get_class( $this ) . ": " . count( $this->_sessionsToSave ) . " sessions updated, " . count( $this->_sessionsToKill ) . " sessions deleted", 'sessions-' . $this->_memberData['member_id'] );
}
}