From 53eeaef28ac9dd7aeeac25f780139c2d471bdce7 Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Wed, 13 Oct 2010 22:31:06 -0600 Subject: [PATCH] Add code needed to manually mark session data as dirty Disable by default in Horde for now (will be enabled when all session access code has been converted to Horde_Session). --- .../Core/lib/Horde/Core/Factory/SessionHandler.php | 21 +--- framework/Core/lib/Horde/Session.php | 15 +++ .../SessionHandler/lib/Horde/SessionHandler.php | 106 +++++++++------------ 3 files changed, 61 insertions(+), 81 deletions(-) diff --git a/framework/Core/lib/Horde/Core/Factory/SessionHandler.php b/framework/Core/lib/Horde/Core/Factory/SessionHandler.php index b24a4ad88..c65d48b1a 100644 --- a/framework/Core/lib/Horde/Core/Factory/SessionHandler.php +++ b/framework/Core/lib/Horde/Core/Factory/SessionHandler.php @@ -69,10 +69,9 @@ class Horde_Core_Factory_SessionHandler } $params['logger'] = $logger; - $params['modified'] = array( - 'get' => array($this, 'getModified'), - 'set' => array($this, 'setModified') - ); + // TODO: Uncomment once all session data is saved through + // Horde_Session. + //$params['no_md5'] = true $params['parse'] = array($this, 'readSessionData'); $driver = basename(strtolower($driver)); @@ -125,18 +124,4 @@ class Horde_Core_Factory_SessionHandler return false; } - /** - */ - public function getModified() - { - return $GLOBALS['session']['horde:session_mod']; - } - - /** - */ - public function setModified($date) - { - $GLOBALS['session']['horde:session_mod'] = $date; - } - } diff --git a/framework/Core/lib/Horde/Session.php b/framework/Core/lib/Horde/Session.php index c3e3468ef..0983bc2dd 100644 --- a/framework/Core/lib/Horde/Session.php +++ b/framework/Core/lib/Horde/Session.php @@ -105,6 +105,20 @@ class Horde_Session implements ArrayAccess /* Is this key serialized? */ $_SESSION[self::SERIALIZED] = array(); } + + /* Determine if we need to force write the session to avoid a + * session timeout, even though the session is unchanged. + * Theory: On initial login, set the current time plus half of the + * max lifetime in the session. Then check this timestamp before + * saving. If we exceed, force a write of the session and set a + * new timestamp. Why half the maxlifetime? It guarantees that if + * we are accessing the server via a periodic mechanism (think + * folder refreshing in IMP) that we will catch this refresh. */ + $curr_time = time(); + if ($curr_time >= intval($this['horde:session_mod'])) { + $this['horde:session_mod'] = $curr_time + (ini_get('session.gc_maxlifetime') / 2); + $this->sessionHandler->changed = true; + } } } @@ -334,6 +348,7 @@ class Horde_Session implements ArrayAccess } $_SESSION[$ob->app][$ob->name] = $value; + $this->sessionHandler->changed = true; } /** diff --git a/framework/SessionHandler/lib/Horde/SessionHandler.php b/framework/SessionHandler/lib/Horde/SessionHandler.php index 6df6f5882..a943715ef 100644 --- a/framework/SessionHandler/lib/Horde/SessionHandler.php +++ b/framework/SessionHandler/lib/Horde/SessionHandler.php @@ -1,7 +1,6 @@ * @category Horde + * @license http://www.fsf.org/copyleft/lgpl.html LGPL * @package SessionHandler */ abstract class Horde_SessionHandler { /** - * Hash containing connection parameters. + * If true, indicates the session data has changed. * - * @var array + * @var boolean */ - protected $_params = array(); + public $changed = false; /** - * Initial session data signature. + * Has a connection been made to the backend? * - * @var string + * @var boolean */ - protected $_sig; + protected $_connected = false; /** - * Force saving the session data? + * A logger instance. * - * @var boolean + * @var Horde_Log_Logger */ - protected $_force = false; + protected $_logger; /** - * Has a connection been made to the backend? + * Hash containing connection parameters. * - * @var boolean + * @var array */ - protected $_connected = false; + protected $_params = array(); /** - * A logger instance. + * Initial session data signature. * - * @var Horde_Log_Logger + * @var string */ - protected $_logger; + protected $_sig; /** * Constructor. * * @param array $params Parameters: *
-     * 'logger' - (Horde_Log_Logger) A logger instance.
-     *            DEFAULT: No logging
-     * 'modified' - (array) Callbacks used to store the session last modified
-     *              value.  Needs to define two keys: 'get' and 'set'. 'get'
-     *              returns the last modified value, 'set' receives the last
-     *              modified value as the only parameter.
-     *              DEFAULT: Not saved
-     * 'noset' - (boolean) If true, don't set the save handler.
-     *           DEFAULT: false
-     * 'parse' - (callback) A callback function that parses session
-     *           information into an array. Is passed the raw session data
-     *           as the only argument; expects either false or an array of
-     *           session data as a return.
-     *           DEFAULT: No
+     * logger - (Horde_Log_Logger) A logger instance.
+     *          DEFAULT: No logging
+     * no_md5 - (boolean) If true, does not do MD5 signatures of the session
+     *          to determine if the session has changed. If true, calling code
+     *          is responsible for marking $changed as true when the session
+     *          data has changed.
+     *          DEFAULT: false
+     * noset - (boolean) If true, don't set the save handler.
+     *         DEFAULT: false
+     * parse - (callback) A callback function that parses session
+     *         information into an array. Is passed the raw session data
+     *         as the only argument; expects either false or an array of
+     *         session data as a return.
+     *         DEFAULT: No
      * 
*/ public function __construct(array $params = array()) @@ -81,10 +81,6 @@ abstract class Horde_SessionHandler $this->_params = $params; - if (isset($this->_params['modified'])) { - register_shutdown_function(array($this, 'shutdown')); - } - if (empty($this->_params['noset'])) { ini_set('session.save_handler', 'user'); session_set_save_handler( @@ -110,27 +106,6 @@ abstract class Horde_SessionHandler } /** - * Shutdown function. - * - * Used to determine if we need to write the session to avoid a session - * timeout, even though the session is unchanged. - * Theory: On initial login, set the current time plus half of the max - * lifetime in the session. Then check this timestamp before saving. - * If we exceed, force a write of the session and set a new timestamp. - * Why half the maxlifetime? It guarantees that if we are accessing the - * server via a periodic mechanism (think folder refreshing in IMP) that - * we will catch this refresh. - */ - public function shutdown() - { - $curr_time = time(); - if ($curr_time >= intval(call_user_func($this->_params['modified']['get']))) { - call_user_func($this->_params['modified']['set'], $curr_time + (ini_get('session.gc_maxlifetime') / 2)); - $this->_force = true; - } - } - - /** * Open the backend. * * @param string $save_path The path to the session object. @@ -205,7 +180,9 @@ abstract class Horde_SessionHandler public function read($id) { $result = $this->_read($id); - $this->_sig = md5($result); + if (empty($this->_params['no_md5'])) { + $this->_sig = md5($result); + } return $result; } @@ -230,14 +207,17 @@ abstract class Horde_SessionHandler */ public function write($id, $session_data) { - if (!$this->_force && ($this->_sig == md5($session_data))) { - if ($this->_logger) { - $this->_logger->log('Session data unchanged (id = ' . $id . ')', 'DEBUG'); - } - return true; + if ($this->changed || + (empty($this->_params['no_md5']) && + ($this->_sig != md5($session_data)))) { + return $this->_write($id, $session_data); } - return $this->_write($id, $session_data); + if ($this->_logger) { + $this->_logger->log('Session data unchanged (id = ' . $id . ')', 'DEBUG'); + } + + return true; } /** -- 2.11.0