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 ([email protected]) // 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 ([email protected]) // 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 ([email protected]) // 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!="expirationn" ) 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,"expirationn$expirationn"); while( list($k,$v) = each($this->vars)) { if( isset($v) ) //global variable possibly destroyed by the user using unset(). { $v = serialize($v); fwrite($f,"$kn$vn"); 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.