Fix #3593

Revert "fixes" for #167, #388, #705 (also #1326) as it turns out
URL-decoding isn't compliant with the CGI/1.1 specification.

RFC 3875: http://www.faqs.org/rfcs/rfc3875.html
diff --git a/application/config/config.php b/application/config/config.php
index 306fc2c..7d5c24c 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -37,17 +37,16 @@
 |--------------------------------------------------------------------------
 |
 | This item determines which server global should be used to retrieve the
-| URI string.  The default setting of 'AUTO' works for most servers.
+| URI string.  The default setting of 'REQUEST_URI' works for most servers.
 | If your links do not seem to work, try one of the other delicious flavors:
 |
-| 'AUTO'		Default - auto detects
-| 'CLI' or 'argv'	Uses $_SERVER['argv'] (for php-cli only)
-| 'PATH_INFO'		Uses $_SERVER['PATH_INFO']
-| 'REQUEST_URI'		Uses $_SERVER['REQUEST_URI']
-| 'QUERY_STRING'	Uses $_SERVER['QUERY_STRING']
+| 'REQUEST_URI'    Uses $_SERVER['REQUEST_URI']
+| 'QUERY_STRING'   Uses $_SERVER['QUERY_STRING']
+| 'PATH_INFO'      Uses $_SERVER['PATH_INFO']
 |
+| WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!
 */
-$config['uri_protocol']	= 'AUTO';
+$config['uri_protocol']	= 'REQUEST_URI';
 
 /*
 |--------------------------------------------------------------------------
diff --git a/system/core/URI.php b/system/core/URI.php
index 9bc34ac..e967494 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -107,37 +107,34 @@
 			$this->_permitted_uri_chars = $this->config->item('permitted_uri_chars');
 
 			// If it's a CLI request, ignore the configuration
-			if (is_cli() OR ($protocol = strtoupper($this->config->item('uri_protocol'))) === 'CLI')
+			if (is_cli())
 			{
-				$this->_set_uri_string($this->_parse_argv());
-			}
-			elseif ($protocol === 'AUTO')
-			{
-				// Is there a PATH_INFO variable? This should be the easiest solution.
-				if (isset($_SERVER['PATH_INFO']))
-				{
-					$this->_set_uri_string($_SERVER['PATH_INFO']);
-				}
-				// No PATH_INFO? Let's try REQUST_URI or QUERY_STRING then
-				elseif (($uri = $this->_parse_request_uri()) !== '' OR ($uri = $this->_parse_query_string()) !== '')
-				{
-					$this->_set_uri_string($uri);
-				}
-				// As a last ditch effor, let's try using the $_GET array
-				elseif (is_array($_GET) && count($_GET) === 1 && trim(key($_GET), '/') !== '')
-				{
-					$this->_set_uri_string(key($_GET));
-				}
-			}
-			elseif (method_exists($this, ($method = '_parse_'.strtolower($protocol))))
-			{
-				$this->_set_uri_string($this->$method());
+				$uri = $this->_parse_argv();
 			}
 			else
 			{
-				$uri = isset($_SERVER[$protocol]) ? $_SERVER[$protocol] : @getenv($protocol);
-				$this->_set_uri_string($uri);
+				$protocol = $this->config->item('uri_protocol');
+				empty($protocol) && $protocol = 'REQUEST_URI';
+
+				switch ($protocol)
+				{
+					case 'AUTO': // For BC purposes only
+					case 'REQUEST_URI':
+						$uri = $this->_parse_request_uri();
+						break;
+					case 'QUERY_STRING':
+						$uri = $this->_parse_query_string();
+						break;
+					case 'PATH_INFO':
+					default:
+						$uri = isset($_SERVER[$protocol])
+							? $_SERVER[$protocol]
+							: $this->_parse_request_uri();
+						break;
+				}
 			}
+
+			$this->_set_uri_string($uri);
 		}
 
 		log_message('info', 'URI Class Initialized');
@@ -206,7 +203,7 @@
 
 		$uri = parse_url($_SERVER['REQUEST_URI']);
 		$query = isset($uri['query']) ? $uri['query'] : '';
-		$uri = isset($uri['path']) ? rawurldecode($uri['path']) : '';
+		$uri = isset($uri['path']) ? $uri['path'] : '';
 
 		if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
 		{
@@ -222,7 +219,7 @@
 		if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0)
 		{
 			$query = explode('?', $query, 2);
-			$uri = rawurldecode($query[0]);
+			$uri = $query[0];
 			$_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : '';
 		}
 		else
@@ -262,7 +259,7 @@
 		{
 			$uri = explode('?', $uri, 2);
 			$_SERVER['QUERY_STRING'] = isset($uri[1]) ? $uri[1] : '';
-			$uri = rawurldecode($uri[0]);
+			$uri = $uri[0];
 		}
 
 		parse_str($_SERVER['QUERY_STRING'], $_GET);
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index aacd2ef..3145e83 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -459,7 +459,7 @@
       -  Renamed internal method ``_detect_uri()`` to ``_parse_request_uri()``.
       -  Changed ``_parse_request_uri()`` to accept absolute URIs for compatibility with HTTP/1.1 as per `RFC2616 <http://www.ietf.org/rfc/rfc2616.txt>`.
       -  Added protected method ``_parse_query_string()`` to URI paths in the the **QUERY_STRING** value, like ``_parse_request_uri()`` does.
-      -  Changed URI string detection logic to try the **PATH_INFO** variable first when auto-detecting.
+      -  Changed URI string detection logic to always default to **REQUEST_URI** unless configured otherwise or under CLI.
       -  Removed methods ``_remove_url_suffix()``, ``_explode_segments()`` and moved their logic into ``_set_uri_string()``.
       -  Removed method ``_fetch_uri_string()`` and moved its logic into the class constructor.
       -  Removed method ``_reindex_segments()``.
@@ -660,7 +660,6 @@
 -  Fixed a bug (#10) - :doc:`URI Library <libraries/uri>` internal method ``_detect_uri()`` failed with paths containing a colon.
 -  Fixed a bug (#1387) - :doc:`Query Builder <database/query_builder>` method ``from()`` didn't escape table aliases.
 -  Fixed a bug (#520) - :doc:`Date Helper <helpers/date_helper>` function :php:func:``nice_date()`` failed when the optional second parameter is not passed.
--  Fixed a bug (#167) - ``$config['permitted_uri_chars']`` didn't affect URL-encoded characters.
 -  Fixed a bug (#318) - :doc:`Profiling Library <general/profiling>` setting *query_toggle_count* was not settable as described in the manual.
 -  Fixed a bug (#938) - :doc:`Config Library <libraries/config>` method ``site_url()`` added a question mark to the URL string when query strings are enabled even if it already existed.
 -  Fixed a bug (#999) - :doc:`Config Library <libraries/config>` method ``site_url()`` always appended ``$config['url_suffix']`` to the end of the URL string, regardless of whether a query string exists in it.
@@ -705,7 +704,6 @@
 -  Fixed a bug (#50) - :doc:`Session Library <libraries/sessions>` unnecessarily stripped slashed from serialized data, making it impossible to read objects in a namespace.
 -  Fixed a bug (#658) - :doc:`Routing <general/routing>` wildcard **:any** didn't work as advertised and matched multiple URI segments instead of all characters within a single segment.
 -  Fixed a bug (#1938) - :doc:`Email Library <libraries/email>` removed multiple spaces inside a pre-formatted plain text message.
--  Fixed a bug (#388, #705) - :doc:`URI Library <libraries/uri>` didn't apply URL-decoding to URI segments that it got from **REQUEST_URI** and/or **QUERY_STRING**.
 -  Fixed a bug (#122) - :doc:`URI Library <libraries/uri>` method ``ruri_string()`` didn't include a directory if one is used.
 -  Fixed a bug - :doc:`Routing Library <general/routing>` didn't properly handle *default_controller* in a subdirectory when a method is also specified.
 -  Fixed a bug (#953) - :doc:`post_controller_constructor hook <general/hooks>` wasn't called with a *404_override*.
diff --git a/user_guide_src/source/installation/troubleshooting.rst b/user_guide_src/source/installation/troubleshooting.rst
index 0dfd408..e874bb0 100644
--- a/user_guide_src/source/installation/troubleshooting.rst
+++ b/user_guide_src/source/installation/troubleshooting.rst
@@ -4,16 +4,15 @@
 
 If you find that no matter what you put in your URL only your default
 page is loading, it might be that your server does not support the
-PATH_INFO variable needed to serve search-engine friendly URLs. As a
+REQUEST_URI variable needed to serve search-engine friendly URLs. As a
 first step, open your application/config/config.php file and look for
 the URI Protocol information. It will recommend that you try a couple
 alternate settings. If it still doesn't work after you've tried this
 you'll need to force CodeIgniter to add a question mark to your URLs. To
-do this open your application/config/config.php file and change this::
+do this open your **application/config/config.php** file and change this::
 
 	$config['index_page'] = "index.php";
 
 To this::
 
 	$config['index_page'] = "index.php?";
-