Show class_session.php syntax highlighted
<?php
/**
2003 (c) Standard SESSION class written by Jason Morriss
This is copywritted software. You may not use this software w/o
written permission from Jason Morriss - stormtrooper@psychostats.com
This Session class is being used for PsychoStats v2.x with full
permission from Jason Morriss <stormtrooper@psychostats.com>. Use of
this class in any other programs or websites is forbidden, except with
written permission as noted above.
This software is provided as-in with NO WARRANTIES. If something breaks
for you due to this software Jason Morriss can not be held liable.
*/
// MYSQL session table for this session class is at the bottom of this file.
if (!defined('VALID_PAGE')) die(basename(__FILE__) . " 666 Error");
if (defined("CLASS_SESSION_PHP")) return 1;
define('CLASS_SESSION_PHP', 1);
class Session {
var $config = array();
var $_is_new = 0;
var $sesshandle = 0;
var $ended = 0;
var $sidmethod = 'get';
var $sessdata = array( // stores all the session data (stored in the database, not the cookie)
'session_id' => '', // always 32 characters long
'session_userid' => 0,
'session_start' => 0,
'session_last' => 0,
'session_ip' => 0,
'session_logged_in' => 0,
);
// session constructor. Sets defaults and will automatically start a new session or load an existing one
function session($_config=array()) {
$this->config = array(
'delaystart' => 0,
'cookielife' => 60 * 60, // 1 hour
'cookiedomain' => '',
'cookiepath' => '/',
'cookiename' => 'sess',
'cookiesecure' => 0,
'secretkey' => '', // mcrypt module must be installed if this is !empty
'login_callback_func' => '',
'dbuser' => '',
'dbpass' => '',
'dbhost' => 'localhost',
'dbname' => 'sessions',
'dbsessiontable' => 'sessions',
'dbusertable' => 'users',
'dbusersessionlast' => 'session_last', // table field name to update the user's last session request
'dbuserlastvisit' => 'lastvisit', // table field name to update the user's last (previous) visit
'dbuserid' => 'userid', // table field name for the user's "user id"
'dbhandle' => 0,
);
$this->config = array_merge($this->config, $_config);
$this->sesshandle = $this->config['dbhandle']; // if the user provided an active DB handle, use it
$this->_initkey();
if (!$this->config['delaystart']) $this->start(); // start session if its not 'delayed'
}
// returns the name of the SID cookie
function sidname($suffix='_id') {
return $this->config['cookiename'] . $suffix;
}
// generates a new random SID. If you provide the $random string it will be used to help generate the md5 hash.
function generate_sid($random="") {
return md5(time() . mt_rand() . $random);
}
// delete expired sessions
function garbage_collect() {
$now = time();
$cmd = "DELETE FROM {$this->config['dbsessiontable']} WHERE ($now - session_last > {$this->config['cookielife']})";
$res = @mysql_query($cmd, $this->sesshandle);
}
// returns the current session SID from a COOKIE or GET data. Returns FALSE if there is none
function _find_user_sid() {
$this->garbage_collect();
$name = $this->sidname();
$sid = FALSE;
if ($_COOKIE[$name] != '') {
$this->sidmethod = 'cookie';
$sid = $_COOKIE[$name];
} elseif ($_GET[$name] != '') {
$this->sidmethod = 'get';
$sid = $_GET[$name];
$_COOKIE[$name] = $sid;
# } elseif ($_POST[$name]) {
# $this->sidmethod = 'get'; // we don't distinguish between get/post
# $sid = $_POST[$name];
# $_COOKIE[$name] = $sid;
}
if ($sid != FALSE and get_magic_quotes_gpc()) stripslashes($sid);
return $sid;
}
function is_new() {
return $this->_is_new;
}
function is_sid($sid) {
return ereg('^[a-f0-9]{32}$', strtolower($sid));
}
// sets a cookie for the user based on the cookie settings we have. $suffix is the trailing part of the SID name.
// '_id' or '_login'
function sendcookie($data, $time=0, $suffix='_id') {
// print "SENDCOOKIE: '$suffix': $data<br>";
return setcookie($this->sidname($suffix), $data, $time, $this->config['cookiepath'], $this->config['cookiedomain'], $this->config['cookiesecure']);
}
// short-cut method for deleting a users cookie.
function delcookie($suffix='_id') {
// print "DELCOOKIE: '$suffix' (the next sendcookie line will be the deletion)<br>";
return ($_COOKIE[ $this->sidname($suffix)]) ? $this->sendcookie("", time()-100000, $suffix) : 0;
}
function _read_session($sid) {
$res = @mysql_query("SELECT * FROM " . $this->config['dbsessiontable'] . " WHERE session_id='" . addslashes($sid) . "'", $this->sesshandle);
if (!$res) die("Fatal Session Error: " . __LINE__ . ": " . mysql_error());
$this->sessdata = @mysql_num_rows($res) > 0 ? @mysql_fetch_assoc($res) : $this->_init_new_session();
// print "READ SESSION ... <br>";
// print_r($this->sessdata); print "<bR>";
}
function _save_session() {
if ($this->ended) return 1; // do not save anything if the session was end()'ed
$res = @mysql_query("SELECT session_id FROM `" . $this->config['dbsessiontable'] . "` WHERE session_id='" . addslashes($this->sessdata['session_id']) . "'");
list($exists) = @mysql_fetch_array($res);
if (!$res) die("Fatal Session Error: " . __LINE__ . ": " . mysql_error());
$prefix = ($exists) ? "UPDATE" : "INSERT INTO";
$cmd = "$prefix `" . $this->config['dbsessiontable'] . "` SET ";
foreach ($this->sessdata as $k => $v) $cmd .= "$k='$v', ";
$cmd = substr($cmd, 0, -2); // strip off trailing ', '
if ($exists) $cmd .= " WHERE session_id='" . addslashes($this->sessdata['session_id']) . "'";
// print "SAVE SESSION: $cmd<br>";
$res = @mysql_query($cmd, $this->sesshandle);
if (!$res) die("Fatal Session Error: " . __LINE__ . ": " . mysql_error());
}
function _delete_session($sid) {
$res = @mysql_query("DELETE FROM `" . $this->config['dbsessiontable'] . "` WHERE session_id='" . addslashes($sid) . "'");
}
function _init_new_session() {
// print "INIT SESSION ... <br>";
$this->_is_new = 1;
$this->sid = $this->generate_sid();
$this->sessdata = array(
'session_id' => $this->sid,
'session_userid' => 0,
'session_start' => time(),
'session_last' => time(),
'session_ip' => sprintf("%u", ip2long($GLOBALS['REMOTE_ADDR'])),
'session_logged_in' => 0,
);
// print_r($this->sessdata); print "<bR>";
}
// private method to get or set the users current SID cookie
function _session_start() {
$sid = $this->_find_user_sid();
if (!$sid or !$this->is_sid($sid)) {
// print "NEW SESSION STARTING ... <BR>";
$this->_init_new_session();
$this->_save_session(); // always SAVE when we create a new session
$this->sendcookie($this->sid); // cookie will expire at the end of the browser session
} else {
// print "PREVIOUS SESSION STARTING ... <BR>";
$this->_read_session($sid);
$this->sid = $this->sessdata['session_id'];
if ($this->_expired()) {
$this->_delete_session($this->sid); // deletes old session from database
$this->_init_new_session(); // generate a new dataset
$this->_save_session();
$this->delcookie(); // delete old sess_id cookie (since we're only using PHP4 its ok to delete first, before sending another cookie below)
$this->sendcookie($this->sid); // send a new cookie
}
}
}
// starts the session (no need to call this unless delaystart is true) ----------------------------
function start() {
$this->ended = 0;
$this->_session_start();
$now = time();
$this->sessdata['session_last'] = $now;
// If the user is NOT logged in and there is a 'login' cookie set, try to verify and log the user in automatically
if ($this->onlinestatus()==0 and !empty($_COOKIE[ $this->config['cookiename'] . '_login' ])) {
$enc = $_COOKIE[ $this->config['cookiename'] . '_login' ];
if (get_magic_quotes_gpc()) $enc = stripslashes($enc);
$data = unserialize(base64_decode($this->decrypt($enc))); // should be an array with a username and password
if (is_array($data) and $data['username'] and $data['password']) {
$login_callback = $this->config['login_callback_func'];
$userid = (function_exists($login_callback)) ? $login_callback($data['username'], $data['password']) : 0;
if ($userid) {
$this->onlinestatus(1, $userid); // user is now magically online!
} else {
$this->delcookie('_login'); // login cookie was invalid, so delete it
}
} else {
$this->delcookie('_login'); // login cookie was invalid, so delete it
}
}
// Update the users LAST event timestamp (in the users database, not the session database).
// When the cookie expires this will remain in the user data to keep track of the last time the user did anything on the site.
// Used for keeping track of NEW messages, etc.
// This must be done AFTER the autlogin block above! otherwise users that are auto logged in will never have the correct
// 'last visit' timestamp.
if (!empty($this->config['dbusertable'])) {
if ($this->sessdata['session_userid'] > 0 and $this->sessdata['session_logged_in']) {
$cmd = sprintf("UPDATE %s SET `%s`=$now WHERE `%s`='%s'",
$this->config['dbusertable'],
$this->config['dbusersessionlast'],
$this->config['dbuserid'],
$this->sessdata['session_userid']
);
// print "UPDATE USER: $cmd<br>";
$res = @mysql_query($cmd, $this->sesshandle);
}
}
} // end function start()
// Saves the autologin cookie to the users browser so the next time they view the page they will be logged on automatically
function saveAutoLogin($username, $password) {
$ary = array('username' => $username, 'password' => $password);
$data = $this->encrypt( base64_encode(serialize($ary)) );
return $this->sendcookie($data, time()+60*60*24*30, '_login'); // autologin cookie is saved for 30 days
}
function removeAutoLogin() {
$this->delcookie('_login');
return 1;
}
function _initkey() {
if (!$this->config['secretkey']) return 0;
$this->td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, ''); // Open the cipher
$this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), MCRYPT_DEV_RANDOM); // Create the IV and determine the keysize length
$this->ks = mcrypt_enc_get_key_size($this->td);
$this->key = substr(md5($this->config['secretkey']), 0, $this->ks); // Create key
mcrypt_generic_init($this->td, $this->key, $this->iv); // Intialize encryption
return 1;
}
function encrypt($str) {
if (!$this->config['secretkey']) return $str;
$encrypted = mcrypt_generic($this->td, $str); // Encrypt data
return $encrypted;
}
function decrypt($str) {
if (!$this->config['secretkey']) return $str;
$decrypted = trim(mdecrypt_generic($this->td, $str));
return $decrypted;
}
// sets or gets the current online status for the session. If the online status is changed, the previous value is returned.
function onlinestatus($online=-1, $userid=0) {
$status = $this->sessdata['session_logged_in']; // get original status by default
if ($online >= 1) { // LOGIN THE USER
$this->sessdata['session_logged_in'] = 1;
$this->sessdata['session_userid'] = $userid;
$this->_save_session();
$res = @mysql_query(sprintf("SELECT %s FROM %s WHERE %s='$userid' LIMIT 1",
$this->config['dbusersessionlast'],
$this->config['dbusertable'],
$this->config['dbuserid']
));
list($last) = ($res) ? mysql_fetch_array($res) : time();
$res = @mysql_query(sprintf("UPDATE %s SET `%s`=$last WHERE `%s`='%s'", // update the USER table
$this->config['dbusertable'],
$this->config['dbuserlastvisit'],
$this->config['dbuserid'],
addslashes($this->sessdata['session_userid'])
));
} elseif ($online == 0) {
$this->sessdata['session_logged_in'] = 0;
$this->sessdata['session_userid'] = 0;
$this->_save_session();
$this->removeAutoLogin();
}
return $status;
}
// returns the total seconds 'online' for the session ------------------------------------------------------------
function secondsonline() {
$diff = $this->sessdata['session_last'] - $this->sessdata['session_start'];
return ($diff > 0) ? $diff : 0;
}
// returns the total number of active sessions -------------------------------------------------------------------
// 5 minutes is generally a reasonable amount of time to wait before a session is 'inactive'
// if $wantarray is true, a 2 element array is is returned with the total 'members' and 'guests' online, respectively
function totalonline($timeframe=300, $wantarray=0) { // 300 seconds = 5 minutes
$memebers = 0;
$guests = 0;
$now = time();
$res = @mysql_query(sprintf("SELECT count(DISTINCT session_userid) FROM %s WHERE session_userid != 0 AND session_last + $timeframe > $now", $this->config['dbsessiontable']));
list($members) = @mysql_fetch_array($res);
$res = @mysql_query(sprintf("SELECT count(*) FROM %s WHERE session_userid=0 AND session_last + $timeframe > $now", $this->config['dbsessiontable']));
list($guests) = @mysql_fetch_array($res);
if ($wantarray) {
return array( $members > 0 ? $members : 0, $guests > 0 ? $guests : 0);
} else {
$total = $members + $guests;
return ($total > 0) ? $total : 1;
}
}
// End/remove the session (including the user's SID cookie)
function end() {
$this->delcookie('_id');
$this->delcookie('_login');
$this->_delete_session($this->sid);
$this->sid = '';
$this->sessdata = array();
$this->_init_new_session(); // generate a new dataset, but it's not saved yet ...
$this->ended = 1;
}
// closes the session. There's no need to call this unless you want to make sure the session is updated before
// redirecting to another page.
function close() {
$this->_save_session();
}
// internal function, returns true if the session has expired
function _expired() {
return (time() - $this->sessdata['session_last'] > $this->config['cookielife']);
}
} // end of session class
/**
CREATE TABLE `pstats_sessions` (
`session_id` char(32) NOT NULL default '',
`session_userid` int(10) unsigned NOT NULL default '0',
`session_start` int(10) unsigned NOT NULL default '0',
`session_last` int(10) unsigned NOT NULL default '0',
`session_ip` int(10) unsigned NOT NULL default '0',
`session_logged_in` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`session_id`),
KEY `session_userid` (`session_userid`)
) TYPE=MyISAM COMMENT='User sessions';
**/
?>
See more files for this project here