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.
IOcornerstone/src/Framework/Services/Sessions/CookieSessionHandler.php

141 lines
4.5 KiB

<?php
declare(strict_types=1);
namespace IOcornerstone\Framework\Services;
use IOcornerstone\Framework\GzCompression;
use IOcornerstone\Framework\Enum\CompressionMethod as Method;
/**
* @author Robert Strutts
* @copyright Copyright (c) 2022, Robert Strutts.
* @license MIT
*/
class CookieSessionsHandlerException extends \Exception {}
class CookieSessionHandler implements \SessionHandlerInterface {
public static string $cookieDomain;
public static string $cookieName = 'SES';
public static string $cookiePath = '/';
public static bool $cookieSecure = true;
public static bool $cookieHTTPOnly = true;
private $enc;
public function __construct($enc, array $options) {
if (isset($options['cookie_domain'])) {
self::$cookieDomain = $options['cookie_domain'];
} else {
self::$cookieDomain = $_SERVER['SERVER_NAME'] ?? '';
}
if (isset($options['cookie_name'])) {
self::$cookieName = $options['cookie_name'];
}
if (isset($options['cookie_path'])) {
self::$cookiePath = $options['cookie_path'];
}
if (isset($options['cookie_secure'])) {
self::$cookieSecure = $options['cookie_secure'];
} else {
/**
* @todo Fix this...use_secure
*/
$use_secure = true;
if ($use_secure === false) {
self::$cookieSecure = false;
}
}
if (isset($options['cookie_HTTP_only'])) {
self::$cookieHTTPOnly = $options['cookie_HTTP_only'];
}
if (isset($options['use_compression'])) {
self::$use_compression = $options['use_compression'];
}
if (isset($options['method'])) {
$method = $options['method'];
} else {
$method = Method::DEFLATE;
}
if (isset($options['level'])) {
$level = $options['level'];
} else {
$level = 4;
}
if (isset($options['enabled'])) {
$enabled = $options['enabled'];
} else {
$enabled = true;
}
$this->compression = new GzCompression($method, $level, $enabled);
$this->enc = $enc;
}
private function writeHelper($data): string {
$gc = $this->compression->compress($data);
if ($gc !== false) {
$data = $gc; // data is now compressed
}
if ($this->enc === false) {
return $data; // encryption is off
}
$e = $this->enc->encrypt($data);
return ($e !== false) ? $e : $data; // and encrypted
}
private function readHelper($data): string {
if ($data === null || $data === false) {
return "";
}
if ($this->enc !== false) {
$de = $this->enc->decrypt($data);
if ($de!== false) {
$data = $de; // data is now decrypted
}
}
$gd = $this->compression->decompress($data);
return ($gd !== false) ? $gd : $data;
}
public function open($save_path, $session_name):bool {
return true;
}
public function close(): bool {
return true;
}
public function read($id): false|string {
$data = isset($_COOKIE[self::$cookieName]) ? $_COOKIE[self::$cookieName] : null;
return $this->readHelper($data) ?: "";
}
public function write($id, $data): bool {
if (headers_sent($file, $line)) {
throw new CookieSessionsHandlerException("Error headers were already sent by $file on line # $line ");
}
$data = $this->writeHelper($data);
/*
* Google Chrome - 4096 bytes confirming to RFC.
* If the data is over 4000 bytes, throw an exception
* as web browsers only support up to 4K of Cookie Data!
*/
if (strlen($data) > 4000) {
throw new cookie_sessions_handler_exception("Session data too big (over 4KB)");
}
$cookie_lifetime = (int) ini_get('session.cookie_lifetime');
return setcookie(self::$cookieName, $data, $cookie_lifetime, self::$cookiePath, self::$cookieDomain, self::$cookieSecure, self::$cookieHTTPOnly);
}
public function destroy($id): bool {
$expiration_time = time() - 3600;
return setcookie(self::$cookieName, "", $expiration_time, self::$cookiePath, self::$cookieDomain, self::$cookieSecure, self::$cookieHTTPOnly);
}
public function gc($max_lifetime): int|false {
return 0;
}
}