Files
server/usr/share/psa-pear/pear/php/Horde/SessionHandler.php
2026-01-07 20:52:11 +01:00

297 lines
8.2 KiB
PHP

<?php
/**
* This class provides the interface to the session storage backend.
*
* Copyright 2002-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package SessionHandler
*/
class Horde_SessionHandler
{
/**
* If true, indicates the session data has changed.
*
* @var boolean
*/
public $changed = false;
/**
* Has a connection been made to the backend?
*
* @var boolean
*/
protected $_connected = false;
/**
* A logger instance.
*
* @var Horde_Log_Logger
*/
protected $_logger;
/**
* Configuration parameters.
*
* @var array
*/
protected $_params = array();
/**
* Initial session data signature.
*
* @var string
*/
protected $_sig;
/**
* The storage object.
*
* @var Horde_SessionHandler_Storage
*/
protected $_storage;
/**
* Constructor.
*
* @param Horde_SessionHandler_Storage $storage The storage object.
* @param array $params Configuration parameters:
* <pre>
* - 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 (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(Horde_SessionHandler_Storage $storage,
array $params = array())
{
$params = array_merge($this->_params, $params);
$this->_logger = isset($params['logger'])
? $params['logger']
: new Horde_Support_Stub();
unset($params['logger']);
$this->_params = $params;
$this->_storage = $storage;
if (empty($this->_params['noset'])) {
session_set_save_handler(
array($this, 'open'),
array($this, 'close'),
array($this, 'read'),
array($this, 'write'),
array($this, 'destroy'),
array($this, 'gc')
);
}
}
/**
* Destructor.
*/
public function __destruct()
{
/* This is necessary as of PHP 5.0.5 because objects are not available
* when the write() handler is called at the end of a session
* access. */
session_write_close();
}
/**
* Open the backend.
*
* @param string $save_path The path to the session object.
* @param string $session_name The name of the session.
*
* @return boolean True on success, false otherwise.
*/
public function open($save_path = null, $session_name = null)
{
if (!$this->_connected) {
try {
$this->_storage->open($save_path, $session_name);
} catch (Horde_SessionHandler_Exception $e) {
$this->_logger->log($e, 'ERR');
return false;
}
$this->_connected = true;
}
return true;
}
/**
* Close the backend.
*
* @return boolean True on success, false otherwise.
*/
public function close()
{
try {
$this->_storage->close();
} catch (Horde_SessionHandler_Exception $e) {
$this->_logger->log($e, 'ERR');
}
$this->_connected = false;
return true;
}
/**
* Read the data for a particular session identifier from the backend.
* This method should only be called internally by PHP via
* session_set_save_handler().
*
* @param string $id The session identifier.
*
* @return string The session data.
*/
public function read($id)
{
if (($result = $this->_storage->read($id)) == '') {
$this->_logger->log('Error retrieving session data (' . $id . ')', 'DEBUG');
} else {
$this->_logger->log('Read session data (' . $id . ')', 'DEBUG');
}
if (empty($this->_params['no_md5'])) {
$this->_sig = md5($result);
}
return $result;
}
/**
* Write session data to the backend.
* This method should only be called internally by PHP via
* session_set_save_handler().
*
* @param string $id The session identifier.
* @param string $session_data The session data.
*
* @return boolean True on success, false otherwise.
*/
public function write($id, $session_data)
{
if ($this->changed ||
(empty($this->_params['no_md5']) &&
($this->_sig != md5($session_data)))) {
if (!$this->_storage->write($id, $session_data)) {
$this->_logger->log('Failed to write session data (' . $id . ')', 'DEBUG');
return false;
}
$this->_logger->log('Wrote session data (' . $id . ')', 'DEBUG');
}
return true;
}
/**
* Destroy the data for a particular session identifier in the backend.
* This method should only be called internally by PHP via
* session_set_save_handler().
*
* @param string $id The session identifier.
*
* @return boolean True on success, false otherwise.
*/
public function destroy($id)
{
if ($this->_storage->destroy($id)) {
$this->_logger->log('Session data destroyed (' . $id . ')', 'DEBUG');
return true;
}
$this->_logger->log('Failed to destroy session data (' . $id . ')', 'DEBUG');
return false;
}
/**
* Garbage collect stale sessions from the backend.
* This method should only be called internally by PHP via
* session_set_save_handler().
*
* @param integer $maxlifetime The maximum age of a session.
*
* @return boolean True on success, false otherwise.
*/
public function gc($maxlifetime = 300)
{
return $this->_storage->gc($maxlifetime);
}
/**
* Get a list of the valid session identifiers.
*
* @return array A list of valid session identifiers.
* @throws Horde_SessionHandler_Exception
*/
public function getSessionIDs()
{
return $this->_storage->getSessionIDs();
}
/**
* Returns a list of authenticated users and data about their session.
*
* @return array For authenticated users, the sessionid as a key and the
* session information as value. If no parsing function
* was provided, will always return an empty array.
* @throws Horde_SessionHandler_Exception
*/
public function getSessionsInfo()
{
$info = array();
if (empty($this->_params['parse']) ||
!is_callable($this->_params['parse'])) {
return $info;
}
/* Explicitly do garbage collection call here to make sure session
* data is correct. */
$this->gc(ini_get('session.gc_maxlifetime'));
$sessions = $this->getSessionIDs();
$this->_storage->readonly = true;
foreach ($sessions as $id) {
try {
$data = $this->read($id);
$this->close();
} catch (Horde_SessionHandler_Exception $e) {
continue;
}
$data = call_user_func($this->_params['parse'], $data);
if ($data !== false) {
$info[$id] = $data;
}
}
$this->_storage->readonly = false;
return $info;
}
}