JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Fix db_get_value after mysql->mysqli upgrade
[wfpl.git] / session.php
index 3b96e84..75508c0 100644 (file)
@@ -1,19 +1,9 @@
 <?php
 
-#  Copyright (C) 2006 Jason Woofenden
-#
-#  This program is free software: you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation, either version 3 of the License, or
-#  (at your option) any later version.
-#  
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#  
-#  You should have received a copy of the GNU General Public License
-#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# This program is in the public domain within the United States. Additionally,
+# we waive copyright and related rights in the work worldwide through the CC0
+# 1.0 Universal public domain dedication, which can be found at
+# http://creativecommons.org/publicdomain/zero/1.0/
 
 
 # The functions in this file assume that you have this database table:
@@ -57,14 +47,12 @@ function session_generate_key() {
        return $id;
 }
 
-# start a new session.
-# by default it'll expire in 24 hours regardless of activity.
-# pass both args for a session that lasts longer if active.
-# sessions are tracked with a "session cookie" (dies on browser close)
-function session_new($idle_timeout = 86400, $max_timeout = 'same_as_idle') {
-       if ($max_timeout === 'same_as_idle') {
-               $max_timeout = $idle_timeout;
-       }
+# start a new session, tracked by a browser "session cookie".
+#
+# args:
+#    $idle_timeout (seconds) session ends after this much inactivity (or up to 10% less)
+#    $max_length (seconds) session ends after this long, regardless of activity
+function session_new($idle_timeout = 129600 /* 36 hours */, $max_length = 604800 /* 1 week */) {
        kill_session();
 
        $session_key = session_generate_key();
@@ -74,7 +62,7 @@ function session_new($idle_timeout = 86400, $max_timeout = 'same_as_idle') {
                'session_key' => $session_key,
                'idle_timeout' => $idle_timeout,
                'expires' => $now + $idle_timeout,
-               'expires_max' => $now + $max_timeout,
+               'expires_max' => $now + $max_length,
                'value' => ''
        );
 
@@ -84,9 +72,9 @@ function session_new($idle_timeout = 86400, $max_timeout = 'same_as_idle') {
                'exists' => true,
                'id' => $session_id,
                'key' => $session_key,
-               'idle_timeout' => $row['idle_timeout'],
-               'expires' => $row['expires'],
-               'expires_max' => $row['expires_max'],
+               'idle_timeout' => $idle_timeout,
+               'expires' => $now + $idle_timeout,
+               'expires_max' => $now + $max_length,
                'value' => array()
        );
        session_set_cookie();
@@ -111,13 +99,16 @@ function session_touch() {
        if ($GLOBALS['wfpl_session']['expires'] < $GLOBALS['wfpl_session']['expires_max']) {
                # would this extend the session by at least 10%?
                $now = time();
-               $session_start = $GLOBALS['wfpl_session']['expires'] - $GLOBALS['wfpl_session']['idle_timeout'];
-               if ($now > $session_start + ceil(0.1 * $GLOBALS['wfpl_session']['idle_timeout'])) {
-                       $expires = max(
+               $last_activity = $GLOBALS['wfpl_session']['expires'] - $GLOBALS['wfpl_session']['idle_timeout'];
+               # don't db_update if only a tiny fraction of the idle timeout has passed
+               $db_threshold = ceil(0.1 * $GLOBALS['wfpl_session']['idle_timeout']);
+               if ($now > $last_activity + $db_threshold) {
+                       $expires = min(
                                $GLOBALS['wfpl_session']['expires_max'],
                                $now + $GLOBALS['wfpl_session']['idle_timeout']
                        );
                        db_update('wfpl_sessions', 'expires', $expires, 'where id=%i', $GLOBALS['wfpl_session']['id']);
+                       $GLOBALS['wfpl_session']['expires'] = $expires;
                }
        }
 }
@@ -148,23 +139,27 @@ function session_exists() {
                return false;
        }
 
-       $session_key = ereg_replace('[^a-zA-Z0-9]', '', $_COOKIE['session_key']);
+       $session_key = preg_replace('|[^a-z0-9]|i', '', $_COOKIE['session_key']);
 
        if(!strlen($session_key) == 16) {
                return false;
        }
 
-       session_purge_old();
        $row = db_get_assoc('wfpl_sessions', 'id,idle_timeout,expires,expires_max,value', 'where session_key=%"', $session_key);
        if($row === false) {
                return false;
        }
+       $now = time();
+       if ($now >= (int) $row['expires']) {
+               session_purge_old();
+               return false;
+       }
 
        $GLOBALS['wfpl_session']['exists'] = true;
        $GLOBALS['wfpl_session']['id'] = $row['id'];
-       $GLOBALS['wfpl_session']['idle_timeout'] = $row['idle_timeout'];
-       $GLOBALS['wfpl_session']['expires'] = $row['expires'];
-       $GLOBALS['wfpl_session']['expires_max'] = $row['expires_max'];
+       $GLOBALS['wfpl_session']['idle_timeout'] = (int) $row['idle_timeout'];
+       $GLOBALS['wfpl_session']['expires'] = (int) $row['expires'];
+       $GLOBALS['wfpl_session']['expires_max'] = (int) $row['expires_max'];
        $GLOBALS['wfpl_session']['key'] = $session_key;
 
        if (strlen($row['value']) && is_array($parsed = json_decode($row['value'], true))) {