webauthn
parent
4d5d93c62b
commit
2d90e73b2f
@ -0,0 +1,3 @@
|
||||
/Tests export-ignore
|
||||
/phpunit.xml.dist export-ignore
|
||||
/.gitignore export-ignore
|
@ -0,0 +1,165 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Represents an Accept-* header.
|
||||
*
|
||||
* An accept header is compound with a list of items,
|
||||
* sorted by descending quality.
|
||||
*
|
||||
* @author Jean-François Simon <contact@jfsimon.fr>
|
||||
*/
|
||||
class AcceptHeader
|
||||
{
|
||||
/**
|
||||
* @var AcceptHeaderItem[]
|
||||
*/
|
||||
private $items = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $sorted = true;
|
||||
|
||||
/**
|
||||
* @param AcceptHeaderItem[] $items
|
||||
*/
|
||||
public function __construct(array $items)
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
$this->add($item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an AcceptHeader instance from a string.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromString(?string $headerValue)
|
||||
{
|
||||
$index = 0;
|
||||
|
||||
$parts = HeaderUtils::split($headerValue ?? '', ',;=');
|
||||
|
||||
return new self(array_map(function ($subParts) use (&$index) {
|
||||
$part = array_shift($subParts);
|
||||
$attributes = HeaderUtils::combine($subParts);
|
||||
|
||||
$item = new AcceptHeaderItem($part[0], $attributes);
|
||||
$item->setIndex($index++);
|
||||
|
||||
return $item;
|
||||
}, $parts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns header value's string representation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return implode(',', $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if header has given value.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has(string $value)
|
||||
{
|
||||
return isset($this->items[$value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns given value's item, if exists.
|
||||
*
|
||||
* @return AcceptHeaderItem|null
|
||||
*/
|
||||
public function get(string $value)
|
||||
{
|
||||
return $this->items[$value] ?? $this->items[explode('/', $value)[0].'/*'] ?? $this->items['*/*'] ?? $this->items['*'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add(AcceptHeaderItem $item)
|
||||
{
|
||||
$this->items[$item->getValue()] = $item;
|
||||
$this->sorted = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all items.
|
||||
*
|
||||
* @return AcceptHeaderItem[]
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
$this->sort();
|
||||
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters items on their value using given regex.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function filter(string $pattern)
|
||||
{
|
||||
return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) {
|
||||
return preg_match($pattern, $item->getValue());
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first item.
|
||||
*
|
||||
* @return AcceptHeaderItem|null
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
$this->sort();
|
||||
|
||||
return !empty($this->items) ? reset($this->items) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts items by descending quality.
|
||||
*/
|
||||
private function sort(): void
|
||||
{
|
||||
if (!$this->sorted) {
|
||||
uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) {
|
||||
$qA = $a->getQuality();
|
||||
$qB = $b->getQuality();
|
||||
|
||||
if ($qA === $qB) {
|
||||
return $a->getIndex() > $b->getIndex() ? 1 : -1;
|
||||
}
|
||||
|
||||
return $qA > $qB ? -1 : 1;
|
||||
});
|
||||
|
||||
$this->sorted = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Represents an Accept-* header item.
|
||||
*
|
||||
* @author Jean-François Simon <contact@jfsimon.fr>
|
||||
*/
|
||||
class AcceptHeaderItem
|
||||
{
|
||||
private $value;
|
||||
private $quality = 1.0;
|
||||
private $index = 0;
|
||||
private $attributes = [];
|
||||
|
||||
public function __construct(string $value, array $attributes = [])
|
||||
{
|
||||
$this->value = $value;
|
||||
foreach ($attributes as $name => $value) {
|
||||
$this->setAttribute($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an AcceptHeaderInstance instance from a string.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromString(?string $itemValue)
|
||||
{
|
||||
$parts = HeaderUtils::split($itemValue ?? '', ';=');
|
||||
|
||||
$part = array_shift($parts);
|
||||
$attributes = HeaderUtils::combine($parts);
|
||||
|
||||
return new self($part[0], $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns header value's string representation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$string = $this->value.($this->quality < 1 ? ';q='.$this->quality : '');
|
||||
if (\count($this->attributes) > 0) {
|
||||
$string .= '; '.HeaderUtils::toString($this->attributes, ';');
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the item value.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the item quality.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setQuality(float $quality)
|
||||
{
|
||||
$this->quality = $quality;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item quality.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getQuality()
|
||||
{
|
||||
return $this->quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the item index.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setIndex(int $index)
|
||||
{
|
||||
$this->index = $index;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item index.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if an attribute exists.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAttribute(string $name)
|
||||
{
|
||||
return isset($this->attributes[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an attribute by its name.
|
||||
*
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttribute(string $name, $default = null)
|
||||
{
|
||||
return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all attributes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an attribute.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttribute(string $name, string $value)
|
||||
{
|
||||
if ('q' === $name) {
|
||||
$this->quality = (float) $value;
|
||||
} else {
|
||||
$this->attributes[$name] = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,354 @@
|
||||
<?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;
|
||||
|
||||
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
|
||||
/**
|
||||
* BinaryFileResponse represents an HTTP response delivering a file.
|
||||
*
|
||||
* @author Niklas Fiekas <niklas.fiekas@tu-clausthal.de>
|
||||
* @author stealth35 <stealth35-php@live.fr>
|
||||
* @author Igor Wiedler <igor@wiedler.ch>
|
||||
* @author Jordan Alliot <jordan.alliot@gmail.com>
|
||||
* @author Sergey Linnik <linniksa@gmail.com>
|
||||
*/
|
||||
class BinaryFileResponse extends Response
|
||||
{
|
||||
protected static $trustXSendfileTypeHeader = false;
|
||||
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
protected $file;
|
||||
protected $offset = 0;
|
||||
protected $maxlen = -1;
|
||||
protected $deleteFileAfterSend = false;
|
||||
|
||||
/**
|
||||
* @param \SplFileInfo|string $file The file to stream
|
||||
* @param int $status The response status code
|
||||
* @param array $headers An array of response headers
|
||||
* @param bool $public Files are public by default
|
||||
* @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
|
||||
*/
|
||||
public function __construct($file, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true)
|
||||
{
|
||||
parent::__construct(null, $status, $headers);
|
||||
|
||||
$this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified);
|
||||
|
||||
if ($public) {
|
||||
$this->setPublic();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SplFileInfo|string $file The file to stream
|
||||
* @param int $status The response status code
|
||||
* @param array $headers An array of response headers
|
||||
* @param bool $public Files are public by default
|
||||
* @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
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function create($file = null, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true)
|
||||
{
|
||||
return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file to stream.
|
||||
*
|
||||
* @param \SplFileInfo|string $file The file to stream
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws FileException
|
||||
*/
|
||||
public function setFile($file, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true)
|
||||
{
|
||||
if (!$file instanceof File) {
|
||||
if ($file instanceof \SplFileInfo) {
|
||||
$file = new File($file->getPathname());
|
||||
} else {
|
||||
$file = new File((string) $file);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$file->isReadable()) {
|
||||
throw new FileException('File must be readable.');
|
||||
}
|
||||
|
||||
$this->file = $file;
|
||||
|
||||
if ($autoEtag) {
|
||||
$this->setAutoEtag();
|
||||
}
|
||||
|
||||
if ($autoLastModified) {
|
||||
$this->setAutoLastModified();
|
||||
}
|
||||
|
||||
if ($contentDisposition) {
|
||||
$this->setContentDisposition($contentDisposition);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file.
|
||||
*
|
||||
* @return File The file to stream
|
||||
*/
|
||||
public function getFile()
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically sets the Last-Modified header according the file modification date.
|
||||
*/
|
||||
public function setAutoLastModified()
|
||||
{
|
||||
$this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime()));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically sets the ETag header according to the checksum of the file.
|
||||
*/
|
||||
public function setAutoEtag()
|
||||
{
|
||||
$this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), true)));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Content-Disposition header with the given filename.
|
||||
*
|
||||
* @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT
|
||||
* @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file
|
||||
* @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setContentDisposition(string $disposition, string $filename = '', string $filenameFallback = '')
|
||||
{
|
||||
if ('' === $filename) {
|
||||
$filename = $this->file->getFilename();
|
||||
}
|
||||
|
||||
if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || false !== strpos($filename, '%'))) {
|
||||
$encoding = mb_detect_encoding($filename, null, true) ?: '8bit';
|
||||
|
||||
for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) {
|
||||
$char = mb_substr($filename, $i, 1, $encoding);
|
||||
|
||||
if ('%' === $char || \ord($char) < 32 || \ord($char) > 126) {
|
||||
$filenameFallback .= '_';
|
||||
} else {
|
||||
$filenameFallback .= $char;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback);
|
||||
$this->headers->set('Content-Disposition', $dispositionHeader);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepare(Request $request)
|
||||
{
|
||||
if (!$this->headers->has('Content-Type')) {
|
||||
$this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream');
|
||||
}
|
||||
|
||||
if ('HTTP/1.0' !== $request->server->get('SERVER_PROTOCOL')) {
|
||||
$this->setProtocolVersion('1.1');
|
||||
}
|
||||
|
||||
$this->ensureIEOverSSLCompatibility($request);
|
||||
|
||||
$this->offset = 0;
|
||||
$this->maxlen = -1;
|
||||
|
||||
if (false === $fileSize = $this->file->getSize()) {
|
||||
return $this;
|
||||
}
|
||||
$this->headers->set('Content-Length', $fileSize);
|
||||
|
||||
if (!$this->headers->has('Accept-Ranges')) {
|
||||
// Only accept ranges on safe HTTP methods
|
||||
$this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none');
|
||||
}
|
||||
|
||||
if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) {
|
||||
// Use X-Sendfile, do not send any content.
|
||||
$type = $request->headers->get('X-Sendfile-Type');
|
||||
$path = $this->file->getRealPath();
|
||||
// Fall back to scheme://path for stream wrapped locations.
|
||||
if (false === $path) {
|
||||
$path = $this->file->getPathname();
|
||||
}
|
||||
if ('x-accel-redirect' === strtolower($type)) {
|
||||
// Do X-Accel-Mapping substitutions.
|
||||
// @link http://wiki.nginx.org/X-accel#X-Accel-Redirect
|
||||
$parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',=');
|
||||
foreach ($parts as $part) {
|
||||
list($pathPrefix, $location) = $part;
|
||||
if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) {
|
||||
$path = $location.substr($path, \strlen($pathPrefix));
|
||||
// Only set X-Accel-Redirect header if a valid URI can be produced
|
||||
// as nginx does not serve arbitrary file paths.
|
||||
$this->headers->set($type, $path);
|
||||
$this->maxlen = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->headers->set($type, $path);
|
||||
$this->maxlen = 0;
|
||||
}
|
||||
} elseif ($request->headers->has('Range')) {
|
||||
// Process the range headers.
|
||||
if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) {
|
||||
$range = $request->headers->get('Range');
|
||||
|
||||
list($start, $end) = explode('-', substr($range, 6), 2) + [0];
|
||||
|
||||
$end = ('' === $end) ? $fileSize - 1 : (int) $end;
|
||||
|
||||
if ('' === $start) {
|
||||
$start = $fileSize - $end;
|
||||
$end = $fileSize - 1;
|
||||
} else {
|
||||
$start = (int) $start;
|
||||
}
|
||||
|
||||
if ($start <= $end) {
|
||||
if ($start < 0 || $end > $fileSize - 1) {
|
||||
$this->setStatusCode(416);
|
||||
$this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize));
|
||||
} elseif (0 !== $start || $end !== $fileSize - 1) {
|
||||
$this->maxlen = $end < $fileSize ? $end - $start + 1 : -1;
|
||||
$this->offset = $start;
|
||||
|
||||
$this->setStatusCode(206);
|
||||
$this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize));
|
||||
$this->headers->set('Content-Length', $end - $start + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function hasValidIfRangeHeader(?string $header): bool
|
||||
{
|
||||
if ($this->getEtag() === $header) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (null === $lastModified = $this->getLastModified()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $lastModified->format('D, d M Y H:i:s').' GMT' === $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the file.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sendContent()
|
||||
{
|
||||
if (!$this->isSuccessful()) {
|
||||
return parent::sendContent();
|
||||
}
|
||||
|
||||
if (0 === $this->maxlen) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$out = fopen('php://output', 'wb');
|
||||
$file = fopen($this->file->getPathname(), 'rb');
|
||||
|
||||
stream_copy_to_stream($file, $out, $this->maxlen, $this->offset);
|
||||
|
||||
fclose($out);
|
||||
fclose($file);
|
||||
|
||||
if ($this->deleteFileAfterSend && file_exists($this->file->getPathname())) {
|
||||
unlink($this->file->getPathname());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws \LogicException when the content is not null
|
||||
*/
|
||||
public function setContent(?string $content)
|
||||
{
|
||||
if (null !== $content) {
|
||||
throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trust X-Sendfile-Type header.
|
||||
*/
|
||||
public static function trustXSendfileTypeHeader()
|
||||
{
|
||||
self::$trustXSendfileTypeHeader = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is set to true, the file will be unlinked after the request is send
|
||||
* Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function deleteFileAfterSend(bool $shouldDelete = true)
|
||||
{
|
||||
$this->deleteFileAfterSend = $shouldDelete;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,244 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
5.0.0
|
||||
-----
|
||||
|
||||
* made `Cookie` auto-secure and lax by default
|
||||
* removed classes in the `MimeType` namespace, use the Symfony Mime component instead
|
||||
* removed method `UploadedFile::getClientSize()` and the related constructor argument
|
||||
* made `Request::getSession()` throw if the session has not been set before
|
||||
* removed `Response::HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL`
|
||||
* passing a null url when instantiating a `RedirectResponse` is not allowed
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* passing arguments to `Request::isMethodSafe()` is deprecated.
|
||||
* `ApacheRequest` is deprecated, use the `Request` class instead.
|
||||
* passing a third argument to `HeaderBag::get()` is deprecated, use method `all()` instead
|
||||
* `PdoSessionHandler` now precalculates the expiry timestamp in the lifetime column,
|
||||
make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database
|
||||
to speed up garbage collection of expired sessions.
|
||||
* added `SessionHandlerFactory` to create session handlers with a DSN
|
||||
* added `IpUtils::anonymize()` to help with GDPR compliance.
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`,
|
||||
`ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame`
|
||||
* deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`.
|
||||
* deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`.
|
||||
* deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`.
|
||||
* deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`.
|
||||
* added `UrlHelper` that allows to get an absolute URL and a relative path for a given path
|
||||
|
||||
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
|
||||
-----
|
||||
|
||||
* [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL`
|
||||
HTTP headers has been dropped for security reasons.
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
||||
* Query string normalization uses `parse_str()` instead of custom parsing logic.
|
||||
* Passing the file size to the constructor of the `UploadedFile` class is deprecated.
|
||||
* The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead.
|
||||
* added `RedisSessionHandler` to use Redis as a session storage
|
||||
* The `get()` method of the `AcceptHeader` class now takes into account the
|
||||
`*` and `*/*` default values (if they are present in the Accept HTTP header)
|
||||
when looking for items.
|
||||
* deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead.
|
||||
* added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`,
|
||||
`IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to
|
||||
handle failed `UploadedFile`.
|
||||
* added `MigratingSessionHandler` for migrating between two session handlers without losing sessions
|
||||
* added `HeaderUtils`.
|
||||
|
||||
4.0.0
|
||||
-----
|
||||
|
||||
* the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()`
|
||||
methods have been removed
|
||||
* the `Request::HEADER_CLIENT_IP` constant has been removed, use
|
||||
`Request::HEADER_X_FORWARDED_FOR` instead
|
||||
* the `Request::HEADER_CLIENT_HOST` constant has been removed, use
|
||||
`Request::HEADER_X_FORWARDED_HOST` instead
|
||||
* the `Request::HEADER_CLIENT_PROTO` constant has been removed, use
|
||||
`Request::HEADER_X_FORWARDED_PROTO` instead
|
||||
* the `Request::HEADER_CLIENT_PORT` constant has been removed, use
|
||||
`Request::HEADER_X_FORWARDED_PORT` instead
|
||||
* checking for cacheable HTTP methods using the `Request::isMethodSafe()`
|
||||
method (by not passing `false` as its argument) is not supported anymore and
|
||||
throws a `\BadMethodCallException`
|
||||
* the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed
|
||||
* setting session save handlers that do not implement `\SessionHandlerInterface` in
|
||||
`NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a
|
||||
`\TypeError`
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
* implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new
|
||||
`AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper
|
||||
* deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes
|
||||
* deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()`
|
||||
* deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead
|
||||
* deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
* the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument,
|
||||
see https://symfony.com/doc/current/deployment/proxies.html for more info,
|
||||
* deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods,
|
||||
* added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown,
|
||||
disabling `Range` and `Content-Length` handling, switching to chunked encoding instead
|
||||
* added the `Cookie::fromString()` method that allows to create a cookie from a
|
||||
raw header string
|
||||
|
||||
3.1.0
|
||||
-----
|
||||
|
||||
* Added support for creating `JsonResponse` with a string of JSON data
|
||||
|
||||
3.0.0
|
||||
-----
|
||||
|
||||
* The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY"
|
||||
|
||||
2.8.0
|
||||
-----
|
||||
|
||||
* Finding deep items in `ParameterBag::get()` is deprecated since version 2.8 and
|
||||
will be removed in 3.0.
|
||||
|
||||
2.6.0
|
||||
-----
|
||||
|
||||
* PdoSessionHandler changes
|
||||
- implemented different session locking strategies to prevent loss of data by concurrent access to the same session
|
||||
- [BC BREAK] save session data in a binary column without base64_encode
|
||||
- [BC BREAK] added lifetime column to the session table which allows to have different lifetimes for each session
|
||||
- implemented lazy connections that are only opened when a session is used by either passing a dsn string
|
||||
explicitly or falling back to session.save_path ini setting
|
||||
- added a createTable method that initializes a correctly defined table depending on the database vendor
|
||||
|
||||
2.5.0
|
||||
-----
|
||||
|
||||
* added `JsonResponse::setEncodingOptions()` & `JsonResponse::getEncodingOptions()` for easier manipulation
|
||||
of the options used while encoding data to JSON format.
|
||||
|
||||
2.4.0
|
||||
-----
|
||||
|
||||
* added RequestStack
|
||||
* added Request::getEncodings()
|
||||
* added accessors methods to session handlers
|
||||
|
||||
2.3.0
|
||||
-----
|
||||
|
||||
* added support for ranges of IPs in trusted proxies
|
||||
* `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode)
|
||||
* Improved error-handling of `\Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler`
|
||||
to ensure the supplied PDO handler throws Exceptions on error (as the class expects). Added related test cases
|
||||
to verify that Exceptions are properly thrown when the PDO queries fail.
|
||||
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* fixed the Request::create() precedence (URI information always take precedence now)
|
||||
* added Request::getTrustedProxies()
|
||||
* deprecated Request::isProxyTrusted()
|
||||
* [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects
|
||||
* added a IpUtils class to check if an IP belongs to a CIDR
|
||||
* added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method)
|
||||
* disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to
|
||||
enable it, and Request::getHttpMethodParameterOverride() to check if it is supported)
|
||||
* Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3
|
||||
* Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
* added Request::getSchemeAndHttpHost() and Request::getUserInfo()
|
||||
* added a fluent interface to the Response class
|
||||
* added Request::isProxyTrusted()
|
||||
* added JsonResponse
|
||||
* added a getTargetUrl method to RedirectResponse
|
||||
* added support for streamed responses
|
||||
* made Response::prepare() method the place to enforce HTTP specification
|
||||
* [BC BREAK] moved management of the locale from the Session class to the Request class
|
||||
* added a generic access to the PHP built-in filter mechanism: ParameterBag::filter()
|
||||
* made FileBinaryMimeTypeGuesser command configurable
|
||||
* added Request::getUser() and Request::getPassword()
|
||||
* added support for the PATCH method in Request
|
||||
* removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3
|
||||
* added ResponseHeaderBag::makeDisposition() (implements RFC 6266)
|
||||
* made mimetype to extension conversion configurable
|
||||
* [BC BREAK] Moved all session related classes and interfaces into own namespace, as
|
||||
`Symfony\Component\HttpFoundation\Session` and renamed classes accordingly.
|
||||
Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`.
|
||||
* SessionHandlers must implement `\SessionHandlerInterface` or extend from the
|
||||
`Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class.
|
||||
* Added internal storage driver proxy mechanism for forward compatibility with
|
||||
PHP 5.4 `\SessionHandler` class.
|
||||
* Added session handlers for custom Memcache, Memcached and Null session save handlers.
|
||||
* [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`.
|
||||
* [BC BREAK] `SessionStorageInterface` metho |