Source for file session-defs.php

Documentation is available at session-defs.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: session-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for managing SESSIONS. */
  24. /* We regard the session as a generic thing which will be */
  25. /* constant in functionality and data across any */
  26. /* application we might write. It deals only with the */
  27. /* the basics of user identity, group membership and */
  28. /* maintaining this across multiple page accesses within */
  29. /* the website. For context variables which will differ */
  30. /* from application to application, see context-defs.php. */
  31. /* */
  32. /* ******************************************************************** */
  33. /** @package core */// SESSION DATABASE OPTIONS
  34. // The user session can be backed by a database, or not. This allows
  35. // simple code-only websites to be implemented, where there is no
  36. // need to track users, sessions and other data.
  37.  
  38. /** Session is backed by a database connection */
  39. ("SESS_DATABASE_BACKED", true );
  40. /** Session is standalone, no database */
  41. ("SESS_STANDALONE", false );
  42.  
  43. // -----------------------------------------------------------------------
  44. // SESSION LIFETIMES
  45. // This value is the number of seconds that you wish a session cookie
  46. // lifetime to be, before it is deemed to have expired. Common choices
  47. // are provided as defines, otherwise use your own value.
  48.  
  49. /** Session lasts forever.. well, 10 years is near enough. */
  50. ("SESS_FOREVER", SECS_10_YEARS);
  51. /** Session lasts for 1 year */
  52. ("SESS_1_YEAR", SECS_1_YEAR);
  53. /** Session lasts for 1 month */
  54. ("SESS_1_MONTH", SECS_1_MONTH);
  55. /** Session lasts for 1 week */
  56. ("SESS_1_WEEK", SECS_1_WEEK);
  57. /** Session lasts for 24 hours */
  58. ("SESS_1_DAY", SECS_1_DAY);
  59. /** Session lasts for 12 hours */
  60. ("SESS_12_HOURS", SECS_12_HOURS);
  61. /** Session lasts for 8 hours */
  62. ("SESS_8_HOURS", SECS_8_HOURS);
  63. /** Session lasts for 4 hours */
  64. ("SESS_4_HOURS", SECS_4_HOURS);
  65. /** Session lasts for 1 hour */
  66. ("SESS_1_HOUR", SECS_1_HOUR);
  67. /** Session lasts for 20 minutes */
  68. ("SESS_20_MINS", SECS_20_MINS);
  69. /** Session lasts as long as user browser is open */
  70. ("SESS_BROWSER_LIFETIME", -1);
  71. /** Session has no lifetime, immediate expiry */
  72. ("SESS_ZERO_LIFETIME", 0);
  73.  
  74. // -----------------------------------------------------------------------
  75. // SESSION LOGIN LIMIT ACTION
  76. // Possibilities for handling a login limit which has been exceeded.
  77.  
  78. /** Login limit exceeded: Allow, assume app. takes action */
  79. ("SESS_ALLOW", 0);
  80. /** Login limit exceeded: Allow session, cull oldest */
  81. ("SESS_ALLOW_CULL", 1);
  82. /** Login limit exceeded: Block session, nice message */
  83. ("SESS_BLOCK_MSG", 2);
  84. /** Login limit exceeded: Block session, no message */
  85. ("SESS_BLOCK_SILENT", 3);
  86. /** Login limit exceeded: Block session, redirect to URL */
  87. ("SESS_BLOCK_REDIRECT", 4);
  88. /** Login limit exceeded: Block session, login as guest instead */
  89. ("SESS_BLOCK_GUEST", 5);
  90.  
  91. // -----------------------------------------------------------------------
  92. // SESSION LOGIN TYPE CODES
  93. // This flags the way the user originally logged in.
  94.  
  95. /** No known login has been achieved */
  96. ("LOGIN_UNKNOWN", 0);
  97. /** Login by using guest account */
  98. ("LOGIN_BY_GUEST", 1);
  99. /** Login by remote IP address match */
  100. ("LOGIN_BY_IP", 2);
  101. /** Login by standard username/password */
  102. ("LOGIN_BY_PASSWD", 3);
  103. /** Login by using authorisation code (MD5 string usually) */
  104. ("LOGIN_BY_AUTHCODE", 4);
  105.  
  106. // -----------------------------------------------------------------------
  107. /**
  108. * THE SESSION CLASS
  109. * A class to manage user sessions. A session is simply a thing which
  110. * contains information about a user who has logged on to the system,
  111. * so in fact the session is just an extension of a user.
  112. * To access the system a user must either create a new session, or
  113. * recover an existing session. A new session is created if the user
  114. * provides login details: userid/password or unique $authid (MD5).
  115. * An existing session may be 'recovered' if the login details are
  116. * absent, and if a cookie is sent containing a valid session key.
  117. * @package core
  118. */
  119. class session extends user {
  120. /** The ID of this session */
  121.  
  122. var $session_id = false;
  123. /** The type of this session */
  124.  
  125. var $db_backed = SESS_DATABASE_BACKED;
  126. /** The session record complete */
  127.  
  128. var $session_record;
  129. /** The session lifetime, in seconds */
  130.  
  131. var $lifetime = 0;
  132. /** True if we should limit 'guest' to browser lifetime */
  133.  
  134. var $guest_browser_lifetime = false;
  135. /** The session cookie name */
  136.  
  137. var $cookiename = "";
  138. /** Time of last login (Unix timestamp) */
  139.  
  140. var $last_logintime = 0;
  141. /** Error condition message if any */
  142.  
  143. var $error_message = "";
  144. /** Option to take on logins exceeded for user */
  145.  
  146. var $logins_exceeded_option = SESS_ALLOW_CULL;
  147. /** Custom message to deliver when blocking */
  148.  
  149. var $logins_exceeded_msg = "";
  150. /** URL to redirect to on logins exceeded */
  151.  
  152. var $logins_exceeded_redirect = "";
  153. /** Login type for this session */
  154.  
  155. var $login_type = LOGIN_BY_PASSWD;
  156. /** Whether we are tracking session logins */
  157.  
  158. var $session_track_logins = true;
  159. // .....................................................................
  160. /**
  161. * Constructor
  162. * Create a new session.
  163. * Initial creation of the session object does nothing.
  164. * The activate() method sets it up, when called.
  165. */
  166. function session() {
  167. $this->session_clear();
  168. } // session
  169. // .....................................................................
  170. /**
  171. * Retrieve the session cookie
  172. * This function looks for the cookie which is appropriate to the
  173. * current application, and returns the session ID if the cookie
  174. * was submitted. Returns false otherwise..
  175. * @return mixed The session ID as a string, or false
  176. * @access private
  177. */
  178. function get_session_cookie() {
  179. $session_id = false;
  180. $cookiename = $this->cookiename;
  181. global $$cookiename;
  182. if (isset($$cookiename)) {
  183. $session_id = $$cookiename;
  184. }
  185. return $session_id;
  186. } // get_session_cookie
  187. // .....................................................................
  188. /**
  189. * Identify the user/client
  190. * Here is where we activate our session. This involves searching
  191. * for the cookie, username/password sequence, or authorisation
  192. * code which will allow us to identify the requester and create
  193. * the proper session for them to access the website..
  194. * @return bool True if we succeeded in identifying the user, else false
  195. */
  196. function identify_user() {
  197. // Access to the vars..
  198. global $tbxUsername, $user; // Userid textbox fieldname submitted from a form
  199. global $tbxPassword, $pass; // Password textbox fieldname submitted from a form
  200. global $chkRememberMe; // Checkbox specific user request for extended cookie life
  201. global $tbxLogoff; // Logoff hidden field sent from a form
  202. global $authid; // Authorisation code (MD5) from form or URL
  203. global $REMOTE_ADDR; // IP address of remote browser/client
  204.  
  205. // Map alternative fieldnames onto standard ones..
  206. if (isset($user) && $user != "" && !isset($tbxUsername)) $tbxUsername = $user;
  207. if (isset($pass) && $pass != "" && !isset($tbxPassword)) $tbxPassword = $pass;
  208.  
  209. // Initialise some variables..
  210. $this->session_clear();
  211. $this->user();
  212.  
  213. // If no database we are not tracking sessions..
  214. if (!$this->db_backed) return true;
  215.  
  216. // Turn tracing on..
  217. debug_trace($this);
  218.  
  219. // SUBMITTED COOKIE
  220. // Gather in any submitted cookie..
  221. $session_id = $this->get_session_cookie();
  222.  
  223. // LOGIN via SUBMITTED AUTHORISATION
  224. // Now we check for login/logoff action. Clear out any session id
  225. // if they have submitted a login, or an authorisation code..
  226. if (((isset($tbxUsername) && $tbxUsername != "") && (isset($tbxPassword) && $tbxPassword != ""))
  227. || (isset($authid))
  228. ) {
  229. // Clear any existing session..
  230. debugbr("authorisation detected, clearing session", DBG_DEBUG);
  231. $session_id = false;
  232. $this->session_clear();
  233. }
  234.  
  235. // EXISTING SESSION RECOVERY
  236. // If we still have a session id, then we try recovery..
  237. if ($session_id) {
  238. debugbr("session id detected.", DBG_DEBUG);
  239. if ($this->recover($session_id)) {
  240. // Check if they want to logoff..
  241. debugbr("recovered session: '$this->session_id'", DBG_DEBUG);
  242. if (isset($tbxLogoff) && strcasecmp($tbxLogoff, "logoff") == 0) {
  243. debugbr("identify_user: user $this->userid logging off, deleting session", DBG_AUTH);
  244. $this->session_delete();
  245. }
  246. else {
  247. // Special case: where recovered session is a GUEST session. In
  248. // this case we check for a possible IP login, so that these
  249. // users don't get marooned in a guest login session..
  250. if ($this->login_type == LOGIN_BY_GUEST) {
  251. debugbr("guest recovered: checking for IP authentication..", DBG_DEBUG);
  252. $login_type = $this->authenticate_ipaddress($REMOTE_ADDR);
  253. if ($login_type != LOGIN_UNKNOWN) {
  254. $this->session_create($login_type);
  255. }
  256. else {
  257. // Keep the original guest authentication..
  258. debugbr("falling back to guest", DBG_DEBUG);
  259. $this->valid = true;
  260. $this->authenticated = true;
  261. }
  262. }
  263. }
  264. }
  265. } // existing session
  266.  
  267. // NEW SESSION CREATION
  268. // If no real session id exists at this point then check
  269. // for a username and password or an authorisation code
  270. // and log them in..
  271. if (!$this->session_id) {
  272. $authenticated = false;
  273. debugbr("no session, looking to create new one", DBG_DEBUG);
  274.  
  275. // AUTH CODE AUTHENTICATION..
  276. if (!$authenticated && isset($authid)) {
  277. debugbr("trying authid authentication..", DBG_DEBUG);
  278. $login_type = $this->authenticate_authid($authid);
  279. if ($login_type != LOGIN_UNKNOWN) {
  280. $this->session_create($login_type);
  281. $authenticated = true;
  282. }
  283. }
  284.  
  285. // IP ADDRESS AUTHENTICATION..
  286. if (!$authenticated && !isset($tbxUsername)) {
  287. debugbr("trying IP authentication..", DBG_DEBUG);
  288. $login_type = $this->authenticate_ipaddress($REMOTE_ADDR);
  289. if ($login_type != LOGIN_UNKNOWN) {
  290. $this->session_create($login_type);
  291. $authenticated = true;
  292. }
  293. }
  294.  
  295. // USERNAME/PASSWORD AUTHENTICATION..
  296. // Login with userid/password. If none provided then we default
  297. // them to 'guest'. For websites which are subscriber-only we
  298. // expect the application code to handle it.
  299. if (!$authenticated) {
  300. // Default to guest, if no login supplied..
  301. if (!isset($tbxUsername)) {
  302. debugbr("username not set, falling back to guest", DBG_DEBUG);
  303. $tbxUsername = "guest";
  304. }
  305. if (!isset($tbxPassword)) $tbxPassword = "";
  306. $tbxUsername = trim($tbxUsername);
  307.  
  308. // Authenticate the login attempt. If successful, this
  309. // populates the user and usergroups information..
  310. $login_type = $this->authenticate_userid($tbxUsername, $tbxPassword);
  311. if ($login_type != LOGIN_UNKNOWN) {
  312. // Check for user request to extend cookie life..
  313. if (isset($chkRememberMe)) {
  314. debugbr("forcing session lifetime to forever", DBG_DEBUG);
  315. $this->set_lifetime(SESS_FOREVER);
  316. }
  317. $this->session_create($login_type);
  318. $authenticated = true;
  319. // Logging of non-guest login details..
  320. if ($this->userid != "guest") {
  321. if ($this->passwd_forever) {
  322. debugbr("get_user_by_id: password expiry: forever", DBG_AUTH);
  323. }
  324. else {
  325. debugbr("get_user_by_id: password expiry: "
  326. . timestamp_to_displaydate(NICE_FULLDATETIME, $this->passwd_expiry_ts),
  327. DBG_AUTH
  328. );
  329. }
  330. debugbr("get_user_by_id: last login: "
  331. . timestamp_to_displaydate(NICE_FULLDATETIME, $this->last_login_ts),
  332. DBG_AUTH
  333. );
  334. if ($this->passwd_failures > 0) {
  335. debugbr("get_user_by_id: login failures: $this->passwd_failures", DBG_AUTH);
  336. }
  337. if ($this->locked) {
  338. debugbr("get_user_by_id: account is locked", DBG_AUTH);
  339. }
  340. }
  341. }
  342. }
  343. } // new session
  344.  
  345. // Return status..
  346. if (debugging() && $this->session_valid()) {
  347. debug("session type: ", DBG_DEBUG);
  348. switch ($this->login_type) {
  349. case LOGIN_BY_GUEST:
  350. debugbr("guest", DBG_DEBUG);
  351. break;
  352. case LOGIN_BY_IP:
  353. debugbr("authorised by IP address", DBG_DEBUG);
  354. break;
  355. case LOGIN_BY_PASSWD:
  356. debugbr("authorised by userid/password", DBG_DEBUG);
  357. break;
  358. case LOGIN_BY_AUTHCODE:
  359. debugbr("authorised by auth code", DBG_DEBUG);
  360. break;
  361. default:
  362. debugbr("unknown", DBG_DEBUG);
  363. } // switch
  364. }
  365. return $this->session_valid();
  366.  
  367. debug_trace();
  368. } // identify_user
  369. // ....................................................................
  370. /**
  371. * Check if we should bump our login count.
  372. * @access private
  373. */
  374. function track_logins() {
  375. if ($this->login_type != LOGIN_BY_GUEST && $this->session_track_logins === true) {
  376. debugbr("session login tracking is enabled", DBG_DEBUG);
  377. debug_trace($this);
  378. // Timestamp of now...
  379. $tinow = time();
  380. $dtnow = timestamp_to_datetime($tinow);
  381.  
  382. // Now check last login time. If the current time is more
  383. // than 4 hours later, then we increment the login count.
  384. if ( $tinow > ($this->last_logintime + SESS_4_HOURS) ) {
  385. if ($this->valid) {
  386. // Update the user record..
  387. $uQ = new dbupdate("ax_user");
  388. $uQ->set("total_logins", ($this->total_logins + 1));
  389. $uQ->set("last_login", $dtnow);
  390. $uQ->where("user_id='" . escape_string($this->userid) . "'");
  391. $uQ->execute();
  392.  
  393. // Update the session record..
  394. $uQ = new dbupdate("ax_wwwsession");
  395. $uQ->set("login_datetime", $dtnow);
  396. $uQ->where("session_id='$this->session_id'");
  397. $uQ->execute();
  398.  
  399. // Set the resident var..
  400. $this->last_logintime = $tinow;
  401. }
  402. }
  403. debug_trace();
  404. }
  405. else {
  406. debugbr("session login tracking is disabled", DBG_DEBUG);
  407. }
  408. } // track_logins
  409. // ...................................................................
  410. /**
  411. * Set logins exceeded action
  412. * This sets the action for when the number of logins for a given
  413. * user of the system exceeds a maximum, if specified. The options
  414. * for the action to take are:
  415. * SESS_ALLOW Allow, assume app. will take action
  416. * SESS_ALLOW_CULL Allow session, cull oldest
  417. * SESS_BLOCK_MSG Block session, nice message
  418. * SESS_BLOCK_SILENT Block session, no message
  419. * SESS_BLOCK_REDIRECT Block session, redirect to URL
  420. * SESS_BLOCK_GUEST Block session, login as guest instead
  421. */
  422. function on_logins_exceeded($option=SESS_ALLOW_CULL, $parm="") {
  423. $this->logins_exceeded_option = $option;
  424. switch ($option) {
  425. case SESS_BLOCK_REDIRECT:
  426. $this->logins_exceeded_redirect = $parm;
  427. break;
  428. case SESS_BLOCK_MSG:
  429. $this->logins_exceeded_msg = $parm;
  430. break;
  431. } // switch
  432. } // on_logins_exceeded
  433. // ....................................................................
  434. /**
  435. * Check for any excess sessions over and above the number which are
  436. * allowed for this user. We may cull oldest sessions first, or take
  437. * other actions as specified in the $RESPONSE.
  438. * @access private
  439. */
  440. function check_excess_sessions() {
  441. global $RESPONSE;
  442. debug_trace($this);
  443. // Check for multiple login limit restriction..
  444. if ($this->limit_logins > 0) {
  445. debugbr("checking login limit of $this->limit_logins.", DBG_DEBUG);
  446. $q = "SELECT session_id";
  447. $q .= " FROM ax_wwwsession";
  448. $q .= " WHERE user_id='" . escape_string($this->userid) . "'";
  449. $q .= " ORDER BY login_datetime";
  450. $loginQ = dbrecordset($q);
  451. // We do +1 to take account of the login we will be
  452. // adding as part of this process shortly..
  453. $excesslogins = 1 + $loginQ->rowcount - $this->limit_logins;
  454. if ($excesslogins > 0) {
  455. debugbr("oops: " . ($loginQ->rowcount) . " logins already; $excesslogins too many.", DBG_DEBUG);
  456. switch ($this->logins_exceeded_option) {
  457. case SESS_ALLOW:
  458. // Do nothing. This is for when the developer
  459. // wants to handle it at application level..
  460. break;
  461. case SESS_ALLOW_CULL:
  462. // Delete the number we need, starting with the oldest..
  463. for ($ix=0; $ix < $excesslogins; $ix++) {
  464. $sessid = $loginQ->field("session_id");
  465. dbcommand("DELETE FROM ax_wwwsession WHERE session_id='$sessid'");
  466. $loginQ->get_next();
  467. } // for
  468. error_log(APP_NAME . ": User '$this->userid' excess logins($excesslogins) triggered a session cull.", 0);
  469. break;
  470. case SESS_BLOCK_MSG:
  471. // Stop the process dead, with nice message in the browser..
  472. if ($RESPONSE->browser_type == BROWSER_HTML || $RESPONSE->browser_type == BROWSER_XHTML) {
  473. $msg = $RESPONSE->logins_exceeded_msg;
  474. if ($msg == "") {
  475. $msg = "<h2>". APP_NAME . " Login Count Exceeded</h2>\n";
  476. $msg .= "<p>You have exceeded your login count. If you closed your browser ";
  477. $msg .= "on another computer, and you are trying to login somewhere else ";
  478. $msg .= "you will have to log off the first machine before you can do so ";
  479. $msg .= "due to the login restrictions on your account.</p>";
  480. $msg .= "<p>Sorry for any inconvenience.</p>";
  481. }
  482. die("<html><body>\n" . $msg . "</body></html>\n");
  483. }
  484. else {
  485. die();
  486. }
  487. break;
  488. case SESS_BLOCK_SILENT:
  489. // Stop the process dead, no message, no nuthin'
  490. // and lucky to get that!
  491. die();
  492. break;
  493. case SESS_BLOCK_REDIRECT:
  494. // Redirect to a given page instead of logging in..
  495. header("Location: $this->logins_exceeded_redirect");
  496. break;
  497. case SESS_BLOCK_GUEST:
  498. // Let them log in, but as a guest instead..
  499. if (!($this->user("guest") && $this->enabled)) {
  500. $this->crash(500);
  501. }
  502. break;
  503.  
  504. } // switch
  505. }
  506. else {
  507. debugbr("no excess logins.", DBG_DEBUG);
  508. }
  509. }
  510. debug_trace();
  511. } // check_excess_sessions
  512. // .....................................................................
  513. /** Recover session
  514. * Recover an existing session. This will obliterate any pre-existing
  515. * session information in this object, since we expect it to succeed..
  516. * @return mixed Session ID or else false
  517. */
  518. function recover($session_id) {
  519. debug_trace($this);
  520. $this->session_clear();
  521. if (!empty($session_id)) {
  522. $session = dbrecordset("SELECT * FROM ax_wwwsession WHERE session_id='$session_id'");
  523. if ($session->hasdata) {
  524. // Find user record and check enabled..
  525. $this->user($session->field("user_id"));
  526. if (!$this->locked) {
  527. if ($this->enabled) {
  528. $this->session_id = $session_id;
  529. $this->userid = $session->field("user_id");
  530. $this->session_record = $session->current_row;
  531. $this->login_type = $session->field("login_type");
  532. $this->last_logintime = datetime_to_timestamp($session->field("login_datetime"));
  533. // This writes login total to the uuser record, and
  534. // login datetime to the wwwsession record..
  535. $this->track_logins();
  536. debugbr("found session record.", DBG_DEBUG);
  537. }
  538. else {
  539. debugbr("session rejected: user '" . $session->field("user_id") . "' not enabled", DBG_DEBUG);
  540. $this->valid = false;
  541. }
  542. }
  543. else {
  544. debugbr("session rejected: '" . $session->field("user_id") . "' account is locked", DBG_DEBUG);
  545. $this->valid = false;
  546. }
  547. }
  548. else {
  549. // Invalidate session and clear cookie..
  550. debugbr("no valid session record found: clearing session data and cookie.", DBG_DEBUG);
  551. $this->session_clear();
  552. $this->delete_cookie();
  553. }
  554. }
  555. debug_trace();
  556.  
  557. // Return session id, or else 'false'..
  558. return $this->session_id;
  559. } // recover
  560. // .....................................................................
  561. /**
  562. * Set the session cookie.
  563. * @param string $content The content of the cookie
  564. * @param integer $expires The Unix time() value for expiry datetime of the cookie
  565. */
  566. function set_cookie($content, $expires=false) {
  567. global $RESPONSE;
  568. global $_SERVER;
  569. if (!isset($RESPONSE)
  570. || $RESPONSE->browser_type == BROWSER_TYPE_HTML
  571. || $RESPONSE->browser_type == BROWSER_TYPE_XHTML
  572. ) {
  573. if ($expires === false) {
  574. debug("cookie lifetime: ", DBG_DEBUG);
  575. if ($this->lifetime == SESS_BROWSER_LIFETIME
  576. || ($this->guest_browser_lifetime && $this->userid == "guest")
  577. ) {
  578. // Cookie lasts for browser lifetime
  579. debugbr("until browser closed", DBG_DEBUG);
  580. $expires = 0;
  581. }
  582. else {
  583. // Cookie lasts for given number of seconds..
  584. $expires = time() + $this->lifetime;
  585. switch ($this->lifetime) {
  586. case SESS_FOREVER:
  587. debugbr("forever", DBG_DEBUG);
  588. break;
  589. default:
  590. debugbr("$this->lifetime secs", DBG_DEBUG);
  591. break;
  592. } // switch
  593. }
  594. }
  595. if (isset($RESPONSE) && $RESPONSE->browser == BROWSER_NETSCAPE) {
  596. debugbr("Setting Netscape cookie ".$this->cookiename.": $content, $expires", DBG_DEBUG);
  597. setcookie($this->cookiename, $content, $expires);
  598. }
  599. else {
  600. if ($_SERVER["SERVER_ADDR"] == "127.0.0.1") {
  601. debugbr("Server running on localhost - setting cookie ".$this->cookiename.": $content, $expires, /", DBG_DEBUG);
  602. setcookie($this->cookiename, $content, $expires, "/");
  603. }
  604. else {
  605. debugbr("Setting cookie ".$this->cookiename.": $content, $expires, /, ".$this->http_host, DBG_DEBUG);
  606. setcookie($this->cookiename, $content, $expires, "/", $this->http_host);
  607. }
  608. }
  609. }
  610. } // set_cookie
  611. // .....................................................................
  612. /**
  613. * Delete session cookie
  614. * Deletes the session cookie from the user's browser.
  615. */
  616. function delete_cookie() {
  617. global $RESPONSE;
  618. debugbr("Expiring cookie ".$this->cookiename, DBG_DEBUG);
  619. if (!isset($RESPONSE)
  620. || $RESPONSE->browser_type == BROWSER_TYPE_HTML
  621. || $RESPONSE->browser_type == BROWSER_TYPE_XHTML
  622. ) {
  623. if (isset($RESPONSE) && $RESPONSE->browser == BROWSER_NETSCAPE) {
  624. setcookie($this->cookiename, "", time() - SESS_1_HOUR);
  625. }
  626. else {
  627. setcookie($this->cookiename, "", time() - SESS_1_HOUR, "/", $this->http_host);
  628. }
  629. }
  630. } // delete_cookie
  631. // ...................................................................
  632. /**
  633. * Set session database backing type
  634. * The database backing 'type' can be either SESS_DATABASE_BACKED, or
  635. * SESS_STANDALONE.
  636. * @param bool $type Session type
  637. */
  638. function set_sessiontype($type=SESS_DATABASE_BACKED) {
  639. $this->db_backed = $type;
  640. } // set_sessiontype
  641. // ...................................................................
  642. /**
  643. * Set session lifetime
  644. * Set the session cookie lifetime in seconds.
  645. * @param integer $secs Seconds lifetime for the session cookie
  646. */
  647. function set_lifetime($secs=SESS_1_DAY) {
  648. $this->lifetime = $secs;
  649. } // set_lifetime
  650. // ...................................................................
  651. /**
  652. * Set session cookie name. This method protects against silliness
  653. * by detecting nullstring cookienames, and re-defining them to a
  654. * default name based on the application prefix. Null cookienames
  655. * are a very bad idea all around.
  656. * @param string $name Cookie name to use for session ID
  657. */
  658. function set_cookiename($name="session_id") {
  659. if ($name == "") {
  660. $name = APP_PREFIX . "_session_id";
  661. }
  662. $this->cookiename = $name;
  663. } // set_cookiename
  664. // ...................................................................
  665. /**
  666. * Set session guest browser lifetime flag
  667. * If set True this causes the cookie lifetime to be forced to the
  668. * browser lifetime if the user is 'guest'.
  669. * @param bool $guest_browser_lifetime True if guest cookie limited to browser lifetime
  670. */
  671. function set_guest_browser_lifetime($guest_browser_lifetime=false) {
  672. $this->guest_browser_lifetime = $guest_browser_lifetime;
  673. } // set_guest_browser_lifetime
  674. // ...................................................................
  675. /**
  676. * Set session track logins flag
  677. * If set True this causes the session logins for this site to be tracked for
  678. * each user. This amounts to an extra DB update of a login count field.
  679. * @param bool $session_track_logins True if we should track all user logins
  680. */
  681. function set_session_track_logins($session_track_logins=false) {
  682. $this->session_track_logins = $session_track_logins;
  683. } // session_track_logins
  684. // .....................................................................
  685. /**
  686. * Create new session
  687. * Make a brand new session for the user.
  688. * @param integer $logintype Type of login for this session
  689. */
  690. function session_create($logintype=LOGIN_BY_PASSWD) {
  691. debug_trace($this);
  692.  
  693. // Check for any excess sessions first..
  694. $this->check_excess_sessions();
  695.  
  696. // Get next session key, and create session..
  697.  
  698. // Generate a unique session handle..
  699. $this->session_id = md5(uniqid(rand(),1));
  700.  
  701. // Initialise the login detail..
  702. $this->login_type = $logintype;
  703. $this->last_logintime = time();
  704. // If we are tracking logins, and it's a real user, then we set the
  705. // login datetime far enough back for the track_logins() method to act..
  706. if ($this->session_track_logins && $this->login_type != LOGIN_BY_GUEST) {
  707. $this->last_logintime -= SESS_FOREVER;
  708. }
  709. // Create the new session..
  710. $ugroups = "";
  711. if (isset($this->user_groups)) {
  712. $ugroups = implode("|", $this->user_groups);
  713. }
  714. $wwwQ = new dbinsert("ax_wwwsession");
  715. $wwwQ->set("session_id", $this->session_id);
  716. $wwwQ->set("user_id", $this->userid);
  717. $wwwQ->set("user_groups", $ugroups);
  718. $wwwQ->set("login_type", $logintype);
  719. $wwwQ->set("login_datetime", timestamp_to_datetime($this->last_logintime));
  720.  
  721. // Create the record..
  722. $wwwQ->execute();
  723.  
  724. // Track logins for this user..
  725. $this->track_logins();
  726.  
  727. // Everything went Ok, so set the cookie for next time..
  728. if ($this->browser_type == BROWSER_TYPE_HTML || $this->browser_type == BROWSER_TYPE_XHTML) {
  729. // Set client session cookie, with appropriate lifetime..
  730. $this->set_cookie($this->session_id);
  731. }
  732.  
  733. debug_trace();
  734.  
  735. // Return session id, or else 'false'..
  736. return $this->session_id;
  737. } // session_create
  738. // .....................................................................
  739. /**
  740. * Delete the session
  741. * Delete the current session from the system.
  742. */
  743. function session_delete() {
  744. debug_trace($this);
  745. if ($this->session_id) {
  746. dbcommand("DELETE FROM ax_wwwsession WHERE session_id='$this->session_id'");
  747. $this->session_clear();
  748. }
  749. debug_trace();
  750. } // session_delete
  751. // .....................................................................
  752. /**
  753. * Clear session vars
  754. * Common method for clearing out the current session info
  755. * from the object variables.
  756. */
  757. function session_clear() {
  758. $this->session_id = false;
  759. if (isset($this->session_record)) {
  760. unset($this->session_record);
  761. }
  762. $this->last_logintime = 0;
  763. $this->error_message = "";
  764. } // session_clear
  765. // .....................................................................
  766. /**
  767. * Is session valid
  768. * Return validity status. If there is a session ID and a valid user
  769. * then the whole session is deemed valid, otherwise not.
  770. * @return bool True if this session is valid
  771. */
  772. function session_valid() {
  773. return ($this->valid && $this->session_id);
  774. } // session_valid
  775.  
  776. } // session class
  777. // -----------------------------------------------------------------------
  778.  
  779. ?>

Documentation generated by phpDocumentor 1.3.0RC3