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/docs/en/changelogs/rc/3.0.10-rc1.md b/docs/en/changelogs/rc/3.0.10-rc1.md index 6f770cb75..9ee024a96 100644 --- a/docs/en/changelogs/rc/3.0.10-rc1.md +++ b/docs/en/changelogs/rc/3.0.10-rc1.md @@ -1,23 +1,25 @@ # 3.0.10-rc1 -## Overview - - * General: [Rewrote usages of error suppression operator](https://github.com/silverstripe/silverstripe-framework/commit/6d5d3d8cb7e69e0b37471b1e34077211b0f631fe) - * Security: [BUG Fix issue with versioned dataobjects being cached between stages](https://github.com/silverstripe/silverstripe-framework/commit/4415a75d9304a3930b9c28763fc092299640c685) - * Security: [BUG Fix encoding of JS redirection script](https://github.com/silverstripe/silverstripe-framework/commit/f8e3bbe3ae3f29f22d85abb73cea033659511168) - * Security: [FIX Prevent SQLi when no URL filters are applied](https://github.com/silverstripe/silverstripe-cms/commit/114df8a3a5e4800ef7586c5d9c8d79798fd2a11d) - * Security: [FIX Do now allow arbitary class creation in CMS](https://github.com/silverstripe/silverstripe-cms/commit/bf9b22fd4331a6f78cec12a75262f570b025ec2d) - ## 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. + 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/) + * [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-rc1) - * [cms](https://github.com/silverstripe/silverstripe-framework/releases/tag/3.0.10-rc1) - * [installer](https://github.com/silverstripe/silverstripe-framework/releases/tag/3.0.10-rc1) + * [cms](https://github.com/silverstripe/silverstripe-cms/releases/tag/3.0.10-rc1) + * [installer](https://github.com/silverstripe/silverstripe-installer/releases/tag/3.0.10-rc1) 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 /