blob: 578d1742955be1919d9846d43672f44c679fb584 [file] [log] [blame]
Derek Jones37f4b9c2011-07-01 17:56:50 -05001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Greg Aker741de1c2010-11-10 14:52:57 -06005 * An open source application development framework for PHP 5.1.6 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
8 *
9 * Licensed under the Open Software License version 3.0
10 *
11 * 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
21 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. (http://ellislab.com/)
22 * @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
25 * @filesource
26 */
27
28// ------------------------------------------------------------------------
29
30/**
31 * URI Class
32 *
33 * Parses URIs and determines routing
34 *
35 * @package CodeIgniter
36 * @subpackage Libraries
37 * @category URI
Derek Jonesf4a4bd82011-10-20 12:18:42 -050038 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000039 * @link http://codeigniter.com/user_guide/libraries/uri.html
40 */
41class CI_URI {
42
David Behler07b53422011-08-15 00:25:06 +020043 /**
44 * List of cached uri segments
45 *
46 * @var array
47 * @access public
48 */
Greg Akera9263282010-11-10 15:26:43 -060049 var $keyval = array();
David Behler07b53422011-08-15 00:25:06 +020050 /**
51 * Current uri string
52 *
53 * @var string
54 * @access public
55 */
Derek Allard2067d1a2008-11-13 22:59:24 +000056 var $uri_string;
David Behler07b53422011-08-15 00:25:06 +020057 /**
58 * List of uri segments
59 *
60 * @var array
61 * @access public
62 */
Derek Allard2067d1a2008-11-13 22:59:24 +000063 var $segments = array();
David Behler07b53422011-08-15 00:25:06 +020064 /**
65 * Re-indexed list of uri segments
66 * Starts at 1 instead of 0
67 *
68 * @var array
69 * @access public
70 */
Derek Allard2067d1a2008-11-13 22:59:24 +000071 var $rsegments = array();
72
73 /**
74 * Constructor
75 *
Derek Jones37f4b9c2011-07-01 17:56:50 -050076 * Simply globalizes the $RTR object. The front
Derek Allard2067d1a2008-11-13 22:59:24 +000077 * loads the Router class early on so it's not available
78 * normally as other classes are.
79 *
80 * @access public
81 */
Greg Akera9263282010-11-10 15:26:43 -060082 function __construct()
Derek Allard2067d1a2008-11-13 22:59:24 +000083 {
Derek Jones7576a3b2010-03-02 14:00:36 -060084 $this->config =& load_class('Config', 'core');
Derek Allard2067d1a2008-11-13 22:59:24 +000085 log_message('debug', "URI Class Initialized");
86 }
87
88
89 // --------------------------------------------------------------------
90
91 /**
92 * Get the URI String
93 *
94 * @access private
95 * @return string
96 */
97 function _fetch_uri_string()
98 {
99 if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
100 {
Phil Sturgeondda07e92011-01-31 23:26:25 +0000101 // Is the request coming from the command line?
Phil Sturgeonc5dccf72011-08-13 11:06:57 -0600102 if (php_sapi_name() == 'cli' or defined('STDIN'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000103 {
Pascal Kriete73598e32011-04-05 15:01:05 -0400104 $this->_set_uri_string($this->_parse_cli_args());
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000105 return;
106 }
107
Dan Horriganfea45ad2011-01-19 00:54:12 -0500108 // Let's try the REQUEST_URI first, this will work in most situations
109 if ($uri = $this->_detect_uri())
110 {
Pascal Kriete73598e32011-04-05 15:01:05 -0400111 $this->_set_uri_string($uri);
Derek Allard2067d1a2008-11-13 22:59:24 +0000112 return;
113 }
114
115 // Is there a PATH_INFO variable?
116 // Note: some servers seem to have trouble with getenv() so we'll test it two ways
117 $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
118 if (trim($path, '/') != '' && $path != "/".SELF)
119 {
Pascal Kriete73598e32011-04-05 15:01:05 -0400120 $this->_set_uri_string($path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000121 return;
122 }
123
124 // No PATH_INFO?... What about QUERY_STRING?
Derek Jones37f4b9c2011-07-01 17:56:50 -0500125 $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
Derek Allard2067d1a2008-11-13 22:59:24 +0000126 if (trim($path, '/') != '')
127 {
Pascal Kriete73598e32011-04-05 15:01:05 -0400128 $this->_set_uri_string($path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000129 return;
130 }
131
Dan Horrigan65d603e2010-12-15 08:38:30 -0500132 // As a last ditch effort lets try using the $_GET array
133 if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000134 {
Pascal Kriete73598e32011-04-05 15:01:05 -0400135 $this->_set_uri_string(key($_GET));
Derek Allard2067d1a2008-11-13 22:59:24 +0000136 return;
137 }
138
139 // We've exhausted all our options...
140 $this->uri_string = '';
Pascal Kriete73598e32011-04-05 15:01:05 -0400141 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000142 }
Pascal Kriete73598e32011-04-05 15:01:05 -0400143
144 $uri = strtoupper($this->config->item('uri_protocol'));
145
146 if ($uri == 'REQUEST_URI')
Derek Allard2067d1a2008-11-13 22:59:24 +0000147 {
Pascal Kriete73598e32011-04-05 15:01:05 -0400148 $this->_set_uri_string($this->_detect_uri());
149 return;
150 }
151 elseif ($uri == 'CLI')
152 {
153 $this->_set_uri_string($this->_parse_cli_args());
154 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000155 }
156
Pascal Kriete73598e32011-04-05 15:01:05 -0400157 $path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);
158 $this->_set_uri_string($path);
159 }
Eric Barnes26eebdd2011-04-17 23:45:41 -0400160
Pascal Kriete73598e32011-04-05 15:01:05 -0400161 // --------------------------------------------------------------------
162
163 /**
164 * Set the URI String
165 *
166 * @access public
David Behler07b53422011-08-15 00:25:06 +0200167 * @param string
Pascal Kriete73598e32011-04-05 15:01:05 -0400168 * @return string
169 */
170 function _set_uri_string($str)
171 {
172 // Filter out control characters
173 $str = remove_invisible_characters($str, FALSE);
Eric Barnes26eebdd2011-04-17 23:45:41 -0400174
Derek Allard2067d1a2008-11-13 22:59:24 +0000175 // If the URI contains only a slash we'll kill it
Pascal Kriete73598e32011-04-05 15:01:05 -0400176 $this->uri_string = ($str == '/') ? '' : $str;
Derek Allard2067d1a2008-11-13 22:59:24 +0000177 }
178
179 // --------------------------------------------------------------------
180
181 /**
Dan Horriganfea45ad2011-01-19 00:54:12 -0500182 * Detects the URI
Derek Allard2067d1a2008-11-13 22:59:24 +0000183 *
Dan Horriganfea45ad2011-01-19 00:54:12 -0500184 * This function will detect the URI automatically and fix the query string
185 * if necessary.
Derek Allard2067d1a2008-11-13 22:59:24 +0000186 *
187 * @access private
188 * @return string
189 */
Paulf7345e42011-08-27 06:51:16 +1200190 protected function _detect_uri()
Derek Allard2067d1a2008-11-13 22:59:24 +0000191 {
Eric Barnes26eebdd2011-04-17 23:45:41 -0400192 if ( ! isset($_SERVER['REQUEST_URI']) OR ! isset($_SERVER['SCRIPT_NAME']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000193 {
194 return '';
195 }
196
Dan Horriganfea45ad2011-01-19 00:54:12 -0500197 $uri = $_SERVER['REQUEST_URI'];
198 if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000199 {
Dan Horriganfea45ad2011-01-19 00:54:12 -0500200 $uri = substr($uri, strlen($_SERVER['SCRIPT_NAME']));
201 }
202 elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
203 {
204 $uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
Derek Allard2067d1a2008-11-13 22:59:24 +0000205 }
206
Dan Horriganfea45ad2011-01-19 00:54:12 -0500207 // This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
208 // URI is found, and also fixes the QUERY_STRING server var and $_GET array.
209 if (strncmp($uri, '?/', 2) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000210 {
Dan Horriganfea45ad2011-01-19 00:54:12 -0500211 $uri = substr($uri, 2);
Derek Allard2067d1a2008-11-13 22:59:24 +0000212 }
Dan Horriganfea45ad2011-01-19 00:54:12 -0500213 $parts = preg_split('#\?#i', $uri, 2);
214 $uri = $parts[0];
215 if (isset($parts[1]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000216 {
Dan Horriganfea45ad2011-01-19 00:54:12 -0500217 $_SERVER['QUERY_STRING'] = $parts[1];
Dan Horrigan65d603e2010-12-15 08:38:30 -0500218 parse_str($_SERVER['QUERY_STRING'], $_GET);
Derek Allard2067d1a2008-11-13 22:59:24 +0000219 }
Dan Horriganfea45ad2011-01-19 00:54:12 -0500220 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000221 {
Dan Horriganfea45ad2011-01-19 00:54:12 -0500222 $_SERVER['QUERY_STRING'] = '';
223 $_GET = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000224 }
Eric Barnes26eebdd2011-04-17 23:45:41 -0400225
ericbarnes@ericbarnes.locale58199b2011-02-02 22:40:36 -0500226 if ($uri == '/' || empty($uri))
227 {
228 return '/';
229 }
Eric Barnes26eebdd2011-04-17 23:45:41 -0400230
Dan Horriganfea45ad2011-01-19 00:54:12 -0500231 $uri = parse_url($uri, PHP_URL_PATH);
Derek Allard2067d1a2008-11-13 22:59:24 +0000232
Dan Horriganfea45ad2011-01-19 00:54:12 -0500233 // Do some final cleaning of the URI and return it
234 return str_replace(array('//', '../'), '/', trim($uri, '/'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000235 }
236
237 // --------------------------------------------------------------------
238
239 /**
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000240 * Parse cli arguments
241 *
242 * Take each command line argument and assume it is a URI segment.
243 *
244 * @access private
245 * @return string
246 */
Paulf7345e42011-08-27 06:51:16 +1200247 protected function _parse_cli_args()
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000248 {
249 $args = array_slice($_SERVER['argv'], 1);
250
251 return $args ? '/' . implode('/', $args) : '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000252 }
253
254 // --------------------------------------------------------------------
255
256 /**
257 * Filter segments for malicious characters
258 *
259 * @access private
260 * @param string
261 * @return string
262 */
263 function _filter_uri($str)
264 {
265 if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
266 {
Derek Jonesf0a9b332009-07-29 14:19:18 +0000267 // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
268 // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
269 if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $str))
Derek Allard2067d1a2008-11-13 22:59:24 +0000270 {
Derek Jones817163a2009-07-11 17:05:58 +0000271 show_error('The URI you submitted has disallowed characters.', 400);
Derek Allard2067d1a2008-11-13 22:59:24 +0000272 }
273 }
274
275 // Convert programatic characters to entities
Barry Mienydd671972010-10-04 16:33:58 +0200276 $bad = array('$', '(', ')', '%28', '%29');
Derek Allard2067d1a2008-11-13 22:59:24 +0000277 $good = array('&#36;', '&#40;', '&#41;', '&#40;', '&#41;');
278
279 return str_replace($bad, $good, $str);
280 }
281
282 // --------------------------------------------------------------------
283
284 /**
285 * Remove the suffix from the URL if needed
286 *
287 * @access private
288 * @return void
289 */
290 function _remove_url_suffix()
291 {
Derek Jones37f4b9c2011-07-01 17:56:50 -0500292 if ($this->config->item('url_suffix') != "")
Derek Allard2067d1a2008-11-13 22:59:24 +0000293 {
294 $this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string);
295 }
296 }
297
298 // --------------------------------------------------------------------
299
300 /**
301 * Explode the URI Segments. The individual segments will
302 * be stored in the $this->segments array.
303 *
304 * @access private
305 * @return void
306 */
307 function _explode_segments()
308 {
Phil Sturgeonc8089152010-12-27 19:06:28 +0000309 foreach (explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000310 {
311 // Filter segments for security
312 $val = trim($this->_filter_uri($val));
313
314 if ($val != '')
315 {
316 $this->segments[] = $val;
317 }
318 }
319 }
320
321 // --------------------------------------------------------------------
322 /**
323 * Re-index Segments
324 *
325 * This function re-indexes the $this->segment array so that it
Derek Jones37f4b9c2011-07-01 17:56:50 -0500326 * starts at 1 rather than 0. Doing so makes it simpler to
Derek Allard2067d1a2008-11-13 22:59:24 +0000327 * use functions like $this->uri->segment(n) since there is
328 * a 1:1 relationship between the segment array and the actual segments.
329 *
330 * @access private
331 * @return void
332 */
333 function _reindex_segments()
334 {
335 array_unshift($this->segments, NULL);
336 array_unshift($this->rsegments, NULL);
337 unset($this->segments[0]);
338 unset($this->rsegments[0]);
339 }
340
341 // --------------------------------------------------------------------
342
343 /**
344 * Fetch a URI Segment
345 *
346 * This function returns the URI segment based on the number provided.
347 *
348 * @access public
349 * @param integer
350 * @param bool
351 * @return string
352 */
353 function segment($n, $no_result = FALSE)
354 {
355 return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];
356 }
357
358 // --------------------------------------------------------------------
359
360 /**
361 * Fetch a URI "routed" Segment
362 *
363 * This function returns the re-routed URI segment (assuming routing rules are used)
Derek Jones37f4b9c2011-07-01 17:56:50 -0500364 * based on the number provided. If there is no routing this function returns the
Derek Allard2067d1a2008-11-13 22:59:24 +0000365 * same result as $this->segment()
366 *
367 * @access public
368 * @param integer
369 * @param bool
370 * @return string
371 */
372 function rsegment($n, $no_result = FALSE)
373 {
374 return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];
375 }
376
377 // --------------------------------------------------------------------
378
379 /**
380 * Generate a key value pair from the URI string
381 *
382 * This function generates and associative array of URI data starting
383 * at the supplied segment. For example, if this is your URI:
384 *
385 * example.com/user/search/name/joe/location/UK/gender/male
386 *
387 * You can use this function to generate an array with this prototype:
388 *
389 * array (
390 * name => joe
391 * location => UK
392 * gender => male
393 * )
394 *
395 * @access public
396 * @param integer the starting segment number
397 * @param array an array of default values
398 * @return array
399 */
400 function uri_to_assoc($n = 3, $default = array())
401 {
Barry Mienydd671972010-10-04 16:33:58 +0200402 return $this->_uri_to_assoc($n, $default, 'segment');
Derek Allard2067d1a2008-11-13 22:59:24 +0000403 }
404 /**
405 * Identical to above only it uses the re-routed segment array
406 *
David Behler07b53422011-08-15 00:25:06 +0200407 * @access public
408 * @param integer the starting segment number
409 * @param array an array of default values
410 * @return array
411 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000412 */
413 function ruri_to_assoc($n = 3, $default = array())
414 {
Barry Mienydd671972010-10-04 16:33:58 +0200415 return $this->_uri_to_assoc($n, $default, 'rsegment');
Derek Allard2067d1a2008-11-13 22:59:24 +0000416 }
417
418 // --------------------------------------------------------------------
419
420 /**
421 * Generate a key value pair from the URI string or Re-routed URI string
422 *
423 * @access private
424 * @param integer the starting segment number
425 * @param array an array of default values
426 * @param string which array we should use
427 * @return array
428 */
429 function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
430 {
431 if ($which == 'segment')
432 {
433 $total_segments = 'total_segments';
434 $segment_array = 'segment_array';
435 }
436 else
437 {
438 $total_segments = 'total_rsegments';
439 $segment_array = 'rsegment_array';
440 }
441
442 if ( ! is_numeric($n))
443 {
444 return $default;
445 }
446
447 if (isset($this->keyval[$n]))
448 {
449 return $this->keyval[$n];
450 }
451
452 if ($this->$total_segments() < $n)
453 {
454 if (count($default) == 0)
455 {
456 return array();
457 }
458
459 $retval = array();
460 foreach ($default as $val)
461 {
462 $retval[$val] = FALSE;
463 }
464 return $retval;
465 }
466
467 $segments = array_slice($this->$segment_array(), ($n - 1));
468
469 $i = 0;
470 $lastval = '';
Derek Jones37f4b9c2011-07-01 17:56:50 -0500471 $retval = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000472 foreach ($segments as $seg)
473 {
474 if ($i % 2)
475 {
476 $retval[$lastval] = $seg;
477 }
478 else
479 {
480 $retval[$seg] = FALSE;
481 $lastval = $seg;
482 }
483
484 $i++;
485 }
486
487 if (count($default) > 0)
488 {
489 foreach ($default as $val)
490 {
491 if ( ! array_key_exists($val, $retval))
492 {
493 $retval[$val] = FALSE;
494 }
495 }
496 }
497
498 // Cache the array for reuse
499 $this->keyval[$n] = $retval;
500 return $retval;
501 }
502
503 // --------------------------------------------------------------------
504
505 /**
506 * Generate a URI string from an associative array
507 *
508 *
509 * @access public
510 * @param array an associative array of key/values
511 * @return array
512 */
513 function assoc_to_uri($array)
514 {
515 $temp = array();
516 foreach ((array)$array as $key => $val)
517 {
518 $temp[] = $key;
519 $temp[] = $val;
520 }
521
522 return implode('/', $temp);
523 }
524
525 // --------------------------------------------------------------------
526
527 /**
528 * Fetch a URI Segment and add a trailing slash
529 *
530 * @access public
531 * @param integer
532 * @param string
533 * @return string
534 */
535 function slash_segment($n, $where = 'trailing')
536 {
537 return $this->_slash_segment($n, $where, 'segment');
538 }
539
540 // --------------------------------------------------------------------
541
542 /**
543 * Fetch a URI Segment and add a trailing slash
544 *
545 * @access public
546 * @param integer
547 * @param string
548 * @return string
549 */
550 function slash_rsegment($n, $where = 'trailing')
551 {
552 return $this->_slash_segment($n, $where, 'rsegment');
553 }
554
555 // --------------------------------------------------------------------
556
557 /**
558 * Fetch a URI Segment and add a trailing slash - helper function
559 *
560 * @access private
561 * @param integer
562 * @param string
563 * @param string
564 * @return string
565 */
566 function _slash_segment($n, $where = 'trailing', $which = 'segment')
567 {
Pascal Krieteebb6f4b2010-11-10 17:09:21 -0500568 $leading = '/';
569 $trailing = '/';
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000570
Derek Allard2067d1a2008-11-13 22:59:24 +0000571 if ($where == 'trailing')
572 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000573 $leading = '';
574 }
575 elseif ($where == 'leading')
576 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000577 $trailing = '';
578 }
Phil Sturgeon48c718c2010-12-30 23:40:02 +0000579
Derek Allard2067d1a2008-11-13 22:59:24 +0000580 return $leading.$this->$which($n).$trailing;
581 }
582
583 // --------------------------------------------------------------------
584
585 /**
586 * Segment Array
587 *
588 * @access public
589 * @return array
590 */
591 function segment_array()
592 {
593 return $this->segments;
594 }
595
596 // --------------------------------------------------------------------
597
598 /**
599 * Routed Segment Array
600 *
601 * @access public
602 * @return array
603 */
604 function rsegment_array()
605 {
606 return $this->rsegments;
607 }
608
609 // --------------------------------------------------------------------
610
611 /**
612 * Total number of segments
613 *
614 * @access public
615 * @return integer
616 */
617 function total_segments()
618 {
619 return count($this->segments);
620 }
621
622 // --------------------------------------------------------------------
623
624 /**
625 * Total number of routed segments
626 *
627 * @access public
628 * @return integer
629 */
630 function total_rsegments()
631 {
632 return count($this->rsegments);
633 }
634
635 // --------------------------------------------------------------------
636
637 /**
638 * Fetch the entire URI string
639 *
640 * @access public
641 * @return string
642 */
643 function uri_string()
644 {
645 return $this->uri_string;
646 }
647
648
649 // --------------------------------------------------------------------
650
651 /**
652 * Fetch the entire Re-routed URI string
653 *
654 * @access public
655 * @return string
656 */
657 function ruri_string()
658 {
Eric Barnesffdc3922011-01-12 09:05:20 -0500659 return '/'.implode('/', $this->rsegment_array());
Derek Allard2067d1a2008-11-13 22:59:24 +0000660 }
661
662}
663// END URI Class
664
665/* End of file URI.php */
Derek Jonesc68dfbf2010-03-02 12:59:23 -0600666/* Location: ./system/core/URI.php */