From cbd91b59527b3262e7d9528b23b0053f8dd99405 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 5 Nov 2012 15:39:43 +0100 Subject: [PATCH] Fix FILTER_VALIDATE_URL not supporting IDNs --- .../Package/Loader/ValidatingArrayLoader.php | 29 +++++++++++++------ .../Repository/ComposerRepository.php | 3 +- src/Composer/Repository/PearRepository.php | 3 +- .../Loader/ValidatingArrayLoaderTest.php | 12 ++++---- .../Repository/ComposerRepositoryTest.php | 2 +- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/Composer/Package/Loader/ValidatingArrayLoader.php b/src/Composer/Package/Loader/ValidatingArrayLoader.php index 53e1cd07d..02f08c55e 100644 --- a/src/Composer/Package/Loader/ValidatingArrayLoader.php +++ b/src/Composer/Package/Loader/ValidatingArrayLoader.php @@ -91,7 +91,7 @@ class ValidatingArrayLoader implements LoaderInterface } } if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) { - $this->warnings[] = 'authors.'.$key.'.homepage : invalid value, must be a valid http/https URL'; + $this->warnings[] = 'authors.'.$key.'.homepage : invalid value, must be an http/https URL'; unset($this->config['authors'][$key]['homepage']); } if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) { @@ -120,16 +120,14 @@ class ValidatingArrayLoader implements LoaderInterface unset($this->config['support']['email']); } - if (isset($this->config['support']['irc']) - && (!filter_var($this->config['support']['irc'], FILTER_VALIDATE_URL) || !preg_match('{^irc://}iu', $this->config['support']['irc'])) - ) { - $this->warnings[] = 'support.irc : invalid value, must be '; + if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) { + $this->warnings[] = 'support.irc : invalid value, must be a irc:/// URL'; unset($this->config['support']['irc']); } foreach (array('issues', 'forum', 'wiki', 'source') as $key) { if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) { - $this->warnings[] = 'support.'.$key.' : invalid value, must be a valid http/https URL'; + $this->warnings[] = 'support.'.$key.' : invalid value, must be an http/https URL'; unset($this->config['support'][$key]); } } @@ -318,7 +316,7 @@ class ValidatingArrayLoader implements LoaderInterface } if (!$this->filterUrl($this->config[$property])) { - $this->warnings[] = $property.' : invalid value, must be a valid http/https URL'; + $this->warnings[] = $property.' : invalid value, must be an http/https URL'; unset($this->config[$property]); return false; @@ -327,8 +325,21 @@ class ValidatingArrayLoader implements LoaderInterface return true; } - private function filterUrl($value) + private function filterUrl($value, array $schemes = array('http', 'https')) { - return filter_var($value, FILTER_VALIDATE_URL) && preg_match('{^https?://}iu', $value); + if ($value === '') { + return true; + } + + $bits = parse_url($value); + if (empty($bits['scheme']) || empty($bits['host'])) { + return false; + } + + if (!in_array($bits['scheme'], $schemes, true)) { + return false; + } + + return true; } } diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 50e1e8c86..85f438db8 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -58,7 +58,8 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6); } - if (function_exists('filter_var') && version_compare(PHP_VERSION, '5.3.3', '>=') && !filter_var($repoConfig['url'], FILTER_VALIDATE_URL)) { + $urlBits = parse_url($repoConfig['url']); + if (empty($urlBits['scheme']) || empty($urlBits['host'])) { throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']); } diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 4fcd3233b..684a64df6 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -49,7 +49,8 @@ class PearRepository extends ArrayRepository $repoConfig['url'] = 'http://'.$repoConfig['url']; } - if (function_exists('filter_var') && version_compare(PHP_VERSION, '5.3.3', '>=') && !filter_var($repoConfig['url'], FILTER_VALIDATE_URL)) { + $urlBits = parse_url($repoConfig['url']); + if (empty($urlBits['scheme']) || empty($urlBits['host'])) { throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']); } diff --git a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php index 1fab51f0c..3433d927c 100644 --- a/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/ValidatingArrayLoaderTest.php @@ -60,7 +60,7 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase ), array( 'name' => 'Bob', - 'homepage' => 'http://example.com', + 'homepage' => '', ), ), 'support' => array( @@ -243,7 +243,7 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase 'homepage' => 'foo:bar', ), array( - 'homepage : invalid value, must be a valid http/https URL' + 'homepage : invalid value, must be an http/https URL' ) ), array( @@ -257,10 +257,10 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase ), ), array( - 'support.source : invalid value, must be a valid http/https URL', - 'support.forum : invalid value, must be a valid http/https URL', - 'support.issues : invalid value, must be a valid http/https URL', - 'support.wiki : invalid value, must be a valid http/https URL', + 'support.source : invalid value, must be an http/https URL', + 'support.forum : invalid value, must be an http/https URL', + 'support.issues : invalid value, must be an http/https URL', + 'support.wiki : invalid value, must be an http/https URL', ) ), ); diff --git a/tests/Composer/Test/Repository/ComposerRepositoryTest.php b/tests/Composer/Test/Repository/ComposerRepositoryTest.php index c74276438..9a2d340af 100644 --- a/tests/Composer/Test/Repository/ComposerRepositoryTest.php +++ b/tests/Composer/Test/Repository/ComposerRepositoryTest.php @@ -25,7 +25,7 @@ class ComposerRepositoryTest extends TestCase public function testLoadData(array $expected, array $repoPackages) { $repoConfig = array( - 'url' => 'file://', + 'url' => 'http://example.org', ); $repository = $this->getMock(