update v 1.0.7.5
This commit is contained in:
@@ -27,6 +27,9 @@ class BinaryFileResponse extends Response
|
||||
{
|
||||
protected static $trustXSendfileTypeHeader = false;
|
||||
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
protected $file;
|
||||
protected $offset;
|
||||
protected $maxlen;
|
||||
@@ -158,6 +161,20 @@ class BinaryFileResponse extends Response
|
||||
$filename = $this->file->getFilename();
|
||||
}
|
||||
|
||||
if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || false !== strpos($filename, '%'))) {
|
||||
$encoding = mb_detect_encoding($filename, null, true);
|
||||
|
||||
for ($i = 0; $i < mb_strlen($filename, $encoding); ++$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);
|
||||
|
||||
@@ -180,7 +197,7 @@ class BinaryFileResponse extends Response
|
||||
$this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream');
|
||||
}
|
||||
|
||||
if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
|
||||
if ('HTTP/1.0' !== $request->server->get('SERVER_PROTOCOL')) {
|
||||
$this->setProtocolVersion('1.1');
|
||||
}
|
||||
|
||||
@@ -193,17 +210,21 @@ class BinaryFileResponse extends Response
|
||||
// Use X-Sendfile, do not send any content.
|
||||
$type = $request->headers->get('X-Sendfile-Type');
|
||||
$path = $this->file->getRealPath();
|
||||
if (strtolower($type) == 'x-accel-redirect') {
|
||||
// Fall back to scheme://path for stream wrapped locations.
|
||||
if (false === $path) {
|
||||
$path = $this->file->getPathname();
|
||||
}
|
||||
if (strtolower($type) === 'x-accel-redirect') {
|
||||
// Do X-Accel-Mapping substitutions.
|
||||
// @link http://wiki.nginx.org/X-accel#X-Accel-Redirect
|
||||
foreach (explode(',', $request->headers->get('X-Accel-Mapping', '')) as $mapping) {
|
||||
$mapping = explode('=', $mapping, 2);
|
||||
|
||||
if (2 == count($mapping)) {
|
||||
if (2 === count($mapping)) {
|
||||
$pathPrefix = trim($mapping[0]);
|
||||
$location = trim($mapping[1]);
|
||||
|
||||
if (substr($path, 0, strlen($pathPrefix)) == $pathPrefix) {
|
||||
if (substr($path, 0, strlen($pathPrefix)) === $pathPrefix) {
|
||||
$path = $location.substr($path, strlen($pathPrefix));
|
||||
break;
|
||||
}
|
||||
@@ -214,7 +235,7 @@ class BinaryFileResponse extends Response
|
||||
$this->maxlen = 0;
|
||||
} elseif ($request->headers->has('Range')) {
|
||||
// Process the range headers.
|
||||
if (!$request->headers->has('If-Range') || $this->getEtag() == $request->headers->get('If-Range')) {
|
||||
if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) {
|
||||
$range = $request->headers->get('Range');
|
||||
$fileSize = $this->file->getSize();
|
||||
|
||||
@@ -232,6 +253,7 @@ class BinaryFileResponse extends Response
|
||||
if ($start <= $end) {
|
||||
if ($start < 0 || $end > $fileSize - 1) {
|
||||
$this->setStatusCode(416);
|
||||
$this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize));
|
||||
} elseif ($start !== 0 || $end !== $fileSize - 1) {
|
||||
$this->maxlen = $end < $fileSize ? $end - $start + 1 : -1;
|
||||
$this->offset = $start;
|
||||
@@ -247,19 +269,32 @@ class BinaryFileResponse extends Response
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function hasValidIfRangeHeader($header)
|
||||
{
|
||||
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()) {
|
||||
parent::sendContent();
|
||||
|
||||
return;
|
||||
return parent::sendContent();
|
||||
}
|
||||
|
||||
if (0 === $this->maxlen) {
|
||||
return;
|
||||
return $this;
|
||||
}
|
||||
|
||||
$out = fopen('php://output', 'wb');
|
||||
@@ -273,6 +308,8 @@ class BinaryFileResponse extends Response
|
||||
if ($this->deleteFileAfterSend) {
|
||||
unlink($this->file->getPathname());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,6 +345,7 @@ class BinaryFileResponse extends Response
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param bool $shouldDelete
|
||||
*
|
||||
* @return BinaryFileResponse
|
@@ -1,6 +1,17 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
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
|
||||
-----
|
||||
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* Represents a cookie.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Cookie
|
||||
{
|
||||
@@ -31,17 +29,15 @@ class Cookie
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the cookie
|
||||
* @param string $value The value of the cookie
|
||||
* @param int|string|\DateTime $expire The time the cookie expires
|
||||
* @param string $path The path on the server in which the cookie will be available on
|
||||
* @param string $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 $httpOnly Whether the cookie will be made accessible only through the HTTP protocol
|
||||
* @param string $name The name of the cookie
|
||||
* @param string $value The value of the cookie
|
||||
* @param int|string|\DateTime|\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 $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 $httpOnly Whether the cookie will be made accessible only through the HTTP protocol
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true)
|
||||
{
|
||||
@@ -55,7 +51,7 @@ class Cookie
|
||||
}
|
||||
|
||||
// convert expiration time to a Unix timestamp
|
||||
if ($expire instanceof \DateTime) {
|
||||
if ($expire instanceof \DateTimeInterface) {
|
||||
$expire = $expire->format('U');
|
||||
} elseif (!is_numeric($expire)) {
|
||||
$expire = strtotime($expire);
|
||||
@@ -116,8 +112,6 @@ class Cookie
|
||||
* Gets the name of the cookie.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
@@ -128,8 +122,6 @@ class Cookie
|
||||
* Gets the value of the cookie.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
@@ -140,8 +132,6 @@ class Cookie
|
||||
* Gets the domain that the cookie is available to.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getDomain()
|
||||
{
|
||||
@@ -152,8 +142,6 @@ class Cookie
|
||||
* Gets the time the cookie expires.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getExpiresTime()
|
||||
{
|
||||
@@ -164,8 +152,6 @@ class Cookie
|
||||
* Gets the path on the server in which the cookie will be available on.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getPath()
|
||||
{
|
||||
@@ -176,8 +162,6 @@ class Cookie
|
||||
* Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isSecure()
|
||||
{
|
||||
@@ -188,8 +172,6 @@ class Cookie
|
||||
* Checks whether the cookie will be made accessible only through the HTTP protocol.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isHttpOnly()
|
||||
{
|
||||
@@ -200,8 +182,6 @@ class Cookie
|
||||
* Whether this cookie is about to be cleared.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isCleared()
|
||||
{
|
@@ -20,8 +20,6 @@ use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
|
||||
* A file in the file system.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class File extends \SplFileInfo
|
||||
{
|
||||
@@ -32,8 +30,6 @@ class File extends \SplFileInfo
|
||||
* @param bool $checkPath Whether to check the path or not
|
||||
*
|
||||
* @throws FileNotFoundException If the given path is not a file
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($path, $checkPath = true)
|
||||
{
|
||||
@@ -54,8 +50,6 @@ class File extends \SplFileInfo
|
||||
*
|
||||
* @return string|null The guessed extension or null if it cannot be guessed
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @see ExtensionGuesser
|
||||
* @see getMimeType()
|
||||
*/
|
||||
@@ -77,8 +71,6 @@ class File extends \SplFileInfo
|
||||
* @return string|null The guessed mime type (i.e. "application/pdf")
|
||||
*
|
||||
* @see MimeTypeGuesser
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getMimeType()
|
||||
{
|
||||
@@ -87,20 +79,6 @@ class File extends \SplFileInfo
|
||||
return $guesser->guess($this->getPathname());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extension of the file.
|
||||
*
|
||||
* \SplFileInfo::getExtension() is not available before PHP 5.3.6
|
||||
*
|
||||
* @return string The extension
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getExtension()
|
||||
{
|
||||
return pathinfo($this->getBasename(), PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the file to a new location.
|
||||
*
|
||||
@@ -110,8 +88,6 @@ class File extends \SplFileInfo
|
||||
* @return File A File object representing the new file
|
||||
*
|
||||
* @throws FileException if the target file could not be created
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function move($directory, $name = null)
|
||||
{
|
@@ -21,8 +21,6 @@ use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class UploadedFile extends File
|
||||
{
|
||||
@@ -52,7 +50,7 @@ class UploadedFile extends File
|
||||
/**
|
||||
* The file size provided by the uploader.
|
||||
*
|
||||
* @var string
|
||||
* @var int|null
|
||||
*/
|
||||
private $size;
|
||||
|
||||
@@ -77,17 +75,15 @@ class UploadedFile extends File
|
||||
*
|
||||
* Calling any other method on an non-valid instance will cause an unpredictable result.
|
||||
*
|
||||
* @param string $path The full temporary path to the file
|
||||
* @param string $originalName The original file name
|
||||
* @param string $mimeType The type of the file as provided by PHP
|
||||
* @param int $size The file size
|
||||
* @param int $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants)
|
||||
* @param bool $test Whether the test mode is active
|
||||
* @param string $path The full temporary path to the file
|
||||
* @param string $originalName The original file name
|
||||
* @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream
|
||||
* @param int|null $size The file size
|
||||
* @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
|
||||
* @param bool $test Whether the test mode is active
|
||||
*
|
||||
* @throws FileException If file_uploads is disabled
|
||||
* @throws FileNotFoundException If the file does not exist
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false)
|
||||
{
|
||||
@@ -107,8 +103,6 @@ class UploadedFile extends File
|
||||
* Then it should not be considered as a safe value.
|
||||
*
|
||||
* @return string|null The original name
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getClientOriginalName()
|
||||
{
|
||||
@@ -140,8 +134,6 @@ class UploadedFile extends File
|
||||
* @return string|null The mime type
|
||||
*
|
||||
* @see getMimeType()
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getClientMimeType()
|
||||
{
|
||||
@@ -180,8 +172,6 @@ class UploadedFile extends File
|
||||
* Then it should not be considered as a safe value.
|
||||
*
|
||||
* @return int|null The file size
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getClientSize()
|
||||
{
|
||||
@@ -195,8 +185,6 @@ class UploadedFile extends File
|
||||
* Otherwise one of the other UPLOAD_ERR_XXX constants is returned.
|
||||
*
|
||||
* @return int The upload error
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
@@ -207,8 +195,6 @@ class UploadedFile extends File
|
||||
* Returns whether the file was uploaded successfully.
|
||||
*
|
||||
* @return bool True if the file has been uploaded with HTTP and no error occurred.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isValid()
|
||||
{
|
||||
@@ -226,8 +212,6 @@ class UploadedFile extends File
|
||||
* @return File A File object representing the new file
|
||||
*
|
||||
* @throws FileException if, for any reason, the file could not have been moved
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function move($directory, $name = null)
|
||||
{
|
@@ -18,8 +18,6 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class FileBag extends ParameterBag
|
||||
{
|
||||
@@ -29,8 +27,6 @@ class FileBag extends ParameterBag
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $parameters An array of HTTP files
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct(array $parameters = array())
|
||||
{
|
||||
@@ -39,8 +35,6 @@ class FileBag extends ParameterBag
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function replace(array $files = array())
|
||||
{
|
||||
@@ -50,8 +44,6 @@ class FileBag extends ParameterBag
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
@@ -64,8 +56,6 @@ class FileBag extends ParameterBag
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function add(array $files = array())
|
||||
{
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* HeaderBag is a container for HTTP headers.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class HeaderBag implements \IteratorAggregate, \Countable
|
||||
{
|
||||
@@ -27,8 +25,6 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $headers An array of HTTP headers
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct(array $headers = array())
|
||||
{
|
||||
@@ -65,8 +61,6 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* Returns the headers.
|
||||
*
|
||||
* @return array An array of headers
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
@@ -77,8 +71,6 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* Returns the parameter keys.
|
||||
*
|
||||
* @return array An array of parameter keys
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function keys()
|
||||
{
|
||||
@@ -89,8 +81,6 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* Replaces the current HTTP headers by a new set.
|
||||
*
|
||||
* @param array $headers An array of HTTP headers
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function replace(array $headers = array())
|
||||
{
|
||||
@@ -102,8 +92,6 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* Adds new headers the current HTTP headers set.
|
||||
*
|
||||
* @param array $headers An array of HTTP headers
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function add(array $headers)
|
||||
{
|
||||
@@ -120,12 +108,10 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* @param bool $first Whether to return the first value or all header values
|
||||
*
|
||||
* @return string|array The first header value if $first is true, an array of values otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function get($key, $default = null, $first = true)
|
||||
{
|
||||
$key = strtr(strtolower($key), '_', '-');
|
||||
$key = str_replace('_', '-', strtolower($key));
|
||||
|
||||
if (!array_key_exists($key, $this->headers)) {
|
||||
if (null === $default) {
|
||||
@@ -148,12 +134,10 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* @param string $key The key
|
||||
* @param string|array $values The value or an array of values
|
||||
* @param bool $replace Whether to replace the actual value or not (true by default)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function set($key, $values, $replace = true)
|
||||
{
|
||||
$key = strtr(strtolower($key), '_', '-');
|
||||
$key = str_replace('_', '-', strtolower($key));
|
||||
|
||||
$values = array_values((array) $values);
|
||||
|
||||
@@ -174,12 +158,10 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* @param string $key The HTTP header
|
||||
*
|
||||
* @return bool true if the parameter exists, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers);
|
||||
return array_key_exists(str_replace('_', '-', strtolower($key)), $this->headers);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,8 +171,6 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* @param string $value The HTTP value
|
||||
*
|
||||
* @return bool true if the value is contained in the header, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function contains($key, $value)
|
||||
{
|
||||
@@ -201,12 +181,10 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* Removes a header.
|
||||
*
|
||||
* @param string $key The HTTP header name
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
$key = strtr(strtolower($key), '_', '-');
|
||||
$key = str_replace('_', '-', strtolower($key));
|
||||
|
||||
unset($this->headers[$key]);
|
||||
|
||||
@@ -224,8 +202,6 @@ class HeaderBag implements \IteratorAggregate, \Countable
|
||||
* @return null|\DateTime The parsed DateTime or the default value if the header does not exist
|
||||
*
|
||||
* @throws \RuntimeException When the HTTP header is not parseable
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getDate($key, \DateTime $default = null)
|
||||
{
|
@@ -57,18 +57,19 @@ class IpUtils
|
||||
* @param string $requestIp IPv4 address to check
|
||||
* @param string $ip IPv4 address or subnet in CIDR notation
|
||||
*
|
||||
* @return bool Whether the IP is valid
|
||||
* @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet.
|
||||
*/
|
||||
public static function checkIp4($requestIp, $ip)
|
||||
{
|
||||
if (false !== strpos($ip, '/')) {
|
||||
if ('0.0.0.0/0' === $ip) {
|
||||
return true;
|
||||
}
|
||||
|
||||
list($address, $netmask) = explode('/', $ip, 2);
|
||||
|
||||
if ($netmask < 1 || $netmask > 32) {
|
||||
if ($netmask === '0') {
|
||||
// Ensure IP is valid - using ip2long below implicitly validates, but we need to do it manually here
|
||||
return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
|
||||
}
|
||||
|
||||
if ($netmask < 0 || $netmask > 32) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -111,8 +112,12 @@ class IpUtils
|
||||
$netmask = 128;
|
||||
}
|
||||
|
||||
$bytesAddr = unpack('n*', inet_pton($address));
|
||||
$bytesTest = unpack('n*', inet_pton($requestIp));
|
||||
$bytesAddr = unpack('n*', @inet_pton($address));
|
||||
$bytesTest = unpack('n*', @inet_pton($requestIp));
|
||||
|
||||
if (!$bytesAddr || !$bytesTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) {
|
||||
$left = $netmask - 16 * ($i - 1);
|
@@ -102,39 +102,12 @@ class JsonResponse extends Response
|
||||
$data = json_encode($data, $this->encodingOptions);
|
||||
} else {
|
||||
try {
|
||||
if (PHP_VERSION_ID < 50400) {
|
||||
// PHP 5.3 triggers annoying warnings for some
|
||||
// types that can't be serialized as JSON (INF, resources, etc.)
|
||||
// but doesn't provide the JsonSerializable interface.
|
||||
set_error_handler('var_dump', 0);
|
||||
$data = @json_encode($data, $this->encodingOptions);
|
||||
} else {
|
||||
// PHP 5.4 and up wrap exceptions thrown by JsonSerializable
|
||||
// objects in a new exception that needs to be removed.
|
||||
// Fortunately, PHP 5.5 and up do not trigger any warning anymore.
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
// Clear json_last_error()
|
||||
json_encode(null);
|
||||
$errorHandler = set_error_handler('var_dump');
|
||||
restore_error_handler();
|
||||
set_error_handler(function () use ($errorHandler) {
|
||||
if (JSON_ERROR_NONE === json_last_error()) {
|
||||
return $errorHandler && false !== call_user_func_array($errorHandler, func_get_args());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$data = json_encode($data, $this->encodingOptions);
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
restore_error_handler();
|
||||
}
|
||||
// PHP 5.4 and up wrap exceptions thrown by JsonSerializable
|
||||
// objects in a new exception that needs to be removed.
|
||||
// Fortunately, PHP 5.5 and up do not trigger any warning anymore.
|
||||
$data = json_encode($data, $this->encodingOptions);
|
||||
} catch (\Exception $e) {
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
restore_error_handler();
|
||||
}
|
||||
if (PHP_VERSION_ID >= 50400 && 'Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) {
|
||||
if ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) {
|
||||
throw $e->getPrevious() ?: $e;
|
||||
}
|
||||
throw $e;
|
||||
@@ -142,7 +115,7 @@ class JsonResponse extends Response
|
||||
}
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \InvalidArgumentException($this->transformJsonError());
|
||||
throw new \InvalidArgumentException(json_last_error_msg());
|
||||
}
|
||||
|
||||
$this->data = $data;
|
||||
@@ -196,31 +169,4 @@ class JsonResponse extends Response
|
||||
|
||||
return $this->setContent($this->data);
|
||||
}
|
||||
|
||||
private function transformJsonError()
|
||||
{
|
||||
if (function_exists('json_last_error_msg')) {
|
||||
return json_last_error_msg();
|
||||
}
|
||||
|
||||
switch (json_last_error()) {
|
||||
case JSON_ERROR_DEPTH:
|
||||
return 'Maximum stack depth exceeded.';
|
||||
|
||||
case JSON_ERROR_STATE_MISMATCH:
|
||||
return 'Underflow or the modes mismatch.';
|
||||
|
||||
case JSON_ERROR_CTRL_CHAR:
|
||||
return 'Unexpected control character found.';
|
||||
|
||||
case JSON_ERROR_SYNTAX:
|
||||
return 'Syntax error, malformed JSON.';
|
||||
|
||||
case JSON_ERROR_UTF8:
|
||||
return 'Malformed UTF-8 characters, possibly incorrectly encoded.';
|
||||
|
||||
default:
|
||||
return 'Unknown error.';
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2015 Fabien Potencier
|
||||
Copyright (c) 2004-2016 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* ParameterBag is a container for key/value pairs.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ParameterBag implements \IteratorAggregate, \Countable
|
||||
{
|
||||
@@ -31,8 +29,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $parameters An array of parameters
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct(array $parameters = array())
|
||||
{
|
||||
@@ -43,8 +39,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* Returns the parameters.
|
||||
*
|
||||
* @return array An array of parameters
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
@@ -55,8 +49,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* Returns the parameter keys.
|
||||
*
|
||||
* @return array An array of parameter keys
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function keys()
|
||||
{
|
||||
@@ -67,8 +59,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* Replaces the current parameters by a new set.
|
||||
*
|
||||
* @param array $parameters An array of parameters
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function replace(array $parameters = array())
|
||||
{
|
||||
@@ -79,8 +69,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* Adds parameters.
|
||||
*
|
||||
* @param array $parameters An array of parameters
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function add(array $parameters = array())
|
||||
{
|
||||
@@ -90,63 +78,14 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
/**
|
||||
* Returns a parameter by name.
|
||||
*
|
||||
* @param string $path The key
|
||||
* @param string $key The key
|
||||
* @param mixed $default The default value if the parameter key does not exist
|
||||
* @param bool $deep If true, a path like foo[bar] will find deeper items
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function get($path, $default = null, $deep = false)
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (!$deep || false === $pos = strpos($path, '[')) {
|
||||
return array_key_exists($path, $this->parameters) ? $this->parameters[$path] : $default;
|
||||
}
|
||||
|
||||
$root = substr($path, 0, $pos);
|
||||
if (!array_key_exists($root, $this->parameters)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$value = $this->parameters[$root];
|
||||
$currentKey = null;
|
||||
for ($i = $pos, $c = strlen($path); $i < $c; ++$i) {
|
||||
$char = $path[$i];
|
||||
|
||||
if ('[' === $char) {
|
||||
if (null !== $currentKey) {
|
||||
throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "[" at position %d.', $i));
|
||||
}
|
||||
|
||||
$currentKey = '';
|
||||
} elseif (']' === $char) {
|
||||
if (null === $currentKey) {
|
||||
throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "]" at position %d.', $i));
|
||||
}
|
||||
|
||||
if (!is_array($value) || !array_key_exists($currentKey, $value)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$value = $value[$currentKey];
|
||||
$currentKey = null;
|
||||
} else {
|
||||
if (null === $currentKey) {
|
||||
throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "%s" at position %d.', $char, $i));
|
||||
}
|
||||
|
||||
$currentKey .= $char;
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $currentKey) {
|
||||
throw new \InvalidArgumentException(sprintf('Malformed path. Path must end with "]".'));
|
||||
}
|
||||
|
||||
return $value;
|
||||
return array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,8 +93,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
*
|
||||
* @param string $key The key
|
||||
* @param mixed $value The value
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
@@ -168,8 +105,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* @param string $key The key
|
||||
*
|
||||
* @return bool true if the parameter exists, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
@@ -180,8 +115,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* Removes a parameter.
|
||||
*
|
||||
* @param string $key The key
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
@@ -192,65 +125,53 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
* Returns the alphabetic characters of the parameter value.
|
||||
*
|
||||
* @param string $key The parameter key
|
||||
* @param mixed $default The default value if the parameter key does not exist
|
||||
* @param bool $deep If true, a path like foo[bar] will find deeper items
|
||||
* @param string $default The default value if the parameter key does not exist
|
||||
*
|
||||
* @return string The filtered value
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getAlpha($key, $default = '', $deep = false)
|
||||
public function getAlpha($key, $default = '')
|
||||
{
|
||||
return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default, $deep));
|
||||
return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the alphabetic characters and digits of the parameter value.
|
||||
*
|
||||
* @param string $key The parameter key
|
||||
* @param mixed $default The default value if the parameter key does not exist
|
||||
* @param bool $deep If true, a path like foo[bar] will find deeper items
|
||||
* @param string $default The default value if the parameter key does not exist
|
||||
*
|
||||
* @return string The filtered value
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getAlnum($key, $default = '', $deep = false)
|
||||
public function getAlnum($key, $default = '')
|
||||
{
|
||||
return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default, $deep));
|
||||
return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the digits of the parameter value.
|
||||
*
|
||||
* @param string $key The parameter key
|
||||
* @param mixed $default The default value if the parameter key does not exist
|
||||
* @param bool $deep If true, a path like foo[bar] will find deeper items
|
||||
* @param string $default The default value if the parameter key does not exist
|
||||
*
|
||||
* @return string The filtered value
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getDigits($key, $default = '', $deep = false)
|
||||
public function getDigits($key, $default = '')
|
||||
{
|
||||
// we need to remove - and + because they're allowed in the filter
|
||||
return str_replace(array('-', '+'), '', $this->filter($key, $default, $deep, FILTER_SANITIZE_NUMBER_INT));
|
||||
return str_replace(array('-', '+'), '', $this->filter($key, $default, FILTER_SANITIZE_NUMBER_INT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parameter value converted to integer.
|
||||
*
|
||||
* @param string $key The parameter key
|
||||
* @param mixed $default The default value if the parameter key does not exist
|
||||
* @param bool $deep If true, a path like foo[bar] will find deeper items
|
||||
* @param int $default The default value if the parameter key does not exist
|
||||
*
|
||||
* @return int The filtered value
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getInt($key, $default = 0, $deep = false)
|
||||
public function getInt($key, $default = 0)
|
||||
{
|
||||
return (int) $this->get($key, $default, $deep);
|
||||
return (int) $this->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,13 +179,12 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
*
|
||||
* @param string $key The parameter key
|
||||
* @param mixed $default The default value if the parameter key does not exist
|
||||
* @param bool $deep If true, a path like foo[bar] will find deeper items
|
||||
*
|
||||
* @return bool The filtered value
|
||||
*/
|
||||
public function getBoolean($key, $default = false, $deep = false)
|
||||
public function getBoolean($key, $default = false)
|
||||
{
|
||||
return $this->filter($key, $default, $deep, FILTER_VALIDATE_BOOLEAN);
|
||||
return $this->filter($key, $default, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +192,6 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
*
|
||||
* @param string $key Key.
|
||||
* @param mixed $default Default = null.
|
||||
* @param bool $deep Default = false.
|
||||
* @param int $filter FILTER_* constant.
|
||||
* @param mixed $options Filter options.
|
||||
*
|
||||
@@ -280,9 +199,9 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function filter($key, $default = null, $deep = false, $filter = FILTER_DEFAULT, $options = array())
|
||||
public function filter($key, $default = null, $filter = FILTER_DEFAULT, $options = array())
|
||||
{
|
||||
$value = $this->get($key, $default, $deep);
|
||||
$value = $this->get($key, $default);
|
||||
|
||||
// Always turn $options into an array - this allows filter_var option shortcuts.
|
||||
if (!is_array($options) && $options) {
|
14
vendor/symfony/http-foundation/README.md
vendored
Normal file
14
vendor/symfony/http-foundation/README.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
HttpFoundation Component
|
||||
========================
|
||||
|
||||
The HttpFoundation component defines an object-oriented layer for the HTTP
|
||||
specification.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/http_foundation/index.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* RedirectResponse represents an HTTP response doing a redirect.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class RedirectResponse extends Response
|
||||
{
|
||||
@@ -25,22 +23,17 @@ class RedirectResponse extends Response
|
||||
/**
|
||||
* Creates a redirect response so that it conforms to the rules defined for a redirect status code.
|
||||
*
|
||||
* @param string $url The URL to redirect to
|
||||
* @param string $url The URL to redirect to. The URL should be a full URL, with schema etc.,
|
||||
* but practically every browser redirects on paths only as well
|
||||
* @param int $status The status code (302 by default)
|
||||
* @param array $headers The headers (Location is always set to the given URL)
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc2616#section-10.3
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($url, $status = 302, $headers = array())
|
||||
{
|
||||
if (empty($url)) {
|
||||
throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
|
||||
}
|
||||
|
||||
parent::__construct('', $status, $headers);
|
||||
|
||||
$this->setTargetUrl($url);
|
@@ -25,11 +25,10 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
* * getUriForPath
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Request
|
||||
{
|
||||
const HEADER_FORWARDED = 'forwarded';
|
||||
const HEADER_CLIENT_IP = 'client_ip';
|
||||
const HEADER_CLIENT_HOST = 'client_host';
|
||||
const HEADER_CLIENT_PROTO = 'client_proto';
|
||||
@@ -46,6 +45,9 @@ class Request
|
||||
const METHOD_TRACE = 'TRACE';
|
||||
const METHOD_CONNECT = 'CONNECT';
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected static $trustedProxies = array();
|
||||
|
||||
/**
|
||||
@@ -62,10 +64,13 @@ class Request
|
||||
* Names for headers that can be trusted when
|
||||
* using trusted proxies.
|
||||
*
|
||||
* The default names are non-standard, but widely used
|
||||
* The FORWARDED header is the standard as of rfc7239.
|
||||
*
|
||||
* The other headers are non-standard, but widely used
|
||||
* by popular reverse proxies (like Apache mod_proxy or Amazon EC2).
|
||||
*/
|
||||
protected static $trustedHeaders = array(
|
||||
self::HEADER_FORWARDED => 'FORWARDED',
|
||||
self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR',
|
||||
self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST',
|
||||
self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO',
|
||||
@@ -78,8 +83,6 @@ class Request
|
||||
* Custom parameters.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\ParameterBag
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public $attributes;
|
||||
|
||||
@@ -87,8 +90,6 @@ class Request
|
||||
* Request body parameters ($_POST).
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\ParameterBag
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public $request;
|
||||
|
||||
@@ -96,8 +97,6 @@ class Request
|
||||
* Query string parameters ($_GET).
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\ParameterBag
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public $query;
|
||||
|
||||
@@ -105,8 +104,6 @@ class Request
|
||||
* Server and execution environment parameters ($_SERVER).
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\ServerBag
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public $server;
|
||||
|
||||
@@ -114,8 +111,6 @@ class Request
|
||||
* Uploaded files ($_FILES).
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\FileBag
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public $files;
|
||||
|
||||
@@ -123,8 +118,6 @@ class Request
|
||||
* Cookies ($_COOKIE).
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\ParameterBag
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public $cookies;
|
||||
|
||||
@@ -132,8 +125,6 @@ class Request
|
||||
* Headers (taken from the $_SERVER).
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\HeaderBag
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public $headers;
|
||||
|
||||
@@ -224,8 +215,6 @@ class Request
|
||||
* @param array $files The FILES parameters
|
||||
* @param array $server The SERVER parameters
|
||||
* @param string|resource $content The raw body data
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
|
||||
{
|
||||
@@ -244,8 +233,6 @@ class Request
|
||||
* @param array $files The FILES parameters
|
||||
* @param array $server The SERVER parameters
|
||||
* @param string|resource $content The raw body data
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
|
||||
{
|
||||
@@ -274,8 +261,6 @@ class Request
|
||||
* Creates a new request with values from PHP's super globals.
|
||||
*
|
||||
* @return Request A new request
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public static function createFromGlobals()
|
||||
{
|
||||
@@ -283,7 +268,7 @@ class Request
|
||||
// stores the Content-Type and Content-Length header values in
|
||||
// HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH fields.
|
||||
$server = $_SERVER;
|
||||
if ('cli-server' === php_sapi_name()) {
|
||||
if ('cli-server' === PHP_SAPI) {
|
||||
if (array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) {
|
||||
$server['CONTENT_LENGTH'] = $_SERVER['HTTP_CONTENT_LENGTH'];
|
||||
}
|
||||
@@ -319,8 +304,6 @@ class Request
|
||||
* @param string $content The raw body data
|
||||
*
|
||||
* @return Request A Request instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
|
||||
{
|
||||
@@ -328,7 +311,7 @@ class Request
|
||||
'SERVER_NAME' => 'localhost',
|
||||
'SERVER_PORT' => 80,
|
||||
'HTTP_HOST' => 'localhost',
|
||||
'HTTP_USER_AGENT' => 'Symfony/2.X',
|
||||
'HTTP_USER_AGENT' => 'Symfony/3.X',
|
||||
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
|
||||
'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
|
||||
@@ -439,8 +422,6 @@ class Request
|
||||
* @param array $server The SERVER parameters
|
||||
*
|
||||
* @return Request The duplicated request
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
|
||||
{
|
||||
@@ -527,8 +508,6 @@ class Request
|
||||
*
|
||||
* It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE.
|
||||
* $_FILES is never overridden, see rfc1867
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function overrideGlobals()
|
||||
{
|
||||
@@ -565,8 +544,6 @@ class Request
|
||||
* You should only list the reverse proxies that you manage directly.
|
||||
*
|
||||
* @param array $proxies A list of trusted proxies
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public static function setTrustedProxies(array $proxies)
|
||||
{
|
||||
@@ -723,37 +700,30 @@ class Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a "parameter" value.
|
||||
* Gets a "parameter" value from any bag.
|
||||
*
|
||||
* This method is mainly useful for libraries that want to provide some flexibility.
|
||||
* This method is mainly useful for libraries that want to provide some flexibility. If you don't need the
|
||||
* flexibility in controllers, it is better to explicitly get request parameters from the appropriate
|
||||
* public property instead (attributes, query, request).
|
||||
*
|
||||
* Order of precedence: GET, PATH, POST
|
||||
*
|
||||
* Avoid using this method in controllers:
|
||||
*
|
||||
* * slow
|
||||
* * prefer to get from a "named" source
|
||||
*
|
||||
* It is better to explicitly get request parameters from the appropriate
|
||||
* public property instead (query, attributes, request).
|
||||
* Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY
|
||||
*
|
||||
* @param string $key the key
|
||||
* @param mixed $default the default value
|
||||
* @param bool $deep is parameter deep in multidimensional array
|
||||
* @param mixed $default the default value if the parameter key does not exist
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null, $deep = false)
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if ($this !== $result = $this->query->get($key, $this, $deep)) {
|
||||
if ($this !== $result = $this->attributes->get($key, $this)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ($this !== $result = $this->attributes->get($key, $this, $deep)) {
|
||||
if ($this !== $result = $this->query->get($key, $this)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ($this !== $result = $this->request->get($key, $this, $deep)) {
|
||||
if ($this !== $result = $this->request->get($key, $this)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -764,8 +734,6 @@ class Request
|
||||
* Gets the Session.
|
||||
*
|
||||
* @return SessionInterface|null The session
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getSession()
|
||||
{
|
||||
@@ -777,8 +745,6 @@ class Request
|
||||
* previous requests.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function hasPreviousSession()
|
||||
{
|
||||
@@ -794,8 +760,6 @@ class Request
|
||||
* is associated with a Session instance.
|
||||
*
|
||||
* @return bool true when the Request contains a Session object, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function hasSession()
|
||||
{
|
||||
@@ -806,8 +770,6 @@ class Request
|
||||
* Sets the Session.
|
||||
*
|
||||
* @param SessionInterface $session The Session
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setSession(SessionInterface $session)
|
||||
{
|
||||
@@ -829,35 +791,48 @@ class Request
|
||||
*/
|
||||
public function getClientIps()
|
||||
{
|
||||
$clientIps = array();
|
||||
$ip = $this->server->get('REMOTE_ADDR');
|
||||
|
||||
if (!$this->isFromTrustedProxy()) {
|
||||
return array($ip);
|
||||
}
|
||||
|
||||
if (!self::$trustedHeaders[self::HEADER_CLIENT_IP] || !$this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
|
||||
return array($ip);
|
||||
if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
|
||||
$forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
|
||||
preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
|
||||
$clientIps = $matches[3];
|
||||
} elseif (self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
|
||||
$clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
|
||||
}
|
||||
|
||||
$clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
|
||||
$clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
|
||||
$firstTrustedIp = null;
|
||||
|
||||
$ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies
|
||||
|
||||
// Eliminate all IPs from the forwarded IP chain which are trusted proxies
|
||||
foreach ($clientIps as $key => $clientIp) {
|
||||
// Remove port on IPv4 address (unfortunately, it does happen)
|
||||
// Remove port (unfortunately, it does happen)
|
||||
if (preg_match('{((?:\d+\.){3}\d+)\:\d+}', $clientIp, $match)) {
|
||||
$clientIps[$key] = $clientIp = $match[1];
|
||||
}
|
||||
|
||||
if (!filter_var($clientIp, FILTER_VALIDATE_IP)) {
|
||||
unset($clientIps[$key]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
|
||||
unset($clientIps[$key]);
|
||||
|
||||
// Fallback to this when the client IP falls into the range of trusted proxies
|
||||
if (null === $firstTrustedIp) {
|
||||
$firstTrustedIp = $clientIp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now the IP chain contains only untrusted proxies and the client IP
|
||||
return $clientIps ? array_reverse($clientIps) : array($ip);
|
||||
return $clientIps ? array_reverse($clientIps) : array($firstTrustedIp);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -877,8 +852,6 @@ class Request
|
||||
*
|
||||
* @see getClientIps()
|
||||
* @see http://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getClientIp()
|
||||
{
|
||||
@@ -891,8 +864,6 @@ class Request
|
||||
* Returns current script name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getScriptName()
|
||||
{
|
||||
@@ -912,8 +883,6 @@ class Request
|
||||
* * http://localhost/mysite/about?var=1 returns '/about'
|
||||
*
|
||||
* @return string The raw path (i.e. not urldecoded)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getPathInfo()
|
||||
{
|
||||
@@ -935,8 +904,6 @@ class Request
|
||||
* * http://localhost/we%20b/index.php returns '/we%20b'
|
||||
*
|
||||
* @return string The raw path (i.e. not urldecoded)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getBasePath()
|
||||
{
|
||||
@@ -956,8 +923,6 @@ class Request
|
||||
* script filename (e.g. index.php) if one exists.
|
||||
*
|
||||
* @return string The raw URL (i.e. not urldecoded)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getBaseUrl()
|
||||
{
|
||||
@@ -972,8 +937,6 @@ class Request
|
||||
* Gets the request's scheme.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getScheme()
|
||||
{
|
||||
@@ -992,8 +955,6 @@ class Request
|
||||
* configure it via "setTrustedHeaderName()" with the "client-port" key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getPort()
|
||||
{
|
||||
@@ -1067,8 +1028,6 @@ class Request
|
||||
* The port name will be appended to the host if it's non-standard.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getHttpHost()
|
||||
{
|
||||
@@ -1086,8 +1045,6 @@ class Request
|
||||
* Returns the requested URI (path and query string).
|
||||
*
|
||||
* @return string The raw URI (i.e. not URI decoded)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getRequestUri()
|
||||
{
|
||||
@@ -1117,8 +1074,6 @@ class Request
|
||||
* @return string A normalized URI (URL) for the Request
|
||||
*
|
||||
* @see getQueryString()
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getUri()
|
||||
{
|
||||
@@ -1135,14 +1090,67 @@ class Request
|
||||
* @param string $path A path to use instead of the current one
|
||||
*
|
||||
* @return string The normalized URI for the path
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getUriForPath($path)
|
||||
{
|
||||
return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path as relative reference from the current Request path.
|
||||
*
|
||||
* Only the URIs path component (no schema, host etc.) is relevant and must be given.
|
||||
* Both paths must be absolute and not contain relative parts.
|
||||
* Relative URLs from one resource to another are useful when generating self-contained downloadable document archives.
|
||||
* Furthermore, they can be used to reduce the link size in documents.
|
||||
*
|
||||
* Example target paths, given a base path of "/a/b/c/d":
|
||||
* - "/a/b/c/d" -> ""
|
||||
* - "/a/b/c/" -> "./"
|
||||
* - "/a/b/" -> "../"
|
||||
* - "/a/b/c/other" -> "other"
|
||||
* - "/a/x/y" -> "../../x/y"
|
||||
*
|
||||
* @param string $path The target path
|
||||
*
|
||||
* @return string The relative target path
|
||||
*/
|
||||
public function getRelativeUriForPath($path)
|
||||
{
|
||||
// be sure that we are dealing with an absolute path
|
||||
if (!isset($path[0]) || '/' !== $path[0]) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
if ($path === $basePath = $this->getPathInfo()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath);
|
||||
$targetDirs = explode('/', isset($path[0]) && '/' === $path[0] ? substr($path, 1) : $path);
|
||||
array_pop($sourceDirs);
|
||||
$targetFile = array_pop($targetDirs);
|
||||
|
||||
foreach ($sourceDirs as $i => $dir) {
|
||||
if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) {
|
||||
unset($sourceDirs[$i], $targetDirs[$i]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$targetDirs[] = $targetFile;
|
||||
$path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs);
|
||||
|
||||
// A reference to the same base directory or an empty subdirectory must be prefixed with "./".
|
||||
// This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
|
||||
// as the first segment of a relative-path reference, as it would be mistaken for a scheme name
|
||||
// (see http://tools.ietf.org/html/rfc3986#section-4.2).
|
||||
return !isset($path[0]) || '/' === $path[0]
|
||||
|| false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos)
|
||||
? "./$path" : $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the normalized query string for the Request.
|
||||
*
|
||||
@@ -1150,8 +1158,6 @@ class Request
|
||||
* and have consistent escaping.
|
||||
*
|
||||
* @return string|null A normalized query string for the Request
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getQueryString()
|
||||
{
|
||||
@@ -1163,7 +1169,7 @@ class Request
|
||||
/**
|
||||
* Checks whether the request is secure or not.
|
||||
*
|
||||
* This method can read the client port from the "X-Forwarded-Proto" header
|
||||
* This method can read the client protocol from the "X-Forwarded-Proto" header
|
||||
* when trusted proxies were set via "setTrustedProxies()".
|
||||
*
|
||||
* The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
|
||||
@@ -1173,8 +1179,6 @@ class Request
|
||||
* the "client-proto" key.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isSecure()
|
||||
{
|
||||
@@ -1190,7 +1194,7 @@ class Request
|
||||
/**
|
||||
* Returns the host name.
|
||||
*
|
||||
* This method can read the client port from the "X-Forwarded-Host" header
|
||||
* This method can read the client host name from the "X-Forwarded-Host" header
|
||||
* when trusted proxies were set via "setTrustedProxies()".
|
||||
*
|
||||
* The "X-Forwarded-Host" header must contain the client host name.
|
||||
@@ -1201,8 +1205,6 @@ class Request
|
||||
* @return string
|
||||
*
|
||||
* @throws \UnexpectedValueException when the host name is invalid
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getHost()
|
||||
{
|
||||
@@ -1252,8 +1254,6 @@ class Request
|
||||
* Sets the request method.
|
||||
*
|
||||
* @param string $method
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setMethod($method)
|
||||
{
|
||||
@@ -1274,8 +1274,6 @@ class Request
|
||||
*
|
||||
* @return string The request method
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @see getRealMethod()
|
||||
*/
|
||||
public function getMethod()
|
||||
@@ -1313,8 +1311,6 @@ class Request
|
||||
* @param string $format The format
|
||||
*
|
||||
* @return string The associated mime type (null if not found)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getMimeType($format)
|
||||
{
|
||||
@@ -1331,13 +1327,12 @@ class Request
|
||||
* @param string $mimeType The associated mime type
|
||||
*
|
||||
* @return string|null The format (null if not found)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getFormat($mimeType)
|
||||
{
|
||||
$canonicalMimeType = null;
|
||||
if (false !== $pos = strpos($mimeType, ';')) {
|
||||
$mimeType = substr($mimeType, 0, $pos);
|
||||
$canonicalMimeType = substr($mimeType, 0, $pos);
|
||||
}
|
||||
|
||||
if (null === static::$formats) {
|
||||
@@ -1348,6 +1343,9 @@ class Request
|
||||
if (in_array($mimeType, (array) $mimeTypes)) {
|
||||
return $format;
|
||||
}
|
||||
if (null !== $canonicalMimeType && in_array($canonicalMimeType, (array) $mimeTypes)) {
|
||||
return $format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1356,8 +1354,6 @@ class Request
|
||||
*
|
||||
* @param string $format The format
|
||||
* @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setFormat($format, $mimeTypes)
|
||||
{
|
||||
@@ -1374,19 +1370,17 @@ class Request
|
||||
* Here is the process to determine the format:
|
||||
*
|
||||
* * format defined by the user (with setRequestFormat())
|
||||
* * _format request parameter
|
||||
* * _format request attribute
|
||||
* * $default
|
||||
*
|
||||
* @param string $default The default format
|
||||
*
|
||||
* @return string The request format
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getRequestFormat($default = 'html')
|
||||
{
|
||||
if (null === $this->format) {
|
||||
$this->format = $this->get('_format', $default);
|
||||
$this->format = $this->attributes->get('_format', $default);
|
||||
}
|
||||
|
||||
return $this->format;
|
||||
@@ -1396,8 +1390,6 @@ class Request
|
||||
* Sets the request format.
|
||||
*
|
||||
* @param string $format The request format.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setRequestFormat($format)
|
||||
{
|
||||
@@ -1408,8 +1400,6 @@ class Request
|
||||
* Gets the format associated with the request.
|
||||
*
|
||||
* @return string|null The format (null if no content type is present)
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
@@ -1420,8 +1410,6 @@ class Request
|
||||
* Sets the default locale.
|
||||
*
|
||||
* @param string $locale
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setDefaultLocale($locale)
|
||||
{
|
||||
@@ -1446,8 +1434,6 @@ class Request
|
||||
* Sets the locale.
|
||||
*
|
||||
* @param string $locale
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setLocale($locale)
|
||||
{
|
||||
@@ -1480,8 +1466,6 @@ class Request
|
||||
* Checks whether the method is safe or not.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isMethodSafe()
|
||||
{
|
||||
@@ -1513,7 +1497,7 @@ class Request
|
||||
|
||||
// Content passed in parameter (test)
|
||||
if (is_string($this->content)) {
|
||||
$resource = fopen('php://temp','r+');
|
||||
$resource = fopen('php://temp', 'r+');
|
||||
fwrite($resource, $this->content);
|
||||
rewind($resource);
|
||||
|
||||
@@ -1562,8 +1546,6 @@ class Request
|
||||
* @param array $locales An array of ordered available locales
|
||||
*
|
||||
* @return string|null The preferred locale
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getPreferredLanguage(array $locales = null)
|
||||
{
|
||||
@@ -1597,8 +1579,6 @@ class Request
|
||||
* Gets a list of languages acceptable by the client browser.
|
||||
*
|
||||
* @return array Languages ordered in the user browser preferences
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getLanguages()
|
||||
{
|
||||
@@ -1639,8 +1619,6 @@ class Request
|
||||
* Gets a list of charsets acceptable by the client browser.
|
||||
*
|
||||
* @return array List of charsets in preferable order
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getCharsets()
|
||||
{
|
||||
@@ -1669,8 +1647,6 @@ class Request
|
||||
* Gets a list of content types acceptable by the client browser.
|
||||
*
|
||||
* @return array List of content types in preferable order
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getAcceptableContentTypes()
|
||||
{
|
||||
@@ -1690,8 +1666,6 @@ class Request
|
||||
* @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
|
||||
*
|
||||
* @return bool true if the request is an XMLHttpRequest, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isXmlHttpRequest()
|
||||
{
|
||||
@@ -1788,9 +1762,9 @@ class Request
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(dirname($baseUrl), '/').'/')) {
|
||||
if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(dirname($baseUrl), '/'.DIRECTORY_SEPARATOR).'/')) {
|
||||
// directory portion of $baseUrl matches
|
||||
return rtrim($prefix, '/');
|
||||
return rtrim($prefix, '/'.DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
$truncatedRequestUri = $requestUri;
|
||||
@@ -1811,7 +1785,7 @@ class Request
|
||||
$baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
|
||||
}
|
||||
|
||||
return rtrim($baseUrl, '/');
|
||||
return rtrim($baseUrl, '/'.DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1853,8 +1827,6 @@ class Request
|
||||
return '/';
|
||||
}
|
||||
|
||||
$pathInfo = '/';
|
||||
|
||||
// Remove the query string from REQUEST_URI
|
||||
if ($pos = strpos($requestUri, '?')) {
|
||||
$requestUri = substr($requestUri, 0, $pos);
|
||||
@@ -1937,7 +1909,7 @@ class Request
|
||||
if (self::$requestFactory) {
|
||||
$request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);
|
||||
|
||||
if (!$request instanceof Request) {
|
||||
if (!$request instanceof self) {
|
||||
throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');
|
||||
}
|
||||
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* RequestMatcher compares a pre-defined set of checks against a Request instance.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class RequestMatcher implements RequestMatcherInterface
|
||||
{
|
||||
@@ -144,8 +142,6 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function matches(Request $request)
|
||||
{
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* RequestMatcherInterface is an interface for strategies to match a Request.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
interface RequestMatcherInterface
|
||||
{
|
||||
@@ -26,8 +24,6 @@ interface RequestMatcherInterface
|
||||
* @param Request $request The request to check for a match
|
||||
*
|
||||
* @return bool true if the request matches, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function matches(Request $request);
|
||||
}
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* Response represents an HTTP response.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Response
|
||||
{
|
||||
@@ -61,6 +59,7 @@ class Response
|
||||
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
|
||||
const HTTP_EXPECTATION_FAILED = 417;
|
||||
const HTTP_I_AM_A_TEAPOT = 418; // RFC2324
|
||||
const HTTP_MISDIRECTED_REQUEST = 421; // RFC7540
|
||||
const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918
|
||||
const HTTP_LOCKED = 423; // RFC4918
|
||||
const HTTP_FAILED_DEPENDENCY = 424; // RFC4918
|
||||
@@ -69,6 +68,7 @@ class Response
|
||||
const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585
|
||||
const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585
|
||||
const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585
|
||||
const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
|
||||
const HTTP_INTERNAL_SERVER_ERROR = 500;
|
||||
const HTTP_NOT_IMPLEMENTED = 501;
|
||||
const HTTP_BAD_GATEWAY = 502;
|
||||
@@ -116,7 +116,7 @@ class Response
|
||||
*
|
||||
* The list of codes is complete according to the
|
||||
* {@link http://www.iana.org/assignments/http-status-codes/ Hypertext Transfer Protocol (HTTP) Status Code Registry}
|
||||
* (last updated 2012-02-13).
|
||||
* (last updated 2016-03-01).
|
||||
*
|
||||
* Unless otherwise noted, the status code is defined in RFC2616.
|
||||
*
|
||||
@@ -142,7 +142,6 @@ class Response
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
306 => 'Reserved',
|
||||
307 => 'Temporary Redirect',
|
||||
308 => 'Permanent Redirect', // RFC7238
|
||||
400 => 'Bad Request',
|
||||
@@ -158,12 +157,13 @@ class Response
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'Request-URI Too Long',
|
||||
413 => 'Payload Too Large',
|
||||
414 => 'URI Too Long',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Requested Range Not Satisfiable',
|
||||
416 => 'Range Not Satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
418 => 'I\'m a teapot', // RFC2324
|
||||
421 => 'Misdirected Request', // RFC7540
|
||||
422 => 'Unprocessable Entity', // RFC4918
|
||||
423 => 'Locked', // RFC4918
|
||||
424 => 'Failed Dependency', // RFC4918
|
||||
@@ -172,6 +172,7 @@ class Response
|
||||
428 => 'Precondition Required', // RFC6585
|
||||
429 => 'Too Many Requests', // RFC6585
|
||||
431 => 'Request Header Fields Too Large', // RFC6585
|
||||
451 => 'Unavailable For Legal Reasons', // RFC7725
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
@@ -193,8 +194,6 @@ class Response
|
||||
* @param array $headers An array of response headers
|
||||
*
|
||||
* @throws \InvalidArgumentException When the HTTP status code is not valid
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($content = '', $status = 200, $headers = array())
|
||||
{
|
||||
@@ -202,9 +201,6 @@ class Response
|
||||
$this->setContent($content);
|
||||
$this->setStatusCode($status);
|
||||
$this->setProtocolVersion('1.0');
|
||||
if (!$this->headers->has('Date')) {
|
||||
$this->setDate(new \DateTime(null, new \DateTimeZone('UTC')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,8 +329,9 @@ class Response
|
||||
return $this;
|
||||
}
|
||||
|
||||
// status
|
||||
header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);
|
||||
if (!$this->headers->has('Date')) {
|
||||
$this->setDate(\DateTime::createFromFormat('U', time()));
|
||||
}
|
||||
|
||||
// headers
|
||||
foreach ($this->headers->allPreserveCase() as $name => $values) {
|
||||
@@ -343,6 +340,9 @@ class Response
|
||||
}
|
||||
}
|
||||
|
||||
// status
|
||||
header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);
|
||||
|
||||
// cookies
|
||||
foreach ($this->headers->getCookies() as $cookie) {
|
||||
setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
|
||||
@@ -367,8 +367,6 @@ class Response
|
||||
* Sends HTTP headers and content.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
@@ -394,8 +392,6 @@ class Response
|
||||
* @return Response
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setContent($content)
|
||||
{
|
||||
@@ -412,8 +408,6 @@ class Response
|
||||
* Gets the current response content.
|
||||
*
|
||||
* @return string Content
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
@@ -426,8 +420,6 @@ class Response
|
||||
* @param string $version The HTTP protocol version
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setProtocolVersion($version)
|
||||
{
|
||||
@@ -440,8 +432,6 @@ class Response
|
||||
* Gets the HTTP protocol version.
|
||||
*
|
||||
* @return string The HTTP protocol version
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getProtocolVersion()
|
||||
{
|
||||
@@ -460,8 +450,6 @@ class Response
|
||||
* @return Response
|
||||
*
|
||||
* @throws \InvalidArgumentException When the HTTP status code is not valid
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setStatusCode($code, $text = null)
|
||||
{
|
||||
@@ -471,7 +459,7 @@ class Response
|
||||
}
|
||||
|
||||
if (null === $text) {
|
||||
$this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : '';
|
||||
$this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : 'unknown status';
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -491,8 +479,6 @@ class Response
|
||||
* Retrieves the status code for the current web response.
|
||||
*
|
||||
* @return int Status code
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
@@ -505,8 +491,6 @@ class Response
|
||||
* @param string $charset Character set
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setCharset($charset)
|
||||
{
|
||||
@@ -519,8 +503,6 @@ class Response
|
||||
* Retrieves the response charset.
|
||||
*
|
||||
* @return string Character set
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getCharset()
|
||||
{
|
||||
@@ -537,8 +519,6 @@ class Response
|
||||
* validator (Last-Modified, ETag) are considered uncacheable.
|
||||
*
|
||||
* @return bool true if the response is worth caching, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isCacheable()
|
||||
{
|
||||
@@ -561,8 +541,6 @@ class Response
|
||||
* indicator or Expires header and the calculated age is less than the freshness lifetime.
|
||||
*
|
||||
* @return bool true if the response is fresh, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isFresh()
|
||||
{
|
||||
@@ -574,8 +552,6 @@ class Response
|
||||
* the response with the origin server using a conditional GET request.
|
||||
*
|
||||
* @return bool true if the response is validateable, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isValidateable()
|
||||
{
|
||||
@@ -588,8 +564,6 @@ class Response
|
||||
* It makes the response ineligible for serving other clients.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setPrivate()
|
||||
{
|
||||
@@ -605,8 +579,6 @@ class Response
|
||||
* It makes the response eligible for serving other clients.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setPublic()
|
||||
{
|
||||
@@ -625,12 +597,10 @@ class Response
|
||||
* greater than the value provided by the origin.
|
||||
*
|
||||
* @return bool true if the response must be revalidated by a cache, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function mustRevalidate()
|
||||
{
|
||||
return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->has('proxy-revalidate');
|
||||
return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,12 +609,14 @@ class Response
|
||||
* @return \DateTime A \DateTime instance
|
||||
*
|
||||
* @throws \RuntimeException When the header is not parseable
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->headers->getDate('Date', new \DateTime());
|
||||
if (!$this->headers->has('Date')) {
|
||||
$this->setDate(\DateTime::createFromFormat('U', time()));
|
||||
}
|
||||
|
||||
return $this->headers->getDate('Date');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -653,8 +625,6 @@ class Response
|
||||
* @param \DateTime $date A \DateTime instance
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setDate(\DateTime $date)
|
||||
{
|
||||
@@ -682,8 +652,6 @@ class Response
|
||||
* Marks the response stale by setting the Age header to be equal to the maximum age of the response.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function expire()
|
||||
{
|
||||
@@ -698,8 +666,6 @@ class Response
|
||||
* Returns the value of the Expires header as a DateTime instance.
|
||||
*
|
||||
* @return \DateTime|null A DateTime instance or null if the header does not exist
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getExpires()
|
||||
{
|
||||
@@ -719,8 +685,6 @@ class Response
|
||||
* @param \DateTime|null $date A \DateTime instance or null to remove the header
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setExpires(\DateTime $date = null)
|
||||
{
|
||||
@@ -743,8 +707,6 @@ class Response
|
||||
* back on an expires header. It returns null when no maximum age can be established.
|
||||
*
|
||||
* @return int|null Number of seconds
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getMaxAge()
|
||||
{
|
||||
@@ -769,8 +731,6 @@ class Response
|
||||
* @param int $value Number of seconds
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setMaxAge($value)
|
||||
{
|
||||
@@ -787,8 +747,6 @@ class Response
|
||||
* @param int $value Number of seconds
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setSharedMaxAge($value)
|
||||
{
|
||||
@@ -807,8 +765,6 @@ class Response
|
||||
* revalidating with the origin.
|
||||
*
|
||||
* @return int|null The TTL in seconds
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getTtl()
|
||||
{
|
||||
@@ -825,8 +781,6 @@ class Response
|
||||
* @param int $seconds Number of seconds
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setTtl($seconds)
|
||||
{
|
||||
@@ -843,8 +797,6 @@ class Response
|
||||
* @param int $seconds Number of seconds
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setClientTtl($seconds)
|
||||
{
|
||||
@@ -859,8 +811,6 @@ class Response
|
||||
* @return \DateTime|null A DateTime instance or null if the header does not exist
|
||||
*
|
||||
* @throws \RuntimeException When the HTTP header is not parseable
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getLastModified()
|
||||
{
|
||||
@@ -875,8 +825,6 @@ class Response
|
||||
* @param \DateTime|null $date A \DateTime instance or null to remove the header
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setLastModified(\DateTime $date = null)
|
||||
{
|
||||
@@ -895,8 +843,6 @@ class Response
|
||||
* Returns the literal value of the ETag HTTP header.
|
||||
*
|
||||
* @return string|null The ETag HTTP header or null if it does not exist
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getEtag()
|
||||
{
|
||||
@@ -910,8 +856,6 @@ class Response
|
||||
* @param bool $weak Whether you want a weak ETag or not
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setEtag($etag = null, $weak = false)
|
||||
{
|
||||
@@ -938,8 +882,6 @@ class Response
|
||||
* @return Response
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setCache(array $options)
|
||||
{
|
||||
@@ -991,8 +933,6 @@ class Response
|
||||
* @return Response
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc2616#section-10.3.5
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setNotModified()
|
||||
{
|
||||
@@ -1011,8 +951,6 @@ class Response
|
||||
* Returns true if the response includes a Vary header.
|
||||
*
|
||||
* @return bool true if the response includes a Vary header, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function hasVary()
|
||||
{
|
||||
@@ -1023,8 +961,6 @@ class Response
|
||||
* Returns an array of header names given in the Vary header.
|
||||
*
|
||||
* @return array An array of Vary names
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getVary()
|
||||
{
|
||||
@@ -1044,11 +980,9 @@ class Response
|
||||
* Sets the Vary header.
|
||||
*
|
||||
* @param string|array $headers
|
||||
* @param bool $replace Whether to replace the actual value of not (true by default)
|
||||
* @param bool $replace Whether to replace the actual value or not (true by default)
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setVary($headers, $replace = true)
|
||||
{
|
||||
@@ -1067,8 +1001,6 @@ class Response
|
||||
* @param Request $request A Request instance
|
||||
*
|
||||
* @return bool true if the Response validators match the Request, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isNotModified(Request $request)
|
||||
{
|
||||
@@ -1095,13 +1027,12 @@ class Response
|
||||
return $notModified;
|
||||
}
|
||||
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
/**
|
||||
* Is response invalid?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
*/
|
||||
public function isInvalid()
|
||||
{
|
||||
@@ -1112,8 +1043,6 @@ class Response
|
||||
* Is response informative?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isInformational()
|
||||
{
|
||||
@@ -1124,8 +1053,6 @@ class Response
|
||||
* Is response successful?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isSuccessful()
|
||||
{
|
||||
@@ -1136,8 +1063,6 @@ class Response
|
||||
* Is the response a redirect?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isRedirection()
|
||||
{
|
||||
@@ -1148,8 +1073,6 @@ class Response
|
||||
* Is there a client error?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isClientError()
|
||||
{
|
||||
@@ -1160,8 +1083,6 @@ class Response
|
||||
* Was there a server side error?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isServerError()
|
||||
{
|
||||
@@ -1172,8 +1093,6 @@ class Response
|
||||
* Is the response OK?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isOk()
|
||||
{
|
||||
@@ -1184,8 +1103,6 @@ class Response
|
||||
* Is the response forbidden?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isForbidden()
|
||||
{
|
||||
@@ -1196,8 +1113,6 @@ class Response
|
||||
* Is the response a not found error?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isNotFound()
|
||||
{
|
||||
@@ -1210,8 +1125,6 @@ class Response
|
||||
* @param string $location
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isRedirect($location = null)
|
||||
{
|
||||
@@ -1222,8 +1135,6 @@ class Response
|
||||
* Is the response empty?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
@@ -1242,6 +1153,7 @@ class Response
|
||||
{
|
||||
$status = ob_get_status(true);
|
||||
$level = count($status);
|
||||
// PHP_OUTPUT_HANDLER_* are not defined on HHVM 3.3
|
||||
$flags = defined('PHP_OUTPUT_HANDLER_REMOVABLE') ? PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE) : -1;
|
||||
|
||||
while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || $flags === ($s['flags'] & $flags) : $s['del'])) {
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* ResponseHeaderBag is a container for Response HTTP headers.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ResponseHeaderBag extends HeaderBag
|
||||
{
|
||||
@@ -45,8 +43,6 @@ class ResponseHeaderBag extends HeaderBag
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $headers An array of HTTP headers
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct(array $headers = array())
|
||||
{
|
||||
@@ -84,8 +80,6 @@ class ResponseHeaderBag extends HeaderBag
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function replace(array $headers = array())
|
||||
{
|
||||
@@ -100,14 +94,12 @@ class ResponseHeaderBag extends HeaderBag
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function set($key, $values, $replace = true)
|
||||
{
|
||||
parent::set($key, $values, $replace);
|
||||
|
||||
$uniqueKey = strtr(strtolower($key), '_', '-');
|
||||
$uniqueKey = str_replace('_', '-', strtolower($key));
|
||||
$this->headerNames[$uniqueKey] = $key;
|
||||
|
||||
// ensure the cache-control header has sensible defaults
|
||||
@@ -121,14 +113,12 @@ class ResponseHeaderBag extends HeaderBag
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
parent::remove($key);
|
||||
|
||||
$uniqueKey = strtr(strtolower($key), '_', '-');
|
||||
$uniqueKey = str_replace('_', '-', strtolower($key));
|
||||
unset($this->headerNames[$uniqueKey]);
|
||||
|
||||
if ('cache-control' === $uniqueKey) {
|
||||
@@ -156,8 +146,6 @@ class ResponseHeaderBag extends HeaderBag
|
||||
* Sets a cookie.
|
||||
*
|
||||
* @param Cookie $cookie
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setCookie(Cookie $cookie)
|
||||
{
|
||||
@@ -170,8 +158,6 @@ class ResponseHeaderBag extends HeaderBag
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function removeCookie($name, $path = '/', $domain = null)
|
||||
{
|
||||
@@ -195,11 +181,9 @@ class ResponseHeaderBag extends HeaderBag
|
||||
*
|
||||
* @param string $format
|
||||
*
|
||||
* @throws \InvalidArgumentException When the $format is invalid
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @api
|
||||
* @throws \InvalidArgumentException When the $format is invalid
|
||||
*/
|
||||
public function getCookies($format = self::COOKIES_FLAT)
|
||||
{
|
||||
@@ -231,8 +215,6 @@ class ResponseHeaderBag extends HeaderBag
|
||||
* @param string $domain
|
||||
* @param bool $secure
|
||||
* @param bool $httpOnly
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function clearCookie($name, $path = '/', $domain = null, $secure = false, $httpOnly = true)
|
||||
{
|
@@ -86,6 +86,10 @@ class ServerBag extends ParameterBag
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($headers['AUTHORIZATION'])) {
|
||||
return $headers;
|
||||
}
|
||||
|
||||
// PHP_AUTH_USER/PHP_AUTH_PW
|
||||
if (isset($headers['PHP_AUTH_USER'])) {
|
||||
$headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']);
|
@@ -14,11 +14,9 @@ namespace Symfony\Component\HttpFoundation\Session\Flash;
|
||||
/**
|
||||
* FlashBag flash message container.
|
||||
*
|
||||
* \IteratorAggregate implementation is deprecated and will be removed in 3.0.
|
||||
*
|
||||
* @author Drak <drak@zikula.org>
|
||||
*/
|
||||
class FlashBag implements FlashBagInterface, \IteratorAggregate
|
||||
class FlashBag implements FlashBagInterface
|
||||
{
|
||||
private $name = 'flashes';
|
||||
|
||||
@@ -165,16 +163,4 @@ class FlashBag implements FlashBagInterface, \IteratorAggregate
|
||||
{
|
||||
return $this->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for flashes.
|
||||
*
|
||||
* @deprecated Will be removed in 3.0.
|
||||
*
|
||||
* @return \ArrayIterator An \ArrayIterator instance
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->all());
|
||||
}
|
||||
}
|
@@ -23,8 +23,6 @@ use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Drak <drak@zikula.org>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
{
|
@@ -26,8 +26,6 @@ interface SessionInterface
|
||||
* @return bool True if session started.
|
||||
*
|
||||
* @throws \RuntimeException If session fails to start.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function start();
|
||||
|
||||
@@ -35,8 +33,6 @@ interface SessionInterface
|
||||
* Returns the session ID.
|
||||
*
|
||||
* @return string The session ID.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
@@ -44,8 +40,6 @@ interface SessionInterface
|
||||
* Sets the session ID.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setId($id);
|
||||
|
||||
@@ -53,8 +47,6 @@ interface SessionInterface
|
||||
* Returns the session name.
|
||||
*
|
||||
* @return mixed The session name.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
@@ -62,8 +54,6 @@ interface SessionInterface
|
||||
* Sets the session name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setName($name);
|
||||
|
||||
@@ -79,8 +69,6 @@ interface SessionInterface
|
||||
* not a Unix timestamp.
|
||||
*
|
||||
* @return bool True if session invalidated, false if error.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function invalidate($lifetime = null);
|
||||
|
||||
@@ -95,8 +83,6 @@ interface SessionInterface
|
||||
* not a Unix timestamp.
|
||||
*
|
||||
* @return bool True if session migrated, false if error.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function migrate($destroy = false, $lifetime = null);
|
||||
|
||||
@@ -115,8 +101,6 @@ interface SessionInterface
|
||||
* @param string $name The attribute name
|
||||
*
|
||||
* @return bool true if the attribute is defined, false otherwise
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function has($name);
|
||||
|
||||
@@ -127,8 +111,6 @@ interface SessionInterface
|
||||
* @param mixed $default The default value if not found.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function get($name, $default = null);
|
||||
|
||||
@@ -137,8 +119,6 @@ interface SessionInterface
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function set($name, $value);
|
||||
|
||||
@@ -146,8 +126,6 @@ interface SessionInterface
|
||||
* Returns attributes.
|
||||
*
|
||||
* @return array Attributes
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function all();
|
||||
|
||||
@@ -164,15 +142,11 @@ interface SessionInterface
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed The removed value or null when it does not exist
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function remove($name);
|
||||
|
||||
/**
|
||||
* Clears all attributes.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function clear();
|
||||
|
@@ -108,7 +108,7 @@ class MemcacheSessionHandler implements \SessionHandlerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Memcache instance
|
||||
* Return a Memcache instance.
|
||||
*
|
||||
* @return \Memcache
|
||||
*/
|
@@ -114,7 +114,7 @@ class MemcachedSessionHandler implements \SessionHandlerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Memcached instance
|
||||
* Return a Memcached instance.
|
||||
*
|
||||
* @return \Memcached
|
||||
*/
|
@@ -177,7 +177,7 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Mongo instance
|
||||
* Return a Mongo instance.
|
||||
*
|
||||
* @return \Mongo
|
||||
*/
|
@@ -48,8 +48,8 @@ class NativeFileSessionHandler extends NativeSessionHandler
|
||||
$baseDir = ltrim(strrchr($savePath, ';'), ';');
|
||||
}
|
||||
|
||||
if ($baseDir && !is_dir($baseDir)) {
|
||||
mkdir($baseDir, 0777, true);
|
||||
if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) {
|
||||
throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $baseDir));
|
||||
}
|
||||
|
||||
ini_set('session.save_path', $savePath);
|
@@ -11,14 +11,11 @@
|
||||
|
||||
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
||||
|
||||
// Adds SessionHandler functionality if available.
|
||||
// @see http://php.net/sessionhandler
|
||||
if (PHP_VERSION_ID >= 50400) {
|
||||
class NativeSessionHandler extends \SessionHandler
|
||||
{
|
||||
}
|
||||
} else {
|
||||
class NativeSessionHandler
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Adds SessionHandler functionality if available.
|
||||
*
|
||||
* @see http://php.net/sessionhandler
|
||||
*/
|
||||
class NativeSessionHandler extends \SessionHandler
|
||||
{
|
||||
}
|
@@ -17,8 +17,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
||||
* Can be used in unit testing or in a situations where persisted sessions are not desired.
|
||||
*
|
||||
* @author Drak <drak@zikula.org>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class NullSessionHandler implements \SessionHandlerInterface
|
||||
{
|
@@ -42,8 +42,8 @@ class MockFileSessionStorage extends MockArraySessionStorage
|
||||
$savePath = sys_get_temp_dir();
|
||||
}
|
||||
|
||||
if (!is_dir($savePath)) {
|
||||
mkdir($savePath, 0777, true);
|
||||
if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) {
|
||||
throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $savePath));
|
||||
}
|
||||
|
||||
$this->savePath = $savePath;
|
@@ -13,7 +13,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
|
||||
|
||||
@@ -65,7 +64,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
* ("auto_start", is not supported as it tells PHP to start a session before
|
||||
* PHP starts to execute user-land code. Setting during runtime has no effect).
|
||||
*
|
||||
* cache_limiter, "nocache" (use "0" to prevent headers from being sent entirely).
|
||||
* cache_limiter, "" (use "0" to prevent headers from being sent entirely).
|
||||
* cookie_domain, ""
|
||||
* cookie_httponly, ""
|
||||
* cookie_lifetime, "0"
|
||||
@@ -101,11 +100,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used)
|
||||
ini_set('session.use_cookies', 1);
|
||||
|
||||
if (PHP_VERSION_ID >= 50400) {
|
||||
session_register_shutdown();
|
||||
} else {
|
||||
register_shutdown_function('session_write_close');
|
||||
}
|
||||
session_register_shutdown();
|
||||
|
||||
$this->setMetadataBag($metaBag);
|
||||
$this->setOptions($options);
|
||||
@@ -131,15 +126,10 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status()) {
|
||||
if (\PHP_SESSION_ACTIVE === session_status()) {
|
||||
throw new \RuntimeException('Failed to start the session: already started by PHP.');
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID < 50400 && !$this->closed && isset($_SESSION) && session_id()) {
|
||||
// not 100% fool-proof, but is the most reliable way to determine if a session is active in PHP 5.3
|
||||
throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).');
|
||||
}
|
||||
|
||||
if (ini_get('session.use_cookies') && 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));
|
||||
}
|
||||
@@ -150,10 +140,6 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
}
|
||||
|
||||
$this->loadSession();
|
||||
if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
|
||||
// This condition matches only PHP 5.3 with internal save handlers
|
||||
$this->saveHandler->setActive(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -195,6 +181,11 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
*/
|
||||
public function regenerate($destroy = false, $lifetime = null)
|
||||
{
|
||||
// Cannot regenerate the session ID for non-active sessions.
|
||||
if (\PHP_SESSION_ACTIVE !== session_status()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $lifetime) {
|
||||
ini_set('session.cookie_lifetime', $lifetime);
|
||||
}
|
||||
@@ -219,11 +210,6 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
{
|
||||
session_write_close();
|
||||
|
||||
if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
|
||||
// This condition matches only PHP 5.3 with internal save handlers
|
||||
$this->saveHandler->setActive(false);
|
||||
}
|
||||
|
||||
$this->closed = true;
|
||||
$this->started = false;
|
||||
}
|
||||
@@ -250,6 +236,10 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
*/
|
||||
public function registerBag(SessionBagInterface $bag)
|
||||
{
|
||||
if ($this->started) {
|
||||
throw new \LogicException('Cannot register a bag when the session is already started.');
|
||||
}
|
||||
|
||||
$this->bags[$bag->getName()] = $bag;
|
||||
}
|
||||
|
||||
@@ -341,7 +331,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
* session.save_handler and session.save_path e.g.
|
||||
*
|
||||
* ini_set('session.save_handler', 'files');
|
||||
* ini_set('session.save_path', /tmp');
|
||||
* ini_set('session.save_path', '/tmp');
|
||||
*
|
||||
* or pass in a NativeSessionHandler instance which configures session.save_handler in the
|
||||
* constructor, for a template see NativeFileSessionHandler or use handlers in
|
||||
@@ -369,24 +359,12 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||
if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
|
||||
$saveHandler = new SessionHandlerProxy($saveHandler);
|
||||
} elseif (!$saveHandler instanceof AbstractProxy) {
|
||||
$saveHandler = PHP_VERSION_ID >= 50400 ?
|
||||
new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy();
|
||||
$saveHandler = new SessionHandlerProxy(new \SessionHandler());
|
||||
}
|
||||
$this->saveHandler = $saveHandler;
|
||||
|
||||
if ($this->saveHandler instanceof \SessionHandlerInterface) {
|
||||
if (PHP_VERSION_ID >= 50400) {
|
||||
session_set_save_handler($this->saveHandler, false);
|
||||
} else {
|
||||
session_set_save_handler(
|
||||
array($this->saveHandler, 'open'),
|
||||
array($this->saveHandler, 'close'),
|
||||
array($this->saveHandler, 'read'),
|
||||
array($this->saveHandler, 'write'),
|
||||
array($this->saveHandler, 'destroy'),
|
||||
array($this->saveHandler, 'gc')
|
||||
);
|
||||
}
|
||||
session_set_save_handler($this->saveHandler, false);
|
||||
}
|
||||
}
|
||||
|
@@ -43,10 +43,6 @@ class PhpBridgeSessionStorage extends NativeSessionStorage
|
||||
}
|
||||
|
||||
$this->loadSession();
|
||||
if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
|
||||
// This condition matches only PHP 5.3 + internal save handlers
|
||||
$this->saveHandler->setActive(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@@ -25,11 +25,6 @@ abstract class AbstractProxy
|
||||
*/
|
||||
protected $wrapper = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $active = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -52,7 +47,7 @@ abstract class AbstractProxy
|
||||
*/
|
||||
public function isSessionHandlerInterface()
|
||||
{
|
||||
return ($this instanceof \SessionHandlerInterface);
|
||||
return $this instanceof \SessionHandlerInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,32 +67,7 @@ abstract class AbstractProxy
|
||||
*/
|
||||
public function isActive()
|
||||
{
|
||||
if (PHP_VERSION_ID >= 50400) {
|
||||
return $this->active = \PHP_SESSION_ACTIVE === session_status();
|
||||
}
|
||||
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active flag.
|
||||
*
|
||||
* Has no effect under PHP 5.4+ as status is detected
|
||||
* automatically in isActive()
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param bool $flag
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function setActive($flag)
|
||||
{
|
||||
if (PHP_VERSION_ID >= 50400) {
|
||||
throw new \LogicException('This method is disabled in PHP 5.4.0+');
|
||||
}
|
||||
|
||||
$this->active = (bool) $flag;
|
||||
return \PHP_SESSION_ACTIVE === session_status();
|
||||
}
|
||||
|
||||
/**
|
@@ -42,13 +42,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
||||
*/
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
$return = (bool) $this->handler->open($savePath, $sessionName);
|
||||
|
||||
if (true === $return) {
|
||||
$this->active = true;
|
||||
}
|
||||
|
||||
return $return;
|
||||
return (bool) $this->handler->open($savePath, $sessionName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,8 +50,6 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->active = false;
|
||||
|
||||
return (bool) $this->handler->close();
|
||||
}
|
||||
|
@@ -18,19 +18,15 @@ use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Drak <drak@zikula.org>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
interface SessionStorageInterface
|
||||
{
|
||||
/**
|
||||
* Starts the session.
|
||||
*
|
||||
* @throws \RuntimeException If something goes wrong starting the session.
|
||||
*
|
||||
* @return bool True if started.
|
||||
*
|
||||
* @api
|
||||
* @throws \RuntimeException If something goes wrong starting the session.
|
||||
*/
|
||||
public function start();
|
||||
|
||||
@@ -45,8 +41,6 @@ interface SessionStorageInterface
|
||||
* Returns the session ID.
|
||||
*
|
||||
* @return string The session ID or empty.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
@@ -54,8 +48,6 @@ interface SessionStorageInterface
|
||||
* Sets the session ID.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setId($id);
|
||||
|
||||
@@ -63,8 +55,6 @@ interface SessionStorageInterface
|
||||
* Returns the session name.
|
||||
*
|
||||
* @return mixed The session name.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
@@ -72,8 +62,6 @@ interface SessionStorageInterface
|
||||
* Sets the session name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setName($name);
|
||||
|
||||
@@ -88,10 +76,10 @@ interface SessionStorageInterface
|
||||
* Note regenerate+destroy should not clear the session data in memory
|
||||
* only delete the session data from persistent storage.
|
||||
*
|
||||
* Care: When regenerating the session ID no locking is involved in PHPs
|
||||
* Care: When regenerating the session ID no locking is involved in PHP's
|
||||
* session design. See https://bugs.php.net/bug.php?id=61470 for a discussion.
|
||||
* So you must make sure the regenerated session is saved BEFORE sending the
|
||||
* headers with the new ID. Symfonys HttpKernel offers a listener for this.
|
||||
* headers with the new ID. Symfony's HttpKernel offers a listener for this.
|
||||
* See Symfony\Component\HttpKernel\EventListener\SaveSessionListener.
|
||||
* Otherwise session data could get lost again for concurrent requests with the
|
||||
* new ID. One result could be that you get logged out after just logging in.
|
||||
@@ -105,8 +93,6 @@ interface SessionStorageInterface
|
||||
* @return bool True if session regenerated, false if error
|
||||
*
|
||||
* @throws \RuntimeException If an error occurs while regenerating this storage
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function regenerate($destroy = false, $lifetime = null);
|
||||
|
||||
@@ -115,7 +101,7 @@ interface SessionStorageInterface
|
||||
*
|
||||
* This method must invoke session_write_close() unless this interface is
|
||||
* used for a storage object design for unit or functional testing where
|
||||
* a real PHP session would interfere with testing, in which case it
|
||||
* a real PHP session would interfere with testing, in which case
|
||||
* it should actually persist the session data if required.
|
||||
*
|
||||
* @throws \RuntimeException If the session is saved without being started, or if the session
|
@@ -23,8 +23,6 @@ namespace Symfony\Component\HttpFoundation;
|
||||
* @see flush()
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class StreamedResponse extends Response
|
||||
{
|
||||
@@ -37,10 +35,8 @@ class StreamedResponse extends Response
|
||||
* @param callable|null $callback A valid PHP callback or null to set it later
|
||||
* @param int $status The response status code
|
||||
* @param array $headers An array of response headers
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($callback = null, $status = 200, $headers = array())
|
||||
public function __construct(callable $callback = null, $status = 200, $headers = array())
|
||||
{
|
||||
parent::__construct(null, $status, $headers);
|
||||
|
||||
@@ -51,7 +47,7 @@ class StreamedResponse extends Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method for chainability
|
||||
* Factory method for chainability.
|
||||
*
|
||||
* @param callable|null $callback A valid PHP callback or null to set it later
|
||||
* @param int $status The response status code
|
||||
@@ -68,14 +64,9 @@ class StreamedResponse extends Response
|
||||
* Sets the PHP callback associated with this Response.
|
||||
*
|
||||
* @param callable $callback A valid PHP callback
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function setCallback($callback)
|
||||
public function setCallback(callable $callback)
|
||||
{
|
||||
if (!is_callable($callback)) {
|
||||
throw new \LogicException('The Response callback must be a valid PHP callable.');
|
||||
}
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
@@ -1,56 +0,0 @@
|
||||
HttpFoundation Component
|
||||
========================
|
||||
|
||||
HttpFoundation defines an object-oriented layer for the HTTP specification.
|
||||
|
||||
It provides an abstraction for requests, responses, uploaded files, cookies,
|
||||
sessions, ...
|
||||
|
||||
In this example, we get a Request object from the current PHP global
|
||||
variables:
|
||||
|
||||
```php
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
$request = Request::createFromGlobals();
|
||||
echo $request->getPathInfo();
|
||||
```
|
||||
|
||||
You can also create a Request directly -- that's interesting for unit testing:
|
||||
|
||||
```php
|
||||
$request = Request::create('/?foo=bar', 'GET');
|
||||
echo $request->getPathInfo();
|
||||
```
|
||||
|
||||
And here is how to create and send a Response:
|
||||
|
||||
```php
|
||||
$response = new Response('Not Found', 404, array('Content-Type' => 'text/plain'));
|
||||
$response->send();
|
||||
```
|
||||
|
||||
The Request and the Response classes have many other methods that implement
|
||||
the HTTP specification.
|
||||
|
||||
Loading
|
||||
-------
|
||||
|
||||
If you are not using Composer but are using PHP 5.3.x, you must add the following to your autoloader:
|
||||
|
||||
```php
|
||||
// SessionHandlerInterface
|
||||
if (!interface_exists('SessionHandlerInterface')) {
|
||||
$loader->registerPrefixFallback(__DIR__.'/../vendor/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs');
|
||||
}
|
||||
```
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
You can run the unit tests with the following command:
|
||||
|
||||
$ cd path/to/Symfony/Component/HttpFoundation/
|
||||
$ composer install
|
||||
$ phpunit
|
@@ -1,102 +0,0 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SessionHandlerInterface for PHP < 5.4.
|
||||
*
|
||||
* The order in which these methods are invoked by PHP are:
|
||||
* 1. open [session_start]
|
||||
* 2. read
|
||||
* 3. gc [optional depending on probability settings: gc_probability / gc_divisor]
|
||||
* 4. destroy [optional when session_regenerate_id(true) is used]
|
||||
* 5. write [session_write_close] or destroy [session_destroy]
|
||||
* 6. close
|
||||
*
|
||||
* Extensive documentation can be found at php.net, see links:
|
||||
*
|
||||
* @see http://php.net/sessionhandlerinterface
|
||||
* @see http://php.net/session.customhandler
|
||||
* @see http://php.net/session-set-save-handler
|
||||
*
|
||||
* @author Drak <drak@zikula.org>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*/
|
||||
interface SessionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Re-initializes existing session, or creates a new one.
|
||||
*
|
||||
* @see http://php.net/sessionhandlerinterface.open
|
||||
*
|
||||
* @param string $savePath Save path
|
||||
* @param string $sessionName Session name, see http://php.net/function.session-name.php
|
||||
*
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
public function open($savePath, $sessionName);
|
||||
|
||||
/**
|
||||
* Closes the current session.
|
||||
*
|
||||
* @see http://php.net/sessionhandlerinterface.close
|
||||
*
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
public function close();
|
||||
|
||||
/**
|
||||
* Reads the session data.
|
||||
*
|
||||
* @see http://php.net/sessionhandlerinterface.read
|
||||
*
|
||||
* @param string $sessionId Session ID, see http://php.net/function.session-id
|
||||
*
|
||||
* @return string Same session data as passed in write() or empty string when non-existent or on failure
|
||||
*/
|
||||
public function read($sessionId);
|
||||
|
||||
/**
|
||||
* Writes the session data to the storage.
|
||||
*
|
||||
* Care, the session ID passed to write() can be different from the one previously
|
||||
* received in read() when the session ID changed due to session_regenerate_id().
|
||||
*
|
||||
* @see http://php.net/sessionhandlerinterface.write
|
||||
*
|
||||
* @param string $sessionId Session ID , see http://php.net/function.session-id
|
||||
* @param string $data Serialized session data to save
|
||||
*
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
public function write($sessionId, $data);
|
||||
|
||||
/**
|
||||
* Destroys a session.
|
||||
*
|
||||
* @see http://php.net/sessionhandlerinterface.destroy
|
||||
*
|
||||
* @param string $sessionId Session ID, see http://php.net/function.session-id
|
||||
*
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
public function destroy($sessionId);
|
||||
|
||||
/**
|
||||
* Cleans up expired sessions (garbage collection).
|
||||
*
|
||||
* @see http://php.net/sessionhandlerinterface.gc
|
||||
*
|
||||
* @param string|int $maxlifetime Sessions that have not updated for the last maxlifetime seconds will be removed
|
||||
*
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
public function gc($maxlifetime);
|
||||
}
|
@@ -1,268 +0,0 @@
|
||||
<?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\Storage\Handler;
|
||||
|
||||
/**
|
||||
* Session handler using a PDO connection to read and write data.
|
||||
*
|
||||
* Session data is a binary string that can contain non-printable characters like the null byte.
|
||||
* For this reason this handler base64 encodes the data to be able to save it in a character column.
|
||||
*
|
||||
* This version of the PdoSessionHandler does NOT implement locking. So concurrent requests to the
|
||||
* same session can result in data loss due to race conditions.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Michael Williams <michael.williams@funsational.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @deprecated Deprecated since version 2.6, to be removed in 3.0. Use
|
||||
* {@link PdoSessionHandler} instead.
|
||||
*/
|
||||
class LegacyPdoSessionHandler implements \SessionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var \PDO PDO instance
|
||||
*/
|
||||
private $pdo;
|
||||
|
||||
/**
|
||||
* @var string Table name
|
||||
*/
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* @var string Column for session id
|
||||
*/
|
||||
private $idCol;
|
||||
|
||||
/**
|
||||
* @var string Column for session data
|
||||
*/
|
||||
private $dataCol;
|
||||
|
||||
/**
|
||||
* @var string Column for timestamp
|
||||
*/
|
||||
private $timeCol;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* List of available options:
|
||||
* * db_table: The name of the table [required]
|
||||
* * db_id_col: The column where to store the session id [default: sess_id]
|
||||
* * db_data_col: The column where to store the session data [default: sess_data]
|
||||
* * db_time_col: The column where to store the timestamp [default: sess_time]
|
||||
*
|
||||
* @param \PDO $pdo A \PDO instance
|
||||
* @param array $dbOptions An associative array of DB options
|
||||
*
|
||||
* @throws \InvalidArgumentException When "db_table" option is not provided
|
||||
*/
|
||||
public function __construct(\PDO $pdo, array $dbOptions = array())
|
||||
{
|
||||
if (!array_key_exists('db_table', $dbOptions)) {
|
||||
throw new \InvalidArgumentException('You must provide the "db_table" option for a PdoSessionStorage.');
|
||||
}
|
||||
if (\PDO::ERRMODE_EXCEPTION !== $pdo->getAttribute(\PDO::ATTR_ERRMODE)) {
|
||||
throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__));
|
||||
}
|
||||
$this->pdo = $pdo;
|
||||
$dbOptions = array_merge(array(
|
||||
'db_id_col' => 'sess_id',
|
||||
'db_data_col' => 'sess_data',
|
||||
'db_time_col' => 'sess_time',
|
||||
), $dbOptions);
|
||||
|
||||
$this->table = $dbOptions['db_table'];
|
||||
$this->idCol = $dbOptions['db_id_col'];
|
||||
$this->dataCol = $dbOptions['db_data_col'];
|
||||
$this->timeCol = $dbOptions['db_time_col'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function destroy($sessionId)
|
||||
{
|
||||
// delete the record associated with this id
|
||||
$sql = "DELETE FROM $this->table WHERE $this->idCol = :id";
|
||||
|
||||
try {
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
} catch (\PDOException $e) {
|
||||
throw new \RuntimeException(sprintf('PDOException was thrown when trying to delete a session: %s', $e->getMessage()), 0, $e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
// delete the session records that have expired
|
||||
$sql = "DELETE FROM $this->table WHERE $this->timeCol < :time";
|
||||
|
||||
try {
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->bindValue(':time', time() - $maxlifetime, \PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
} catch (\PDOException $e) {
|
||||
throw new \RuntimeException(sprintf('PDOException was thrown when trying to delete expired sessions: %s', $e->getMessage()), 0, $e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($sessionId)
|
||||
{
|
||||
$sql = "SELECT $this->dataCol FROM $this->table WHERE $this->idCol = :id";
|
||||
|
||||
try {
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
|
||||
// We use fetchAll instead of fetchColumn to make sure the DB cursor gets closed
|
||||
$sessionRows = $stmt->fetchAll(\PDO::FETCH_NUM);
|
||||
|
||||
if ($sessionRows) {
|
||||
return base64_decode($sessionRows[0][0]);
|
||||
}
|
||||
|
||||
return '';
|
||||
} catch (\PDOException $e) {
|
||||
throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($sessionId, $data)
|
||||
{
|
||||
$encoded = base64_encode($data);
|
||||
|
||||
try {
|
||||
// We use a single MERGE SQL query when supported by the database.
|
||||
$mergeSql = $this->getMergeSql();
|
||||
|
||||
if (null !== $mergeSql) {
|
||||
$mergeStmt = $this->pdo->prepare($mergeSql);
|
||||
$mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$mergeStmt->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$updateStmt = $this->pdo->prepare(
|
||||
"UPDATE $this->table SET $this->dataCol = :data, $this->timeCol = :time WHERE $this->idCol = :id"
|
||||
);
|
||||
$updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$updateStmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
|
||||
$updateStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$updateStmt->execute();
|
||||
|
||||
// When MERGE is not supported, like in Postgres, we have to use this approach that can result in
|
||||
// duplicate key errors when the same session is written simultaneously. We can just catch such an
|
||||
// error and re-execute the update. This is similar to a serializable transaction with retry logic
|
||||
// on serialization failures but without the overhead and without possible false positives due to
|
||||
// longer gap locking.
|
||||
if (!$updateStmt->rowCount()) {
|
||||
try {
|
||||
$insertStmt = $this->pdo->prepare(
|
||||
"INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)"
|
||||
);
|
||||
$insertStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$insertStmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
|
||||
$insertStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$insertStmt->execute();
|
||||
} catch (\PDOException $e) {
|
||||
// Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys
|
||||
if (0 === strpos($e->getCode(), '23')) {
|
||||
$updateStmt->execute();
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a merge/upsert (i.e. insert or update) SQL query when supported by the database.
|
||||
*
|
||||
* @return string|null The SQL string or null when not supported
|
||||
*/
|
||||
private function getMergeSql()
|
||||
{
|
||||
$driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
||||
|
||||
switch ($driver) {
|
||||
case 'mysql':
|
||||
return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ".
|
||||
"ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->timeCol = VALUES($this->timeCol)";
|
||||
case 'oci':
|
||||
// DUAL is Oracle specific dummy table
|
||||
return "MERGE INTO $this->table USING DUAL ON ($this->idCol = :id) ".
|
||||
"WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ".
|
||||
"WHEN MATCHED THEN UPDATE SET $this->dataCol = :data, $this->timeCol = :time";
|
||||
case 'sqlsrv' === $driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='):
|
||||
// MERGE is only available since SQL Server 2008 and must be terminated by semicolon
|
||||
// It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
|
||||
return "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = :id) ".
|
||||
"WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ".
|
||||
"WHEN MATCHED THEN UPDATE SET $this->dataCol = :data, $this->timeCol = :time;";
|
||||
case 'sqlite':
|
||||
return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a PDO instance
|
||||
*
|
||||
* @return \PDO
|
||||
*/
|
||||
protected function getConnection()
|
||||
{
|
||||
return $this->pdo;
|
||||
}
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
<?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;
|
||||
|
||||
function time($asFloat = false)
|
||||
{
|
||||
return Tests\time();
|
||||
}
|
||||
|
||||
namespace Symfony\Component\HttpFoundation\Tests;
|
||||
|
||||
function time()
|
||||
{
|
||||
return $_SERVER['REQUEST_TIME'];
|
||||
}
|
@@ -1,116 +0,0 @@
|
||||
<?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\Tests\Session\Storage\Handler;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\LegacyPdoSessionHandler;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class LegacyPdoSessionHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $pdo;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) {
|
||||
$this->markTestSkipped('This test requires SQLite support in your environment');
|
||||
}
|
||||
|
||||
$this->pdo = new \PDO('sqlite::memory:');
|
||||
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
$sql = 'CREATE TABLE sessions (sess_id VARCHAR(128) PRIMARY KEY, sess_data TEXT, sess_time INTEGER)';
|
||||
$this->pdo->exec($sql);
|
||||
}
|
||||
|
||||
public function testIncompleteOptions()
|
||||
{
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
$storage = new LegacyPdoSessionHandler($this->pdo, array());
|
||||
}
|
||||
|
||||
public function testWrongPdoErrMode()
|
||||
{
|
||||
$pdo = new \PDO('sqlite::memory:');
|
||||
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_SILENT);
|
||||
$pdo->exec('CREATE TABLE sessions (sess_id VARCHAR(128) PRIMARY KEY, sess_data TEXT, sess_time INTEGER)');
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
$storage = new LegacyPdoSessionHandler($pdo, array('db_table' => 'sessions'));
|
||||
}
|
||||
|
||||
public function testWrongTableOptionsWrite()
|
||||
{
|
||||
$storage = new LegacyPdoSessionHandler($this->pdo, array('db_table' => 'bad_name'));
|
||||
$this->setExpectedException('RuntimeException');
|
||||
$storage->write('foo', 'bar');
|
||||
}
|
||||
|
||||
public function testWrongTableOptionsRead()
|
||||
{
|
||||
$storage = new LegacyPdoSessionHandler($this->pdo, array('db_table' => 'bad_name'));
|
||||
$this->setExpectedException('RuntimeException');
|
||||
$storage->read('foo', 'bar');
|
||||
}
|
||||
|
||||
public function testWriteRead()
|
||||
{
|
||||
$storage = new LegacyPdoSessionHandler($this->pdo, array('db_table' => 'sessions'));
|
||||
$storage->write('foo', 'bar');
|
||||
$this->assertEquals('bar', $storage->read('foo'), 'written value can be read back correctly');
|
||||
}
|
||||
|
||||
public function testMultipleInstances()
|
||||
{
|
||||
$storage1 = new LegacyPdoSessionHandler($this->pdo, array('db_table' => 'sessions'));
|
||||
$storage1->write('foo', 'bar');
|
||||
|
||||
$storage2 = new LegacyPdoSessionHandler($this->pdo, array('db_table' => 'sessions'));
|
||||
$this->assertEquals('bar', $storage2->read('foo'), 'values persist between instances');
|
||||
}
|
||||
|
||||
public function testSessionDestroy()
|
||||
{
|
||||
$storage = new LegacyPdoSessionHandler($this->pdo, array('db_table' => 'sessions'));
|
||||
$storage->write('foo', 'bar');
|
||||
$this->assertCount(1, $this->pdo->query('SELECT * FROM sessions')->fetchAll());
|
||||
|
||||
$storage->destroy('foo');
|
||||
|
||||
$this->assertCount(0, $this->pdo->query('SELECT * FROM sessions')->fetchAll());
|
||||
}
|
||||
|
||||
public function testSessionGC()
|
||||
{
|
||||
$storage = new LegacyPdoSessionHandler($this->pdo, array('db_table' => 'sessions'));
|
||||
|
||||
$storage->write('foo', 'bar');
|
||||
$storage->write('baz', 'bar');
|
||||
|
||||
$this->assertCount(2, $this->pdo->query('SELECT * FROM sessions')->fetchAll());
|
||||
|
||||
$storage->gc(-1);
|
||||
$this->assertCount(0, $this->pdo->query('SELECT * FROM sessions')->fetchAll());
|
||||
}
|
||||
|
||||
public function testGetConnection()
|
||||
{
|
||||
$storage = new LegacyPdoSessionHandler($this->pdo, array('db_table' => 'sessions'), array());
|
||||
|
||||
$method = new \ReflectionMethod($storage, 'getConnection');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$this->assertInstanceOf('\PDO', $method->invoke($storage));
|
||||
}
|
||||
}
|
@@ -34,6 +34,17 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
$this->assertEquals('inline; filename="README.md"', $response->headers->get('Content-Disposition'));
|
||||
}
|
||||
|
||||
public function testConstructWithNonAsciiFilename()
|
||||
{
|
||||
touch(sys_get_temp_dir().'/fööö.html');
|
||||
|
||||
$response = new BinaryFileResponse(sys_get_temp_dir().'/fööö.html', 200, array(), true, 'attachment');
|
||||
|
||||
@unlink(sys_get_temp_dir().'/fööö.html');
|
||||
|
||||
$this->assertSame('fööö.html', $response->getFile()->getFilename());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
@@ -49,12 +60,20 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
$this->assertFalse($response->getContent());
|
||||
}
|
||||
|
||||
public function testSetContentDispositionGeneratesSafeFallbackFilename()
|
||||
{
|
||||
$response = new BinaryFileResponse(__FILE__);
|
||||
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, 'föö.html');
|
||||
|
||||
$this->assertSame('attachment; filename="f__.html"; filename*=utf-8\'\'f%C3%B6%C3%B6.html', $response->headers->get('Content-Disposition'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideRanges
|
||||
*/
|
||||
public function testRequests($requestRange, $offset, $length, $responseRange)
|
||||
{
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag();
|
||||
|
||||
// do a request to get the ETag
|
||||
$request = Request::create('/');
|
||||
@@ -80,6 +99,37 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
$this->assertEquals($responseRange, $response->headers->get('Content-Range'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideRanges
|
||||
*/
|
||||
public function testRequestsWithoutEtag($requestRange, $offset, $length, $responseRange)
|
||||
{
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'));
|
||||
|
||||
// do a request to get the LastModified
|
||||
$request = Request::create('/');
|
||||
$response->prepare($request);
|
||||
$lastModified = $response->headers->get('Last-Modified');
|
||||
|
||||
// prepare a request for a range of the testing file
|
||||
$request = Request::create('/');
|
||||
$request->headers->set('If-Range', $lastModified);
|
||||
$request->headers->set('Range', $requestRange);
|
||||
|
||||
$file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
|
||||
fseek($file, $offset);
|
||||
$data = fread($file, $length);
|
||||
fclose($file);
|
||||
|
||||
$this->expectOutputString($data);
|
||||
$response = clone $response;
|
||||
$response->prepare($request);
|
||||
$response->sendContent();
|
||||
|
||||
$this->assertEquals(206, $response->getStatusCode());
|
||||
$this->assertEquals($responseRange, $response->headers->get('Content-Range'));
|
||||
}
|
||||
|
||||
public function provideRanges()
|
||||
{
|
||||
return array(
|
||||
@@ -91,12 +141,31 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testRangeRequestsWithoutLastModifiedDate()
|
||||
{
|
||||
// prevent auto last modified
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'), true, null, false, false);
|
||||
|
||||
// prepare a request for a range of the testing file
|
||||
$request = Request::create('/');
|
||||
$request->headers->set('If-Range', date('D, d M Y H:i:s').' GMT');
|
||||
$request->headers->set('Range', 'bytes=1-4');
|
||||
|
||||
$this->expectOutputString(file_get_contents(__DIR__.'/File/Fixtures/test.gif'));
|
||||
$response = clone $response;
|
||||
$response->prepare($request);
|
||||
$response->sendContent();
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertNull($response->headers->get('Content-Range'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideFullFileRanges
|
||||
*/
|
||||
public function testFullFileRequests($requestRange)
|
||||
{
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag();
|
||||
|
||||
// prepare a request for a range of the testing file
|
||||
$request = Request::create('/');
|
||||
@@ -131,7 +200,7 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
*/
|
||||
public function testInvalidRequests($requestRange)
|
||||
{
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag();
|
||||
|
||||
// prepare a request for a range of the testing file
|
||||
$request = Request::create('/');
|
||||
@@ -142,7 +211,7 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
$response->sendContent();
|
||||
|
||||
$this->assertEquals(416, $response->getStatusCode());
|
||||
#$this->assertEquals('', $response->headers->get('Content-Range'));
|
||||
$this->assertEquals('bytes */35', $response->headers->get('Content-Range'));
|
||||
}
|
||||
|
||||
public function provideInvalidRanges()
|
||||
@@ -153,13 +222,16 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testXSendfile()
|
||||
/**
|
||||
* @dataProvider provideXSendfileFiles
|
||||
*/
|
||||
public function testXSendfile($file)
|
||||
{
|
||||
$request = Request::create('/');
|
||||
$request->headers->set('X-Sendfile-Type', 'X-Sendfile');
|
||||
|
||||
BinaryFileResponse::trustXSendfileTypeHeader();
|
||||
$response = BinaryFileResponse::create(__DIR__.'/../README.md');
|
||||
$response = BinaryFileResponse::create($file, 200, array('Content-Type' => 'application/octet-stream'));
|
||||
$response->prepare($request);
|
||||
|
||||
$this->expectOutputString('');
|
||||
@@ -168,6 +240,14 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
$this->assertContains('README.md', $response->headers->get('X-Sendfile'));
|
||||
}
|
||||
|
||||
public function provideXSendfileFiles()
|
||||
{
|
||||
return array(
|
||||
array(__DIR__.'/../README.md'),
|
||||
array('file://'.__DIR__.'/../README.md'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getSampleXAccelMappings
|
||||
*/
|
||||
@@ -180,7 +260,7 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
$file = new FakeFile($realpath, __DIR__.'/File/Fixtures/test');
|
||||
|
||||
BinaryFileResponse::trustXSendfileTypeHeader();
|
||||
$response = new BinaryFileResponse($file);
|
||||
$response = new BinaryFileResponse($file, 200, array('Content-Type' => 'application/octet-stream'));
|
||||
$reflection = new \ReflectionObject($response);
|
||||
$property = $reflection->getProperty('file');
|
||||
$property->setAccessible(true);
|
||||
@@ -199,7 +279,7 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
$realPath = realpath($path);
|
||||
$this->assertFileExists($realPath);
|
||||
|
||||
$response = new BinaryFileResponse($realPath);
|
||||
$response = new BinaryFileResponse($realPath, 200, array('Content-Type' => 'application/octet-stream'));
|
||||
$response->deleteFileAfterSend(true);
|
||||
|
||||
$response->prepare($request);
|
||||
@@ -211,7 +291,7 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
public function testAcceptRangeOnUnsafeMethods()
|
||||
{
|
||||
$request = Request::create('/', 'POST');
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif');
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'));
|
||||
$response->prepare($request);
|
||||
|
||||
$this->assertEquals('none', $response->headers->get('Accept-Ranges'));
|
||||
@@ -220,7 +300,7 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
public function testAcceptRangeNotOverriden()
|
||||
{
|
||||
$request = Request::create('/', 'POST');
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif');
|
||||
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'));
|
||||
$response->headers->set('Accept-Ranges', 'foo');
|
||||
$response->prepare($request);
|
||||
|
||||
@@ -237,7 +317,7 @@ class BinaryFileResponseTest extends ResponseTestCase
|
||||
|
||||
protected function provideResponse()
|
||||
{
|
||||
return new BinaryFileResponse(__DIR__.'/../README.md');
|
||||
return new BinaryFileResponse(__DIR__.'/../README.md', 200, array('Content-Type' => 'application/octet-stream'));
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass()
|
@@ -13,13 +13,13 @@ namespace Symfony\Component\HttpFoundation\Tests;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
|
||||
require_once __DIR__.'/ClockMock.php';
|
||||
|
||||
/**
|
||||
* CookieTest.
|
||||
*
|
||||
* @author John Kary <john@johnkary.net>
|
||||
* @author Hugo Hamon <hugo.hamon@sensio.com>
|
||||
*
|
||||
* @group time-sensitive
|
||||
*/
|
||||
class CookieTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
@@ -41,7 +41,6 @@ class CookieTest extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* @dataProvider invalidNames
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @covers Symfony\Component\HttpFoundation\Cookie::__construct
|
||||
*/
|
||||
public function testInstantiationThrowsExceptionIfCookieNameContainsInvalidCharacters($name)
|
||||
{
|
||||
@@ -56,9 +55,6 @@ class CookieTest extends \PHPUnit_Framework_TestCase
|
||||
$cookie = new Cookie('MyCookie', 'foo', 'bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Cookie::getValue
|
||||
*/
|
||||
public function testGetValue()
|
||||
{
|
||||
$value = 'MyValue';
|
||||
@@ -89,13 +85,24 @@ class CookieTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 5.5
|
||||
*/
|
||||
public function testConstructorWithDateTimeImmutable()
|
||||
{
|
||||
$expire = new \DateTimeImmutable();
|
||||
$cookie = new Cookie('foo', 'bar', $expire);
|
||||
|
||||
$this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
|
||||
}
|
||||
|
||||
public function testGetExpiresTimeWithStringValue()
|
||||
{
|
||||
$value = '+1 day';
|
||||
$cookie = new Cookie('foo', 'bar', $value);
|
||||
$expire = strtotime($value);
|
||||
|
||||
$this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date');
|
||||
$this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date', 1);
|
||||
}
|
||||
|
||||
public function testGetDomain()
|
@@ -45,6 +45,9 @@ class FileTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('gif', $file->guessExtension());
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension fileinfo
|
||||
*/
|
||||
public function testGuessExtensionWithReset()
|
||||
{
|
||||
$file = new File(__DIR__.'/Fixtures/other-file.example');
|
||||
@@ -78,8 +81,8 @@ class FileTest extends \PHPUnit_Framework_TestCase
|
||||
$movedFile = $file->move($targetDir);
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\File\File', $movedFile);
|
||||
|
||||
$this->assertTrue(file_exists($targetPath));
|
||||
$this->assertFalse(file_exists($path));
|
||||
$this->assertFileExists($targetPath);
|
||||
$this->assertFileNotExists($path);
|
||||
$this->assertEquals(realpath($targetPath), $movedFile->getRealPath());
|
||||
|
||||
@unlink($targetPath);
|
||||
@@ -97,8 +100,8 @@ class FileTest extends \PHPUnit_Framework_TestCase
|
||||
$file = new File($path);
|
||||
$movedFile = $file->move($targetDir, 'test.newname.gif');
|
||||
|
||||
$this->assertTrue(file_exists($targetPath));
|
||||
$this->assertFalse(file_exists($path));
|
||||
$this->assertFileExists($targetPath);
|
||||
$this->assertFileNotExists($path);
|
||||
$this->assertEquals(realpath($targetPath), $movedFile->getRealPath());
|
||||
|
||||
@unlink($targetPath);
|
||||
@@ -132,8 +135,8 @@ class FileTest extends \PHPUnit_Framework_TestCase
|
||||
$movedFile = $file->move($targetDir, $filename);
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\File\File', $movedFile);
|
||||
|
||||
$this->assertTrue(file_exists($targetPath));
|
||||
$this->assertFalse(file_exists($path));
|
||||
$this->assertFileExists($targetPath);
|
||||
$this->assertFileNotExists($path);
|
||||
$this->assertEquals(realpath($targetPath), $movedFile->getRealPath());
|
||||
|
||||
@unlink($targetPath);
|
||||
@@ -161,12 +164,6 @@ class FileTest extends \PHPUnit_Framework_TestCase
|
||||
@rmdir($targetDir);
|
||||
}
|
||||
|
||||
public function testGetExtension()
|
||||
{
|
||||
$file = new File(__DIR__.'/Fixtures/test.gif');
|
||||
$this->assertEquals('gif', $file->getExtension());
|
||||
}
|
||||
|
||||
protected function createMockGuesser($path, $mimeType)
|
||||
{
|
||||
$guesser = $this->getMock('Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface');
|
Before Width: | Height: | Size: 35 B After Width: | Height: | Size: 35 B |
Before Width: | Height: | Size: 35 B After Width: | Height: | Size: 35 B |
@@ -14,17 +14,16 @@ namespace Symfony\Component\HttpFoundation\Tests\File\MimeType;
|
||||
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
|
||||
use Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser;
|
||||
|
||||
/**
|
||||
* @requires extension fileinfo
|
||||
*/
|
||||
class MimeTypeTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $path;
|
||||
|
||||
public function testGuessImageWithoutExtension()
|
||||
{
|
||||
if (extension_loaded('fileinfo')) {
|
||||
$this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
|
||||
} else {
|
||||
$this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
|
||||
}
|
||||
$this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
|
||||
}
|
||||
|
||||
public function testGuessImageWithDirectory()
|
||||
@@ -38,29 +37,17 @@ class MimeTypeTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$guesser = MimeTypeGuesser::getInstance();
|
||||
$guesser->register(new FileBinaryMimeTypeGuesser());
|
||||
if (extension_loaded('fileinfo')) {
|
||||
$this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
|
||||
} else {
|
||||
$this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
|
||||
}
|
||||
$this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test'));
|
||||
}
|
||||
|
||||
public function testGuessImageWithKnownExtension()
|
||||
{
|
||||
if (extension_loaded('fileinfo')) {
|
||||
$this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif'));
|
||||
} else {
|
||||
$this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif'));
|
||||
}
|
||||
$this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test.gif'));
|
||||
}
|
||||
|
||||
public function testGuessFileWithUnknownExtension()
|
||||
{
|
||||
if (extension_loaded('fileinfo')) {
|
||||
$this->assertEquals('application/octet-stream', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension'));
|
||||
} else {
|
||||
$this->assertNull(MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension'));
|
||||
}
|
||||
$this->assertEquals('application/octet-stream', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/.unknownextension'));
|
||||
}
|
||||
|
||||
public function testGuessWithIncorrectPath()
|
||||
@@ -75,7 +62,7 @@ class MimeTypeTest extends \PHPUnit_Framework_TestCase
|
||||
$this->markTestSkipped('Can not verify chmod operations on Windows');
|
||||
}
|
||||
|
||||
if ('root' === get_current_user()) {
|
||||
if (!getenv('USER') || 'root' === getenv('USER')) {
|
||||
$this->markTestSkipped('This test will fail if run under superuser');
|
||||
}
|
||||
|
||||
@@ -83,7 +70,7 @@ class MimeTypeTest extends \PHPUnit_Framework_TestCase
|
||||
touch($path);
|
||||
@chmod($path, 0333);
|
||||
|
||||
if (get_current_user() != 'root' && substr(sprintf('%o', fileperms($path)), -4) == '0333') {
|
||||
if (substr(sprintf('%o', fileperms($path)), -4) == '0333') {
|
||||
$this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException');
|
||||
MimeTypeGuesser::getInstance()->guess($path);
|
||||
} else {
|
@@ -164,8 +164,8 @@ class UploadedFileTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$movedFile = $file->move(__DIR__.'/Fixtures/directory');
|
||||
|
||||
$this->assertTrue(file_exists($targetPath));
|
||||
$this->assertFalse(file_exists($path));
|
||||
$this->assertFileExists($targetPath);
|
||||
$this->assertFileNotExists($path);
|
||||
$this->assertEquals(realpath($targetPath), $movedFile->getRealPath());
|
||||
|
||||
@unlink($targetPath);
|
@@ -15,9 +15,6 @@ use Symfony\Component\HttpFoundation\HeaderBag;
|
||||
|
||||
class HeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\HeaderBag::__construct
|
||||
*/
|
||||
public function testConstructor()
|
||||
{
|
||||
$bag = new HeaderBag(array('foo' => 'bar'));
|
||||
@@ -67,9 +64,6 @@ class HeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('#a', $bag->getCacheControlDirective('public'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\HeaderBag::all
|
||||
*/
|
||||
public function testAll()
|
||||
{
|
||||
$bag = new HeaderBag(array('foo' => 'bar'));
|
||||
@@ -79,9 +73,6 @@ class HeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(array('foo' => array('BAR')), $bag->all(), '->all() gets all the input key are lower case');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\HeaderBag::replace
|
||||
*/
|
||||
public function testReplace()
|
||||
{
|
||||
$bag = new HeaderBag(array('foo' => 'bar'));
|
||||
@@ -91,9 +82,6 @@ class HeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\HeaderBag::get
|
||||
*/
|
||||
public function testGet()
|
||||
{
|
||||
$bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz'));
|
||||
@@ -119,9 +107,6 @@ class HeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(array('value'), $bag->get('foo', 'nope', false), 'assoc indices of multi-valued headers are ignored');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\HeaderBag::contains
|
||||
*/
|
||||
public function testContains()
|
||||
{
|
||||
$bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz'));
|
||||
@@ -186,9 +171,6 @@ class HeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(10, $bag->getCacheControlDirective('max-age'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\HeaderBag::getIterator
|
||||
*/
|
||||
public function testGetIterator()
|
||||
{
|
||||
$headers = array('foo' => 'bar', 'hello' => 'world', 'third' => 'charm');
|
||||
@@ -203,9 +185,6 @@ class HeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(count($headers), $i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\HeaderBag::count
|
||||
*/
|
||||
public function testCount()
|
||||
{
|
||||
$headers = array('foo' => 'bar', 'HELLO' => 'WORLD');
|
@@ -30,13 +30,13 @@ class IpUtilsTest extends \PHPUnit_Framework_TestCase
|
||||
array(true, '192.168.1.1', '192.168.1.1/1'),
|
||||
array(true, '192.168.1.1', '192.168.1.0/24'),
|
||||
array(false, '192.168.1.1', '1.2.3.4/1'),
|
||||
array(false, '192.168.1.1', '192.168.1/33'),
|
||||
array(false, '192.168.1.1', '192.168.1.1/33'), // invalid subnet
|
||||
array(true, '192.168.1.1', array('1.2.3.4/1', '192.168.1.0/24')),
|
||||
array(true, '192.168.1.1', array('192.168.1.0/24', '1.2.3.4/1')),
|
||||
array(false, '192.168.1.1', array('1.2.3.4/1', '4.3.2.1/1')),
|
||||
array(true, '1.2.3.4', '0.0.0.0/0'),
|
||||
array(false, '1.2.3.4', '256.256.256/0'),
|
||||
array(false, '1.2.3.4', '192.168.1.0/0'),
|
||||
array(true, '1.2.3.4', '192.168.1.0/0'),
|
||||
array(false, '1.2.3.4', '256.256.256/0'), // invalid CIDR notation
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,18 +63,17 @@ class IpUtilsTest extends \PHPUnit_Framework_TestCase
|
||||
array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '2a01:198:603:0::/65')),
|
||||
array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('2a01:198:603:0::/65', '::1')),
|
||||
array(false, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '1a01:198:603:0::/65')),
|
||||
array(false, '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2', '::1'),
|
||||
array(false, '2a01:198:603:0:396e:4789:8e99:890f', 'unknown'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @requires extension sockets
|
||||
*/
|
||||
public function testAnIpv6WithOptionDisabledIpv6()
|
||||
{
|
||||
if (!extension_loaded('sockets')) {
|
||||
$this->markTestSkipped('Only works when the socket extension is enabled');
|
||||
}
|
||||
|
||||
if (defined('AF_INET6')) {
|
||||
$this->markTestSkipped('Only works when PHP is compiled with the option "disable-ipv6".');
|
||||
}
|
@@ -208,10 +208,6 @@ class JsonResponseTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testSetContentJsonSerializeError()
|
||||
{
|
||||
if (!interface_exists('JsonSerializable')) {
|
||||
$this->markTestSkipped('Interface JsonSerializable is available in PHP 5.4+');
|
||||
}
|
||||
|
||||
$serializable = new JsonSerializableObject();
|
||||
|
||||
JsonResponse::create($serializable);
|
@@ -15,17 +15,11 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::__construct
|
||||
*/
|
||||
public function testConstructor()
|
||||
{
|
||||
$this->testAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::all
|
||||
*/
|
||||
public function testAll()
|
||||
{
|
||||
$bag = new ParameterBag(array('foo' => 'bar'));
|
||||
@@ -54,9 +48,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(array('foo' => 'bar'), $bag->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::replace
|
||||
*/
|
||||
public function testReplace()
|
||||
{
|
||||
$bag = new ParameterBag(array('foo' => 'bar'));
|
||||
@@ -66,9 +57,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::get
|
||||
*/
|
||||
public function testGet()
|
||||
{
|
||||
$bag = new ParameterBag(array('foo' => 'bar', 'null' => null));
|
||||
@@ -85,40 +73,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertNull($bag->get('foo[bar]'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getInvalidPaths
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testGetDeepWithInvalidPaths($path)
|
||||
{
|
||||
$bag = new ParameterBag(array('foo' => array('bar' => 'moo')));
|
||||
|
||||
$bag->get($path, null, true);
|
||||
}
|
||||
|
||||
public function getInvalidPaths()
|
||||
{
|
||||
return array(
|
||||
array('foo[['),
|
||||
array('foo[d'),
|
||||
array('foo[bar]]'),
|
||||
array('foo[bar]d'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetDeep()
|
||||
{
|
||||
$bag = new ParameterBag(array('foo' => array('bar' => array('moo' => 'boo'))));
|
||||
|
||||
$this->assertEquals(array('moo' => 'boo'), $bag->get('foo[bar]', null, true));
|
||||
$this->assertEquals('boo', $bag->get('foo[bar][moo]', null, true));
|
||||
$this->assertEquals('default', $bag->get('foo[bar][foo]', 'default', true));
|
||||
$this->assertEquals('default', $bag->get('bar[moo][foo]', 'default', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::set
|
||||
*/
|
||||
public function testSet()
|
||||
{
|
||||
$bag = new ParameterBag(array());
|
||||
@@ -130,9 +84,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::has
|
||||
*/
|
||||
public function testHas()
|
||||
{
|
||||
$bag = new ParameterBag(array('foo' => 'bar'));
|
||||
@@ -141,9 +92,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertFalse($bag->has('unknown'), '->has() return false if a parameter is not defined');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::getAlpha
|
||||
*/
|
||||
public function testGetAlpha()
|
||||
{
|
||||
$bag = new ParameterBag(array('word' => 'foo_BAR_012'));
|
||||
@@ -152,9 +100,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('', $bag->getAlpha('unknown'), '->getAlpha() returns empty string if a parameter is not defined');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::getAlnum
|
||||
*/
|
||||
public function testGetAlnum()
|
||||
{
|
||||
$bag = new ParameterBag(array('word' => 'foo_BAR_012'));
|
||||
@@ -163,9 +108,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('', $bag->getAlnum('unknown'), '->getAlnum() returns empty string if a parameter is not defined');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::getDigits
|
||||
*/
|
||||
public function testGetDigits()
|
||||
{
|
||||
$bag = new ParameterBag(array('word' => 'foo_BAR_012'));
|
||||
@@ -174,9 +116,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('', $bag->getDigits('unknown'), '->getDigits() returns empty string if a parameter is not defined');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::getInt
|
||||
*/
|
||||
public function testGetInt()
|
||||
{
|
||||
$bag = new ParameterBag(array('digits' => '0123'));
|
||||
@@ -185,9 +124,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(0, $bag->getInt('unknown'), '->getInt() returns zero if a parameter is not defined');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::filter
|
||||
*/
|
||||
public function testFilter()
|
||||
{
|
||||
$bag = new ParameterBag(array(
|
||||
@@ -201,31 +137,28 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertEmpty($bag->filter('nokey'), '->filter() should return empty by default if no key is found');
|
||||
|
||||
$this->assertEquals('0123', $bag->filter('digits', '', false, FILTER_SANITIZE_NUMBER_INT), '->filter() gets a value of parameter as integer filtering out invalid characters');
|
||||
$this->assertEquals('0123', $bag->filter('digits', '', FILTER_SANITIZE_NUMBER_INT), '->filter() gets a value of parameter as integer filtering out invalid characters');
|
||||
|
||||
$this->assertEquals('example@example.com', $bag->filter('email', '', false, FILTER_VALIDATE_EMAIL), '->filter() gets a value of parameter as email');
|
||||
$this->assertEquals('example@example.com', $bag->filter('email', '', FILTER_VALIDATE_EMAIL), '->filter() gets a value of parameter as email');
|
||||
|
||||
$this->assertEquals('http://example.com/foo', $bag->filter('url', '', false, FILTER_VALIDATE_URL, array('flags' => FILTER_FLAG_PATH_REQUIRED)), '->filter() gets a value of parameter as URL with a path');
|
||||
$this->assertEquals('http://example.com/foo', $bag->filter('url', '', FILTER_VALIDATE_URL, array('flags' => FILTER_FLAG_PATH_REQUIRED)), '->filter() gets a value of parameter as URL with a path');
|
||||
|
||||
// This test is repeated for code-coverage
|
||||
$this->assertEquals('http://example.com/foo', $bag->filter('url', '', false, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED), '->filter() gets a value of parameter as URL with a path');
|
||||
$this->assertEquals('http://example.com/foo', $bag->filter('url', '', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED), '->filter() gets a value of parameter as URL with a path');
|
||||
|
||||
$this->assertFalse($bag->filter('dec', '', false, FILTER_VALIDATE_INT, array(
|
||||
$this->assertFalse($bag->filter('dec', '', FILTER_VALIDATE_INT, array(
|
||||
'flags' => FILTER_FLAG_ALLOW_HEX,
|
||||
'options' => array('min_range' => 1, 'max_range' => 0xff),
|
||||
)), '->filter() gets a value of parameter as integer between boundaries');
|
||||
|
||||
$this->assertFalse($bag->filter('hex', '', false, FILTER_VALIDATE_INT, array(
|
||||
$this->assertFalse($bag->filter('hex', '', FILTER_VALIDATE_INT, array(
|
||||
'flags' => FILTER_FLAG_ALLOW_HEX,
|
||||
'options' => array('min_range' => 1, 'max_range' => 0xff),
|
||||
)), '->filter() gets a value of parameter as integer between boundaries');
|
||||
|
||||
$this->assertEquals(array('bang'), $bag->filter('array', '', false), '->filter() gets a value of parameter as an array');
|
||||
$this->assertEquals(array('bang'), $bag->filter('array', ''), '->filter() gets a value of parameter as an array');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::getIterator
|
||||
*/
|
||||
public function testGetIterator()
|
||||
{
|
||||
$parameters = array('foo' => 'bar', 'hello' => 'world');
|
||||
@@ -240,9 +173,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(count($parameters), $i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::count
|
||||
*/
|
||||
public function testCount()
|
||||
{
|
||||
$parameters = array('foo' => 'bar', 'hello' => 'world');
|
||||
@@ -251,9 +181,6 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(count($parameters), count($bag));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ParameterBag::getBoolean
|
||||
*/
|
||||
public function testGetBoolean()
|
||||
{
|
||||
$parameters = array('string_true' => 'true', 'string_false' => 'false');
|
@@ -17,17 +17,6 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::__construct
|
||||
*/
|
||||
public function testConstructor()
|
||||
{
|
||||
$this->testInitialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::initialize
|
||||
*/
|
||||
public function testInitialize()
|
||||
{
|
||||
$request = new Request();
|
||||
@@ -94,9 +83,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('pl', $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::create
|
||||
*/
|
||||
public function testCreate()
|
||||
{
|
||||
$request = Request::create('http://test.com/foo?bar=baz');
|
||||
@@ -224,7 +210,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('/?foo', $request->getRequestUri());
|
||||
$this->assertEquals(array('foo' => ''), $request->query->all());
|
||||
|
||||
## assume rewrite rule: (.*) --> app/app.php ; app/ is a symlink to a symfony web/ directory
|
||||
// assume rewrite rule: (.*) --> app/app.php; app/ is a symlink to a symfony web/ directory
|
||||
$request = Request::create('http://test.com/apparthotel-1234', 'GET', array(), array(), array(),
|
||||
array(
|
||||
'DOCUMENT_ROOT' => '/var/www/www.test.com',
|
||||
@@ -240,9 +226,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertFalse($request->isSecure());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::create
|
||||
*/
|
||||
public function testCreateCheckPrecedence()
|
||||
{
|
||||
// server is used by default
|
||||
@@ -311,8 +294,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getFormat
|
||||
* @covers Symfony\Component\HttpFoundation\Request::setFormat
|
||||
* @dataProvider getFormatToMimeTypeMapProvider
|
||||
*/
|
||||
public function testGetFormatFromMimeType($format, $mimeTypes)
|
||||
@@ -327,9 +308,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getFormat
|
||||
*/
|
||||
public function testGetFormatFromMimeTypeWithParameters()
|
||||
{
|
||||
$request = new Request();
|
||||
@@ -337,7 +315,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getMimeType
|
||||
* @dataProvider getFormatToMimeTypeMapProvider
|
||||
*/
|
||||
public function testGetMimeTypeFromFormat($format, $mimeTypes)
|
||||
@@ -348,6 +325,13 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetFormatWithCustomMimeType()
|
||||
{
|
||||
$request = new Request();
|
||||
$request->setFormat('custom', 'application/vnd.foo.api;myversion=2.3');
|
||||
$this->assertEquals('custom', $request->getFormat('application/vnd.foo.api;myversion=2.3'));
|
||||
}
|
||||
|
||||
public function getFormatToMimeTypeMapProvider()
|
||||
{
|
||||
return array(
|
||||
@@ -358,13 +342,10 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
array('json', array('application/json', 'application/x-json')),
|
||||
array('xml', array('text/xml', 'application/xml', 'application/x-xml')),
|
||||
array('rdf', array('application/rdf+xml')),
|
||||
array('atom',array('application/atom+xml')),
|
||||
array('atom', array('application/atom+xml')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getUri
|
||||
*/
|
||||
public function testGetUri()
|
||||
{
|
||||
$server = array();
|
||||
@@ -480,9 +461,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getUriForPath
|
||||
*/
|
||||
public function testGetUriForPath()
|
||||
{
|
||||
$request = Request::create('http://test.com/foo?bar=baz');
|
||||
@@ -591,13 +569,30 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getUserInfo
|
||||
* @dataProvider getRelativeUriForPathData()
|
||||
*/
|
||||
public function testGetRelativeUriForPath($expected, $pathinfo, $path)
|
||||
{
|
||||
$this->assertEquals($expected, Request::create($pathinfo)->getRelativeUriForPath($path));
|
||||
}
|
||||
|
||||
public function getRelativeUriForPathData()
|
||||
{
|
||||
return array(
|
||||
array('me.png', '/foo', '/me.png'),
|
||||
array('../me.png', '/foo/bar', '/me.png'),
|
||||
array('me.png', '/foo/bar', '/foo/me.png'),
|
||||
array('../baz/me.png', '/foo/bar/b', '/foo/baz/me.png'),
|
||||
array('../../fooz/baz/me.png', '/foo/bar/b', '/fooz/baz/me.png'),
|
||||
array('baz/me.png', '/foo/bar/b', 'baz/me.png'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetUserInfo()
|
||||
{
|
||||
$request = new Request();
|
||||
|
||||
$server['PHP_AUTH_USER'] = 'fabien';
|
||||
$server = array('PHP_AUTH_USER' => 'fabien');
|
||||
$request->initialize(array(), array(), array(), array(), array(), $server);
|
||||
$this->assertEquals('fabien', $request->getUserInfo());
|
||||
|
||||
@@ -610,9 +605,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('0:0', $request->getUserInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getSchemeAndHttpHost
|
||||
*/
|
||||
public function testGetSchemeAndHttpHost()
|
||||
{
|
||||
$request = new Request();
|
||||
@@ -637,8 +629,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getQueryString
|
||||
* @covers Symfony\Component\HttpFoundation\Request::normalizeQueryString
|
||||
* @dataProvider getQueryStringNormalizationData
|
||||
*/
|
||||
public function testGetQueryString($query, $expectedQuery, $msg)
|
||||
@@ -774,10 +764,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$request->getHost();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Request::setMethod
|
||||
* @covers Symfony\Component\HttpFoundation\Request::getMethod
|
||||
*/
|
||||
public function testGetSetMethod()
|
||||
{
|
||||
$request = new Request();
|
||||
@@ -857,6 +843,31 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
Request::setTrustedProxies(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider testGetClientIpsForwardedProvider
|
||||
*/
|
||||
public function testGetClientIpsForwarded($expected, $remoteAddr, $httpForwarded, $trustedProxies)
|
||||
{
|
||||
$request = $this->getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies);
|
||||
|
||||
$this->assertEquals($expected, $request->getClientIps());
|
||||
|
||||
Request::setTrustedProxies(array());
|
||||
}
|
||||
|
||||
public function testGetClientIpsForwardedProvider()
|
||||
{
|
||||
// $expected $remoteAddr $httpForwarded $trustedProxies
|
||||
return array(
|
||||
array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', null),
|
||||
array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')),
|
||||
array(array('88.88.88.88'), '127.0.0.1', 'for="88.88.88.88:80"', array('127.0.0.1')),
|
||||
array(array('192.0.2.60'), '::1', 'for=192.0.2.60;proto=http;by=203.0.113.43', array('::1')),
|
||||
array(array('2620:0:1cfe:face:b00c::3', '192.0.2.43'), '::1', 'for=192.0.2.43, for=2620:0:1cfe:face:b00c::3', array('::1')),
|
||||
array(array('2001:db8:cafe::17'), '::1', 'for="[2001:db8:cafe::17]:4711', array('::1')),
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetClientIpsProvider()
|
||||
{
|
||||
// $expected $remoteAddr $httpForwardedFor $trustedProxies
|
||||
@@ -905,6 +916,10 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
// client IP with port
|
||||
array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88:12345, 127.0.0.1', array('127.0.0.1')),
|
||||
|
||||
// invalid forwarded IP is ignored
|
||||
array(array('88.88.88.88'), '127.0.0.1', 'unknown,88.88.88.88', array('127.0.0.1')),
|
||||
array(array('88.88.88.88'), '127.0.0.1', '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2,88.88.88.88', array('127.0.0.1')),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -935,7 +950,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testContentAsResource()
|
||||
{
|
||||
$resource = fopen('php://memory','r+');
|
||||
$resource = fopen('php://memory', 'r+');
|
||||
fwrite($resource, 'My other content');
|
||||
rewind($resource);
|
||||
|
||||
@@ -961,13 +976,10 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
/**
|
||||
* @dataProvider getContentCantBeCalledTwiceWithResourcesProvider
|
||||
* @requires PHP 5.6
|
||||
*/
|
||||
public function testGetContentCanBeCalledTwiceWithResources($first, $second)
|
||||
{
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
$this->markTestSkipped('PHP < 5.6 does not allow to open php://input several times.');
|
||||
}
|
||||
|
||||
$req = new Request();
|
||||
$a = $req->getContent($first);
|
||||
$b = $req->getContent($second);
|
||||
@@ -1176,6 +1188,25 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('/path%20test/info', $request->getPathInfo());
|
||||
}
|
||||
|
||||
public function testGetParameterPrecedence()
|
||||
{
|
||||
$request = new Request();
|
||||
$request->attributes->set('foo', 'attr');
|
||||
$request->query->set('foo', 'query');
|
||||
$request->request->set('foo', 'body');
|
||||
|
||||
$this->assertSame('attr', $request->get('foo'));
|
||||
|
||||
$request->attributes->remove('foo');
|
||||
$this->assertSame('query', $request->get('foo'));
|
||||
|
||||
$request->query->remove('foo');
|
||||
$this->assertSame('body', $request->get('foo'));
|
||||
|
||||
$request->request->remove('foo');
|
||||
$this->assertNull($request->get('foo'));
|
||||
}
|
||||
|
||||
public function testGetPreferredLanguage()
|
||||
{
|
||||
$request = new Request();
|
||||
@@ -1215,12 +1246,11 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertFalse($request->isXmlHttpRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension intl
|
||||
*/
|
||||
public function testIntlLocale()
|
||||
{
|
||||
if (!extension_loaded('intl')) {
|
||||
$this->markTestSkipped('The intl extension is needed to run this test.');
|
||||
}
|
||||
|
||||
$request = new Request();
|
||||
|
||||
$request->setDefaultLocale('fr');
|
||||
@@ -1318,6 +1348,9 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$request = new Request();
|
||||
$this->assertNull($request->setRequestFormat('foo'));
|
||||
$this->assertEquals('foo', $request->getRequestFormat(null));
|
||||
|
||||
$request = new Request(array('_format' => 'foo'));
|
||||
$this->assertEquals('html', $request->getRequestFormat());
|
||||
}
|
||||
|
||||
public function testHasSession()
|
||||
@@ -1518,6 +1551,25 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
return $request;
|
||||
}
|
||||
|
||||
private function getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies)
|
||||
{
|
||||
$request = new Request();
|
||||
|
||||
$server = array('REMOTE_ADDR' => $remoteAddr);
|
||||
|
||||
if (null !== $httpForwarded) {
|
||||
$server['HTTP_FORWARDED'] = $httpForwarded;
|
||||
}
|
||||
|
||||
if ($trustedProxies) {
|
||||
Request::setTrustedProxies($trustedProxies);
|
||||
}
|
||||
|
||||
$request->initialize(array(), array(), array(), array(), array(), $server);
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
public function testTrustedProxies()
|
||||
{
|
||||
$request = Request::create('http://example.com/');
|
||||
@@ -1544,6 +1596,13 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(80, $request->getPort());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
// request is forwarded by a non-trusted proxy
|
||||
Request::setTrustedProxies(array('2.2.2.2'));
|
||||
$this->assertEquals('3.3.3.3', $request->getClientIp());
|
||||
$this->assertEquals('example.com', $request->getHost());
|
||||
$this->assertEquals(80, $request->getPort());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
// trusted proxy via setTrustedProxies()
|
||||
Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'));
|
||||
$this->assertEquals('1.1.1.1', $request->getClientIp());
|
||||
@@ -1765,7 +1824,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$request = Request::create('/');
|
||||
$request->headers->set('host', $host);
|
||||
$this->assertEquals($host, $request->getHost());
|
||||
$this->assertLessThan(1, microtime(true) - $start);
|
||||
$this->assertLessThan(5, microtime(true) - $start);
|
||||
}
|
||||
|
||||
/**
|
@@ -14,12 +14,12 @@ namespace Symfony\Component\HttpFoundation\Tests;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
|
||||
require_once __DIR__.'/ClockMock.php';
|
||||
|
||||
/**
|
||||
* @group time-sensitive
|
||||
*/
|
||||
class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\ResponseHeaderBag::allPreserveCase
|
||||
* @dataProvider provideAllPreserveCase
|
||||
*/
|
||||
public function testAllPreserveCase($headers, $expected)
|
@@ -14,6 +14,9 @@ namespace Symfony\Component\HttpFoundation\Tests;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* @group time-sensitive
|
||||
*/
|
||||
class ResponseTest extends ResponseTestCase
|
||||
{
|
||||
public function testCreate()
|
||||
@@ -105,6 +108,22 @@ class ResponseTest extends ResponseTestCase
|
||||
$this->assertFalse($response->mustRevalidate());
|
||||
}
|
||||
|
||||
public function testMustRevalidateWithMustRevalidateCacheControlHeader()
|
||||
{
|
||||
$response = new Response();
|
||||
$response->headers->set('cache-control', 'must-revalidate');
|
||||
|
||||
$this->assertTrue($response->mustRevalidate());
|
||||
}
|
||||
|
||||
public function testMustRevalidateWithProxyRevalidateCacheControlHeader()
|
||||
{
|
||||
$response = new Response();
|
||||
$response->headers->set('cache-control', 'proxy-revalidate');
|
||||
|
||||
$this->assertTrue($response->mustRevalidate());
|
||||
}
|
||||
|
||||
public function testSetNotModified()
|
||||
{
|
||||
$response = new Response();
|
||||
@@ -243,16 +262,18 @@ class ResponseTest extends ResponseTestCase
|
||||
{
|
||||
$oneHourAgo = $this->createDateTimeOneHourAgo();
|
||||
$response = new Response('', 200, array('Date' => $oneHourAgo->format(DATE_RFC2822)));
|
||||
$this->assertEquals(0, $oneHourAgo->diff($response->getDate())->format('%s'), '->getDate() returns the Date header if present');
|
||||
$date = $response->getDate();
|
||||
$this->assertEquals($oneHourAgo->getTimestamp(), $date->getTimestamp(), '->getDate() returns the Date header if present');
|
||||
|
||||
$response = new Response();
|
||||
$date = $response->getDate();
|
||||
$this->assertLessThan(1, $date->diff(new \DateTime(), true)->format('%s'), '->getDate() returns the current Date if no Date header present');
|
||||
$this->assertEquals(time(), $date->getTimestamp(), '->getDate() returns the current Date if no Date header present');
|
||||
|
||||
$response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)));
|
||||
$now = $this->createDateTimeNow();
|
||||
$response->headers->set('Date', $now->format(DATE_RFC2822));
|
||||
$this->assertLessThanOrEqual(1, $now->diff($response->getDate())->format('%s'), '->getDate() returns the date when the header has been modified');
|
||||
$date = $response->getDate();
|
||||
$this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the date when the header has been modified');
|
||||
|
||||
$response = new Response('', 200);
|
||||
$response->headers->remove('Date');
|
||||
@@ -272,7 +293,7 @@ class ResponseTest extends ResponseTestCase
|
||||
$response = new Response();
|
||||
$response->headers->set('Cache-Control', 'must-revalidate');
|
||||
$response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822));
|
||||
$this->assertLessThanOrEqual(1, $response->getMaxAge() - 3600, '->getMaxAge() falls back to Expires when no max-age or s-maxage directive present');
|
||||
$this->assertEquals(3600, $response->getMaxAge(), '->getMaxAge() falls back to Expires when no max-age or s-maxage directive present');
|
||||
|
||||
$response = new Response();
|
||||
$response->headers->set('Cache-Control', 'must-revalidate');
|
||||
@@ -343,7 +364,7 @@ class ResponseTest extends ResponseTestCase
|
||||
|
||||
$response = new Response();
|
||||
$response->headers->set('Expires', $this->createDateTimeOneHourLater()->format(DATE_RFC2822));
|
||||
$this->assertLessThanOrEqual(1, 3600 - $response->getTtl(), '->getTtl() uses the Expires header when no max-age is present');
|
||||
$this->assertEquals(3600, $response->getTtl(), '->getTtl() uses the Expires header when no max-age is present');
|
||||
|
||||
$response = new Response();
|
||||
$response->headers->set('Expires', $this->createDateTimeOneHourAgo()->format(DATE_RFC2822));
|
||||
@@ -356,7 +377,7 @@ class ResponseTest extends ResponseTestCase
|
||||
|
||||
$response = new Response();
|
||||
$response->headers->set('Cache-Control', 'max-age=60');
|
||||
$this->assertLessThan(1, 60 - $response->getTtl(), '->getTtl() uses Cache-Control max-age when present');
|
||||
$this->assertEquals(60, $response->getTtl(), '->getTtl() uses Cache-Control max-age when present');
|
||||
}
|
||||
|
||||
public function testSetClientTtl()
|
||||
@@ -556,7 +577,7 @@ class ResponseTest extends ResponseTestCase
|
||||
$response->setCache($options);
|
||||
$this->assertEquals($response->getEtag(), '"whatever"');
|
||||
|
||||
$now = new \DateTime();
|
||||
$now = $this->createDateTimeNow();
|
||||
$options = array('last_modified' => $now);
|
||||
$response->setCache($options);
|
||||
$this->assertEquals($response->getLastModified()->getTimestamp(), $now->getTimestamp());
|
||||
@@ -615,7 +636,7 @@ class ResponseTest extends ResponseTestCase
|
||||
|
||||
$this->assertNull($response->getExpires(), '->setExpires() remove the header when passed null');
|
||||
|
||||
$now = new \DateTime();
|
||||
$now = $this->createDateTimeNow();
|
||||
$response->setExpires($now);
|
||||
|
||||
$this->assertEquals($response->getExpires()->getTimestamp(), $now->getTimestamp());
|
||||
@@ -624,7 +645,7 @@ class ResponseTest extends ResponseTestCase
|
||||
public function testSetLastModified()
|
||||
{
|
||||
$response = new Response();
|
||||
$response->setLastModified(new \DateTime());
|
||||
$response->setLastModified($this->createDateTimeNow());
|
||||
$this->assertNotNull($response->getLastModified());
|
||||
|
||||
$response->setLastModified(null);
|
||||
@@ -674,7 +695,7 @@ class ResponseTest extends ResponseTestCase
|
||||
array('200', null, 'OK'),
|
||||
array('200', false, ''),
|
||||
array('200', 'foo', 'foo'),
|
||||
array('199', null, ''),
|
||||
array('199', null, 'unknown status'),
|
||||
array('199', false, ''),
|
||||
array('199', 'foo', 'foo'),
|
||||
);
|
||||
@@ -809,7 +830,7 @@ class ResponseTest extends ResponseTestCase
|
||||
'setCharset' => 'UTF-8',
|
||||
'setPublic' => null,
|
||||
'setPrivate' => null,
|
||||
'setDate' => new \DateTime(),
|
||||
'setDate' => $this->createDateTimeNow(),
|
||||
'expire' => null,
|
||||
'setMaxAge' => 1,
|
||||
'setSharedMaxAge' => 1,
|
||||
@@ -842,21 +863,19 @@ class ResponseTest extends ResponseTestCase
|
||||
|
||||
protected function createDateTimeOneHourAgo()
|
||||
{
|
||||
$date = new \DateTime();
|
||||
|
||||
return $date->sub(new \DateInterval('PT1H'));
|
||||
return $this->createDateTimeNow()->sub(new \DateInterval('PT1H'));
|
||||
}
|
||||
|
||||
protected function createDateTimeOneHourLater()
|
||||
{
|
||||
$date = new \DateTime();
|
||||
|
||||
return $date->add(new \DateInterval('PT1H'));
|
||||
return $this->createDateTimeNow()->add(new \DateInterval('PT1H'));
|
||||
}
|
||||
|
||||
protected function createDateTimeNow()
|
||||
{
|
||||
return new \DateTime();
|
||||
$date = new \DateTime();
|
||||
|
||||
return $date->setTimestamp(time());
|
||||
}
|
||||
|
||||
protected function provideResponse()
|
@@ -151,4 +151,19 @@ class ServerBagTest extends \PHPUnit_Framework_TestCase
|
||||
'AUTHORIZATION' => $headerContent,
|
||||
), $bag->getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/symfony/symfony/issues/17345
|
||||
*/
|
||||
public function testItDoesNotOverwriteTheAuthorizationHeaderIfItIsAlreadySet()
|
||||
{
|
||||
$headerContent = 'Bearer L-yLEOr9zhmUYRkzN1jwwxwQ-PBNiKDc8dgfB4hTfvo';
|
||||
$bag = new ServerBag(array('PHP_AUTH_USER' => 'foo', 'HTTP_AUTHORIZATION' => $headerContent));
|
||||
|
||||
$this->assertEquals(array(
|
||||
'AUTHORIZATION' => $headerContent,
|
||||
'PHP_AUTH_USER' => 'foo',
|
||||
'PHP_AUTH_PW' => '',
|
||||
), $bag->getHeaders());
|
||||
}
|
||||
}
|
@@ -43,8 +43,9 @@ class AttributeBagTest extends \PHPUnit_Framework_TestCase
|
||||
'category' => array(
|
||||
'fishing' => array(
|
||||
'first' => 'cod',
|
||||
'second' => 'sole',),
|
||||
'second' => 'sole',
|
||||
),
|
||||
),
|
||||
);
|
||||
$this->bag = new AttributeBag('_sf2');
|
||||
$this->bag->initialize($this->array);
|
||||
@@ -169,9 +170,6 @@ class AttributeBagTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag::getIterator
|
||||
*/
|
||||
public function testGetIterator()
|
||||
{
|
||||
$i = 0;
|
||||
@@ -183,9 +181,6 @@ class AttributeBagTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(count($this->array), $i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag::count
|
||||
*/
|
||||
public function testCount()
|
||||
{
|
||||
$this->assertEquals(count($this->array), count($this->bag));
|
@@ -43,8 +43,9 @@ class NamespacedAttributeBagTest extends \PHPUnit_Framework_TestCase
|
||||
'category' => array(
|
||||
'fishing' => array(
|
||||
'first' => 'cod',
|
||||
'second' => 'sole',),
|
||||
'second' => 'sole',
|
||||
),
|
||||
),
|
||||
);
|
||||
$this->bag = new NamespacedAttributeBag('_sf2', '/');
|
||||
$this->bag->initialize($this->array);
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user