There needs to be some way of clearing old session and variable data
from the database beyond the methods in the constructor (which only
clean the old data for the session stored in the cookie). It looks
like deleting the cookie from the browser cache would leave these
records orphaned indefinitely without some method of clearing them
each time the class is called. I've added the appropriate "else"
branch to the if(isset($_COOKIE["PHPSESSID"])) logic statement.
Code:
public function __construct()
{
# Connect to database
parent::__construct();
# Set up the handler
session_set_save_handler(
array(&$this, '_session_open_method'),
array(&$this, '_session_close_method'),
array(&$this, '_session_read_method'),
array(&$this, '_session_write_method'),
array(&$this, '_session_destroy_method'),
array(&$this, '_session_gc_method')
);
# Check the cookie passed - if one is - if it looks wrong we'll scrub it right away
$strUserAgent = $_SERVER["HTTP_USER_AGENT"];
$strUserIP = $_SERVER["REMOTE_ADDR"];
if (isset($_COOKIE["PHPSESSID"]))
{
# Security and age check
$this->php_session_id = $_COOKIE["PHPSESSID"];
$sql = "SELECT id FROM user_session WHERE ascii_session_id = '" . $this->php_session_id . "' AND DATE_SUB(NOW(), INTERVAL " . $this->session_lifespan . " SECOND) < created AND user_agent = '" . $strUserAgent . "' AND user_ip = '" . $strUserIP . "' AND DATE_SUB(now(), INTERVAL " . $this->session_timeout . " SECOND) <= last_impression OR last_impression IS NULL";
$rows = 0;
if($stmt = $this->fconn->prepare($sql))
{
$stmt->execute();
$stmt->bind_result($id);
while($stmt->fetch())
{
$this->native_session_id = $id;
$rows++;
}
$stmt->free_result();
$stmt->close();
}
if($rows == 0)
{
# Set failed flag
$failed = 1;
# Delete from database - we do garbage cleanup at the same time
$sql = "DELETE FROM user_session WHERE (ascii_session_id = '" . $this->php_session_id . "') OR DATE_SUB(now(), INTERVAL " . $this->session_lifespan . " SECOND) > created";
if($stmt_user = $this->fconn->prepare($sql))
{
$stmt_user->execute();
$stmt_user->close();
}
# Clean up stray session variables
$sql = "DELETE FROM session_variable WHERE session_id NOT IN (SELECT id FROM user_session)";
if($stmt_vars = $this->fconn->prepare($sql))
{
$stmt_vars->execute();
$stmt_vars->close();
}
# Get rid of this one... this will force PHP to give us another
unset($_COOKIE["PHPSESSID"]);
}
}
else
{
# Delete from database - we do garbage cleanup at the same time
$sql = "DELETE FROM user_session WHERE DATE_SUB(now(), INTERVAL " . $this->session_lifespan . " SECOND) > created";
if($stmt_user = $this->fconn->prepare($sql))
{
$stmt_user->execute();
$stmt_user->close();
}
# Clean up stray session variables
$sql = "DELETE FROM session_variable WHERE session_id NOT IN (SELECT id FROM user_session)";
if($stmt_vars = $this->fconn->prepare($sql))
{
$stmt_vars->execute();
$stmt_vars->close();
}
}
# Set the life time for the cookie
session_set_cookie_params($this->session_lifespan);
# Call the session_start method to get things started
session_start();
session_cache_limiter("no-cache, must-revalidate");
}
Carl Olsen
www.carl-olsen.com