CI_URI::_detect_uri() to accept absolute URIs

(thanks to @sourcejedi, PR #1326)

For HTTP/1.1 compliance, RFC2616 specifies that both relative
and absolute URI formats must be accepted:

- http://localhost/path/ (absolute)
- /path/ (relative)
diff --git a/system/core/URI.php b/system/core/URI.php
index d67a35d..3d942ed 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -185,46 +185,46 @@
 			return '';
 		}
 
-		if (strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']) === 0)
-		{
-			$uri = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']));
-		}
-		elseif (strpos($_SERVER['REQUEST_URI'], dirname($_SERVER['SCRIPT_NAME'])) === 0)
-		{
-			$uri = substr($_SERVER['REQUEST_URI'], strlen(dirname($_SERVER['SCRIPT_NAME'])));
-		}
-		else
-		{
-			$uri = $_SERVER['REQUEST_URI'];
-		}
+		$uri = parse_url($_SERVER['REQUEST_URI']);
+		$query = isset($uri['query']) ? $uri['query'] : '';
+		$uri = isset($uri['path']) ? $uri['path'] : '';
 
+		if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
+		{
+			$uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME']));
+		}
+		elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
+		{
+			$uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
+		}
 		// This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
 		// URI is found, and also fixes the QUERY_STRING server var and $_GET array.
-		if (strpos($uri, '?/') === 0)
-		{
-			$uri = substr($uri, 2);
-		}
 
-		$parts = explode('?', $uri, 2);
-		$uri = $parts[0];
-		if (isset($parts[1]))
+		if ($uri === '' && strncmp($query, '/', 1) === 0)
 		{
-			$_SERVER['QUERY_STRING'] = $parts[1];
-			parse_str($_SERVER['QUERY_STRING'], $_GET);
+			$query = explode('?', $query, 2);
+			$uri = $query[0];
+			$_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : '';
 		}
 		else
 		{
-			$_SERVER['QUERY_STRING'] = '';
+			$_SERVER['QUERY_STRING'] = $query;
+		}
+
+		if ($_SERVER['QUERY_STRING'] === '')
+		{
 			$_GET = array();
 		}
+		else
+		{
+			parse_str($_SERVER['QUERY_STRING'], $_GET);
+		}
 
 		if ($uri === '/' OR $uri === '')
 		{
 			return '/';
 		}
 
-		$uri = parse_url('pseudo://hostname/'.$uri, PHP_URL_PATH);
-
 		// Do some final cleaning of the URI and return it
 		return str_replace(array('//', '../'), '/', trim($uri, '/'));
 	}