composer update
This commit is contained in:
@@ -49,7 +49,7 @@ class AcceptHeaderItem
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns header value's string representation.
|
||||
* Returns header value's string representation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@@ -40,7 +40,7 @@ class BinaryFileResponse extends Response
|
||||
* @param int $status The response status code
|
||||
* @param array $headers An array of response headers
|
||||
* @param bool $public Files are public by default
|
||||
* @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename
|
||||
* @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename
|
||||
* @param bool $autoEtag Whether the ETag header should be automatically set
|
||||
* @param bool $autoLastModified Whether the Last-Modified header should be automatically set
|
||||
*/
|
||||
@@ -60,7 +60,7 @@ class BinaryFileResponse extends Response
|
||||
* @param int $status The response status code
|
||||
* @param array $headers An array of response headers
|
||||
* @param bool $public Files are public by default
|
||||
* @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename
|
||||
* @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename
|
||||
* @param bool $autoEtag Whether the ETag header should be automatically set
|
||||
* @param bool $autoLastModified Whether the Last-Modified header should be automatically set
|
||||
*
|
||||
@@ -219,8 +219,8 @@ class BinaryFileResponse extends Response
|
||||
// Do X-Accel-Mapping substitutions.
|
||||
// @link http://wiki.nginx.org/X-accel#X-Accel-Redirect
|
||||
$parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',=');
|
||||
$mappings = HeaderUtils::combine($parts);
|
||||
foreach ($mappings as $pathPrefix => $location) {
|
||||
foreach ($parts as $part) {
|
||||
list($pathPrefix, $location) = $part;
|
||||
if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) {
|
||||
$path = $location.substr($path, \strlen($pathPrefix));
|
||||
break;
|
||||
|
8
vendor/symfony/http-foundation/CHANGELOG.md
vendored
8
vendor/symfony/http-foundation/CHANGELOG.md
vendored
@@ -1,6 +1,14 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* the default value of the "$secure" and "$samesite" arguments of Cookie's constructor
|
||||
will respectively change from "false" to "null" and from "null" to "lax" in Symfony
|
||||
5.0, you should define their values explicitly or use "Cookie::create()" instead.
|
||||
* added `matchPort()` in RequestMatcher
|
||||
|
||||
4.1.3
|
||||
-----
|
||||
|
||||
|
28
vendor/symfony/http-foundation/Cookie.php
vendored
28
vendor/symfony/http-foundation/Cookie.php
vendored
@@ -27,6 +27,7 @@ class Cookie
|
||||
protected $httpOnly;
|
||||
private $raw;
|
||||
private $sameSite;
|
||||
private $secureDefault = false;
|
||||
|
||||
const SAMESITE_LAX = 'lax';
|
||||
const SAMESITE_STRICT = 'strict';
|
||||
@@ -66,21 +67,30 @@ class Cookie
|
||||
return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']);
|
||||
}
|
||||
|
||||
public static function create(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self
|
||||
{
|
||||
return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name The name of the cookie
|
||||
* @param string|null $value The value of the cookie
|
||||
* @param int|string|\DateTimeInterface $expire The time the cookie expires
|
||||
* @param string $path The path on the server in which the cookie will be available on
|
||||
* @param string|null $domain The domain that the cookie is available to
|
||||
* @param bool $secure Whether the cookie should only be transmitted over a secure HTTPS connection from the client
|
||||
* @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS
|
||||
* @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol
|
||||
* @param bool $raw Whether the cookie value should be sent with no url encoding
|
||||
* @param string|null $sameSite Whether the cookie will be available for cross-site requests
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true, bool $raw = false, string $sameSite = null)
|
||||
public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, ?bool $secure = false, bool $httpOnly = true, bool $raw = false, string $sameSite = null)
|
||||
{
|
||||
if (9 > \func_num_args()) {
|
||||
@trigger_error(sprintf('The default value of the "$secure" and "$samesite" arguments of "%s"\'s constructor will respectively change from "false" to "null" and from "null" to "lax" in Symfony 5.0, you should define their values explicitly or use "Cookie::create()" instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
// from PHP source code
|
||||
if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
|
||||
throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
|
||||
@@ -110,7 +120,9 @@ class Cookie
|
||||
$this->httpOnly = $httpOnly;
|
||||
$this->raw = $raw;
|
||||
|
||||
if (null !== $sameSite) {
|
||||
if ('' === $sameSite) {
|
||||
$sameSite = null;
|
||||
} elseif (null !== $sameSite) {
|
||||
$sameSite = strtolower($sameSite);
|
||||
}
|
||||
|
||||
@@ -232,7 +244,7 @@ class Cookie
|
||||
*/
|
||||
public function isSecure()
|
||||
{
|
||||
return $this->secure;
|
||||
return $this->secure ?? $this->secureDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,4 +286,12 @@ class Cookie
|
||||
{
|
||||
return $this->sameSite;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $default The default value of the "secure" flag when it is set to null
|
||||
*/
|
||||
public function setSecureDefault(bool $default): void
|
||||
{
|
||||
$this->secureDefault = $default;
|
||||
}
|
||||
}
|
||||
|
2
vendor/symfony/http-foundation/HeaderBag.php
vendored
2
vendor/symfony/http-foundation/HeaderBag.php
vendored
@@ -206,7 +206,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* @param string $key The parameter key
|
||||
* @param \DateTime $default The default value
|
||||
*
|
||||
* @return null|\DateTime The parsed DateTime or the default value if the header does not exist
|
||||
* @return \DateTime|null The parsed DateTime or the default value if the header does not exist
|
||||
*
|
||||
* @throws \RuntimeException When the HTTP header is not parseable
|
||||
*/
|
||||
|
51
vendor/symfony/http-foundation/HeaderUtils.php
vendored
51
vendor/symfony/http-foundation/HeaderUtils.php
vendored
@@ -18,6 +18,9 @@ namespace Symfony\Component\HttpFoundation;
|
||||
*/
|
||||
class HeaderUtils
|
||||
{
|
||||
public const DISPOSITION_ATTACHMENT = 'attachment';
|
||||
public const DISPOSITION_INLINE = 'inline';
|
||||
|
||||
/**
|
||||
* This class should not be instantiated.
|
||||
*/
|
||||
@@ -143,6 +146,54 @@ class HeaderUtils
|
||||
return preg_replace('/\\\\(.)|"/', '$1', $s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a HTTP Content-Disposition field-value.
|
||||
*
|
||||
* @param string $disposition One of "inline" or "attachment"
|
||||
* @param string $filename A unicode string
|
||||
* @param string $filenameFallback A string containing only ASCII characters that
|
||||
* is semantically equivalent to $filename. If the filename is already ASCII,
|
||||
* it can be omitted, or just copied from $filename
|
||||
*
|
||||
* @return string A string suitable for use as a Content-Disposition field-value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @see RFC 6266
|
||||
*/
|
||||
public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string
|
||||
{
|
||||
if (!\in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) {
|
||||
throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
|
||||
}
|
||||
|
||||
if ('' === $filenameFallback) {
|
||||
$filenameFallback = $filename;
|
||||
}
|
||||
|
||||
// filenameFallback is not ASCII.
|
||||
if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
|
||||
throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
|
||||
}
|
||||
|
||||
// percent characters aren't safe in fallback.
|
||||
if (false !== strpos($filenameFallback, '%')) {
|
||||
throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
|
||||
}
|
||||
|
||||
// path separators aren't allowed in either.
|
||||
if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) {
|
||||
throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
|
||||
}
|
||||
|
||||
$params = array('filename' => $filenameFallback);
|
||||
if ($filename !== $filenameFallback) {
|
||||
$params['filename*'] = "utf-8''".rawurlencode($filename);
|
||||
}
|
||||
|
||||
return $disposition.'; '.self::toString($params, ';');
|
||||
}
|
||||
|
||||
private static function groupParts(array $matches, string $separators): array
|
||||
{
|
||||
$separator = $separators[0];
|
||||
|
@@ -174,7 +174,7 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* Returns the parameter value converted to boolean.
|
||||
*
|
||||
* @param string $key The parameter key
|
||||
* @param mixed $default The default value if the parameter key does not exist
|
||||
* @param bool $default The default value if the parameter key does not exist
|
||||
*
|
||||
* @return bool The filtered value
|
||||
*/
|
||||
|
29
vendor/symfony/http-foundation/Request.php
vendored
29
vendor/symfony/http-foundation/Request.php
vendored
@@ -344,7 +344,7 @@ class Request
|
||||
|
||||
if (isset($components['port'])) {
|
||||
$server['SERVER_PORT'] = $components['port'];
|
||||
$server['HTTP_HOST'] = $server['HTTP_HOST'].':'.$components['port'];
|
||||
$server['HTTP_HOST'] .= ':'.$components['port'];
|
||||
}
|
||||
|
||||
if (isset($components['user'])) {
|
||||
@@ -545,10 +545,13 @@ class Request
|
||||
$requestOrder = ini_get('request_order') ?: ini_get('variables_order');
|
||||
$requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp';
|
||||
|
||||
$_REQUEST = array();
|
||||
$_REQUEST = array(array());
|
||||
|
||||
foreach (str_split($requestOrder) as $order) {
|
||||
$_REQUEST = array_merge($_REQUEST, $request[$order]);
|
||||
$_REQUEST[] = $request[$order];
|
||||
}
|
||||
|
||||
$_REQUEST = array_merge(...$_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1059,7 +1062,7 @@ class Request
|
||||
}
|
||||
|
||||
$sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath);
|
||||
$targetDirs = explode('/', isset($path[0]) && '/' === $path[0] ? substr($path, 1) : $path);
|
||||
$targetDirs = explode('/', substr($path, 1));
|
||||
array_pop($sourceDirs);
|
||||
$targetFile = array_pop($targetDirs);
|
||||
|
||||
@@ -1284,7 +1287,7 @@ class Request
|
||||
{
|
||||
$canonicalMimeType = null;
|
||||
if (false !== $pos = strpos($mimeType, ';')) {
|
||||
$canonicalMimeType = substr($mimeType, 0, $pos);
|
||||
$canonicalMimeType = trim(substr($mimeType, 0, $pos));
|
||||
}
|
||||
|
||||
if (null === static::$formats) {
|
||||
@@ -1325,7 +1328,7 @@ class Request
|
||||
* * _format request attribute
|
||||
* * $default
|
||||
*
|
||||
* @param string $default The default format
|
||||
* @param string|null $default The default format
|
||||
*
|
||||
* @return string The request format
|
||||
*/
|
||||
@@ -1448,7 +1451,7 @@ class Request
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-4.2.3
|
||||
*
|
||||
* @return bool
|
||||
* @return bool True for GET and HEAD, false otherwise
|
||||
*/
|
||||
public function isMethodCacheable()
|
||||
{
|
||||
@@ -1695,10 +1698,16 @@ class Request
|
||||
$this->server->remove('IIS_WasUrlRewritten');
|
||||
} elseif ($this->server->has('REQUEST_URI')) {
|
||||
$requestUri = $this->server->get('REQUEST_URI');
|
||||
|
||||
// HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path
|
||||
$schemeAndHttpHost = $this->getSchemeAndHttpHost();
|
||||
if (0 === strpos($requestUri, $schemeAndHttpHost)) {
|
||||
$requestUri = substr($requestUri, \strlen($schemeAndHttpHost));
|
||||
$uriComponents = parse_url($requestUri);
|
||||
|
||||
if (isset($uriComponents['path'])) {
|
||||
$requestUri = $uriComponents['path'];
|
||||
}
|
||||
|
||||
if (isset($uriComponents['query'])) {
|
||||
$requestUri .= '?'.$uriComponents['query'];
|
||||
}
|
||||
} elseif ($this->server->has('ORIG_PATH_INFO')) {
|
||||
// IIS 5.0, PHP as CGI
|
||||
|
@@ -28,6 +28,11 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $port;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
@@ -56,13 +61,14 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
* @param array $attributes
|
||||
* @param string|string[]|null $schemes
|
||||
*/
|
||||
public function __construct(string $path = null, string $host = null, $methods = null, $ips = null, array $attributes = array(), $schemes = null)
|
||||
public function __construct(string $path = null, string $host = null, $methods = null, $ips = null, array $attributes = array(), $schemes = null, int $port = null)
|
||||
{
|
||||
$this->matchPath($path);
|
||||
$this->matchHost($host);
|
||||
$this->matchMethod($methods);
|
||||
$this->matchIps($ips);
|
||||
$this->matchScheme($schemes);
|
||||
$this->matchPort($port);
|
||||
|
||||
foreach ($attributes as $k => $v) {
|
||||
$this->matchAttribute($k, $v);
|
||||
@@ -89,6 +95,16 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
$this->host = $regexp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a check for the the URL port.
|
||||
*
|
||||
* @param int|null $port The port number to connect to
|
||||
*/
|
||||
public function matchPort(int $port = null)
|
||||
{
|
||||
$this->port = $port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a check for the URL path info.
|
||||
*
|
||||
@@ -167,6 +183,10 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $this->port && 0 < $this->port && $request->getPort() !== $this->port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IpUtils::checkIp($request->getClientIp(), $this->ips)) {
|
||||
return true;
|
||||
}
|
||||
|
11
vendor/symfony/http-foundation/Response.php
vendored
11
vendor/symfony/http-foundation/Response.php
vendored
@@ -313,6 +313,12 @@ class Response
|
||||
|
||||
$this->ensureIEOverSSLCompatibility($request);
|
||||
|
||||
if ($request->isSecure()) {
|
||||
foreach ($headers->getCookies() as $cookie) {
|
||||
$cookie->setSecureDefault(true);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -330,8 +336,9 @@ class Response
|
||||
|
||||
// headers
|
||||
foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) {
|
||||
$replace = 0 === strcasecmp($name, 'Content-Type');
|
||||
foreach ($values as $value) {
|
||||
header($name.': '.$value, false, $this->statusCode);
|
||||
header($name.': '.$value, $replace, $this->statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -933,7 +940,7 @@ class Response
|
||||
public function setCache(array $options)
|
||||
{
|
||||
if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public', 'immutable'))) {
|
||||
throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff))));
|
||||
throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', $diff)));
|
||||
}
|
||||
|
||||
if (isset($options['etag'])) {
|
||||
|
@@ -247,55 +247,15 @@ class ResponseHeaderBag extends HeaderBag
|
||||
*/
|
||||
public function clearCookie($name, $path = '/', $domain = null, $secure = false, $httpOnly = true)
|
||||
{
|
||||
$this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly));
|
||||
$this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a HTTP Content-Disposition field-value.
|
||||
*
|
||||
* @param string $disposition One of "inline" or "attachment"
|
||||
* @param string $filename A unicode string
|
||||
* @param string $filenameFallback A string containing only ASCII characters that
|
||||
* is semantically equivalent to $filename. If the filename is already ASCII,
|
||||
* it can be omitted, or just copied from $filename
|
||||
*
|
||||
* @return string A string suitable for use as a Content-Disposition field-value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @see RFC 6266
|
||||
* @see HeaderUtils::makeDisposition()
|
||||
*/
|
||||
public function makeDisposition($disposition, $filename, $filenameFallback = '')
|
||||
{
|
||||
if (!\in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) {
|
||||
throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
|
||||
}
|
||||
|
||||
if ('' == $filenameFallback) {
|
||||
$filenameFallback = $filename;
|
||||
}
|
||||
|
||||
// filenameFallback is not ASCII.
|
||||
if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
|
||||
throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
|
||||
}
|
||||
|
||||
// percent characters aren't safe in fallback.
|
||||
if (false !== strpos($filenameFallback, '%')) {
|
||||
throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
|
||||
}
|
||||
|
||||
// path separators aren't allowed in either.
|
||||
if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) {
|
||||
throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
|
||||
}
|
||||
|
||||
$params = array('filename' => $filenameFallback);
|
||||
if ($filename !== $filenameFallback) {
|
||||
$params['filename*'] = "utf-8''".rawurlencode($filename);
|
||||
}
|
||||
|
||||
return $disposition.'; '.HeaderUtils::toString($params, ';');
|
||||
return HeaderUtils::makeDisposition((string) $disposition, (string) $filename, (string) $filenameFallback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -209,7 +209,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->storage->setId($id);
|
||||
if ($this->storage->getId() !== $id) {
|
||||
$this->storage->setId($id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
59
vendor/symfony/http-foundation/Session/SessionUtils.php
vendored
Normal file
59
vendor/symfony/http-foundation/Session/SessionUtils.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpFoundation\Session;
|
||||
|
||||
/**
|
||||
* Session utility functions.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
* @author Rémon van de Kamp <rpkamp@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class SessionUtils
|
||||
{
|
||||
/**
|
||||
* Finds the session header amongst the headers that are to be sent, removes it, and returns
|
||||
* it so the caller can process it further.
|
||||
*/
|
||||
public static function popSessionCookie(string $sessionName, string $sessionId): ?string
|
||||
{
|
||||
$sessionCookie = null;
|
||||
$sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName));
|
||||
$sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId));
|
||||
$otherCookies = array();
|
||||
foreach (headers_list() as $h) {
|
||||
if (0 !== stripos($h, 'Set-Cookie:')) {
|
||||
continue;
|
||||
}
|
||||
if (11 === strpos($h, $sessionCookiePrefix, 11)) {
|
||||
$sessionCookie = $h;
|
||||
|
||||
if (11 !== strpos($h, $sessionCookieWithId, 11)) {
|
||||
$otherCookies[] = $h;
|
||||
}
|
||||
} else {
|
||||
$otherCookies[] = $h;
|
||||
}
|
||||
}
|
||||
if (null === $sessionCookie) {
|
||||
return null;
|
||||
}
|
||||
|
||||
header_remove('Set-Cookie');
|
||||
foreach ($otherCookies as $h) {
|
||||
header($h, false);
|
||||
}
|
||||
|
||||
return $sessionCookie;
|
||||
}
|
||||
}
|
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\SessionUtils;
|
||||
|
||||
/**
|
||||
* This abstract session handler provides a generic implementation
|
||||
* of the PHP 7.0 SessionUpdateTimestampHandlerInterface,
|
||||
@@ -117,36 +119,20 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess
|
||||
*/
|
||||
public function destroy($sessionId)
|
||||
{
|
||||
if (!headers_sent() && ini_get('session.use_cookies')) {
|
||||
if (!headers_sent() && filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN)) {
|
||||
if (!$this->sessionName) {
|
||||
throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', \get_class($this)));
|
||||
}
|
||||
$sessionCookie = sprintf(' %s=', urlencode($this->sessionName));
|
||||
$sessionCookieWithId = sprintf('%s%s;', $sessionCookie, urlencode($sessionId));
|
||||
$sessionCookieFound = false;
|
||||
$otherCookies = array();
|
||||
foreach (headers_list() as $h) {
|
||||
if (0 !== stripos($h, 'Set-Cookie:')) {
|
||||
continue;
|
||||
}
|
||||
if (11 === strpos($h, $sessionCookie, 11)) {
|
||||
$sessionCookieFound = true;
|
||||
|
||||
if (11 !== strpos($h, $sessionCookieWithId, 11)) {
|
||||
$otherCookies[] = $h;
|
||||
}
|
||||
$cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId);
|
||||
if (null === $cookie) {
|
||||
if (\PHP_VERSION_ID < 70300) {
|
||||
setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), FILTER_VALIDATE_BOOLEAN));
|
||||
} else {
|
||||
$otherCookies[] = $h;
|
||||
$params = session_get_cookie_params();
|
||||
unset($params['lifetime']);
|
||||
setcookie($this->sessionName, '', $params);
|
||||
}
|
||||
}
|
||||
if ($sessionCookieFound) {
|
||||
header_remove('Set-Cookie');
|
||||
foreach ($otherCookies as $h) {
|
||||
header($h, false);
|
||||
}
|
||||
} else {
|
||||
setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure'), ini_get('session.cookie_httponly'));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->newSessionId === $sessionId || $this->doDestroy($sessionId);
|
||||
|
@@ -50,9 +50,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler
|
||||
$this->memcached = $memcached;
|
||||
|
||||
if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'The following options are not supported "%s"', implode(', ', $diff)
|
||||
));
|
||||
throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff)));
|
||||
}
|
||||
|
||||
$this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400;
|
||||
|
@@ -71,7 +71,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
||||
private $pdo;
|
||||
|
||||
/**
|
||||
* @var string|null|false DSN string or null for session.save_path or false when lazy connection disabled
|
||||
* @var string|false|null DSN string or null for session.save_path or false when lazy connection disabled
|
||||
*/
|
||||
private $dsn = false;
|
||||
|
||||
@@ -637,7 +637,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
||||
throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.');
|
||||
}
|
||||
|
||||
if (!ini_get('session.use_strict_mode') && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
|
||||
if (!filter_var(ini_get('session.use_strict_mode'), FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
|
||||
// In strict mode, session fixation is not possible: new sessions always start with a unique
|
||||
// random id, so that concurrency is not possible and this code path can be skipped.
|
||||
// Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
||||
|
||||
use Predis\Response\ErrorInterface;
|
||||
use Symfony\Component\Cache\Traits\RedisClusterProxy;
|
||||
use Symfony\Component\Cache\Traits\RedisProxy;
|
||||
|
||||
/**
|
||||
@@ -45,7 +46,8 @@ class RedisSessionHandler extends AbstractSessionHandler
|
||||
!$redis instanceof \RedisArray &&
|
||||
!$redis instanceof \RedisCluster &&
|
||||
!$redis instanceof \Predis\Client &&
|
||||
!$redis instanceof RedisProxy
|
||||
!$redis instanceof RedisProxy &&
|
||||
!$redis instanceof RedisClusterProxy
|
||||
) {
|
||||
throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, %s given', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis)));
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\HttpFoundation\Session\Storage;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionUtils;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
|
||||
@@ -48,6 +49,11 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
*/
|
||||
protected $metadataBag;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $emulateSameSite;
|
||||
|
||||
/**
|
||||
* Depending on how you want the storage driver to behave you probably
|
||||
* want to override this constructor entirely.
|
||||
@@ -67,6 +73,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
* cookie_lifetime, "0"
|
||||
* cookie_path, "/"
|
||||
* cookie_secure, ""
|
||||
* cookie_samesite, null
|
||||
* gc_divisor, "100"
|
||||
* gc_maxlifetime, "1440"
|
||||
* gc_probability, "1"
|
||||
@@ -134,7 +141,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
throw new \RuntimeException('Failed to start the session: already started by PHP.');
|
||||
}
|
||||
|
||||
if (ini_get('session.use_cookies') && headers_sent($file, $line)) {
|
||||
if (filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) {
|
||||
throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
|
||||
}
|
||||
|
||||
@@ -143,6 +150,13 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
throw new \RuntimeException('Failed to start the session');
|
||||
}
|
||||
|
||||
if (null !== $this->emulateSameSite) {
|
||||
$originalCookie = SessionUtils::popSessionCookie(session_name(), session_id());
|
||||
if (null !== $originalCookie) {
|
||||
header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite));
|
||||
}
|
||||
}
|
||||
|
||||
$this->loadSession();
|
||||
|
||||
return true;
|
||||
@@ -208,6 +222,13 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
// @see https://bugs.php.net/bug.php?id=70013
|
||||
$this->loadSession();
|
||||
|
||||
if (null !== $this->emulateSameSite) {
|
||||
$originalCookie = SessionUtils::popSessionCookie(session_name(), session_id());
|
||||
if (null !== $originalCookie) {
|
||||
header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite));
|
||||
}
|
||||
}
|
||||
|
||||
return $isRegenerated;
|
||||
}
|
||||
|
||||
@@ -227,29 +248,22 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
unset($_SESSION[$key]);
|
||||
}
|
||||
|
||||
// Register custom error handler to catch a possible failure warning during session write
|
||||
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
|
||||
throw new \ErrorException($errstr, $errno, E_WARNING, $errfile, $errline);
|
||||
}, E_WARNING);
|
||||
// Register error handler to add information about the current save handler
|
||||
$previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) {
|
||||
if (E_WARNING === $type && 0 === strpos($msg, 'session_write_close():')) {
|
||||
$handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler;
|
||||
$msg = sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler));
|
||||
}
|
||||
|
||||
return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false;
|
||||
});
|
||||
|
||||
try {
|
||||
$e = null;
|
||||
session_write_close();
|
||||
} catch (\ErrorException $e) {
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
$_SESSION = $session;
|
||||
}
|
||||
if (null !== $e) {
|
||||
// The default PHP error message is not very helpful, as it does not give any information on the current save handler.
|
||||
// Therefore, we catch this error and trigger a warning with a better error message
|
||||
$handler = $this->getSaveHandler();
|
||||
if ($handler instanceof SessionHandlerProxy) {
|
||||
$handler = $handler->getHandler();
|
||||
}
|
||||
|
||||
trigger_error(sprintf('session_write_close(): Failed to write session data with %s handler', \get_class($handler)), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$this->closed = true;
|
||||
$this->started = false;
|
||||
@@ -347,7 +361,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
|
||||
$validOptions = array_flip(array(
|
||||
'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly',
|
||||
'cookie_lifetime', 'cookie_path', 'cookie_secure',
|
||||
'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite',
|
||||
'gc_divisor', 'gc_maxlifetime', 'gc_probability',
|
||||
'lazy_write', 'name', 'referer_check',
|
||||
'serialize_handler', 'use_strict_mode', 'use_cookies',
|
||||
@@ -359,6 +373,12 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
|
||||
foreach ($options as $key => $value) {
|
||||
if (isset($validOptions[$key])) {
|
||||
if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) {
|
||||
// PHP < 7.3 does not support same_site cookies. We will emulate it in
|
||||
// the start() method instead.
|
||||
$this->emulateSameSite = $value;
|
||||
continue;
|
||||
}
|
||||
ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value);
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* A StreamedResponse uses a callback for its content.
|
||||
*
|
||||
* The callback should use the standard PHP functions like echo
|
||||
* to stream the response back to the client. The flush() method
|
||||
* to stream the response back to the client. The flush() function
|
||||
* can also be used if needed.
|
||||
*
|
||||
* @see flush()
|
||||
@@ -129,6 +129,8 @@ class StreamedResponse extends Response
|
||||
throw new \LogicException('The content cannot be set on a StreamedResponse instance.');
|
||||
}
|
||||
|
||||
$this->streamed = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -141,16 +143,4 @@ class StreamedResponse extends Response
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setNotModified()
|
||||
{
|
||||
$this->setCallback(function () {});
|
||||
|
||||
return parent::setNotModified();
|
||||
}
|
||||
}
|
||||
|
@@ -337,7 +337,8 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
{
|
||||
return array(
|
||||
array('/var/www/var/www/files/foo.txt', '/var/www/=/files/', '/files/var/www/files/foo.txt'),
|
||||
array('/home/foo/bar.txt', '/var/www/=/files/,/home/foo/=/baz/', '/baz/bar.txt'),
|
||||
array('/home/Foo/bar.txt', '/var/www/=/files/,/home/Foo/=/baz/', '/baz/bar.txt'),
|
||||
array('/home/Foo/bar.txt', '"/var/www/"="/files/", "/home/Foo/"="/baz/"', '/baz/bar.txt'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -45,7 +45,7 @@ class CookieTest extends TestCase
|
||||
*/
|
||||
public function testInstantiationThrowsExceptionIfCookieNameContainsInvalidCharacters($name)
|
||||
{
|
||||
new Cookie($name);
|
||||
Cookie::create($name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,12 +53,12 @@ class CookieTest extends TestCase
|
||||
*/
|
||||
public function testInvalidExpiration()
|
||||
{
|
||||
new Cookie('MyCookie', 'foo', 'bar');
|
||||
Cookie::create('MyCookie', 'foo', 'bar');
|
||||
}
|
||||
|
||||
public function testNegativeExpirationIsNotPossible()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', -100);
|
||||
$cookie = Cookie::create('foo', 'bar', -100);
|
||||
|
||||
$this->assertSame(0, $cookie->getExpiresTime());
|
||||
}
|
||||
@@ -66,32 +66,32 @@ class CookieTest extends TestCase
|
||||
public function testGetValue()
|
||||
{
|
||||
$value = 'MyValue';
|
||||
$cookie = new Cookie('MyCookie', $value);
|
||||
$cookie = Cookie::create('MyCookie', $value);
|
||||
|
||||
$this->assertSame($value, $cookie->getValue(), '->getValue() returns the proper value');
|
||||
}
|
||||
|
||||
public function testGetPath()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar');
|
||||
$cookie = Cookie::create('foo', 'bar');
|
||||
|
||||
$this->assertSame('/', $cookie->getPath(), '->getPath() returns / as the default path');
|
||||
}
|
||||
|
||||
public function testGetExpiresTime()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar');
|
||||
$cookie = Cookie::create('foo', 'bar');
|
||||
|
||||
$this->assertEquals(0, $cookie->getExpiresTime(), '->getExpiresTime() returns the default expire date');
|
||||
|
||||
$cookie = new Cookie('foo', 'bar', $expire = time() + 3600);
|
||||
$cookie = Cookie::create('foo', 'bar', $expire = time() + 3600);
|
||||
|
||||
$this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
|
||||
}
|
||||
|
||||
public function testGetExpiresTimeIsCastToInt()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', 3600.9);
|
||||
$cookie = Cookie::create('foo', 'bar', 3600.9);
|
||||
|
||||
$this->assertSame(3600, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date as an integer');
|
||||
}
|
||||
@@ -99,7 +99,7 @@ class CookieTest extends TestCase
|
||||
public function testConstructorWithDateTime()
|
||||
{
|
||||
$expire = new \DateTime();
|
||||
$cookie = new Cookie('foo', 'bar', $expire);
|
||||
$cookie = Cookie::create('foo', 'bar', $expire);
|
||||
|
||||
$this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
|
||||
}
|
||||
@@ -107,7 +107,7 @@ class CookieTest extends TestCase
|
||||
public function testConstructorWithDateTimeImmutable()
|
||||
{
|
||||
$expire = new \DateTimeImmutable();
|
||||
$cookie = new Cookie('foo', 'bar', $expire);
|
||||
$cookie = Cookie::create('foo', 'bar', $expire);
|
||||
|
||||
$this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
|
||||
}
|
||||
@@ -115,7 +115,7 @@ class CookieTest extends TestCase
|
||||
public function testGetExpiresTimeWithStringValue()
|
||||
{
|
||||
$value = '+1 day';
|
||||
$cookie = new Cookie('foo', 'bar', $value);
|
||||
$cookie = Cookie::create('foo', 'bar', $value);
|
||||
$expire = strtotime($value);
|
||||
|
||||
$this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date', 1);
|
||||
@@ -123,99 +123,99 @@ class CookieTest extends TestCase
|
||||
|
||||
public function testGetDomain()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com');
|
||||
$cookie = Cookie::create('foo', 'bar', 0, '/', '.myfoodomain.com');
|
||||
|
||||
$this->assertEquals('.myfoodomain.com', $cookie->getDomain(), '->getDomain() returns the domain name on which the cookie is valid');
|
||||
}
|
||||
|
||||
public function testIsSecure()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com', true);
|
||||
$cookie = Cookie::create('foo', 'bar', 0, '/', '.myfoodomain.com', true);
|
||||
|
||||
$this->assertTrue($cookie->isSecure(), '->isSecure() returns whether the cookie is transmitted over HTTPS');
|
||||
}
|
||||
|
||||
public function testIsHttpOnly()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com', false, true);
|
||||
$cookie = Cookie::create('foo', 'bar', 0, '/', '.myfoodomain.com', false, true);
|
||||
|
||||
$this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns whether the cookie is only transmitted over HTTP');
|
||||
}
|
||||
|
||||
public function testCookieIsNotCleared()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', time() + 3600 * 24);
|
||||
$cookie = Cookie::create('foo', 'bar', time() + 3600 * 24);
|
||||
|
||||
$this->assertFalse($cookie->isCleared(), '->isCleared() returns false if the cookie did not expire yet');
|
||||
}
|
||||
|
||||
public function testCookieIsCleared()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', time() - 20);
|
||||
$cookie = Cookie::create('foo', 'bar', time() - 20);
|
||||
|
||||
$this->assertTrue($cookie->isCleared(), '->isCleared() returns true if the cookie has expired');
|
||||
|
||||
$cookie = new Cookie('foo', 'bar');
|
||||
$cookie = Cookie::create('foo', 'bar');
|
||||
|
||||
$this->assertFalse($cookie->isCleared());
|
||||
|
||||
$cookie = new Cookie('foo', 'bar', 0);
|
||||
$cookie = Cookie::create('foo', 'bar');
|
||||
|
||||
$this->assertFalse($cookie->isCleared());
|
||||
|
||||
$cookie = new Cookie('foo', 'bar', -1);
|
||||
$cookie = Cookie::create('foo', 'bar', -1);
|
||||
|
||||
$this->assertFalse($cookie->isCleared());
|
||||
}
|
||||
|
||||
public function testToString()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', $expire = strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
|
||||
$cookie = Cookie::create('foo', 'bar', $expire = strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, false, null);
|
||||
$this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; Max-Age=0; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie');
|
||||
|
||||
$cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
|
||||
$cookie = Cookie::create('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, false, null);
|
||||
$this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; Max-Age=0; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)');
|
||||
|
||||
$cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
|
||||
$cookie = Cookie::create('foo', null, 1, '/admin/', '.myfoodomain.com', false, true, false, null);
|
||||
$this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', $expire = time() - 31536001).'; Max-Age=0; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');
|
||||
|
||||
$cookie = new Cookie('foo', 'bar', 0, '/', '');
|
||||
$this->assertEquals('foo=bar; path=/; httponly', (string) $cookie);
|
||||
$cookie = Cookie::create('foo', 'bar');
|
||||
$this->assertEquals('foo=bar; path=/; httponly; samesite=lax', (string) $cookie);
|
||||
}
|
||||
|
||||
public function testRawCookie()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'b a r', 0, '/', null, false, false);
|
||||
$cookie = Cookie::create('foo', 'b a r', 0, '/', null, false, false, false, null);
|
||||
$this->assertFalse($cookie->isRaw());
|
||||
$this->assertEquals('foo=b%20a%20r; path=/', (string) $cookie);
|
||||
|
||||
$cookie = new Cookie('foo', 'b+a+r', 0, '/', null, false, false, true);
|
||||
$cookie = Cookie::create('foo', 'b+a+r', 0, '/', null, false, false, true, null);
|
||||
$this->assertTrue($cookie->isRaw());
|
||||
$this->assertEquals('foo=b+a+r; path=/', (string) $cookie);
|
||||
}
|
||||
|
||||
public function testGetMaxAge()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar');
|
||||
$cookie = Cookie::create('foo', 'bar');
|
||||
$this->assertEquals(0, $cookie->getMaxAge());
|
||||
|
||||
$cookie = new Cookie('foo', 'bar', $expire = time() + 100);
|
||||
$cookie = Cookie::create('foo', 'bar', $expire = time() + 100);
|
||||
$this->assertEquals($expire - time(), $cookie->getMaxAge());
|
||||
|
||||
$cookie = new Cookie('foo', 'bar', $expire = time() - 100);
|
||||
$cookie = Cookie::create('foo', 'bar', $expire = time() - 100);
|
||||
$this->assertEquals(0, $cookie->getMaxAge());
|
||||
}
|
||||
|
||||
public function testFromString()
|
||||
{
|
||||
$cookie = Cookie::fromString('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly');
|
||||
$this->assertEquals(new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, true), $cookie);
|
||||
$this->assertEquals(Cookie::create('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, true, null), $cookie);
|
||||
|
||||
$cookie = Cookie::fromString('foo=bar', true);
|
||||
$this->assertEquals(new Cookie('foo', 'bar', 0, '/', null, false, false), $cookie);
|
||||
$this->assertEquals(Cookie::create('foo', 'bar', 0, '/', null, false, false, false, null), $cookie);
|
||||
|
||||
$cookie = Cookie::fromString('foo', true);
|
||||
$this->assertEquals(new Cookie('foo', null, 0, '/', null, false, false), $cookie);
|
||||
$this->assertEquals(Cookie::create('foo', null, 0, '/', null, false, false, false, null), $cookie);
|
||||
}
|
||||
|
||||
public function testFromStringWithHttpOnly()
|
||||
@@ -227,9 +227,27 @@ class CookieTest extends TestCase
|
||||
$this->assertFalse($cookie->isHttpOnly());
|
||||
}
|
||||
|
||||
public function testSameSiteAttributeIsCaseInsensitive()
|
||||
public function testSameSiteAttribute()
|
||||
{
|
||||
$cookie = new Cookie('foo', 'bar', 0, '/', null, false, true, false, 'Lax');
|
||||
$this->assertEquals('lax', $cookie->getSameSite());
|
||||
|
||||
$cookie = new Cookie('foo', 'bar', 0, '/', null, false, true, false, '');
|
||||
$this->assertNull($cookie->getSameSite());
|
||||
}
|
||||
|
||||
public function testSetSecureDefault()
|
||||
{
|
||||
$cookie = Cookie::create('foo', 'bar');
|
||||
|
||||
$this->assertFalse($cookie->isSecure());
|
||||
|
||||
$cookie->setSecureDefault(true);
|
||||
|
||||
$this->assertTrue($cookie->isSecure());
|
||||
|
||||
$cookie->setSecureDefault(false);
|
||||
|
||||
$this->assertFalse($cookie->isSecure());
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ error_reporting(-1);
|
||||
ini_set('html_errors', 0);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
if (ini_get('xdebug.default_enable')) {
|
||||
if (filter_var(ini_get('xdebug.default_enable'), FILTER_VALIDATE_BOOLEAN)) {
|
||||
xdebug_disable();
|
||||
}
|
||||
|
||||
|
@@ -4,7 +4,7 @@ use Symfony\Component\HttpFoundation\Cookie;
|
||||
|
||||
$r = require __DIR__.'/common.inc';
|
||||
|
||||
$r->headers->setCookie(new Cookie('foo', 'bar', 253402310800, '', null, false, false));
|
||||
$r->headers->setCookie(new Cookie('foo', 'bar', 253402310800, '', null, false, false, false, null));
|
||||
$r->sendHeaders();
|
||||
|
||||
setcookie('foo2', 'bar', 253402310800, '/');
|
||||
|
@@ -6,7 +6,7 @@ $r = require __DIR__.'/common.inc';
|
||||
|
||||
$str = '?*():@&+$/%#[]';
|
||||
|
||||
$r->headers->setCookie(new Cookie($str, $str, 0, '/', null, false, false, true));
|
||||
$r->headers->setCookie(new Cookie($str, $str, 0, '/', null, false, false, true, null));
|
||||
$r->sendHeaders();
|
||||
|
||||
setrawcookie($str, $str, 0, '/', null, false, false);
|
||||
|
@@ -6,7 +6,7 @@ $r = require __DIR__.'/common.inc';
|
||||
|
||||
$str = '?*():@&+$/%#[]';
|
||||
|
||||
$r->headers->setCookie(new Cookie($str, $str, 0, '', null, false, false));
|
||||
$r->headers->setCookie(new Cookie($str, $str, 0, '', null, false, false, false, null));
|
||||
$r->sendHeaders();
|
||||
|
||||
setcookie($str, $str, 0, '/');
|
||||
|
@@ -5,7 +5,7 @@ use Symfony\Component\HttpFoundation\Cookie;
|
||||
$r = require __DIR__.'/common.inc';
|
||||
|
||||
try {
|
||||
$r->headers->setCookie(new Cookie('Hello + world', 'hodor'));
|
||||
$r->headers->setCookie(Cookie::create('Hello + world', 'hodor'));
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
@@ -82,4 +82,53 @@ class HeaderUtilsTest extends TestCase
|
||||
$this->assertEquals('foo "bar"', HeaderUtils::unquote('"foo \"\b\a\r\""'));
|
||||
$this->assertEquals('foo \\ bar', HeaderUtils::unquote('"foo \\\\ bar"'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testMakeDispositionInvalidDisposition()
|
||||
{
|
||||
HeaderUtils::makeDisposition('invalid', 'foo.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMakeDisposition
|
||||
*/
|
||||
public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected)
|
||||
{
|
||||
$this->assertEquals($expected, HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback));
|
||||
}
|
||||
|
||||
public function provideMakeDisposition()
|
||||
{
|
||||
return array(
|
||||
array('attachment', 'foo.html', 'foo.html', 'attachment; filename=foo.html'),
|
||||
array('attachment', 'foo.html', '', 'attachment; filename=foo.html'),
|
||||
array('attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'),
|
||||
array('attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'),
|
||||
array('attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'),
|
||||
array('attachment', 'föö.html', 'foo.html', 'attachment; filename=foo.html; filename*=utf-8\'\'f%C3%B6%C3%B6.html'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMakeDispositionFail
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testMakeDispositionFail($disposition, $filename)
|
||||
{
|
||||
HeaderUtils::makeDisposition($disposition, $filename);
|
||||
}
|
||||
|
||||
public function provideMakeDispositionFail()
|
||||
{
|
||||
return array(
|
||||
array('attachment', 'foo%20bar.html'),
|
||||
array('attachment', 'foo/bar.html'),
|
||||
array('attachment', '/foo.html'),
|
||||
array('attachment', 'foo\bar.html'),
|
||||
array('attachment', '\foo.html'),
|
||||
array('attachment', 'föö.html'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -78,6 +78,21 @@ class RequestMatcherTest extends TestCase
|
||||
$this->assertSame($isMatch, $matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testPort()
|
||||
{
|
||||
$matcher = new RequestMatcher();
|
||||
$request = Request::create('', 'get', array(), array(), array(), array('HTTP_HOST' => null, 'SERVER_PORT' => 8000));
|
||||
|
||||
$matcher->matchPort(8000);
|
||||
$this->assertTrue($matcher->matches($request));
|
||||
|
||||
$matcher->matchPort(9000);
|
||||
$this->assertFalse($matcher->matches($request));
|
||||
|
||||
$matcher = new RequestMatcher(null, null, null, null, array(), null, 8000);
|
||||
$this->assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function getHostData()
|
||||
{
|
||||
return array(
|
||||
|
@@ -232,6 +232,55 @@ class RequestTest extends TestCase
|
||||
$this->assertEquals(80, $request->getPort());
|
||||
$this->assertEquals('test.com', $request->getHttpHost());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
// Fragment should not be included in the URI
|
||||
$request = Request::create('http://test.com/foo#bar');
|
||||
$this->assertEquals('http://test.com/foo', $request->getUri());
|
||||
}
|
||||
|
||||
public function testCreateWithRequestUri()
|
||||
{
|
||||
$request = Request::create('http://test.com:80/foo');
|
||||
$request->server->set('REQUEST_URI', 'http://test.com:80/foo');
|
||||
$this->assertEquals('http://test.com/foo', $request->getUri());
|
||||
$this->assertEquals('/foo', $request->getPathInfo());
|
||||
$this->assertEquals('test.com', $request->getHost());
|
||||
$this->assertEquals('test.com', $request->getHttpHost());
|
||||
$this->assertEquals(80, $request->getPort());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
$request = Request::create('http://test.com:8080/foo');
|
||||
$request->server->set('REQUEST_URI', 'http://test.com:8080/foo');
|
||||
$this->assertEquals('http://test.com:8080/foo', $request->getUri());
|
||||
$this->assertEquals('/foo', $request->getPathInfo());
|
||||
$this->assertEquals('test.com', $request->getHost());
|
||||
$this->assertEquals('test.com:8080', $request->getHttpHost());
|
||||
$this->assertEquals(8080, $request->getPort());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
$request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz'));
|
||||
$request->server->set('REQUEST_URI', 'http://test.com/foo?bar=foo');
|
||||
$this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
|
||||
$this->assertEquals('/foo', $request->getPathInfo());
|
||||
$this->assertEquals('bar=baz', $request->getQueryString());
|
||||
$this->assertEquals('test.com', $request->getHost());
|
||||
$this->assertEquals('test.com', $request->getHttpHost());
|
||||
$this->assertEquals(80, $request->getPort());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
$request = Request::create('https://test.com:443/foo');
|
||||
$request->server->set('REQUEST_URI', 'https://test.com:443/foo');
|
||||
$this->assertEquals('https://test.com/foo', $request->getUri());
|
||||
$this->assertEquals('/foo', $request->getPathInfo());
|
||||
$this->assertEquals('test.com', $request->getHost());
|
||||
$this->assertEquals('test.com', $request->getHttpHost());
|
||||
$this->assertEquals(443, $request->getPort());
|
||||
$this->assertTrue($request->isSecure());
|
||||
|
||||
// Fragment should not be included in the URI
|
||||
$request = Request::create('http://test.com/foo#bar');
|
||||
$request->server->set('REQUEST_URI', 'http://test.com/foo#bar');
|
||||
$this->assertEquals('http://test.com/foo', $request->getUri());
|
||||
}
|
||||
|
||||
public function testCreateCheckPrecedence()
|
||||
@@ -332,6 +381,9 @@ class RequestTest extends TestCase
|
||||
{
|
||||
$request = new Request();
|
||||
$this->assertEquals('json', $request->getFormat('application/json; charset=utf-8'));
|
||||
$this->assertEquals('json', $request->getFormat('application/json;charset=utf-8'));
|
||||
$this->assertEquals('json', $request->getFormat('application/json ; charset=utf-8'));
|
||||
$this->assertEquals('json', $request->getFormat('application/json ;charset=utf-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -110,9 +110,9 @@ class ResponseHeaderBagTest extends TestCase
|
||||
public function testToStringIncludesCookieHeaders()
|
||||
{
|
||||
$bag = new ResponseHeaderBag(array());
|
||||
$bag->setCookie(new Cookie('foo', 'bar'));
|
||||
$bag->setCookie(Cookie::create('foo', 'bar'));
|
||||
|
||||
$this->assertSetCookieHeader('foo=bar; path=/; httponly', $bag);
|
||||
$this->assertSetCookieHeader('foo=bar; path=/; httponly; samesite=lax', $bag);
|
||||
|
||||
$bag->clearCookie('foo');
|
||||
|
||||
@@ -154,24 +154,24 @@ class ResponseHeaderBagTest extends TestCase
|
||||
public function testCookiesWithSameNames()
|
||||
{
|
||||
$bag = new ResponseHeaderBag();
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar'));
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'foo.bar'));
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'bar.foo'));
|
||||
$bag->setCookie(new Cookie('foo', 'bar'));
|
||||
$bag->setCookie(Cookie::create('foo', 'bar', 0, '/path/foo', 'foo.bar'));
|
||||
$bag->setCookie(Cookie::create('foo', 'bar', 0, '/path/bar', 'foo.bar'));
|
||||
$bag->setCookie(Cookie::create('foo', 'bar', 0, '/path/bar', 'bar.foo'));
|
||||
$bag->setCookie(Cookie::create('foo', 'bar'));
|
||||
|
||||
$this->assertCount(4, $bag->getCookies());
|
||||
$this->assertEquals('foo=bar; path=/path/foo; domain=foo.bar; httponly', $bag->get('set-cookie'));
|
||||
$this->assertEquals('foo=bar; path=/path/foo; domain=foo.bar; httponly; samesite=lax', $bag->get('set-cookie'));
|
||||
$this->assertEquals(array(
|
||||
'foo=bar; path=/path/foo; domain=foo.bar; httponly',
|
||||
'foo=bar; path=/path/bar; domain=foo.bar; httponly',
|
||||
'foo=bar; path=/path/bar; domain=bar.foo; httponly',
|
||||
'foo=bar; path=/; httponly',
|
||||
'foo=bar; path=/path/foo; domain=foo.bar; httponly; samesite=lax',
|
||||
'foo=bar; path=/path/bar; domain=foo.bar; httponly; samesite=lax',
|
||||
'foo=bar; path=/path/bar; domain=bar.foo; httponly; samesite=lax',
|
||||
'foo=bar; path=/; httponly; samesite=lax',
|
||||
), $bag->get('set-cookie', null, false));
|
||||
|
||||
$this->assertSetCookieHeader('foo=bar; path=/path/foo; domain=foo.bar; httponly', $bag);
|
||||
$this->assertSetCookieHeader('foo=bar; path=/path/bar; domain=foo.bar; httponly', $bag);
|
||||
$this->assertSetCookieHeader('foo=bar; path=/path/bar; domain=bar.foo; httponly', $bag);
|
||||
$this->assertSetCookieHeader('foo=bar; path=/; httponly', $bag);
|
||||
$this->assertSetCookieHeader('foo=bar; path=/path/foo; domain=foo.bar; httponly; samesite=lax', $bag);
|
||||
$this->assertSetCookieHeader('foo=bar; path=/path/bar; domain=foo.bar; httponly; samesite=lax', $bag);
|
||||
$this->assertSetCookieHeader('foo=bar; path=/path/bar; domain=bar.foo; httponly; samesite=lax', $bag);
|
||||
$this->assertSetCookieHeader('foo=bar; path=/; httponly; samesite=lax', $bag);
|
||||
|
||||
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
|
||||
@@ -186,8 +186,8 @@ class ResponseHeaderBagTest extends TestCase
|
||||
$bag = new ResponseHeaderBag();
|
||||
$this->assertFalse($bag->has('set-cookie'));
|
||||
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar'));
|
||||
$bag->setCookie(new Cookie('bar', 'foo', 0, '/path/bar', 'foo.bar'));
|
||||
$bag->setCookie(Cookie::create('foo', 'bar', 0, '/path/foo', 'foo.bar'));
|
||||
$bag->setCookie(Cookie::create('bar', 'foo', 0, '/path/bar', 'foo.bar'));
|
||||
$this->assertTrue($bag->has('set-cookie'));
|
||||
|
||||
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
@@ -209,8 +209,8 @@ class ResponseHeaderBagTest extends TestCase
|
||||
public function testRemoveCookieWithNullRemove()
|
||||
{
|
||||
$bag = new ResponseHeaderBag();
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0));
|
||||
$bag->setCookie(new Cookie('bar', 'foo', 0));
|
||||
$bag->setCookie(Cookie::create('foo', 'bar'));
|
||||
$bag->setCookie(Cookie::create('bar', 'foo'));
|
||||
|
||||
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
$this->assertArrayHasKey('/', $cookies['']);
|
||||
@@ -228,12 +228,12 @@ class ResponseHeaderBagTest extends TestCase
|
||||
{
|
||||
$bag = new ResponseHeaderBag();
|
||||
$bag->set('set-cookie', 'foo=bar');
|
||||
$this->assertEquals(array(new Cookie('foo', 'bar', 0, '/', null, false, false, true)), $bag->getCookies());
|
||||
$this->assertEquals(array(Cookie::create('foo', 'bar', 0, '/', null, false, false, true, null)), $bag->getCookies());
|
||||
|
||||
$bag->set('set-cookie', 'foo2=bar2', false);
|
||||
$this->assertEquals(array(
|
||||
new Cookie('foo', 'bar', 0, '/', null, false, false, true),
|
||||
new Cookie('foo2', 'bar2', 0, '/', null, false, false, true),
|
||||
Cookie::create('foo', 'bar', 0, '/', null, false, false, true, null),
|
||||
Cookie::create('foo2', 'bar2', 0, '/', null, false, false, true, null),
|
||||
), $bag->getCookies());
|
||||
|
||||
$bag->remove('set-cookie');
|
||||
@@ -250,26 +250,6 @@ class ResponseHeaderBagTest extends TestCase
|
||||
$bag->getCookies('invalid_argument');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testMakeDispositionInvalidDisposition()
|
||||
{
|
||||
$headers = new ResponseHeaderBag();
|
||||
|
||||
$headers->makeDisposition('invalid', 'foo.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMakeDisposition
|
||||
*/
|
||||
public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected)
|
||||
{
|
||||
$headers = new ResponseHeaderBag();
|
||||
|
||||
$this->assertEquals($expected, $headers->makeDisposition($disposition, $filename, $filenameFallback));
|
||||
}
|
||||
|
||||
public function testToStringDoesntMessUpHeaders()
|
||||
{
|
||||
$headers = new ResponseHeaderBag();
|
||||
@@ -284,41 +264,6 @@ class ResponseHeaderBagTest extends TestCase
|
||||
$this->assertEquals(array('text/html'), $allHeaders['Content-type']);
|
||||
}
|
||||
|
||||
public function provideMakeDisposition()
|
||||
{
|
||||
return array(
|
||||
array('attachment', 'foo.html', 'foo.html', 'attachment; filename=foo.html'),
|
||||
array('attachment', 'foo.html', '', 'attachment; filename=foo.html'),
|
||||
array('attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'),
|
||||
array('attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'),
|
||||
array('attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'),
|
||||
array('attachment', 'föö.html', 'foo.html', 'attachment; filename=foo.html; filename*=utf-8\'\'f%C3%B6%C3%B6.html'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMakeDispositionFail
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testMakeDispositionFail($disposition, $filename)
|
||||
{
|
||||
$headers = new ResponseHeaderBag();
|
||||
|
||||
$headers->makeDisposition($disposition, $filename);
|
||||
}
|
||||
|
||||
public function provideMakeDispositionFail()
|
||||
{
|
||||
return array(
|
||||
array('attachment', 'foo%20bar.html'),
|
||||
array('attachment', 'foo/bar.html'),
|
||||
array('attachment', '/foo.html'),
|
||||
array('attachment', 'foo\bar.html'),
|
||||
array('attachment', '\foo.html'),
|
||||
array('attachment', 'föö.html'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testDateHeaderAddedOnCreation()
|
||||
{
|
||||
$now = time();
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\HttpFoundation\Tests;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@@ -573,6 +574,24 @@ class ResponseTest extends ResponseTestCase
|
||||
$this->assertFalse($response->headers->has('expires'));
|
||||
}
|
||||
|
||||
public function testPrepareSetsCookiesSecure()
|
||||
{
|
||||
$cookie = Cookie::create('foo', 'bar');
|
||||
|
||||
$response = new Response('foo');
|
||||
$response->headers->setCookie($cookie);
|
||||
|
||||
$request = Request::create('/', 'GET');
|
||||
$response->prepare($request);
|
||||
|
||||
$this->assertFalse($cookie->isSecure());
|
||||
|
||||
$request = Request::create('https://localhost/', 'GET');
|
||||
$response->prepare($request);
|
||||
|
||||
$this->assertTrue($cookie->isSecure());
|
||||
}
|
||||
|
||||
public function testSetCache()
|
||||
{
|
||||
$response = new Response();
|
||||
|
@@ -45,7 +45,7 @@ class AttributeBagTest extends TestCase
|
||||
),
|
||||
),
|
||||
);
|
||||
$this->bag = new AttributeBag('_sf2');
|
||||
$this->bag = new AttributeBag('_sf');
|
||||
$this->bag->initialize($this->array);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ class AttributeBagTest extends TestCase
|
||||
|
||||
public function testGetStorageKey()
|
||||
{
|
||||
$this->assertEquals('_sf2', $this->bag->getStorageKey());
|
||||
$this->assertEquals('_sf', $this->bag->getStorageKey());
|
||||
$attributeBag = new AttributeBag('test');
|
||||
$this->assertEquals('test', $attributeBag->getStorageKey());
|
||||
}
|
||||
|
@@ -70,6 +70,27 @@ class SessionTest extends TestCase
|
||||
$this->assertEquals('0123456789abcdef', $this->session->getId());
|
||||
}
|
||||
|
||||
public function testSetIdAfterStart()
|
||||
{
|
||||
$this->session->start();
|
||||
$id = $this->session->getId();
|
||||
|
||||
$e = null;
|
||||
try {
|
||||
$this->session->setId($id);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
$this->assertNull($e);
|
||||
|
||||
try {
|
||||
$this->session->setId('different');
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
$this->assertInstanceOf('\LogicException', $e);
|
||||
}
|
||||
|
||||
public function testSetName()
|
||||
{
|
||||
$this->assertEquals('MOCKSESSID', $this->session->getName());
|
||||
|
16
vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected
vendored
Normal file
16
vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
open
|
||||
validateId
|
||||
read
|
||||
doRead:
|
||||
read
|
||||
|
||||
write
|
||||
doWrite: foo|s:3:"bar";
|
||||
close
|
||||
Array
|
||||
(
|
||||
[0] => Content-Type: text/plain; charset=utf-8
|
||||
[1] => Cache-Control: max-age=0, private, must-revalidate
|
||||
[2] => Set-Cookie: sid=random_session_id; path=/; secure; HttpOnly; SameSite=lax
|
||||
)
|
||||
shutdown
|
13
vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php
vendored
Normal file
13
vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
require __DIR__.'/common.inc';
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
|
||||
$storage = new NativeSessionStorage(array('cookie_samesite' => 'lax'));
|
||||
$storage->setSaveHandler(new TestSessionHandler());
|
||||
$storage->start();
|
||||
|
||||
$_SESSION = array('foo' => 'bar');
|
||||
|
||||
ob_start(function ($buffer) { return str_replace(session_id(), 'random_session_id', $buffer); });
|
@@ -0,0 +1,23 @@
|
||||
open
|
||||
validateId
|
||||
read
|
||||
doRead:
|
||||
read
|
||||
destroy
|
||||
close
|
||||
open
|
||||
validateId
|
||||
read
|
||||
doRead:
|
||||
read
|
||||
|
||||
write
|
||||
doWrite: foo|s:3:"bar";
|
||||
close
|
||||
Array
|
||||
(
|
||||
[0] => Content-Type: text/plain; charset=utf-8
|
||||
[1] => Cache-Control: max-age=0, private, must-revalidate
|
||||
[2] => Set-Cookie: sid=random_session_id; path=/; secure; HttpOnly; SameSite=lax
|
||||
)
|
||||
shutdown
|
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
require __DIR__.'/common.inc';
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
|
||||
$storage = new NativeSessionStorage(array('cookie_samesite' => 'lax'));
|
||||
$storage->setSaveHandler(new TestSessionHandler());
|
||||
$storage->start();
|
||||
|
||||
$_SESSION = array('foo' => 'bar');
|
||||
|
||||
$storage->regenerate(true);
|
||||
|
||||
ob_start(function ($buffer) { return preg_replace('~_sf2_meta.*$~m', '', str_replace(session_id(), 'random_session_id', $buffer)); });
|
@@ -45,7 +45,7 @@ class MongoDbSessionHandlerTest extends TestCase
|
||||
'data_field' => 'data',
|
||||
'time_field' => 'time',
|
||||
'expiry_field' => 'expires_at',
|
||||
'database' => 'sf2-test',
|
||||
'database' => 'sf-test',
|
||||
'collection' => 'session-test',
|
||||
);
|
||||
|
||||
|
@@ -33,7 +33,7 @@ class PdoSessionHandlerTest extends TestCase
|
||||
|
||||
protected function getPersistentSqliteDsn()
|
||||
{
|
||||
$this->dbFile = tempnam(sys_get_temp_dir(), 'sf2_sqlite_sessions');
|
||||
$this->dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_sessions');
|
||||
|
||||
return 'sqlite:'.$this->dbFile;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ class PdoSessionHandlerTest extends TestCase
|
||||
|
||||
public function testReadLockedConvertsStreamToString()
|
||||
{
|
||||
if (ini_get('session.use_strict_mode')) {
|
||||
if (filter_var(ini_get('session.use_strict_mode'), FILTER_VALIDATE_BOOLEAN)) {
|
||||
$this->markTestSkipped('Strict mode needs no locking for new sessions.');
|
||||
}
|
||||
|
||||
|
@@ -48,7 +48,7 @@ class MockArraySessionStorageTest extends TestCase
|
||||
$this->data = array(
|
||||
$this->attributes->getStorageKey() => array('foo' => 'bar'),
|
||||
$this->flashes->getStorageKey() => array('notice' => 'hello'),
|
||||
);
|
||||
);
|
||||
|
||||
$this->storage = new MockArraySessionStorage();
|
||||
$this->storage->registerBag($this->flashes);
|
||||
|
@@ -35,7 +35,7 @@ class MockFileSessionStorageTest extends TestCase
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->sessionDir = sys_get_temp_dir().'/sf2test';
|
||||
$this->sessionDir = sys_get_temp_dir().'/sftest';
|
||||
$this->storage = $this->getStorage();
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,7 @@ class NativeSessionStorageTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
$this->iniSet('session.save_handler', 'files');
|
||||
$this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test');
|
||||
$this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sftest');
|
||||
if (!is_dir($this->savePath)) {
|
||||
mkdir($this->savePath);
|
||||
}
|
||||
@@ -171,6 +171,10 @@ class NativeSessionStorageTest extends TestCase
|
||||
'cookie_httponly' => false,
|
||||
);
|
||||
|
||||
if (\PHP_VERSION_ID >= 70300) {
|
||||
$options['cookie_samesite'] = 'lax';
|
||||
}
|
||||
|
||||
$this->getStorage($options);
|
||||
$temp = session_get_cookie_params();
|
||||
$gco = array();
|
||||
|
@@ -32,7 +32,7 @@ class PhpBridgeSessionStorageTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
$this->iniSet('session.save_handler', 'files');
|
||||
$this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test');
|
||||
$this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sftest');
|
||||
if (!is_dir($this->savePath)) {
|
||||
mkdir($this->savePath);
|
||||
}
|
||||
|
2
vendor/symfony/http-foundation/composer.json
vendored
2
vendor/symfony/http-foundation/composer.json
vendored
@@ -32,7 +32,7 @@
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.1-dev"
|
||||
"dev-master": "4.2-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
|
Reference in New Issue
Block a user