pt[$thing] = true; } } } function is_registered($name) { if ($this->pt[$name] == true) return true; return false; } function unregister($things) { $things = explode(",", $things); reset($things); while (list(,$thing) = each($things)) { $thing = trim($thing); if ($thing) { unset($this->pt[$thing]); } } } ## get_id(): ## ## Propagate the session id according to mode and lifetime. ## Will create a new id if necessary. To take over abandoned sessions, ## one may provide the new session id as a parameter (not recommended). function get_id($id = "") { global $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS, $QUERY_STRING; $newid=true; $this->name = $this->cookiename==""?$this->classname:$this->cookiename; if ( "" == $id ) { $newid=false; switch ($this->mode) { case "get": if ("" == ($id = isset($HTTP_GET_VARS[$this->name]) ? $HTTP_GET_VARS[$this->name] : "")) $id = isset($HTTP_POST_VARS[$this->name]) ? $HTTP_POST_VARS[$this->name] : ""; break; case "cookie": $id = isset($HTTP_COOKIE_VARS[$this->name]) ? $HTTP_COOKIE_VARS[$this->name] : ""; break; default: die("This has not been coded yet."); break; } } if ( "" == $id ) { $newid=true; $id = $this->that->ac_newid(md5(uniqid($this->magic)), $this->name); } switch ($this->mode) { case "cookie": if ( $newid && ( 0 == $this->lifetime ) ) { SetCookie($this->name, $id, 0, "/", $this->cookie_domain); } if ( 0 < $this->lifetime ) { SetCookie($this->name, $id, time()+$this->lifetime*60, "/", $this->cookie_domain); } break; case "get": if ( isset($QUERY_STRING) ) { $QUERY_STRING = ereg_replace( "(^|&)".quotemeta(urlencode($this->name))."=".$id."(&|$)", "\\1", $QUERY_STRING); } break; default: ; break; } $this->id = $id; } ## put_id(): ## ## Stop using the current session id (unset cookie, ...) and ## abandon a session. function put_id() { global $HTTP_COOKIE_VARS; $this->name = $this->cookiename==""?$this->classname:$this->cookiename; switch ($this->mode) { case "inline": die("This has not been coded yet."); break; case "get": die("This has not been coded yet."); break; default: SetCookie($this->name, "", 0, "/", $this->cookie_domain); $HTTP_COOKIE_VARS[$this->name] = ""; break; } } ## delete(): ## ## Delete the current session record and put the session id. function delete() { $this->that->ac_delete($this->id, $this->name); $this->put_id(); } ## url($url): ## ## Helper function: returns $url concatenated with the current ## session $id. function url($url){ $url=ereg_replace("[&?]+$", "", $url); switch ($this->mode) { case "get": $url .= ( strpos($url, "?") != false ? "&" : "?" ). urlencode($this->name)."=".$this->id; break; default: ; break; } return $url; } function purl($url) { print $this->url($url); } function self_url() { global $PHP_SELF, $QUERY_STRING; return $this->url($PHP_SELF. ((isset($QUERY_STRING) && ("" != $QUERY_STRING)) ? "?".$QUERY_STRING : "")); } function pself_url() { print $this->self_url(); } function hidden_session() { printf("\n", $this->name, $this->id); } function add_query($qarray) { global $PHP_SELF; global $QUERY_STRING; if ((isset($QUERY_STRING) && ("" != $QUERY_STRING)) || ($this->mode == "get")) { $sep_char = "&"; } else { $sep_char = "?"; } $qstring = ""; while (list($k, $v) = each($qarray)) { $qstring .= $sep_char . urlencode($k) . "=" . urlencode($v); $sep_char = "&"; } return $qstring; } function padd_query($qarray) { print $this->add_query($qarray); } ## serialize($prefix,&$str): ## ## appends a serialized representation of $$prefix ## at the end of $str. ## ## To be able to serialize an object, the object must implement ## a variable $classname (containing the name of the class as string) ## and a variable $persistent_slots (containing the names of the slots ## to be saved as an array of strings). ## ## You don't need to know... function serialize($prefix, $str) { static $t,$l,$k; ## Determine the type of $$prefix eval("\$t = gettype(\$$prefix);"); switch ( $t ) { case "array": ## $$prefix is an array. Enumerate the elements and serialize them. eval("reset(\$$prefix); \$l = gettype(list(\$k)=each(\$$prefix));"); $str .= "\$$prefix = array(); "; while ( "array" == $l ) { ## Structural recursion $this->serialize($prefix."['".ereg_replace("([\\'])", "\\\\1", $k)."']", &$str); eval("\$l = gettype(list(\$k)=each(\$$prefix));"); } break; case "object": ## $$prefix is an object. Enumerate the slots and serialize them. eval("\$k = \$${prefix}->classname; \$l = reset(\$${prefix}->persistent_slots);"); $str.="\$$prefix = new $k; "; while ( $l ) { ## Structural recursion. $this->serialize($prefix."->".$l,&$str); eval("\$l = next(\$${prefix}->persistent_slots);"); } break; default: ## $$prefix is an atom. Extract it to $l, then generate code. eval("\$l = \$$prefix;"); $str.="\$$prefix = '".ereg_replace("([\\'])", "\\\\1", $l)."'; "; break; } } function get_lock() { $this->that->ac_get_lock(); } function release_lock() { $this->that->ac_release_lock(); } ## freeze(): ## ## freezes all registered things ( scalar variables, arrays, objects ) into ## a database table function freeze() { $str=""; $this->serialize("this->in",&$str); $this->serialize("this->pt",&$str); reset($this->pt); while ( list($thing) = each($this->pt) ) { $thing=trim($thing); if ( $thing ) { $this->serialize("GLOBALS['".$thing."']",&$str); } } $r = $this->that->ac_store($this->id, $this->name, $str); $this->release_lock(); if(!$r) $this->that->ac_halt("Session: freeze() failed."); } ## thaw: ## ## Reload frozen variables from the database and microwave them. function thaw() { $this->get_lock(); $vals = $this->that->ac_get_value($this->id, $this->name); eval(sprintf(";%s",$vals)); } ## ## Garbage collection ## ## Destroy all session data older than this ## function gc() { $this->that->ac_gc($this->gc_time, $this->name); } ## ## Variable precedence functions ## function reimport_get_vars() { $this->reimport_any_vars("HTTP_GET_VARS"); } function reimport_post_vars() { $this->reimport_any_vars("HTTP_POST_VARS"); } function reimport_cookie_vars() { $this->reimport_any_vars("HTTP_COOKIE_VARS"); } function reimport_any_vars($arrayname) { global $$arrayname; if (!is_array($$arrayname)) return; reset($$arrayname); while(list($key, $val) = each($$arrayname)) { $GLOBALS[$key] = $val; } } ## ## All this is support infrastructure for the start() method ## function set_container(){ $name = $this->that_class; $this->that = new $name; $this->that->ac_start(); } function set_tokenname(){ $this->name = $this->cookiename==""?$this->classname:$this->cookiename; } function release_token(){ global $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_HOST, $HTTPS; if ( isset($this->fallback_mode) && ( "get" == $this->fallback_mode ) && ( "cookie" == $this->mode ) && ( ! isset($HTTP_COOKIE_VARS[$this->name]) ) ) { if ( isset($HTTP_GET_VARS[$this->name]) ) { $this->mode = $this->fallback_mode; } else { header("Status: 302 Moved Temporarily"); if(!isset($sid)){ $sid=''; } $this->get_id($sid); $this->mode = $this->fallback_mode; if( isset($HTTPS) && $HTTPS == 'on' ){ ## You will need to fix suexec as well, if you use Apache and CGI PHP $PROTOCOL='https'; } else { $PROTOCOL='http'; } header("Location: ". $PROTOCOL. "://".$HTTP_HOST.$this->self_url()); exit; } } } function put_headers() { # Allowing a limited amount of caching, as suggested by # Padraic Renaghan on phplib@lists.netuse.de. # # Note that in HTTP/1.1 the Cache-Control headers override the Expires # headers and HTTP/1.0 ignores headers it does not recognize (e.g, # Cache-Control). Mulitple Cache-Control directives are split into # mulitple headers to better support MSIE 4.x. # # Added pre- and post-check for MSIE 5.x as suggested by R.C.Winters, # see http://msdn.microsoft.com/workshop/author/perf/perftips.asp#Use%20Cache-Control%20Extensions # for details switch ($this->allowcache) { case "passive": $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT"; header("Last-Modified: " . $mod_gmt); # possibly ie5 needs the pre-check line. This needs testing. header("Cache-Control: post-check=0, pre-check=0"); break; case "public": $exp_gmt = gmdate("D, d M Y H:i:s", time() + $this->allowcache_expire * 60) . " GMT"; $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT"; header("Expires: " . $exp_gmt); header("Last-Modified: " . $mod_gmt); header("Cache-Control: public"); header("Cache-Control: max-age=" . $this->allowcache_expire * 60); break; case "private": $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT"; header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . $mod_gmt); header("Cache-Control: private"); header("Cache-Control: max-age=" . $this->allowcache_expire * 60); header("Cache-Control: pre-check=" . $this->allowcache_expire * 60); break; default: header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-cache"); header("Cache-Control: post-check=0, pre-check=0"); header("Pragma: no-cache"); break; } } ## ## Garbage collection ## ## Destroy all session data older than this ## function gc() { srand(time()); if ((rand()%100) < $this->gc_probability) { $this->that->ac_gc($this->gc_time, $this->name); } } ## ## Initialization ## function start($sid = "") { $this->set_container(); $this->set_tokenname(); $this->release_token($sid); $this->put_headers(); $this->get_id($sid); $this->thaw(); $this->gc(); } } ?>