| Server IP : 104.26.5.103 / Your IP : 216.73.217.51 Web Server : nginx/1.27.1 System : Linux in-5 5.15.0-191-generic #201-Ubuntu SMP Fri Aug 7 18:39:04 UTC 2026 x86_64 User : arabianexpress ( 1872) PHP Version : 8.0.30 Disable Function : exec,passthru,shell_exec,system,proc_open,popen,parse_ini_file,show_source MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /storage/v9321/leapdubai/public_html/wp-content/plugins/kirki/libraries/framework/Http/ |
Upload File : |
<?php
/**
* Immutable value object describing a single HTTP cookie and its attributes.
* Normalizes the same-site attribute and validates the name against header injection.
* Converts itself into a setcookie() options array or a Set-Cookie header string.
*
* @package Framework
* @subpackage Http
* @since 1.0.0
*/
namespace Kirki\Framework\Http;
\defined('ABSPATH') || exit;
use InvalidArgumentException;
class Cookie
{
/**
* The same site lax value.
*
* @var string
*
* @since 1.0.0
*/
public const SAME_SITE_LAX = 'Lax';
/**
* The same site strict value.
*
* @var string
*
* @since 1.0.0
*/
public const SAME_SITE_STRICT = 'Strict';
/**
* The same site none value.
*
* @var string
*
* @since 1.0.0
*/
public const SAME_SITE_NONE = 'None';
/**
* The characters that may never appear in a cookie name.
*
* @var string
*
* @since 1.0.0
*/
protected const RESERVED_CHARACTERS = "=,; \t\r\n\v\f";
/**
* The name of the cookie.
*
* @var string
*
* @since 1.0.0
*/
protected $name;
/**
* The value of the cookie.
*
* @var string
*
* @since 1.0.0
*/
protected $value;
/**
* The unix timestamp at which the cookie expires. Zero means a session cookie.
*
* @var int
*
* @since 1.0.0
*/
protected $expire;
/**
* The path the cookie is scoped to.
*
* @var string
*
* @since 1.0.0
*/
protected $path;
/**
* The domain the cookie is scoped to.
*
* @var string|null
*
* @since 1.0.0
*/
protected $domain;
/**
* Whether the cookie is restricted to secure connections.
*
* @var bool
*
* @since 1.0.0
*/
protected $secure;
/**
* Whether the cookie is hidden from client side scripts.
*
* @var bool
*
* @since 1.0.0
*/
protected $http_only;
/**
* Whether the value is sent without URL encoding.
*
* @var bool
*
* @since 1.0.0
*/
protected $raw;
/**
* The same site policy of the cookie.
*
* @var string|null
*
* @since 1.0.0
*/
protected $same_site;
/**
* Create a new cookie instance.
*
* @param string $name The name of the cookie.
* @param string $value The value of the cookie.
* @param int $expire The unix timestamp at which the cookie expires, zero for a session cookie.
* @param string|null $path The path the cookie is scoped to.
* @param string|null $domain The domain the cookie is scoped to.
* @param bool|null $secure Whether the cookie is restricted to secure connections.
* @param bool $http_only Whether the cookie is hidden from client side scripts.
* @param bool $raw Whether the value is sent without URL encoding.
* @param string|null $same_site The same site policy of the cookie.
*
* @return void
*
* @throws \InvalidArgumentException When the name or the same site policy is invalid.
*
* @since 1.0.0
*/
public function __construct(string $name, string $value = '', int $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = \false, bool $http_only = \true, bool $raw = \false, ?string $same_site = null)
{
$this->validate_name($name);
$this->name = $name;
$this->value = $value;
$this->expire = $expire;
$this->path = $path === null || $path === '' ? '/' : $path;
$this->domain = $domain;
$this->secure = (bool) $secure;
$this->http_only = $http_only;
$this->raw = $raw;
$this->same_site = $this->normalize_same_site($same_site);
if ($this->same_site === static::SAME_SITE_NONE) {
$this->secure = \true;
}
}
/**
* Get the name of the cookie.
*
* @return string
*
* @since 1.0.0
*/
public function get_name()
{
return $this->name;
}
/**
* Get the value of the cookie.
*
* @return string
*
* @since 1.0.0
*/
public function get_value()
{
return $this->value;
}
/**
* Get the unix timestamp at which the cookie expires.
*
* @return int
*
* @since 1.0.0
*/
public function get_expires_time()
{
return $this->expire;
}
/**
* Get the number of seconds until the cookie expires.
*
* @return int
*
* @since 1.0.0
*/
public function get_max_age()
{
$age = $this->expire - \time();
return \max(0, $age);
}
/**
* Get the path the cookie is scoped to.
*
* @return string
*
* @since 1.0.0
*/
public function get_path()
{
return $this->path;
}
/**
* Get the domain the cookie is scoped to.
*
* @return string|null
*
* @since 1.0.0
*/
public function get_domain()
{
return $this->domain;
}
/**
* Get the same site policy of the cookie.
*
* @return string|null
*
* @since 1.0.0
*/
public function get_same_site()
{
return $this->same_site;
}
/**
* Determine whether the cookie is restricted to secure connections.
*
* @return bool
*
* @since 1.0.0
*/
public function is_secure()
{
return $this->secure;
}
/**
* Determine whether the cookie is hidden from client side scripts.
*
* @return bool
*
* @since 1.0.0
*/
public function is_http_only()
{
return $this->http_only;
}
/**
* Determine whether the value is sent without URL encoding.
*
* @return bool
*
* @since 1.0.0
*/
public function is_raw()
{
return $this->raw;
}
/**
* Determine whether the cookie is a session cookie.
*
* @return bool
*
* @since 1.0.0
*/
public function is_session()
{
return $this->expire === 0;
}
/**
* Determine whether the cookie has already expired.
*
* @return bool
*
* @since 1.0.0
*/
public function is_expired()
{
return !$this->is_session() && $this->expire < \time();
}
/**
* Get the cookie as an options array for the setcookie function.
*
* @return array
*
* @since 1.0.0
*/
public function to_options()
{
$options = ['expires' => $this->expire, 'path' => $this->path, 'domain' => $this->domain ?? '', 'secure' => $this->secure, 'httponly' => $this->http_only];
if ($this->same_site !== null) {
$options['samesite'] = $this->same_site;
}
return $options;
}
/**
* Get the cookie as a Set-Cookie header string.
*
* @return string
*
* @since 1.0.0
*/
public function to_header_string()
{
$value = $this->raw ? $this->value : \rawurlencode($this->value);
$header = $this->name . '=' . $value;
if ($this->expire !== 0) {
$header .= '; expires=' . \gmdate('D, d-M-Y H:i:s T', $this->expire);
$header .= '; Max-Age=' . $this->get_max_age();
}
$header .= '; path=' . $this->path;
if (!empty($this->domain)) {
$header .= '; domain=' . $this->domain;
}
if ($this->secure) {
$header .= '; secure';
}
if ($this->http_only) {
$header .= '; HttpOnly';
}
if ($this->same_site !== null) {
$header .= '; SameSite=' . $this->same_site;
}
return $header;
}
/**
* Get the string representation of the cookie.
*
* @return string
*
* @since 1.0.0
*/
public function __toString()
{
return $this->to_header_string();
}
/**
* Normalize the same site policy to a supported value.
*
* @param string|null $same_site The same site policy to normalize.
*
* @return string|null
*
* @throws \InvalidArgumentException When the policy is not supported.
*
* @since 1.0.0
*/
protected function normalize_same_site($same_site)
{
if ($same_site === null || $same_site === '') {
return null;
}
$supported = ['lax' => static::SAME_SITE_LAX, 'strict' => static::SAME_SITE_STRICT, 'none' => static::SAME_SITE_NONE];
$normalized = \strtolower((string) $same_site);
if (!isset($supported[$normalized])) {
throw new InvalidArgumentException(\sprintf('The same site attribute "%s" is invalid.', $same_site));
}
return $supported[$normalized];
}
/**
* Validate the cookie name against empty and reserved characters.
*
* @param string $name The name to validate.
*
* @return void
*
* @throws \InvalidArgumentException When the name is empty or contains reserved characters.
*
* @since 1.0.0
*/
protected function validate_name(string $name)
{
if ($name === '') {
throw new InvalidArgumentException('The cookie name cannot be empty.');
}
if (\strpbrk($name, static::RESERVED_CHARACTERS) !== \false) {
throw new InvalidArgumentException(\sprintf('The cookie name "%s" contains invalid characters.', $name));
}
}
}