/* 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;
+ }
}
}
}
$_SESSION[$ob->app][$ob->name] = $value;
+ $this->sessionHandler->changed = true;
}
/**
<?php
/**
- * Horde_SessionHandler_Base is the abstract class that all drivers inherit
- * from.
+ * This is the abstract class that all drivers inherit from.
*
* Copyright 2002-2010 The Horde Project (http://www.horde.org/)
*
*
* @author Michael Slusarz <slusarz@horde.org>
* @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:
* <pre>
- * '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
* </pre>
*/
public function __construct(array $params = array())
$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(
}
/**
- * 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.
public function read($id)
{
$result = $this->_read($id);
- $this->_sig = md5($result);
+ if (empty($this->_params['no_md5'])) {
+ $this->_sig = md5($result);
+ }
return $result;
}
*/
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;
}
/**