blob: d10a5daeb40e2add6a29e3f1ad596fce7a2de12c [file] [log] [blame]
Derek Allardd2df9bc2007-04-15 17:41:17 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
Derek Allard3d879d52008-01-18 19:41:32 +00008 * @author ExpressionEngine Dev Team
Derek Allardd2df9bc2007-04-15 17:41:17 +00009 * @copyright Copyright (c) 2006, EllisLab, Inc.
Derek Jones7a9193a2008-01-21 18:39:20 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
Derek Allardd2df9bc2007-04-15 17:41:17 +000012 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * URI Class
20 *
21 * Parses URIs and determines routing
22 *
23 * @package CodeIgniter
24 * @subpackage Libraries
25 * @category URI
Derek Allard3d879d52008-01-18 19:41:32 +000026 * @author ExpressionEngine Dev Team
Derek Jones7a9193a2008-01-21 18:39:20 +000027 * @link http://codeigniter.com/user_guide/libraries/uri.html
Derek Allardd2df9bc2007-04-15 17:41:17 +000028 */
29class CI_URI {
30
Derek Allardd2df9bc2007-04-15 17:41:17 +000031 var $keyval = array();
Rick Ellis30b40152007-07-20 00:01:13 +000032 var $uri_string;
33 var $segments = array();
34 var $rsegments = array();
Derek Allardd2df9bc2007-04-15 17:41:17 +000035
36 /**
37 * Constructor
38 *
39 * Simply globalizes the $RTR object. The front
40 * loads the Router class early on so it's not available
41 * normally as other classes are.
42 *
43 * @access public
44 */
45 function CI_URI()
46 {
Rick Ellis30b40152007-07-20 00:01:13 +000047 $this->config =& load_class('Config');
Derek Allardd2df9bc2007-04-15 17:41:17 +000048 log_message('debug', "URI Class Initialized");
49 }
50
Rick Ellis30b40152007-07-20 00:01:13 +000051
52 // --------------------------------------------------------------------
53
54 /**
55 * Get the URI String
56 *
57 * @access private
58 * @return string
59 */
60 function _fetch_uri_string()
Rick Ellisde2623c2007-07-21 18:28:24 +000061 {
Rick Ellis30b40152007-07-20 00:01:13 +000062 if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
63 {
64 // If the URL has a question mark then it's simplest to just
65 // build the URI string from the zero index of the $_GET array.
66 // This avoids having to deal with $_SERVER variables, which
67 // can be unreliable in some environments
Derek Jones27b50052008-04-14 14:03:04 +000068 if (is_array($_GET) AND count($_GET) == 1 AND trim(key($_GET), '/') != '')
Rick Ellis30b40152007-07-20 00:01:13 +000069 {
Derek Jones27126102008-01-29 23:43:09 +000070 $this->uri_string = key($_GET);
Rick Ellisde2623c2007-07-21 18:28:24 +000071 return;
Rick Ellis30b40152007-07-20 00:01:13 +000072 }
73
74 // Is there a PATH_INFO variable?
75 // Note: some servers seem to have trouble with getenv() so we'll test it two ways
76 $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
Derek Jones27b50052008-04-14 14:03:04 +000077 if (trim($path, '/') != '' AND $path != "/".SELF)
Rick Ellis30b40152007-07-20 00:01:13 +000078 {
79 $this->uri_string = $path;
Rick Ellisde2623c2007-07-21 18:28:24 +000080 return;
Rick Ellis30b40152007-07-20 00:01:13 +000081 }
82
83 // No PATH_INFO?... What about QUERY_STRING?
84 $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
Derek Jones27b50052008-04-14 14:03:04 +000085 if (trim($path, '/') != '')
Rick Ellis30b40152007-07-20 00:01:13 +000086 {
87 $this->uri_string = $path;
Rick Ellisde2623c2007-07-21 18:28:24 +000088 return;
Rick Ellis30b40152007-07-20 00:01:13 +000089 }
90
91 // No QUERY_STRING?... Maybe the ORIG_PATH_INFO variable exists?
92 $path = (isset($_SERVER['ORIG_PATH_INFO'])) ? $_SERVER['ORIG_PATH_INFO'] : @getenv('ORIG_PATH_INFO');
Derek Jones27b50052008-04-14 14:03:04 +000093 if (trim($path, '/') != '' AND $path != "/".SELF)
Rick Ellis30b40152007-07-20 00:01:13 +000094 {
95 $this->uri_string = $path;
Rick Ellisde2623c2007-07-21 18:28:24 +000096 return;
Rick Ellis30b40152007-07-20 00:01:13 +000097 }
98
99 // We've exhausted all our options...
100 $this->uri_string = '';
101 }
102 else
103 {
104 $uri = strtoupper($this->config->item('uri_protocol'));
105
106 if ($uri == 'REQUEST_URI')
107 {
108 $this->uri_string = $this->_parse_request_uri();
Rick Ellisde2623c2007-07-21 18:28:24 +0000109 return;
Rick Ellis30b40152007-07-20 00:01:13 +0000110 }
111
112 $this->uri_string = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);
113 }
114
115 // If the URI contains only a slash we'll kill it
116 if ($this->uri_string == '/')
117 {
118 $this->uri_string = '';
119 }
120 }
Rick Ellisde2623c2007-07-21 18:28:24 +0000121
Rick Ellis30b40152007-07-20 00:01:13 +0000122 // --------------------------------------------------------------------
123
124 /**
125 * Parse the REQUEST_URI
126 *
127 * Due to the way REQUEST_URI works it usually contains path info
128 * that makes it unusable as URI data. We'll trim off the unnecessary
129 * data, hopefully arriving at a valid URI that we can use.
130 *
131 * @access private
132 * @return string
133 */
134 function _parse_request_uri()
135 {
136 if ( ! isset($_SERVER['REQUEST_URI']) OR $_SERVER['REQUEST_URI'] == '')
137 {
138 return '';
139 }
140
141 $request_uri = preg_replace("|/(.*)|", "\\1", str_replace("\\", "/", $_SERVER['REQUEST_URI']));
142
143 if ($request_uri == '' OR $request_uri == SELF)
144 {
145 return '';
146 }
147
148 $fc_path = FCPATH;
149 if (strpos($request_uri, '?') !== FALSE)
150 {
151 $fc_path .= '?';
152 }
153
154 $parsed_uri = explode("/", $request_uri);
155
156 $i = 0;
157 foreach(explode("/", $fc_path) as $segment)
158 {
159 if (isset($parsed_uri[$i]) AND $segment == $parsed_uri[$i])
160 {
161 $i++;
162 }
163 }
164
165 $parsed_uri = implode("/", array_slice($parsed_uri, $i));
166
167 if ($parsed_uri != '')
168 {
169 $parsed_uri = '/'.$parsed_uri;
170 }
171
172 return $parsed_uri;
173 }
174
175 // --------------------------------------------------------------------
176
177 /**
178 * Filter segments for malicious characters
179 *
180 * @access private
181 * @param string
182 * @return string
183 */
184 function _filter_uri($str)
185 {
Derek Jones500b9d32008-01-19 17:12:31 +0000186 if ($str != '' AND $this->config->item('permitted_uri_chars') != '')
Rick Ellis30b40152007-07-20 00:01:13 +0000187 {
188 if ( ! preg_match("|^[".preg_quote($this->config->item('permitted_uri_chars'))."]+$|i", $str))
189 {
190 exit('The URI you submitted has disallowed characters.');
191 }
Derek Jones500b9d32008-01-19 17:12:31 +0000192 }
193
194 return $str;
Rick Ellis30b40152007-07-20 00:01:13 +0000195 }
196
197 // --------------------------------------------------------------------
198
199 /**
200 * Remove the suffix from the URL if needed
201 *
202 * @access private
203 * @return void
204 */
205 function _remove_url_suffix()
206 {
207 if ($this->config->item('url_suffix') != "")
208 {
209 $this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string);
210 }
211 }
212
213 // --------------------------------------------------------------------
214
215 /**
216 * Explode the URI Segments. The individual segments will
217 * be stored in the $this->segments array.
218 *
219 * @access private
220 * @return void
221 */
222 function _explode_segments()
223 {
224 foreach(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
225 {
226 // Filter segments for security
227 $val = trim($this->_filter_uri($val));
228
229 if ($val != '')
230 $this->segments[] = $val;
231 }
232 }
233
234 // --------------------------------------------------------------------
235 /**
236 * Re-index Segments
237 *
238 * This function re-indexes the $this->segment array so that it
239 * starts at 1 rather then 0. Doing so makes it simpler to
240 * use functions like $this->uri->segment(n) since there is
241 * a 1:1 relationship between the segment array and the actual segments.
242 *
243 * @access private
244 * @return void
245 */
246 function _reindex_segments()
247 {
Rick Ellis30b40152007-07-20 00:01:13 +0000248 $i = 1;
Derek Jonesb0697892008-02-13 03:38:39 +0000249
Rick Ellis30b40152007-07-20 00:01:13 +0000250 foreach ($this->segments as $val)
251 {
252 $this->segments[$i++] = $val;
253 }
Derek Jonesb0697892008-02-13 03:38:39 +0000254
Rick Ellis30b40152007-07-20 00:01:13 +0000255 unset($this->segments[0]);
256
Derek Jonesb0697892008-02-13 03:38:39 +0000257 $i = 1;
258
259 foreach ($this->rsegments as $val)
Rick Ellis30b40152007-07-20 00:01:13 +0000260 {
Derek Jonesb0697892008-02-13 03:38:39 +0000261 $this->rsegments[$i++] = $val;
Rick Ellis30b40152007-07-20 00:01:13 +0000262 }
Derek Jonesb0697892008-02-13 03:38:39 +0000263
264 unset($this->rsegments[0]);
Rick Ellis30b40152007-07-20 00:01:13 +0000265 }
266
Derek Allardd2df9bc2007-04-15 17:41:17 +0000267 // --------------------------------------------------------------------
268
269 /**
270 * Fetch a URI Segment
271 *
272 * This function returns the URI segment based on the number provided.
273 *
274 * @access public
275 * @param integer
276 * @param bool
277 * @return string
278 */
279 function segment($n, $no_result = FALSE)
280 {
Rick Ellis30b40152007-07-20 00:01:13 +0000281 return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];
Derek Allardd2df9bc2007-04-15 17:41:17 +0000282 }
283
284 // --------------------------------------------------------------------
285
286 /**
287 * Fetch a URI "routed" Segment
288 *
289 * This function returns the re-routed URI segment (assuming routing rules are used)
290 * based on the number provided. If there is no routing this function returns the
291 * same result as $this->segment()
292 *
293 * @access public
294 * @param integer
295 * @param bool
296 * @return string
297 */
298 function rsegment($n, $no_result = FALSE)
299 {
Rick Ellis30b40152007-07-20 00:01:13 +0000300 return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];
Derek Allardd2df9bc2007-04-15 17:41:17 +0000301 }
302
303 // --------------------------------------------------------------------
304
305 /**
306 * Generate a key value pair from the URI string
307 *
308 * This function generates and associative array of URI data starting
309 * at the supplied segment. For example, if this is your URI:
310 *
311 * www.your-site.com/user/search/name/joe/location/UK/gender/male
312 *
313 * You can use this function to generate an array with this prototype:
314 *
315 * array (
316 * name => joe
317 * location => UK
318 * gender => male
319 * )
320 *
321 * @access public
322 * @param integer the starting segment number
323 * @param array an array of default values
324 * @return array
325 */
326 function uri_to_assoc($n = 3, $default = array())
327 {
328 return $this->_uri_to_assoc($n, $default, 'segment');
329 }
330 /**
331 * Identical to above only it uses the re-routed segment array
332 *
333 */
334 function ruri_to_assoc($n = 3, $default = array())
335 {
336 return $this->_uri_to_assoc($n, $default, 'rsegment');
337 }
338
339 // --------------------------------------------------------------------
340
341 /**
342 * Generate a key value pair from the URI string or Re-routed URI string
343 *
344 * @access private
345 * @param integer the starting segment number
346 * @param array an array of default values
347 * @param string which array we should use
348 * @return array
349 */
350 function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
351 {
352 if ($which == 'segment')
353 {
354 $total_segments = 'total_segments';
355 $segment_array = 'segment_array';
356 }
357 else
358 {
359 $total_segments = 'total_rsegments';
360 $segment_array = 'rsegment_array';
361 }
362
363 if ( ! is_numeric($n))
364 {
365 return $default;
366 }
367
368 if (isset($this->keyval[$n]))
369 {
370 return $this->keyval[$n];
371 }
372
373 if ($this->$total_segments() < $n)
374 {
375 if (count($default) == 0)
376 {
377 return array();
378 }
379
380 $retval = array();
381 foreach ($default as $val)
382 {
383 $retval[$val] = FALSE;
384 }
385 return $retval;
386 }
387
388 $segments = array_slice($this->$segment_array(), ($n - 1));
389
390 $i = 0;
391 $lastval = '';
392 $retval = array();
393 foreach ($segments as $seg)
394 {
395 if ($i % 2)
396 {
397 $retval[$lastval] = $seg;
398 }
399 else
400 {
401 $retval[$seg] = FALSE;
402 $lastval = $seg;
403 }
404
405 $i++;
406 }
407
408 if (count($default) > 0)
409 {
410 foreach ($default as $val)
411 {
412 if ( ! array_key_exists($val, $retval))
413 {
414 $retval[$val] = FALSE;
415 }
416 }
417 }
418
419 // Cache the array for reuse
420 $this->keyval[$n] = $retval;
421 return $retval;
422 }
423
Rick Ellis30b40152007-07-20 00:01:13 +0000424 // --------------------------------------------------------------------
425
Derek Allardd2df9bc2007-04-15 17:41:17 +0000426 /**
427 * Generate a URI string from an associative array
428 *
429 *
430 * @access public
431 * @param array an associative array of key/values
432 * @return array
Rick Ellis30b40152007-07-20 00:01:13 +0000433 */
434 function assoc_to_uri($array)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000435 {
436 $temp = array();
437 foreach ((array)$array as $key => $val)
438 {
439 $temp[] = $key;
440 $temp[] = $val;
441 }
442
443 return implode('/', $temp);
444 }
445
446 // --------------------------------------------------------------------
447
448 /**
449 * Fetch a URI Segment and add a trailing slash
450 *
451 * @access public
452 * @param integer
453 * @param string
454 * @return string
455 */
456 function slash_segment($n, $where = 'trailing')
457 {
458 return $this->_slash_segment($n, $where, 'segment');
459 }
460
461 // --------------------------------------------------------------------
462
463 /**
464 * Fetch a URI Segment and add a trailing slash
465 *
466 * @access public
467 * @param integer
468 * @param string
469 * @return string
470 */
471 function slash_rsegment($n, $where = 'trailing')
472 {
473 return $this->_slash_segment($n, $where, 'rsegment');
474 }
475
476 // --------------------------------------------------------------------
477
478 /**
479 * Fetch a URI Segment and add a trailing slash - helper function
480 *
481 * @access private
482 * @param integer
483 * @param string
484 * @param string
485 * @return string
486 */
487 function _slash_segment($n, $where = 'trailing', $which = 'segment')
488 {
489 if ($where == 'trailing')
490 {
491 $trailing = '/';
492 $leading = '';
493 }
494 elseif ($where == 'leading')
495 {
496 $leading = '/';
497 $trailing = '';
498 }
499 else
500 {
501 $leading = '/';
502 $trailing = '/';
503 }
504 return $leading.$this->$which($n).$trailing;
505 }
506
507 // --------------------------------------------------------------------
508
509 /**
510 * Segment Array
511 *
512 * @access public
513 * @return array
514 */
515 function segment_array()
516 {
Rick Ellis30b40152007-07-20 00:01:13 +0000517 return $this->segments;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000518 }
519
520 // --------------------------------------------------------------------
521
522 /**
523 * Routed Segment Array
524 *
525 * @access public
526 * @return array
527 */
528 function rsegment_array()
529 {
Rick Ellis30b40152007-07-20 00:01:13 +0000530 return $this->rsegments;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000531 }
532
533 // --------------------------------------------------------------------
534
535 /**
536 * Total number of segments
537 *
538 * @access public
539 * @return integer
540 */
541 function total_segments()
542 {
Rick Ellis30b40152007-07-20 00:01:13 +0000543 return count($this->segments);
Derek Allardd2df9bc2007-04-15 17:41:17 +0000544 }
545
546 // --------------------------------------------------------------------
547
548 /**
549 * Total number of routed segments
550 *
551 * @access public
552 * @return integer
553 */
554 function total_rsegments()
555 {
Rick Ellis30b40152007-07-20 00:01:13 +0000556 return count($this->rsegments);
Derek Allardd2df9bc2007-04-15 17:41:17 +0000557 }
558
559 // --------------------------------------------------------------------
560
561 /**
562 * Fetch the entire URI string
563 *
564 * @access public
565 * @return string
566 */
567 function uri_string()
568 {
Rick Ellis30b40152007-07-20 00:01:13 +0000569 return $this->uri_string;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000570 }
571
572
573 // --------------------------------------------------------------------
574
575 /**
576 * Fetch the entire Re-routed URI string
577 *
578 * @access public
579 * @return string
580 */
581 function ruri_string()
582 {
583 return '/'.implode('/', $this->rsegment_array()).'/';
584 }
585
586}
587// END URI Class
adminb0dd10f2006-08-25 17:25:49 +0000588?>