first commit
This commit is contained in:
126
ZeedFramework/library/Zeed/Session/Storage/Abstract.php
Normal file
126
ZeedFramework/library/Zeed/Session/Storage/Abstract.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Zeed Platform Project
|
||||
* Based on Zeed Framework & Zend Framework.
|
||||
*
|
||||
* BTS - Billing Transaction Service
|
||||
* CAS - Central Authentication Service
|
||||
*
|
||||
* LICENSE
|
||||
* http://www.zeed.com.cn/license/
|
||||
*
|
||||
* @category Zeed
|
||||
* @package Zeed_ChangeMe
|
||||
* @subpackage ChangeMe
|
||||
* @copyright Copyright (c) 2010 Zeed Technologies PRC Inc. (http://www.zeed.com.cn)
|
||||
* @author Zeed Team (http://blog.zeed.com.cn)
|
||||
* @since 2010-7-2
|
||||
* @version SVN: $Id$
|
||||
*/
|
||||
|
||||
abstract class Zeed_Session_Storage_Abstract {
|
||||
/**
|
||||
* Session lifetime
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_lifetime = false;
|
||||
|
||||
/**
|
||||
* Whether or not the lifetime of an existing session should be overridden
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_overrideLifetime = false;
|
||||
|
||||
/**
|
||||
* Session 保存路径
|
||||
* 该值从 session_set_save_handler.Open 中传递过来
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_sessionSavePath;
|
||||
|
||||
/**
|
||||
* Session 名称
|
||||
* 该值从 session_set_save_handler.Open 中传递过来
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_sessionName;
|
||||
|
||||
/**
|
||||
* 设置 Session 生命周期,如果设置了一个无效值那么使用系统配置 PHP.INI
|
||||
*
|
||||
* @param integer $lifetime
|
||||
* @return Zend_Session_SaveHandler_DbTable
|
||||
*/
|
||||
public function setLifetime($lifetime)
|
||||
{
|
||||
if (empty($lifetime) || $lifetime < 0) {
|
||||
$this->_lifetime = (int) ini_get('session.gc_maxlifetime');
|
||||
} else {
|
||||
$this->_lifetime = (int) $lifetime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Session 生命周期
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getLifetime()
|
||||
{
|
||||
return $this->_lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 Session 在更新后是否同时更新时间
|
||||
* 如果设置为否,那么 Session 的生命不会得到延长
|
||||
*
|
||||
* @param boolean $overrideLifetime
|
||||
*/
|
||||
public function setOverrideLifetime($overrideLifetime)
|
||||
{
|
||||
$this->_overrideLifetime = (boolean) $overrideLifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve whether or not the lifetime of an existing session should be overridden
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getOverrideLifetime()
|
||||
{
|
||||
return $this->_overrideLifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Session
|
||||
*
|
||||
* @param string $save_path
|
||||
* @param string $name
|
||||
* @return boolean
|
||||
*/
|
||||
public function open($savePath, $name)
|
||||
{
|
||||
$this->_sessionSavePath = $savePath;
|
||||
$this->_sessionName = $name;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close session
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// End ^ Native EOL ^ encoding
|
||||
88
ZeedFramework/library/Zeed/Session/Storage/Db.php
Normal file
88
ZeedFramework/library/Zeed/Session/Storage/Db.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* iNewS Project
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* http://www.inews.com.cn/license/inews
|
||||
*
|
||||
* @category iNewS
|
||||
* @package ChangeMe
|
||||
* @subpackage ChangeMe
|
||||
* @copyright Copyright (c) 2008 Zeed Technologies PRC Inc. (http://www.inews.com.cn)
|
||||
* @author xSharp ( GTalk: xSharp@gmail.com )
|
||||
* @since 2010-3-8
|
||||
* @version SVN: $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Storage session data to SQL Database Server(MySQL/PostgreSQL/MSSQL/Oracle).
|
||||
*/
|
||||
class Zeed_Session_Storage_Db extends Zeed_Db_Model implements Zeed_Session_Storage_Interface
|
||||
{
|
||||
|
||||
/*
|
||||
* The table name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_name = 'session';
|
||||
|
||||
public function open($save_path, $name)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Array $set
|
||||
* @param String $where
|
||||
* @return Integer
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
}
|
||||
|
||||
public function read($id)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Array $set
|
||||
* @return Integer
|
||||
*/
|
||||
public function write($id, $data)
|
||||
{
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
}
|
||||
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 为啥需要这个函数呢?
|
||||
* 这个就是用来获取这个Class的类名
|
||||
*
|
||||
* @return Zeed_Db_Session
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
return parent::_instance(__CLASS__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// End ^ LF ^ encoding
|
||||
67
ZeedFramework/library/Zeed/Session/Storage/Interface.php
Normal file
67
ZeedFramework/library/Zeed/Session/Storage/Interface.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* iNewS Project
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* http://www.inews.com.cn/license/inews
|
||||
*
|
||||
* @category iNewS
|
||||
* @package ChangeMe
|
||||
* @subpackage ChangeMe
|
||||
* @copyright Copyright (c) 2008 Zeed Technologies PRC Inc. (http://www.inews.com.cn)
|
||||
* @author xSharp ( GTalk: xSharp@gmail.com )
|
||||
* @since Apr 2, 2010
|
||||
* @version SVN: $Id$
|
||||
*/
|
||||
|
||||
interface Zeed_Session_Storage_Interface
|
||||
{
|
||||
/**
|
||||
* Open Session - retrieve resources
|
||||
*
|
||||
* @param string $save_path
|
||||
* @param string $name
|
||||
*/
|
||||
public function open($save_path, $name);
|
||||
|
||||
/**
|
||||
* Close Session - free resources
|
||||
*
|
||||
*/
|
||||
public function close();
|
||||
|
||||
/**
|
||||
* Read session data
|
||||
*
|
||||
* @param string $id
|
||||
*/
|
||||
public function read($id);
|
||||
|
||||
/**
|
||||
* Write Session - commit data to resource
|
||||
*
|
||||
* @param string $id
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function write($id, $data);
|
||||
|
||||
/**
|
||||
* Destroy Session - remove data from resource for
|
||||
* given session id
|
||||
*
|
||||
* @param string $id
|
||||
*/
|
||||
public function destroy($id);
|
||||
|
||||
/**
|
||||
* Garbage Collection - remove old session data older
|
||||
* than $maxlifetime (in seconds)
|
||||
*
|
||||
* @param int $maxlifetime
|
||||
*/
|
||||
public function gc($maxlifetime);
|
||||
}
|
||||
|
||||
|
||||
// End ^ LF ^ encoding
|
||||
31
ZeedFramework/library/Zeed/Session/Storage/Libmemcached.php
Normal file
31
ZeedFramework/library/Zeed/Session/Storage/Libmemcached.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* iNewS Project
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* http://www.inews.com.cn/license/inews
|
||||
*
|
||||
* @category iNewS
|
||||
* @package ChangeMe
|
||||
* @subpackage ChangeMe
|
||||
* @copyright Copyright (c) 2008 Zeed Technologies PRC Inc. (http://www.inews.com.cn)
|
||||
* @author xSharp ( GTalk: xSharp@gmail.com )
|
||||
* @since Apr 2, 2010
|
||||
* @version SVN: $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Zend_Session_SaveHandler_DbTable
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Session
|
||||
* @subpackage SaveHandler
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zeed_Session_Storage_Libmemcached extends Zeed_Session_Storage_Memcached
|
||||
{
|
||||
}
|
||||
|
||||
// End ^ LF ^ encoding
|
||||
215
ZeedFramework/library/Zeed/Session/Storage/Memcache.php
Normal file
215
ZeedFramework/library/Zeed/Session/Storage/Memcache.php
Normal file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
/**
|
||||
* iNewS Project
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* http://www.inews.com.cn/license/inews
|
||||
*
|
||||
* @category iNewS
|
||||
* @package ChangeMe
|
||||
* @subpackage ChangeMe
|
||||
* @copyright Copyright (c) 2008 Zeed Technologies PRC Inc. (http://www.inews.com.cn)
|
||||
* @author xSharp ( GTalk: xSharp@gmail.com )
|
||||
* @since Apr 2, 2010
|
||||
* @version SVN: $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Zend_Session_SaveHandler_DbTable
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Session
|
||||
* @subpackage SaveHandler
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zeed_Session_Storage_Memcache extends Zend_Cache_Backend_Memcached implements Zeed_Session_Storage_Interface
|
||||
{
|
||||
/**
|
||||
* Session lifetime
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_lifetime = false;
|
||||
|
||||
/**
|
||||
* Whether or not the lifetime of an existing session should be overridden
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_overrideLifetime = false;
|
||||
|
||||
/**
|
||||
* Session 保存路径
|
||||
* 该值从 session_set_save_handler.Open 中传递过来
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_sessionSavePath;
|
||||
|
||||
/**
|
||||
* Session 名称
|
||||
* 该值从 session_set_save_handler.Open 中传递过来
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_sessionName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* lifetime => (integer) Session lifetime (optional; default: ini_get('session.gc_maxlifetime'))
|
||||
*
|
||||
* @param array $config
|
||||
* @return void
|
||||
* @throws Zeed_Exception
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
if (! is_array($config)) {
|
||||
throw new Zeed_Exception('$config must be an array of key/value pairs containing ' . 'configuration options for Zeed_Session_Storage_Memcached.');
|
||||
}
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
do {
|
||||
switch ($key) {
|
||||
case 'lifetime' :
|
||||
$this->setLifetime($value);
|
||||
break;
|
||||
default :
|
||||
// unrecognized options passed to parent::__construct()
|
||||
break 2;
|
||||
}
|
||||
unset($config[$key]);
|
||||
} while (false);
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
Zeed_Session::writeClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 Session 生命周期,如果设置了一个无效值那么使用系统配置 PHP.INI
|
||||
*
|
||||
* @param integer $lifetime
|
||||
* @return Zend_Session_SaveHandler_DbTable
|
||||
*/
|
||||
public function setLifetime($lifetime)
|
||||
{
|
||||
if (empty($lifetime) || $lifetime < 0) {
|
||||
$this->_lifetime = (int) ini_get('session.gc_maxlifetime');
|
||||
} else {
|
||||
$this->_lifetime = (int) $lifetime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Session 生命周期
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getLifetime($specificLifetime = false)
|
||||
{
|
||||
return $this->_lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Session
|
||||
*
|
||||
* @param string $save_path
|
||||
* @param string $name
|
||||
* @return boolean
|
||||
*/
|
||||
public function open($savePath, $name)
|
||||
{
|
||||
$this->_sessionSavePath = $savePath;
|
||||
$this->_sessionName = $name;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close session
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read session data
|
||||
*
|
||||
* @param string $id
|
||||
* @return string
|
||||
*/
|
||||
public function read($id)
|
||||
{
|
||||
$return = '';
|
||||
|
||||
if (false != $data = $this->load($id)) {
|
||||
$return = $data;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write session data
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $data
|
||||
* @return boolean
|
||||
*/
|
||||
public function write($id, $data)
|
||||
{
|
||||
$return = false;
|
||||
|
||||
if ($this->save($data, $id, array(), $this->_lifetime)) {
|
||||
$return = true;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy session
|
||||
*
|
||||
* @param string $id
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$return = false;
|
||||
|
||||
if ($this->remove($id)) {
|
||||
$return = true;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param int $maxlifetime
|
||||
* @return true
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// End ^ LF ^ encoding
|
||||
215
ZeedFramework/library/Zeed/Session/Storage/Memcached.php
Normal file
215
ZeedFramework/library/Zeed/Session/Storage/Memcached.php
Normal file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
/**
|
||||
* iNewS Project
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* http://www.inews.com.cn/license/inews
|
||||
*
|
||||
* @category iNewS
|
||||
* @package ChangeMe
|
||||
* @subpackage ChangeMe
|
||||
* @copyright Copyright (c) 2008 Zeed Technologies PRC Inc. (http://www.inews.com.cn)
|
||||
* @author xSharp ( GTalk: xSharp@gmail.com )
|
||||
* @since Apr 2, 2010
|
||||
* @version SVN: $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Zend_Session_SaveHandler_DbTable
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Session
|
||||
* @subpackage SaveHandler
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zeed_Session_Storage_Memcached extends Zend_Cache_Backend_Libmemcached implements Zeed_Session_Storage_Interface
|
||||
{
|
||||
/**
|
||||
* Session lifetime
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_lifetime = false;
|
||||
|
||||
/**
|
||||
* Whether or not the lifetime of an existing session should be overridden
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_overrideLifetime = false;
|
||||
|
||||
/**
|
||||
* Session 保存路径
|
||||
* 该值从 session_set_save_handler.Open 中传递过来
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_sessionSavePath;
|
||||
|
||||
/**
|
||||
* Session 名称
|
||||
* 该值从 session_set_save_handler.Open 中传递过来
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_sessionName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* lifetime => (integer) Session lifetime (optional; default: ini_get('session.gc_maxlifetime'))
|
||||
*
|
||||
* @param array $config
|
||||
* @return void
|
||||
* @throws Zeed_Exception
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
if (! is_array($config)) {
|
||||
throw new Zeed_Exception('$config must be an array of key/value pairs containing ' . 'configuration options for Zeed_Session_Storage_Memcached.');
|
||||
}
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
do {
|
||||
switch ($key) {
|
||||
case 'lifetime' :
|
||||
$this->setLifetime($value);
|
||||
break;
|
||||
default :
|
||||
// unrecognized options passed to parent::__construct()
|
||||
break 2;
|
||||
}
|
||||
unset($config[$key]);
|
||||
} while (false);
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
Zeed_Session::writeClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 Session 生命周期,如果设置了一个无效值那么使用系统配置 PHP.INI
|
||||
*
|
||||
* @param integer $lifetime
|
||||
* @return Zend_Session_SaveHandler_DbTable
|
||||
*/
|
||||
public function setLifetime($lifetime)
|
||||
{
|
||||
if (empty($lifetime) || $lifetime < 0) {
|
||||
$this->_lifetime = (int) ini_get('session.gc_maxlifetime');
|
||||
} else {
|
||||
$this->_lifetime = (int) $lifetime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Session 生命周期
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getLifetime($specificLifetime = false)
|
||||
{
|
||||
return $this->_lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Session
|
||||
*
|
||||
* @param string $save_path
|
||||
* @param string $name
|
||||
* @return boolean
|
||||
*/
|
||||
public function open($savePath, $name)
|
||||
{
|
||||
$this->_sessionSavePath = $savePath;
|
||||
$this->_sessionName = $name;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close session
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read session data
|
||||
*
|
||||
* @param string $id
|
||||
* @return string
|
||||
*/
|
||||
public function read($id)
|
||||
{
|
||||
$return = '';
|
||||
|
||||
if (false != $data = $this->load($id)) {
|
||||
$return = $data;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write session data
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $data
|
||||
* @return boolean
|
||||
*/
|
||||
public function write($id, $data)
|
||||
{
|
||||
$return = false;
|
||||
|
||||
if ($this->save($data, $id, array(), $this->_lifetime)) {
|
||||
$return = true;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy session
|
||||
*
|
||||
* @param string $id
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$return = false;
|
||||
|
||||
if ($this->remove($id)) {
|
||||
$return = true;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param int $maxlifetime
|
||||
* @return true
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// End ^ LF ^ encoding
|
||||
279
ZeedFramework/library/Zeed/Session/Storage/Mongo.php
Normal file
279
ZeedFramework/library/Zeed/Session/Storage/Mongo.php
Normal file
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
/*
|
||||
* This MongoDB session handler is intended to store any data you see fit.
|
||||
*/
|
||||
class Zeed_Session_Storage_Mongo implements Zeed_Session_Storage_Interface
|
||||
{
|
||||
|
||||
/**
|
||||
* Whether session writes should be performed safely.
|
||||
* If TRUE, the
|
||||
* program will wait for a database response and throw a
|
||||
* MongoCursorException if the update failed. Can also be set to an
|
||||
* integer value for replication. For more information, see:
|
||||
* http://www.php.net/manual/en/mongocollection.update.php
|
||||
* Slower when on but minimizes any session errors when coupled with FSYNC.
|
||||
*/
|
||||
const SAFE = false;
|
||||
|
||||
/**
|
||||
* If TRUE, forces the session write to be synced to disk before
|
||||
* returning success.
|
||||
*/
|
||||
const FSYNC = false;
|
||||
|
||||
// example config with support for multiple servers
|
||||
// (helpful for sharding and replication setups)
|
||||
protected $_config = array(
|
||||
// cookie related vars
|
||||
'cookie_path' => '/',
|
||||
'cookie_domain' => null, // .mydomain.com
|
||||
|
||||
// session related vars
|
||||
'lifetime' => 3600, // session lifetime in seconds
|
||||
'database' => 'session', // name of MongoDB database
|
||||
'collection' => 'session', // name of MongoDB collection
|
||||
|
||||
// array of mongo db servers
|
||||
'servers' => array(
|
||||
array(
|
||||
'host' => Mongo::DEFAULT_HOST,
|
||||
'port' => Mongo::DEFAULT_PORT,
|
||||
'username' => null,
|
||||
'password' => null,
|
||||
'persistent' => false)));
|
||||
|
||||
// stores the mongo db
|
||||
protected $mongo;
|
||||
|
||||
// stores session data results
|
||||
private $session;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @access public
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
// initialize the database
|
||||
$this->_init(empty($config) ? $this->_config : $config);
|
||||
|
||||
// set object as the save handler
|
||||
session_set_save_handler(
|
||||
array(&$this, 'open'),
|
||||
array(&$this, 'close'),
|
||||
array(&$this, 'read'),
|
||||
array(&$this, 'write'),
|
||||
array(&$this, 'destroy'),
|
||||
array(&$this, 'gc')
|
||||
);
|
||||
|
||||
// set some important session vars
|
||||
ini_set('session.auto_start', 0);
|
||||
ini_set('session.gc_probability', 1);
|
||||
ini_set('session.gc_divisor', 100);
|
||||
ini_set('session.gc_maxlifetime', $this->_config['lifetime']);
|
||||
ini_set('session.referer_check', '');
|
||||
ini_set('session.entropy_file', '/dev/urandom');
|
||||
ini_set('session.entropy_length', 16);
|
||||
ini_set('session.use_cookies', 1);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
ini_set('session.use_trans_sid', 0);
|
||||
ini_set('session.hash_function', 1);
|
||||
ini_set('session.hash_bits_per_character', 5);
|
||||
|
||||
// disable client/proxy caching
|
||||
session_cache_limiter('nocache');
|
||||
|
||||
// set the cookie parameters
|
||||
session_set_cookie_params($this->_config['lifetime'], $this->_config['cookie_path'], $this->_config['cookie_domain']);
|
||||
// name the session
|
||||
session_name('mongo_sess');
|
||||
|
||||
// start it up
|
||||
session_start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize MongoDB.
|
||||
* There is currently no support for persistent
|
||||
* connections. It would be very easy to implement, I just didn't need it.
|
||||
*
|
||||
* @access private
|
||||
* @param array $config
|
||||
*/
|
||||
private function _init($config)
|
||||
{
|
||||
// ensure they supplied a database
|
||||
if (empty($config['database'])) {
|
||||
throw new Exception('You must specify a MongoDB database to use for session storage.');
|
||||
}
|
||||
|
||||
if (empty($config['collection'])) {
|
||||
throw new Exception('You must specify a MongoDB collection to use for session storage.');
|
||||
}
|
||||
|
||||
// update config
|
||||
$this->_config = $config;
|
||||
|
||||
// generate server connection strings
|
||||
$connections = array();
|
||||
if (! empty($this->_config['servers'])) {
|
||||
foreach ($this->_config['servers'] as $server) {
|
||||
$str = '';
|
||||
if (! empty($server['username']) && ! empty($server['password'])) {
|
||||
$str .= $server['username'] . ':' . $server['password'] . '@';
|
||||
}
|
||||
$str .= $server['host'] . ':' . $server['port'];
|
||||
array_push($connections, $str);
|
||||
}
|
||||
} else {
|
||||
// use default connection settings
|
||||
array_push($connections, Mongo::DEFAULT_HOST . ':' . Mongo::DEFAULT_PORT);
|
||||
}
|
||||
|
||||
// load mongo servers
|
||||
$mongo = new Mongo('mongodb://' . implode(',', $connections));
|
||||
|
||||
// load db
|
||||
try {
|
||||
$mongo = $mongo->selectDB($this->_config['database']);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
throw new Exception('The MongoDB database specified in the config does not exist.');
|
||||
}
|
||||
|
||||
// load collection
|
||||
try {
|
||||
$this->mongo = $mongo->selectCollection($this->_config['collection']);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('The MongoDB collection specified in the config does not exist.');
|
||||
}
|
||||
|
||||
// ensure we have proper indexing on the expiration
|
||||
$this->mongo->ensureIndex('expiry', array('expiry' => 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Open does absolutely nothing as we already have an open connection.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function open($save_path, $session_name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close does absolutely nothing as we can assume __destruct handles
|
||||
* things just fine.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the session data.
|
||||
*
|
||||
* @access public
|
||||
* @param string $id
|
||||
* @return string
|
||||
*/
|
||||
public function read($id)
|
||||
{
|
||||
// exclude results that are inactive or expired
|
||||
$result = $this->mongo->findOne(array('_id' => $id, 'expiry' => array('$gte' => time()), 'active' => 1));
|
||||
|
||||
if ($result) {
|
||||
$this->session = $result;
|
||||
return $result['data'];
|
||||
}
|
||||
|
||||
$this->mongo->insert(array('_id' => $id, 'data' => null, 'expiry' => 0, 'active' => 0));
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically write data to the session.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @param string $id
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
public function write($id, $data)
|
||||
{
|
||||
// create expires
|
||||
$expiry = time() + $this->_config['lifetime'];
|
||||
|
||||
// create new session data
|
||||
$new_obj = array('data' => $data, 'active' => 1, 'expiry' => $expiry);
|
||||
|
||||
// check for existing session for merge
|
||||
if (! empty($this->session)) {
|
||||
$obj = (array) $this->session;
|
||||
$new_obj = array_merge($obj, $new_obj);
|
||||
}
|
||||
|
||||
// atomic update
|
||||
$query = array('_id' => $id);
|
||||
|
||||
// update options
|
||||
$options = array('upsert' => true, 'safe' => Mongo::SAFE, 'fsync' => Mongo::FSYNC);
|
||||
|
||||
// perform the update or insert
|
||||
try {
|
||||
$this->mongo->update($query, array('$set' => $new_obj), $options);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the session by removing the document with
|
||||
* matching session_id.
|
||||
*
|
||||
* @access public
|
||||
* @param string $id
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$this->mongo->remove(array('_id' => $id), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collection.
|
||||
* Remove all expired entries atomically.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
// define the query
|
||||
$query = array('expiry' => array('$lt' => time()));
|
||||
|
||||
// specify the update vars
|
||||
$update = array('$set' => array('active' => 0));
|
||||
|
||||
// update options
|
||||
$options = array('multiple' => TRUE, 'safe' => Mongo::SAFE, 'fsync' => Mongo::FSYNC);
|
||||
|
||||
// update expired elements and set to inactive
|
||||
$this->mongo->update($query, $update, $options);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
397
ZeedFramework/library/Zeed/Session/Storage/MongoSession.php
Normal file
397
ZeedFramework/library/Zeed/Session/Storage/MongoSession.php
Normal file
@@ -0,0 +1,397 @@
|
||||
<?php
|
||||
/*
|
||||
* This MongoDB session handler is intended to store any data you see fit.
|
||||
* One interesting optimization to note is the setting of the active flag
|
||||
* to 0 when a session has expired. The intended purpose of this garbage
|
||||
* collection is to allow you to create a batch process for removal of
|
||||
* all expired sessions. This should most likely be implemented as a cronjob
|
||||
* script.
|
||||
*
|
||||
* @author Corey Ballou
|
||||
* @copyright Corey Ballou (2010)
|
||||
*
|
||||
*/
|
||||
class MongoSession {
|
||||
|
||||
// default config with support for multiple servers
|
||||
// (helpful for sharding and replication setups)
|
||||
protected $_config = array(
|
||||
// cookie related vars
|
||||
'cookie_path' => '/',
|
||||
'cookie_domain' => '.mydomain.com', // .mydomain.com
|
||||
|
||||
// session related vars
|
||||
'lifetime' => 3600, // session lifetime in seconds
|
||||
'database' => 'session', // name of MongoDB database
|
||||
'collection' => 'session', // name of MongoDB collection
|
||||
|
||||
// persistent related vars
|
||||
'persistent' => false, // persistent connection to DB?
|
||||
'persistentId' => 'MongoSession', // name of persistent connection
|
||||
|
||||
// whether we're supporting replicaSet
|
||||
'replicaSet' => false,
|
||||
|
||||
// array of mongo db servers
|
||||
'servers' => array(
|
||||
array(
|
||||
'host' => Mongo::DEFAULT_HOST,
|
||||
'port' => Mongo::DEFAULT_PORT,
|
||||
'username' => null,
|
||||
'password' => null
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// stores the connection
|
||||
protected $_connection;
|
||||
|
||||
// stores the mongo db
|
||||
protected $_mongo;
|
||||
|
||||
// stores session data results
|
||||
protected $_session;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @access public
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
// initialize the database
|
||||
$this->_init(empty($config) ? $this->_config : $config);
|
||||
|
||||
// set object as the save handler
|
||||
session_set_save_handler(
|
||||
array(&$this, 'open'),
|
||||
array(&$this, 'close'),
|
||||
array(&$this, 'read'),
|
||||
array(&$this, 'write'),
|
||||
array(&$this, 'destroy'),
|
||||
array(&$this, 'gc')
|
||||
);
|
||||
|
||||
// set some important session vars
|
||||
ini_set('session.auto_start', 0);
|
||||
ini_set('session.gc_probability', 1);
|
||||
ini_set('session.gc_divisor', 100);
|
||||
ini_set('session.gc_maxlifetime', $this->_config['lifetime']);
|
||||
ini_set('session.referer_check', '');
|
||||
ini_set('session.entropy_file', '/dev/urandom');
|
||||
ini_set('session.entropy_length', 16);
|
||||
ini_set('session.use_cookies', 1);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
ini_set('session.use_trans_sid', 0);
|
||||
ini_set('session.hash_function', 1);
|
||||
ini_set('session.hash_bits_per_character', 5);
|
||||
|
||||
// disable client/proxy caching
|
||||
session_cache_limiter('nocache');
|
||||
|
||||
// set the cookie parameters
|
||||
session_set_cookie_params(
|
||||
$this->_config['lifetime'],
|
||||
$this->_config['cookie_path'],
|
||||
$this->_config['cookie_domain']
|
||||
);
|
||||
|
||||
// name the session
|
||||
session_name('mongo_sess');
|
||||
|
||||
// start it up
|
||||
session_start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize MongoDB. There is currently no support for persistent
|
||||
* connections. It would be very easy to implement, I just didn't need it.
|
||||
*
|
||||
* @access private
|
||||
* @param array $config
|
||||
*/
|
||||
private function _init($config)
|
||||
{
|
||||
// ensure they supplied a database
|
||||
if (empty($config['database'])) {
|
||||
throw new Exception('You must specify a MongoDB database to use for session storage.');
|
||||
}
|
||||
|
||||
if (empty($config['collection'])) {
|
||||
throw new Exception('You must specify a MongoDB collection to use for session storage.');
|
||||
}
|
||||
|
||||
// update config
|
||||
$this->_config = $config;
|
||||
|
||||
// generate server connection strings
|
||||
$connections = array();
|
||||
if (!empty($this->_config['servers'])) {
|
||||
foreach ($this->_config['servers'] as $server) {
|
||||
$str = '';
|
||||
if (!empty($server['username']) && !empty($server['password'])) {
|
||||
$str .= $server['username'] . ':' . $server['password'] . '@';
|
||||
}
|
||||
$str .= !empty($server['host']) ? $server['host'] : Mongo::DEFAULT_HOST;
|
||||
$str .= ':' . (!empty($server['port']) ? (int) $server['port'] : Mongo::DEFAULT_PORT);
|
||||
array_push($connections, $str);
|
||||
}
|
||||
} else {
|
||||
// use default connection settings
|
||||
array_push($connections, Mongo::DEFAULT_HOST . ':' . Mongo::DEFAULT_PORT);
|
||||
}
|
||||
|
||||
// add immediate connection
|
||||
$opts = array('connect' => true);
|
||||
|
||||
// support persistent connections
|
||||
if ($this->_config['persistent'] && !empty($this->_config['persistentId'])) {
|
||||
$opts['persist'] = $this->_config['persistentId'];
|
||||
}
|
||||
|
||||
// support replica sets
|
||||
if ($this->_config['replicaSet']) {
|
||||
$opts['replicaSet'] = true;
|
||||
}
|
||||
|
||||
// load mongo server connection
|
||||
try {
|
||||
$this->_connection = new Mongo('mongodb://' . implode(',', $connections), $opts);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('Can\'t connect to the MongoDB server.');
|
||||
}
|
||||
|
||||
// load the db
|
||||
try {
|
||||
$mongo = $this->_connection->selectDB($this->_config['database']);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
throw new Exception('The MongoDB database specified in the config does not exist.');
|
||||
}
|
||||
|
||||
// load collection
|
||||
try {
|
||||
$this->_mongo = $mongo->selectCollection($this->_config['collection']);
|
||||
} catch(Exception $e) {
|
||||
throw new Exception('The MongoDB collection specified in the config does not exist.');
|
||||
}
|
||||
|
||||
// proper indexing on the expiration
|
||||
$this->_mongo->ensureIndex(
|
||||
array('expiry' => 1),
|
||||
array('name' => 'expiry',
|
||||
'unique' => true,
|
||||
'dropDups' => true,
|
||||
'safe' => true
|
||||
)
|
||||
);
|
||||
|
||||
// proper indexing of session id and lock
|
||||
$this->_mongo->ensureIndex(
|
||||
array('session_id' => 1, 'lock' => 1),
|
||||
array('name' => 'session_id',
|
||||
'unique' => true,
|
||||
'dropDups' => true,
|
||||
'safe' => true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open does absolutely nothing as we already have an open connection.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function open($save_path, $session_name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close does absolutely nothing as we can assume __destruct handles
|
||||
* things just fine.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the session data.
|
||||
*
|
||||
* @access public
|
||||
* @param string $id
|
||||
* @return string
|
||||
*/
|
||||
public function read($id)
|
||||
{
|
||||
// obtain a read lock on the data, or subsequently wait for
|
||||
// the lock to be released
|
||||
$this->_lock($id);
|
||||
|
||||
// exclude results that are inactive or expired
|
||||
$result = $this->_mongo->findOne(
|
||||
array(
|
||||
'session_id' => $id,
|
||||
'expiry' => array('$gte' => time()),
|
||||
'active' => 1
|
||||
)
|
||||
);
|
||||
|
||||
if (isset($result['data'])) {
|
||||
$this->_session = $result;
|
||||
return $result['data'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically write data to the session, ensuring we remove any
|
||||
* read locks.
|
||||
*
|
||||
* @access public
|
||||
* @param string $id
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
public function write($id, $data)
|
||||
{
|
||||
// create expires
|
||||
$expiry = time() + $this->_config['lifetime'];
|
||||
|
||||
// create new session data
|
||||
$new_obj = array(
|
||||
'data' => $data,
|
||||
'lock' => 0,
|
||||
'active' => 1,
|
||||
'expiry' => $expiry
|
||||
);
|
||||
|
||||
// check for existing session for merge
|
||||
if (!empty($this->_session)) {
|
||||
$obj = (array) $this->_session;
|
||||
$new_obj = array_merge($obj, $new_obj);
|
||||
}
|
||||
|
||||
// atomic update
|
||||
$query = array('session_id' => $id);
|
||||
|
||||
// update options
|
||||
$options = array(
|
||||
'upsert' => TRUE,
|
||||
'safe' => TRUE,
|
||||
'fsync' => TRUE
|
||||
);
|
||||
|
||||
// perform the update or insert
|
||||
try {
|
||||
$result = $this->_mongo->update($query, array('$set' => $new_obj), $options);
|
||||
return $result['ok'] == 1;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the session by removing the document with
|
||||
* matching session_id.
|
||||
*
|
||||
* @access public
|
||||
* @param string $id
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$this->_mongo->remove(array('session_id' => $id), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collection. Remove all expired entries atomically.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
// define the query
|
||||
$query = array('expiry' => array('$lt' => time()));
|
||||
|
||||
// specify the update vars
|
||||
$update = array('$set' => array('active' => 0));
|
||||
|
||||
// update options
|
||||
$options = array(
|
||||
'multiple' => TRUE,
|
||||
'safe' => TRUE,
|
||||
'fsync' => TRUE
|
||||
);
|
||||
|
||||
// update expired elements and set to inactive
|
||||
$this->_mongo->update($query, $update, $options);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Solves issues with write() and close() throwing exceptions.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a global lock for the specified document.
|
||||
*
|
||||
* @author Benson Wong (mostlygeek@gmail.com)
|
||||
* @access private
|
||||
* @param string $id
|
||||
*/
|
||||
private function _lock($id)
|
||||
{
|
||||
$remaining = 30000000;
|
||||
$timeout = 5000;
|
||||
|
||||
do {
|
||||
|
||||
try {
|
||||
|
||||
$query = array('session_id' => $id, 'lock' => 0);
|
||||
$update = array('$set' => array('lock' => 1));
|
||||
$options = array('safe' => true, 'upsert' => true);
|
||||
$result = $this->_mongo->update($query, $update, $options);
|
||||
if ($result['ok'] == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (MongoCursorException $e) {
|
||||
if (substr($e->getMessage(), 0, 26) != 'E11000 duplicate key error') {
|
||||
throw $e; // not a dup key?
|
||||
}
|
||||
}
|
||||
|
||||
// force delay in microseconds
|
||||
usleep($timeout);
|
||||
$remaining -= $timeout;
|
||||
|
||||
// backoff on timeout, save a tree. max wait 1 second
|
||||
$timeout = ($timeout < 1000000) ? $timeout * 2 : 1000000;
|
||||
|
||||
} while ($remaining > 0);
|
||||
|
||||
// aww shit.
|
||||
throw new Exception('Could not obtain a session lock.');
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user