From: Jason Gerfen on
I have used session classes before and am at a loss as to why I cannot
for the life of me get this to work... Any help is appreciated.

I might just be confused with the database connection handles in order
to pull and store session information as there was some information
posted on php.net referencing some changes between php4 and php5 in
regards to passing a database connection handle to a custom session
handler class. However as you can see from the class here it initializes
a database connection handle for each function call to *hopefully
eliminate this problem.

I do appreciate help on this. Thanks.

First the db sessions table:
CREATE TABLE IF NOT EXISTS `admin_sessions` (
`session_id` varchar(32) NOT NULL default '',
`http_user_agent` varchar(32) NOT NULL default '',
`session_data` blob NOT NULL,
`session_expire` int(11) NOT NULL default '0',
PRIMARY KEY (`session_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Pretty simple right? Now here is my dbSessions class (complete with
debugging statements:
class dbSession
{
private $data;
private $max_time;
private $dbconn;

public function __construct( $max_time )
{

//@register_shutdown_function( 'session_write_close' );

if( !empty( $max_time ) ) {
@ini_set( 'session.gc_maxlifetime', $max_time );
} else {
@ini_set( 'session.gc_maxlifetime', 3600 );
}

session_set_save_handler(
array( &$this, 'open' ),
array( &$this, 'close' ),
array( &$this, 'read' ),
array( &$this, 'write' ),
array( &$this, 'destroy' ),
array( &$this, 'gc' )
);

//@ini_set('session.gc_probability', 50);
//@ini_set('session.save_handler', 'user');
@register_shutdown_function( 'session_write_close' );
@session_start();
}

public function register( $name, $data )
{
return $_SESSION[$name] = $data;
}

public function open( $path, $name )
{ echo "OPEN CALLED<BR>";
global $defined;
global $handles;

if( ( $this->dbconn = $handles['db']->dbConnect( $defined['dbhost'],
$defined['username'], $defined['password'], $defined['dbname'] ) ) !==
-1 ) {
return true;//$this->dbconn;
} else {
return false;
}
}

public function close()
{ echo "CLOSE CALLED<BR>";
global $defined;
global $handles;

// clean up data
$handles['misc']->CleanUpVars( $_SESSION, NULL );

// Perform analyze, repair and optimize on used tables
$handles['db']->dbFixTable( "admin_sessions", $this->dbconn );

// Free db handle and close connection(s)
$handles['db']->dbFreeData( $this->dbconn );
$handles['db']->dbCloseConn( $this->dbconn );

return true;
}

public function read( $id )
{ echo "READ CALLED<BR>"; echo "<pre>"; var_dump( print_r(
func_get_args() ) ); echo "</pre>";
global $handles;
global $defined;

$this->dbconn = $handles['db']->dbConnect( $defined['dbhost'],
$defined['username'], $defined['password'], $defined['dbname'] );

$query = "SELECT `session_data` FROM `admin_sessions` WHERE
`session_id` = \"" . $id . "\" AND `http_user_agent` = \"" . md5(
$_SERVER["HTTP_USER_AGENT"] ) . "\" LIMIT 1";
$result = $handles['db']->dbQuery( $handles['val']->ValidateSQL(
$query, $this->dbconn ), $this->dbconn );

echo "RAN: " . $query . " => " . $handles['db']->dbNumRowsAffected(
$this->dbconn ) . "<br>";

if( ( is_resource( $result ) ) && ( $handles['db']->dbNumRowsAffected(
$this->dbconn ) > 0 ) ) {
$fields = $handles['db']->dbArrayResultsAssoc( $result );
echo "FOUND EXISTING SESSION DATA: " . print_r(
$fields['session_data'] ) . "<br>";
return stripslashes( $fields['session_data'] );
}
echo "NOTHING FOUND FOR: " . $id . "<br>";
return "";
}

public function write( $id, $data )
{ echo "WRITE CALLED<BR>"; echo "<pre>"; var_dump( print_r(
func_get_args() ) ); echo "</pre>";
global $handles;
global $defined;

$this->dbconn = $handles['db']->dbConnect( $defined['dbhost'],
$defined['username'], $defined['password'], $defined['dbname'] );

$query = "SELECT `session_data` FROM `admin_sessions` WHERE
`session_id` = \"" . $id . "\" AND `http_user_agent` = \"" . md5(
$_SERVER["HTTP_USER_AGENT"] ) . "\" LIMIT 1";
$result = $handles['db']->dbQuery( $handles['val']->ValidateSQL(
$query, $this->dbconn ), $this->dbconn );
//$data = $handles['db']->dbArrayResultsAssoc( $result );
//echo "<pre>"; print_r( $data ); echo "</pre>";
if( ( is_resource( $result ) ) && ( $handles['db']->dbNumRowsAffected(
$result ) > 0 ) ) {
$query = "UPDATE `admin_sessions` SET `session_data` = \"" .
mysql_real_escape_string( $data ) . "\", `session_expire` = \"" . time()
.. "\" WHERE `session_id` = \"" . $id . "\" LIMIT 1";
} else {
$query = "INSERT INTO `admin_sessions` ( `session_id`,
`http_user_agent`, `session_data`, `session_expire` ) VALUES ( \"" . $id
.. "\", \"" . md5( $_SERVER["HTTP_USER_AGENT"] ) . "\", \"" .
mysql_real_escape_string( $data ) . "\", \"" . time() . "\" ) ON
DUPLICATE KEY UPDATE `session_data` = \"" . mysql_real_escape_string(
$data ) . "\", `session_expire` = \"" . time() . "\"";
}

$result = $handles['db']->dbQuery( $handles['val']->ValidateSQL(
$query, $this->dbconn ), $this->dbconn );

echo "RAN: " . $query . " => " . $handles['db']->dbQuery(
$handles['val']->ValidateSQL( $query, $this->dbconn ), $this->dbconn ) .
"<br>";

if( ( is_resource( $result ) ) && ( $handles['db']->dbNumRowsAffected(
$this->dbconn ) > 0 ) ) {
$fields = $handles['db']->dbArrayResultsAssoc( $result );
return stripslashes( $fields["session_data"] );
}
return "";
}

public function destroy( $id )
{ echo "DESTROY CALLED<BR>";
global $handles;
global $defined;

$this->dbconn = $handles['db']->dbConnect( $defined['dbhost'],
$defined['username'], $defined['password'], $defined['dbname'] );

$query = "DELETE FROM `admin_sessions` WHERE `session_id` = \"" . $id
.. "\" LIMIT 1";
$result = $handles['db']->dbQuery($handles['val']->ValidateSQL($query,
$this->dbconn), $this->dbconn);

if( ( is_resource( $result ) ) && ( $handles['db']->dbNumRowsAffected(
$this->dbconn ) !== -1 ) ) {
return true;
}
return false;
}

public function gc( $max_time )
{ echo "GC CALLED<BR>";
global $handles;

$this->dbconn = $handles['db']->dbConnect( $defined['dbhost'],
$defined['username'], $defined['password'], $defined['dbname'] );

$query = "DELETE FROM `admin_sessions` WHERE `session_expire` < \"" .
time() - $this->max_time . "\"";
$result = $handles['db']->dbQuery($handles['val']->ValidateSQL($query,
$this->dbconn), $this->dbconn);

if( ( is_resource( $result ) ) && ( $handles['db']->dbNumRowsAffected(
$this->dbconn ) !== -1 ) ) {
return true;
}
return false;
}
}

And of course the usage:
require 'class.dbsessions.php';
if( empty( $_SESSION['token'] ) ) {
$handles['session'] = new dbSession( $defined['timeout'] );
}

Then once the user has passed a valid authentication mechanism the users
session token is set with:
$handles['session']->register( 'token', $token );


--
Jason Gerfen
Systems Administration/Web application development
jason.gerfen(a)scl.utah.edu

Marriott Library
Lab Systems PC
295 South 1500 East
Salt Lake City, Utah 84112-0806
Ext 5-9810