Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Sat, Feb 22, 12:06 AM

in-portal

Index: branches/5.2.x/core/kernel/session/session_storage.php
===================================================================
--- branches/5.2.x/core/kernel/session/session_storage.php (revision 16653)
+++ branches/5.2.x/core/kernel/session/session_storage.php (revision 16654)
@@ -1,528 +1,552 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
/**
* Implements Session Store in the Database
*
*/
class SessionStorage extends kDBBase {
/**
* Reference to session
*
* @var Session
* @access protected
*/
protected $Session = null;
var $Expiration;
var $SessionTimeout = 0;
var $DirectVars = Array ();
var $ChangedDirectVars = Array ();
var $PersistentVars = Array ();
+ /**
+ * Default persistent vars
+ *
+ * @var array
+ */
+ protected $defaultPersistentVars = array();
+
var $OriginalData = Array ();
var $TimestampField;
var $SessionDataTable;
var $DataValueField;
var $DataVarField;
public function Init($prefix, $special)
{
parent::Init($prefix, $special);
$this->TableName = 'sessions';
$this->IDField = 'sid';
$this->TimestampField = 'expire';
$this->SessionDataTable = 'SessionData';
$this->DataValueField = 'value';
$this->DataVarField = 'var';
}
/**
* Sets reference to session
*
* @param Session $session
*/
public function setSession(&$session)
{
$this->Session =& $session;
$this->SessionTimeout = $session->SessionTimeout;
}
/**
* Calculates browser signature
*
* @return string
*/
function _getBrowserSignature()
{
$signature_parts = Array(
'HTTP_USER_AGENT', 'SERVER_PROTOCOL',
'HTTP_ACCEPT_CHARSET', 'HTTP_ACCEPT_ENCODING', 'HTTP_ACCEPT_LANGUAGE'
);
$ret = '';
foreach ($signature_parts as $signature_part) {
if (array_key_exists($signature_part, $_SERVER)) {
$ret .= '&|&' . $_SERVER[$signature_part];
}
}
return md5( substr($ret, 3) );
}
function GetSessionDefaults()
{
$fields_hash = Array (
$this->IDField => $this->Session->SID,
$this->TimestampField => $this->Session->Expiration,
);
if (!defined('IS_INSTALL') || !IS_INSTALL) {
// this column was added only in 5.0.1 version,
// so accessing it while database is not upgraded
// will result in admin's inability to login inside
// installator
$fields_hash['BrowserSignature'] = $this->_getBrowserSignature();
}
// default values + values set during this script run
return array_merge($fields_hash, $this->DirectVars);
}
/**
* Stores session to database
*
* @param bool $to_database
*
* @return void
* @access public
*/
public function StoreSession($to_database = true)
{
if ( defined('IS_INSTALL') && IS_INSTALL && $to_database && !$this->Application->TableFound($this->TableName, true) ) {
return;
}
$fields_hash = $this->GetSessionDefaults();
if ( $to_database ) {
$this->Conn->doInsert($fields_hash, $this->TableName);
}
foreach ($fields_hash as $field_name => $field_value) {
$this->SetField($field_name, $field_value);
}
// ensure user groups are stored in a way, that kPermissionsHelper::CheckUserPermission can understand
$this->Session->StoreVar('UserGroups', $this->GetField('GroupList'), !$to_database);
}
function DeleteSession()
{
$this->DeleteSessions( Array ($this->Session->SID), SESSION_LOG_LOGGED_OUT );
$this->DirectVars = $this->ChangedDirectVars = $this->OriginalData = Array();
}
function UpdateSession($timeout = 0)
{
$this->SetField($this->TimestampField, $this->Session->Expiration);
$query = ' UPDATE '.$this->TableName.' SET '.$this->TimestampField.' = '.$this->Session->Expiration.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($this->Session->SID);
$this->Conn->Query($query);
}
function LocateSession($sid)
{
$sql = 'SELECT *
FROM ' . $this->TableName . '
WHERE ' . $this->IDField . ' = ' . $this->Conn->qstr($sid);
$result = $this->Conn->GetRow($sql);
if ($result === false) {
return false;
}
// perform security checks to ensure, that session is used by it's creator
if ($this->Application->ConfigValue('SessionBrowserSignatureCheck') && ($result['BrowserSignature'] != $this->_getBrowserSignature()) && $this->Application->GetVar('flashsid') === false) {
return false;
}
if ($this->Application->ConfigValue('SessionIPAddressCheck') && ($result['IpAddress'] != $this->Application->getClientIp())) {
// most secure, except for cases where NAT (Network Address Translation)
// is used and two or more computers can have same IP address
return false;
}
$this->DirectVars = $result;
$this->Expiration = $result[$this->TimestampField];
return true;
}
function GetExpiration()
{
return $this->Expiration;
}
function LoadData()
{
$query = 'SELECT '.$this->DataValueField.','.$this->DataVarField.' FROM '.$this->SessionDataTable.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($this->Session->SID);
$this->OriginalData = $this->Conn->GetCol($query, $this->DataVarField);
return $this->OriginalData;
}
/**
* Enter description here...
*
* @param string $var_name
* @param mixed $default
* @return mixed
*/
function GetField($var_name, $default = false)
{
return isset($this->DirectVars[$var_name]) ? $this->DirectVars[$var_name] : $default;
//return $this->Conn->GetOne('SELECT '.$var_name.' FROM '.$this->TableName.' WHERE `'.$this->IDField.'` = '.$this->Conn->qstr($this->Session->GetID()) );
}
function SetField($var_name, $value)
{
$value_changed = !isset($this->DirectVars[$var_name]) || ($this->DirectVars[$var_name] != $value);
if ($value_changed) {
$this->DirectVars[$var_name] = $value;
$this->ChangedDirectVars[] = $var_name;
$this->ChangedDirectVars = array_unique($this->ChangedDirectVars);
}
//return $this->Conn->Query('UPDATE '.$this->TableName.' SET '.$var_name.' = '.$this->Conn->qstr($value).' WHERE '.$this->IDField.' = '.$this->Conn->qstr($this->Session->GetID()) );
}
/**
* Saves changes in session to database using single REPLACE query
*
* @return void
* @access public
*/
public function SaveData()
{
if ( !$this->Session->SID ) {
// can't save without sid
return ;
}
$replace = '';
$ses_data = $this->Session->Data->GetParams();
foreach ($ses_data as $key => $value) {
if ( isset($this->OriginalData[$key]) && $this->OriginalData[$key] == $value ) {
continue; //skip unchanged session data
}
else {
$replace .= sprintf("(%s, %s, %s),", $this->Conn->qstr($this->Session->SID), $this->Conn->qstr($key), $this->Conn->qstr($value));
}
}
$replace = rtrim($replace, ',');
if ( $replace != '' ) {
$query = ' REPLACE INTO ' . $this->SessionDataTable . ' (' . $this->IDField . ', ' . $this->DataVarField . ', ' . $this->DataValueField . ') VALUES ' . $replace;
$this->Conn->Query($query);
}
if ( $this->ChangedDirectVars ) {
$changes = Array ();
foreach ($this->ChangedDirectVars as $var) {
$changes[] = $var . ' = ' . $this->Conn->qstr($this->DirectVars[$var]);
}
$query = ' UPDATE ' . $this->TableName . '
SET ' . implode(',', $changes) . '
WHERE ' . $this->IDField . ' = ' . $this->Conn->qstr($this->Session->GetID());
$this->Conn->Query($query);
}
}
function RemoveFromData($var)
{
if ($this->Session->SessionSet) {
// only, when session is stored in database
$sql = 'DELETE FROM ' . $this->SessionDataTable . '
WHERE ' . $this->IDField . ' = ' . $this->Conn->qstr($this->Session->SID) . ' AND ' . $this->DataVarField . ' = ' . $this->Conn->qstr($var);
$this->Conn->Query($sql);
}
unset($this->OriginalData[$var]);
}
function GetFromData($var, $default = false)
{
return array_key_exists($var, $this->OriginalData) ? $this->OriginalData[$var] : $default;
}
function GetExpiredSIDs()
{
$sql = 'SELECT ' . $this->IDField . '
FROM ' . $this->TableName . '
WHERE ' . $this->TimestampField . ' > ' . adodb_mktime();
return $this->Conn->GetCol($sql);
}
function DeleteExpired()
{
$expired_sids = $this->GetExpiredSIDs();
$this->DeleteSessions($expired_sids);
return $expired_sids;
}
function DeleteSessions($session_ids, $delete_reason = SESSION_LOG_EXPIRED)
{
if (!$session_ids) {
return ;
}
$log_table = $this->Application->getUnitOption('session-log', 'TableName');
if ($log_table) {
// mark session with proper status
$sub_sql = 'SELECT ' . $this->TimestampField . ' - ' . $this->SessionTimeout . '
FROM ' . $this->TableName . '
WHERE ' . $this->IDField . ' = ' . $log_table . '.SessionId';
$sql = 'UPDATE ' . $log_table . '
SET Status = ' . $delete_reason . ', SessionEnd = (' . $sub_sql . ')
WHERE Status = ' . SESSION_LOG_ACTIVE . ' AND SessionId IN (' . implode(',', $session_ids) . ')';
$this->Conn->Query($sql);
}
$where_clause = ' WHERE ' . $this->IDField . ' IN (' . implode(',', $session_ids) . ')';
$sql = 'DELETE FROM ' . $this->SessionDataTable . $where_clause;
$this->Conn->Query($sql);
$sql = 'DELETE FROM ' . $this->TableName . $where_clause;
$this->Conn->Query($sql);
// delete debugger ouputs left of deleted sessions
foreach ($session_ids as $session_id) {
$debug_file = (defined('RESTRICTED') ? RESTRICTED : WRITEABLE . '/cache') . '/debug_@' . $session_id . '@.txt';
if (file_exists($debug_file)) {
@unlink($debug_file);
}
}
}
function LoadPersistentVars()
{
$user_id = $this->Session->RecallVar('user_id');
- if ($user_id != USER_GUEST) {
- // root & normal users
- $sql = 'SELECT VariableValue, VariableName
- FROM '.TABLE_PREFIX.'UserPersistentSessionData
- WHERE PortalUserId = '.$user_id;
- $this->PersistentVars = (array)$this->Conn->GetCol($sql, 'VariableName');
+
+ if ( $user_id != USER_GUEST ) {
+ // Root & normal users.
+ $this->PersistentVars = $this->getPersistentVars($user_id);
}
else {
$this->PersistentVars = Array ();
}
+
+ $default_user_id = (int)$this->Application->ConfigValue('DefaultSettingsUserId');
+
+ if ( !$default_user_id ) {
+ $default_user_id = USER_ROOT;
+ }
+
+ if ( $user_id != $default_user_id ) {
+ $this->defaultPersistentVars = $this->getPersistentVars($default_user_id);
+ }
+ }
+
+ /**
+ * Get persistent vars
+ *
+ * @param integer $user_id User Id.
+ *
+ * @return array
+ */
+ protected function getPersistentVars($user_id)
+ {
+ $sql = 'SELECT VariableValue, VariableName
+ FROM ' . TABLE_PREFIX . 'UserPersistentSessionData
+ WHERE PortalUserId = ' . $user_id;
+
+ return $this->Conn->GetCol($sql, 'VariableName');
}
/**
* Stores variable to persistent session
*
* @param string $var_name
* @param mixed $var_value
* @param bool $optional
* @return void
* @access public
*/
public function StorePersistentVar($var_name, $var_value, $optional = false)
{
$user_id = $this->Session->RecallVar('user_id');
if ( $user_id == USER_GUEST || $user_id === false ) {
// -2 (when not logged in), false (when after u:OnLogout event)
$this->Session->StoreVar($var_name, $var_value, $optional);
return;
}
$this->PersistentVars[$var_name] = $var_value;
$key_clause = 'PortalUserId = ' . $user_id . ' AND VariableName = ' . $this->Conn->qstr($var_name);
$sql = 'SELECT VariableName
FROM ' . TABLE_PREFIX . 'UserPersistentSessionData
WHERE ' . $key_clause;
$record_found = $this->Conn->GetOne($sql);
$fields_hash = Array (
'PortalUserId' => $user_id,
'VariableName' => $var_name,
'VariableValue' => $var_value,
);
if ( $record_found ) {
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'UserPersistentSessionData', $key_clause);
}
else {
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'UserPersistentSessionData');
}
}
/**
* Gets persistent variable
*
* @param string $var_name
* @param mixed $default
* @return mixed
* @access public
*/
public function RecallPersistentVar($var_name, $default = false)
{
if ( $this->Session->RecallVar('user_id') == USER_GUEST ) {
if ( $default == ALLOW_DEFAULT_SETTINGS ) {
$default = null;
}
return $this->Session->RecallVar($var_name, $default);
}
if ( array_key_exists($var_name, $this->PersistentVars) ) {
return $this->PersistentVars[$var_name];
}
elseif ( $default == ALLOW_DEFAULT_SETTINGS ) {
- $default_user_id = $this->Application->ConfigValue('DefaultSettingsUserId');
+ if ( isset($this->defaultPersistentVars[$var_name]) ) {
+ $value = $this->defaultPersistentVars[$var_name];
+ $this->StorePersistentVar($var_name, $value);
- if ( !$default_user_id ) {
- $default_user_id = USER_ROOT;
+ return $value;
}
- $sql = 'SELECT VariableValue, VariableName
- FROM ' . TABLE_PREFIX . 'UserPersistentSessionData
- WHERE VariableName = ' . $this->Conn->qstr($var_name) . ' AND PortalUserId = ' . $default_user_id;
- $value = $this->Conn->GetOne($sql);
- $this->PersistentVars[$var_name] = $value;
+ $this->PersistentVars[$var_name] = false;
- if ( $value !== false ) {
- $this->StorePersistentVar($var_name, $value); //storing it, so next time we don't load default user setting
- }
-
- return $value;
+ return false;
}
return $default;
}
/**
* Removes variable from persistent session
*
* @param string $var_name
* @return void
* @access public
*/
function RemovePersistentVar($var_name)
{
unset($this->PersistentVars[$var_name]);
$user_id = $this->Session->RecallVar('user_id');
if ( $user_id == USER_GUEST || $user_id === false ) {
// -2 (when not logged in), false (when after u:OnLogout event)
$this->Session->RemoveVar($var_name);
}
else {
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'UserPersistentSessionData
WHERE PortalUserId = ' . $user_id . ' AND VariableName = ' . $this->Conn->qstr($var_name);
$this->Conn->Query($sql);
}
}
/**
* Checks of object has given field
*
* @param string $name
*
* @return bool
* @access public
* @throws BadMethodCallException Always.
*/
public function HasField($name)
{
throw new BadMethodCallException('Unsupported');
}
/**
* Returns field values
*
* @return Array
* @access public
* @throws BadMethodCallException Always.
*/
public function GetFieldValues()
{
throw new BadMethodCallException('Unsupported');
}
/**
* Returns unformatted field value
*
* @param string $field
*
* @return string
* @access public
* @throws BadMethodCallException Always.
*/
public function GetDBField($field)
{
throw new BadMethodCallException('Unsupported');
}
/**
* Returns true, when list/item was queried/loaded
*
* @return bool
* @access public
* @throws BadMethodCallException Always.
*/
public function isLoaded()
{
throw new BadMethodCallException('Unsupported');
}
/**
* Returns specified field value from all selected rows.
* Don't affect current record index
*
* @param string $field
*
* @return Array
* @access public
* @throws BadMethodCallException Always.
*/
public function GetCol($field)
{
throw new BadMethodCallException('Unsupported');
}
-}
\ No newline at end of file
+}

Event Timeline