PageRenderTime 367ms CodeModel.GetById 161ms app.highlight 15ms RepoModel.GetById 186ms app.codeStats 0ms

/halogy/libraries/URI.php

https://bitbucket.org/haloweb/halogy-1.0/
PHP | 586 lines | 258 code | 73 blank | 255 comment | 55 complexity | 0bddc0bfdb8b57f57f290ad4cd36c412 MD5 | raw file
  1<?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
  8 * @author		ExpressionEngine Dev Team
  9 * @copyright	Copyright (c) 2008 - 2009, EllisLab, Inc.
 10 * @license		http://codeigniter.com/user_guide/license.html
 11 * @link		http://codeigniter.com
 12 * @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
 26 * @author		ExpressionEngine Dev Team
 27 * @link		http://codeigniter.com/user_guide/libraries/uri.html
 28 */
 29class CI_URI {
 30
 31	var	$keyval	= array();
 32	var $uri_string;
 33	var $segments		= array();
 34	var $rsegments		= array();
 35
 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	{
 47		$this->config =& load_class('Config');
 48		log_message('debug', "URI Class Initialized");
 49	}
 50
 51
 52	// --------------------------------------------------------------------
 53
 54	/**
 55	 * Get the URI String
 56	 *
 57	 * @access	private
 58	 * @return	string
 59	 */
 60	function _fetch_uri_string()
 61	{
 62		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
 68			if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
 69			{
 70				$this->uri_string = key($_GET);
 71				return;
 72			}
 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');
 77			if (trim($path, '/') != '' && $path != "/".SELF)
 78			{
 79				$this->uri_string = $path;
 80				return;
 81			}
 82
 83			// No PATH_INFO?... What about QUERY_STRING?
 84			$path =  (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
 85			if (trim($path, '/') != '')
 86			{
 87				$this->uri_string = $path;
 88				return;
 89			}
 90
 91			// No QUERY_STRING?... Maybe the ORIG_PATH_INFO variable exists?
 92			$path = str_replace($_SERVER['SCRIPT_NAME'], '', (isset($_SERVER['ORIG_PATH_INFO'])) ? $_SERVER['ORIG_PATH_INFO'] : @getenv('ORIG_PATH_INFO'));
 93			if (trim($path, '/') != '' && $path != "/".SELF)
 94			{
 95				// remove path and script information so we have good URI data
 96				$this->uri_string = $path;
 97				return;
 98			}
 99
100			// We've exhausted all our options...
101			$this->uri_string = '';
102		}
103		else
104		{
105			$uri = strtoupper($this->config->item('uri_protocol'));
106
107			if ($uri == 'REQUEST_URI')
108			{
109				$this->uri_string = $this->_parse_request_uri();
110				return;
111			}
112
113			$this->uri_string = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);
114		}
115
116		// If the URI contains only a slash we'll kill it
117		if ($this->uri_string == '/')
118		{
119			$this->uri_string = '';
120		}
121	}
122
123	// --------------------------------------------------------------------
124
125	/**
126	 * Parse the REQUEST_URI
127	 *
128	 * Due to the way REQUEST_URI works it usually contains path info
129	 * that makes it unusable as URI data.  We'll trim off the unnecessary
130	 * data, hopefully arriving at a valid URI that we can use.
131	 *
132	 * @access	private
133	 * @return	string
134	 */
135	function _parse_request_uri()
136	{
137		if ( ! isset($_SERVER['REQUEST_URI']) OR $_SERVER['REQUEST_URI'] == '')
138		{
139			return '';
140		}
141
142		$request_uri = preg_replace("|/(.*)|", "\\1", str_replace("\\", "/", $_SERVER['REQUEST_URI']));
143
144		if ($request_uri == '' OR $request_uri == SELF)
145		{
146			return '';
147		}
148
149		$fc_path = FCPATH.SELF;
150		if (strpos($request_uri, '?') !== FALSE)
151		{
152			$fc_path .= '?';
153		}
154
155		$parsed_uri = explode("/", $request_uri);
156
157		$i = 0;
158		foreach(explode("/", $fc_path) as $segment)
159		{
160			if (isset($parsed_uri[$i]) && $segment == $parsed_uri[$i])
161			{
162				$i++;
163			}
164		}
165
166		$parsed_uri = implode("/", array_slice($parsed_uri, $i));
167
168		if ($parsed_uri != '')
169		{
170			$parsed_uri = '/'.$parsed_uri;
171		}
172
173		return $parsed_uri;
174	}
175
176	// --------------------------------------------------------------------
177
178	/**
179	 * Filter segments for malicious characters
180	 *
181	 * @access	private
182	 * @param	string
183	 * @return	string
184	 */
185	function _filter_uri($str)
186	{
187		if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
188		{
189			// preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
190			// compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
191			if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $str))
192			{
193				show_error('The URI you submitted has disallowed characters.', 400);
194			}
195		}
196
197		// Convert programatic characters to entities
198		$bad	= array('$', 		'(', 		')',	 	'%28', 		'%29');
199		$good	= array('&#36;',	'&#40;',	'&#41;',	'&#40;',	'&#41;');
200
201		return str_replace($bad, $good, $str);
202	}
203
204	// --------------------------------------------------------------------
205
206	/**
207	 * Remove the suffix from the URL if needed
208	 *
209	 * @access	private
210	 * @return	void
211	 */
212	function _remove_url_suffix()
213	{
214		if  ($this->config->item('url_suffix') != "")
215		{
216			$this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string);
217		}
218	}
219
220	// --------------------------------------------------------------------
221
222	/**
223	 * Explode the URI Segments. The individual segments will
224	 * be stored in the $this->segments array.
225	 *
226	 * @access	private
227	 * @return	void
228	 */
229	function _explode_segments()
230	{
231		foreach(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
232		{
233			// Filter segments for security
234			$val = trim($this->_filter_uri($val));
235
236			if ($val != '')
237			{
238				$this->segments[] = $val;
239			}
240		}
241	}
242
243	// --------------------------------------------------------------------
244	/**
245	 * Re-index Segments
246	 *
247	 * This function re-indexes the $this->segment array so that it
248	 * starts at 1 rather than 0.  Doing so makes it simpler to
249	 * use functions like $this->uri->segment(n) since there is
250	 * a 1:1 relationship between the segment array and the actual segments.
251	 *
252	 * @access	private
253	 * @return	void
254	 */
255	function _reindex_segments()
256	{
257		array_unshift($this->segments, NULL);
258		array_unshift($this->rsegments, NULL);
259		unset($this->segments[0]);
260		unset($this->rsegments[0]);
261	}
262
263	// --------------------------------------------------------------------
264
265	/**
266	 * Fetch a URI Segment
267	 *
268	 * This function returns the URI segment based on the number provided.
269	 *
270	 * @access	public
271	 * @param	integer
272	 * @param	bool
273	 * @return	string
274	 */
275	function segment($n, $no_result = FALSE)
276	{
277		return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];
278	}
279
280	// --------------------------------------------------------------------
281
282	/**
283	 * Fetch a URI "routed" Segment
284	 *
285	 * This function returns the re-routed URI segment (assuming routing rules are used)
286	 * based on the number provided.  If there is no routing this function returns the
287	 * same result as $this->segment()
288	 *
289	 * @access	public
290	 * @param	integer
291	 * @param	bool
292	 * @return	string
293	 */
294	function rsegment($n, $no_result = FALSE)
295	{
296		return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];
297	}
298
299	// --------------------------------------------------------------------
300
301	/**
302	 * Generate a key value pair from the URI string
303	 *
304	 * This function generates and associative array of URI data starting
305	 * at the supplied segment. For example, if this is your URI:
306	 *
307	 *	example.com/user/search/name/joe/location/UK/gender/male
308	 *
309	 * You can use this function to generate an array with this prototype:
310	 *
311	 * array (
312	 *			name => joe
313	 *			location => UK
314	 *			gender => male
315	 *		 )
316	 *
317	 * @access	public
318	 * @param	integer	the starting segment number
319	 * @param	array	an array of default values
320	 * @return	array
321	 */
322	function uri_to_assoc($n = 3, $default = array())
323	{
324	 	return $this->_uri_to_assoc($n, $default, 'segment');
325	}
326	/**
327	 * Identical to above only it uses the re-routed segment array
328	 *
329	 */
330	function ruri_to_assoc($n = 3, $default = array())
331	{
332	 	return $this->_uri_to_assoc($n, $default, 'rsegment');
333	}
334
335	// --------------------------------------------------------------------
336
337	/**
338	 * Generate a key value pair from the URI string or Re-routed URI string
339	 *
340	 * @access	private
341	 * @param	integer	the starting segment number
342	 * @param	array	an array of default values
343	 * @param	string	which array we should use
344	 * @return	array
345	 */
346	function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
347	{
348		if ($which == 'segment')
349		{
350			$total_segments = 'total_segments';
351			$segment_array = 'segment_array';
352		}
353		else
354		{
355			$total_segments = 'total_rsegments';
356			$segment_array = 'rsegment_array';
357		}
358
359		if ( ! is_numeric($n))
360		{
361			return $default;
362		}
363
364		if (isset($this->keyval[$n]))
365		{
366			return $this->keyval[$n];
367		}
368
369		if ($this->$total_segments() < $n)
370		{
371			if (count($default) == 0)
372			{
373				return array();
374			}
375
376			$retval = array();
377			foreach ($default as $val)
378			{
379				$retval[$val] = FALSE;
380			}
381			return $retval;
382		}
383
384		$segments = array_slice($this->$segment_array(), ($n - 1));
385
386		$i = 0;
387		$lastval = '';
388		$retval  = array();
389		foreach ($segments as $seg)
390		{
391			if ($i % 2)
392			{
393				$retval[$lastval] = $seg;
394			}
395			else
396			{
397				$retval[$seg] = FALSE;
398				$lastval = $seg;
399			}
400
401			$i++;
402		}
403
404		if (count($default) > 0)
405		{
406			foreach ($default as $val)
407			{
408				if ( ! array_key_exists($val, $retval))
409				{
410					$retval[$val] = FALSE;
411				}
412			}
413		}
414
415		// Cache the array for reuse
416		$this->keyval[$n] = $retval;
417		return $retval;
418	}
419
420	// --------------------------------------------------------------------
421
422	/**
423	 * Generate a URI string from an associative array
424	 *
425	 *
426	 * @access	public
427	 * @param	array	an associative array of key/values
428	 * @return	array
429	 */
430	function assoc_to_uri($array)
431	{
432		$temp = array();
433		foreach ((array)$array as $key => $val)
434		{
435			$temp[] = $key;
436			$temp[] = $val;
437		}
438
439		return implode('/', $temp);
440	}
441
442	// --------------------------------------------------------------------
443
444	/**
445	 * Fetch a URI Segment and add a trailing slash
446	 *
447	 * @access	public
448	 * @param	integer
449	 * @param	string
450	 * @return	string
451	 */
452	function slash_segment($n, $where = 'trailing')
453	{
454		return $this->_slash_segment($n, $where, 'segment');
455	}
456
457	// --------------------------------------------------------------------
458
459	/**
460	 * Fetch a URI Segment and add a trailing slash
461	 *
462	 * @access	public
463	 * @param	integer
464	 * @param	string
465	 * @return	string
466	 */
467	function slash_rsegment($n, $where = 'trailing')
468	{
469		return $this->_slash_segment($n, $where, 'rsegment');
470	}
471
472	// --------------------------------------------------------------------
473
474	/**
475	 * Fetch a URI Segment and add a trailing slash - helper function
476	 *
477	 * @access	private
478	 * @param	integer
479	 * @param	string
480	 * @param	string
481	 * @return	string
482	 */
483	function _slash_segment($n, $where = 'trailing', $which = 'segment')
484	{
485		if ($where == 'trailing')
486		{
487			$trailing	= '/';
488			$leading	= '';
489		}
490		elseif ($where == 'leading')
491		{
492			$leading	= '/';
493			$trailing	= '';
494		}
495		else
496		{
497			$leading	= '/';
498			$trailing	= '/';
499		}
500		return $leading.$this->$which($n).$trailing;
501	}
502
503	// --------------------------------------------------------------------
504
505	/**
506	 * Segment Array
507	 *
508	 * @access	public
509	 * @return	array
510	 */
511	function segment_array()
512	{
513		return $this->segments;
514	}
515
516	// --------------------------------------------------------------------
517
518	/**
519	 * Routed Segment Array
520	 *
521	 * @access	public
522	 * @return	array
523	 */
524	function rsegment_array()
525	{
526		return $this->rsegments;
527	}
528
529	// --------------------------------------------------------------------
530
531	/**
532	 * Total number of segments
533	 *
534	 * @access	public
535	 * @return	integer
536	 */
537	function total_segments()
538	{
539		return count($this->segments);
540	}
541
542	// --------------------------------------------------------------------
543
544	/**
545	 * Total number of routed segments
546	 *
547	 * @access	public
548	 * @return	integer
549	 */
550	function total_rsegments()
551	{
552		return count($this->rsegments);
553	}
554
555	// --------------------------------------------------------------------
556
557	/**
558	 * Fetch the entire URI string
559	 *
560	 * @access	public
561	 * @return	string
562	 */
563	function uri_string()
564	{
565		return $this->uri_string;
566	}
567
568
569	// --------------------------------------------------------------------
570
571	/**
572	 * Fetch the entire Re-routed URI string
573	 *
574	 * @access	public
575	 * @return	string
576	 */
577	function ruri_string()
578	{
579		return '/'.implode('/', $this->rsegment_array()).'/';
580	}
581
582}
583// END URI Class
584
585/* End of file URI.php */
586/* Location: ./system/libraries/URI.php */