8000 Work around parse_url() bug · symfony/symfony@5db1928 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5db1928

Browse files
Work around parse_url() bug
1 parent adc87ad commit 5db1928

File tree

9 files changed

+43
-8
lines changed

9 files changed

+43
-8
lines changed

src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php

+8-3
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,19 @@ public function urlRedirectAction(Request $request, string $path, bool $permanen
119119
$statusCode = $permanent ? 301 : 302;
120120
}
121121

122+
if (null === $scheme) {
123+
$scheme = $request->getScheme();
124+
}
125+
126+
if (str_starts_with($path, '//')) {
127+
$path = $scheme.':'.$path;
128+
}
129+
122130
// redirect if the path is a full URL
123131
if (parse_url($path, \PHP_URL_SCHEME)) {
124132
return new RedirectResponse($path, $statusCode);
125133
}
126134

127-
if (null === $scheme) {
128-
$scheme = $request->getScheme();
129-
}
130135

131136
if ($qs = $request->server->get('QUERY_STRING') ?: $request->getQueryString()) {
132137
if (!str_contains($path, '?')) {

src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php

+15
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,21 @@ public function testFullURLWithMethodKeep()
183183
$this->assertEquals(307, $returnResponse->getStatusCode());
184184
}
185185

186+
public function testProtocolRelative()
187+
{
188+
$request = new Request();
189+
$controller = new RedirectController();
190+
191+
$returnResponse = $controller->urlRedirectAction($request, '//foo.bar/');
192+
$this->assertRedirectUrl($returnResponse, 'http://foo.bar/');
193+
$this->assertSame(302, $returnResponse->getStatusCode());
194+
195+
$returnResponse = $controller->urlRedirectAction($request, '//foo.bar/', false, 'https');
196+
$this->assertRedirectUrl($returnResponse, 'https://foo.bar/');
197+
$this->assertSame(302, $returnResponse->getStatusCode());
198+
}
199+
200+
186201
public function testUrlRedirectDefaultPorts()
187202
{
188203
$host = 'www.example.com';

src/Symfony/Component/DomCrawler/Tests/UriResolverTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public static function provideResolverTests()
8686
['foo', 'http://localhost#bar', 'http://localhost/foo'],
8787

8888
['http://', 'http://localhost', 'http://'],
89+
['/foo:123', 'http://localhost', 'http://localhost/foo:123'],
8990
];
9091
}
9192
}

src/Symfony/Component/DomCrawler/UriResolver.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@ public static function resolve(string $uri, ?string $baseUri): string
3232
{
3333
$uri = trim($uri);
3434

35+
if (false === ($scheme = parse_url($uri, \PHP_URL_SCHEME)) && '/' === ($uri[0] ?? '')) {
36+
$scheme = parse_url($uri.'#', \PHP_URL_SCHEME);
37+
}
38+
3539
// absolute URL?
36-
if (null !== parse_url($uri, \PHP_URL_SCHEME)) {
40+
if (null !== $scheme) {
3741
return $uri;
3842
}
3943

src/Symfony/Component/HttpClient/HttpClientTrait.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,10 @@ private static function resolveUrl(array $url, ?array $base, array $queryDefault
515515
private static function parseUrl(string $url, array $query = [], array $allowedSchemes = ['http' => 80, 'https' => 443]): array
516516
{
517517
if (false === $parts = parse_url($url)) {
518-
throw new InvalidArgumentException(sprintf('Malformed URL "%s".', $url));
518+
if ('/' !== ($url[0] ?? '') || false === $parts = parse_url($url.'#')) {
519+
throw new InvalidArgumentException(sprintf('Malformed URL "%s".', $url));
520+
}
521+
unset($parts['fragment']);
519522
}
520523

521524
if ($query) {

src/Symfony/Component/HttpClient/NativeHttpClient.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ private static function createRedirectResolver(array $options, string $host, ?ar
416416

417417
[$host, $port] = self::parseHostPort($url, $info);
418418

419-
if (false !== (parse_url($location, \PHP_URL_HOST) ?? false)) {
419+
if (false !== (parse_url($location.'#', \PHP_URL_HOST) ?? false)) {
420420
// Authorization and Cookie headers MUST NOT follow except for the initial host name
421421
$requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth'];
422422
$requestHeaders[] = 'Host: '.$host.$port;

src/Symfony/Component/HttpFoundation/Request.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,11 @@ public static function create(string $uri, string $method = 'GET', array $parame
355355
$server['PATH_INFO'] = '';
356356
$server['REQUEST_METHOD'] = strtoupper($method);
357357

358-
$components = parse_url($uri);
358+
if (false === ($components = parse_url($uri)) && '/' === ($uri[0] ?? '')) {
359+
$components = parse_url($uri.'#');
360+
unset($components['fragment']);
361+
}
362+
359363
if (isset($components['host'])) {
360364
$server['SERVER_NAME'] = $components['host'];
361365
$server['HTTP_HOST'] = $components['host'];

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

+3
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ public function testCreate()
244244
// Fragment should not be included in the URI
245245
$request = Request::create('http://test.com/foo#bar');
246246
$this->assertEquals('http://test.com/foo', $request->getUri());
247+
248+
$request = Request::create('/foo:123');
249+
$this->assertEquals('http://localhost/foo:123', $request->getUri());
247250
}
248251

249252
public function testCreateWithRequestUri()

src/Symfony/Component/Security/Http/Impersonate/ImpersonateUrlGenerator.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private function buildExitPath(?string $targetUri = null): string
6969
$targetUri = $request->getRequestUri();
7070
}
7171

72-
$targetUri .= (parse_url($targetUri, \PHP_URL_QUERY) ? '&' : '?').http_build_query([$switchUserConfig['parameter'] => SwitchUserListener::EXIT_VALUE], '', '&');
72+
$targetUri .= (str_contains($targetUri, '?') ? '&' : '?').http_build_query([$switchUserConfig['parameter'] => SwitchUserListener::EXIT_VALUE], '', '&');
7373

7474
return $targetUri;
7575
}

0 commit comments

Comments
 (0)
0