From: Tim Otten Date: Sat, 22 Jul 2023 01:18:27 +0000 (-0700) Subject: Fix relative URL generation when using alternate HTTP port X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=395d9b5ec1735f47ffd595209054f769706cb42a;p=civicrm-core.git Fix relative URL generation when using alternate HTTP port --- diff --git a/CRM/Utils/Url.php b/CRM/Utils/Url.php index 5a40beb5a0..d30d3003e6 100644 --- a/CRM/Utils/Url.php +++ b/CRM/Utils/Url.php @@ -40,13 +40,19 @@ class CRM_Utils_Url { * Convert to a relative URL (if host/port matches). * * @param string $value + * @param string|null $currentHostPort + * The value of HTTP_HOST. (NULL means "lookup HTTP_HOST") * @return string */ - public static function toRelative(string $value): string { - $parsed = parse_url($value); - if (isset($_SERVER['HTTP_HOST']) && isset($parsed['host']) && $_SERVER['HTTP_HOST'] == $parsed['host']) { - $value = $parsed['path']; + public static function toRelative(string $value, ?string $currentHostPort = NULL): string { + $currentHostPort = $currentHostPort ?: $_SERVER['HTTP_HOST'] ?? NULL; + + if (preg_match(';^(//|http://|https://)([^/]*)(.*);', $value, $m)) { + if ($m[2] === $currentHostPort) { + return $m[3]; + } } + return $value; } diff --git a/tests/phpunit/CRM/Utils/UrlTest.php b/tests/phpunit/CRM/Utils/UrlTest.php new file mode 100644 index 0000000000..fdbf6301b7 --- /dev/null +++ b/tests/phpunit/CRM/Utils/UrlTest.php @@ -0,0 +1,72 @@ +useTransaction(); + } + + /** + * Equal cases. + * + * @return array + */ + public function relativeCases() { + // array(0 => $absoluteUrl, 1 => $currentHost, 2 => $expectedResult) + $cases = []; + $cases[] = ['//example.com/', 'example.com', '/']; + $cases[] = ['http://example.com/', 'example.com', '/']; + $cases[] = ['http://example.com/foo', 'example.com', '/foo']; + $cases[] = ['https://example.com/foo/bar', 'example.com', '/foo/bar']; + $cases[] = ['http://example.com/foo?bar#baz', 'example.com', '/foo?bar#baz']; + + $cases[] = ['//example.com/', 'example.com:8001', '//example.com/']; + $cases[] = ['http://example.com/', 'example.com:8001', 'http://example.com/']; + $cases[] = ['http://example.com/foo', 'example.com:8001', 'http://example.com/foo']; + $cases[] = ['https://example.com/foo/bar', 'example.com:8001', 'https://example.com/foo/bar']; + $cases[] = ['http://example.com/foo?bar#baz', 'example.com:8001', 'http://example.com/foo?bar#baz']; + + $cases[] = ['//example.com:8001/', 'example.com:8001', '/']; + $cases[] = ['http://example.com:8001/', 'example.com:8001', '/']; + $cases[] = ['http://example.com:8001/foo', 'example.com:8001', '/foo']; + $cases[] = ['https://example.com:8001/foo/bar', 'example.com:8001', '/foo/bar']; + $cases[] = ['http://example.com:8001/foo?bar#baz', 'example.com:8001', '/foo?bar#baz']; + + $cases[] = ['//sub.example.com/', 'example.com', '//sub.example.com/']; + $cases[] = ['http://sub.example.com/', 'example.com', 'http://sub.example.com/']; + $cases[] = ['http://sub.example.com/foo', 'example.com', 'http://sub.example.com/foo']; + + $cases[] = ['//sub.example.com/', 'sub.example.com', '/']; + $cases[] = ['http://sub.example.com/', 'sub.example.com', '/']; + $cases[] = ['http://sub.example.com/foo/bar', 'sub.example.com', '/foo/bar']; + + $cases[] = ['http://127.0.0.1/foo/bar', 'sub.example.com', 'http://127.0.0.1/foo/bar']; + $cases[] = ['https://127.0.0.1/foo/bar', '127.0.0.1', '/foo/bar']; + + $cases[] = ['http://[2001:aaaa:bbbb:cccc:dddd:eeee:ffff:9999]:8001/foo/bar', 'sub.example.com', 'http://[2001:aaaa:bbbb:cccc:dddd:eeee:ffff:9999]:8001/foo/bar']; + $cases[] = ['https://[2001:aaaa:bbbb:cccc:dddd:eeee:ffff:9999]:8001/foo/bar', '[2001:aaaa:bbbb:cccc:dddd:eeee:ffff:9999]:8001', '/foo/bar']; + + // return CRM_Utils_Array::subset($cases, [2]); + return $cases; + } + + /** + * Test relative URL conversions. + * + * @param string $absoluteUrl + * @param string $currentHost + * @param string $expectedResult + * + * @dataProvider relativeCases + */ + public function testEquals($absoluteUrl, $currentHost, $expectedResult) { + $actual = CRM_Utils_Url::toRelative($absoluteUrl, $currentHost); + $this->assertEquals($expectedResult, $actual, "Within \"$currentHost\", \"$absoluteUrl\" should render as \"$expectedResult\""); + } + +}