diff --git a/core/lib/Drupal/Core/File/FileUrlGenerator.php b/core/lib/Drupal/Core/File/FileUrlGenerator.php index b3fdefea70804eda22d7d590fd2de98b830c6d98..3f32d485a69ca6a083c5f078a74516a06053f306 100644 --- a/core/lib/Drupal/Core/File/FileUrlGenerator.php +++ b/core/lib/Drupal/Core/File/FileUrlGenerator.php @@ -211,7 +211,6 @@ public function transformRelative(string $file_url, bool $root_relative = TRUE): // instead of a port number. $request = $this->requestStack->getCurrentRequest(); $host = $request->getHost(); - $scheme = $request->getScheme(); $port = $request->getPort() ?: 80; // Files may be accessible on a different port than the web request. @@ -220,20 +219,15 @@ public function transformRelative(string $file_url, bool $root_relative = TRUE): return $file_url; } - if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) { - $http_host = $host; - } - else { - $http_host = $host . ':' . $port; - } - // If this should not be a root-relative path but relative to the drupal // base path, add it to the host to be removed from the URL as well. - if (!$root_relative) { - $http_host .= $request->getBasePath(); - } + $base_path = !$root_relative ? $request->getBasePath() : ''; + + $host = preg_quote($host, '@'); + $port = preg_quote($port, '@'); + $base_path = preg_quote($base_path, '@'); - return preg_replace('|^https?://' . preg_quote($http_host, '|') . '|', '', $file_url); + return preg_replace("@^https?://{$host}(:{$port})?{$base_path}($|/)@", '/', $file_url); } } diff --git a/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php b/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php index 57111ee2f442a235dcaf51ecd96ed909cfdcd4fd..4a4d7e5a42b3195bb1fd9ed68e5c99ac1d77fdd4 100644 --- a/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php @@ -19,25 +19,25 @@ class UrlTransformRelativeTest extends KernelTestBase { * * @dataProvider providerFileUrlTransformRelative */ - public function testFileUrlTransformRelative($host, $port, $https, $url, $expected) { + public function testFileUrlTransformRelative($host, $port, $https, $base_path, $root_relative, $url, $expected) { $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; $_SERVER['SERVER_ADDR'] = '127.0.0.1'; $_SERVER['SERVER_PORT'] = $port; $_SERVER['SERVER_SOFTWARE'] = NULL; $_SERVER['SERVER_NAME'] = $host; - $_SERVER['REQUEST_URI'] = '/'; + $_SERVER['REQUEST_URI'] = "{$base_path}/"; $_SERVER['REQUEST_METHOD'] = 'GET'; - $_SERVER['SCRIPT_NAME'] = '/index.php'; - $_SERVER['SCRIPT_FILENAME'] = '/index.php'; - $_SERVER['PHP_SELF'] = '/index.php'; + $_SERVER['SCRIPT_NAME'] = "{$base_path}/index.php"; + $_SERVER['SCRIPT_FILENAME'] = "{$base_path}/index.php"; + $_SERVER['PHP_SELF'] = "{$base_path}/index.php"; $_SERVER['HTTP_USER_AGENT'] = 'Drupal command line'; $_SERVER['HTTPS'] = $https; $request = Request::createFromGlobals(); \Drupal::requestStack()->push($request); - $this->assertSame($expected, \Drupal::service('file_url_generator')->transformRelative($url)); + $this->assertSame($expected, \Drupal::service('file_url_generator')->transformRelative($url, $root_relative)); } public function providerFileUrlTransformRelative() { @@ -46,20 +46,116 @@ public function providerFileUrlTransformRelative() { 'example.com', 80, '', + '', + TRUE, 'http://example.com/page', '/page', ], + 'http with base path and root relative' => [ + 'example.com', + 80, + '', + '/~foo', + TRUE, + 'http://example.com/~foo/page', + '/~foo/page', + ], + 'http with base path and not root relative' => [ + 'example.com', + 80, + '', + '/~foo', + FALSE, + 'http://example.com/~foo/page', + '/page', + ], + 'http with weird base path and root relative' => [ + 'example.com', + 80, + '', + '/~foo$.*!', + TRUE, + 'http://example.com/~foo$.*!/page', + '/~foo$.*!/page', + ], + 'http with weird base path and not root relative' => [ + 'example.com', + 80, + '', + '/~foo$.*!', + FALSE, + 'http://example.com/~foo$.*!/page', + '/page', + ], + 'http frontpage' => [ + 'example.com', + 80, + '', + '', + TRUE, + 'http://example.com', + '/', + ], + 'http frontpage with a slash' => [ + 'example.com', + 80, + '', + '', + TRUE, + 'http://example.com/', + '/', + ], + 'https on http' => [ + 'example.com', + 80, + '', + '', + TRUE, + 'https://example.com/page', + '/page', + ], 'https' => [ 'example.com', 443, 'on', + '', + TRUE, 'https://example.com/page', '/page', ], + 'https frontpage' => [ + 'example.com', + 443, + 'on', + '', + TRUE, + 'https://example.com', + '/', + ], + 'https frontpage with a slash' => [ + 'example.com', + 443, + 'on', + '', + TRUE, + 'https://example.com/', + '/', + ], + 'http with path containing special chars' => [ + 'example.com', + 80, + '', + '', + TRUE, + 'http://example.com/~page$.*!', + '/~page$.*!', + ], 'http 8080' => [ 'example.com', 8080, '', + '', + TRUE, 'https://example.com:8080/page', '/page', ], @@ -67,6 +163,8 @@ public function providerFileUrlTransformRelative() { 'example.com', 8443, 'on', + '', + TRUE, 'https://example.com:8443/page', '/page', ], @@ -74,6 +172,8 @@ public function providerFileUrlTransformRelative() { 'example.com', 80, '', + '', + TRUE, 'http://exampleXcom/page', 'http://exampleXcom/page', ], @@ -81,6 +181,8 @@ public function providerFileUrlTransformRelative() { 'example.com', 80, '', + '', + TRUE, 'http://example.com:9000/page', 'http://example.com:9000/page', ], @@ -88,9 +190,47 @@ public function providerFileUrlTransformRelative() { 'example.com', 443, 'on', + '', + TRUE, 'https://example.com:8443/page', 'https://example.com:8443/page', ], + 'http files on different port than the web request on non default port' => [ + 'example.com', + 8080, + '', + '', + TRUE, + 'http://example.com:9000/page', + 'http://example.com:9000/page', + ], + 'https files on different port than the web request on non default port' => [ + 'example.com', + 8443, + 'on', + '', + TRUE, + 'https://example.com:9000/page', + 'https://example.com:9000/page', + ], + 'http with default port explicit mentioned in URL' => [ + 'example.com', + 80, + '', + '', + TRUE, + 'http://example.com:80/page', + '/page', + ], + 'https with default port explicit mentioned in URL' => [ + 'example.com', + 443, + 'on', + '', + TRUE, + 'https://example.com:443/page', + '/page', + ], ]; return $data; }