diff --git a/core/includes/common.inc b/core/includes/common.inc index 0aeb3fa..585bd20 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1090,7 +1090,7 @@ function valid_url($url, $absolute = FALSE) { if ($absolute) { return (bool)preg_match(" /^ # Start at the beginning of the text - (?:ftp|https?|feed):\/\/ # Look for ftp, http, https or feed schemes + (?:ftp:|https?:|feed:)?\/\/ # Look for ftp, http, https, feed or scheme relative schemes (?: # Userinfo (optional) which is typically (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)* # a username or a username and password (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@ # combination diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php index b4cd7e7..d5b54e1 100644 --- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php @@ -299,6 +299,20 @@ function testMenuQueryAndFragment() { } /** + * Add a menu link with a scheme-relative url. + */ + function testMenuSchemeRelative() { + $this->drupalLogin($this->big_user); + + // Make a path with query and fragment on. + $path = '//drupal.org'; + $item = $this->addMenuLink(0, $path); + + $this->drupalGet('admin/structure/menu/item/' . $item['mlid'] . '/edit'); + $this->assertFieldByName('link_path', $path, 'Path is found with scheme-relative URL.'); + } + + /** * Add a menu link using the menu module UI. * * @param integer $plid Parent menu link id. diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php index d178709..d60c2f1 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php @@ -217,4 +217,36 @@ function testExternalUrls() { $result = url($url, array('query' => $query)); $this->assertEqual($url . '&' . http_build_query($query, '', '&'), $result, 'External URL query string can be extended with a custom query string in $options.'); } + + function testSchemeRelativeUrls() { + $test_url = '//drupal.org'; + + // Verify scheme-relative URL can contain a fragment. + $url = $test_url . '#drupal'; + $result = url($url); + $this->assertEqual($url, $result, 'Scheme-relative URL with fragment works without a fragment in $options.'); + + // Verify fragment can be overidden in an external URL. + $url = $test_url . '#drupal'; + $fragment = $this->randomName(10); + $result = url($url, array('fragment' => $fragment)); + $this->assertEqual($test_url . '#' . $fragment, $result, 'Scheme-relative URL fragment is overidden with a custom fragment in $options.'); + + // Verify external URL can contain a query string. + $url = $test_url . '?drupal=awesome'; + $result = url($url); + $this->assertEqual($url, $result, 'Scheme-relative URL with query string works without a query string in $options.'); + + // Verify external URL can be extended with a query string. + $url = $test_url; + $query = array($this->randomName(5) => $this->randomName(5)); + $result = url($url, array('query' => $query)); + $this->assertEqual($url . '?' . http_build_query($query, '', '&'), $result, 'Scheme-relative URL can be extended with a query string in $options.'); + + // Verify query string can be extended in an external URL. + $url = $test_url . '?drupal=awesome'; + $query = array($this->randomName(5) => $this->randomName(5)); + $result = url($url, array('query' => $query)); + $this->assertEqual($url . '&' . http_build_query($query, '', '&'), $result, 'Scheme-relative URL query string can be extended with a custom query string in $options.'); + } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/ValidUrlUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/ValidUrlUnitTest.php index bc9b6a9..32814f4 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/ValidUrlUnitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/ValidUrlUnitTest.php @@ -25,7 +25,7 @@ public static function getInfo() { * Test valid absolute URLs. */ function testValidAbsolute() { - $url_schemes = array('http', 'https', 'ftp'); + $url_schemes = array('http://', 'https://', 'ftp://', '//'); $valid_absolute_urls = array( 'example.com', 'www.example.com', @@ -49,7 +49,7 @@ function testValidAbsolute() { foreach ($url_schemes as $scheme) { foreach ($valid_absolute_urls as $url) { - $test_url = $scheme . '://' . $url; + $test_url = $scheme . $url; $valid_url = valid_url($test_url, TRUE); $this->assertTrue($valid_url, format_string('@url is a valid URL.', array('@url' => $test_url))); } @@ -60,7 +60,7 @@ function testValidAbsolute() { * Test invalid absolute URLs. */ function testInvalidAbsolute() { - $url_schemes = array('http', 'https', 'ftp'); + $url_schemes = array('http://', 'https://', 'ftp://', '//'); $invalid_ablosule_urls = array( '', 'ex!ample.com', @@ -69,7 +69,7 @@ function testInvalidAbsolute() { foreach ($url_schemes as $scheme) { foreach ($invalid_ablosule_urls as $url) { - $test_url = $scheme . '://' . $url; + $test_url = $scheme . $url; $valid_url = valid_url($test_url, TRUE); $this->assertFalse($valid_url, format_string('@url is NOT a valid URL.', array('@url' => $test_url))); }