Laravel version update
Laravel version update
This commit is contained in:
544
vendor/symfony/http-foundation/Request.php
vendored
544
vendor/symfony/http-foundation/Request.php
vendored
@@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\HttpFoundation;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
|
||||
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
/**
|
||||
@@ -29,11 +30,22 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
*/
|
||||
class Request
|
||||
{
|
||||
const HEADER_FORWARDED = 'forwarded';
|
||||
const HEADER_CLIENT_IP = 'client_ip';
|
||||
const HEADER_CLIENT_HOST = 'client_host';
|
||||
const HEADER_CLIENT_PROTO = 'client_proto';
|
||||
const HEADER_CLIENT_PORT = 'client_port';
|
||||
const HEADER_FORWARDED = 0b00001; // When using RFC 7239
|
||||
const HEADER_X_FORWARDED_FOR = 0b00010;
|
||||
const HEADER_X_FORWARDED_HOST = 0b00100;
|
||||
const HEADER_X_FORWARDED_PROTO = 0b01000;
|
||||
const HEADER_X_FORWARDED_PORT = 0b10000;
|
||||
const HEADER_X_FORWARDED_ALL = 0b11110; // All "X-Forwarded-*" headers
|
||||
const HEADER_X_FORWARDED_AWS_ELB = 0b11010; // AWS ELB doesn't send X-Forwarded-Host
|
||||
|
||||
/** @deprecated since version 3.3, to be removed in 4.0 */
|
||||
const HEADER_CLIENT_IP = self::HEADER_X_FORWARDED_FOR;
|
||||
/** @deprecated since version 3.3, to be removed in 4.0 */
|
||||
const HEADER_CLIENT_HOST = self::HEADER_X_FORWARDED_HOST;
|
||||
/** @deprecated since version 3.3, to be removed in 4.0 */
|
||||
const HEADER_CLIENT_PROTO = self::HEADER_X_FORWARDED_PROTO;
|
||||
/** @deprecated since version 3.3, to be removed in 4.0 */
|
||||
const HEADER_CLIENT_PORT = self::HEADER_X_FORWARDED_PORT;
|
||||
|
||||
const METHOD_HEAD = 'HEAD';
|
||||
const METHOD_GET = 'GET';
|
||||
@@ -69,6 +81,8 @@ class Request
|
||||
*
|
||||
* The other headers are non-standard, but widely used
|
||||
* by popular reverse proxies (like Apache mod_proxy or Amazon EC2).
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0
|
||||
*/
|
||||
protected static $trustedHeaders = array(
|
||||
self::HEADER_FORWARDED => 'FORWARDED',
|
||||
@@ -130,7 +144,7 @@ class Request
|
||||
public $headers;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @var string|resource|false|null
|
||||
*/
|
||||
protected $content;
|
||||
|
||||
@@ -206,16 +220,35 @@ class Request
|
||||
|
||||
protected static $requestFactory;
|
||||
|
||||
private $isHostValid = true;
|
||||
private $isForwardedValid = true;
|
||||
|
||||
private static $trustedHeaderSet = -1;
|
||||
|
||||
/** @deprecated since version 3.3, to be removed in 4.0 */
|
||||
private static $trustedHeaderNames = 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',
|
||||
self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT',
|
||||
);
|
||||
|
||||
private static $forwardedParams = array(
|
||||
self::HEADER_X_FORWARDED_FOR => 'for',
|
||||
self::HEADER_X_FORWARDED_HOST => 'host',
|
||||
self::HEADER_X_FORWARDED_PROTO => 'proto',
|
||||
self::HEADER_X_FORWARDED_PORT => 'host',
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $query The GET parameters
|
||||
* @param array $request The POST parameters
|
||||
* @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
|
||||
* @param array $cookies The COOKIE parameters
|
||||
* @param array $files The FILES parameters
|
||||
* @param array $server The SERVER parameters
|
||||
* @param string|resource $content The raw body data
|
||||
* @param array $query The GET parameters
|
||||
* @param array $request The POST parameters
|
||||
* @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
|
||||
* @param array $cookies The COOKIE parameters
|
||||
* @param array $files The FILES parameters
|
||||
* @param array $server The SERVER parameters
|
||||
* @param string|resource|null $content The raw body data
|
||||
*/
|
||||
public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
|
||||
{
|
||||
@@ -227,13 +260,13 @@ class Request
|
||||
*
|
||||
* This method also re-initializes all properties.
|
||||
*
|
||||
* @param array $query The GET parameters
|
||||
* @param array $request The POST parameters
|
||||
* @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
|
||||
* @param array $cookies The COOKIE parameters
|
||||
* @param array $files The FILES parameters
|
||||
* @param array $server The SERVER parameters
|
||||
* @param string|resource $content The raw body data
|
||||
* @param array $query The GET parameters
|
||||
* @param array $request The POST parameters
|
||||
* @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
|
||||
* @param array $cookies The COOKIE parameters
|
||||
* @param array $files The FILES parameters
|
||||
* @param array $server The SERVER parameters
|
||||
* @param string|resource|null $content The raw body data
|
||||
*/
|
||||
public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
|
||||
{
|
||||
@@ -261,7 +294,7 @@ class Request
|
||||
/**
|
||||
* Creates a new request with values from PHP's super globals.
|
||||
*
|
||||
* @return Request A new request
|
||||
* @return static
|
||||
*/
|
||||
public static function createFromGlobals()
|
||||
{
|
||||
@@ -269,7 +302,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) {
|
||||
if ('cli-server' === \PHP_SAPI) {
|
||||
if (array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) {
|
||||
$server['CONTENT_LENGTH'] = $_SERVER['HTTP_CONTENT_LENGTH'];
|
||||
}
|
||||
@@ -281,7 +314,7 @@ class Request
|
||||
$request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $server);
|
||||
|
||||
if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
|
||||
&& in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
|
||||
&& \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
|
||||
) {
|
||||
parse_str($request->getContent(), $data);
|
||||
$request->request = new ParameterBag($data);
|
||||
@@ -296,15 +329,15 @@ class Request
|
||||
* The information contained in the URI always take precedence
|
||||
* over the other information (server and parameters).
|
||||
*
|
||||
* @param string $uri The URI
|
||||
* @param string $method The HTTP method
|
||||
* @param array $parameters The query (GET) or request (POST) parameters
|
||||
* @param array $cookies The request cookies ($_COOKIE)
|
||||
* @param array $files The request files ($_FILES)
|
||||
* @param array $server The server parameters ($_SERVER)
|
||||
* @param string $content The raw body data
|
||||
* @param string $uri The URI
|
||||
* @param string $method The HTTP method
|
||||
* @param array $parameters The query (GET) or request (POST) parameters
|
||||
* @param array $cookies The request cookies ($_COOKIE)
|
||||
* @param array $files The request files ($_FILES)
|
||||
* @param array $server The server parameters ($_SERVER)
|
||||
* @param string|resource|null $content The raw body data
|
||||
*
|
||||
* @return Request A Request instance
|
||||
* @return static
|
||||
*/
|
||||
public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
|
||||
{
|
||||
@@ -422,27 +455,27 @@ class Request
|
||||
* @param array $files The FILES parameters
|
||||
* @param array $server The SERVER parameters
|
||||
*
|
||||
* @return Request The duplicated request
|
||||
* @return static
|
||||
*/
|
||||
public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
|
||||
{
|
||||
$dup = clone $this;
|
||||
if ($query !== null) {
|
||||
if (null !== $query) {
|
||||
$dup->query = new ParameterBag($query);
|
||||
}
|
||||
if ($request !== null) {
|
||||
if (null !== $request) {
|
||||
$dup->request = new ParameterBag($request);
|
||||
}
|
||||
if ($attributes !== null) {
|
||||
if (null !== $attributes) {
|
||||
$dup->attributes = new ParameterBag($attributes);
|
||||
}
|
||||
if ($cookies !== null) {
|
||||
if (null !== $cookies) {
|
||||
$dup->cookies = new ParameterBag($cookies);
|
||||
}
|
||||
if ($files !== null) {
|
||||
if (null !== $files) {
|
||||
$dup->files = new FileBag($files);
|
||||
}
|
||||
if ($server !== null) {
|
||||
if (null !== $server) {
|
||||
$dup->server = new ServerBag($server);
|
||||
$dup->headers = new HeaderBag($dup->server->getHeaders());
|
||||
}
|
||||
@@ -498,9 +531,21 @@ class Request
|
||||
return trigger_error($e, E_USER_ERROR);
|
||||
}
|
||||
|
||||
$cookieHeader = '';
|
||||
$cookies = array();
|
||||
|
||||
foreach ($this->cookies as $k => $v) {
|
||||
$cookies[] = $k.'='.$v;
|
||||
}
|
||||
|
||||
if (!empty($cookies)) {
|
||||
$cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n";
|
||||
}
|
||||
|
||||
return
|
||||
sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
|
||||
$this->headers."\r\n".
|
||||
$this->headers.
|
||||
$cookieHeader."\r\n".
|
||||
$content;
|
||||
}
|
||||
|
||||
@@ -512,7 +557,7 @@ class Request
|
||||
*/
|
||||
public function overrideGlobals()
|
||||
{
|
||||
$this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), null, '&')));
|
||||
$this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&')));
|
||||
|
||||
$_GET = $this->query->all();
|
||||
$_POST = $this->request->all();
|
||||
@@ -521,7 +566,7 @@ class Request
|
||||
|
||||
foreach ($this->headers->all() as $key => $value) {
|
||||
$key = strtoupper(str_replace('-', '_', $key));
|
||||
if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) {
|
||||
if (\in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) {
|
||||
$_SERVER[$key] = implode(', ', $value);
|
||||
} else {
|
||||
$_SERVER['HTTP_'.$key] = implode(', ', $value);
|
||||
@@ -544,11 +589,26 @@ class Request
|
||||
*
|
||||
* You should only list the reverse proxies that you manage directly.
|
||||
*
|
||||
* @param array $proxies A list of trusted proxies
|
||||
* @param array $proxies A list of trusted proxies
|
||||
* @param int $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies
|
||||
*
|
||||
* @throws \InvalidArgumentException When $trustedHeaderSet is invalid
|
||||
*/
|
||||
public static function setTrustedProxies(array $proxies)
|
||||
public static function setTrustedProxies(array $proxies/*, int $trustedHeaderSet*/)
|
||||
{
|
||||
self::$trustedProxies = $proxies;
|
||||
|
||||
if (2 > \func_num_args()) {
|
||||
@trigger_error(sprintf('The %s() method expects a bit field of Request::HEADER_* as second argument since Symfony 3.3. Defining it will be required in 4.0. ', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return;
|
||||
}
|
||||
$trustedHeaderSet = (int) func_get_arg(1);
|
||||
|
||||
foreach (self::$trustedHeaderNames as $header => $name) {
|
||||
self::$trustedHeaders[$header] = $header & $trustedHeaderSet ? $name : null;
|
||||
}
|
||||
self::$trustedHeaderSet = $trustedHeaderSet;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -561,6 +621,16 @@ class Request
|
||||
return self::$trustedProxies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of trusted headers from trusted proxies.
|
||||
*
|
||||
* @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies
|
||||
*/
|
||||
public static function getTrustedHeaderSet()
|
||||
{
|
||||
return self::$trustedHeaderSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of trusted host patterns.
|
||||
*
|
||||
@@ -571,7 +641,7 @@ class Request
|
||||
public static function setTrustedHosts(array $hostPatterns)
|
||||
{
|
||||
self::$trustedHostPatterns = array_map(function ($hostPattern) {
|
||||
return sprintf('#%s#i', $hostPattern);
|
||||
return sprintf('{%s}i', $hostPattern);
|
||||
}, $hostPatterns);
|
||||
// we need to reset trusted hosts on trusted host patterns change
|
||||
self::$trustedHosts = array();
|
||||
@@ -596,6 +666,7 @@ class Request
|
||||
* * Request::HEADER_CLIENT_HOST: defaults to X-Forwarded-Host (see getHost())
|
||||
* * Request::HEADER_CLIENT_PORT: defaults to X-Forwarded-Port (see getPort())
|
||||
* * Request::HEADER_CLIENT_PROTO: defaults to X-Forwarded-Proto (see getScheme() and isSecure())
|
||||
* * Request::HEADER_FORWARDED: defaults to Forwarded (see RFC 7239)
|
||||
*
|
||||
* Setting an empty value allows to disable the trusted header for the given key.
|
||||
*
|
||||
@@ -603,14 +674,35 @@ class Request
|
||||
* @param string $value The header name
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.
|
||||
*/
|
||||
public static function setTrustedHeaderName($key, $value)
|
||||
{
|
||||
if (!array_key_exists($key, self::$trustedHeaders)) {
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if ('forwarded' === $key) {
|
||||
$key = self::HEADER_FORWARDED;
|
||||
} elseif ('client_ip' === $key) {
|
||||
$key = self::HEADER_CLIENT_IP;
|
||||
} elseif ('client_host' === $key) {
|
||||
$key = self::HEADER_CLIENT_HOST;
|
||||
} elseif ('client_proto' === $key) {
|
||||
$key = self::HEADER_CLIENT_PROTO;
|
||||
} elseif ('client_port' === $key) {
|
||||
$key = self::HEADER_CLIENT_PORT;
|
||||
} elseif (!array_key_exists($key, self::$trustedHeaders)) {
|
||||
throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key));
|
||||
}
|
||||
|
||||
self::$trustedHeaders[$key] = $value;
|
||||
|
||||
if (null !== $value) {
|
||||
self::$trustedHeaderNames[$key] = $value;
|
||||
self::$trustedHeaderSet |= $key;
|
||||
} else {
|
||||
self::$trustedHeaderSet &= ~$key;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -621,9 +713,15 @@ class Request
|
||||
* @return string The header name
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0. Use the Request::getTrustedHeaderSet() method instead.
|
||||
*/
|
||||
public static function getTrustedHeaderName($key)
|
||||
{
|
||||
if (2 > \func_num_args() || func_get_arg(1)) {
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the Request::getTrustedHeaderSet() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (!array_key_exists($key, self::$trustedHeaders)) {
|
||||
throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key));
|
||||
}
|
||||
@@ -709,8 +807,8 @@ class Request
|
||||
*
|
||||
* Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY
|
||||
*
|
||||
* @param string $key the key
|
||||
* @param mixed $default the default value if the parameter key does not exist
|
||||
* @param string $key The key
|
||||
* @param mixed $default The default value if the parameter key does not exist
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
@@ -792,41 +890,13 @@ class Request
|
||||
*/
|
||||
public function getClientIps()
|
||||
{
|
||||
$clientIps = array();
|
||||
$ip = $this->server->get('REMOTE_ADDR');
|
||||
|
||||
if (!$this->isFromTrustedProxy()) {
|
||||
return array($ip);
|
||||
}
|
||||
|
||||
$hasTrustedForwardedHeader = self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED]);
|
||||
$hasTrustedClientIpHeader = self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP]);
|
||||
|
||||
if ($hasTrustedForwardedHeader) {
|
||||
$forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
|
||||
preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
|
||||
$forwardedClientIps = $matches[3];
|
||||
|
||||
$forwardedClientIps = $this->normalizeAndFilterClientIps($forwardedClientIps, $ip);
|
||||
$clientIps = $forwardedClientIps;
|
||||
}
|
||||
|
||||
if ($hasTrustedClientIpHeader) {
|
||||
$xForwardedForClientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
|
||||
|
||||
$xForwardedForClientIps = $this->normalizeAndFilterClientIps($xForwardedForClientIps, $ip);
|
||||
$clientIps = $xForwardedForClientIps;
|
||||
}
|
||||
|
||||
if ($hasTrustedForwardedHeader && $hasTrustedClientIpHeader && $forwardedClientIps !== $xForwardedForClientIps) {
|
||||
throw new ConflictingHeadersException('The request has both a trusted Forwarded header and a trusted Client IP header, conflicting with each other with regards to the originating IP addresses of the request. This is the result of a misconfiguration. You should either configure your proxy only to send one of these headers, or configure Symfony to distrust one of them.');
|
||||
}
|
||||
|
||||
if (!$hasTrustedForwardedHeader && !$hasTrustedClientIpHeader) {
|
||||
return $this->normalizeAndFilterClientIps(array(), $ip);
|
||||
}
|
||||
|
||||
return $clientIps;
|
||||
return $this->getTrustedValues(self::HEADER_CLIENT_IP, $ip) ?: array($ip);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -839,10 +909,10 @@ class Request
|
||||
* adding the IP address where it received the request from.
|
||||
*
|
||||
* If your reverse proxy uses a different header name than "X-Forwarded-For",
|
||||
* ("Client-Ip" for instance), configure it via "setTrustedHeaderName()" with
|
||||
* the "client-ip" key.
|
||||
* ("Client-Ip" for instance), configure it via the $trustedHeaderSet
|
||||
* argument of the Request::setTrustedProxies() method instead.
|
||||
*
|
||||
* @return string The client IP address
|
||||
* @return string|null The client IP address
|
||||
*
|
||||
* @see getClientIps()
|
||||
* @see http://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
@@ -946,37 +1016,32 @@ class Request
|
||||
* The "X-Forwarded-Port" header must contain the client port.
|
||||
*
|
||||
* If your reverse proxy uses a different header name than "X-Forwarded-Port",
|
||||
* configure it via "setTrustedHeaderName()" with the "client-port" key.
|
||||
* configure it via via the $trustedHeaderSet argument of the
|
||||
* Request::setTrustedProxies() method instead.
|
||||
*
|
||||
* @return string
|
||||
* @return int|string can be a string if fetched from the server bag
|
||||
*/
|
||||
public function getPort()
|
||||
{
|
||||
if ($this->isFromTrustedProxy()) {
|
||||
if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) {
|
||||
return $port;
|
||||
}
|
||||
|
||||
if (self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && 'https' === $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO], 'http')) {
|
||||
return 443;
|
||||
}
|
||||
if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_PORT)) {
|
||||
$host = $host[0];
|
||||
} elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) {
|
||||
$host = $host[0];
|
||||
} elseif (!$host = $this->headers->get('HOST')) {
|
||||
return $this->server->get('SERVER_PORT');
|
||||
}
|
||||
|
||||
if ($host = $this->headers->get('HOST')) {
|
||||
if ($host[0] === '[') {
|
||||
$pos = strpos($host, ':', strrpos($host, ']'));
|
||||
} else {
|
||||
$pos = strrpos($host, ':');
|
||||
}
|
||||
|
||||
if (false !== $pos) {
|
||||
return (int) substr($host, $pos + 1);
|
||||
}
|
||||
|
||||
return 'https' === $this->getScheme() ? 443 : 80;
|
||||
if ('[' === $host[0]) {
|
||||
$pos = strpos($host, ':', strrpos($host, ']'));
|
||||
} else {
|
||||
$pos = strrpos($host, ':');
|
||||
}
|
||||
|
||||
return $this->server->get('SERVER_PORT');
|
||||
if (false !== $pos) {
|
||||
return (int) substr($host, $pos + 1);
|
||||
}
|
||||
|
||||
return 'https' === $this->getScheme() ? 443 : 80;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1028,7 +1093,7 @@ class Request
|
||||
$scheme = $this->getScheme();
|
||||
$port = $this->getPort();
|
||||
|
||||
if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) {
|
||||
if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) {
|
||||
return $this->getHost();
|
||||
}
|
||||
|
||||
@@ -1134,7 +1199,7 @@ class Request
|
||||
}
|
||||
|
||||
$targetDirs[] = $targetFile;
|
||||
$path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs);
|
||||
$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
|
||||
@@ -1169,15 +1234,15 @@ class Request
|
||||
* The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
|
||||
*
|
||||
* If your reverse proxy uses a different header name than "X-Forwarded-Proto"
|
||||
* ("SSL_HTTPS" for instance), configure it via "setTrustedHeaderName()" with
|
||||
* the "client-proto" key.
|
||||
* ("SSL_HTTPS" for instance), configure it via the $trustedHeaderSet
|
||||
* argument of the Request::setTrustedProxies() method instead.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSecure()
|
||||
{
|
||||
if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) {
|
||||
return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1'));
|
||||
if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_CLIENT_PROTO)) {
|
||||
return \in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true);
|
||||
}
|
||||
|
||||
$https = $this->server->get('HTTPS');
|
||||
@@ -1194,18 +1259,17 @@ class Request
|
||||
* The "X-Forwarded-Host" header must contain the client host name.
|
||||
*
|
||||
* If your reverse proxy uses a different header name than "X-Forwarded-Host",
|
||||
* configure it via "setTrustedHeaderName()" with the "client-host" key.
|
||||
* configure it via the $trustedHeaderSet argument of the
|
||||
* Request::setTrustedProxies() method instead.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \UnexpectedValueException when the host name is invalid
|
||||
* @throws SuspiciousOperationException when the host name is invalid or not trusted
|
||||
*/
|
||||
public function getHost()
|
||||
{
|
||||
if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
|
||||
$elements = explode(',', $host);
|
||||
|
||||
$host = $elements[count($elements) - 1];
|
||||
if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) {
|
||||
$host = $host[0];
|
||||
} elseif (!$host = $this->headers->get('HOST')) {
|
||||
if (!$host = $this->server->get('SERVER_NAME')) {
|
||||
$host = $this->server->get('SERVER_ADDR', '');
|
||||
@@ -1220,13 +1284,18 @@ class Request
|
||||
// check that it does not contain forbidden characters (see RFC 952 and RFC 2181)
|
||||
// use preg_replace() instead of preg_match() to prevent DoS attacks with long host names
|
||||
if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) {
|
||||
throw new \UnexpectedValueException(sprintf('Invalid Host "%s"', $host));
|
||||
if (!$this->isHostValid) {
|
||||
return '';
|
||||
}
|
||||
$this->isHostValid = false;
|
||||
|
||||
throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host));
|
||||
}
|
||||
|
||||
if (count(self::$trustedHostPatterns) > 0) {
|
||||
if (\count(self::$trustedHostPatterns) > 0) {
|
||||
// to avoid host header injection attacks, you should provide a list of trusted host patterns
|
||||
|
||||
if (in_array($host, self::$trustedHosts)) {
|
||||
if (\in_array($host, self::$trustedHosts)) {
|
||||
return $host;
|
||||
}
|
||||
|
||||
@@ -1238,7 +1307,12 @@ class Request
|
||||
}
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException(sprintf('Untrusted Host "%s"', $host));
|
||||
if (!$this->isHostValid) {
|
||||
return '';
|
||||
}
|
||||
$this->isHostValid = false;
|
||||
|
||||
throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host));
|
||||
}
|
||||
|
||||
return $host;
|
||||
@@ -1279,7 +1353,10 @@ class Request
|
||||
if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
|
||||
$this->method = strtoupper($method);
|
||||
} elseif (self::$httpMethodParameterOverride) {
|
||||
$this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
|
||||
$method = $this->request->get('_method', $this->query->get('_method', 'POST'));
|
||||
if (\is_string($method)) {
|
||||
$this->method = strtoupper($method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1304,7 +1381,7 @@ class Request
|
||||
*
|
||||
* @param string $format The format
|
||||
*
|
||||
* @return string The associated mime type (null if not found)
|
||||
* @return string|null The associated mime type (null if not found)
|
||||
*/
|
||||
public function getMimeType($format)
|
||||
{
|
||||
@@ -1315,6 +1392,22 @@ class Request
|
||||
return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mime types associated with the format.
|
||||
*
|
||||
* @param string $format The format
|
||||
*
|
||||
* @return array The associated mime types
|
||||
*/
|
||||
public static function getMimeTypes($format)
|
||||
{
|
||||
if (null === static::$formats) {
|
||||
static::initializeFormats();
|
||||
}
|
||||
|
||||
return isset(static::$formats[$format]) ? static::$formats[$format] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the format associated with the mime type.
|
||||
*
|
||||
@@ -1334,10 +1427,10 @@ class Request
|
||||
}
|
||||
|
||||
foreach (static::$formats as $format => $mimeTypes) {
|
||||
if (in_array($mimeType, (array) $mimeTypes)) {
|
||||
if (\in_array($mimeType, (array) $mimeTypes)) {
|
||||
return $format;
|
||||
}
|
||||
if (null !== $canonicalMimeType && in_array($canonicalMimeType, (array) $mimeTypes)) {
|
||||
if (null !== $canonicalMimeType && \in_array($canonicalMimeType, (array) $mimeTypes)) {
|
||||
return $format;
|
||||
}
|
||||
}
|
||||
@@ -1355,7 +1448,7 @@ class Request
|
||||
static::initializeFormats();
|
||||
}
|
||||
|
||||
static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
|
||||
static::$formats[$format] = \is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1374,10 +1467,10 @@ class Request
|
||||
public function getRequestFormat($default = 'html')
|
||||
{
|
||||
if (null === $this->format) {
|
||||
$this->format = $this->attributes->get('_format', $default);
|
||||
$this->format = $this->attributes->get('_format');
|
||||
}
|
||||
|
||||
return $this->format;
|
||||
return null === $this->format ? $default : $this->format;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1457,13 +1550,71 @@ class Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the method is safe or not.
|
||||
* Checks whether or not the method is safe.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-4.2.1
|
||||
*
|
||||
* @param bool $andCacheable Adds the additional condition that the method should be cacheable. True by default.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMethodSafe()
|
||||
public function isMethodSafe(/* $andCacheable = true */)
|
||||
{
|
||||
return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE'));
|
||||
if (!\func_num_args() || func_get_arg(0)) {
|
||||
// This deprecation should be turned into a BadMethodCallException in 4.0 (without adding the argument in the signature)
|
||||
// then setting $andCacheable to false should be deprecated in 4.1
|
||||
@trigger_error('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since Symfony 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead.', E_USER_DEPRECATED);
|
||||
|
||||
return \in_array($this->getMethod(), array('GET', 'HEAD'));
|
||||
}
|
||||
|
||||
return \in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the method is idempotent.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMethodIdempotent()
|
||||
{
|
||||
return \in_array($this->getMethod(), array('HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the method is cacheable or not.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-4.2.3
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMethodCacheable()
|
||||
{
|
||||
return \in_array($this->getMethod(), array('GET', 'HEAD'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol version.
|
||||
*
|
||||
* If the application is behind a proxy, the protocol version used in the
|
||||
* requests between the client and the proxy and between the proxy and the
|
||||
* server might be different. This returns the former (from the "Via" header)
|
||||
* if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns
|
||||
* the latter (from the "SERVER_PROTOCOL" server parameter).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProtocolVersion()
|
||||
{
|
||||
if ($this->isFromTrustedProxy()) {
|
||||
preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via'), $matches);
|
||||
|
||||
if ($matches) {
|
||||
return 'HTTP/'.$matches[2];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->server->get('SERVER_PROTOCOL');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1477,8 +1628,8 @@ class Request
|
||||
*/
|
||||
public function getContent($asResource = false)
|
||||
{
|
||||
$currentContentIsResource = is_resource($this->content);
|
||||
if (PHP_VERSION_ID < 50600 && false === $this->content) {
|
||||
$currentContentIsResource = \is_resource($this->content);
|
||||
if (\PHP_VERSION_ID < 50600 && false === $this->content) {
|
||||
throw new \LogicException('getContent() can only be called once when using the resource return type and PHP below 5.6.');
|
||||
}
|
||||
|
||||
@@ -1490,7 +1641,7 @@ class Request
|
||||
}
|
||||
|
||||
// Content passed in parameter (test)
|
||||
if (is_string($this->content)) {
|
||||
if (\is_string($this->content)) {
|
||||
$resource = fopen('php://temp', 'r+');
|
||||
fwrite($resource, $this->content);
|
||||
rewind($resource);
|
||||
@@ -1509,7 +1660,7 @@ class Request
|
||||
return stream_get_contents($this->content);
|
||||
}
|
||||
|
||||
if (null === $this->content) {
|
||||
if (null === $this->content || false === $this->content) {
|
||||
$this->content = file_get_contents('php://input');
|
||||
}
|
||||
|
||||
@@ -1558,7 +1709,7 @@ class Request
|
||||
$extendedPreferredLanguages[] = $language;
|
||||
if (false !== $position = strpos($language, '_')) {
|
||||
$superLanguage = substr($language, 0, $position);
|
||||
if (!in_array($superLanguage, $preferredLanguages)) {
|
||||
if (!\in_array($superLanguage, $preferredLanguages)) {
|
||||
$extendedPreferredLanguages[] = $superLanguage;
|
||||
}
|
||||
}
|
||||
@@ -1589,12 +1740,12 @@ class Request
|
||||
// Language not listed in ISO 639 that are not variants
|
||||
// of any listed language, which can be registered with the
|
||||
// i-prefix, such as i-cherokee
|
||||
if (count($codes) > 1) {
|
||||
if (\count($codes) > 1) {
|
||||
$lang = $codes[1];
|
||||
}
|
||||
} else {
|
||||
for ($i = 0, $max = count($codes); $i < $max; ++$i) {
|
||||
if ($i === 0) {
|
||||
for ($i = 0, $max = \count($codes); $i < $max; ++$i) {
|
||||
if (0 === $i) {
|
||||
$lang = strtolower($codes[0]);
|
||||
} else {
|
||||
$lang .= '_'.strtoupper($codes[$i]);
|
||||
@@ -1657,7 +1808,7 @@ class Request
|
||||
* It works if your JavaScript library sets an X-Requested-With HTTP header.
|
||||
* It is known to work with common JavaScript frameworks:
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
|
||||
* @see http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
|
||||
*
|
||||
* @return bool true if the request is an XMLHttpRequest, false otherwise
|
||||
*/
|
||||
@@ -1678,18 +1829,7 @@ class Request
|
||||
{
|
||||
$requestUri = '';
|
||||
|
||||
if ($this->headers->has('X_ORIGINAL_URL')) {
|
||||
// IIS with Microsoft Rewrite Module
|
||||
$requestUri = $this->headers->get('X_ORIGINAL_URL');
|
||||
$this->headers->remove('X_ORIGINAL_URL');
|
||||
$this->server->remove('HTTP_X_ORIGINAL_URL');
|
||||
$this->server->remove('UNENCODED_URL');
|
||||
$this->server->remove('IIS_WasUrlRewritten');
|
||||
} elseif ($this->headers->has('X_REWRITE_URL')) {
|
||||
// IIS with ISAPI_Rewrite
|
||||
$requestUri = $this->headers->get('X_REWRITE_URL');
|
||||
$this->headers->remove('X_REWRITE_URL');
|
||||
} elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') {
|
||||
if ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) {
|
||||
// IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem)
|
||||
$requestUri = $this->server->get('UNENCODED_URL');
|
||||
$this->server->remove('UNENCODED_URL');
|
||||
@@ -1698,8 +1838,8 @@ class Request
|
||||
$requestUri = $this->server->get('REQUEST_URI');
|
||||
// HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path
|
||||
$schemeAndHttpHost = $this->getSchemeAndHttpHost();
|
||||
if (strpos($requestUri, $schemeAndHttpHost) === 0) {
|
||||
$requestUri = substr($requestUri, strlen($schemeAndHttpHost));
|
||||
if (0 === strpos($requestUri, $schemeAndHttpHost)) {
|
||||
$requestUri = substr($requestUri, \strlen($schemeAndHttpHost));
|
||||
}
|
||||
} elseif ($this->server->has('ORIG_PATH_INFO')) {
|
||||
// IIS 5.0, PHP as CGI
|
||||
@@ -1739,7 +1879,7 @@ class Request
|
||||
$segs = explode('/', trim($file, '/'));
|
||||
$segs = array_reverse($segs);
|
||||
$index = 0;
|
||||
$last = count($segs);
|
||||
$last = \count($segs);
|
||||
$baseUrl = '';
|
||||
do {
|
||||
$seg = $segs[$index];
|
||||
@@ -1750,15 +1890,18 @@ class Request
|
||||
|
||||
// Does the baseUrl have anything in common with the request_uri?
|
||||
$requestUri = $this->getRequestUri();
|
||||
if ('' !== $requestUri && '/' !== $requestUri[0]) {
|
||||
$requestUri = '/'.$requestUri;
|
||||
}
|
||||
|
||||
if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) {
|
||||
// full $baseUrl matches
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(dirname($baseUrl), '/'.DIRECTORY_SEPARATOR).'/')) {
|
||||
if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/'.\DIRECTORY_SEPARATOR).'/')) {
|
||||
// directory portion of $baseUrl matches
|
||||
return rtrim($prefix, '/'.DIRECTORY_SEPARATOR);
|
||||
return rtrim($prefix, '/'.\DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
$truncatedRequestUri = $requestUri;
|
||||
@@ -1775,11 +1918,11 @@ class Request
|
||||
// If using mod_rewrite or ISAPI_Rewrite strip the script filename
|
||||
// out of baseUrl. $pos !== 0 makes sure it is not matching a value
|
||||
// from PATH_INFO or QUERY_STRING
|
||||
if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && $pos !== 0) {
|
||||
$baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
|
||||
if (\strlen($requestUri) >= \strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) {
|
||||
$baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl));
|
||||
}
|
||||
|
||||
return rtrim($baseUrl, '/'.DIRECTORY_SEPARATOR);
|
||||
return rtrim($baseUrl, '/'.\DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1789,19 +1932,19 @@ class Request
|
||||
*/
|
||||
protected function prepareBasePath()
|
||||
{
|
||||
$filename = basename($this->server->get('SCRIPT_FILENAME'));
|
||||
$baseUrl = $this->getBaseUrl();
|
||||
if (empty($baseUrl)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$filename = basename($this->server->get('SCRIPT_FILENAME'));
|
||||
if (basename($baseUrl) === $filename) {
|
||||
$basePath = dirname($baseUrl);
|
||||
$basePath = \dirname($baseUrl);
|
||||
} else {
|
||||
$basePath = $baseUrl;
|
||||
}
|
||||
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||
$basePath = str_replace('\\', '/', $basePath);
|
||||
}
|
||||
|
||||
@@ -1815,23 +1958,26 @@ class Request
|
||||
*/
|
||||
protected function preparePathInfo()
|
||||
{
|
||||
$baseUrl = $this->getBaseUrl();
|
||||
|
||||
if (null === ($requestUri = $this->getRequestUri())) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
// Remove the query string from REQUEST_URI
|
||||
if ($pos = strpos($requestUri, '?')) {
|
||||
if (false !== $pos = strpos($requestUri, '?')) {
|
||||
$requestUri = substr($requestUri, 0, $pos);
|
||||
}
|
||||
if ('' !== $requestUri && '/' !== $requestUri[0]) {
|
||||
$requestUri = '/'.$requestUri;
|
||||
}
|
||||
|
||||
$pathInfo = substr($requestUri, strlen($baseUrl));
|
||||
if (null !== $baseUrl && (false === $pathInfo || '' === $pathInfo)) {
|
||||
if (null === ($baseUrl = $this->getBaseUrl())) {
|
||||
return $requestUri;
|
||||
}
|
||||
|
||||
$pathInfo = substr($requestUri, \strlen($baseUrl));
|
||||
if (false === $pathInfo || '' === $pathInfo) {
|
||||
// If substr() returns false then PATH_INFO is set to an empty string
|
||||
return '/';
|
||||
} elseif (null === $baseUrl) {
|
||||
return $requestUri;
|
||||
}
|
||||
|
||||
return (string) $pathInfo;
|
||||
@@ -1848,6 +1994,7 @@ class Request
|
||||
'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'),
|
||||
'css' => array('text/css'),
|
||||
'json' => array('application/json', 'application/x-json'),
|
||||
'jsonld' => array('application/ld+json'),
|
||||
'xml' => array('text/xml', 'application/xml', 'application/x-xml'),
|
||||
'rdf' => array('application/rdf+xml'),
|
||||
'atom' => array('application/atom+xml'),
|
||||
@@ -1889,7 +2036,7 @@ class Request
|
||||
return false;
|
||||
}
|
||||
|
||||
$len = strlen($prefix);
|
||||
$len = \strlen($prefix);
|
||||
|
||||
if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) {
|
||||
return $match[0];
|
||||
@@ -1901,7 +2048,7 @@ class Request
|
||||
private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
|
||||
{
|
||||
if (self::$requestFactory) {
|
||||
$request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);
|
||||
$request = \call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);
|
||||
|
||||
if (!$request instanceof self) {
|
||||
throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');
|
||||
@@ -1913,13 +2060,66 @@ class Request
|
||||
return new static($query, $request, $attributes, $cookies, $files, $server, $content);
|
||||
}
|
||||
|
||||
private function isFromTrustedProxy()
|
||||
/**
|
||||
* Indicates whether this request originated from a trusted proxy.
|
||||
*
|
||||
* This can be useful to determine whether or not to trust the
|
||||
* contents of a proxy-specific header.
|
||||
*
|
||||
* @return bool true if the request came from a trusted proxy, false otherwise
|
||||
*/
|
||||
public function isFromTrustedProxy()
|
||||
{
|
||||
return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies);
|
||||
}
|
||||
|
||||
private function getTrustedValues($type, $ip = null)
|
||||
{
|
||||
$clientValues = array();
|
||||
$forwardedValues = array();
|
||||
|
||||
if (self::$trustedHeaders[$type] && $this->headers->has(self::$trustedHeaders[$type])) {
|
||||
foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) {
|
||||
$clientValues[] = (self::HEADER_CLIENT_PORT === $type ? '0.0.0.0:' : '').trim($v);
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
|
||||
$forwardedValues = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
|
||||
$forwardedValues = preg_match_all(sprintf('{(?:%s)=(?:"?\[?)([a-zA-Z0-9\.:_\-/]*+)}', self::$forwardedParams[$type]), $forwardedValues, $matches) ? $matches[1] : array();
|
||||
if (self::HEADER_CLIENT_PORT === $type) {
|
||||
foreach ($forwardedValues as $k => $v) {
|
||||
$forwardedValues[$k] = substr_replace($v, '0.0.0.0', 0, strrpos($v, ':'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $ip) {
|
||||
$clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip);
|
||||
$forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip);
|
||||
}
|
||||
|
||||
if ($forwardedValues === $clientValues || !$clientValues) {
|
||||
return $forwardedValues;
|
||||
}
|
||||
|
||||
if (!$forwardedValues) {
|
||||
return $clientValues;
|
||||
}
|
||||
|
||||
if (!$this->isForwardedValid) {
|
||||
return null !== $ip ? array('0.0.0.0', $ip) : array();
|
||||
}
|
||||
$this->isForwardedValid = false;
|
||||
|
||||
throw new ConflictingHeadersException(sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::$trustedHeaders[self::HEADER_FORWARDED], self::$trustedHeaders[$type]));
|
||||
}
|
||||
|
||||
private function normalizeAndFilterClientIps(array $clientIps, $ip)
|
||||
{
|
||||
if (!$clientIps) {
|
||||
return array();
|
||||
}
|
||||
$clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
|
||||
$firstTrustedIp = null;
|
||||
|
||||
|
Reference in New Issue
Block a user