diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 6645863bfd7..0a95132681a 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.50 under development ------------------------ +- Bug #17191: Fixed `BaseUrl::isRelative($url)` method in `yii\helpers\BaseUrl` (ggh2e3) - Bug #18469: Fixed `Link::serialize(array $links)` method in `yii\web\Link` (ggh2e3) - Bug #20040: Fix type `boolean` in `MSSQL` (terabytesoftw) - Bug #20005: Fix `yii\console\controllers\ServeController` to specify the router script (terabytesoftw) diff --git a/framework/helpers/BaseUrl.php b/framework/helpers/BaseUrl.php index a671123c7cd..dcbab192730 100644 --- a/framework/helpers/BaseUrl.php +++ b/framework/helpers/BaseUrl.php @@ -378,7 +378,8 @@ public static function home($scheme = false) */ public static function isRelative($url) { - return strncmp($url, '//', 2) && strpos($url, '://') === false; + $urlComponents = parse_url($url, PHP_URL_SCHEME); + return strncmp($url, '//', 2) && empty($urlComponents); } /** diff --git a/tests/framework/helpers/BaseUrlTest.php b/tests/framework/helpers/BaseUrlTest.php new file mode 100644 index 00000000000..9bcd39ef981 --- /dev/null +++ b/tests/framework/helpers/BaseUrlTest.php @@ -0,0 +1,116 @@ +assertTrue(BaseUrl::isRelative($url)); + } + + /** @dataProvider relativeFalseUrlProvider */ + public function testIsRelativeWillReturnFalse($url) + { + $this->assertFalse(BaseUrl::isRelative($url)); + } + + /** @dataProvider ensureSchemeUrlProvider */ + public function testEnsureScheme($url, $scheme, $expected) + { + $this->assertEquals($expected, BaseUrl::ensureScheme($url, $scheme)); + } + + public function ensureSchemeUrlProvider() + { + return [ + 'relative url and https scheme will return input url' => [ + 'url' => 'acme.com?name=bugs.bunny', + 'scheme' => 'https', + 'expected result' => 'acme.com?name=bugs.bunny', + ], + 'relative url and another url as parameter will return input url' => [ + 'url' => 'acme.com/test?tnt-link=https://tnt.com/', + 'scheme' => 'https', + 'expected' => 'acme.com/test?tnt-link=https://tnt.com/', + ], + 'url with scheme not a string will return input url' => [ + 'url' => 'acme.com?name=bugs.bunny', + 'scheme' => 123, + 'expected' => 'acme.com?name=bugs.bunny', + ], + 'protocol relative url and https scheme will be processed' => [ + 'url' => '//acme.com?characters/list', + 'scheme' => 'https', + 'expected' => 'https://acme.com?characters/list', + ], + 'protocol relative url and empty scheme will be returned' => [ + 'url' => '//acme.com?characters/list', + 'scheme' => '', + 'expected' => '//acme.com?characters/list', + ], + 'absolute url and empty scheme will create protocol relative url' => [ + 'url' => 'https://acme.com?characters/list', + 'scheme' => '', + 'expected' => '//acme.com?characters/list', + ], + 'absolute url and different scheme will be processed' => [ + 'url' => 'http://acme.com/test?tnt-link=https://tnt.com/', + 'scheme' => 'https', + 'expected' => 'https://acme.com/test?tnt-link=https://tnt.com/', + ] + ]; + } + + public function relativeTrueUrlProvider() + { + return [ + 'url url without protocol' => [ + 'url' => 'acme.com/tnt-room=123', + ], + 'url without protocol and another url in a parameter value' => [ + 'url' => 'acme.com?tnt-room-link=https://tnt.com', + ], + 'path only' => [ + 'url' => '/path', + ], + 'path with param' => [ + 'url' => '/path=/home/user', + ], + ]; + } + + public function relativeFalseUrlProvider() + { + return [ + 'url with https protocol' => [ + 'url' => 'https://acme.com', + ], + 'url with https protocol and ending slash' => [ + 'url' => 'https://acme.com/', + ], + 'url with https protocol and another url as param value' => [ + 'url' => 'https://acme.com?tnt-link=https://tnt.com', + ], + 'url starting with two slashes' => [ + 'url' => '//example.com', + ], + 'url with ftp protocol' => [ + 'url' => 'ftp://ftp.acme.com/tnt-suppliers.txt', + ], + 'url with http protocol' => [ + 'url' => 'http://no-protection.acme.com', + ], + 'file url' => [ + 'url' => 'file:///home/User/2ndFile.html', + ] + ]; + } +}