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 # start a new session.
61 # by default it'll expire in 24 hours regardless of activity.
62 # pass both args for a session that lasts longer if active.
63 # sessions are tracked with a "session cookie" (dies on browser close)
64 function session_new($idle_timeout = 86400, $max_timeout = 'same_as_idle') {
65 if ($max_timeout === 'same_as_idle') {
66 $max_timeout = $idle_timeout;
70 $session_key = session_generate_key();
74 'session_key' => $session_key,
75 'idle_timeout' => $idle_timeout,
76 'expires' => $now + $idle_timeout,
77 'expires_max' => $now + $max_timeout,
81 db_insert_assoc('wfpl_sessions', $row);
82 $session_id = db_auto_id();
83 $GLOBALS['wfpl_session'] = array(
86 'key' => $session_key,
87 'idle_timeout' => $row['idle_timeout'],
88 'expires' => $row['expires'],
89 'expires_max' => $row['expires_max'],
96 function session_set_cookie() {
97 if (session_exists()) {
98 if (!isset($GLOBALS['wfpl_session']['cookie_set'])) {
99 $GLOBALS['wfpl_session']['cookie_set'] = true;
100 header('Set-Cookie: session_key=' . $GLOBALS['wfpl_session']['key'] . '; Path=/');
105 # this is a helper function. See session_new()
106 function session_touch() {
107 if(!session_exists()) {
110 # is the session extendable?
111 if ($GLOBALS['wfpl_session']['expires'] < $GLOBALS['wfpl_session']['expires_max']) {
112 # would this extend the session by at least 10%?
114 $session_start = $GLOBALS['wfpl_session']['expires'] - $GLOBALS['wfpl_session']['idle_timeout'];
115 if ($now > $session_start + ceil(0.1 * $GLOBALS['wfpl_session']['idle_timeout'])) {
117 $GLOBALS['wfpl_session']['expires_max'],
118 $now + $GLOBALS['wfpl_session']['idle_timeout']
120 db_update('wfpl_sessions', 'expires', $expires, 'where id=%i', $GLOBALS['wfpl_session']['id']);
125 # delete the current session
126 function kill_session() {
127 if(!session_exists()) {
130 db_delete('wfpl_sessions', 'where id=%i', $GLOBALS['wfpl_session']['id']);
131 $GLOBALS['wfpl_session'] = array('exists' => false);
134 # delete expired sessions from database
135 function session_purge_old() {
136 db_delete('wfpl_sessions', 'where expires < %i', time());
139 # return true if a session exists
140 function session_exists() {
141 if (isset($GLOBALS['wfpl_session'])) {
142 return $GLOBALS['wfpl_session']['exists'];
145 $GLOBALS['wfpl_session'] = array('exists' => false);
147 if(!isset($_COOKIE['session_key'])) {
151 $session_key = ereg_replace('[^a-zA-Z0-9]', '', $_COOKIE['session_key']);
153 if(!strlen($session_key) == 16) {
158 $row = db_get_assoc('wfpl_sessions', 'id,idle_timeout,expires,expires_max,value', 'where session_key=%"', $session_key);
163 $GLOBALS['wfpl_session']['exists'] = true;
164 $GLOBALS['wfpl_session']['id'] = $row['id'];
165 $GLOBALS['wfpl_session']['idle_timeout'] = $row['idle_timeout'];
166 $GLOBALS['wfpl_session']['expires'] = $row['expires'];
167 $GLOBALS['wfpl_session']['expires_max'] = $row['expires_max'];
168 $GLOBALS['wfpl_session']['key'] = $session_key;
170 if (strlen($row['value']) && is_array($parsed = json_decode($row['value'], true))) {
171 $GLOBALS['wfpl_session']['value'] = $parsed;
173 $GLOBALS['wfpl_session']['value'] = array();
176 # mark session as not idle
183 # generate a random password using only letters and numbers that look
184 # particularly unique
185 function new_readable_password($length = 8) {
186 $character_set = "ABCDEFHJKLMNPQRTUWXY34789";
189 # PHP 4.2.0 and up seed the random number generator for you.
190 # Lets hope that it seeds with something harder to guess than the clock.
192 $code .= $character_set{mt_rand(0, 24)}; # inclusive
199 # return username if a session exists and is authenticated
200 function logged_in() {
201 if(!session_exists()) {
205 return session_get('auth_username');
210 function session_exists_and_authed() {
216 # return true if a session exists and is authenticated
217 function logged_in_as_admin() {
218 if(!session_exists()) {
222 if(session_get('auth_admin')) {
229 # find existing session, or make one (name "session_init" was taken)
230 function init_session() {
231 if(!session_exists()) {
236 # internal use only (write session cache to db)
237 function _sync_session() {
238 if (count($GLOBALS['wfpl_session']['value']) > 0) {
239 $value = json_encode($GLOBALS['wfpl_session']['value']);
243 db_update('wfpl_sessions', 'value', $value, 'where id=%i', $GLOBALS['wfpl_session']['id']);
246 # save data into the session
247 # $value can be anything json_encode()able
248 function session_set($name, $value) {
250 if (isset($GLOBALS['wfpl_session']['value'][$name])) {
251 if ($GLOBALS['wfpl_session']['value'][$name] === $value) {
255 $GLOBALS['wfpl_session']['value'][$name] = $value;
259 # save data into the session
260 # values can be anything json_encode()able
261 function session_sets($assoc) {
264 foreach ($assoc as $name => &$value) {
265 if (isset($GLOBALS['wfpl_session']['value'][$name])) {
266 if ($GLOBALS['wfpl_session']['value'][$name] === $value) {
270 $GLOBALS['wfpl_session']['value'][$name] = $value;
278 # remove variable from the session
279 # with no args: clear all
280 function session_clear($name = -1) {
281 if(!session_exists()) {
285 if (count($GLOBALS['wfpl_session']['value']) > 0) {
286 $GLOBALS['wfpl_session']['value'] = array();
289 } elseif (isset($GLOBALS['wfpl_session']['value'][$name])) {
290 unset($GLOBALS['wfpl_session']['value'][$name]);
295 # get a variable into the session
296 function session_get($name) {
297 if(!session_exists()) {
300 if (isset($GLOBALS['wfpl_session']['value'][$name])) {
301 return $GLOBALS['wfpl_session']['value'][$name];