Changes for database-driven PHPSESSION implementation. See bug 312629.

This commit is contained in:
mike.morgan%oregonstate.edu 2005-10-17 20:27:34 +00:00
Родитель d6f11c8376
Коммит 599b996360
4 изменённых файлов: 241 добавлений и 166 удалений

Просмотреть файл

@ -1,32 +0,0 @@
<?php
/**
* AMO global configuration document.
* Unless otherwise noted, trailing slashes should not be used.
* @package amo
* @subpackage inc
*/
// Set runtime error options.
// See http://php.oregonstate.edu/manual/en/ref.errorfunc.php#errorfunc.constants
define('DISPLAY_ERRORS',1);
define('ERROR_REPORTING',2047);
define('ROOT_PATH','/home/morgamic/public_html/v2');
define('WEB_PATH','/~morgamic/v2');
// The repository directory is the place to store all addons binaries.
// This directory should be writable by the webserver (apache:apache).
define('REPO_DIR',ROOT_PATH.'/files');
define('LIB',ROOT_PATH.'/lib');
define('TEMPLATE_DIR',ROOT_PATH.'/tpl');
define('COMPILE_DIR',LIB.'/smarty/templates_c');
define('CACHE_DIR',LIB.'/smarty/cache');
define('CONFIG_DIR',LIB.'/smarty/configs');
define('DB_USER','username');
define('DB_PASS','password');
define('DB_HOST','localhost');
define('DB_NAME','database');
?>

Просмотреть файл

@ -6,12 +6,12 @@
* @subpackage inc
*/
// Disconnect from our database.
$db->disconnect();
// Set our wrapper if it has not been set.
$wrapper = (!isset($wrapper)) ? 'inc/wrappers/default.tpl' : $wrapper;
// Display output.
$tpl->display($wrapper);
// Disconnect from our database.
//$db->disconnect();
?>

Просмотреть файл

@ -28,6 +28,43 @@ require_once(LIB.'/sql.class.php');
require_once(LIB.'/user.class.php');
require_once(LIB.'/version.class.php');
// Database configuration.
class AMO_SQL extends SQL
{
function AMO_SQL()
{
$dsn = array (
'phptype' => 'mysql',
'dbsyntax' => 'mysql',
'username' => DB_USER,
'password' => DB_PASS,
'hostspec' => DB_HOST,
'database' => DB_NAME,
'port' => DB_PORT
);
$this->connect($dsn);
// Test connection; display "gone fishing" on failure.
if (DB::isError($this->db)) {
triggerError($this->error,'site-down.tpl');
}
}
}
// Global DB object.
$db = new AMO_SQL();
if (USE_DB_SESSIONS)
{
$amo_session_handler = new AMO_Session($db);
session_set_save_handler(array(&$amo_session_handler, '_open'),
array(&$amo_session_handler, '_close'),
array(&$amo_session_handler, '_read'),
array(&$amo_session_handler, '_write'),
array(&$amo_session_handler, '_destroy'),
array(&$amo_session_handler, '_gc'));
}
// Smarty configuration.
class AMO_Smarty extends Smarty
{
@ -47,31 +84,7 @@ class AMO_Smarty extends Smarty
}
}
// Database configuration.
class AMO_SQL extends SQL
{
function AMO_SQL()
{
$dsn = array (
'phptype' => 'mysql',
'dbsyntax' => 'mysql',
'username' => DB_USER,
'password' => DB_PASS,
'hostspec' => DB_HOST,
'database' => DB_NAME
);
$this->connect($dsn);
// Test connection; display "gone fishing" on failure.
if (DB::isError($this->db)) {
triggerError($this->error,'site-down.tpl');
}
}
}
// Global template object.
$tpl = new AMO_Smarty();
// Global DB object.
$db = new AMO_SQL();
?>

Просмотреть файл

@ -4,123 +4,217 @@
* This class circumvents basic PHP Sessions and uses MySQL to store all session data.
* This was done was to preserve sessions across different LVS nodes by utilizing the application latyer.
*
* References:
* http://www.zend.com/zend/spotlight/code-gallery-wade8.php
*
* Due to the realities of PHP 5.0.5+ having a new and upsetting
* order of destruction [1] we have to force a session write at
* __destruct or there'll be no [db] class to use. Not really an
* issue for AMO live, but annoying for devs using 5+
*
* [1] http://bugs.php.net/bug.php?id=33772
*
* @package amo
* @subpackage lib
*/
class Session {
var $id;
var $data;
var $db;
class AMO_Session
{
/**
* SQL Pear::DB wrapper
* @var SQL
*/
private static $db;
/**
* The table in which sessions are stored
* @var string
*/
private static $dbTable = 'PHPSESSION';
/**
* Constructor
* @param $aDb object the database handle to use for storage
*/
function __construct(&$aDb)
{
self::$db = $aDb;
}
/**
* Constructor.
*
* @param int $id
*/
function Session($id=null) {
global $db;
$this->db =& $db;
/**
* Destructor
* Required to force a flush of the session data to the database
* before the class disappears.
* @link http://bugs.php.net/bug.php?id=33772
*/
function __destruct()
{
session_write_close();
}
if (!is_null($id)) {
$this->resume($id);
}
}
/**
* Prepare variables for use in SQL
* @param aArray array hash of variables to clean
* @return array a new hash with SQL cleaned values, FALSE on failure
*
* TODO: should this be here or should we extend SQL to handle hashes like
* this since it happens so often?
*/
function _prepareForSql($in)
{
/**
* If we don't have a database connection then we
* can't really continue
*/
if (empty(self::$db))
return FALSE;
$out = array();
foreach ($in as $key => $value)
{
// TODO: when the SQL class gets it's own escapeSimple then
// change this to use that instead
$out[$key] = self::$db->db->escapeSimple($value);
}
/**
* Write (or overwrite) a value to the session data array.
*
* @param string $key
* @param mixed $val
* @param bool $overwrite
*
* @return bool
*/
function write($key,$val,$overwrite=false) {
if (!isset($this->data[$key]) || ($this->data[$key] == $val && $overwrite)) {
$this->data[$key] = $val;
return true;
} else {
return false;
}
}
return $out;
}
/**
* Retrieve a value from the session data array.
*
* @param string $key
*
* @return mixed|bool
*/
function read($key) {
if (isset($this->data[$key])) {
return $this->data[$key];
} else {
return false;
}
}
/**
* Open a new session
*
* @param $aPath string a path to be used to store the session
* @param $aName string a filename to be used to store the session
* @return boolean TRUE on success, FALSE otherwise
*/
function _open($aPath, $aName)
{
/**
* Return FALSE if we don't have a database to use
*/
/**
* Start a session.
*
* @return bool
*/
function create() {
// Insert a session entry in the database.
if (true) {
return true;
} else {
return false;
}
// Set a cookie containing the session ID.
}
return empty(self::$db) == FALSE;
}
/**
* Resume a session. This gathers session data and restores it.
*
* @param $id
*
* @return bool
*/
function resume($id) {
// Retrieve session data from database based on id.
if (true) {
return true;
} else {
return false;
}
}
/**
* Close a session
* @return boolean TRUE on success, FALSE otherwise
*/
function _close()
{
return TRUE;
}
/**
* Read some data from a session
* @param $aSessId string a session Id
* @return string the data, or an empty string on failure
*/
function _read($aSessId)
{
if (! strlen($aSessId))
return '';
/**
* Authenticate a user account against a database.
*
* @param string $username
* @param string $password
*
* @return bool
*/
function authencticate($username,$password) {
if (true) {
return true;
} else {
return false;
}
}
/**
* If for some reason we don't have a database handle, then
* we can't really continue here
*/
if (empty(self::$db))
return '';
/**
* Clean the arguments for SQL
*/
$clean = $this->_prepareForSql(array('SessId' => $aSessId));
/**
* We only want the data, don't care about anything else
*/
$sql = sprintf("SELECT SESSIONDATA FROM %s WHERE SESSIONID='%s'", self::$dbTable, $clean['SessId']);
$data = '';
if (self::$db->query($sql, SQL_INIT, SQL_ASSOC))
{
/**
* Anything other than 1 row should indicate an error, so don't
* propagate this but rather handle it as if there was no data
* at all.
*/
if (self::$db->result->numRows() == 1)
{
$data = self::$db->record['SESSIONDATA'];
}
self::$db->result->free();
}
/**
* Check to see if the user's session is valid.
*
* @param string $cookieName
*
* @return bool
*/
function isValidSession($cookieName='mozilla-addons') {
if (true) {
return true;
} else {
return false;
}
}
return $data;
}
/**
* Write some data to the session
* @param $aSessId string a session Id
* @param $aSessData string the encoded [serialized?] session data to store
*/
function _write($aSessId, $aSessData)
{
/**
* If for some reason we don't have a database handle, then
* we can't really continue here
*/
if (empty(self::$db))
return FALSE;
/**
* Clean the arguments for SQL
*/
$clean = $this->_prepareForSql(array('SessId' => $aSessId, 'SessData' => $aSessData));
/**
* Due to the handy REPLACE [INTO] syntax, we don't care if there is already
* a record there or not, this one statment will insert or replace as needed.
* HOWEVER:
* Should we ever try to use the session Id as a foreign key in the database
* then this will cause a referential constraint failure, as the REPLACE will
* include a DELETE in cases where the record already exists. Additionally, if
* we store anything other than the SESSIONDATA in the table which doesn't have
* an automatic default then it will get lost between writes unless it is included
* in the statement.
*/
$sql = sprintf("REPLACE %s SET SESSIONID='%s', SESSIONDATA='%s'", self::$dbTable, $clean['SessId'], $clean['SessData']);
return self::$db->query($sql, SQL_NONE);
}
/**
* Destroy a session
* @param $aSessId string a session Id
* @return boolean TRUE on success, FALSE otherwise
*/
function _destroy($aSessId)
{
/**
* If for some reason we don't have a database handle, then
* we can't really continue here
*/
if (empty(self::$db))
return FALSE;
/**
* Clean the arguments for SQL
*/
$clean = $this->_prepareForSql(array('SessId' => $aSessId));
$sql = sprintf("DELETE FROM %s WHERE SESSIONID='%s'", self::$dbTable, $clean['SessId']);
return self::$db->db->query($sql);
}
/**
* Garbage collector
* @param $aLifeTime number maximum age of a session to retain
* @return boolean TRUE on success, FALSE otherwise
*/
function _gc($sLifeTime)
{
return TRUE;
}
}
?>