SetCookieDomain('my.domain.com'); $session->SetCookiePath('/myscript'); $session->SetCookieName('my_sid_cookie'); $session->SetGETName('sid'); $session->InitSession(); ... //link output: echo "NeedQueryString() ? 'sid='.$session->SID : '' ) .">My Link"; */ //Implements session storage in the database class SessionStorage extends kDBBase { var $Expiration; var $OriginalData=Array(); function StoreSession(&$session) { $query = sprintf( "INSERT INTO %sSessions (sid, expire) VALUES (%s, %s)", TABLE_PREFIX, $session->SID, $session->Expiration); $this->Conn->Query($query); } function DeleteSession(&$session) { $query = sprintf( "DELETE FROM %sSessions WHERE %s = %s", TABLE_PREFIX, 'sid', $session->SID); $this->Conn->Query($query); $query = sprintf( "DELETE FROM %sSessionData WHERE %s = %s", TABLE_PREFIX, 'sid', $session->SID); $this->Conn->Query($query); $this->OriginalData = Array(); } function UpdateSession(&$session) { $query = sprintf( "UPDATE %sSessions SET expire = %s WHERE %s = %s", TABLE_PREFIX, $session->Expiration, 'sid', $session->SID); $this->Conn->Query($query); } function LocateSession($sid) { $query = sprintf( "SELECT expire FROM %sSessions WHERE %s = %s", TABLE_PREFIX, 'sid', $sid); $result = $this->Conn->GetOne($query); if($result===false) return false; $this->Expiration = $result; return true; } function GetExpiration() { return $this->Expiration; } function LoadData(&$session) { $query = sprintf( "SELECT value,name FROM %sSessionData WHERE %s = %s", TABLE_PREFIX, 'sid', $session->SID); $this->OriginalData = $this->Conn->GetCol($query,'name'); return $this->OriginalData; } function SaveData(&$session) { $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),", $session->SID, $this->Conn->qstr($key), $this->Conn->qstr($value)); } } $replace = rtrim($replace, ','); if ($replace != '') { $query = sprintf( 'REPLACE INTO %sSessionData (sid, name, value) VALUES %s', TABLE_PREFIX, $replace); $this->Conn->Query($query); } } function RemoveFromData(&$session, $var) { $query = sprintf( "DELETE FROM %sSessionData WHERE %s = %s AND %s = %s", TABLE_PREFIX, 'sid', $session->SID, 'name', $this->Conn->qstr($var)); $this->Conn->Query($query); unset($this->OriginalData[$var]); } } define('smAUTO', 1); define('smCOOKIES_ONLY', 2); define('smGET_ONLY', 3); define('smCOOKIES_AND_GET', 4); class Session extends kBase { var $Checkers; var $Mode; var $GETName = 'sid'; var $CookiesEnabled = true; var $CookieName = 'sid'; var $CookieDomain; var $CookiePath; var $CookieSecure = 0; var $SessionTimeout = 3600; var $Expiration; var $SID; var $Storage; var $CachedNeedQueryString = null; var $Data; function Session($mode=smAUTO) { parent::kBase(); $this->SetMode($mode); } function SetMode($mode) { $this->Mode = $mode; } function SetCookiePath($path) { $this->CookiePath = $path; } function SetCookieDomain($domain) { $this->CookieDomain = $domain; } function SetGETName($get_name) { $this->GETName = $get_name; } function SetCookieName($cookie_name) { $this->CookieName = $cookie_name; } function InitStorage() { $this->Storage =& new SessionStorage(); } function Init($prefix,$special) { parent::Init($prefix,$special); $this->CheckIfCookiesAreOn(); $this->Checkers = Array(); $this->InitStorage(); $this->Data =& new Params(); if ($this->Check()) { $this->SID = $this->GetPassedSIDValue(); $this->Refresh(); $this->LoadData(); } else { $this->SetSession(); } } function CheckReferer() { $reg = '#^'.preg_quote(PROTOCOL.$this->CookieDomain.$this->CookiePath).'#'; return preg_match($reg, $_SERVER['HTTP_REFERER']); } function CheckIfCookiesAreOn() { if ($this->Mode == smGET_ONLY) { //we don't need to bother checking if we would not use it $this->CookiesEnabled = false; return; } $http_query =& $this->Application->recallObject('HTTPQuery'); $cookies_on = $http_query->Cookie['cookies_on']; // not good here if (!$cookies_on) { //If referer is our server, but we don't have our cookies_on, it's definetly off if ($this->CheckReferer()) { $this->CookiesEnabled = false; } else { //Otherwise we still suppose cookies are on, because may be it's the first time user visits the site //So we send cookies on to get it next time (when referal will tell us if they are realy off setcookie( 'cookies_on', 1, time()+31104000, //one year should be enough $this->CookiePath, $this->CookieDomain, $this->CookieSecure ); } } else $this->CookiesEnabled = true; return $this->CookiesEnabled; } function Check() { // we should check referer if cookies are disabled, and in combined mode // auto mode would detect cookies, get only mode would turn it off - so we would get here // and we don't care about referal in cookies only mode if ( $this->Mode != smCOOKIES_ONLY && (!$this->CookiesEnabled || $this->Mode == smCOOKIES_AND_GET) ) { if (!$this->CheckReferer()) return false; } $sid = $this->GetPassedSIDValue(); if (empty($sid)) return false; //try to load session by sid, if everything is fine $result = $this->LoadSession($sid); return $result; } function LoadSession($sid) { if ($this->Storage->LocateSession($sid)) { //if we have session with such SID - get its expiration $this->Expiration = $this->Storage->GetExpiration(); //If session has expired if ($this->Expiration < time()) return false; //Otherwise it's ok return true; } else //fake or deleted due to expiration SID return false; } function GetPassedSIDValue($use_cache = 1) { if (!empty($this->CachedSID) && $use_cache) return $this->CachedSID; $http_query =& $this->Application->recallObject('HTTPQuery'); $get_sid=$this->Application->GetVar($this->GETName); switch ($this->Mode) { case smAUTO: //Cookies has the priority - we ignore everything else $sid=$this->CookiesEnabled?$http_query->Cookie[$this->CookieName]:$get_sid; break; case smCOOKIES_ONLY: $sid = $http_query->Cookie[$this->CookieName]; break; case smGET_ONLY: $sid = $get_sid; break; case smCOOKIES_AND_GET: $cookie_sid = $http_query->Cookie[$this->CookieName]; //both sids should match if cookies are enabled if (!$this->CookiesEnabled || ($cookie_sid == $get_sid)) { $sid = $get_sid; //we use get here just in case cookies are disabled } else { $sid = ''; } break; } $this->CachedSID = $sid; return $this->CachedSID; } /** * Returns session id * * @return int * @access public */ function GetID() { return $this->SID; } /** * Generates new session id * * @return int * @access private */ function GenerateSID() { list($usec, $sec) = explode(" ",microtime()); $sid_part_1 = substr($usec, 4, 4); $sid_part_2 = mt_rand(1,9); $sid_part_3 = substr($sec, 6, 4); $digit_one = substr($sid_part_1, 0, 1); if ($digit_one == 0) { $digit_one = mt_rand(1,9); $sid_part_1 = ereg_replace("^0","",$sid_part_1); $sid_part_1=$digit_one.$sid_part_1; } $this->setSID($sid_part_1.$sid_part_2.$sid_part_3); return $this->SID; } /** * Set's new session id * * @param int $new_sid * @access private */ function setSID($new_sid) { $this->SID=$new_sid; $this->Application->SetVar($this->GETName,$new_sid); } function SetSession() { $this->GenerateSID(); $this->Expiration = time() + $this->SessionTimeout; switch ($this->Mode) { case smAUTO: if ($this->CookiesEnabled) { $this->SetSessionCookie(); } break; case smGET_ONLY: break; case smCOOKIES_ONLY: case smCOOKIES_AND_GET: $this->SetSessionCookie(); break; } $this->Storage->StoreSession($this); } function SetSessionCookie() { setcookie( $this->CookieName, $this->SID, $this->Expiration, $this->CookiePath, $this->CookieDomain, $this->CookieSecure ); } /** * Refreshes session expiration time * * @access private */ function Refresh() { if ($this->CookiesEnabled) $this->SetSessionCookie(); //we need to refresh the cookie $this->Storage->UpdateSession($this); } function Destroy() { $this->Storage->DeleteSession($this); $this->Data =& new Params(); $this->SID = ''; if ($this->CookiesEnabled) $this->SetSessionCookie(); //will remove the cookie due to value (sid) is empty $this->SetSession(); //will create a new session } function NeedQueryString($use_cache = 1) { if ($this->CachedNeedQueryString != null && $use_cache) return $this->CachedNeedQueryString; switch ($this->Mode) { case smAUTO: if ($this->CookiesEnabled) { $res = 0; } else { $res = 1; } break; case smCOOKIES_ONLY: break; case smGET_ONLY: case smCOOKIES_AND_GET: $res = 1; break; } $this->CachedNeedQueryString = $res; return $res; } function LoadData() { $this->Data->AddParams($this->Storage->LoadData($this)); } function SaveData() { $this->Storage->SaveData($this); } function StoreVar($name, $value) { $this->Data->Set($name, $value); } function RecallVar($name,$default=false) { $ret=$this->Data->Get($name); return ($ret===false)?$default:$ret; } function RemoveVar($name) { $this->Storage->RemoveFromData($this, $name); $this->Data->Remove($name); } } ?>