You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.6 KiB
134 lines
3.6 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* @author Robert Strutts <Robert@TryingToScale.com>
|
|
* @copyright Copyright (c) 2022, Robert Strutts.
|
|
* @license https://mit-license.org/
|
|
*/
|
|
|
|
namespace tts\services\sessions;
|
|
|
|
class redis_sessions implements \SessionHandlerInterface {
|
|
public static int $zlib_compression_level = 4;
|
|
public static bool $use_compression = true;
|
|
public $ttl = 1800; // 30 minutes default
|
|
protected $db;
|
|
protected $prefix;
|
|
private $enc;
|
|
|
|
public function __construct($enc, array $options) {
|
|
$exists = \main_tts\registry::get('di')->exists('session_redis_servers');
|
|
if ($exists) {
|
|
$db = \main_tts\registry::get('di')->get_service('session_redis_servers');
|
|
}
|
|
if (! is_object($db)) {
|
|
throw new \Exception("Session service type not set");
|
|
}
|
|
$this->db = $options['db'] ?? $db;
|
|
if (isset($options['prefix'])) {
|
|
$prefix = $options['prefix'];
|
|
} else {
|
|
$prefix = 'SESS:';
|
|
}
|
|
|
|
$this->prefix = $prefix;
|
|
$this->enc = $enc;
|
|
if (isset($options['compression_level'])) {
|
|
self::$zlib_compression_level = $options['compression_level'];
|
|
}
|
|
if (isset($options['use_compression'])) {
|
|
self::$use_compression = $options['use_compression'];
|
|
}
|
|
|
|
}
|
|
|
|
private function encrypt(string & $data): void {
|
|
if ($this->enc === false) {
|
|
return;
|
|
}
|
|
$data = $this->enc->encrypt($data);
|
|
}
|
|
|
|
private function decrypt(string & $data): void {
|
|
if ($this->enc === false) {
|
|
return;
|
|
}
|
|
try {
|
|
$data = $this->enc->decrypt($data);
|
|
} catch (\Exception $e) {
|
|
$data = false; // Maybe it has no data to decode
|
|
}
|
|
}
|
|
|
|
private function compress(string & $data): void {
|
|
if (self::$use_compression === false) {
|
|
return;
|
|
}
|
|
$data = gzdeflate($data, self::$zlib_compression_level);
|
|
if ($data === false) {
|
|
throw new \Exception('Failed to compress session data');
|
|
}
|
|
}
|
|
|
|
private function decompress(string & $data): void {
|
|
if (self::$use_compression === false) {
|
|
return;
|
|
}
|
|
$ret = gzinflate($data);
|
|
if ($ret !== false) {
|
|
$data = $ret;
|
|
}
|
|
}
|
|
|
|
public function open($save_path, $session_name): bool{
|
|
// No action necessary because connection is injected
|
|
// in constructor and arguments are not applicable.
|
|
}
|
|
|
|
public function close(): bool {
|
|
$this->db = null;
|
|
unset($this->db);
|
|
}
|
|
|
|
public function read($id): false|string {
|
|
$id = $this->prefix . $id;
|
|
$data = $this->db->get($id);
|
|
$this->db->expire($id, $this->ttl);
|
|
|
|
if ($data === null) {
|
|
return "";
|
|
}
|
|
|
|
$data = base64_decode($data);
|
|
if ($data === false) {
|
|
return "";
|
|
}
|
|
|
|
$this->decrypt($data);
|
|
if ($data === false) {
|
|
return "";
|
|
}
|
|
|
|
$this->decompress($data);
|
|
return ($data !== false) ? $data : '';
|
|
}
|
|
|
|
public function write($id, $data): bool {
|
|
$this->compress($data);
|
|
$this->encrypt($data);
|
|
$data = base64_encode($data);
|
|
|
|
$id = $this->prefix . $id;
|
|
$this->db->set($id, $data);
|
|
$this->db->expire($id, $this->ttl);
|
|
}
|
|
|
|
public function destroy($id): bool {
|
|
$this->db->del($this->prefix . $id);
|
|
}
|
|
public function gc($max_lifetime): int|false {
|
|
// no action necessary because using EXPIRE
|
|
}
|
|
} |