зеркало из https://github.com/mozilla/pjs.git
Changes for database-driven PHPSESSION implementation. See bug 312629.
This commit is contained in:
Родитель
d6f11c8376
Коммит
599b996360
|
@ -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;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
Загрузка…
Ссылка в новой задаче