File: /home/assibfaf/public_html/prox-classes/Cookie.php
<?php
/**
* @package Proxim
* @author Davison Pro <davisonpro.coder@gmail.com | https://davisonpro.dev>
* @copyright 2019 Proxim
* @version 1.0.0
* @since File available since Release 1.0.0
*/
namespace Proxim;
use Defuse\Crypto\Key;
/**
* Cookie
*
*/
class Cookie {
/** @var array Contain cookie content in a key => value format */
protected $_content;
/** @var array Crypted cookie name for setcookie() */
protected $_name;
/** @var array expiration date for setcookie() */
protected $_expire;
/** @var array Website domain for setcookie() */
protected $_domain;
/** @var array Path for setcookie() */
protected $_path;
/** @var array cipher tool instance */
protected $cipherTool;
protected $_modified = false;
protected $_allow_writing;
protected $_salt;
protected $_secure = false;
/**
* Get data if the cookie exists and else initialize an new one.
*
* @param $name string Cookie name before encrypting
* @param $path string
*/
public function __construct($name, $path = '', $expire = null, $shared_urls = null, $secure = false)
{
$this->_content = array();
$this->_expire = is_null($expire) ? time() + 1728000 : (int) $expire;
$this->_path = '/';
$this->_domain = $this->getDomain($shared_urls);
$this->_name = 'Proxim-' . md5( $name . $this->_domain);
// $this->_name = $name;
$this->_allow_writing = true;
$this->_salt = str_pad('', 8, md5('hp' . __FILE__));
$asciiSafeString = \Defuse\Crypto\Encoding::saveBytesToChecksummedAsciiSafeString(Key::KEY_CURRENT_VERSION, str_pad($name, Key::KEY_BYTE_SIZE, __FILE__));
$this->cipherTool = new PhpEncryption($asciiSafeString);
$this->_secure = (bool) $secure;
$this->update();
}
protected function getDomain($shared_urls = null)
{
$r = '!(?:(\w+)://)?(?:(\w+)\:(\w+)@)?([^/:]+)?(?:\:(\d*))?([^#?]+)?(?:\?([^#]+))?(?:#(.+$))?!i';
if (!preg_match($r, Tools::getHttpHost(false, false), $out) || !isset($out[4])) {
return false;
}
if (preg_match('/^(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]{1}[0-9]|[1-9]).)' .
'{1}((25[0-5]|2[0-4][0-9]|[1]{1}[0-9]{2}|[1-9]{1}[0-9]|[0-9]).)' .
'{2}((25[0-5]|2[0-4][0-9]|[1]{1}[0-9]{2}|[1-9]{1}[0-9]|[0-9]){1}))$/', $out[4])) {
return false;
}
if (!strstr(Tools::getHttpHost(false, false), '.')) {
return false;
}
$domain = false;
if ($shared_urls !== null) {
foreach ($shared_urls as $shared_url) {
if ($shared_url != $out[4]) {
continue;
}
if (preg_match('/^(?:.*\.)?([^.]*(?:.{2,4})?\..{2,3})$/Ui', $shared_url, $res)) {
$domain = '.' . $res[1];
break;
}
}
}
if (!$domain) {
$domain = $out[4];
}
return $domain;
}
/**
* Set expiration date.
*
* @param int $expire Expiration time from now
*/
public function setExpire($expire)
{
$this->_expire = (int) ($expire);
}
/**
* Magic method wich return cookie data from _content array.
*
* @param string $key key wanted
*
* @return string value corresponding to the key
*/
public function __get($key)
{
return isset($this->_content[$key]) ? $this->_content[$key] : false;
}
/**
* Magic method which check if key exists in the cookie.
*
* @param string $key key wanted
*
* @return bool key existence
*/
public function __isset($key)
{
return isset($this->_content[$key]);
}
/**
* Magic method which adds data into _content array.
*
* @param string $key Access key for the value
* @param mixed $value Value corresponding to the key
*
* @throws Exception
*/
public function __set($key, $value)
{
if (is_array($value)) {
die(Tools::displayError());
}
if (preg_match('/¤|\|/', $key . $value)) {
throw new Exception('Forbidden chars in cookie');
}
if (!$this->_modified && (!isset($this->_content[$key]) || (isset($this->_content[$key]) && $this->_content[$key] != $value))) {
$this->_modified = true;
}
$this->_content[$key] = $value;
}
/**
* Magic method wich delete data into _content array.
*
* @param string $key key wanted
*/
public function __unset($key)
{
if (isset($this->_content[$key])) {
$this->_modified = true;
}
unset($this->_content[$key]);
}
/**
* Delete cookie
*/
public function logout()
{
$this->_content = array();
$this->encryptAndSetCookie();
unset($_COOKIE[$this->_name]);
$this->_modified = true;
}
/**
* Soft logout, delete everything links to the user
*/
public function userLogout()
{
unset($this->_content['logged']);
unset($this->_content['email']);
unset($this->_content['user_id']);
$this->_modified = true;
}
/**
* Get cookie content.
*/
public function update($nullValues = false)
{
try {
if (isset($_COOKIE[$this->_name])) {
/* Decrypt cookie content */
$content = $this->cipherTool->decrypt($_COOKIE[$this->_name]);
//printf("\$content = %s<br />", $content);
/* Get cookie checksum */
$tmpTab = explode('¤', $content);
array_pop($tmpTab);
$content_for_checksum = implode('¤', $tmpTab) . '¤';
$checksum = crc32($this->_salt . $content_for_checksum);
//printf("\$checksum = %s<br />", $checksum);
/* Unserialize cookie content */
$tmpTab = explode('¤', $content);
foreach ($tmpTab as $keyAndValue) {
$tmpTab2 = explode('|', $keyAndValue);
if (count($tmpTab2) == 2) {
$this->_content[$tmpTab2[0]] = $tmpTab2[1];
}
}
/* Check if cookie has not been modified */
if (!isset($this->_content['checksum']) || $this->_content['checksum'] != $checksum) {
$this->logout();
}
if (!isset($this->_content['date_add'])) {
$this->_content['date_add'] = date('Y-m-d H:i:s');
}
} else {
$this->_content['date_add'] = date('Y-m-d H:i:s');
}
} catch (\Exception $e) {
// error decrypting
$this->logout();
}
}
/**
* Encrypt and set the Cookie.
*
* @param string|null $cookie Cookie content
*
* @return bool Indicates whether the Cookie was successfully set
*
* @deprecated 1.7.0
*/
protected function _setcookie($cookie = null)
{
return $this->encryptAndSetCookie($cookie);
}
/**
* Encrypt and set the Cookie.
*
* @param string|null $cookie Cookie content
*
* @return bool Indicates whether the Cookie was successfully set
*
* @since 1.7.0
*/
protected function encryptAndSetCookie($cookie = null)
{
// Check if the content fits in the Cookie
$length = (ini_get('mbstring.func_overload') & 2) ? mb_strlen($cookie, ini_get('default_charset')) : strlen($cookie);
if ($length >= 1048576) {
return false;
}
if ($cookie) {
$content = $this->cipherTool->encrypt($cookie);
$time = $this->_expire;
} else {
$content = 0;
$time = 1;
}
return setcookie($this->_name, $content, $time, $this->_path, $this->_domain, $this->_secure, true);
}
public function __destruct()
{
$this->write();
}
/**
* Save cookie with setcookie().
*/
public function write()
{
if (!$this->_modified || headers_sent() || !$this->_allow_writing) {
return;
}
$cookie = '';
/* Serialize cookie content */
if (isset($this->_content['checksum'])) {
unset($this->_content['checksum']);
}
foreach ($this->_content as $key => $value) {
$cookie .= $key . '|' . $value . '¤';
}
/* Add checksum to cookie */
$cookie .= 'checksum|' . crc32($this->_salt . $cookie);
$this->_modified = false;
/* Cookies are encrypted for evident security reasons */
return $this->encryptAndSetCookie($cookie);
}
/**
* Get a family of variables (e.g. "filter_").
*/
public function getFamily($origin)
{
$result = array();
if (count($this->_content) == 0) {
return $result;
}
foreach ($this->_content as $key => $value) {
if (strncmp($key, $origin, strlen($origin)) == 0) {
$result[$key] = $value;
}
}
return $result;
}
public function unsetFamily($origin)
{
$family = $this->getFamily($origin);
foreach (array_keys($family) as $member) {
unset($this->$member);
}
}
public function getAll()
{
return $this->_content;
}
/**
* @return string name of cookie
*/
public function getName()
{
return $this->_name;
}
/**
* Check if the cookie exists.
*
* @since 1.5.0
*
* @return bool
*/
public function exists()
{
return isset($_COOKIE[$this->_name]);
}
}