From c7519144105bf319fd7ce437f9733b3cdc443ce7 Mon Sep 17 00:00:00 2001 From: pfofi <7479939+pfofi@users.noreply.github.com> Date: Fri, 10 May 2019 13:55:31 +0200 Subject: [PATCH 1/3] Fix URL resolution for Composer repositories Composer was unable canonicalize URLs in non-HTTP(S) Composer repositories. For example it was not possible to use a `providers-url` in a repository loaded via the `file://` scheme. See also: #8115 --- .../Repository/ComposerRepository.php | 6 +- .../Repository/ComposerRepositoryTest.php | 67 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 38b865103..1b03885fe 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -562,7 +562,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito protected function canonicalizeUrl($url) { if ('/' === $url[0]) { - return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url); + if (preg_match('{[^:]+://[^/]*}', $this->url, $matches)) { + return $matches[0] . $url; + } + + return $this->url; } return $url; diff --git a/tests/Composer/Test/Repository/ComposerRepositoryTest.php b/tests/Composer/Test/Repository/ComposerRepositoryTest.php index 3e29e8023..8e9216b35 100644 --- a/tests/Composer/Test/Repository/ComposerRepositoryTest.php +++ b/tests/Composer/Test/Repository/ComposerRepositoryTest.php @@ -204,4 +204,71 @@ class ComposerRepositoryTest extends TestCase $repository->search('foo', RepositoryInterface::SEARCH_FULLTEXT, 'library') ); } + + /** + * @dataProvider canonicalizeUrlProvider + * + * @param string $expected + * @param string $url + * @param string $repositoryUrl + */ + public function testCanonicalizeUrl($expected, $url, $repositoryUrl) + { + $repository = new ComposerRepository( + array('url' => $repositoryUrl), + new NullIO(), + FactoryMock::createConfig() + ); + + $object = new \ReflectionObject($repository); + + $method = $object->getMethod('canonicalizeUrl'); + $method->setAccessible(true); + + // ComposerRepository::__construct ensures that the repository URL has a + // protocol, so reset it here in order to test all cases. + $property = $object->getProperty('url'); + $property->setAccessible(true); + $property->setValue($repository, $repositoryUrl); + + $this->assertSame($expected, $method->invoke($repository, $url)); + } + + public function canonicalizeUrlProvider() + { + return array( + array( + 'https://example.org/path/to/file', + '/path/to/file', + 'https://example.org', + ), + array( + 'https://example.org/canonic_url', + 'https://example.org/canonic_url', + 'https://should-not-see-me.test', + ), + array( + 'file:///path/to/repository/file', + '/path/to/repository/file', + 'file:///path/to/repository', + ), + array( + // Assert that the repository URL is returned unchanged if it is + // not a URL. + // (Backward compatibility test) + 'invalid_repo_url', + '/path/to/file', + 'invalid_repo_url', + ), + array( + // Assert that URLs can contain sequences resembling pattern + // references as understood by preg_replace() without messing up + // the result. + // (Regression test) + 'https://example.org/path/to/unusual_$0_filename', + '/path/to/unusual_$0_filename', + 'https://example.org', + ), + ); + } } From e7f02be9ffec80384df5d49e463d9f127d6957bc Mon Sep 17 00:00:00 2001 From: pfofi <7479939+pfofi@users.noreply.github.com> Date: Sat, 11 May 2019 16:27:39 +0200 Subject: [PATCH 2/3] Anchor pattern --- src/Composer/Repository/ComposerRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 1b03885fe..8fc40c812 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -562,7 +562,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito protected function canonicalizeUrl($url) { if ('/' === $url[0]) { - if (preg_match('{[^:]+://[^/]*}', $this->url, $matches)) { + if (preg_match('{^[^:]+://[^/]*}', $this->url, $matches)) { return $matches[0] . $url; } From 82825ccc74b977a86010dc78a80502e0dd5dc5dd Mon Sep 17 00:00:00 2001 From: pfofi <7479939+pfofi@users.noreply.github.com> Date: Fri, 7 Jun 2019 09:13:11 +0200 Subject: [PATCH 3/3] Use possessive quantifiers --- src/Composer/Repository/ComposerRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 8fc40c812..9d5b727cc 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -562,7 +562,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito protected function canonicalizeUrl($url) { if ('/' === $url[0]) { - if (preg_match('{^[^:]+://[^/]*}', $this->url, $matches)) { + if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) { return $matches[0] . $url; }