From 1325d736a06d62b37fe2b1371044800e7a2cfafa Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Fri, 10 May 2013 22:03:54 +1200 Subject: [PATCH] API: Add Director::is_https() --- control/Director.php | 57 +++++++++++++++++++++++++--------- tests/control/DirectorTest.php | 57 +++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 15 deletions(-) diff --git a/control/Director.php b/control/Director.php index d63ffde35..a3686d279 100644 --- a/control/Director.php +++ b/control/Director.php @@ -418,33 +418,63 @@ class Director implements TemplateGlobalProvider { } /** - * Return the current protocol that the site is running under + * Return the current protocol that the site is running under. * - * @return String + * @return string */ public static function protocol() { - if(isset($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])&&strtolower($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])=='https') { - return "https://"; + return (self::is_https()) ? 'https://' : 'http://'; + } + + /** + * Return whether the site is running as under HTTPS. + * + * @return boolean + */ + public static function is_https() { + if(isset($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])) { + if(strtolower($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) == 'https') { + return true; + } } - return (isset($_SERVER['SSL']) || (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')) - ? 'https://' : 'http://'; + + if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')) { + return true; + } + else if(isset($_SERVER['SSL'])) { + return true; + } + + return false; } /** * Returns the root URL for the site. - * It will be automatically calculated unless it is overridden with {@link setBaseURL()}. + * + * It will be automatically calculated unless it is overridden with + * {@link setBaseURL()}. + * + * @return string */ public static function baseURL() { $alternate = Config::inst()->get('Director', 'alternate_base_url'); + if($alternate) { return $alternate; } else { $base = BASE_URL; - if($base == '/' || $base == '/.' || $base == '\\') $baseURL = '/'; - else $baseURL = $base . '/'; - if(defined('BASE_SCRIPT_URL')) return $baseURL . BASE_SCRIPT_URL; - else return $baseURL; + if($base == '/' || $base == '/.' || $base == '\\') { + $baseURL = '/'; + } else { + $baseURL = $base . '/'; + } + + if(defined('BASE_SCRIPT_URL')) { + return $baseURL . BASE_SCRIPT_URL; + } + + return $baseURL; } } @@ -737,9 +767,7 @@ class Director implements TemplateGlobalProvider { $matched = true; } - if($matched && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off') - && !(isset($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) - && strtolower($_SERVER['HTTP_X_FORWARDED_PROTOCOL']) == 'https')) { + if($matched && !self::is_https()) { // if an domain is specified, redirect to that instead of the current domain if($secureDomain) { @@ -755,6 +783,7 @@ class Director implements TemplateGlobalProvider { return $destURL; } else { if(!headers_sent()) header("Location: $destURL"); + die("

Your browser is not accepting header redirects

" . "

Please click here"); } diff --git a/tests/control/DirectorTest.php b/tests/control/DirectorTest.php index d3d4b5164..213c25e30 100644 --- a/tests/control/DirectorTest.php +++ b/tests/control/DirectorTest.php @@ -9,6 +9,8 @@ class DirectorTest extends SapphireTest { protected static $originalRequestURI; + protected $originalProtocolHeaders = array(); + public function setUp() { parent::setUp(); @@ -24,6 +26,16 @@ class DirectorTest extends SapphireTest { 'Locale' => 'en_NZ' ) )); + + $headers = array( + 'HTTP_X_FORWARDED_PROTOCOL', 'HTTPS', 'SSL' + ); + + foreach($headers as $header) { + if(isset($_SERVER[$header])) { + $this->originalProtocolHeaders[$header] = $_SERVER[$header]; + } + } } public function tearDown() { @@ -31,7 +43,13 @@ class DirectorTest extends SapphireTest { // Reinstate the original REQUEST_URI after it was modified by some tests $_SERVER['REQUEST_URI'] = self::$originalRequestURI; - + + if($this->originalProtocolHeaders) { + foreach($this->originalProtocolHeaders as $header => $value) { + $_SERVER[$header] = $value; + } + } + parent::tearDown(); } @@ -285,6 +303,43 @@ class DirectorTest extends SapphireTest { $this->assertEquals(404, Director::test('no-route')->getStatusCode()); } + public function testIsHttps() { + // nothing available + $headers = array( + 'HTTP_X_FORWARDED_PROTOCOL', 'HTTPS', 'SSL' + ); + + foreach($headers as $header) { + if(isset($_SERVER[$header])) { + unset($_SERVER['HTTP_X_FORWARDED_PROTOCOL']); + } + } + + $this->assertFalse(Director::is_https()); + + $_SERVER['HTTP_X_FORWARDED_PROTOCOL'] = 'https'; + $this->assertTrue(Director::is_https()); + + $_SERVER['HTTP_X_FORWARDED_PROTOCOL'] = 'http'; + $this->assertFalse(Director::is_https()); + + $_SERVER['HTTP_X_FORWARDED_PROTOCOL'] = 'ftp'; + $this->assertFalse(Director::is_https()); + + // https via HTTPS + $_SERVER['HTTPS'] = 'true'; + $this->assertTrue(Director::is_https()); + + $_SERVER['HTTPS'] = '1'; + $this->assertTrue(Director::is_https()); + + $_SERVER['HTTPS'] = 'off'; + $this->assertFalse(Director::is_https()); + + // https via SSL + $_SERVER['SSL'] = ''; + $this->assertTrue(Director::is_https()); + } } class DirectorTestRequest_Controller extends Controller implements TestOnly {