diff options
Diffstat (limited to 'system/core/URI.php')
-rw-r--r-- | system/core/URI.php | 282 |
1 files changed, 94 insertions, 188 deletions
diff --git a/system/core/URI.php b/system/core/URI.php index bc086d223..15d6263be 100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -18,7 +18,7 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/) + * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 1.0 @@ -44,21 +44,21 @@ class CI_URI { * * @var array */ - public $keyval = array(); + public $keyval = array(); /** * Current URI string * * @var string */ - public $uri_string; + public $uri_string = ''; /** * List of URI segments * * @var array */ - public $segments = array(); + public $segments = array(); /** * Re-indexed list of URI segments @@ -67,90 +67,67 @@ class CI_URI { * * @var array */ - public $rsegments = array(); + public $rsegments = array(); /** - * Class constructor + * Permitted URI chars * - * Simply globalizes the $RTR object. The front - * loads the Router class early on so it's not available - * normally as other classes are. + * PCRE character group allowed in URI segments * - * @return void + * @var string */ - public function __construct() - { - $this->config =& load_class('Config', 'core'); - log_message('debug', 'URI Class Initialized'); - } - - // -------------------------------------------------------------------- + protected $_permitted_uri_chars; /** - * Fetch URI String + * Class constructor * - * @used-by CI_Router * @return void */ - public function _fetch_uri_string() + public function __construct() { - $protocol = strtoupper($this->config->item('uri_protocol')); + $this->config =& load_class('Config', 'core'); - if ($protocol === 'AUTO') + // If query strings are enabled, we don't need to parse any segments. + // However, they don't make sense under CLI. + if (is_cli() OR $this->config->item('enable_query_strings') !== TRUE) { - // Is the request coming from the command line? - if ($this->_is_cli_request()) + $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') { $this->_set_uri_string($this->_parse_argv()); - return; } - - // Is there a PATH_INFO variable? This should be the easiest solution. - if (isset($_SERVER['PATH_INFO'])) + elseif ($protocol === 'AUTO') { - $this->_set_uri_string($_SERVER['PATH_INFO']); - return; + // 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)); + } } - - // Let's try REQUEST_URI then, this will work in most situations - if (($uri = $this->_parse_request_uri()) !== '') + elseif (method_exists($this, ($method = '_parse_'.strtolower($protocol)))) { - $this->_set_uri_string($uri); - return; + $this->_set_uri_string($this->$method()); } - - // No REQUEST_URI either?... What about QUERY_STRING? - if (($uri = $this->_parse_query_string()) !== '') + else { + $uri = isset($_SERVER[$protocol]) ? $_SERVER[$protocol] : @getenv($protocol); $this->_set_uri_string($uri); - return; - } - - // As a last ditch effort let's try using the $_GET array - if (is_array($_GET) && count($_GET) === 1 && trim(key($_GET), '/') !== '') - { - $this->_set_uri_string(key($_GET)); - return; } - - // We've exhausted all our options... - $this->uri_string = ''; - return; } - if ($protocol === 'CLI') - { - $this->_set_uri_string($this->_parse_argv()); - return; - } - elseif (method_exists($this, ($method = '_parse_'.strtolower($protocol)))) - { - $this->_set_uri_string($this->$method()); - return; - } - - $uri = isset($_SERVER[$protocol]) ? $_SERVER[$protocol] : @getenv($protocol); - $this->_set_uri_string($uri); + log_message('debug', 'URI Class Initialized'); } // -------------------------------------------------------------------- @@ -165,6 +142,35 @@ class CI_URI { { // Filter out control characters and trim slashes $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/'); + + if ($this->uri_string !== '') + { + // Remove the URL suffix, if present + if (($suffix = (string) $this->config->item('url_suffix')) !== '') + { + $slen = strlen($suffix); + + if (substr($this->uri_string, -$slen) === $suffix) + { + $this->uri_string = substr($this->uri_string, 0, -$slen); + } + } + + $this->segments[0] = NULL; + // Populate the segments array + foreach (explode('/', preg_replace('|/*(.+?)/*$|', '\\1', $this->uri_string)) as $val) + { + // Filter segments for security + $val = trim($this->filter_uri($val)); + + if ($val !== '') + { + $this->segments[] = $val; + } + } + + unset($this->segments[0]); + } } // -------------------------------------------------------------------- @@ -225,36 +231,10 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Remove relative directory (../) and multi slashes (///) - * - * Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri() - * - * @param string $url - * @return string - */ - protected function _remove_relative_directory($uri) - { - $uris = array(); - $tok = strtok($uri, '/'); - while ($tok !== FALSE) - { - if (( ! empty($tok) OR $tok === '0') && $tok !== '..') - { - $uris[] = $tok; - } - $tok = strtok('/'); - } - return implode('/', $uris); - } - - // -------------------------------------------------------------------- - - /** * Parse QUERY_STRING * * Will parse QUERY_STRING and automatically detect the URI from it. * - * @used-by CI_URI::_fetch_uri_string() * @return string */ protected function _parse_query_string() @@ -280,23 +260,6 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Is CLI Request? - * - * Duplicate of method from the Input class to test to see if - * a request was made from the command line. - * - * @see CI_Input::is_cli_request() - * @used-by CI_URI::_fetch_uri_string() - * @return bool - */ - protected function _is_cli_request() - { - return (PHP_SAPI === 'cli') OR defined('STDIN'); - } - - // -------------------------------------------------------------------- - - /** * Parse CLI arguments * * Take each command line argument and assume it is a URI segment. @@ -312,104 +275,52 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Filter URI + * Remove relative directory (../) and multi slashes (///) * - * Filters segments for malicious characters. + * Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri() * - * @used-by CI_Router - * @param string $str + * @param string $url * @return string */ - public function _filter_uri($str) + protected function _remove_relative_directory($uri) { - if ($str !== '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') === FALSE) + $uris = array(); + $tok = strtok($uri, '/'); + while ($tok !== FALSE) { - // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards - // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern - if ( ! preg_match('|^['.str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-')).']+$|i', $str)) + if (( ! empty($tok) OR $tok === '0') && $tok !== '..') { - show_error('The URI you submitted has disallowed characters.', 400); + $uris[] = $tok; } + $tok = strtok('/'); } - // Convert programatic characters to entities and return - return str_replace( - array('$', '(', ')', '%28', '%29'), // Bad - array('$', '(', ')', '(', ')'), // Good - $str); - } - - // -------------------------------------------------------------------- - - /** - * Remove URL suffix - * - * Removes the suffix from the URL if needed. - * - * @used-by CI_Router - * @return void - */ - public function _remove_url_suffix() - { - $suffix = (string) $this->config->item('url_suffix'); - - if ($suffix === '') - { - return; - } - - $slen = strlen($suffix); - - if (substr($this->uri_string, -$slen) === $suffix) - { - $this->uri_string = substr($this->uri_string, 0, -$slen); - } + return implode('/', $uris); } // -------------------------------------------------------------------- /** - * Explode URI segments + * Filter URI * - * The individual segments will be stored in the $this->segments array. + * Filters segments for malicious characters. * - * @see CI_URI::$segments - * @used-by CI_Router - * @return void + * @param string $str + * @return string */ - public function _explode_segments() + public function filter_uri($str) { - foreach (explode('/', preg_replace('|/*(.+?)/*$|', '\\1', $this->uri_string)) as $val) + if ( ! empty($str) && ! empty($this->_permitted_uri_chars) && ! preg_match('/^['.$this->_permitted_uri_chars.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $str)) { - // Filter segments for security - $val = trim($this->_filter_uri($val)); - - if ($val !== '') - { - $this->segments[] = $val; - } + show_error('The URI you submitted has disallowed characters.', 400); } - } - // -------------------------------------------------------------------- - - /** - * Re-index Segments - * - * Re-indexes the CI_URI::$segment array so that it starts at 1 rather - * than 0. Doing so makes it simpler to use methods like - * CI_URI::segment(n) since there is a 1:1 relationship between the - * segment array and the actual segments. - * - * @used-by CI_Router - * @return void - */ - public function _reindex_segments() - { - array_unshift($this->segments, NULL); - array_unshift($this->rsegments, NULL); - unset($this->segments[0]); - unset($this->rsegments[0]); + // Convert programatic characters to entities and return + return str_replace( + array('$', '(', ')', '%28', '%29'), // Bad + array('$', '(', ')', '(', ')'), // Good + $str + ); } // -------------------------------------------------------------------- @@ -720,12 +631,7 @@ class CI_URI { { global $RTR; - if (($dir = $RTR->directory) === '/') - { - $dir = ''; - } - - return $dir.implode('/', $this->rsegment_array()); + return ltrim($RTR->directory, '/').implode('/', $this->rsegments); } } |