Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 04fcac7

Browse filesBrowse files
committed
Merge branch '2.8' into 3.2
* 2.8: [HttpFoundation] Fix missing handling of for/host/proto info from "Forwarded" header [Validator] Add object handling of invalid constraints in Composite [WebProfilerBundle] Remove uneeded directive in the form collector styles Revert "bug #21841 [Console] Do not squash input changes made from console.command event (chalasr)" [HttpFoundation] Fix Request::getHost() when having several hosts in X_FORWARDED_HOST
2 parents 7d76227 + 8371dea commit 04fcac7
Copy full SHA for 04fcac7

File tree

10 files changed

+142
-106
lines changed
Filter options

10 files changed

+142
-106
lines changed

‎src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
}
6161
#tree-menu .empty {
6262
border: 0;
63-
margin: 0;
6463
padding: 0;
6564
}
6665
#tree-details-container {

‎src/Symfony/Component/Console/Application.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Application.php
-4Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -839,10 +839,6 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
839839
// ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
840840
}
841841

842-
// don't bind the input again as it would override any input argument/option set from the command event in
843-
// addition to being useless
844-
$command->setInputBound(true);
845-
846842
$event = new ConsoleCommandEvent($command, $input, $output);
847843
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
848844

‎src/Symfony/Component/Console/Command/Command.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Command/Command.php
+5-16Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ class Command
4040
private $ignoreValidationErrors = false;
4141
private $applicationDefinitionMerged = false;
4242
private $applicationDefinitionMergedWithArgs = false;
43-
private $inputBound = false;
4443
private $code;
4544
private $synopsis = array();
4645
private $usages = array();
@@ -217,13 +216,11 @@ public function run(InputInterface $input, OutputInterface $output)
217216
$this->mergeApplicationDefinition();
218217

219218
// bind the input against the command specific arguments/options
220-
if (!$this->inputBound) {
221-
try {
222-
$input->bind($this->definition);
223-
} catch (ExceptionInterface $e) {
224-
if (!$this->ignoreValidationErrors) {
225-
throw $e;
226-
}
219+
try {
220+
$input->bind($this->definition);
221+
} catch (ExceptionInterface $e) {
222+
if (!$this->ignoreValidationErrors) {
223+
throw $e;
227224
}
228225
}
229226

@@ -652,14 +649,6 @@ public function getHelper($name)
652649
return $this->helperSet->get($name);
653650
}
654651

655-
/**
656-
* @internal
657-
*/
658-
public function setInputBound($inputBound)
659-
{
660-
$this->inputBound = $inputBound;
661-
}
662-
663652
/**
664653
* Validates a command name.
665654
*

‎src/Symfony/Component/Console/Tests/ApplicationTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tests/ApplicationTest.php
-25Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,31 +1106,6 @@ public function testRunWithDispatcherAddingInputOptions()
11061106
$this->assertEquals('some test value', $extraValue);
11071107
}
11081108

1109-
public function testUpdateInputFromConsoleCommandEvent()
1110-
{
1111-
$dispatcher = $this->getDispatcher();
1112-
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
1113-
$event->getInput()->setOption('extra', 'overriden');
1114-
});
1115-
1116-
$application = new Application();
1117-
$application->setDispatcher($dispatcher);
1118-
$application->setAutoExit(false);
1119-
1120-
$application
1121-
->register('foo')
1122-
->addOption('extra', null, InputOption::VALUE_REQUIRED)
1123-
->setCode(function (InputInterface $input, OutputInterface $output) {
1124-
$output->write('foo.');
1125-
})
1126-
;
1127-
1128-
$tester = new ApplicationTester($application);
1129-
$tester->run(array('command' => 'foo', '--extra' => 'original'));
1130-
1131-
$this->assertEquals('overriden', $tester->getInput()->getOption('extra'));
1132-
}
1133-
11341109
/**
11351110
* @group legacy
11361111
*/

‎src/Symfony/Component/HttpFoundation/Request.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Request.php
+68-55Lines changed: 68 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,15 @@ class Request
206206

207207
protected static $requestFactory;
208208

209+
private $isForwardedValid = true;
210+
211+
private static $forwardedParams = array(
212+
self::HEADER_CLIENT_IP => 'for',
213+
self::HEADER_CLIENT_HOST => 'host',
214+
self::HEADER_CLIENT_PROTO => 'proto',
215+
self::HEADER_CLIENT_PORT => 'host',
216+
);
217+
209218
/**
210219
* Constructor.
211220
*
@@ -793,41 +802,13 @@ public function setSession(SessionInterface $session)
793802
*/
794803
public function getClientIps()
795804
{
796-
$clientIps = array();
797805
$ip = $this->server->get('REMOTE_ADDR');
798806

799807
if (!$this->isFromTrustedProxy()) {
800808
return array($ip);
801809
}
802810

803-
$hasTrustedForwardedHeader = self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED]);
804-
$hasTrustedClientIpHeader = self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP]);
805-
806-
if ($hasTrustedForwardedHeader) {
807-
$forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
808-
preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
809-
$forwardedClientIps = $matches[3];
810-
811-
$forwardedClientIps = $this->normalizeAndFilterClientIps($forwardedClientIps, $ip);
812-
$clientIps = $forwardedClientIps;
813-
}
814-
815-
if ($hasTrustedClientIpHeader) {
816-
$xForwardedForClientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
817-
818-
$xForwardedForClientIps = $this->normalizeAndFilterClientIps($xForwardedForClientIps, $ip);
819-
$clientIps = $xForwardedForClientIps;
820-
}
821-
822-
if ($hasTrustedForwardedHeader && $hasTrustedClientIpHeader && $forwardedClientIps !== $xForwardedForClientIps) {
823-
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.');
824-
}
825-
826-
if (!$hasTrustedForwardedHeader && !$hasTrustedClientIpHeader) {
827-
return $this->normalizeAndFilterClientIps(array(), $ip);
828-
}
829-
830-
return $clientIps;
811+
return $this->getTrustedValues(self::HEADER_CLIENT_IP, $ip) ?: array($ip);
831812
}
832813

833814
/**
@@ -953,31 +934,25 @@ public function getScheme()
953934
*/
954935
public function getPort()
955936
{
956-
if ($this->isFromTrustedProxy()) {
957-
if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) {
958-
return $port;
959-
}
960-
961-
if (self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && 'https' === $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO], 'http')) {
962-
return 443;
963-
}
937+
if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_PORT)) {
938+
$host = $host[0];
939+
} elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) {
940+
$host = $host[0];
941+
} elseif (!$host = $this->headers->get('HOST')) {
942+
return $this->server->get('SERVER_PORT');
964943
}
965944

966-
if ($host = $this->headers->get('HOST')) {
967-
if ($host[0] === '[') {
968-
$pos = strpos($host, ':', strrpos($host, ']'));
969-
} else {
970-
$pos = strrpos($host, ':');
971-
}
972-
973-
if (false !== $pos) {
974-
return (int) substr($host, $pos + 1);
975-
}
945+
if ($host[0] === '[') {
946+
$pos = strpos($host, ':', strrpos($host, ']'));
947+
} else {
948+
$pos = strrpos($host, ':');
949+
}
976950

977-
return 'https' === $this->getScheme() ? 443 : 80;
951+
if (false !== $pos) {
952+
return (int) substr($host, $pos + 1);
978953
}
979954

980-
return $this->server->get('SERVER_PORT');
955+
return 'https' === $this->getScheme() ? 443 : 80;
981956
}
982957

983958
/**
@@ -1177,8 +1152,8 @@ public function getQueryString()
11771152
*/
11781153
public function isSecure()
11791154
{
1180-
if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) {
1181-
return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1'));
1155+
if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_CLIENT_PROTO)) {
1156+
return in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true);
11821157
}
11831158

11841159
$https = $this->server->get('HTTPS');
@@ -1203,10 +1178,8 @@ public function isSecure()
12031178
*/
12041179
public function getHost()
12051180
{
1206-
if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
1207-
$elements = explode(',', $host);
1208-
1209-
$host = $elements[count($elements) - 1];
1181+
if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) {
1182+
$host = $host[0];
12101183
} elseif (!$host = $this->headers->get('HOST')) {
12111184
if (!$host = $this->server->get('SERVER_NAME')) {
12121185
$host = $this->server->get('SERVER_ADDR', '');
@@ -1977,8 +1950,48 @@ public function isFromTrustedProxy()
19771950
return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies);
19781951
}
19791952

1953+
private function getTrustedValues($type, $ip = null)
1954+
{
1955+
$clientValues = array();
1956+
$forwardedValues = array();
1957+
1958+
if (self::$trustedHeaders[$type] && $this->headers->has(self::$trustedHeaders[$type])) {
1959+
foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) {
1960+
$clientValues[] = (self::HEADER_CLIENT_PORT === $type ? '0.0.0.0:' : '').trim($v);
1961+
}
1962+
}
1963+
1964+
if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
1965+
$forwardedValues = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
1966+
$forwardedValues = preg_match_all(sprintf('{(?:%s)=(?:"?\[?)([a-zA-Z0-9\.:_\-/]*+)}', self::$forwardedParams[$type]), $forwardedValues, $matches) ? $matches[1] : array();
1967+
}
1968+
1969+
if (null !== $ip) {
1970+
$clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip);
1971+
$forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip);
1972+
}
1973+
1974+
if ($forwardedValues === $clientValues || !$clientValues) {
1975+
return $forwardedValues;
1976+
}
1977+
1978+
if (!$forwardedValues) {
1979+
return $clientValues;
1980+
}
1981+
1982+
if (!$this->isForwardedValid) {
1983+
return null !== $ip ? array('0.0.0.0', $ip) : array();
1984+
}
1985+
$this->isForwardedValid = false;
1986+
1987+
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]));
1988+
}
1989+
19801990
private function normalizeAndFilterClientIps(array $clientIps, $ip)
19811991
{
1992+
if (!$clientIps) {
1993+
return array();
1994+
}
19821995
$clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
19831996
$firstTrustedIp = null;
19841997

‎src/Symfony/Component/HttpFoundation/Tests/RequestTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
+52-3Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,12 +1670,12 @@ private function getRequestInstanceForClientIpsForwardedTests($remoteAddr, $http
16701670
return $request;
16711671
}
16721672

1673-
public function testTrustedProxies()
1673+
public function testTrustedProxiesXForwardedFor()
16741674
{
16751675
$request = Request::create('http://example.com/');
16761676
$request->server->set('REMOTE_ADDR', '3.3.3.3');
16771677
$request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2');
1678-
$request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080');
1678+
$request->headers->set('X_FORWARDED_HOST', 'foo.example.com:1234, real.example.com:8080');
16791679
$request->headers->set('X_FORWARDED_PROTO', 'https');
16801680
$request->headers->set('X_FORWARDED_PORT', 443);
16811681
$request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4');
@@ -1706,7 +1706,7 @@ public function testTrustedProxies()
17061706
// trusted proxy via setTrustedProxies()
17071707
Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'));
17081708
$this->assertEquals('1.1.1.1', $request->getClientIp());
1709-
$this->assertEquals('real.example.com', $request->getHost());
1709+
$this->assertEquals('foo.example.com', $request->getHost());
17101710
$this->assertEquals(443, $request->getPort());
17111711
$this->assertTrue($request->isSecure());
17121712

@@ -1753,6 +1753,55 @@ public function testTrustedProxies()
17531753
Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO');
17541754
}
17551755

1756+
public function testTrustedProxiesForwarded()
1757+
{
1758+
$request = Request::create('http://example.com/');
1759+
$request->server->set('REMOTE_ADDR', '3.3.3.3');
1760+
$request->headers->set('FORWARDED', 'for=1.1.1.1, host=foo.example.com:8080, proto=https, for=2.2.2.2, host=real.example.com:8080');
1761+
1762+
// no trusted proxies
1763+
$this->assertEquals('3.3.3.3', $request->getClientIp());
1764+
$this->assertEquals('example.com', $request->getHost());
1765+
$this->assertEquals(80, $request->getPort());
1766+
$this->assertFalse($request->isSecure());
1767+
1768+
// disabling proxy trusting
1769+
Request::setTrustedProxies(array());
1770+
$this->assertEquals('3.3.3.3', $request->getClientIp());
1771+
$this->assertEquals('example.com', $request->getHost());
1772+
$this->assertEquals(80, $request->getPort());
1773+
$this->assertFalse($request->isSecure());
1774+
1775+
// request is forwarded by a non-trusted proxy
1776+
Request::setTrustedProxies(array('2.2.2.2'));
1777+
$this->assertEquals('3.3.3.3', $request->getClientIp());
1778+
$this->assertEquals('example.com', $request->getHost());
1779+
$this->assertEquals(80, $request->getPort());
1780+
$this->assertFalse($request->isSecure());
1781+
1782+
// trusted proxy via setTrustedProxies()
1783+
Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'));
1784+
$this->assertEquals('1.1.1.1', $request->getClientIp());
1785+
$this->assertEquals('foo.example.com', $request->getHost());
1786+
$this->assertEquals(8080, $request->getPort());
1787+
$this->assertTrue($request->isSecure());
1788+
1789+
// trusted proxy via setTrustedProxies()
1790+
Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'));
1791+
$this->assertEquals('3.3.3.3', $request->getClientIp());
1792+
$this->assertEquals('example.com', $request->getHost());
1793+
$this->assertEquals(80, $request->getPort());
1794+
$this->assertFalse($request->isSecure());
1795+
1796+
// check various X_FORWARDED_PROTO header values
1797+
Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'));
1798+
$request->headers->set('FORWARDED', 'proto=ssl');
1799+
$this->assertTrue($request->isSecure());
1800+
1801+
$request->headers->set('FORWARDED', 'proto=https, proto=http');
1802+
$this->assertTrue($request->isSecure());
1803+
}
1804+
17561805
/**
17571806
* @expectedException \InvalidArgumentException
17581807
*/

‎src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function testListenerThrowsWhenMasterRequestHasInconsistentClientIps()
3232
$request = new Request();
3333
$request->setTrustedProxies(array('1.1.1.1'));
3434
$request->server->set('REMOTE_ADDR', '1.1.1.1');
35-
$request->headers->set('FORWARDED', '2.2.2.2');
35+
$request->headers->set('FORWARDED', 'for=2.2.2.2');
3636
$request->headers->set('X_FORWARDED_FOR', '3.3.3.3');
3737

3838
$dispatcher->addListener(KernelEvents::REQUEST, array(new ValidateRequestListener(), 'onKernelRequest'));

‎src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ public function testInconsistentClientIpsOnMasterRequests()
311311
$request = new Request();
312312
$request->setTrustedProxies(array('1.1.1.1'));
313313
$request->server->set('REMOTE_ADDR', '1.1.1.1');
314-
$request->headers->set('FORWARDED', '2.2.2.2');
314+
$request->headers->set('FORWARDED', 'for=2.2.2.2');
315315
$request->headers->set('X_FORWARDED_FOR', '3.3.3.3');
316316

317317
$dispatcher = new EventDispatcher();

‎src/Symfony/Component/Validator/Constraints/Composite.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/Composite.php
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ public function __construct($options = null)
6767

6868
foreach ($nestedConstraints as $constraint) {
6969
if (!$constraint instanceof Constraint) {
70+
if (is_object($constraint)) {
71+
$constraint = get_class($constraint);
72+
}
73+
7074
throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, get_class($this)));
7175
}
7276

‎src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,17 @@ public function testFailIfNoConstraint()
125125
));
126126
}
127127

128+
/**
129+
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
130+
*/
131+
public function testFailIfNoConstraintObject()
132+
{
133+
new ConcreteComposite(array(
134+
new NotNull(array('groups' => 'Default')),
135+
new \ArrayObject(),
136+
));
137+
}
138+
128139
/**
129140
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
130141
*/

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.