<?php
/**
* @file : sesssion.class.php
* @desc : sessions handling class
* @lmod : 13.09.2006
*/
class session
{
// session idle
var $max_idle;
var $no_expire;
// session values
var $sessid;
var $sesshost;
var $variables;
var $codelength = 20;
// handlers
var $dbh;
// system messages
var $messages = array();
function session($host=null)
{
// get database link
global $s;
$this->dbh = & $s;
// set max idle time
global $_MAX_IDLE;
$this->max_idle = $_MAX_IDLE;
// set no expire (actually it expires after a really long time)
$this->no_expire = (time()+(365*24*60*60)); // 1 year
// set session host
$this->sesshost = $host;
// get session id(if some)
$sessid = $_COOKIE['session'];
// preform some session id validation (code lenght, validity of the session)
if (isset($sessid) && strlen($sessid) == $this->codelength && $this->isSession($sessid))
{
$this->sessid = $sessid;
// check no expire
if ($_COOKIE['no_expire'] && $this->isNoExpire())
{
$noexpire = 1;
}
else
{
$noexpire = 0;
}
// update current session last action
$this->updSession($this->sessid, $noexpire);
// load all session values
$this->listVals($this->sessid);
}
else
{
// start new session
$this->sessid = $this->startSession();
}
// get page referer
if ($this->isVal('_current'))
{
$this->setVal('_referer', $this->getVal('_current'));
}
// save current page
$this->setVal('_current', $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']);
// clear old sessions
$this->clearSession();
}
/**
* @desc : start session
* @return $sessid : string : session id
*/
function startSession()
{
// session id
$sessid = $this->genSessid();
// generate sql record of sessions
$qry = 'INSERT INTO sessions ( s_id, s_lastact, s_ip ) ';
$qry .= "VALUES ( '{$sessid}', '" . time() . "', '{$_SERVER['REMOTE_ADDR']}' )";
$this->dbh->query($qry);
// save session id to cookie and system session, in case cookies don't work
setcookie('session', $sessid, false, '/', $this->sesshost);
return $sessid;
}
/**
* @desc : end current session, destroing all it values
* @return : boolean : status
*/
function endSession()
{
// delete session sql record and it's values
$this->dbh->delete(array('sessions', 'sessvalues'), "s_id='{$this->sessid}'");
// detete session id from cookie and system session
setcookie('session', '', time()-3600, '/', $this->sesshost);
// unset session values within the class
$this->sessid = null;
$this->variables = null;
return true;
}
/**
* @desc : update session last action
* @param $sessid : string : session id
* @param $noexpire : int : is this not expire session
* @return : boolean : status
*/
function updSession($sessid=0, $noexpire=0)
{
$sessid = $sessid ? $sessid : $this->sessid;
// check if this is no expire session
if ($noexpire)
{
$time = $this->no_expire;
}
else
{
$time = time();
}
// update last action
return $this->dbh->query("UPDATE sessions SET s_lastact='{$time}' WHERE s_id='{$sessid}' ");
}
/**
* @desc : check if session exists
* @param $sessid : string : session id
* @return : boolean : is session exists
*/
function isSession($sessid)
{
$this->dbh->query("SELECT s_id FROM sessions WHERE s_id='{$sessid}' LIMIT 1 ");
return ($this->dbh->getnumrows() > 0 ? true : false );
}
/**
* @desc : clear expired sessions
* @return : boolean : status
*/
function clearSession()
{
$time = time() - $this->max_idle;
// select expired sessions
$qry = 'SELECT s_id AS id FROM sessions WHERE ';
$qry .= "s_lastact < {$time}" ;
$this->dbh->query($qry, 1);
if ($this->dbh->getnumrows(1) == 0) { return true; }
while ($row = $this->dbh->getrow(1))
{
// delete sql record values
$this->dbh->query("DELETE FROM sessvalues WHERE s_id='{$row->id}' ");
}
// delete expired sql records
$this->dbh->query("DELETE FROM sessions WHERE s_lastact < {$time}");
return true;
}
/**
* @desc : generate random unique session id
* @return $sessid : string : session id
*/
function genSessid()
{
$sessid = 0;
// genereate random string
mt_srand ((double) microtime() * 1000000);
$puddle = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for($i=0; $i < $this->codelength - 1; $i++)
{
$sessid .= substr($puddle, (mt_rand()%(strlen($puddle))), 1);
}
// check if session id already exists
if ($this->isSession($sessid))
{
$sessid = $this->genSessid();
}
return $sessid;
}
/**
* @desc : set value(s) to session
* @param $name : string/array : value name or array containig the values
* @param $value : string : value
* @return : boolean : is setting succesful
*/
function setVal($name, $value=0)
{
// if name is not array it is value name, so add a single value
if (!is_array($name)) return $this->_setVal($name, $value);
// else add a list of values
foreach ($name as $key => $val)
{
if (!$this->_setVal($key, $val))
{
return false;
}
}
return true;
}
/**
* @desc : set value to session
* @param $name : string : value name
* @param $value : string : value
* @return : boolean : is setting succesful
*/
function _setVal($name, $value)
{
// escape value
$value = addslashes($value);
// check if value exists
$this->dbh->query("SELECT s_id FROM sessvalues WHERE s_id='{$this->sessid}' AND sv_name='{$name}' LIMIT 1");
if ($this->dbh->getnumrows() > 0)
{
// value exists, update it
$qry = 'UPDATE sessvalues SET ';
$qry .= "sv_value='{$value}' WHERE s_id='{$this->sessid}' AND sv_name='{$name}'";
if (!$this->dbh->query($qry)) { return false; }
}
else
{
// if value don't exists add it
$qry = 'INSERT INTO sessvalues ( s_id, sv_name, sv_value ) ';
$qry .= "VALUES ( '{$this->sessid}', '$name', '$value' )";
if (!$this->dbh->query($qry)) { return false; }
}
// save the value
$this->variables[$name] = stripslashes($value);
return true;
}
/**
* @desc : save this->variables to database
* @return : boolean : is array added to database succesfully
*/
function toDB()
{
foreach ($this->variables as $key => $val)
{
$this->setVal($key, $val);
}
return true;
}
/**
* @desc : delete session value
* @param $name : string : value name
* @return : boolean : is deleting succesful
*/
function delVal($name=0)
{
// delete value
$qry = "DELETE FROM sessvalues WHERE s_id='{$this->sessid}' ";
if (func_num_args() > 1)
{
// get all functions arguments
$args = func_get_args();
// delete list of values
$qry .= 'AND sv_name IN ( ';
foreach ($args as $val)
{
$qry .= "'{$val}', ";
// delete value from session variables
unset($this->variables[$val]);
}
$qry = rtrim($qry, ', ');
$qry .= ') ';
}
elseif ($name)
{
// delete one value
$qry .= "AND sv_name='{$name}' ";
// delete value from session variables
unset($this->variables[$name]);
}
else
{
// delete all values
unset($this->variables);
}
return $this->dbh->query($qry);
}
/**
* @desc : clear all values which are not protected(_*)
* @return : boolean : is clearing succesfull
*/
function clearVal()
{
return $this->dbh->query("DELETE FROM sessvalues WHERE s_id='{$this->sessid}' WHERE sv_name NOT LIKE '_%' ");
}
/**
* @desc : check session value exists
* @param $name : string : value name
* @return : boolean : is session value exists
*/
function isVal($name)
{
return isset($this->variables[$name]);
}
/**
* @desc : get session value
* @param $name : string : variable name
* @return : unknown : variable
*/
function getVal($name)
{
return $this->variables[$name];
}
/**
* @desc : get session value and then delete it
* @param $name : string : variable name
* @return : uknow : variable
*/
function cutVal($name)
{
if ($this->variables[$name])
{
$this->delVal($name);
}
return $this->variables[$name];
}
/**
* @desc : lsit session values
* @param $sessid : string : session id
* @return : boolean : status
*/
function listVals($sessid=0)
{
$sessid = $sessid ? $sessid : $this->sessid;
$this->dbh->query("SELECT sv_name, sv_value FROM sessvalues WHERE s_id='{$sessid}' ");
$this->variables = array();
while ($row = $this->dbh->getrow())
{
$this->variables[$row->sv_name] = stripslashes($row->sv_value);
}
return true;
}
/**
* @desc : check if this is no expire session
* @return : boolean : is this no expire session
*/
function isNoExpire()
{
$cookie = $_COOKIE['noexpire'];
$parts = explode('::', $this->variables['noexpire_str']);
if ($_SERVER['REMOTE_ADDR'] == $parts[0] && $cookie == $parts[1])
{
return true;
}
return false;
}
/**
* @desc : makes current session no expire
* @note : this work only with cookies available
*/
function setNoExpire()
{
// generate random id, using genSessid function
$randid = $this->genSessid();
// generate sring by current ip and the random id
$string = $_SERVER['REMOTE_ADDR'] . '::' . $randid;
// save no expire string
$this->setVal('noexpire_str', $string);
// set the never expiring cookies
setcookie('noexpire', $randid, $this->no_expire, '/', $this->sesshost);
setcookie('session', $this->sessid, $this->no_expire, '/', $this->sesshost);
}
/**
* @desc : count activ sessions
* @param $fld : string : count by field name
* @param $last : int : last action (in seconds)
* @return : int : sessions count
*/
function count($fld=0, $last=600)
{
if (!$fld)
{
$qry = "SELECT s_id FROM sessions WHERE s_lastact > " . ( time() - $last );
$qry .= " GROUP BY s_ip ";
$this->dbh->query($qry);
return $this->dbh->getnumrows();
}
$qry = "SELECT a.s_id FROM sessions a, sessvalues b ";
$qry .= "WHERE s_lastact > " . ( time() - $last );
$qry .= " AND a.s_id = b.s_id AND b.sv_name='{$fld}' ";
$qry .= "GROUP BY a.s_ip ";
$this->dbh->query($qry);
return $this->dbh->getnumrows();
}
/**
* @desc : return to page referer
*
*/
function back()
{
if ($_SERVER['HTTP_REFERER'])
{
header("location: {$_SERVER['HTTP_REFERER']}");
exit;
}
header('location: http://' . $this->getVal('_referer'));
exit;
}
/**
* @desc : add message
* @param $value : string : message text, value
* @param $name : string : message name, topic
*
*/
function add_msg($value, $name=false)
{
// add message
if ($name)
{
// add in message array $name as key
$this->messages[$name] = $value;
}
else
{
// add message just as next array value
$this->messages[] = $value;
}
}
/**
* @desc : clear all messages
*
*/
function clear_msg()
{
// 'restart' $messages array
$this->messages = array();
}
/**
* @desc : check if there is at least one message
*
*/
function is_msg()
{
if (count($this->messages) > 0)
{
return true;
}
return false;
}
/**
* @desc : throw messages to some page
* @param $message : string : message to send (if set message type is 2);
* @param $redirect : string : redirect link (def: HTTP_REFERER)
*/
function throw_msg($message=0, $redirect=0)
{
// prepare message(s) string for session
if (!$message)
{
//set message type
$type = 1;
// seriazle messages
$message = serialize($this->messages);
}
$message = addslashes($message);
// save message(s) in session
$this->setVal(array(
'_sysmtype' => $type,
'_sysmsg' => $message
));
// redirect
if ($redirect)
{
header("location: {$redirect}");
exit;
}
// [else] goto to referer
$this->back();
}
/**
* @desc : catch message(s)
* @return $message : string/array : the message(s) (if some)
*
*/
function catch_msg()
{
// check if there is registered message
if (!$this->isVal('_sysmsg'))
{
return false;
}
// recover message type and message value(s) from session and then delete them
$mtype = $this->cutVal('_sysmtype');
$message = $this->cutVal('_sysmsg');
$message = stripslashes($message);
// check if message is serialized array
if ($mtype == 1)
{
$message = unserialize($message);
}
// return the message
return $message;
}
}
?>