Merge pull request #589 from simonwelsh/absolute_url

FIX Director::is_absolute_url() now ignores query string
This commit is contained in:
Ingo Schommer 2012-08-16 11:50:29 -07:00
commit 5a2247a440
2 changed files with 24 additions and 16 deletions

View File

@ -561,24 +561,29 @@ class Director implements TemplateGlobalProvider {
* @return boolean * @return boolean
*/ */
public static function is_absolute_url($url) { public static function is_absolute_url($url) {
// Strip off the query and fragment parts of the URL before checking
if(($queryPosition = strpos($url, '?')) !== false) {
$url = substr($url, 0, $queryPosition-1);
}
if(($hashPosition = strpos($url, '#')) !== false) {
$url = substr($url, 0, $hashPosition-1);
}
$colonPosition = strpos($url, ':'); $colonPosition = strpos($url, ':');
return ( $slashPosition = strpos($url, '/');
// Base check for existence of a host on a compliant URL return (
parse_url($url, PHP_URL_HOST) // Base check for existence of a host on a compliant URL
// Check for more than one leading slash without a protocol. parse_url($url, PHP_URL_HOST)
// Check for more than one leading slash without a protocol.
// While not a RFC compliant absolute URL, it is completed to a valid URL by some browsers, // While not a RFC compliant absolute URL, it is completed to a valid URL by some browsers,
// and hence a potential security risk. Single leading slashes are not an issue though. // and hence a potential security risk. Single leading slashes are not an issue though.
|| preg_match('/\s*[\/]{2,}/', $url) || preg_match('/\s*[\/]{2,}/', $url)
|| ( || (
// If a colon is found, check if it's part of a valid scheme definition // If a colon is found, check if it's part of a valid scheme definition
// (meaning its not preceded by a slash, hash or questionmark). // (meaning its not preceded by a slash).
// URLs in query parameters are assumed to be correctly urlencoded based on RFC3986, $colonPosition !== FALSE
// in which case no colon should be present in the parameters. && ($slashPosition === FALSE || $colonPosition < $slashPosition)
$colonPosition !== FALSE )
&& !preg_match('![/?#]!', substr($url, 0, $colonPosition)) );
)
);
} }
/** /**

View File

@ -98,6 +98,8 @@ class DirectorTest extends SapphireTest {
$this->assertFalse(Director::is_absolute_url('test.com/testpage')); $this->assertFalse(Director::is_absolute_url('test.com/testpage'));
$this->assertFalse(Director::is_absolute_url('/relative')); $this->assertFalse(Director::is_absolute_url('/relative'));
$this->assertFalse(Director::is_absolute_url('relative')); $this->assertFalse(Director::is_absolute_url('relative'));
$this->assertFalse(Director::is_absolute_url("/relative/?url=http://foo.com"));
$this->assertFalse(Director::is_absolute_url("/relative/#http://foo.com"));
$this->assertTrue(Director::is_absolute_url("https://test.com/?url=http://foo.com")); $this->assertTrue(Director::is_absolute_url("https://test.com/?url=http://foo.com"));
$this->assertTrue(Director::is_absolute_url("trickparseurl:http://test.com")); $this->assertTrue(Director::is_absolute_url("trickparseurl:http://test.com"));
$this->assertTrue(Director::is_absolute_url('//test.com')); $this->assertTrue(Director::is_absolute_url('//test.com'));
@ -116,7 +118,8 @@ class DirectorTest extends SapphireTest {
$this->assertFalse(Director::is_relative_url('ftp://test.com')); $this->assertFalse(Director::is_relative_url('ftp://test.com'));
$this->assertTrue(Director::is_relative_url('/relative')); $this->assertTrue(Director::is_relative_url('/relative'));
$this->assertTrue(Director::is_relative_url('relative')); $this->assertTrue(Director::is_relative_url('relative'));
// $this->assertTrue(Director::is_relative_url('/relative/?url=http://test.com')); $this->assertTrue(Director::is_relative_url('/relative/?url=http://test.com'));
$this->assertTrue(Director::is_relative_url('/relative/#=http://test.com'));
} }
public function testMakeRelative() { public function testMakeRelative() {