Created
April 14, 2011 20:35
-
-
Save gadhra/920462 to your computer and use it in GitHub Desktop.
A PHP5 Session handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/*** | |
* @note session handler::PHP5::session-class-php | |
* @author Stefan Antonowicz | |
* @link http://us2.php.net/manual/en/function.session-set-save-handler.php | |
* | |
* Database session handler | |
* | |
* This class overwrites the default session save functions for PHP, so we | |
* can write to the database rather than the filesystem | |
* | |
* | |
* | |
* This dbSession handler writes to a mysql table: | |
* CREATE TABLE `sessions` ( | |
* `sessionID` varchar(32) NOT NULL, | |
* `session_data` longtext, | |
* `session_time` int(11) NOT NULL DEFAULT '0', | |
* `session_ip` varchar(32) DEFAULT NULL, | |
* `session_status` enum('active','passive') DEFAULT NULL, | |
* PRIMARY KEY (`sessionID`) | |
*) ENGINE=InnoDB DEFAULT CHARSET=latin1; | |
* | |
* This file should also include the MySQL class, either through | |
* autoloader or directly in controller | |
*/ | |
class dbSession { | |
/** | |
* @access private | |
* @var int | |
* | |
* Base lifetime of session | |
*/ | |
private static $lifetime = 0; | |
/** | |
* @access private | |
* @var string | |
* | |
* User defined Data Source Name (DSN) for mysql connection. | |
*/ | |
private static $dsn = 'mysql://<username>:<password>@<host>/<dbname>'; | |
/** | |
* @access private | |
* @var string | |
* | |
* User defined domain for any cookies to be set. Set to .foo.com to | |
* allow cookies to be used across multiple servers and/or multiple | |
* subdomains | |
*/ | |
private static $cookie_domain = ''; | |
/** | |
* Constructor | |
* | |
* The constructor uses the session_set_save_handler to overload the user-level session storage functions in PHP | |
* Additionally, it calls session_start() after the session has been registered. | |
* All session_start( ) callouts sitewide MUST be in | |
* the form of "new dbSession()" and NOT just "session_start()" | |
* | |
* @access public | |
*/ | |
public function __construct( ) { | |
if( dbSession::$lifetime ) { | |
$this->lifetime = dbSession::$lifetime; | |
} else { | |
$this->lifetime = ini_get( 'session.gc_maxlifetime' ); | |
} | |
session_set_save_handler( | |
array( &$this, 'open' ), | |
array( &$this, 'close' ), | |
array( &$this, 'read' ), | |
array( &$this, 'write' ), | |
array( &$this, 'destroy' ), | |
array( &$this, 'gc' ) | |
); | |
register_shutdown_function( 'session_write_close' ); | |
$this->my = new MySQL( dbSession::$dsn ); | |
session_start( ); | |
} | |
/** | |
* open | |
* | |
* As of PHP 5.0.5 the write and close handlers are called after object destruction and | |
* therefore cannot use objects or throw exceptions. Not useful for current implementation | |
* | |
* @access public | |
* @return bool Always returns true (See Notes) | |
*/ | |
public function open( $path, $name ) { | |
return( TRUE ); | |
} | |
/** | |
* close | |
* | |
* As of PHP 5.0.5 the write and close handlers are called after object destruction and | |
* therefore cannot use objects or throw exceptions. Not useful for current implementation | |
* | |
* @access public | |
* @return bool Always returns true (See Notes) | |
*/ | |
public function close( ) { | |
return( TRUE ); | |
} | |
/** | |
* read | |
* | |
* @access public | |
* @return array unserialized $_SESSION array stored in database | |
* | |
*/ | |
public function read( $sid ) { | |
$this->my->sql = "SELECT session_data FROM sessions WHERE sessionID = '$sid' AND session_time > " . time(); | |
$this->my->query( ); | |
$fields = mysql_fetch_assoc( $this->my->result ); | |
return( $fields['session_data'] ); | |
} | |
/** | |
* write | |
* | |
* Stores unserialied array from $_SESSION as serialized string in database. Serialization takes | |
* place automagically by PHP session handlers. Additionally, creates new record if no record | |
* currently exists | |
* | |
* @access public | |
* @param $sid the php_session_id | |
* @param $data the data to store | |
*/ | |
public function write( $sid, $data ) { | |
/** | |
* quick clean of ip so no one can poison the db via GLOBAL overload | |
*/ | |
preg_match( '/[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}/', $_SERVER['REMOTE_ADDR'], $match ); | |
$ip = sizeof( $match ) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0'; | |
$expiry = time( ) + $this->lifetime; | |
$data = mysql_real_escape_string( $data ); | |
$sql = "INSERT INTO sessions (sessionID, session_data, session_time, session_ip) | |
VALUES ('$sid', '$data', $expiry, '$ip') | |
ON DUPLICATE KEY UPDATE session_data='$data', session_time = '$expiry'"; | |
$this->my->query( $sql );; | |
} | |
/** | |
* destroy | |
* | |
* Deletes session from database. For now, also kills $_COOKIE containing session_name | |
* | |
* @access public | |
*/ | |
public function destroy( $sid ) { | |
$sql = "DELETE FROM sessions WHERE sessionID = '$sid'"; | |
$this->my->query( $sql ); | |
if( isset( $_COOKIE[session_name()] ) ) { | |
setcookie( session_name( ), '', time()-42000, '/' ); | |
} | |
} | |
/** | |
* gc | |
* | |
* Perform garbage collection, dependent on lifetime, gc_probability, | |
* and gc_divisor established in php.ini | |
* | |
* @access public | |
* @return int | |
*/ | |
public function gc( ) { | |
$time = time( ) - $this->lifetime; | |
$sql = "DELETE FROM sessions WHERE session_time < $time"; | |
$res = $this->my->query( $sql ); | |
return; | |
} | |
/** | |
* saveMessage | |
* | |
* Saves a message as an array - useful for passing messages | |
* from one page to the other | |
* | |
* @access public | |
* @param $msg array of messages | |
*/ | |
public static function saveMessage( $msg ) { | |
if(! session_id( ) ) { | |
return( FALSE ); | |
} | |
$_SESSION['message'] = $msg; | |
} | |
/** | |
* getMessageFromSession | |
* | |
* returns an array of messages set by saveMessage, and unsets | |
* the variable | |
* | |
* @access public | |
* @see saveMessage | |
*/ | |
public static function getMessageFromSession( ) { | |
if(! session_id( ) ) { | |
return( FALSE ); | |
} | |
if(! $_SESSION['message'] ) { | |
return( FALSE ); | |
} | |
$msg = $_SESSION['message']; | |
unset( $_SESSION['message'] ); | |
return( $msg ); | |
} | |
/** | |
* makeCookie | |
* | |
* wrapper to set a cookie | |
* @access public | |
* @param $name the cookie name | |
* @param $value the cookie value | |
* @param $expiry when the cookie should expire. Leave as "0" for the cookie to expire on browser close | |
* @param $path the path on the server that the cookie is valid. Leave as "/" to allow the cookie to be | |
* accessed at all directory levels | |
* @param $domain the domain that the cookie is set on. | |
*/ | |
public static function makeCookie( $name, $value, $expiry=0, $path="/", $domain='' ) { | |
if(! $domain ) { | |
$domain = dbSession::$cookie_domain; | |
} | |
setcookie( $name, $value, $expiry, $path, $domain ); | |
} | |
/** | |
* getCookie | |
* | |
* wrapper to retrieve a cookie | |
* @access public | |
* @param $name the cookie name | |
* @param $serialized whether the cookie contains a serialized string, like a serialized array | |
*/ | |
public static function getCookie( $name, $serialized=FALSE ) { | |
if(! $_COOKIE[$name] ) { | |
return; | |
} | |
$c = $_COOKIE[$name]; | |
if( $serialized ) { | |
$c = unserialize( stripslashes( $c ) ); | |
} | |
return( $c ); | |
} | |
/** | |
* killCookie | |
* | |
* wrapper to destroy a cookie | |
* @access public | |
* @param $name the cookie name | |
* @param $path the path on the server that the cookie is valid. Leave as "/" to allow the cookie to be | |
* accessed at all directory levels | |
* @param $domain the domain that the cookie is set on. | |
*/ | |
public static function killCookie( $name, $path="/", $domain='' ) { | |
if(! $domain ) { | |
$domain = dbSession::$cookie_domain; | |
} | |
dbSession::makeCookie( $name, '', time()-3600, $path, $domain ); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment