Update to Drupal 8.1.0. For more information, see https://www.drupal.org/drupal-8.1.0-release-notes

This commit is contained in:
Pantheon Automation 2016-04-20 09:56:34 -07:00 committed by Greg Anderson
parent b11a755ba8
commit c0a0d5a94c
6920 changed files with 64395 additions and 57312 deletions

View file

@ -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;
}
/**

View file

@ -1,6 +1,12 @@
CHANGELOG
=========
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
-----

View file

@ -29,13 +29,13 @@ 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
*/
@ -51,7 +51,7 @@ class Cookie
}
// convert expiration time to a Unix timestamp
if ($expire instanceof \DateTime) {
if ($expire instanceof \DateTime || $expire instanceof \DateTimeInterface) {
$expire = $expire->format('U');
} elseif (!is_numeric($expire)) {
$expire = strtotime($expire);

View file

@ -111,7 +111,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
*/
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) {
@ -137,7 +137,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
*/
public function set($key, $values, $replace = true)
{
$key = strtr(strtolower($key), '_', '-');
$key = str_replace('_', '-', strtolower($key));
$values = array_values((array) $values);
@ -161,7 +161,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
*/
public function has($key)
{
return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers);
return array_key_exists(str_replace('_', '-', strtolower($key)), $this->headers);
}
/**
@ -184,7 +184,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
*/
public function remove($key)
{
$key = strtr(strtolower($key), '_', '-');
$key = str_replace('_', '-', strtolower($key));
unset($this->headers[$key]);

View file

@ -112,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);

View file

@ -106,7 +106,7 @@ class JsonResponse extends Response
// 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);
set_error_handler(function () { return false; });
$data = @json_encode($data, $this->encodingOptions);
} else {
// PHP 5.4 and up wrap exceptions thrown by JsonSerializable
@ -142,7 +142,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 +196,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.';
}
}
}

View file

@ -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

View file

@ -78,7 +78,9 @@ class ParameterBag implements \IteratorAggregate, \Countable
/**
* Returns a parameter by name.
*
* @param string $path The key
* Note: Finding deep items is deprecated since version 2.8, to be removed in 3.0.
*
* @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
*
@ -86,21 +88,25 @@ class ParameterBag implements \IteratorAggregate, \Countable
*
* @throws \InvalidArgumentException
*/
public function get($path, $default = null, $deep = false)
public function get($key, $default = null, $deep = false)
{
if (!$deep || false === $pos = strpos($path, '[')) {
return array_key_exists($path, $this->parameters) ? $this->parameters[$path] : $default;
if ($deep) {
@trigger_error('Using paths to find deeper items in '.__METHOD__.' is deprecated since version 2.8 and will be removed in 3.0. Filter the returned value in your own code instead.', E_USER_DEPRECATED);
}
$root = substr($path, 0, $pos);
if (!$deep || false === $pos = strpos($key, '[')) {
return array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default;
}
$root = substr($key, 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];
for ($i = $pos, $c = strlen($key); $i < $c; ++$i) {
$char = $key[$i];
if ('[' === $char) {
if (null !== $currentKey) {
@ -172,7 +178,7 @@ 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 string $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 string The filtered value
@ -186,7 +192,7 @@ class ParameterBag implements \IteratorAggregate, \Countable
* 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 string $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 string The filtered value
@ -200,7 +206,7 @@ class ParameterBag implements \IteratorAggregate, \Countable
* 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 string $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 string The filtered value
@ -208,14 +214,14 @@ class ParameterBag implements \IteratorAggregate, \Countable
public function getDigits($key, $default = '', $deep = false)
{
// 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, array(), $deep));
}
/**
* 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 int $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 int The filtered value
@ -236,7 +242,7 @@ class ParameterBag implements \IteratorAggregate, \Countable
*/
public function getBoolean($key, $default = false, $deep = false)
{
return $this->filter($key, $default, $deep, FILTER_VALIDATE_BOOLEAN);
return $this->filter($key, $default, FILTER_VALIDATE_BOOLEAN, array(), $deep);
}
/**
@ -244,16 +250,31 @@ 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.
* @param bool $deep Default = false.
*
* @see http://php.net/manual/en/function.filter-var.php
*
* @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(), $deep = false)
{
static $filters = null;
if (null === $filters) {
foreach (filter_list() as $tmp) {
$filters[filter_id($tmp)] = 1;
}
}
if (is_bool($filter) || !isset($filters[$filter]) || is_array($deep)) {
@trigger_error('Passing the $deep boolean as 3rd argument to the '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0. Remove it altogether as the $deep argument will be removed in 3.0.', E_USER_DEPRECATED);
$tmp = $deep;
$deep = $filter;
$filter = $options;
$options = $tmp;
}
$value = $this->get($key, $default, $deep);
// Always turn $options into an array - this allows filter_var option shortcuts.

View file

@ -1,56 +1,14 @@
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');
}
```
The HttpFoundation component defines an object-oriented layer for the HTTP
specification.
Resources
---------
You can run the unit tests with the following command:
$ cd path/to/Symfony/Component/HttpFoundation/
$ composer install
$ phpunit
* [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)

View file

@ -23,7 +23,8 @@ 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)
*
@ -33,10 +34,6 @@ class RedirectResponse extends Response
*/
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);

View file

@ -268,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'];
}
@ -714,6 +714,8 @@ class Request
* It is better to explicitly get request parameters from the appropriate
* public property instead (query, attributes, request).
*
* Note: Finding deep items is deprecated since version 2.8, to be removed in 3.0.
*
* @param string $key the key
* @param mixed $default the default value
* @param bool $deep is parameter deep in multidimensional array
@ -722,6 +724,10 @@ class Request
*/
public function get($key, $default = null, $deep = false)
{
if ($deep) {
@trigger_error('Using paths to find deeper items in '.__METHOD__.' is deprecated since version 2.8 and will be removed in 3.0. Filter the returned value in your own code instead.', E_USER_DEPRECATED);
}
if ($this !== $result = $this->query->get($key, $this, $deep)) {
return $result;
}
@ -814,7 +820,7 @@ class Request
}
$clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
$ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies
$firstTrustedIp = null;
foreach ($clientIps as $key => $clientIp) {
// Remove port (unfortunately, it does happen)
@ -822,13 +828,24 @@ class Request
$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);
}
/**
@ -1326,8 +1343,9 @@ class Request
*/
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) {
@ -1338,6 +1356,9 @@ class Request
if (in_array($mimeType, (array) $mimeTypes)) {
return $format;
}
if (null !== $canonicalMimeType && in_array($canonicalMimeType, (array) $mimeTypes)) {
return $format;
}
}
}
@ -1819,8 +1840,6 @@ class Request
return '/';
}
$pathInfo = '/';
// Remove the query string from REQUEST_URI
if ($pos = strpos($requestUri, '?')) {
$requestUri = substr($requestUri, 0, $pos);

View file

@ -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);
}

View file

@ -67,6 +67,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;
@ -114,7 +115,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 2015-05-19).
*
* Unless otherwise noted, the status code is defined in RFC2616.
*
@ -140,7 +141,6 @@ class Response
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => 'Reserved',
307 => 'Temporary Redirect',
308 => 'Permanent Redirect', // RFC7238
400 => 'Bad Request',
@ -156,10 +156,10 @@ 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
422 => 'Unprocessable Entity', // RFC4918
@ -170,6 +170,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',
@ -198,9 +199,6 @@ class Response
$this->setContent($content);
$this->setStatusCode($status);
$this->setProtocolVersion('1.0');
if (!$this->headers->has('Date')) {
$this->setDate(\DateTime::createFromFormat('U', time(), new \DateTimeZone('UTC')));
}
}
/**
@ -329,8 +327,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) {
@ -339,6 +338,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());
@ -455,7 +457,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;
}
@ -608,7 +610,11 @@ class Response
*/
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');
}
/**
@ -972,7 +978,7 @@ 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
*/
@ -1019,11 +1025,12 @@ class Response
return $notModified;
}
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
/**
* Is response invalid?
*
* @return bool
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
*/
public function isInvalid()
{

View file

@ -99,7 +99,7 @@ class ResponseHeaderBag extends HeaderBag
{
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
@ -118,7 +118,7 @@ class ResponseHeaderBag extends HeaderBag
{
parent::remove($key);
$uniqueKey = strtr(strtolower($key), '_', '-');
$uniqueKey = str_replace('_', '-', strtolower($key));
unset($this->headerNames[$uniqueKey]);
if ('cache-control' === $uniqueKey) {

View file

@ -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']);

View file

@ -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);

View file

@ -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;

View file

@ -101,11 +101,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);
@ -260,6 +256,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;
}
@ -351,7 +351,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

View file

@ -52,7 +52,7 @@ abstract class AbstractProxy
*/
public function isSessionHandlerInterface()
{
return ($this instanceof \SessionHandlerInterface);
return $this instanceof \SessionHandlerInterface;
}
/**

View file

@ -76,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.
@ -101,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

View file

@ -16,19 +16,24 @@
}
],
"require": {
"php": ">=5.3.9"
"php": ">=5.3.9",
"symfony/polyfill-php54": "~1.0",
"symfony/polyfill-php55": "~1.0",
"symfony/polyfill-mbstring": "~1.1"
},
"require-dev": {
"symfony/expression-language": "~2.4"
"symfony/expression-language": "~2.4|~3.0.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\HttpFoundation\\": "" },
"classmap": [ "Resources/stubs" ]
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "2.7-dev"
"dev-master": "2.8-dev"
}
}
}