Version: 1.0
Type: Class
Category: HTTP
License: GNU General Public License
Description: 4 Files: ses.php - main file, contains server-side PHP code. ses.js - contains some client-side JavaScript routines. ses1.php - sample file, demonstrates features, loads ses2.php ses2.php - sample file, demonstrates features, loads ses1.php Installation: - split the text into 4 files - copy all the files into a test dir, and diplay ses1.php or ses2.php in your browser. Description: - Feature-rich session managing class for PHP 4.0.x. - Never uses cookies, so always working on the same way for every browser. Transmits the session ID through URLs, keeps track name-value pairs in files. Supports expiration, various URL handling features, etc. Version information: 1.0 (2001-may-12) - Initial release. - Independent of PHP's own session handling code - Transmits session id through URL - Stores variable names and values in plain text files. - Supplies URL managing functions for seamless web-page integration - Contains session handling examples for links, GET forms, POST forms, self-calling JavaScript drop-down lists - Tunable automatic expiration settings on a per-session basis. - Performs regular, tunable garbage collection of expired server-side session files. - as does not use cookies, it is nothing to with headers, and the session handling code may be placed anywhere on the PHP page - MD5-based session ID generation - Session config parameters used from php.conf: -- session.name -- session.save_path -- session.gc_maxlifetime -- session.gc_probability
======================== START OF ses_readme.txt FILE ========================
//---------------------------------------------------------------------------
// SimpleSession - a powerful URL-based session handler for PHP4.
//---------------------------------------------------------------------------
// Author: Joseph Ostor (ostor@posta.net)
// Version: 1.0 (2001-may-12)
// Requirements: PHP >= 4.0.x
// License: GPL
// Files:
// ses.php - this file, contains server-side PHP code.
// ses.js - contains some client-side JavaScript routines.
// ses1.php - sample file, demonstrates features, loads ses2.php
// ses2.php - sample file, demonstrates features, loads ses1.php
// Installation: copy all the files into a test dir, and diplay
// ses1.php or ses2.php in your browser.
//
// Description:
// Feature-rich session managing class for PHP 4.0.x.
// Never uses cookies, so always working on the same way for every
// browser. Transmits the session ID through URLs, keeps track
// name-value pairs in files. Supports expiration, various URL
// handling features, etc.
//
// Version information:
// 1.0 (2001-may-12) - Initial release.
// - Independent of PHP's own session handling code
// - Transmits session id through URL
// - Stores variable names and values in plain text files.
// - Supplies URL managing functions for seamless web-page
// integration
// - Contains session handling examples for links, GET forms,
// POST forms, self-calling JavaScript drop-down lists
// - Tunable automatic expiration settings on a per-session
// basis.
// - Performs regular, tunable garbage collection of expired
// server-side session files.
// - as does not use cookies, it is nothing to with headers,
// and the session handling code may be placed anywhere on
// the PHP page
// - MD5-based session ID generation
// - Session config parameters used from php.conf:
// session.name = name of the request variable in the URL
// session.save_path = OS file path to save session data files.
// session.gc_maxlifetime = after these seconds elapsed, session
// file will be removed by the garbage
// collector
// session.gc_probability = percentual probability of the garbage
// collector to start on session start
//---------------------------------------------------------------------------
======================== END OF ses_readme.txt FILE ========================
======================== START OF ses.js FILE ========================
//------------------
// SimpleSession - a powerful URL-based session handler
// ses.js - contains some client-side JavaScript routines.
//------------------
// Author: Joseph Ostor (ostor@posta.net)
// Version: 1.0 (2001-may-12)
//------------------
function getformopt(formname,selectname)
{
var sel = 'document.'+formname+'.'+selectname+'.';
var expr = sel+'options['+sel+'selectedIndex].value';
var val = parseFloat(eval(expr));
if( isNaN(val) ) return 0;
return val;
}
function splitURL()
{
var i,url = new Array();
var reqpos = location.href.indexOf('?');
if( reqpos>0 )
{
url[0] = location.href.substring(0,reqpos);
var qstr = location.href.substr(reqpos+1);
var qarr = qstr.split("&");
for(i=0; i<qarr.length; i++)
{
var qvar = qarr[i].split("=");
if( qvar.length==2 )
url[url.length] = qvar;
}
}
else
url[0] = location.href;
return url;
}
function assembleURL(urlarr)
{
if( urlarr.length<1 ) return '';
var url = urlarr[0];
if( urlarr.length<2 ) return url;
url += '?';
for(i=1; i<urlarr.length; i++)
{
if( i>1 ) url += '&';
url += urlarr[i][0] + '=' + urlarr[i][1];
}
return url;
}
function removeElement(arr,idx)
{
var tmp = new Array();
var i1,i2;
for(i1=0,i2=0; i1<arr.length; i1++)
{
if( i1!=idx )
{
tmp[i2]=arr[i1];
i2++;
}
}
return tmp;
}
======================== END OF ses.js FILE ========================
======================== START OF ses.php FILE ========================
<?
//---------------------------------------------------------------------------
// SimpleSession - a powerful URL-based session handler for PHP4.
//---------------------------------------------------------------------------
// Author: Joseph Ostor (ostor@posta.net)
// Version: 1.0 (2001-may-12)
// Requirements: PHP 4.0.x
//
// See 'ses_readme.txt' for details.
//---------------------------------------------------------------------------
class SimpleSession
{
var $id,$name,$lifetime,$gc_probability;
var $vars;
var $rqm;
//---------------------
function SimpleSession($autostart=true)
{
$cache_expire = (int)get_cfg_var('session.gc_maxlifetime');
if( $cache_expire<100 )
$cache_expire = 1440; //seconds
$gc_prob = (int)get_cfg_var('session.gc_probability');
if( $gc_prob>100 || $gc_prob<1 )
$gc_prob = 1;
$sessionname = get_cfg_var('session.name');
if( !$sessionname )
$sessionname = 'SIMPSESSID';
$this->id = '';
$this->name = $sessionname; //PHP built-in function.
$this->lifetime = $cache_expire; //seconds.
$this->gc_probability = $gc_prob; //percentage
$this->vars = array();
$this->active = false;
$this->rqm = new ReqManager();
if( $autostart ) $this->session_start();
}
function Save()
{
if( $this->active )
{
dbg("Save started");
$this->session_save_internal();
}
}
//removeoldreqs: removes additional GET variables from the URL.
function Req($startchar='?',$removeoldreqs=true)
{
if( $removeoldreqs )
$this->rqm->clear();
if( $this->active )
$this->rqm->add($this->name,$this->id);
return $this->rqm->request($startchar);
}
function session_name(){return $this->name;}
function session_id() {return $this->id;}
function SID() {return "{$this->name}={$this->id}";}
function FormSID() {return "<input type=\"hidden\" name=\"{$this->name}\" value=\"{$this->id}\">\n";}
function read($nam,$defval=false)
{
if( !isset($this->vars[$nam]) ) return $defval;
return $this->vars[$nam];
}
function is_registered($nam){return isset($this->vars[$nam]);}
function register($nam) //storing a new session variable.
{
if( !$this->active ) $this->session_start();
if( !$this->active ) return false; //could not start session.
if( !isset($GLOBALS[$nam]) )
{
warn("Warning: register: registered variable ($nam) has not assigned a value - set to true.");
$GLOBALS[$nam] = true;
}
$this->vars[$nam] = &$GLOBALS[$nam];
}
function register_from_GET($nam,$defval=false) //storing a new session variable from Query string.
{
global $HTTP_GET_VARS;
if( isset($HTTP_GET_VARS[$nam]) )
{
$GLOBALS[$nam] = $HTTP_GET_VARS[$nam];
$this->register($nam);
dbg("register_from_GET: $nam found in the reqest string, value: {$HTTP_GET_VARS[$nam]}");
return true;
}
elseif( $this->is_registered($nam) )
{
dbg("register_from_GET: $nam NOT found in the reqest string, but registered, value: ".$this->read($nam));
return true;
}
if( (!isset($GLOBALS[$nam])) )
{
$GLOBALS[$nam] = $defval;
dbg("register_from_GET: $nam NOT found in the reqest string, NOT registered, created from default value $defval");
}
else
dbg("register_from_GET: $nam NOT found in the reqest string, NOT registered, leaved as undefined (defval=$defval)");
return false;
}
function register_from_POST($nam,$defval=false) //storing a new session variable from POSTed variable.
{
global $HTTP_POST_VARS;
if( isset($HTTP_POST_VARS[$nam]) )
{
$GLOBALS[$nam] = $HTTP_POST_VARS[$nam];
$this->register($nam);
return true;
}
elseif( $this->is_registered($nam) )
return true;
if( !isset($GLOBALS[$nam]) && isset($defval) && $defval!='nodefault' ) $GLOBALS[$nam] = $defval;
return false;
}
function unregister($nam) //storing a new session variable.
{
if( isset($this->vars[$nam]) ) {unset($this->vars[$nam]);}
}
function get($nam) //returning current value of the session variable.
{
if( !isset($this->vars[$nam]) ) return '';
return $this->vars[$nam];
}
function get_sessionfile_name_internal()
{
if( !$this->id ) return '';
return session_save_path()."/sse_{$this->id}";
}
function garbage_collection_internal()
{
//limit garbage collection resource usage.
if( rand(1, 100) > $this->gc_probability )
return false;
dbg("garbage_collection_internal started");
$dir = dir(session_save_path());
while($entry = $dir->read())
{
if( strncmp($entry, 'sse_', 4)==0 )
{
$fnam = session_save_path()."/$entry";
$f = fopen($fnam, 'r');
if( $f )
{
$l1 = fgets($f, 100);
$l2 = fgets($f, 100);
fclose($f);
$this->check_expire_and_delete($l1,$l2,$fnam);
}
}
}//for each file in the dir.
$dir->close();
}
function delete_sessionfile_internal($fnam='')
{
if( !$fnam ) $fnam=$this->get_sessionfile_name_internal();
if( !$fnam ) return false;
dbg("delete_sessionfile_internal(fnam=$fnam)");
return unlink($fnam);
}
function check_expire_and_delete($line1,$line2,$filename)
{
if( $line1!="expiration\n" ) return false;
$expire = (int)($line2); //first 2 values: expiration name and value
if( $expire < time() ) //this session has been expired.
{
dbg("session expired and now will be deleted(filename=$filename)");
$this->delete_sessionfile_internal($filename);
return false;
}
return true;
}
function session_load_internal($newsesid)
{
dbg("session_load_internal started");
$this->active = false;
$this->vars = array();
//---getting session file name---
$this->id = $newsesid;
$fnam = $this->get_sessionfile_name_internal();
if( !$fnam || !file_exists($fnam) )
{
$this->id = '';
return false;
}
//---reading session file content---
$lines = file($fnam);
if( !is_array($lines) || count($lines)<2 )
{
$this->id = '';
return false;
}
//---checking session data expiration---
if( !$this->check_expire_and_delete($lines[0],$lines[1],$fnam) )
{
$this->id = '';
return false;
}
//---reading back session variables---
$n=count($lines);
for($i=2; $i<$n; $i+=2)
{
$varnam = rtrim($lines[$i]);
if( $varnam )
{
$varval = unserialize($lines[$i+1]);
$GLOBALS[$varnam] = $varval;
$this->vars[$varnam] = &$GLOBALS[$varnam];
dbg("session var retrieved: {$varnam}={$this->vars[$varnam]}");
}
}//for each line.
dbg("session_load_internal succeed");
$this->active = true;
}
function session_save_internal()
{
$fnam = '';
$fnam = $this->get_sessionfile_name_internal();
$f = fopen($fnam,'w');
dbg("session_save_internal: file overwritten=$fnam");
if( !$f )
{
err("Error: could not create session file '$fnam' - giving up (SimpleSession::session_save_internal)");
return false;
}
$expiration = time()+$this->lifetime;
fwrite($f,"expiration\n$expiration\n");
while( list($k,$v) = each($this->vars))
{
if( isset($v) ) //global variable possibly destroyed by the user using unset().
{
$v = serialize($v);
fwrite($f,"$k\n$v\n");
dbg("session_save_internal: written: varname=$k, value=$v");
}
}
fclose($f);
return true;
}
function session_start_internal()
{
dbg("session_start_internal started");
$this->active = false;
for($i=0; $i<100; $i++)
{
$this->id = md5(uniqid(rand()).'0123456789');
$fnam = $this->get_sessionfile_name_internal();
if( !file_exists($fnam) )
{
$f = fopen($fnam,'w');
if( $f )
{
fclose($f);
dbg("empty session file created: $fnam");
break;
}
}
$this->id = '';
}
if( !$this->id )
{
err("Error: could not create new session id, '$fnam' - giving up (SimpleSession::session_save_internal)");
return false;
}
$this->active = true;
dbg("session_start_internal succeed");
return true;
}
function session_unset()
{
$this->vars = array();
return true;
}
function session_destroy()
{
if( $this->active ) //this session has been expired.
$this->delete_sessionfile_internal();
$this->session_unset();
$this->active = false;
return true;
}
function session_start()
{
global $HTTP_GET_VARS,$HTTP_POST_VARS;
dbg("session_start() started");
if( $this->active ) return true;
$this->garbage_collection_internal();
if( isset($HTTP_GET_VARS[$this->name]) )
$this->session_load_internal($HTTP_GET_VARS[$this->name]);
elseif( isset($HTTP_POST_VARS[$this->name]) )
$this->session_load_internal($HTTP_POST_VARS[$this->name]);
if( !$this->active )
$this->session_start_internal();
return $this->active;
}
};
function dbg($msg) //for debugging messages.
{
//echo "$msg<br>\n";
}
function warn($msg) //for warning messages.
{
echo "$msg<br>\n";
}
function err($msg) //for error messages.
{
echo "$msg<br>\n";
}
//---------------
// ReqManager
// Request string parser class - for intelligent merging of values
//---------------
class ReqManager
{
var $reqvars;
function ReqManager()
{
global $HTTP_GET_VARS;
$this->reqvars = $HTTP_GET_VARS;
while( list($k,$v)=each($HTTP_GET_VARS) )
$this->reqvars[$k] = urldecode($v);
}
function clear()
{
$this->reqvars = array();
}
function request($startchar='?')
{
if( count($this->reqvars)<1 ) return '';
$req = '';
while( list($k,$v)=each($this->reqvars) )
{
if( $req ) $req .= '&';
$req .= "$k=".urlencode($v);
}
return "$startchar$req";
}
function add($nam,$val)
{
$this->reqvars[$nam] = $val;
}
function remove($nam,$val)
{
if( isset($this->reqvars[$nam]) )
{
unset($this->reqvars[$nam]);
return true;
}
return false;
}
function get($nam,$defval=false)
{
if( !isset($this->reqvars[$nam]) ) return $defval;
return $this->reqvars[$nam];
}
};
//----------------
?>
======================== END OF ses.php FILE ========================
======================== START OF ses1.php FILE ========================
<?
include_once('./ses.php');
global $session;
$session = new SimpleSession();
?>
<script language="JavaScript" src="ses.js"></script>
<script language="JavaScript">
function SafeSelfReload(removepg)
{
var fn = 'OklessForm';
var st = 'CarBrand';
var sr = 'CarColor';
var i,requests = splitURL();
var typefound=false;
var recnfound=false;
var pgidx=-1;
for(i=1; i<requests.length; i++) //first element is the page address: skip it.
{
if( requests[i][0]==st )
{
requests[i][1] = getformopt(fn,st);
typefound=true;
}
else
if( requests[i][0]==sr )
{
requests[i][1] = getformopt(fn,sr);
recnfound=true;
}
else
if( requests[i][0]=='pg' ) //note the position of the pagenum, which will be removed now by some reason.
pgidx=i;
}
if( !typefound ) requests[requests.length] = new Array(st,getformopt(fn,st));
if( !recnfound ) requests[requests.length] = new Array(sr,getformopt(fn,sr));
if( removepg ) requests = removeElement(requests,pgidx);
var newurl = assembleURL(requests);
location.href=newurl;
}
</script>
<?
if( !isset($myvar) )
{
global $myvar;
$myvar = 1;
$session->register('myvar');
}
if( !isset($origin) )
{
global $origin;
$origin = 'unknown';
$session->register('origin');
}
?>
<h1>First session test page</h1>
You are coming from page '<?= $origin ?>'. Welcome!<br>
Number of visited pages in the session: <?=$myvar?><br>
<!--Session ID: '<?=$session->session_id();?>'--><br>
<hr>
1. Transferring session ID with a URL:<br>
Please visit <a href="ses2.php<?=$session->Req();?>">2nd session test page</a>.<br>
<?
$session->register_from_POST('TextValue', ''); //read posted value and register it.
$session->register_from_GET ('TextValueGet','');
$session->register_from_GET ('CarBrand', 0);
$session->register_from_GET ('CarColor', 0);
?>
<hr>
2. Transferring session ID with a form POST:<br>
<form action="ses2.php?pg=2" method="post">
Fill up this field: <input type="text" name="TextValue" value="<?=$session->read('TextValue')?>">
<input type="submit" value="Go">
<?=$session->FormSID()?>
</form>
<hr>
3. Transferring session ID with a form GET:<br>
<form action="ses2.php<?=$session->Req()?>&pg=1" method="get">
Fill up this field: <input type="text" name="TextValueGet" value="<?=$session->read('TextValueGet')?>">
<input type="submit" value="Go">
<?=$session->FormSID()?>
</form>
<hr>
4. Transferring session ID to itself by client-side JavaScript - retaining other Request values:<br>
<form action="ses1.php" method="POST" name="OklessForm">
Car brand:
<select name="CarBrand" onChange="javascript:SafeSelfReload(1);return true;">
<option value="0" <?= $CarBrand<1 || $CarBrand>3 ? 'selected':'' ?> >-please select brand-</option>
<option value="1" <?= $CarBrand==1 ? 'selected':'' ?> >Ford T-Modell</option>
<option value="2" <?= $CarBrand==2 ? 'selected':'' ?> >Mitsubishi</option>
<option value="3" <?= $CarBrand==3 ? 'selected':'' ?> >Citroen</option>
</select>
Color:
<select name="CarColor" onChange="javascript:SafeSelfReload(1);return true;">
<option value="0" <?= $CarColor<1 || $CarColor>4 ? 'selected':'' ?> >-please select color-</option>
<option value="1" <?= $CarColor==1 ? 'selected':'' ?> >black</option>
<option value="2" <?= $CarColor==2 ? 'selected':'' ?> >not painted</option>
<option value="3" <?= $CarColor==3 ? 'selected':'' ?> >pink</option>
<option value="4" <?= $CarColor==4 ? 'selected':'' ?> >yellow</option>
</select>
</form>
<?
$origin = 'First test page';
$myvar++;
?>
<? $session->Save(); ?>
======================== END OF ses1.php FILE ========================
======================== START OF ses2.php FILE ========================
<?
include_once('./ses.php');
global $session;
$session = new SimpleSession();
if( !isset($myvar) )
{
global $myvar;
$myvar = 1;
$session->register('myvar');
}
if( !isset($origin) )
{
global $origin;
$origin = 'unknown';
$session->register('origin');
}
?>
<h1>Second session test page</h1>
You are coming from page '<?= $origin ?>'. Welcome!<br>
Number of visited pages in the session: <?=$myvar?><br>
<!--Session ID: '<?=$session->session_id()?>'--><br>
<hr>
1. Transferring session ID with a URL:<br>
Please visit <a href="ses1.php<?=$session->Req()?>">1st session test page</a>.<br>
<?
$session->register_from_POST('TextValue', ''); //read posted value and register it.
$session->register_from_GET ('TextValueGet','');
$session->register_from_GET ('CarBrand', 0);
$session->register_from_GET ('CarColor', 0);
?>
<hr>
2. Transferring session ID with a form POST:<br>
<form action="ses1.php" method="post">
Fill up this field: <input type="text" name="TextValue" value="<?=$session->read('TextValue')?>">
<input type="submit" value="Go">
<?=$session->FormSID()?>
</form>
<hr>
3. Transferring session ID with a form GET:<br>
<form action="ses1.php<?=$session->Req()?>" method="get">
Fill up this field: <input type="text" name="TextValueGet" value="<?=$session->read('TextValueGet')?>">
<input type="submit" value="Go">
<?=$session->FormSID()?>
</form>
<?
$origin = 'Second test page';
$myvar++;
?>
<? $session->Save(); ?>
======================== END OF ses2.php FILE ========================
that's all.