Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/http-foundation/Request.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | 7a779792577d |
children | c2387f117808 |
comparison
equal
deleted
inserted
replaced
13:5fb285c0d0e3 | 14:1fec387a4317 |
---|---|
10 */ | 10 */ |
11 | 11 |
12 namespace Symfony\Component\HttpFoundation; | 12 namespace Symfony\Component\HttpFoundation; |
13 | 13 |
14 use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; | 14 use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; |
15 use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; | |
15 use Symfony\Component\HttpFoundation\Session\SessionInterface; | 16 use Symfony\Component\HttpFoundation\Session\SessionInterface; |
16 | 17 |
17 /** | 18 /** |
18 * Request represents an HTTP request. | 19 * Request represents an HTTP request. |
19 * | 20 * |
27 * | 28 * |
28 * @author Fabien Potencier <fabien@symfony.com> | 29 * @author Fabien Potencier <fabien@symfony.com> |
29 */ | 30 */ |
30 class Request | 31 class Request |
31 { | 32 { |
32 const HEADER_FORWARDED = 'forwarded'; | 33 const HEADER_FORWARDED = 0b00001; // When using RFC 7239 |
33 const HEADER_CLIENT_IP = 'client_ip'; | 34 const HEADER_X_FORWARDED_FOR = 0b00010; |
34 const HEADER_CLIENT_HOST = 'client_host'; | 35 const HEADER_X_FORWARDED_HOST = 0b00100; |
35 const HEADER_CLIENT_PROTO = 'client_proto'; | 36 const HEADER_X_FORWARDED_PROTO = 0b01000; |
36 const HEADER_CLIENT_PORT = 'client_port'; | 37 const HEADER_X_FORWARDED_PORT = 0b10000; |
38 const HEADER_X_FORWARDED_ALL = 0b11110; // All "X-Forwarded-*" headers | |
39 const HEADER_X_FORWARDED_AWS_ELB = 0b11010; // AWS ELB doesn't send X-Forwarded-Host | |
40 | |
41 /** @deprecated since version 3.3, to be removed in 4.0 */ | |
42 const HEADER_CLIENT_IP = self::HEADER_X_FORWARDED_FOR; | |
43 /** @deprecated since version 3.3, to be removed in 4.0 */ | |
44 const HEADER_CLIENT_HOST = self::HEADER_X_FORWARDED_HOST; | |
45 /** @deprecated since version 3.3, to be removed in 4.0 */ | |
46 const HEADER_CLIENT_PROTO = self::HEADER_X_FORWARDED_PROTO; | |
47 /** @deprecated since version 3.3, to be removed in 4.0 */ | |
48 const HEADER_CLIENT_PORT = self::HEADER_X_FORWARDED_PORT; | |
37 | 49 |
38 const METHOD_HEAD = 'HEAD'; | 50 const METHOD_HEAD = 'HEAD'; |
39 const METHOD_GET = 'GET'; | 51 const METHOD_GET = 'GET'; |
40 const METHOD_POST = 'POST'; | 52 const METHOD_POST = 'POST'; |
41 const METHOD_PUT = 'PUT'; | 53 const METHOD_PUT = 'PUT'; |
67 * | 79 * |
68 * The FORWARDED header is the standard as of rfc7239. | 80 * The FORWARDED header is the standard as of rfc7239. |
69 * | 81 * |
70 * The other headers are non-standard, but widely used | 82 * The other headers are non-standard, but widely used |
71 * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). | 83 * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). |
84 * | |
85 * @deprecated since version 3.3, to be removed in 4.0 | |
72 */ | 86 */ |
73 protected static $trustedHeaders = array( | 87 protected static $trustedHeaders = array( |
74 self::HEADER_FORWARDED => 'FORWARDED', | 88 self::HEADER_FORWARDED => 'FORWARDED', |
75 self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', | 89 self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', |
76 self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', | 90 self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', |
128 * @var \Symfony\Component\HttpFoundation\HeaderBag | 142 * @var \Symfony\Component\HttpFoundation\HeaderBag |
129 */ | 143 */ |
130 public $headers; | 144 public $headers; |
131 | 145 |
132 /** | 146 /** |
147 * @var string|resource|false|null | |
148 */ | |
149 protected $content; | |
150 | |
151 /** | |
152 * @var array | |
153 */ | |
154 protected $languages; | |
155 | |
156 /** | |
157 * @var array | |
158 */ | |
159 protected $charsets; | |
160 | |
161 /** | |
162 * @var array | |
163 */ | |
164 protected $encodings; | |
165 | |
166 /** | |
167 * @var array | |
168 */ | |
169 protected $acceptableContentTypes; | |
170 | |
171 /** | |
133 * @var string | 172 * @var string |
134 */ | 173 */ |
135 protected $content; | 174 protected $pathInfo; |
175 | |
176 /** | |
177 * @var string | |
178 */ | |
179 protected $requestUri; | |
180 | |
181 /** | |
182 * @var string | |
183 */ | |
184 protected $baseUrl; | |
185 | |
186 /** | |
187 * @var string | |
188 */ | |
189 protected $basePath; | |
190 | |
191 /** | |
192 * @var string | |
193 */ | |
194 protected $method; | |
195 | |
196 /** | |
197 * @var string | |
198 */ | |
199 protected $format; | |
200 | |
201 /** | |
202 * @var \Symfony\Component\HttpFoundation\Session\SessionInterface | |
203 */ | |
204 protected $session; | |
205 | |
206 /** | |
207 * @var string | |
208 */ | |
209 protected $locale; | |
210 | |
211 /** | |
212 * @var string | |
213 */ | |
214 protected $defaultLocale = 'en'; | |
136 | 215 |
137 /** | 216 /** |
138 * @var array | 217 * @var array |
139 */ | 218 */ |
140 protected $languages; | |
141 | |
142 /** | |
143 * @var array | |
144 */ | |
145 protected $charsets; | |
146 | |
147 /** | |
148 * @var array | |
149 */ | |
150 protected $encodings; | |
151 | |
152 /** | |
153 * @var array | |
154 */ | |
155 protected $acceptableContentTypes; | |
156 | |
157 /** | |
158 * @var string | |
159 */ | |
160 protected $pathInfo; | |
161 | |
162 /** | |
163 * @var string | |
164 */ | |
165 protected $requestUri; | |
166 | |
167 /** | |
168 * @var string | |
169 */ | |
170 protected $baseUrl; | |
171 | |
172 /** | |
173 * @var string | |
174 */ | |
175 protected $basePath; | |
176 | |
177 /** | |
178 * @var string | |
179 */ | |
180 protected $method; | |
181 | |
182 /** | |
183 * @var string | |
184 */ | |
185 protected $format; | |
186 | |
187 /** | |
188 * @var \Symfony\Component\HttpFoundation\Session\SessionInterface | |
189 */ | |
190 protected $session; | |
191 | |
192 /** | |
193 * @var string | |
194 */ | |
195 protected $locale; | |
196 | |
197 /** | |
198 * @var string | |
199 */ | |
200 protected $defaultLocale = 'en'; | |
201 | |
202 /** | |
203 * @var array | |
204 */ | |
205 protected static $formats; | 219 protected static $formats; |
206 | 220 |
207 protected static $requestFactory; | 221 protected static $requestFactory; |
208 | 222 |
223 private $isHostValid = true; | |
209 private $isForwardedValid = true; | 224 private $isForwardedValid = true; |
210 | 225 |
226 private static $trustedHeaderSet = -1; | |
227 | |
228 /** @deprecated since version 3.3, to be removed in 4.0 */ | |
229 private static $trustedHeaderNames = array( | |
230 self::HEADER_FORWARDED => 'FORWARDED', | |
231 self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', | |
232 self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', | |
233 self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', | |
234 self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', | |
235 ); | |
236 | |
211 private static $forwardedParams = array( | 237 private static $forwardedParams = array( |
212 self::HEADER_CLIENT_IP => 'for', | 238 self::HEADER_X_FORWARDED_FOR => 'for', |
213 self::HEADER_CLIENT_HOST => 'host', | 239 self::HEADER_X_FORWARDED_HOST => 'host', |
214 self::HEADER_CLIENT_PROTO => 'proto', | 240 self::HEADER_X_FORWARDED_PROTO => 'proto', |
215 self::HEADER_CLIENT_PORT => 'host', | 241 self::HEADER_X_FORWARDED_PORT => 'host', |
216 ); | 242 ); |
217 | 243 |
218 /** | 244 /** |
219 * Constructor. | 245 * @param array $query The GET parameters |
220 * | 246 * @param array $request The POST parameters |
221 * @param array $query The GET parameters | 247 * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) |
222 * @param array $request The POST parameters | 248 * @param array $cookies The COOKIE parameters |
223 * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) | 249 * @param array $files The FILES parameters |
224 * @param array $cookies The COOKIE parameters | 250 * @param array $server The SERVER parameters |
225 * @param array $files The FILES parameters | 251 * @param string|resource|null $content The raw body data |
226 * @param array $server The SERVER parameters | |
227 * @param string|resource $content The raw body data | |
228 */ | 252 */ |
229 public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) | 253 public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) |
230 { | 254 { |
231 $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); | 255 $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); |
232 } | 256 } |
234 /** | 258 /** |
235 * Sets the parameters for this request. | 259 * Sets the parameters for this request. |
236 * | 260 * |
237 * This method also re-initializes all properties. | 261 * This method also re-initializes all properties. |
238 * | 262 * |
239 * @param array $query The GET parameters | 263 * @param array $query The GET parameters |
240 * @param array $request The POST parameters | 264 * @param array $request The POST parameters |
241 * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) | 265 * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) |
242 * @param array $cookies The COOKIE parameters | 266 * @param array $cookies The COOKIE parameters |
243 * @param array $files The FILES parameters | 267 * @param array $files The FILES parameters |
244 * @param array $server The SERVER parameters | 268 * @param array $server The SERVER parameters |
245 * @param string|resource $content The raw body data | 269 * @param string|resource|null $content The raw body data |
246 */ | 270 */ |
247 public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) | 271 public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) |
248 { | 272 { |
249 $this->request = new ParameterBag($request); | 273 $this->request = new ParameterBag($request); |
250 $this->query = new ParameterBag($query); | 274 $this->query = new ParameterBag($query); |
303 * Creates a Request based on a given URI and configuration. | 327 * Creates a Request based on a given URI and configuration. |
304 * | 328 * |
305 * The information contained in the URI always take precedence | 329 * The information contained in the URI always take precedence |
306 * over the other information (server and parameters). | 330 * over the other information (server and parameters). |
307 * | 331 * |
308 * @param string $uri The URI | 332 * @param string $uri The URI |
309 * @param string $method The HTTP method | 333 * @param string $method The HTTP method |
310 * @param array $parameters The query (GET) or request (POST) parameters | 334 * @param array $parameters The query (GET) or request (POST) parameters |
311 * @param array $cookies The request cookies ($_COOKIE) | 335 * @param array $cookies The request cookies ($_COOKIE) |
312 * @param array $files The request files ($_FILES) | 336 * @param array $files The request files ($_FILES) |
313 * @param array $server The server parameters ($_SERVER) | 337 * @param array $server The server parameters ($_SERVER) |
314 * @param string $content The raw body data | 338 * @param string|resource|null $content The raw body data |
315 * | 339 * |
316 * @return static | 340 * @return static |
317 */ | 341 */ |
318 public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null) | 342 public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null) |
319 { | 343 { |
434 * @return static | 458 * @return static |
435 */ | 459 */ |
436 public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) | 460 public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) |
437 { | 461 { |
438 $dup = clone $this; | 462 $dup = clone $this; |
439 if ($query !== null) { | 463 if (null !== $query) { |
440 $dup->query = new ParameterBag($query); | 464 $dup->query = new ParameterBag($query); |
441 } | 465 } |
442 if ($request !== null) { | 466 if (null !== $request) { |
443 $dup->request = new ParameterBag($request); | 467 $dup->request = new ParameterBag($request); |
444 } | 468 } |
445 if ($attributes !== null) { | 469 if (null !== $attributes) { |
446 $dup->attributes = new ParameterBag($attributes); | 470 $dup->attributes = new ParameterBag($attributes); |
447 } | 471 } |
448 if ($cookies !== null) { | 472 if (null !== $cookies) { |
449 $dup->cookies = new ParameterBag($cookies); | 473 $dup->cookies = new ParameterBag($cookies); |
450 } | 474 } |
451 if ($files !== null) { | 475 if (null !== $files) { |
452 $dup->files = new FileBag($files); | 476 $dup->files = new FileBag($files); |
453 } | 477 } |
454 if ($server !== null) { | 478 if (null !== $server) { |
455 $dup->server = new ServerBag($server); | 479 $dup->server = new ServerBag($server); |
456 $dup->headers = new HeaderBag($dup->server->getHeaders()); | 480 $dup->headers = new HeaderBag($dup->server->getHeaders()); |
457 } | 481 } |
458 $dup->languages = null; | 482 $dup->languages = null; |
459 $dup->charsets = null; | 483 $dup->charsets = null; |
505 $content = $this->getContent(); | 529 $content = $this->getContent(); |
506 } catch (\LogicException $e) { | 530 } catch (\LogicException $e) { |
507 return trigger_error($e, E_USER_ERROR); | 531 return trigger_error($e, E_USER_ERROR); |
508 } | 532 } |
509 | 533 |
534 $cookieHeader = ''; | |
535 $cookies = array(); | |
536 | |
537 foreach ($this->cookies as $k => $v) { | |
538 $cookies[] = $k.'='.$v; | |
539 } | |
540 | |
541 if (!empty($cookies)) { | |
542 $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n"; | |
543 } | |
544 | |
510 return | 545 return |
511 sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". | 546 sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". |
512 $this->headers."\r\n". | 547 $this->headers. |
548 $cookieHeader."\r\n". | |
513 $content; | 549 $content; |
514 } | 550 } |
515 | 551 |
516 /** | 552 /** |
517 * Overrides the PHP global variables according to this request instance. | 553 * Overrides the PHP global variables according to this request instance. |
519 * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. | 555 * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. |
520 * $_FILES is never overridden, see rfc1867 | 556 * $_FILES is never overridden, see rfc1867 |
521 */ | 557 */ |
522 public function overrideGlobals() | 558 public function overrideGlobals() |
523 { | 559 { |
524 $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), null, '&'))); | 560 $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); |
525 | 561 |
526 $_GET = $this->query->all(); | 562 $_GET = $this->query->all(); |
527 $_POST = $this->request->all(); | 563 $_POST = $this->request->all(); |
528 $_SERVER = $this->server->all(); | 564 $_SERVER = $this->server->all(); |
529 $_COOKIE = $this->cookies->all(); | 565 $_COOKIE = $this->cookies->all(); |
551 /** | 587 /** |
552 * Sets a list of trusted proxies. | 588 * Sets a list of trusted proxies. |
553 * | 589 * |
554 * You should only list the reverse proxies that you manage directly. | 590 * You should only list the reverse proxies that you manage directly. |
555 * | 591 * |
556 * @param array $proxies A list of trusted proxies | 592 * @param array $proxies A list of trusted proxies |
557 */ | 593 * @param int $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies |
558 public static function setTrustedProxies(array $proxies) | 594 * |
595 * @throws \InvalidArgumentException When $trustedHeaderSet is invalid | |
596 */ | |
597 public static function setTrustedProxies(array $proxies/*, int $trustedHeaderSet*/) | |
559 { | 598 { |
560 self::$trustedProxies = $proxies; | 599 self::$trustedProxies = $proxies; |
600 | |
601 if (2 > func_num_args()) { | |
602 @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); | |
603 | |
604 return; | |
605 } | |
606 $trustedHeaderSet = (int) func_get_arg(1); | |
607 | |
608 foreach (self::$trustedHeaderNames as $header => $name) { | |
609 self::$trustedHeaders[$header] = $header & $trustedHeaderSet ? $name : null; | |
610 } | |
611 self::$trustedHeaderSet = $trustedHeaderSet; | |
561 } | 612 } |
562 | 613 |
563 /** | 614 /** |
564 * Gets the list of trusted proxies. | 615 * Gets the list of trusted proxies. |
565 * | 616 * |
566 * @return array An array of trusted proxies | 617 * @return array An array of trusted proxies |
567 */ | 618 */ |
568 public static function getTrustedProxies() | 619 public static function getTrustedProxies() |
569 { | 620 { |
570 return self::$trustedProxies; | 621 return self::$trustedProxies; |
622 } | |
623 | |
624 /** | |
625 * Gets the set of trusted headers from trusted proxies. | |
626 * | |
627 * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies | |
628 */ | |
629 public static function getTrustedHeaderSet() | |
630 { | |
631 return self::$trustedHeaderSet; | |
571 } | 632 } |
572 | 633 |
573 /** | 634 /** |
574 * Sets a list of trusted host patterns. | 635 * Sets a list of trusted host patterns. |
575 * | 636 * |
611 * | 672 * |
612 * @param string $key The header key | 673 * @param string $key The header key |
613 * @param string $value The header name | 674 * @param string $value The header name |
614 * | 675 * |
615 * @throws \InvalidArgumentException | 676 * @throws \InvalidArgumentException |
677 * | |
678 * @deprecated since version 3.3, to be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. | |
616 */ | 679 */ |
617 public static function setTrustedHeaderName($key, $value) | 680 public static function setTrustedHeaderName($key, $value) |
618 { | 681 { |
619 if (!array_key_exists($key, self::$trustedHeaders)) { | 682 @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); |
683 | |
684 if ('forwarded' === $key) { | |
685 $key = self::HEADER_FORWARDED; | |
686 } elseif ('client_ip' === $key) { | |
687 $key = self::HEADER_CLIENT_IP; | |
688 } elseif ('client_host' === $key) { | |
689 $key = self::HEADER_CLIENT_HOST; | |
690 } elseif ('client_proto' === $key) { | |
691 $key = self::HEADER_CLIENT_PROTO; | |
692 } elseif ('client_port' === $key) { | |
693 $key = self::HEADER_CLIENT_PORT; | |
694 } elseif (!array_key_exists($key, self::$trustedHeaders)) { | |
620 throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); | 695 throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); |
621 } | 696 } |
622 | 697 |
623 self::$trustedHeaders[$key] = $value; | 698 self::$trustedHeaders[$key] = $value; |
699 | |
700 if (null !== $value) { | |
701 self::$trustedHeaderNames[$key] = $value; | |
702 self::$trustedHeaderSet |= $key; | |
703 } else { | |
704 self::$trustedHeaderSet &= ~$key; | |
705 } | |
624 } | 706 } |
625 | 707 |
626 /** | 708 /** |
627 * Gets the trusted proxy header name. | 709 * Gets the trusted proxy header name. |
628 * | 710 * |
629 * @param string $key The header key | 711 * @param string $key The header key |
630 * | 712 * |
631 * @return string The header name | 713 * @return string The header name |
632 * | 714 * |
633 * @throws \InvalidArgumentException | 715 * @throws \InvalidArgumentException |
716 * | |
717 * @deprecated since version 3.3, to be removed in 4.0. Use the Request::getTrustedHeaderSet() method instead. | |
634 */ | 718 */ |
635 public static function getTrustedHeaderName($key) | 719 public static function getTrustedHeaderName($key) |
636 { | 720 { |
721 if (2 > func_num_args() || func_get_arg(1)) { | |
722 @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); | |
723 } | |
724 | |
637 if (!array_key_exists($key, self::$trustedHeaders)) { | 725 if (!array_key_exists($key, self::$trustedHeaders)) { |
638 throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key)); | 726 throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key)); |
639 } | 727 } |
640 | 728 |
641 return self::$trustedHeaders[$key]; | 729 return self::$trustedHeaders[$key]; |
717 * flexibility in controllers, it is better to explicitly get request parameters from the appropriate | 805 * flexibility in controllers, it is better to explicitly get request parameters from the appropriate |
718 * public property instead (attributes, query, request). | 806 * public property instead (attributes, query, request). |
719 * | 807 * |
720 * Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY | 808 * Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY |
721 * | 809 * |
722 * @param string $key the key | 810 * @param string $key The key |
723 * @param mixed $default the default value if the parameter key does not exist | 811 * @param mixed $default The default value if the parameter key does not exist |
724 * | 812 * |
725 * @return mixed | 813 * @return mixed |
726 */ | 814 */ |
727 public function get($key, $default = null) | 815 public function get($key, $default = null) |
728 { | 816 { |
819 * header value is a comma+space separated list of IP addresses, the left-most | 907 * header value is a comma+space separated list of IP addresses, the left-most |
820 * being the original client, and each successive proxy that passed the request | 908 * being the original client, and each successive proxy that passed the request |
821 * adding the IP address where it received the request from. | 909 * adding the IP address where it received the request from. |
822 * | 910 * |
823 * If your reverse proxy uses a different header name than "X-Forwarded-For", | 911 * If your reverse proxy uses a different header name than "X-Forwarded-For", |
824 * ("Client-Ip" for instance), configure it via "setTrustedHeaderName()" with | 912 * ("Client-Ip" for instance), configure it via the $trustedHeaderSet |
825 * the "client-ip" key. | 913 * argument of the Request::setTrustedProxies() method instead. |
826 * | 914 * |
827 * @return string|null The client IP address | 915 * @return string|null The client IP address |
828 * | 916 * |
829 * @see getClientIps() | 917 * @see getClientIps() |
830 * @see http://en.wikipedia.org/wiki/X-Forwarded-For | 918 * @see http://en.wikipedia.org/wiki/X-Forwarded-For |
926 * when trusted proxies were set via "setTrustedProxies()". | 1014 * when trusted proxies were set via "setTrustedProxies()". |
927 * | 1015 * |
928 * The "X-Forwarded-Port" header must contain the client port. | 1016 * The "X-Forwarded-Port" header must contain the client port. |
929 * | 1017 * |
930 * If your reverse proxy uses a different header name than "X-Forwarded-Port", | 1018 * If your reverse proxy uses a different header name than "X-Forwarded-Port", |
931 * configure it via "setTrustedHeaderName()" with the "client-port" key. | 1019 * configure it via via the $trustedHeaderSet argument of the |
1020 * Request::setTrustedProxies() method instead. | |
932 * | 1021 * |
933 * @return int|string can be a string if fetched from the server bag | 1022 * @return int|string can be a string if fetched from the server bag |
934 */ | 1023 */ |
935 public function getPort() | 1024 public function getPort() |
936 { | 1025 { |
940 $host = $host[0]; | 1029 $host = $host[0]; |
941 } elseif (!$host = $this->headers->get('HOST')) { | 1030 } elseif (!$host = $this->headers->get('HOST')) { |
942 return $this->server->get('SERVER_PORT'); | 1031 return $this->server->get('SERVER_PORT'); |
943 } | 1032 } |
944 | 1033 |
945 if ($host[0] === '[') { | 1034 if ('[' === $host[0]) { |
946 $pos = strpos($host, ':', strrpos($host, ']')); | 1035 $pos = strpos($host, ':', strrpos($host, ']')); |
947 } else { | 1036 } else { |
948 $pos = strrpos($host, ':'); | 1037 $pos = strrpos($host, ':'); |
949 } | 1038 } |
950 | 1039 |
1002 public function getHttpHost() | 1091 public function getHttpHost() |
1003 { | 1092 { |
1004 $scheme = $this->getScheme(); | 1093 $scheme = $this->getScheme(); |
1005 $port = $this->getPort(); | 1094 $port = $this->getPort(); |
1006 | 1095 |
1007 if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) { | 1096 if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) { |
1008 return $this->getHost(); | 1097 return $this->getHost(); |
1009 } | 1098 } |
1010 | 1099 |
1011 return $this->getHost().':'.$port; | 1100 return $this->getHost().':'.$port; |
1012 } | 1101 } |
1143 * when trusted proxies were set via "setTrustedProxies()". | 1232 * when trusted proxies were set via "setTrustedProxies()". |
1144 * | 1233 * |
1145 * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". | 1234 * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". |
1146 * | 1235 * |
1147 * If your reverse proxy uses a different header name than "X-Forwarded-Proto" | 1236 * If your reverse proxy uses a different header name than "X-Forwarded-Proto" |
1148 * ("SSL_HTTPS" for instance), configure it via "setTrustedHeaderName()" with | 1237 * ("SSL_HTTPS" for instance), configure it via the $trustedHeaderSet |
1149 * the "client-proto" key. | 1238 * argument of the Request::setTrustedProxies() method instead. |
1150 * | 1239 * |
1151 * @return bool | 1240 * @return bool |
1152 */ | 1241 */ |
1153 public function isSecure() | 1242 public function isSecure() |
1154 { | 1243 { |
1168 * when trusted proxies were set via "setTrustedProxies()". | 1257 * when trusted proxies were set via "setTrustedProxies()". |
1169 * | 1258 * |
1170 * The "X-Forwarded-Host" header must contain the client host name. | 1259 * The "X-Forwarded-Host" header must contain the client host name. |
1171 * | 1260 * |
1172 * If your reverse proxy uses a different header name than "X-Forwarded-Host", | 1261 * If your reverse proxy uses a different header name than "X-Forwarded-Host", |
1173 * configure it via "setTrustedHeaderName()" with the "client-host" key. | 1262 * configure it via the $trustedHeaderSet argument of the |
1263 * Request::setTrustedProxies() method instead. | |
1174 * | 1264 * |
1175 * @return string | 1265 * @return string |
1176 * | 1266 * |
1177 * @throws \UnexpectedValueException when the host name is invalid | 1267 * @throws SuspiciousOperationException when the host name is invalid or not trusted |
1178 */ | 1268 */ |
1179 public function getHost() | 1269 public function getHost() |
1180 { | 1270 { |
1181 if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) { | 1271 if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) { |
1182 $host = $host[0]; | 1272 $host = $host[0]; |
1192 | 1282 |
1193 // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) | 1283 // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) |
1194 // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) | 1284 // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) |
1195 // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names | 1285 // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names |
1196 if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) { | 1286 if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) { |
1197 throw new \UnexpectedValueException(sprintf('Invalid Host "%s"', $host)); | 1287 if (!$this->isHostValid) { |
1288 return ''; | |
1289 } | |
1290 $this->isHostValid = false; | |
1291 | |
1292 throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host)); | |
1198 } | 1293 } |
1199 | 1294 |
1200 if (count(self::$trustedHostPatterns) > 0) { | 1295 if (count(self::$trustedHostPatterns) > 0) { |
1201 // to avoid host header injection attacks, you should provide a list of trusted host patterns | 1296 // to avoid host header injection attacks, you should provide a list of trusted host patterns |
1202 | 1297 |
1210 | 1305 |
1211 return $host; | 1306 return $host; |
1212 } | 1307 } |
1213 } | 1308 } |
1214 | 1309 |
1215 throw new \UnexpectedValueException(sprintf('Untrusted Host "%s"', $host)); | 1310 if (!$this->isHostValid) { |
1311 return ''; | |
1312 } | |
1313 $this->isHostValid = false; | |
1314 | |
1315 throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host)); | |
1216 } | 1316 } |
1217 | 1317 |
1218 return $host; | 1318 return $host; |
1219 } | 1319 } |
1220 | 1320 |
1458 public function isMethodSafe(/* $andCacheable = true */) | 1558 public function isMethodSafe(/* $andCacheable = true */) |
1459 { | 1559 { |
1460 if (!func_num_args() || func_get_arg(0)) { | 1560 if (!func_num_args() || func_get_arg(0)) { |
1461 // This deprecation should be turned into a BadMethodCallException in 4.0 (without adding the argument in the signature) | 1561 // This deprecation should be turned into a BadMethodCallException in 4.0 (without adding the argument in the signature) |
1462 // then setting $andCacheable to false should be deprecated in 4.1 | 1562 // then setting $andCacheable to false should be deprecated in 4.1 |
1463 @trigger_error('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since version 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); | 1563 @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); |
1464 | 1564 |
1465 return in_array($this->getMethod(), array('GET', 'HEAD')); | 1565 return in_array($this->getMethod(), array('GET', 'HEAD')); |
1466 } | 1566 } |
1467 | 1567 |
1468 return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE')); | 1568 return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE')); |
1486 * @return bool | 1586 * @return bool |
1487 */ | 1587 */ |
1488 public function isMethodCacheable() | 1588 public function isMethodCacheable() |
1489 { | 1589 { |
1490 return in_array($this->getMethod(), array('GET', 'HEAD')); | 1590 return in_array($this->getMethod(), array('GET', 'HEAD')); |
1591 } | |
1592 | |
1593 /** | |
1594 * Returns the protocol version. | |
1595 * | |
1596 * If the application is behind a proxy, the protocol version used in the | |
1597 * requests between the client and the proxy and between the proxy and the | |
1598 * server might be different. This returns the former (from the "Via" header) | |
1599 * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns | |
1600 * the latter (from the "SERVER_PROTOCOL" server parameter). | |
1601 * | |
1602 * @return string | |
1603 */ | |
1604 public function getProtocolVersion() | |
1605 { | |
1606 if ($this->isFromTrustedProxy()) { | |
1607 preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via'), $matches); | |
1608 | |
1609 if ($matches) { | |
1610 return 'HTTP/'.$matches[2]; | |
1611 } | |
1612 } | |
1613 | |
1614 return $this->server->get('SERVER_PROTOCOL'); | |
1491 } | 1615 } |
1492 | 1616 |
1493 /** | 1617 /** |
1494 * Returns the request body content. | 1618 * Returns the request body content. |
1495 * | 1619 * |
1616 if (count($codes) > 1) { | 1740 if (count($codes) > 1) { |
1617 $lang = $codes[1]; | 1741 $lang = $codes[1]; |
1618 } | 1742 } |
1619 } else { | 1743 } else { |
1620 for ($i = 0, $max = count($codes); $i < $max; ++$i) { | 1744 for ($i = 0, $max = count($codes); $i < $max; ++$i) { |
1621 if ($i === 0) { | 1745 if (0 === $i) { |
1622 $lang = strtolower($codes[0]); | 1746 $lang = strtolower($codes[0]); |
1623 } else { | 1747 } else { |
1624 $lang .= '_'.strtoupper($codes[$i]); | 1748 $lang .= '_'.strtoupper($codes[$i]); |
1625 } | 1749 } |
1626 } | 1750 } |
1711 $this->server->remove('IIS_WasUrlRewritten'); | 1835 $this->server->remove('IIS_WasUrlRewritten'); |
1712 } elseif ($this->headers->has('X_REWRITE_URL')) { | 1836 } elseif ($this->headers->has('X_REWRITE_URL')) { |
1713 // IIS with ISAPI_Rewrite | 1837 // IIS with ISAPI_Rewrite |
1714 $requestUri = $this->headers->get('X_REWRITE_URL'); | 1838 $requestUri = $this->headers->get('X_REWRITE_URL'); |
1715 $this->headers->remove('X_REWRITE_URL'); | 1839 $this->headers->remove('X_REWRITE_URL'); |
1716 } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') { | 1840 } elseif ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { |
1717 // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) | 1841 // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) |
1718 $requestUri = $this->server->get('UNENCODED_URL'); | 1842 $requestUri = $this->server->get('UNENCODED_URL'); |
1719 $this->server->remove('UNENCODED_URL'); | 1843 $this->server->remove('UNENCODED_URL'); |
1720 $this->server->remove('IIS_WasUrlRewritten'); | 1844 $this->server->remove('IIS_WasUrlRewritten'); |
1721 } elseif ($this->server->has('REQUEST_URI')) { | 1845 } elseif ($this->server->has('REQUEST_URI')) { |
1722 $requestUri = $this->server->get('REQUEST_URI'); | 1846 $requestUri = $this->server->get('REQUEST_URI'); |
1723 // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path | 1847 // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path |
1724 $schemeAndHttpHost = $this->getSchemeAndHttpHost(); | 1848 $schemeAndHttpHost = $this->getSchemeAndHttpHost(); |
1725 if (strpos($requestUri, $schemeAndHttpHost) === 0) { | 1849 if (0 === strpos($requestUri, $schemeAndHttpHost)) { |
1726 $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); | 1850 $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); |
1727 } | 1851 } |
1728 } elseif ($this->server->has('ORIG_PATH_INFO')) { | 1852 } elseif ($this->server->has('ORIG_PATH_INFO')) { |
1729 // IIS 5.0, PHP as CGI | 1853 // IIS 5.0, PHP as CGI |
1730 $requestUri = $this->server->get('ORIG_PATH_INFO'); | 1854 $requestUri = $this->server->get('ORIG_PATH_INFO'); |
1772 } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); | 1896 } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); |
1773 } | 1897 } |
1774 | 1898 |
1775 // Does the baseUrl have anything in common with the request_uri? | 1899 // Does the baseUrl have anything in common with the request_uri? |
1776 $requestUri = $this->getRequestUri(); | 1900 $requestUri = $this->getRequestUri(); |
1777 if ($requestUri !== '' && $requestUri[0] !== '/') { | 1901 if ('' !== $requestUri && '/' !== $requestUri[0]) { |
1778 $requestUri = '/'.$requestUri; | 1902 $requestUri = '/'.$requestUri; |
1779 } | 1903 } |
1780 | 1904 |
1781 if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { | 1905 if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { |
1782 // full $baseUrl matches | 1906 // full $baseUrl matches |
1800 } | 1924 } |
1801 | 1925 |
1802 // If using mod_rewrite or ISAPI_Rewrite strip the script filename | 1926 // If using mod_rewrite or ISAPI_Rewrite strip the script filename |
1803 // out of baseUrl. $pos !== 0 makes sure it is not matching a value | 1927 // out of baseUrl. $pos !== 0 makes sure it is not matching a value |
1804 // from PATH_INFO or QUERY_STRING | 1928 // from PATH_INFO or QUERY_STRING |
1805 if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && $pos !== 0) { | 1929 if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { |
1806 $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); | 1930 $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); |
1807 } | 1931 } |
1808 | 1932 |
1809 return rtrim($baseUrl, '/'.DIRECTORY_SEPARATOR); | 1933 return rtrim($baseUrl, '/'.DIRECTORY_SEPARATOR); |
1810 } | 1934 } |
1814 * | 1938 * |
1815 * @return string base path | 1939 * @return string base path |
1816 */ | 1940 */ |
1817 protected function prepareBasePath() | 1941 protected function prepareBasePath() |
1818 { | 1942 { |
1819 $filename = basename($this->server->get('SCRIPT_FILENAME')); | |
1820 $baseUrl = $this->getBaseUrl(); | 1943 $baseUrl = $this->getBaseUrl(); |
1821 if (empty($baseUrl)) { | 1944 if (empty($baseUrl)) { |
1822 return ''; | 1945 return ''; |
1823 } | 1946 } |
1824 | 1947 |
1948 $filename = basename($this->server->get('SCRIPT_FILENAME')); | |
1825 if (basename($baseUrl) === $filename) { | 1949 if (basename($baseUrl) === $filename) { |
1826 $basePath = dirname($baseUrl); | 1950 $basePath = dirname($baseUrl); |
1827 } else { | 1951 } else { |
1828 $basePath = $baseUrl; | 1952 $basePath = $baseUrl; |
1829 } | 1953 } |
1840 * | 1964 * |
1841 * @return string path info | 1965 * @return string path info |
1842 */ | 1966 */ |
1843 protected function preparePathInfo() | 1967 protected function preparePathInfo() |
1844 { | 1968 { |
1845 $baseUrl = $this->getBaseUrl(); | |
1846 | |
1847 if (null === ($requestUri = $this->getRequestUri())) { | 1969 if (null === ($requestUri = $this->getRequestUri())) { |
1848 return '/'; | 1970 return '/'; |
1849 } | 1971 } |
1850 | 1972 |
1851 // Remove the query string from REQUEST_URI | 1973 // Remove the query string from REQUEST_URI |
1852 if (false !== $pos = strpos($requestUri, '?')) { | 1974 if (false !== $pos = strpos($requestUri, '?')) { |
1853 $requestUri = substr($requestUri, 0, $pos); | 1975 $requestUri = substr($requestUri, 0, $pos); |
1854 } | 1976 } |
1855 if ($requestUri !== '' && $requestUri[0] !== '/') { | 1977 if ('' !== $requestUri && '/' !== $requestUri[0]) { |
1856 $requestUri = '/'.$requestUri; | 1978 $requestUri = '/'.$requestUri; |
1857 } | 1979 } |
1858 | 1980 |
1981 if (null === ($baseUrl = $this->getBaseUrl())) { | |
1982 return $requestUri; | |
1983 } | |
1984 | |
1859 $pathInfo = substr($requestUri, strlen($baseUrl)); | 1985 $pathInfo = substr($requestUri, strlen($baseUrl)); |
1860 if (null !== $baseUrl && (false === $pathInfo || '' === $pathInfo)) { | 1986 if (false === $pathInfo || '' === $pathInfo) { |
1861 // If substr() returns false then PATH_INFO is set to an empty string | 1987 // If substr() returns false then PATH_INFO is set to an empty string |
1862 return '/'; | 1988 return '/'; |
1863 } elseif (null === $baseUrl) { | |
1864 return $requestUri; | |
1865 } | 1989 } |
1866 | 1990 |
1867 return (string) $pathInfo; | 1991 return (string) $pathInfo; |
1868 } | 1992 } |
1869 | 1993 |
1876 'html' => array('text/html', 'application/xhtml+xml'), | 2000 'html' => array('text/html', 'application/xhtml+xml'), |
1877 'txt' => array('text/plain'), | 2001 'txt' => array('text/plain'), |
1878 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), | 2002 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), |
1879 'css' => array('text/css'), | 2003 'css' => array('text/css'), |
1880 'json' => array('application/json', 'application/x-json'), | 2004 'json' => array('application/json', 'application/x-json'), |
2005 'jsonld' => array('application/ld+json'), | |
1881 'xml' => array('text/xml', 'application/xml', 'application/x-xml'), | 2006 'xml' => array('text/xml', 'application/xml', 'application/x-xml'), |
1882 'rdf' => array('application/rdf+xml'), | 2007 'rdf' => array('application/rdf+xml'), |
1883 'atom' => array('application/atom+xml'), | 2008 'atom' => array('application/atom+xml'), |
1884 'rss' => array('application/rss+xml'), | 2009 'rss' => array('application/rss+xml'), |
1885 'form' => array('application/x-www-form-urlencoded'), | 2010 'form' => array('application/x-www-form-urlencoded'), |