3 # Copyright (C) 2006 Jason Woofenden
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 3 of the License, or
8 # (at your option) any later version.
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.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # The functions in this file assume that you have this database table:
20 # drop table if exists wfpl_sessions;
21 # create table wfpl_sessions (
22 # id int unique auto_increment,
23 # session_key varchar(16),
30 # You'll want to use these:
33 # session_new('timeout', 'max_len')
34 # session_set('key', 'value')
35 # session_sets(['key': 'value', 'key2': 'val2'])
37 # session_clear() # removes all set() values
38 # session_clear('key')
41 # All session data is cached in globals, so:
42 # 1. don't set large amonuts of data
43 # 2. session_get() is very fast (no db access)
46 # generate a new random 16-character string
47 function session_generate_key() {
48 $character_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
51 # PHP 4.2.0 and up seed the random number generator for you.
52 # Lets hope that it seeds with something harder to guess than the clock.
53 for($i = 0; $i < 16; ++$i) {
54 $id{$i} = $character_set{mt_rand(0, 61)};
60 # track this user with a session cookie (ie a cookie that goes away when the
61 # user closes the browser). The timestamp is how long to track the session in
62 # the database. Defaults to one day.
63 function session_new($idle_timeout = 86400, $max_timeout = 'same_as_idle') {
64 if ($max_timeout === 'same_as_idle') {
65 $max_timeout = $idle_timeout;
69 $session_key = session_generate_key();
73 'session_key' => $session_key,
74 'idle_timeout' => $idle_timeout,
75 'expires' => $now + $idle_timeout,
76 'expires_max' => $now + $max_timeout,
80 db_insert_assoc('wfpl_sessions', $row);
81 $session_id = db_auto_id();
82 $GLOBALS['wfpl_session'] = array(
85 'key' => $session_key,
86 'idle_timeout' => $row['idle_timeout'],
87 'expires' => $row['expires'],
88 'expires_max' => $row['expires_max'],
95 function session_set_cookie() {
96 if (session_exists()) {
97 if (!isset($GLOBALS['wfpl_session']['cookie_set'])) {
98 $GLOBALS['wfpl_session']['cookie_set'] = true;
99 header('Set-Cookie: session_key=' . $GLOBALS['wfpl_session']['key'] . '; Path=/');
104 # update the idle_timeout
105 function session_touch() {
106 if(!session_exists()) {
109 # is the session extendable?
110 if ($GLOBALS['wfpl_session']['expires'] < $GLOBALS['wfpl_session']['expires_max']) {
111 # would this extend the session by at least 10%?
113 $session_start = $GLOBALS['wfpl_session']['expires'] - $GLOBALS['wfpl_session']['idle_timeout'];
114 if ($now > $session_start + ceil(0.1 * $GLOBALS['wfpl_session']['idle_timeout'])) {
116 $GLOBALS['wfpl_session']['expires_max'],
117 $now + $GLOBALS['wfpl_session']['idle_timeout']
119 db_update('wfpl_sessions', 'expires', $expires, 'where id=%i', $GLOBALS['wfpl_session']['id']);
124 # delete the current session
125 function kill_session() {
126 if(!session_exists()) {
129 db_delete('wfpl_sessions', 'where id=%i', $GLOBALS['wfpl_session']['id']);
130 $GLOBALS['wfpl_session'] = array('exists' => false);
133 # delete expired sessions from database
134 function session_purge_old() {
135 db_delete('wfpl_sessions', 'where expires < %i', time());
138 # return true if a session exists
139 function session_exists() {
140 if (isset($GLOBALS['wfpl_session'])) {
141 return $GLOBALS['wfpl_session']['exists'];
144 $GLOBALS['wfpl_session'] = array('exists' => false);
146 if(!isset($_COOKIE['session_key'])) {
150 $session_key = ereg_replace('[^a-zA-Z0-9]', '', $_COOKIE['session_key']);
152 if(!strlen($session_key) == 16) {
157 $row = db_get_assoc('wfpl_sessions', 'id,idle_timeout,expires,expires_max,value', 'where session_key=%"', $session_key);
162 $GLOBALS['wfpl_session']['exists'] = true;
163 $GLOBALS['wfpl_session']['id'] = $row['id'];
164 $GLOBALS['wfpl_session']['idle_timeout'] = $row['idle_timeout'];
165 $GLOBALS['wfpl_session']['expires'] = $row['expires'];
166 $GLOBALS['wfpl_session']['expires_max'] = $row['expires_max'];
167 $GLOBALS['wfpl_session']['key'] = $session_key;
169 if ($row['value'] && is_array($parsed = json_decode($row['value'], true))) {
170 $GLOBALS['wfpl_session']['value'] = $parsed;
172 $GLOBALS['wfpl_session']['value'] = array();
175 # this session is not idle (extend if it's extendable)
182 # generate a random password using only letters and numbers that look
183 # particularly unique
184 function new_readable_password($length = 8) {
185 $character_set = "ABCDEFHJKLMNPQRTUWXY34789";
188 # PHP 4.2.0 and up seed the random number generator for you.
189 # Lets hope that it seeds with something harder to guess than the clock.
191 $code .= $character_set{mt_rand(0, 24)}; # inclusive
198 # return username if a session exists and is authenticated
199 function logged_in() {
200 if(!session_exists()) {
204 return session_get('auth_username');
209 function session_exists_and_authed() {
215 # return true if a session exists and is authenticated
216 function logged_in_as_admin() {
217 if(!session_exists()) {
221 if(session_get('auth_admin')) {
228 # find existing session, or make one (name "session_init" was taken)
229 function init_session() {
230 if(!session_exists()) {
235 # internal use only (write session cache to db)
236 function _sync_session() {
237 db_update('wfpl_sessions',
238 'value', json_encode($GLOBALS['wfpl_session']['value']),
239 'where id=%i', $GLOBALS['wfpl_session']['id']
243 # save data into the session
244 # $value can be anything json_encode()able
245 function session_set($name, $value) {
247 if (isset($GLOBALS['wfpl_session']['value'][$name])) {
248 if ($GLOBALS['wfpl_session']['value'][$name] === $value) {
252 $GLOBALS['wfpl_session']['value'][$name] = $value;
256 # save data into the session
257 # values can be anything json_encode()able
258 function session_sets($assoc) {
261 foreach ($assoc as $name => &$value) {
262 if (isset($GLOBALS['wfpl_session']['value'][$name])) {
263 if ($GLOBALS['wfpl_session']['value'][$name] === $value) {
267 $GLOBALS['wfpl_session']['value'][$name] = $value;
275 # remove variable from the session
276 # with no args: clear all
277 function session_clear($name = -1) {
278 if(!session_exists()) {
282 if (count($GLOBALS['wfpl_session']['value']) > 0) {
283 $GLOBALS['wfpl_session']['value'] = array();
286 } elseif (isset($GLOBALS['wfpl_session']['value'][$name])) {
287 unset($GLOBALS['wfpl_session']['value'][$name]);
292 # get a variable into the session
293 function session_get($name) {
294 if(!session_exists()) {
297 if (isset($GLOBALS['wfpl_session']['value'][$name])) {
298 return $GLOBALS['wfpl_session']['value'][$name];