Index: branches/5.2.x/core/kernel/session/session.php =================================================================== diff -u -N -r14092 -r14095 --- branches/5.2.x/core/kernel/session/session.php (.../session.php) (revision 14092) +++ branches/5.2.x/core/kernel/session/session.php (.../session.php) (revision 14095) @@ -1,6 +1,6 @@ SetCookieDomain('my.domain.com'); $session->SetCookiePath('/myscript'); @@ -72,404 +72,13 @@ */ +class Session extends kBase { -/** - * Implements Session Store in the Database - * - */ -class SessionStorage extends kDBBase { + const smAUTO = 1; + const smCOOKIES_ONLY = 2; + const smGET_ONLY = 3; + const smCOOKIES_AND_GET = 4; - var $Expiration; - var $SessionTimeout=0; - - var $DirectVars = Array(); - var $ChangedDirectVars = Array(); - - var $PersistentVars = Array (); - - var $OriginalData=Array(); - - var $TimestampField; - var $SessionDataTable; - var $DataValueField; - var $DataVarField; - - function Init($prefix,$special) - { - parent::Init($prefix,$special); - $this->setTableName('sessions'); - $this->setIDField('sid'); - $this->TimestampField = 'expire'; - $this->SessionDataTable = 'SessionData'; - $this->DataValueField = 'value'; - $this->DataVarField = 'var'; - } - - function setSessionTimeout($new_timeout) - { - $this->SessionTimeout = $new_timeout; - } - - /** - * 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 StoreSession(&$session, $additional_fields = Array()) - { - if (defined('IS_INSTALL') && IS_INSTALL && !$this->Application->TableFound($this->TableName)) { - return false; - } - - $fields_hash = Array ( - $this->IDField => $session->SID, - $this->TimestampField => $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 + additional values + values set during this script run - $additional_fields = array_merge($additional_fields, $this->DirectVars); // used 2 times later - $fields_hash = array_merge($fields_hash, $additional_fields); - - $this->Conn->doInsert($fields_hash, $this->TableName); - - foreach ($additional_fields as $field_name => $field_value) { - $this->SetField($session, $field_name, $field_value); - } - } - - function DeleteSession(&$session) - { - $query = ' DELETE FROM '.$this->TableName.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID); - $this->Conn->Query($query); - - $query = ' DELETE FROM '.$this->SessionDataTable.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID); - $this->Conn->Query($query); - - $this->DirectVars = $this->ChangedDirectVars = $this->OriginalData = Array(); - } - - function UpdateSession(&$session, $timeout=0) - { - $this->SetField($session, $this->TimestampField, $session->Expiration); - $query = ' UPDATE '.$this->TableName.' SET '.$this->TimestampField.' = '.$session->Expiration.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($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())) { - return false; - } - - if ($this->Application->ConfigValue('SessionIPAddressCheck') && ($result['IpAddress'] != $_SERVER['REMOTE_ADDR'])) { - // 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(&$session) - { - $query = 'SELECT '.$this->DataValueField.','.$this->DataVarField.' FROM '.$this->SessionDataTable.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID); - - $this->OriginalData = $this->Conn->GetCol($query, $this->DataVarField); - return $this->OriginalData; - } - - /** - * Enter description here... - * - * @param Session $session - * @param string $var_name - * @param mixed $default - */ - function GetField(&$session, $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($session->GetID()) ); - } - - function SetField(&$session, $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($session->GetID()) ); - } - - function SaveData(&$session) - { - if(!$session->SID) return false; // can't save without sid - - $ses_data = $session->Data->GetParams(); - - $replace = ''; - 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($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($session->GetID()); - $this->Conn->Query($query); - } - } - - function RemoveFromData(&$session, $var) - { - $query = 'DELETE FROM '.$this->SessionDataTable.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($session->SID). - ' AND '.$this->DataVarField.' = '.$this->Conn->qstr($var); - $this->Conn->Query($query); - unset($this->OriginalData[$var]); - } - - function GetFromData(&$session, $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 = WRITEABLE . '/cache/debug_@' . $session_id . '@.txt'; - if (file_exists($debug_file)) { - @unlink($debug_file); - } - } - } - - function LoadPersistentVars(&$session) - { - $user_id = $session->RecallVar('user_id'); - if ($user_id != USER_GUEST) { - // root & normal users - $sql = 'SELECT VariableValue, VariableName - FROM '.TABLE_PREFIX.'PersistantSessionData - WHERE PortalUserId = '.$user_id; - $this->PersistentVars = $this->Conn->GetCol($sql, 'VariableName'); - } - else { - $this->PersistentVars = Array (); - } - } - - /** - * Stores variable to persistent session - * - * @param Session $session - * @param string $var_name - * @param mixed $var_value - * @param bool $optional - */ - function StorePersistentVar(&$session, $var_name, $var_value, $optional = false) - { - $user_id = $session->RecallVar('user_id'); - if ($user_id == USER_GUEST || $user_id === false) { - // -2 (when not logged in), false (when after u:OnLogout event) - $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.'PersistantSessionData - 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.'PersistantSessionData', $key_clause); - } - else { - $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'PersistantSessionData'); - } - } - - /** - * Gets persistent variable - * - * @param Session $session - * @param string $var_name - * @param mixed $default - * @return mixed - */ - function RecallPersistentVar(&$session, $var_name, $default = false) - { - if ($session->RecallVar('user_id') == USER_GUEST) { - if ($default == ALLOW_DEFAULT_SETTINGS) { - $default = null; - } - return $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 (!$default_user_id) { - $default_user_id = USER_ROOT; - } - $sql = 'SELECT VariableValue, VariableName - FROM '.TABLE_PREFIX.'PersistantSessionData - WHERE VariableName = '.$this->Conn->qstr($var_name).' AND PortalUserId = '.$default_user_id; - $value = $this->Conn->GetOne($sql); - $this->PersistentVars[$var_name] = $value; - if ($value !== false) { - $this->StorePersistentVar($session, $var_name, $value); //storing it, so next time we don't load default user setting - } - return $value; - } - else { - return $default; - } - } - - function RemovePersistentVar(&$session, $var_name) - { - unset($this->PersistentVars[$var_name]); - - $user_id = $session->RecallVar('user_id'); - - if ($user_id == USER_GUEST || $user_id === false) { - // -2 (when not logged in), false (when after u:OnLogout event) - $session->RemoveVar($var_name); - } - else { - $sql = 'DELETE FROM '.TABLE_PREFIX.'PersistantSessionData - WHERE PortalUserId = '.$user_id.' AND VariableName = '.$this->Conn->qstr($var_name); - $this->Conn->Query($sql); - } - } -} - -define('smAUTO', 1); -define('smCOOKIES_ONLY', 2); -define('smGET_ONLY', 3); -define('smCOOKIES_AND_GET', 4); - - -class Session extends kBase { var $Checkers; var $Mode; @@ -528,9 +137,15 @@ */ var $expired = false; - function Session($mode = smAUTO) + /** + * Creates session + * + * @param int $mode + * @access public + */ + public function __construct($mode = self::smAUTO) { - parent::kBase(); + parent::__construct(); $this->SetMode($mode); } @@ -624,12 +239,12 @@ function InitStorage($special) { $this->Storage =& $this->Application->recallObject('SessionStorage.'.$special); - $this->Storage->setSessionTimeout($this->SessionTimeout); + $this->Storage->setSession($this); } - function Init($prefix,$special) + public function Init($prefix, $special) { - parent::Init($prefix,$special); + parent::Init($prefix, $special); $this->CheckIfCookiesAreOn(); if ($this->CookiesEnabled) $_COOKIE['cookies_on'] = 1; @@ -723,7 +338,7 @@ function CheckIfCookiesAreOn() { - if ($this->Mode == smGET_ONLY) { + if ($this->Mode == self::smGET_ONLY) { //we don't need to bother checking if we would not use it $this->CookiesEnabled = false; return; @@ -736,7 +351,7 @@ if ($this->IsHTTPSRedirect() && $get_sid) { // Redirect from http to https on different domain $this->OriginalMode = $this->Mode; - $this->SetMode(smGET_ONLY); + $this->SetMode(self::smGET_ONLY); } if (!$cookies_on || $this->IsHTTPSRedirect()) { @@ -857,7 +472,7 @@ } else { switch ($this->Mode) { - case smAUTO: + case self::smAUTO: //Cookies has the priority - we ignore everything else $sid = $this->CookiesEnabled ? $this->GetSessionCookie() : $get_sid; @@ -866,15 +481,15 @@ } break; - case smCOOKIES_ONLY: + case self::smCOOKIES_ONLY: $sid = $this->GetSessionCookie(); break; - case smGET_ONLY: + case self::smGET_ONLY: $sid = $get_sid; break; - case smCOOKIES_AND_GET: + case self::smCOOKIES_AND_GET: $cookie_sid = $this->GetSessionCookie(); //both sids should match if cookies are enabled if (!$this->CookiesEnabled || ($cookie_sid == $get_sid)) { @@ -979,22 +594,22 @@ $this->Expiration = adodb_mktime() + $this->SessionTimeout; switch ($this->Mode) { - case smAUTO: + case self::smAUTO: if ($this->CookiesEnabled) { $this->SetSessionCookie(); } break; - case smGET_ONLY: + case self::smGET_ONLY: break; - case smCOOKIES_ONLY: - case smCOOKIES_AND_GET: + case self::smCOOKIES_ONLY: + case self::smCOOKIES_AND_GET: $this->SetSessionCookie(); break; } - $this->Storage->StoreSession($this); + $this->Storage->StoreSession(); if ($this->Application->isAdmin || $this->Special == 'admin') { $this->StoreVar('admin', 1); @@ -1070,12 +685,12 @@ // we need to refresh the cookie $this->SetSessionCookie(); } - $this->Storage->UpdateSession($this); + $this->Storage->UpdateSession(); } function Destroy() { - $this->Storage->DeleteSession($this); + $this->Storage->DeleteSession(); $this->Data = new Params(); $this->SID = $this->CachedSID = ''; $this->SessionSet = false; @@ -1095,17 +710,17 @@ $result = false; switch ($this->Mode) { - case smAUTO: + case self::smAUTO: if (!$this->CookiesEnabled) { $result = true; } break; - /*case smCOOKIES_ONLY: + /*case self::smCOOKIES_ONLY: break;*/ - case smGET_ONLY: - case smCOOKIES_AND_GET: + case self::smGET_ONLY: + case self::smCOOKIES_AND_GET: $result = true; break; } @@ -1117,18 +732,18 @@ function LoadData() { - $this->Data->AddParams($this->Storage->LoadData($this)); + $this->Data->AddParams( $this->Storage->LoadData() ); } function PrintSession($comment = '') { - if (defined('DEBUG_MODE') && $this->Application->isDebugMode() && constOn('DBG_SHOW_SESSIONDATA')) { + if (defined('DEBUG_MODE') && $this->Application->isDebugMode() && kUtil::constOn('DBG_SHOW_SESSIONDATA')) { // dump session data $this->Application->Debugger->appendHTML('SessionStorage [' . ($this->RecallVar('admin') == 1 ? 'Admin' : 'Front-End') . '] ('.$comment.'):'); $session_data = $this->Data->GetParams(); ksort($session_data); foreach ($session_data as $session_key => $session_value) { - if (IsSerialized($session_value)) { + if (kUtil::IsSerialized($session_value)) { $session_data[$session_key] = unserialize($session_value); } } @@ -1151,14 +766,14 @@ } } - if (defined('DEBUG_MODE') && $this->Application->isDebugMode() && constOn('DBG_SHOW_PERSISTENTDATA')) { + if (defined('DEBUG_MODE') && $this->Application->isDebugMode() && kUtil::constOn('DBG_SHOW_PERSISTENTDATA')) { // dump persistent session data if ($this->Storage->PersistentVars) { $this->Application->Debugger->appendHTML('Persistant Session:'); $session_data = $this->Storage->PersistentVars; ksort($session_data); foreach ($session_data as $session_key => $session_value) { - if (IsSerialized($session_value)) { + if (kUtil::IsSerialized($session_value)) { $session_data[$session_key] = unserialize($session_value); } } @@ -1178,7 +793,7 @@ } $this->PrintSession('after save'); - $this->Storage->SaveData($this); + $this->Storage->SaveData(); } /** @@ -1304,12 +919,12 @@ function StorePersistentVar($name, $value, $optional = false) { - $this->Storage->StorePersistentVar($this, $name, $value, $optional); + $this->Storage->StorePersistentVar($name, $value, $optional); } function LoadPersistentVars() { - $this->Storage->LoadPersistentVars($this); + $this->Storage->LoadPersistentVars(); } function StoreVarDefault($name, $value, $optional=false) @@ -1329,19 +944,19 @@ function RecallPersistentVar($name, $default = false) { - return $this->Storage->RecallPersistentVar($this, $name, $default); + return $this->Storage->RecallPersistentVar($name, $default); } function RemoveVar($name) { - $this->Storage->RemoveFromData($this, $name); + $this->Storage->RemoveFromData($name); $this->Data->Remove($name); } function RemovePersistentVar($name) { - return $this->Storage->RemovePersistentVar($this, $name); + return $this->Storage->RemovePersistentVar($name); } /** @@ -1351,7 +966,7 @@ */ function RestoreVar($name) { - $value = $this->Storage->GetFromData($this, $name, '__missing__'); + $value = $this->Storage->GetFromData($name, '__missing__'); if ($value === '__missing__') { // there is nothing to restore (maybe session was not saved), look in optional variable values @@ -1363,12 +978,12 @@ function GetField($var_name, $default = false) { - return $this->Storage->GetField($this, $var_name, $default); + return $this->Storage->GetField($var_name, $default); } function SetField($var_name, $value) { - $this->Storage->SetField($this, $var_name, $value); + $this->Storage->SetField($var_name, $value); } /**