From 85e7d70f3ed2799564624df730141faf837d8182 Mon Sep 17 00:00:00 2001 From: David McReynolds Date: Fri, 20 Dec 2013 16:38:33 -0800 Subject: [PATCH 01/25] Added non_ssl configuration to Fuel_redirects to force folks from https to http --- fuel/application/config/redirects.php | 3 + fuel/modules/fuel/hooks/Fuel_hooks.php | 1 + .../modules/fuel/libraries/Fuel_redirects.php | 154 +++++++++++++++++- .../fuel/views/_docs/general/redirects.php | 17 +- 4 files changed, 162 insertions(+), 13 deletions(-) diff --git a/fuel/application/config/redirects.php b/fuel/application/config/redirects.php index dbdac5cfc..18e9f2d7e 100644 --- a/fuel/application/config/redirects.php +++ b/fuel/application/config/redirects.php @@ -29,6 +29,9 @@ // The paths to force SSL with the key being the environment it belongs to $config['ssl'] = array('development' => array()); +// The paths to force NON SSL with the key being the environment it belongs to +$config['non_ssl'] = array('development' => array()); + // The host name to enforce (e.g. mysite.com vs www.mysite.com) with the key being the environment it belongs to $config['host'] = array('production' => ''); diff --git a/fuel/modules/fuel/hooks/Fuel_hooks.php b/fuel/modules/fuel/hooks/Fuel_hooks.php index e7a8852f3..dba4924e6 100644 --- a/fuel/modules/fuel/hooks/Fuel_hooks.php +++ b/fuel/modules/fuel/hooks/Fuel_hooks.php @@ -59,6 +59,7 @@ public function redirects() $CI =& get_instance(); $CI->fuel->redirects->enforce_host(); $CI->fuel->redirects->ssl(); + $CI->fuel->redirects->non_ssl(); if (!USE_FUEL_ROUTES) { diff --git a/fuel/modules/fuel/libraries/Fuel_redirects.php b/fuel/modules/fuel/libraries/Fuel_redirects.php index 24294f423..55a3aa4d3 100644 --- a/fuel/modules/fuel/libraries/Fuel_redirects.php +++ b/fuel/modules/fuel/libraries/Fuel_redirects.php @@ -34,7 +34,8 @@ class Fuel_redirects extends Fuel_base_library { public $http_code = 301; // The HTTP response code to return... 301 = permanent redirect public $case_sensitive = TRUE; // Determines whether the pattern matching for the redirects is case sensitive - public $ssl = array(); // The paths to force SSL with + public $ssl = array(); // The paths to force SSL + public $non_ssl = array(); // The paths to force NON SSL public $aggressive_redirects = array(); // The pages to redirect to regardless if it's found by FUEL. WARNING: Run on every request. public $passive_redirects = array(); // The pages to redirect to only AFTER no page is found by FUEL public $max_redirects = 2; // Sets the number of times the page can redirect before giving nup and displaying a 404 @@ -142,18 +143,82 @@ public function remove($uri, $passive = TRUE) * @return array */ public function add_ssl($uri, $redirect = '') + { + $this->_add_ssl_type($uri, $environment, 'ssl'); + } + + // -------------------------------------------------------------------- + + /** + * Remove from the ssl redirect list + * + * @access public + * @param string The URI location of the page to remove + * @param string The name of the environment key that the redirect applies to (optional) + * @return array + */ + public function remove_ssl($uri, $environment = 'production') + { + $this->_add_ssl_type($uri, $environment, 'non_ssl'); + } + + // -------------------------------------------------------------------- + + /** + * Adds to the NON ssl redirect list + * + * @access public + * @param string The URI location of the page to remove + * @param string The page to redirect to or the name of the environment if the first parameter is an array(optional) + * @param string The name of the environment key that the redirect applies to (optional) + * @return array + */ + public function add_non_ssl($uri, $redirect = '') + { + $this->_add_ssl_type($uri, $environment, 'non_ssl'); + + } + + // -------------------------------------------------------------------- + + /** + * Remove from the NON ssl redirect list + * + * @access public + * @param string The URI location of the page to remove + * @param string The name of the environment key that the redirect applies to (optional) + * @return array + */ + public function remove_non_ssl($uri, $environment = 'production') + { + $this->_remove_ssl_type($uri, $environment, 'non_ssl'); + } + + // -------------------------------------------------------------------- + + /** + * Adds to the ssl redirect list + * + * @access protected + * @param string The URI location of the page to remove + * @param string The page to redirect to or the name of the environment if the first parameter is an array(optional) + * @param string The name of the environment key that the redirect applies to (optional) + * @param string The type of SSL either redirect... either to https or http (optional) + * @return array + */ + protected function _add_ssl_type($uri, $redirect = '', $type = 'ssl') { if (is_array($uri)) { - if (!isset($this->ssl[$redirect])) + if (!isset($this->$type[$redirect])) { - $this->ssl[$redirect] = array(); + $this->$type[$redirect] = array(); } - $this->ssl[$redirect] = array_merge($this->ssl[$redirect], $uri); + $this->$type[$redirect] = array_merge($this->$type[$redirect], $uri); } else if (is_string($uri)) { - $this->ssl[$environment][$uri] = $redirect; + $this->$type[$environment][$uri] = $redirect; } } @@ -162,16 +227,17 @@ public function add_ssl($uri, $redirect = '') /** * Remove from the ssl redirect list * - * @access public + * @access protected * @param string The URI location of the page to remove * @param string The name of the environment key that the redirect applies to (optional) + * @param string The type of SSL either redirect... either to https or http (optional) * @return array */ - public function remove_ssl($uri, $environment = 'production') + protected function _remove_ssl_type($uri, $environment = 'production', $type = 'ssl') { - if (isset($this->ssl[$environment][$uri])) + if (isset($this->$type[$environment][$uri])) { - unset($this->ssl[$environment][$uri]); + unset($this->$type[$environment][$uri]); } } @@ -436,6 +502,76 @@ public function ssl() } } + /** + * Loops through the ssl config to find a possible match to redirect to an NON SSL uri + * + * @access public + * @return void + */ + public function non_ssl() + { + $config = $this->config(); + $is_https = is_https(); + + if (!isset($config['non_ssl']) OR !$is_https) + { + return; + } + + $non_ssl = $config['non_ssl']; + $ssl = $config['ssl']; + + if ( ! empty($non_ssl[ENVIRONMENT])) + { + // get the diff since we don't want to include any SSL which would put us in an infinite loop + $non_ssl_redirects = $non_ssl[ENVIRONMENT]; + if (!empty($ssl[ENVIRONMENT])) + { + $non_ssl_redirects = array_diff($non_ssl[ENVIRONMENT], $ssl[ENVIRONMENT]); + } + + $uri = $this->_get_uri(); + + // Is there a literal match? If so we're done + if (isset($non_ssl_redirects[$uri]) AND $is_https) + { + redirect( site_url($uri, FALSE) ); + } + + // check that it's not in the ssl already and if it is, just return (to prevent infinite loops) + if ( ! empty($ssl[ENVIRONMENT])) + { + foreach($ssl[ENVIRONMENT] as $s) + { + $s = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $s)); + + // Does the RegEx match? + $pattern = '#^'.$s.'$#'; + + // if there is already an SSL rule, then that takes precedence + if (preg_match($pattern, $uri)) + { + return; + } + } + } + + foreach ($non_ssl_redirects as $val) + { + // Convert wild-cards to RegEx + $val = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $val)); + + // Does the RegEx match? + $pattern = '#^'.$val.'$#'; + + if (preg_match($pattern, $uri) AND $is_https) + { + redirect( site_url($uri, FALSE), 'location', 301); + } + } + } + } + // -------------------------------------------------------------------- /** diff --git a/fuel/modules/fuel/views/_docs/general/redirects.php b/fuel/modules/fuel/views/_docs/general/redirects.php index 7bf4e5cc3..161aadc36 100644 --- a/fuel/modules/fuel/views/_docs/general/redirects.php +++ b/fuel/modules/fuel/views/_docs/general/redirects.php @@ -40,7 +40,7 @@

The max_redirects is used to prevent scenarios where it can cause an infinite redirect loop.

-

SSL

+

SSL

The ssl configuration provides an easy way to force SSL encryption (https) for your page URLs. The following example would restrict any url under "store" to use SSL encription when in the "production" environment:

@@ -49,14 +49,23 @@
 )); 
 
-

Enforce Host

+

Non SSL

+

The non_ssl configuration provides an easy way to force pages that are in SSL to not be encrypted (opposite of SSL). If there is an ssl configuration +that conflicts with a non_ssl, then the ssl will take precedence and ignore the non_ssl to prevent infinte redirects. +The following example would redirect any url under "about" to NOT use SSL encription when in the "production" environment:

+
+$config['non_ssl'] = array('production' => array(
+	'^about|about/:any'
+)); 
+
+

Enforce Host

The host configuration provides an alternative to .htaccess for redirecting your page if the current $_SERVER['HTTP_HOST'] PHP variable doesn't match what is specified as the "host" value in the redirect configuration. The following example would redirect any requests to "mysite.com" if the HTTP_HOST value doesn't match in the "production" environment (e.g. www.mysite.com):

 $config['host'] = array('production' => 'mysite.com'); 
 
-

Testing Redirects

+

Testing Redirects

If you are needing to check the redirects, you can utilize Fuel_redirects::test method and create a simple view file at fuel/applications/views/redirects_test.php with the following:

 <?php 
@@ -67,7 +76,7 @@
 

Regular expressions and shorthand :any will not be properly translated and will return errors.

-

Redirect Hooks

+

Redirect Hooks