D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
var
/
www
/
oems
/
wp-content
/
plugins
/
.akeebabackupwp
/
helpers
/
Solo
/
Session
/
Filename :
Manager.php
back
Copy
<?php /** * @package solo * @copyright Copyright (c)2014-2024 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Solo\Session; use Awf\Session\CsrfToken; use Awf\Session\CsrfTokenFactory; use Awf\Session\Segment; use Awf\Session\SegmentFactory; use Awf\Session\SegmentInterface; use Solo\Helper\HashHelper; class Manager extends \Awf\Session\Manager { /** * A session segment factory. * * @var SegmentFactory */ protected $segment_factory; /** * The CSRF token for this session. * * @var CsrfToken */ protected $csrf_token; /** * A CSRF token factory, for lazy-creating the CSRF token. * * @var CsrfTokenFactory */ protected $csrf_token_factory; /** * Session cookie parameters. Ignored in this implementation. * * @var array */ protected $cookie_params = []; /** * Session segments * * @var Segment[] */ protected $segments = []; /** * Session name. Used as a prefix of the user meta values. * * @var string */ private $sessionName = 'AkeebaSession'; /** * Session ID. This is set to a random string every time we "start a session" (load stuff from the database). * * @var string */ private $sessionId = ''; public function __construct( $segment_factory, $csrf_token_factory, array $cookies = [], array $sessionCreateParameters = [] ) { $this->segment_factory = $segment_factory; $this->csrf_token_factory = $csrf_token_factory; $this->cookies = $cookies; $this->cookie_params = session_get_cookie_params(); $this->sessionCreateParameters = $sessionCreateParameters; } /** * Gets a new session segment instance by name. Segments with the same name will be different objects but will * reference the same registry values, so it is possible to have two or more objects that share state. * * @param string $name The name of the session segment * * @return Segment */ public function newSegment(string $name): Segment { if (!isset($this->segments[$name])) { $this->segments[$name] = $this->segment_factory->newInstance($this, $name); } return $this->segments[$name]; } /** * Tells us if a session is available to be reactivated. It won't tell you if it has started yet. * * @return bool */ public function isAvailable(): bool { // CLI mode if (!defined('WPINC')) { return true; } // Checks if the <session name>_id user meta key exists in WP's database $metaKey = $this->getName() . '_id'; $userId = get_current_user_id(); // If the user meta key doesn't exist WP will return an empty string... $id = get_user_meta($userId, $metaKey, true); // ...which means we are available UNLESS $id is an empty string return $id !== ''; } /** * Tells us if a session has started. * * @return bool */ public function isStarted(): bool { // CLI mode if (!defined('WPINC')) { return true; } return $this->getStatus() == PHP_SESSION_ACTIVE; } /** * Starts a new session, or resumes an existing one. * * @return bool */ public function start(): bool { // CLI mode if (!defined('WPINC')) { return true; } if (!$this->isStarted()) { // Create a random ID $this->regenerateId(); // Save the random ID to the database $metaKey = $this->getName() . '_id'; $userId = get_current_user_id(); update_user_meta($userId, $metaKey, $this->getId()); } return true; } /** * Clears all session variables across all segments. This is implemented by removing all WordPress user meta for * the current user. Note that this does NOT close the session, it simply nukes its data. * * @return void */ public function clear(): void { // CLI mode if (!defined('WPINC')) { return; } $this->clearUserMeta(); } /** * Writes session data from all segments and ends the session. * * @return void */ public function commit(): void { // CLI mode if (!defined('WPINC')) { return; } if (count($this->segments)) { /** @var SegmentInterface $segment */ foreach ($this->segments as $segment) { $segment->save(); } } // Close the session (remove the user meta with the session ID) $userId = get_current_user_id(); delete_user_meta($userId, $this->getName() . '_id'); // Clear the ID, marking the session as closed $this->sessionId = ''; } /** * Destroys the session entirely. * * @return bool */ public function destroy(): bool { // CLI mode if (!defined('WPINC')) { return true; } $this->clearUserMeta(true); // Clear the ID, marking the session as closed $this->sessionId = ''; return true; } /** * Returns the CSRF token, creating it if needed (and thereby starting a session). * * @return CsrfToken * */ public function getCsrfToken(): CsrfToken { if (!$this->csrf_token) { $this->csrf_token = $this->csrf_token_factory->newInstance($this); } return $this->csrf_token; } /** * Sets the session cache expire time. Completely ignored in this implementation. * * @param int $expire The expiration time in seconds. * * @return int */ public function setCacheExpire(int $expire): int { return $this->getCacheExpire(); } /** * Gets the session cache expire time. Faked in this implementation to return PHP's default of 180 seconds. * * @return int The cache expiration time in seconds. */ public function getCacheExpire(): int { return 180; } /** * Sets the session cache limiter value. Ignored in this implementation (we always emulate nocache). * * @param string $limiter The limiter value. * * @return string */ public function setCacheLimiter(string $limiter): string { return $this->getCacheLimiter(); } /** * Gets the session cache limiter value. * * @return string The limiter value. */ public function getCacheLimiter(): string { return <<< END_HEADERS Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache END_HEADERS; } /** * Sets the session cookie params. * * Cookies are completely ignored in this implementation * * @param array $params The array of session cookie param keys and values. * * @return void */ public function setCookieParams(array $params) { $this->cookie_params = array_merge($this->cookie_params, $params); } /** * Gets the current session id. * * @return string */ public function getId(): string { return $this->sessionId; } /** * Regenerates and replaces the current session id; also regenerates the CSRF token value if one exists. * * @return bool True is regeneration worked, false if not. * */ public function regenerateId(): bool { $this->sessionId = HashHelper::md5(random_bytes(32)); if ($this->csrf_token) { $this->csrf_token->regenerateValue(); } return true; } /** * Sets the current session name. * * @param string $name The session name to use. * * @return string */ public function setName(string $name): string { $oldName = $this->sessionName; $this->sessionName = $name; return $oldName; } /** * Returns the current session name. * * @return string */ public function getName(): string { return $this->sessionName; } /** * Sets the session save path. Not supported by this implementation. * * * @param string $path * @param int $levels * * * @return string */ public function setSavePath(string $path, int $levels = 0): string { return $this->getSavePath(); } /** * Gets the session save path. Not supported by this implementation * * @return string * */ public function getSavePath(): string { return ''; } /** * Returns the current session status: * * - `PHP_SESSION_DISABLED` if sessions are disabled. * - `PHP_SESSION_NONE` if sessions are enabled, but none exists. * - `PHP_SESSION_ACTIVE` if sessions are enabled, and one exists. * * @return int * */ public function getStatus(): int { // CLI mode if (!defined('WPINC')) { return PHP_SESSION_ACTIVE; } $sid = $this->getId(); if (empty($sid)) { return PHP_SESSION_NONE; } return PHP_SESSION_ACTIVE; } /** * Clear the user meta which hold the session data * * @param $clearId bool Should I also clear the session ID (close the session)? * * @return void */ private function clearUserMeta($clearId = false) { $this->segments = []; $userId = get_current_user_id(); $allMeta = get_user_meta($userId); $sessionName = $this->getName(); $idKey = $sessionName . '_id'; foreach ($allMeta as $key => $value) { if (($key == $idKey) && !$clearId) { continue; } if (strpos($key, $sessionName . '_') === 0) { delete_user_meta($userId, $key); } } } }