diff --git a/control/Director.php b/control/Director.php index 1c9373fef..084c9bbc5 100644 --- a/control/Director.php +++ b/control/Director.php @@ -409,7 +409,12 @@ class Director implements TemplateGlobalProvider { /** * Turns the given URL into an absolute URL. - * @todo Document how relativeToSiteBase works + * By default non-site root relative urls will be evaluated relative to the current request. + * + * @param string $url URL To transform to absolute + * @param bool $relativeToSiteBase Flag indicating if non-site root relative urls should be + * evaluated relative to the site BaseURL instead of the current url. + * @return string The fully qualified URL */ public static function absoluteURL($url, $relativeToSiteBase = false) { if(!isset($_SERVER['REQUEST_URI'])) return false; diff --git a/control/HTTPResponse.php b/control/HTTPResponse.php index f1556a1c9..b8e1d18ec 100644 --- a/control/HTTPResponse.php +++ b/control/HTTPResponse.php @@ -234,7 +234,7 @@ class SS_HTTPResponse { } if(in_array($this->statusCode, self::$redirect_codes) && headers_sent($file, $line)) { - $url = (string)$this->headers['Location']; + $url = Director::absoluteURL($this->headers['Location'], true); $urlATT = Convert::raw2htmlatt($url); $urlJS = Convert::raw2js($url); echo diff --git a/docs/en/changelogs/3.0.10.md b/docs/en/changelogs/3.0.10.md new file mode 100644 index 000000000..8e06089aa --- /dev/null +++ b/docs/en/changelogs/3.0.10.md @@ -0,0 +1,26 @@ +# 3.0.10 + +## Upgrading + + * If relying on partial caching of content between logged in users, be aware that the cache is now automatically + segmented based on both the current member ID, and the versioned reading mode. If this is not an appropriate + method (such as if the same content is served to logged in users within partial caching) then it is necessary + to adjust the config value of `SSViewer.global_key` to something more or less sensitive. + +## Security + + * [BUG Fix issue with versioned dataobjects being cached between stages](https://github.com/silverstripe/silverstripe-framework/commit/4415a75d9304a3930b9c28763fc092299640c685) - See [announcement SS-2014-007](http://www.silverstripe.org/ss-2014-007-confidentiality-breach-can-occur-between-draft-and-live-modes/) + * [BUG Fix encoding of JS redirection script](https://github.com/silverstripe/silverstripe-framework/commit/f8e3bbe3ae3f29f22d85abb73cea033659511168) - See [announcement SS-2014-006](http://www.silverstripe.org/ss-2014-006-xss-in-returnurl-redirection/) + * [Amends solution to SS-2014-006](https://github.com/silverstripe/silverstripe-framework/commit/5b0a96979484fad12e11ce69aef98feda57b321f) + * [FIX Prevent SQLi when no URL filters are applied](https://github.com/silverstripe/silverstripe-cms/commit/114df8a3a5e4800ef7586c5d9c8d79798fd2a11d) - See [announcement SS-2014-004](http://www.silverstripe.org/ss-2014-004-sql-injection-in-sitetree-with-custom-urlsegmentfilter-rules/) + * [FIX Do now allow arbitary class creation in CMS](https://github.com/silverstripe/silverstripe-cms/commit/bf9b22fd4331a6f78cec12a75262f570b025ec2d) - See [announcement SS-2014-005](http://www.silverstripe.org/ss-2014-005-arbitrary-class-creation-in-cms-backend/) + +## General + + * [Rewrote usages of error suppression operator](https://github.com/silverstripe/silverstripe-framework/commit/6d5d3d8cb7e69e0b37471b1e34077211b0f631fe) + +## Changelog + + * [framework](https://github.com/silverstripe/silverstripe-framework/releases/tag/3.0.10) + * [cms](https://github.com/silverstripe/silverstripe-cms/releases/tag/3.0.10) + * [installer](https://github.com/silverstripe/silverstripe-installer/releases/tag/3.0.10) diff --git a/tests/control/DirectorTest.php b/tests/control/DirectorTest.php index adbaeae6e..7f8d26a3e 100644 --- a/tests/control/DirectorTest.php +++ b/tests/control/DirectorTest.php @@ -41,6 +41,9 @@ class DirectorTest extends SapphireTest { public function tearDown() { // TODO Remove director rule, currently API doesnt allow this + // Remove base URL override (setting to false reverts to default behaviour) + Director::setBaseURL(false); + // Reinstate the original REQUEST_URI after it was modified by some tests $_SERVER['REQUEST_URI'] = self::$originalRequestURI; @@ -72,6 +75,40 @@ class DirectorTest extends SapphireTest { unlink($tempFilePath); } + + public function testAbsoluteURL() { + + $rootURL = Director::protocolAndHost(); + $_SERVER['REQUEST_URI'] = "$rootURL/mysite/sub-page/"; + Director::setBaseURL('/mysite/'); + + // Test already absolute url + $this->assertEquals($rootURL, Director::absoluteURL($rootURL)); + $this->assertEquals($rootURL, Director::absoluteURL($rootURL, true)); + $this->assertEquals('http://www.mytest.com', Director::absoluteURL('http://www.mytest.com')); + $this->assertEquals('http://www.mytest.com', Director::absoluteURL('http://www.mytest.com', true)); + $this->assertEquals("$rootURL/test", Director::absoluteURL("$rootURL/test")); + $this->assertEquals("$rootURL/test", Director::absoluteURL("$rootURL/test", true)); + + // Test relative to base + $this->assertEquals("$rootURL/mysite/test", Director::absoluteURL("test", true)); + $this->assertEquals("$rootURL/mysite/test/url", Director::absoluteURL("test/url", true)); + $this->assertEquals("$rootURL/root", Director::absoluteURL("/root", true)); + $this->assertEquals("$rootURL/root/url", Director::absoluteURL("/root/url", true)); + + // Test relative to requested page + $this->assertEquals("$rootURL/mysite/sub-page/test", Director::absoluteURL("test")); + // Legacy behaviour resolves this to $rootURL/mysite/test/url + //$this->assertEquals("$rootURL/mysite/sub-page/test/url", Director::absoluteURL("test/url")); + $this->assertEquals("$rootURL/root", Director::absoluteURL("/root")); + $this->assertEquals("$rootURL/root/url", Director::absoluteURL("/root/url")); + + // Test that javascript links are not left intact + $this->assertStringStartsNotWith('javascript', Director::absoluteURL('javascript:alert("attack")')); + $this->assertStringStartsNotWith('alert', Director::absoluteURL('javascript:alert("attack")')); + $this->assertStringStartsNotWith('javascript', Director::absoluteURL('alert("attack")')); + $this->assertStringStartsNotWith('alert', Director::absoluteURL('alert("attack")')); + } public function testAlternativeBaseURL() { // relative base URLs - you should end them in a /