From 6eda25a09077c20c1067d0c79f93458bf9342519 Mon Sep 17 00:00:00 2001 From: Sean Harvey Date: Wed, 3 Apr 2013 16:53:58 +1300 Subject: [PATCH] NEW Allow specifying the secure domain to Director::forceSSL() --- control/Director.php | 22 +++++++++++++++++++--- tests/control/DirectorTest.php | 7 +++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/control/Director.php b/control/Director.php index f59b6cfd4..c7337de93 100644 --- a/control/Director.php +++ b/control/Director.php @@ -693,15 +693,23 @@ class Director implements TemplateGlobalProvider { * if(Director::isLive()) Director::forceSSL(array('/^admin/', '/^Security/')); * * + * If you want certain parts of your site protected under a different domain, you can specify + * the domain as an argument: + * + * if(Director::isLive()) Director::forceSSL(array('/^admin/', '/^Security/'), 'secure.mysite.com'); + * + * * Note that the session data will be lost when moving from HTTP to HTTPS. * It is your responsibility to ensure that this won't cause usability problems. * * CAUTION: This does not respect the site environment mode. You should check this * as per the above examples using Director::isLive() or Director::isTest() for example. * + * @param array $patterns Array of regex patterns to match URLs that should be HTTPS + * @param string $secureDomain Secure domain to redirect to. Defaults to the current domain * @return boolean|string String of URL when unit tests running, boolean FALSE if patterns don't match request URI */ - public static function forceSSL($patterns = null) { + public static function forceSSL($patterns = null, $secureDomain = null) { if(!isset($_SERVER['REQUEST_URI'])) return false; $matched = false; @@ -710,8 +718,9 @@ class Director implements TemplateGlobalProvider { // Calling from the command-line? if(!isset($_SERVER['REQUEST_URI'])) return; - // protect portions of the site based on the pattern $relativeURL = self::makeRelative(Director::absoluteURL($_SERVER['REQUEST_URI'])); + + // protect portions of the site based on the pattern foreach($patterns as $pattern) { if(preg_match($pattern, $relativeURL)) { $matched = true; @@ -727,7 +736,14 @@ class Director implements TemplateGlobalProvider { && !(isset($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) == 'https')) { - $destURL = str_replace('http:', 'https:', Director::absoluteURL($_SERVER['REQUEST_URI'])); + // if an domain is specified, redirect to that instead of the current domain + if($secureDomain) { + $url = 'https://' . $secureDomain . $_SERVER['REQUEST_URI']; + } else { + $url = $_SERVER['REQUEST_URI']; + } + + $destURL = str_replace('http:', 'https:', Director::absoluteURL($url)); // This coupling to SapphireTest is necessary to test the destination URL and to not interfere with tests if(class_exists('SapphireTest', false) && SapphireTest::is_running_test()) { diff --git a/tests/control/DirectorTest.php b/tests/control/DirectorTest.php index efec16a96..4d1ccae17 100644 --- a/tests/control/DirectorTest.php +++ b/tests/control/DirectorTest.php @@ -242,6 +242,13 @@ class DirectorTest extends SapphireTest { $this->assertFalse($output); } + public function testForceSSLAlternateDomain() { + Director::setBaseURL('/'); + $_SERVER['REQUEST_URI'] = Director::baseURL() . 'admin'; + $output = Director::forceSSL(array('/^admin/'), 'secure.mysite.com'); + $this->assertEquals($output, 'https://secure.mysite.com/admin'); + } + /** * @covers Director::extract_request_headers() */