PageRenderTime 33ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/ser-0.9.6/serweb-0.9.4/phplib/session.inc

#
PHP | 509 lines | 429 code | 33 blank | 47 comment | 35 complexity | 180e2e8554300d81cd2a73b94983b031 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0
  1. <?php
  2. /*
  3. * Session Management for PHP3
  4. *
  5. * Copyright (c) 1998-2000 NetUSE AG
  6. * Boris Erdmann, Kristian Koehntopp
  7. *
  8. * $Id: session.inc,v 1.4 2005/05/24 09:35:23 kozlik Exp $
  9. *
  10. */
  11. class Session {
  12. var $classname = "Session"; ## Needed for object serialization.
  13. ## Define the parameters of your session by either overwriting
  14. ## these values or by subclassing session (recommended).
  15. var $magic = ""; ## Some string you should change.
  16. var $mode = "cookie"; ## We propagate session IDs with cookies
  17. var $fallback_mode; ## If this doesn't work, fall back...
  18. var $lifetime = 0; ## 0 = do session cookies, else minutes
  19. var $cookie_domain = ""; ## If set, the domain for which the
  20. ## session cookie is set.
  21. var $gc_time = 1440; ## Purge all session data older than 1440 minutes.
  22. var $gc_probability = 5; ## Garbage collect probability in percent
  23. var $auto_init = ""; ## Name of the autoinit-File, if any.
  24. var $secure_auto_init = 1; ## Set to 0 only, if all pages call
  25. ## page_close() guaranteed.
  26. var $allowcache = "no"; ## "passive", "no", "private" or "public"
  27. var $allowcache_expire = 1440; ## If you allowcache, data expires in this
  28. ## many minutes.
  29. var $block_alien_sid = true; ## do not accept IDs in URL for session creation
  30. var $that_class = ""; ## Name of data storage container
  31. ##
  32. ## End of parameters.
  33. ##
  34. var $name; ## Session name
  35. var $id; ## Unique Session ID
  36. var $newid; ## Newly Generated ID Flag
  37. var $that;
  38. var $pt = array(); ## This Array contains the registered things
  39. var $in = 0; ## Marker: Did we already include the autoinit file?
  40. ## register($things):
  41. ##
  42. ## call this function to register the things that should become persistent
  43. function register($things) {
  44. $things = explode(",",$things);
  45. reset($things);
  46. while ( list(,$thing) = each($things) ) {
  47. $thing=trim($thing);
  48. if ( $thing ) {
  49. $this->pt[$thing] = true;
  50. }
  51. }
  52. }
  53. function is_registered($name) {
  54. if (isset($this->pt[$name]) && $this->pt[$name] == true)
  55. return true;
  56. return false;
  57. }
  58. function unregister($things) {
  59. $things = explode(",", $things);
  60. reset($things);
  61. while (list(,$thing) = each($things)) {
  62. $thing = trim($thing);
  63. if ($thing) {
  64. unset($this->pt[$thing]);
  65. }
  66. }
  67. }
  68. ## get_id():
  69. ##
  70. ## Propagate the session id according to mode and lifetime.
  71. ## Will create a new id if necessary. To take over abandoned sessions,
  72. ## one may provide the new session id as a parameter (not recommended).
  73. function get_id($id = "") {
  74. $this->newid=true;
  75. $this->name = $this->cookiename==""?$this->classname:$this->cookiename;
  76. if ( "" == $id ) {
  77. $this->newid=false;
  78. switch ($this->mode) {
  79. case "get":
  80. $id = isset($_GET[$this->name]) ?
  81. $_GET[$this->name] :
  82. ( isset($_POST[$this->name]) ?
  83. $_POST[$this->name] :
  84. "") ;
  85. break;
  86. case "cookie":
  87. $id = isset($_COOKIE[$this->name]) ?
  88. $_COOKIE[$this->name] : "";
  89. break;
  90. default:
  91. die("This has not been coded yet.");
  92. break;
  93. }
  94. }
  95. ### do not accept user provided ids for creation
  96. if($id != "" && $this->block_alien_sid) { # somehow an id was provided by the user
  97. if($this->that->ac_get_value($id, $this->name) == "") {
  98. # no - the id doesn't exist in the database: Ignore it!
  99. $id = "";
  100. }
  101. }
  102. if ( "" == $id ) {
  103. $this->newid=true;
  104. $id = $this->that->ac_newid(md5(uniqid($this->magic)), $this->name);
  105. }
  106. switch ($this->mode) {
  107. case "cookie":
  108. if ( $this->newid && ( 0 == $this->lifetime ) ) {
  109. SetCookie($this->name, $id, 0, "/", $this->cookie_domain);
  110. }
  111. if ( 0 < $this->lifetime ) {
  112. SetCookie($this->name, $id, time()+$this->lifetime*60, "/", $this->cookie_domain);
  113. }
  114. // Remove session ID info from QUERY String - it is in cookie
  115. if ( isset($_SERVER["QUERY_STRING"]) && ("" != $_SERVER["QUERY_STRING"]) ) {
  116. $_SERVER["QUERY_STRING"] = ereg_replace(
  117. "(^|&)".quotemeta(urlencode($this->name))."=(.)*(&|$)", ## subst *any* preexistent sess
  118. "\\1", $_SERVER["QUERY_STRING"]);
  119. }
  120. break;
  121. case "get":
  122. #we don't trust user input; session in url doesn't
  123. #mean cookies are disabled
  124. if ($this->newid &&( 0 == $this->lifetime )) { ## even if not a newid
  125. SetCookie($this->name, $id, 0, "/", $this->cookie_domain);
  126. }
  127. if ( 0 < $this->lifetime ) {
  128. SetCookie($this->name, $id, time()+$this->lifetime*60, "/", $this->cookie_domain);
  129. }
  130. if ( isset($_SERVER["QUERY_STRING"]) && ("" != $_SERVER["QUERY_STRING"]) ) {
  131. $_SERVER["QUERY_STRING"] = ereg_replace(
  132. # "(^|&)".quotemeta(urlencode($this->name))."=".$id."(&|$)",
  133. "(^|&)".quotemeta(urlencode($this->name))."=(.)*(&|$)", ## subst *any* preexistent sess
  134. "\\1", $_SERVER["QUERY_STRING"]);
  135. }
  136. break;
  137. default:
  138. ;
  139. break;
  140. }
  141. $this->id = $id;
  142. }
  143. ## put_id():
  144. ##
  145. ## Stop using the current session id (unset cookie, ...) and
  146. ## abandon a session.
  147. function put_id() {
  148. switch ($this->mode) {
  149. case "cookie":
  150. $this->name = $this->cookiename == "" ? $this->classname : $this->cookiename;
  151. SetCookie($this->name, "", 0, "/", $this->cookie_domain);
  152. $_COOKIE[$this->name] = "";
  153. break;
  154. default:
  155. // do nothing. We don't need to die for modes other than cookie here.
  156. break;
  157. }
  158. }
  159. ## delete():
  160. ##
  161. ## Delete the current session record and put the session id.
  162. function delete() {
  163. $this->that->ac_delete($this->id, $this->name);
  164. $this->put_id();
  165. }
  166. ## url($url):
  167. ##
  168. ## Helper function: returns $url concatenated with the current
  169. ## session $id.
  170. function url($url) {
  171. // Remove existing session info from url
  172. $url = ereg_replace(
  173. # "([&?])".quotemeta(urlencode($this->name))."=".$this->id."(&|$)",
  174. "([&?])".quotemeta(urlencode($this->name))."=(.)*(&|$)", # we clean any(also bogus) sess in url
  175. "\\1", $url);
  176. // Remove trailing ?/& if needed
  177. $url=ereg_replace("[&?]+$", "", $url);
  178. switch ($this->mode) {
  179. case "get":
  180. $url .= ( strpos($url, "?") != false ? "&" : "?" ).
  181. urlencode($this->name)."=".$this->id;
  182. break;
  183. default:
  184. ;
  185. break;
  186. }
  187. // Encode naughty characters in the URL
  188. $url = str_replace(array("<", ">", " ", "\"", "'"),
  189. array("%3C", "%3E", "+", "%22", "%27"), $url);
  190. return $url;
  191. }
  192. function purl($url) {
  193. print $this->url($url);
  194. }
  195. function self_url() {
  196. return $this->url($_SERVER["PHP_SELF"] .
  197. ((isset($_SERVER["QUERY_STRING"]) && ("" != $_SERVER["QUERY_STRING"]))
  198. ? "?" . $_SERVER["QUERY_STRING"] : ""));
  199. }
  200. function pself_url() {
  201. print $this->self_url();
  202. }
  203. function hidden_session()
  204. {
  205. printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n", $this->name, $this->id);
  206. }
  207. function add_query($qarray) {
  208. if ((isset($_SERVER["QUERY_STRING"])
  209. && ("" != $_SERVER["QUERY_STRING"]))
  210. || ($this->mode == "get")) {
  211. $sep_char = "&";
  212. } else {
  213. $sep_char = "?";
  214. }
  215. $qstring = "";
  216. while (list($k, $v) = each($qarray)) {
  217. $qstring .= $sep_char . urlencode($k) . "=" . urlencode($v);
  218. $sep_char = "&";
  219. }
  220. return $qstring;
  221. }
  222. function padd_query($qarray) {
  223. print $this->add_query($qarray);
  224. }
  225. ## serialize($var,&$str):
  226. ##
  227. ## appends a serialized representation of $$var
  228. ## at the end of $str.
  229. ##
  230. ## To be able to serialize an object, the object must implement
  231. ## a variable $classname (containing the name of the class as string)
  232. ## and a variable $persistent_slots (containing the names of the slots
  233. ## to be saved as an array of strings).
  234. function serialize($var, &$str) {
  235. static $t,$l,$k;
  236. ## Determine the type of $$var
  237. eval("\$t = gettype(\$$var);");
  238. switch ( $t ) {
  239. case "array":
  240. ## $$var is an array. Enumerate the elements and serialize them.
  241. eval("reset(\$$var); \$l = gettype(list(\$k)=each(\$$var));");
  242. $str .= "\$$var = array(); ";
  243. while ( "array" == $l ) {
  244. ## Structural recursion
  245. $this->serialize($var."['".ereg_replace("([\\'])", "\\\\1", $k)."']", $str);
  246. eval("\$l = gettype(list(\$k)=each(\$$var));");
  247. }
  248. break;
  249. case "object":
  250. ## $$var is an object. Enumerate the slots and serialize them.
  251. eval("\$k = \$${var}->classname; \$l = reset(\$${var}->persistent_slots);");
  252. $str.="\$$var = new $k; ";
  253. while ( $l ) {
  254. ## Structural recursion.
  255. $this->serialize($var."->".$l, $str);
  256. eval("\$l = next(\$${var}->persistent_slots);");
  257. }
  258. break;
  259. default:
  260. ## $$var is an atom. Extract it to $l, then generate code.
  261. eval("\$l = \$$var;");
  262. $str.="\$$var = '".ereg_replace("([\\'])", "\\\\1", $l)."'; ";
  263. break;
  264. }
  265. }
  266. function get_lock() {
  267. $this->that->ac_get_lock();
  268. }
  269. function release_lock() {
  270. $this->that->ac_release_lock();
  271. }
  272. ## freeze():
  273. ##
  274. ## freezes all registered things ( scalar variables, arrays, objects ) into
  275. ## a database table
  276. function freeze() {
  277. $str="";
  278. $this->serialize("this->in", $str);
  279. $this->serialize("this->pt", $str);
  280. reset($this->pt);
  281. while ( list($thing) = each($this->pt) ) {
  282. $thing=trim($thing);
  283. if ( $thing ) {
  284. $this->serialize("GLOBALS['".$thing."']", $str);
  285. }
  286. }
  287. $r = $this->that->ac_store($this->id, $this->name, $str);
  288. $this->release_lock();
  289. if (!$r) $this->that->ac_halt("Session: freeze() failed.");
  290. }
  291. ## thaw:
  292. ##
  293. ## Reload frozen variables from the database and microwave them.
  294. function thaw() {
  295. $this->get_lock();
  296. $vals = $this->that->ac_get_value($this->id, $this->name);
  297. eval(sprintf(";%s",$vals));
  298. }
  299. ##
  300. ## Variable precedence functions
  301. ##
  302. function reimport_get_vars() {
  303. $this->reimport_any_vars("_GET");
  304. }
  305. function reimport_post_vars() {
  306. $this->reimport_any_vars("_POST");
  307. }
  308. function reimport_cookie_vars() {
  309. $this->reimport_any_vars("_COOKIE");
  310. }
  311. function reimport_any_vars($arrayname) {
  312. global $$arrayname;
  313. if (!is_array($$arrayname))
  314. return;
  315. reset($$arrayname);
  316. while(list($key, $val) = each($$arrayname)) {
  317. $GLOBALS[$key] = $val;
  318. }
  319. }
  320. ##
  321. ## All this is support infrastructure for the start() method
  322. ##
  323. function set_container() {
  324. $name = $this->that_class;
  325. $this->that = new $name;
  326. $this->that->ac_start();
  327. }
  328. function set_tokenname() {
  329. $this->name = $this->cookiename==""?$this->classname:$this->cookiename;
  330. }
  331. function release_token($sid = "") {
  332. # set the mode for this run
  333. if ( isset($this->fallback_mode)
  334. && ("get" == $this->fallback_mode)
  335. && ("cookie" == $this->mode)
  336. && (! isset($_COOKIE[$this->name])) ) {
  337. $this->mode = $this->fallback_mode;
  338. }
  339. if ($this->mode=="get") ## now it catches also when primary mode is get
  340. {
  341. $this->get_id($sid);
  342. if ($this->newid)
  343. {
  344. if ( isset($_SERVER["HTTPS"])
  345. && $_SERVER["HTTPS"] == 'on' ) {
  346. ## You will need to fix suexec as well, if you
  347. ## use Apache and CGI PHP
  348. $PROTOCOL = 'https';
  349. } else {
  350. $PROTOCOL = 'http';
  351. }
  352. $this->freeze();
  353. header("Status: 302 Moved Temporarily");
  354. header("Location: " . $PROTOCOL . "://" .
  355. $_SERVER["HTTP_HOST"] . $this->self_url());
  356. exit;
  357. }
  358. }
  359. }
  360. function put_headers() {
  361. # Allowing a limited amount of caching, as suggested by
  362. # Padraic Renaghan on phplib@lists.netuse.de.
  363. #
  364. # Note that in HTTP/1.1 the Cache-Control headers override the Expires
  365. # headers and HTTP/1.0 ignores headers it does not recognize (e.g,
  366. # Cache-Control). Mulitple Cache-Control directives are split into
  367. # mulitple headers to better support MSIE 4.x.
  368. #
  369. # Added pre- and post-check for MSIE 5.x as suggested by R.C.Winters,
  370. # see http://msdn.microsoft.com/workshop/author/perf/perftips.asp#Use%20Cache-Control%20Extensions
  371. # for details
  372. switch ($this->allowcache) {
  373. case "passive":
  374. $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT";
  375. header("Last-Modified: " . $mod_gmt);
  376. # possibly ie5 needs the pre-check line. This needs testing.
  377. header("Cache-Control: post-check=0, pre-check=0");
  378. break;
  379. case "public":
  380. $exp_gmt = gmdate("D, d M Y H:i:s", time() + $this->allowcache_expire * 60) . " GMT";
  381. $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT";
  382. header("Expires: " . $exp_gmt);
  383. header("Last-Modified: " . $mod_gmt);
  384. header("Cache-Control: public");
  385. header("Cache-Control: max-age=" . $this->allowcache_expire * 60, false);
  386. break;
  387. case "private":
  388. $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT";
  389. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  390. header("Last-Modified: " . $mod_gmt);
  391. header("Cache-Control: private");
  392. header("Cache-Control: max-age=" . $this->allowcache_expire * 60, false);
  393. header("Cache-Control: pre-check=" . $this->allowcache_expire * 60, false);
  394. break;
  395. default:
  396. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  397. header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  398. header("Cache-Control: no-cache");
  399. header("Cache-Control: post-check=0, pre-check=0", false);
  400. header("Pragma: no-cache");
  401. break;
  402. }
  403. }
  404. ##
  405. ## Garbage collection
  406. ##
  407. ## Destroy all session data older than this
  408. ##
  409. function gc() {
  410. srand(time());
  411. if ((rand()%100) < $this->gc_probability) {
  412. $this->that->ac_gc($this->gc_time, $this->name);
  413. }
  414. }
  415. ##
  416. ## Initialization
  417. ##
  418. function start($sid = "") {
  419. $this->set_container();
  420. $this->set_tokenname();
  421. $this->put_headers();
  422. $this->release_token($sid);
  423. $this->get_id($sid);
  424. $this->thaw();
  425. $this->gc();
  426. }
  427. }
  428. ?>