forked from qwerty/milfs
202 lines
5.1 KiB
PHP
202 lines
5.1 KiB
PHP
<?php
|
|
/**
|
|
* Slim Framework (https://slimframework.com)
|
|
*
|
|
* @link https://github.com/slimphp/Slim
|
|
* @copyright Copyright (c) 2011-2017 Josh Lockhart
|
|
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
|
|
*/
|
|
namespace Slim\Http;
|
|
|
|
use InvalidArgumentException;
|
|
use Slim\Interfaces\Http\CookiesInterface;
|
|
|
|
/**
|
|
* Cookie helper
|
|
*/
|
|
class Cookies implements CookiesInterface
|
|
{
|
|
/**
|
|
* Cookies from HTTP request
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $requestCookies = [];
|
|
|
|
/**
|
|
* Cookies for HTTP response
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $responseCookies = [];
|
|
|
|
/**
|
|
* Default cookie properties
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $defaults = [
|
|
'value' => '',
|
|
'domain' => null,
|
|
'hostonly' => null,
|
|
'path' => null,
|
|
'expires' => null,
|
|
'secure' => false,
|
|
'httponly' => false,
|
|
'samesite' => null
|
|
];
|
|
|
|
/**
|
|
* Create new cookies helper
|
|
*
|
|
* @param array $cookies
|
|
*/
|
|
public function __construct(array $cookies = [])
|
|
{
|
|
$this->requestCookies = $cookies;
|
|
}
|
|
|
|
/**
|
|
* Set default cookie properties
|
|
*
|
|
* @param array $settings
|
|
*/
|
|
public function setDefaults(array $settings)
|
|
{
|
|
$this->defaults = array_replace($this->defaults, $settings);
|
|
}
|
|
|
|
/**
|
|
* Get request cookie
|
|
*
|
|
* @param string $name Cookie name
|
|
* @param mixed $default Cookie default value
|
|
*
|
|
* @return mixed Cookie value if present, else default
|
|
*/
|
|
public function get($name, $default = null)
|
|
{
|
|
return isset($this->requestCookies[$name]) ? $this->requestCookies[$name] : $default;
|
|
}
|
|
|
|
/**
|
|
* Set response cookie
|
|
*
|
|
* @param string $name Cookie name
|
|
* @param string|array $value Cookie value, or cookie properties
|
|
*/
|
|
public function set($name, $value)
|
|
{
|
|
if (!is_array($value)) {
|
|
$value = ['value' => (string)$value];
|
|
}
|
|
$this->responseCookies[$name] = array_replace($this->defaults, $value);
|
|
}
|
|
|
|
/**
|
|
* Convert to `Set-Cookie` headers
|
|
*
|
|
* @return string[]
|
|
*/
|
|
public function toHeaders()
|
|
{
|
|
$headers = [];
|
|
foreach ($this->responseCookies as $name => $properties) {
|
|
$headers[] = $this->toHeader($name, $properties);
|
|
}
|
|
|
|
return $headers;
|
|
}
|
|
|
|
/**
|
|
* Convert to `Set-Cookie` header
|
|
*
|
|
* @param string $name Cookie name
|
|
* @param array $properties Cookie properties
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function toHeader($name, array $properties)
|
|
{
|
|
$result = urlencode($name) . '=' . urlencode($properties['value']);
|
|
|
|
if (isset($properties['domain'])) {
|
|
$result .= '; domain=' . $properties['domain'];
|
|
}
|
|
|
|
if (isset($properties['path'])) {
|
|
$result .= '; path=' . $properties['path'];
|
|
}
|
|
|
|
if (isset($properties['expires'])) {
|
|
if (is_string($properties['expires'])) {
|
|
$timestamp = strtotime($properties['expires']);
|
|
} else {
|
|
$timestamp = (int)$properties['expires'];
|
|
}
|
|
if ($timestamp !== 0) {
|
|
$result .= '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp);
|
|
}
|
|
}
|
|
|
|
if (isset($properties['secure']) && $properties['secure']) {
|
|
$result .= '; secure';
|
|
}
|
|
|
|
if (isset($properties['hostonly']) && $properties['hostonly']) {
|
|
$result .= '; HostOnly';
|
|
}
|
|
|
|
if (isset($properties['httponly']) && $properties['httponly']) {
|
|
$result .= '; HttpOnly';
|
|
}
|
|
|
|
if (isset($properties['samesite']) && in_array(strtolower($properties['samesite']), ['lax', 'strict'], true)) {
|
|
// While strtolower is needed for correct comparison, the RFC doesn't care about case
|
|
$result .= '; SameSite=' . $properties['samesite'];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Parse HTTP request `Cookie:` header and extract
|
|
* into a PHP associative array.
|
|
*
|
|
* @param string $header The raw HTTP request `Cookie:` header
|
|
*
|
|
* @return array Associative array of cookie names and values
|
|
*
|
|
* @throws InvalidArgumentException if the cookie data cannot be parsed
|
|
*/
|
|
public static function parseHeader($header)
|
|
{
|
|
if (is_array($header) === true) {
|
|
$header = isset($header[0]) ? $header[0] : '';
|
|
}
|
|
|
|
if (is_string($header) === false) {
|
|
throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.');
|
|
}
|
|
|
|
$header = rtrim($header, "\r\n");
|
|
$pieces = preg_split('@[;]\s*@', $header);
|
|
$cookies = [];
|
|
|
|
foreach ($pieces as $cookie) {
|
|
$cookie = explode('=', $cookie, 2);
|
|
|
|
if (count($cookie) === 2) {
|
|
$key = urldecode($cookie[0]);
|
|
$value = urldecode($cookie[1]);
|
|
|
|
if (!isset($cookies[$key])) {
|
|
$cookies[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $cookies;
|
|
}
|
|
}
|