<?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:
return $id;
}
-# track this user with a session cookie (ie a cookie that goes away when the
-# user closes the browser). The timestamp is how long to track the session in
-# the database. Defaults to one day.
-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();
'session_key' => $session_key,
'idle_timeout' => $idle_timeout,
'expires' => $now + $idle_timeout,
- 'expires_max' => $now + $max_timeout,
- 'value' => '{}'
+ 'expires_max' => $now + $max_length,
+ 'value' => ''
);
db_insert_assoc('wfpl_sessions', $row);
'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();
}
}
-# update the idle_timeout
+# this is a helper function. See session_new()
function session_touch() {
if(!session_exists()) {
return;
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;
}
}
}
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 ($row['value'] && is_array($parsed = json_decode($row['value'], true))) {
+ if (strlen($row['value']) && is_array($parsed = json_decode($row['value'], true))) {
$GLOBALS['wfpl_session']['value'] = $parsed;
} else {
$GLOBALS['wfpl_session']['value'] = array();
}
- # this session is not idle (extend if it's extendable)
+ # mark session as not idle
session_touch();
return true;
# internal use only (write session cache to db)
function _sync_session() {
- db_update('wfpl_sessions',
- 'value', json_encode($GLOBALS['wfpl_session']['value']),
- 'where id=%i', $GLOBALS['wfpl_session']['id']
- );
+ if (count($GLOBALS['wfpl_session']['value']) > 0) {
+ $value = json_encode($GLOBALS['wfpl_session']['value']);
+ } else {
+ $value = '';
+ }
+ db_update('wfpl_sessions', 'value', $value, 'where id=%i', $GLOBALS['wfpl_session']['id']);
}
# save data into the session