blob: 3f8775d4ece148a42a4e983586b2d8b1e667243b [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Andrey Andreevc123e112012-01-08 00:17:34 +02008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Andrey Andreevc123e112012-01-08 00:17:34 +020010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
Andrey Andreev92ebfb62012-05-17 12:49:24 +030025 * @filesource
Derek Allard2067d1a2008-11-13 22:59:24 +000026 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020027defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000028
Derek Allard2067d1a2008-11-13 22:59:24 +000029/**
30 * URI Class
31 *
32 * Parses URIs and determines routing
33 *
34 * @package CodeIgniter
35 * @subpackage Libraries
36 * @category URI
Derek Jonesf4a4bd82011-10-20 12:18:42 -050037 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000038 * @link http://codeigniter.com/user_guide/libraries/uri.html
39 */
40class CI_URI {
41
David Behler07b53422011-08-15 00:25:06 +020042 /**
Andrey Andreevcca74272012-10-28 14:43:36 +020043 * List of cached URI segments
David Behler07b53422011-08-15 00:25:06 +020044 *
Andrey Andreevcca74272012-10-28 14:43:36 +020045 * @var array
David Behler07b53422011-08-15 00:25:06 +020046 */
Timothy Warren48a7fbb2012-04-23 11:58:16 -040047 public $keyval = array();
Andrey Andreev92ebfb62012-05-17 12:49:24 +030048
David Behler07b53422011-08-15 00:25:06 +020049 /**
Andrey Andreevcca74272012-10-28 14:43:36 +020050 * Current URI string
David Behler07b53422011-08-15 00:25:06 +020051 *
Andrey Andreevcca74272012-10-28 14:43:36 +020052 * @var string
David Behler07b53422011-08-15 00:25:06 +020053 */
Andrey Andreevc123e112012-01-08 00:17:34 +020054 public $uri_string;
Andrey Andreev92ebfb62012-05-17 12:49:24 +030055
David Behler07b53422011-08-15 00:25:06 +020056 /**
Andrey Andreevcca74272012-10-28 14:43:36 +020057 * List of URI segments
David Behler07b53422011-08-15 00:25:06 +020058 *
Andrey Andreevcca74272012-10-28 14:43:36 +020059 * @var array
David Behler07b53422011-08-15 00:25:06 +020060 */
Timothy Warren48a7fbb2012-04-23 11:58:16 -040061 public $segments = array();
Andrey Andreev92ebfb62012-05-17 12:49:24 +030062
David Behler07b53422011-08-15 00:25:06 +020063 /**
Andrey Andreevcca74272012-10-28 14:43:36 +020064 * Re-indexed list of URI segments
David Behler07b53422011-08-15 00:25:06 +020065 *
Andrey Andreevcca74272012-10-28 14:43:36 +020066 * Starts at 1 instead of 0.
67 *
68 * @var array
David Behler07b53422011-08-15 00:25:06 +020069 */
Timothy Warren48a7fbb2012-04-23 11:58:16 -040070 public $rsegments = array();
Derek Allard2067d1a2008-11-13 22:59:24 +000071
72 /**
Andrey Andreevcca74272012-10-28 14:43:36 +020073 * Class constructor
Derek Allard2067d1a2008-11-13 22:59:24 +000074 *
Andrey Andreevc123e112012-01-08 00:17:34 +020075 * Simply globalizes the $RTR object. The front
Derek Allard2067d1a2008-11-13 22:59:24 +000076 * loads the Router class early on so it's not available
77 * normally as other classes are.
Andrey Andreev92ebfb62012-05-17 12:49:24 +030078 *
79 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +000080 */
Andrey Andreevc123e112012-01-08 00:17:34 +020081 public function __construct()
Derek Allard2067d1a2008-11-13 22:59:24 +000082 {
Derek Jones7576a3b2010-03-02 14:00:36 -060083 $this->config =& load_class('Config', 'core');
Andrey Andreevc123e112012-01-08 00:17:34 +020084 log_message('debug', 'URI Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +000085 }
86
Derek Allard2067d1a2008-11-13 22:59:24 +000087 // --------------------------------------------------------------------
88
89 /**
Andrey Andreevcca74272012-10-28 14:43:36 +020090 * Fetch URI String
Derek Allard2067d1a2008-11-13 22:59:24 +000091 *
Andrey Andreevcca74272012-10-28 14:43:36 +020092 * @used-by CI_Router
Andrey Andreevc123e112012-01-08 00:17:34 +020093 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +000094 */
Andrey Andreevc123e112012-01-08 00:17:34 +020095 public function _fetch_uri_string()
Derek Allard2067d1a2008-11-13 22:59:24 +000096 {
Andrey Andreevc123e112012-01-08 00:17:34 +020097 if (strtoupper($this->config->item('uri_protocol')) === 'AUTO')
Derek Allard2067d1a2008-11-13 22:59:24 +000098 {
Phil Sturgeondda07e92011-01-31 23:26:25 +000099 // Is the request coming from the command line?
Stephen2e00c242011-08-28 10:25:40 +0200100 if ($this->_is_cli_request())
Derek Allard2067d1a2008-11-13 22:59:24 +0000101 {
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200102 $this->_set_uri_string($this->_parse_argv());
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000103 return;
104 }
105
Andrey Andreev3b72eb52012-11-01 00:45:26 +0200106 // Is there a PATH_INFO variable? This should be the easiest solution.
107 if (isset($_SERVER['PATH_INFO']))
108 {
109 $this->_set_uri_string($_SERVER['PATH_INFO']);
110 return;
111 }
112
113 // Let's try REQUEST_URI then, this will work in most situations
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200114 if (($uri = $this->_parse_request_uri()) !== '')
Dan Horriganfea45ad2011-01-19 00:54:12 -0500115 {
Pascal Kriete73598e32011-04-05 15:01:05 -0400116 $this->_set_uri_string($uri);
Derek Allard2067d1a2008-11-13 22:59:24 +0000117 return;
118 }
119
Andrey Andreev3b72eb52012-11-01 00:45:26 +0200120 // No REQUEST_URI either?... What about QUERY_STRING?
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200121 if (($uri = $this->_parse_query_string()) !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000122 {
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200123 $this->_set_uri_string($uri);
Derek Allard2067d1a2008-11-13 22:59:24 +0000124 return;
125 }
126
Dan Horrigan65d603e2010-12-15 08:38:30 -0500127 // As a last ditch effort lets try using the $_GET array
Alex Bilbieed944a32012-06-02 11:07:47 +0100128 if (is_array($_GET) && count($_GET) === 1 && trim(key($_GET), '/') !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000129 {
Pascal Kriete73598e32011-04-05 15:01:05 -0400130 $this->_set_uri_string(key($_GET));
Derek Allard2067d1a2008-11-13 22:59:24 +0000131 return;
132 }
133
134 // We've exhausted all our options...
135 $this->uri_string = '';
Pascal Kriete73598e32011-04-05 15:01:05 -0400136 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000137 }
Pascal Kriete73598e32011-04-05 15:01:05 -0400138
139 $uri = strtoupper($this->config->item('uri_protocol'));
140
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200141 if ($uri === 'CLI')
Derek Allard2067d1a2008-11-13 22:59:24 +0000142 {
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200143 $this->_set_uri_string($this->_parse_argv());
Pascal Kriete73598e32011-04-05 15:01:05 -0400144 return;
145 }
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200146 elseif (method_exists($this, ($method = '_parse_'.strtolower($uri))))
Pascal Kriete73598e32011-04-05 15:01:05 -0400147 {
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200148 $this->_set_uri_string($this->$method());
Pascal Kriete73598e32011-04-05 15:01:05 -0400149 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000150 }
151
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200152 $uri = isset($_SERVER[$uri]) ? $_SERVER[$uri] : @getenv($uri);
153 $this->_set_uri_string($uri);
Pascal Kriete73598e32011-04-05 15:01:05 -0400154 }
Eric Barnes26eebdd2011-04-17 23:45:41 -0400155
Pascal Kriete73598e32011-04-05 15:01:05 -0400156 // --------------------------------------------------------------------
157
158 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200159 * Set URI String
Pascal Kriete73598e32011-04-05 15:01:05 -0400160 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200161 * @param string $str
Andrey Andreevc123e112012-01-08 00:17:34 +0200162 * @return void
Pascal Kriete73598e32011-04-05 15:01:05 -0400163 */
Andrey Andreevd4619342012-06-14 02:27:25 +0300164 protected function _set_uri_string($str)
Pascal Kriete73598e32011-04-05 15:01:05 -0400165 {
Andrey Andreevf5f898f2012-10-23 02:13:29 +0300166 // Filter out control characters and trim slashes
167 $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');
Derek Allard2067d1a2008-11-13 22:59:24 +0000168 }
169
170 // --------------------------------------------------------------------
171
172 /**
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200173 * Parse REQUEST_URI
Derek Allard2067d1a2008-11-13 22:59:24 +0000174 *
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200175 * Will parse REQUEST_URI and automatically detect the URI from it,
176 * while fixing the query string if necessary.
Derek Allard2067d1a2008-11-13 22:59:24 +0000177 *
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200178 * @used-by CI_URI::_fetch_uri_string()
Derek Allard2067d1a2008-11-13 22:59:24 +0000179 * @return string
180 */
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200181 protected function _parse_request_uri()
Derek Allard2067d1a2008-11-13 22:59:24 +0000182 {
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300183 if ( ! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000184 {
185 return '';
186 }
187
Andrey Andreevd4516e32012-10-31 14:44:38 +0200188 $uri = parse_url($_SERVER['REQUEST_URI']);
189 $query = isset($uri['query']) ? $uri['query'] : '';
Andrey Andreev9dd2dbb2012-10-31 17:54:56 +0200190 $uri = isset($uri['path']) ? rawurldecode($uri['path']) : '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000191
Andrey Andreevd4516e32012-10-31 14:44:38 +0200192 if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
193 {
194 $uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME']));
195 }
196 elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
197 {
198 $uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
199 }
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200200
Dan Horriganfea45ad2011-01-19 00:54:12 -0500201 // This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
202 // URI is found, and also fixes the QUERY_STRING server var and $_GET array.
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200203 if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000204 {
Andrey Andreevd4516e32012-10-31 14:44:38 +0200205 $query = explode('?', $query, 2);
Andrey Andreev9dd2dbb2012-10-31 17:54:56 +0200206 $uri = rawurldecode($query[0]);
Andrey Andreevd4516e32012-10-31 14:44:38 +0200207 $_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000208 }
Dan Horriganfea45ad2011-01-19 00:54:12 -0500209 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000210 {
Andrey Andreevd4516e32012-10-31 14:44:38 +0200211 $_SERVER['QUERY_STRING'] = $query;
212 }
213
Andrey Andreevea6688b2012-10-31 21:52:11 +0200214 parse_str($_SERVER['QUERY_STRING'], $_GET);
Eric Barnes26eebdd2011-04-17 23:45:41 -0400215
Andrey Andreev4b322b12012-10-26 15:37:28 +0300216 if ($uri === '/' OR $uri === '')
ericbarnes@ericbarnes.locale58199b2011-02-02 22:40:36 -0500217 {
218 return '/';
219 }
Eric Barnes26eebdd2011-04-17 23:45:41 -0400220
Dan Horriganfea45ad2011-01-19 00:54:12 -0500221 // Do some final cleaning of the URI and return it
chernjieaf3bd3e2012-12-06 12:06:50 +0800222 return $this->_remove_relative_directory_str($uri);
223 }
224
225 // --------------------------------------------------------------------
226
227 /**
228 * Remove relative directory (../) and multi slashes (///)
229 * @param string $url
230 * @return string
231 */
232 private function _remove_relative_directory_str($url)
233 {
234 $uris = array();
235 $tok = strtok($url, '/');
236 while ($tok !== false)
237 {
238 ($tok != '..' && ! empty($tok) || $tok === '0') && $uris[] = $tok;
239 $tok = strtok('/');
240 }
241 return implode('/', $uris);
Derek Allard2067d1a2008-11-13 22:59:24 +0000242 }
243
244 // --------------------------------------------------------------------
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300245
Stephen2e00c242011-08-28 10:25:40 +0200246 /**
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200247 * Parse QUERY_STRING
248 *
249 * Will parse QUERY_STRING and automatically detect the URI from it.
250 *
251 * @used-by CI_URI::_fetch_uri_string()
252 * @return string
253 */
254 protected function _parse_query_string()
255 {
256 $uri = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
257
258 if (trim($uri, '/') === '')
259 {
260 return '';
261 }
262 elseif (strncmp($uri, '/', 1) === 0)
263 {
264 $uri = explode('?', $uri, 2);
265 $_SERVER['QUERY_STRING'] = isset($uri[1]) ? $uri[1] : '';
Andrey Andreev9dd2dbb2012-10-31 17:54:56 +0200266 $uri = rawurldecode($uri[0]);
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200267 }
Andrey Andreev9dd2dbb2012-10-31 17:54:56 +0200268
Andrey Andreevea6688b2012-10-31 21:52:11 +0200269 parse_str($_SERVER['QUERY_STRING'], $_GET);
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200270
271 return str_replace(array('//', '../'), '/', trim($uri, '/'));
272 }
273
274 // --------------------------------------------------------------------
275
276 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200277 * Is CLI Request?
Stephen2e00c242011-08-28 10:25:40 +0200278 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200279 * Duplicate of method from the Input class to test to see if
280 * a request was made from the command line.
Stephen2e00c242011-08-28 10:25:40 +0200281 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200282 * @see CI_Input::is_cli_request()
283 * @used-by CI_URI::_fetch_uri_string()
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300284 * @return bool
Stephen2e00c242011-08-28 10:25:40 +0200285 */
286 protected function _is_cli_request()
287 {
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300288 return (php_sapi_name() === 'cli') OR defined('STDIN');
Stephen2e00c242011-08-28 10:25:40 +0200289 }
290
Stephen2e00c242011-08-28 10:25:40 +0200291 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000292
293 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200294 * Parse CLI arguments
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000295 *
296 * Take each command line argument and assume it is a URI segment.
297 *
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000298 * @return string
299 */
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200300 protected function _parse_argv()
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000301 {
302 $args = array_slice($_SERVER['argv'], 1);
Andrey Andreevf2b19fe2012-10-31 16:16:24 +0200303 return $args ? implode('/', $args) : '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000304 }
305
306 // --------------------------------------------------------------------
307
308 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200309 * Filter URI
Derek Allard2067d1a2008-11-13 22:59:24 +0000310 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200311 * Filters segments for malicious characters.
Andrey Andreevc123e112012-01-08 00:17:34 +0200312 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200313 * @used-by CI_Router
314 * @param string $str
Derek Allard2067d1a2008-11-13 22:59:24 +0000315 * @return string
316 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200317 public function _filter_uri($str)
Derek Allard2067d1a2008-11-13 22:59:24 +0000318 {
Alex Bilbie04d43fe2012-06-02 17:59:11 +0100319 if ($str !== '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000320 {
Derek Jonesf0a9b332009-07-29 14:19:18 +0000321 // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
322 // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
Andrey Andreevc3751f82012-11-02 16:50:00 +0200323 if ( ! preg_match('|^['.str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-')).']+$|i', $str))
Derek Allard2067d1a2008-11-13 22:59:24 +0000324 {
Derek Jones817163a2009-07-11 17:05:58 +0000325 show_error('The URI you submitted has disallowed characters.', 400);
Derek Allard2067d1a2008-11-13 22:59:24 +0000326 }
327 }
328
Andrey Andreevc123e112012-01-08 00:17:34 +0200329 // Convert programatic characters to entities and return
330 return str_replace(
331 array('$', '(', ')', '%28', '%29'), // Bad
332 array('&#36;', '&#40;', '&#41;', '&#40;', '&#41;'), // Good
333 $str);
Derek Allard2067d1a2008-11-13 22:59:24 +0000334 }
335
336 // --------------------------------------------------------------------
337
338 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200339 * Remove URL suffix
Derek Allard2067d1a2008-11-13 22:59:24 +0000340 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200341 * Removes the suffix from the URL if needed.
Andrey Andreevc123e112012-01-08 00:17:34 +0200342 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200343 * @used-by CI_Router
Derek Allard2067d1a2008-11-13 22:59:24 +0000344 * @return void
345 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200346 public function _remove_url_suffix()
Derek Allard2067d1a2008-11-13 22:59:24 +0000347 {
Andrey Andreev95d78cf2012-06-16 19:54:33 +0300348 $suffix = (string) $this->config->item('url_suffix');
349
350 if ($suffix !== '' && ($offset = strrpos($this->uri_string, $suffix)) !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000351 {
Andrey Andreev95d78cf2012-06-16 19:54:33 +0300352 $this->uri_string = substr_replace($this->uri_string, '', $offset, strlen($suffix));
Derek Allard2067d1a2008-11-13 22:59:24 +0000353 }
354 }
355
356 // --------------------------------------------------------------------
357
358 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200359 * Explode URI segments
Derek Allard2067d1a2008-11-13 22:59:24 +0000360 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200361 * The individual segments will be stored in the $this->segments array.
Andrey Andreevc123e112012-01-08 00:17:34 +0200362 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200363 * @see CI_URI::$segments
364 * @used-by CI_Router
Derek Allard2067d1a2008-11-13 22:59:24 +0000365 * @return void
366 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200367 public function _explode_segments()
Derek Allard2067d1a2008-11-13 22:59:24 +0000368 {
Andrey Andreevc123e112012-01-08 00:17:34 +0200369 foreach (explode('/', preg_replace('|/*(.+?)/*$|', '\\1', $this->uri_string)) as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000370 {
371 // Filter segments for security
372 $val = trim($this->_filter_uri($val));
373
Alex Bilbieed944a32012-06-02 11:07:47 +0100374 if ($val !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000375 {
376 $this->segments[] = $val;
377 }
378 }
379 }
380
381 // --------------------------------------------------------------------
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300382
Derek Allard2067d1a2008-11-13 22:59:24 +0000383 /**
384 * Re-index Segments
385 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200386 * Re-indexes the CI_URI::$segment array so that it starts at 1 rather
387 * than 0. Doing so makes it simpler to use methods like
388 * CI_URI::segment(n) since there is a 1:1 relationship between the
389 * segment array and the actual segments.
Derek Allard2067d1a2008-11-13 22:59:24 +0000390 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200391 * @used-by CI_Router
Derek Allard2067d1a2008-11-13 22:59:24 +0000392 * @return void
393 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200394 public function _reindex_segments()
Derek Allard2067d1a2008-11-13 22:59:24 +0000395 {
396 array_unshift($this->segments, NULL);
397 array_unshift($this->rsegments, NULL);
398 unset($this->segments[0]);
399 unset($this->rsegments[0]);
400 }
401
402 // --------------------------------------------------------------------
403
404 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200405 * Fetch URI Segment
Derek Allard2067d1a2008-11-13 22:59:24 +0000406 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200407 * @see CI_URI::$segments
408 * @param int $n Index
409 * @param mixed $no_result What to return if the segment index is not found
410 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000411 */
Phil Sturgeon55a6ddb2012-05-23 18:37:24 +0100412 public function segment($n, $no_result = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000413 {
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300414 return isset($this->segments[$n]) ? $this->segments[$n] : $no_result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000415 }
416
417 // --------------------------------------------------------------------
418
419 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200420 * Fetch URI "routed" Segment
Derek Allard2067d1a2008-11-13 22:59:24 +0000421 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200422 * Returns the re-routed URI segment (assuming routing rules are used)
423 * based on the index provided. If there is no routing, will return
424 * the same result as CI_URI::segment().
Derek Allard2067d1a2008-11-13 22:59:24 +0000425 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200426 * @see CI_URI::$rsegments
427 * @see CI_URI::segment()
428 * @param int $n Index
429 * @param mixed $no_result What to return if the segment index is not found
430 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000431 */
Phil Sturgeon55a6ddb2012-05-23 18:37:24 +0100432 public function rsegment($n, $no_result = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000433 {
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300434 return isset($this->rsegments[$n]) ? $this->rsegments[$n] : $no_result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000435 }
436
437 // --------------------------------------------------------------------
438
439 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200440 * URI to assoc
Derek Allard2067d1a2008-11-13 22:59:24 +0000441 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200442 * Generates an associative array of URI data starting at the supplied
443 * segment index. For example, if this is your URI:
Derek Allard2067d1a2008-11-13 22:59:24 +0000444 *
445 * example.com/user/search/name/joe/location/UK/gender/male
446 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200447 * You can use this method to generate an array with this prototype:
Derek Allard2067d1a2008-11-13 22:59:24 +0000448 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200449 * array (
450 * name => joe
451 * location => UK
452 * gender => male
453 * )
Derek Allard2067d1a2008-11-13 22:59:24 +0000454 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200455 * @param int $n Index (default: 3)
456 * @param array $default Default values
Derek Allard2067d1a2008-11-13 22:59:24 +0000457 * @return array
458 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200459 public function uri_to_assoc($n = 3, $default = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000460 {
Barry Mienydd671972010-10-04 16:33:58 +0200461 return $this->_uri_to_assoc($n, $default, 'segment');
Derek Allard2067d1a2008-11-13 22:59:24 +0000462 }
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300463
Timothy Warren40403d22012-04-19 16:38:50 -0400464 // --------------------------------------------------------------------
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300465
Derek Allard2067d1a2008-11-13 22:59:24 +0000466 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200467 * Routed URI to assoc
Derek Allard2067d1a2008-11-13 22:59:24 +0000468 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200469 * Identical to CI_URI::uri_to_assoc(), only it uses the re-routed
470 * segment array.
471 *
472 * @see CI_URI::uri_to_assoc()
473 * @param int $n Index (default: 3)
474 * @param array $default Default values
David Behler07b53422011-08-15 00:25:06 +0200475 * @return array
Derek Allard2067d1a2008-11-13 22:59:24 +0000476 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200477 public function ruri_to_assoc($n = 3, $default = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000478 {
Barry Mienydd671972010-10-04 16:33:58 +0200479 return $this->_uri_to_assoc($n, $default, 'rsegment');
Derek Allard2067d1a2008-11-13 22:59:24 +0000480 }
481
482 // --------------------------------------------------------------------
483
484 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200485 * Internal URI-to-assoc
Derek Allard2067d1a2008-11-13 22:59:24 +0000486 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200487 * Generates a key/value pair from the URI string or re-routed URI string.
488 *
489 * @used-by CI_URI::uri_to_assoc()
490 * @used-by CI_URI::ruri_to_assoc()
491 * @param int $n Index (default: 3)
492 * @param array $default Default values
493 * @param string $which Array name ('segment' or 'rsegment')
Derek Allard2067d1a2008-11-13 22:59:24 +0000494 * @return array
495 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200496 protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
Derek Allard2067d1a2008-11-13 22:59:24 +0000497 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000498 if ( ! is_numeric($n))
499 {
500 return $default;
501 }
502
Andrey Andreev4a7cc762012-10-24 23:52:05 +0300503 in_array($which, array('segment', 'rsegment'), TRUE) OR $which = 'segment';
504
505 if (isset($this->keyval[$which], $this->keyval[$which][$n]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000506 {
Andrey Andreev4a7cc762012-10-24 23:52:05 +0300507 return $this->keyval[$which][$n];
Derek Allard2067d1a2008-11-13 22:59:24 +0000508 }
509
Andrey Andreevc123e112012-01-08 00:17:34 +0200510 if ($which === 'segment')
511 {
512 $total_segments = 'total_segments';
513 $segment_array = 'segment_array';
514 }
515 else
516 {
517 $total_segments = 'total_rsegments';
518 $segment_array = 'rsegment_array';
519 }
520
Derek Allard2067d1a2008-11-13 22:59:24 +0000521 if ($this->$total_segments() < $n)
522 {
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300523 return (count($default) === 0)
524 ? array()
Phil Sturgeon55a6ddb2012-05-23 18:37:24 +0100525 : array_fill_keys($default, NULL);
Derek Allard2067d1a2008-11-13 22:59:24 +0000526 }
527
528 $segments = array_slice($this->$segment_array(), ($n - 1));
Derek Allard2067d1a2008-11-13 22:59:24 +0000529 $i = 0;
530 $lastval = '';
vkeranov2b6b4302012-10-27 18:12:24 +0300531 $retval = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000532 foreach ($segments as $seg)
533 {
534 if ($i % 2)
535 {
536 $retval[$lastval] = $seg;
537 }
538 else
539 {
Phil Sturgeon55a6ddb2012-05-23 18:37:24 +0100540 $retval[$seg] = NULL;
Derek Allard2067d1a2008-11-13 22:59:24 +0000541 $lastval = $seg;
542 }
543
544 $i++;
545 }
546
547 if (count($default) > 0)
548 {
549 foreach ($default as $val)
550 {
551 if ( ! array_key_exists($val, $retval))
552 {
Phil Sturgeon55a6ddb2012-05-23 18:37:24 +0100553 $retval[$val] = NULL;
Derek Allard2067d1a2008-11-13 22:59:24 +0000554 }
555 }
556 }
557
558 // Cache the array for reuse
Andrey Andreev90930422012-10-24 23:53:12 +0300559 isset($this->keyval[$which]) OR $this->keyval[$which] = array();
Andrey Andreev4a7cc762012-10-24 23:52:05 +0300560 $this->keyval[$which][$n] = $retval;
Derek Allard2067d1a2008-11-13 22:59:24 +0000561 return $retval;
562 }
563
564 // --------------------------------------------------------------------
565
566 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200567 * Assoc to URI
Derek Allard2067d1a2008-11-13 22:59:24 +0000568 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200569 * Generates a URI string from an associative array.
570 *
571 * @param array $array Input array of key/value pairs
572 * @return string URI string
Derek Allard2067d1a2008-11-13 22:59:24 +0000573 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200574 public function assoc_to_uri($array)
Derek Allard2067d1a2008-11-13 22:59:24 +0000575 {
576 $temp = array();
Phil Sturgeon55a6ddb2012-05-23 18:37:24 +0100577 foreach ((array) $array as $key => $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000578 {
Andrey Andreeva798fdb2012-01-08 00:20:49 +0200579 $temp[] = $key;
Derek Allard2067d1a2008-11-13 22:59:24 +0000580 $temp[] = $val;
581 }
582
583 return implode('/', $temp);
584 }
585
586 // --------------------------------------------------------------------
587
588 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200589 * Slash segment
Derek Allard2067d1a2008-11-13 22:59:24 +0000590 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200591 * Fetches an URI segment with a slash.
592 *
593 * @param int $n Index
594 * @param string $where Where to add the slash ('trailing' or 'leading')
Derek Allard2067d1a2008-11-13 22:59:24 +0000595 * @return string
596 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200597 public function slash_segment($n, $where = 'trailing')
Derek Allard2067d1a2008-11-13 22:59:24 +0000598 {
599 return $this->_slash_segment($n, $where, 'segment');
600 }
601
602 // --------------------------------------------------------------------
603
604 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200605 * Slash routed segment
Derek Allard2067d1a2008-11-13 22:59:24 +0000606 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200607 * Fetches an URI routed segment with a slash.
608 *
609 * @param int $n Index
610 * @param string $where Where to add the slash ('trailing' or 'leading')
Derek Allard2067d1a2008-11-13 22:59:24 +0000611 * @return string
612 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200613 public function slash_rsegment($n, $where = 'trailing')
Derek Allard2067d1a2008-11-13 22:59:24 +0000614 {
615 return $this->_slash_segment($n, $where, 'rsegment');
616 }
617
618 // --------------------------------------------------------------------
619
620 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200621 * Internal Slash segment
Derek Allard2067d1a2008-11-13 22:59:24 +0000622 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200623 * Fetches an URI Segment and adds a slash to it.
624 *
625 * @used-by CI_URI::slash_segment()
626 * @used-by CI_URI::slash_rsegment()
627 *
628 * @param int $n Index
629 * @param string $where Where to add the slash ('trailing' or 'leading')
630 * @param string $which Array name ('segment' or 'rsegment')
Derek Allard2067d1a2008-11-13 22:59:24 +0000631 * @return string
632 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200633 protected function _slash_segment($n, $where = 'trailing', $which = 'segment')
Derek Allard2067d1a2008-11-13 22:59:24 +0000634 {
Andrey Andreevc123e112012-01-08 00:17:34 +0200635 $leading = $trailing = '/';
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000636
Andrey Andreevc123e112012-01-08 00:17:34 +0200637 if ($where === 'trailing')
Derek Allard2067d1a2008-11-13 22:59:24 +0000638 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000639 $leading = '';
640 }
Andrey Andreevc123e112012-01-08 00:17:34 +0200641 elseif ($where === 'leading')
Derek Allard2067d1a2008-11-13 22:59:24 +0000642 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000643 $trailing = '';
644 }
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000645
Derek Allard2067d1a2008-11-13 22:59:24 +0000646 return $leading.$this->$which($n).$trailing;
647 }
648
649 // --------------------------------------------------------------------
650
651 /**
652 * Segment Array
653 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200654 * @return array CI_URI::$segments
Derek Allard2067d1a2008-11-13 22:59:24 +0000655 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200656 public function segment_array()
Derek Allard2067d1a2008-11-13 22:59:24 +0000657 {
658 return $this->segments;
659 }
660
661 // --------------------------------------------------------------------
662
663 /**
664 * Routed Segment Array
665 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200666 * @return array CI_URI::$rsegments
Derek Allard2067d1a2008-11-13 22:59:24 +0000667 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200668 public function rsegment_array()
Derek Allard2067d1a2008-11-13 22:59:24 +0000669 {
670 return $this->rsegments;
671 }
672
673 // --------------------------------------------------------------------
674
675 /**
676 * Total number of segments
677 *
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300678 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +0000679 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200680 public function total_segments()
Derek Allard2067d1a2008-11-13 22:59:24 +0000681 {
682 return count($this->segments);
683 }
684
685 // --------------------------------------------------------------------
686
687 /**
688 * Total number of routed segments
689 *
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300690 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +0000691 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200692 public function total_rsegments()
Derek Allard2067d1a2008-11-13 22:59:24 +0000693 {
694 return count($this->rsegments);
695 }
696
697 // --------------------------------------------------------------------
698
699 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200700 * Fetch URI string
Derek Allard2067d1a2008-11-13 22:59:24 +0000701 *
Andrey Andreevcca74272012-10-28 14:43:36 +0200702 * @return string CI_URI::$uri_string
Derek Allard2067d1a2008-11-13 22:59:24 +0000703 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200704 public function uri_string()
Derek Allard2067d1a2008-11-13 22:59:24 +0000705 {
706 return $this->uri_string;
707 }
708
Derek Allard2067d1a2008-11-13 22:59:24 +0000709 // --------------------------------------------------------------------
710
711 /**
Andrey Andreevcca74272012-10-28 14:43:36 +0200712 * Fetch Re-routed URI string
Derek Allard2067d1a2008-11-13 22:59:24 +0000713 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000714 * @return string
715 */
Andrey Andreevc123e112012-01-08 00:17:34 +0200716 public function ruri_string()
Derek Allard2067d1a2008-11-13 22:59:24 +0000717 {
Andrey Andreev254735e2012-11-01 21:21:20 +0200718 global $RTR;
719
720 if (($dir = $RTR->fetch_directory()) === '/')
721 {
722 $dir = '';
723 }
724
725 return $dir.implode('/', $this->rsegment_array());
Derek Allard2067d1a2008-11-13 22:59:24 +0000726 }
727
728}
Derek Allard2067d1a2008-11-13 22:59:24 +0000729
730/* End of file URI.php */
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300731/* Location: ./system/core/URI.php */