PageRenderTime 76ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/system/libraries/URI.php

https://github.com/mkhairul/Presta
PHP | 591 lines | 264 code | 77 blank | 250 comment | 47 complexity | f3313f7603d6382e4f5a56cb707b8242 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) 2006, 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. * URI Class
  18. *
  19. * Parses URIs and determines routing
  20. *
  21. * @package CodeIgniter
  22. * @subpackage Libraries
  23. * @category URI
  24. * @author ExpressionEngine Dev Team
  25. * @link http://codeigniter.com/user_guide/libraries/uri.html
  26. */
  27. class CI_URI {
  28. var $keyval = array();
  29. var $uri_string;
  30. var $segments = array();
  31. var $rsegments = array();
  32. /**
  33. * Constructor
  34. *
  35. * Simply globalizes the $RTR object. The front
  36. * loads the Router class early on so it's not available
  37. * normally as other classes are.
  38. *
  39. * @access public
  40. */
  41. function CI_URI()
  42. {
  43. $this->config =& load_class('Config');
  44. log_message('debug', "URI Class Initialized");
  45. }
  46. // --------------------------------------------------------------------
  47. /**
  48. * Get the URI String
  49. *
  50. * @access private
  51. * @return string
  52. */
  53. function _fetch_uri_string()
  54. {
  55. if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
  56. {
  57. // If the URL has a question mark then it's simplest to just
  58. // build the URI string from the zero index of the $_GET array.
  59. // This avoids having to deal with $_SERVER variables, which
  60. // can be unreliable in some environments
  61. if (is_array($_GET) AND count($_GET) == 1 AND trim(key($_GET), '/') != '')
  62. {
  63. $this->uri_string = key($_GET);
  64. return;
  65. }
  66. // Is there a PATH_INFO variable?
  67. // Note: some servers seem to have trouble with getenv() so we'll test it two ways
  68. $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
  69. if (trim($path, '/') != '' AND $path != "/".SELF)
  70. {
  71. $this->uri_string = $path;
  72. return;
  73. }
  74. // No PATH_INFO?... What about QUERY_STRING?
  75. $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
  76. if (trim($path, '/') != '')
  77. {
  78. $this->uri_string = $path;
  79. return;
  80. }
  81. // No QUERY_STRING?... Maybe the ORIG_PATH_INFO variable exists?
  82. $path = (isset($_SERVER['ORIG_PATH_INFO'])) ? $_SERVER['ORIG_PATH_INFO'] : @getenv('ORIG_PATH_INFO');
  83. if (trim($path, '/') != '' AND $path != "/".SELF)
  84. {
  85. // remove path and script information so we have good URI data
  86. $this->uri_string = str_replace($_SERVER['SCRIPT_NAME'], '', $path);
  87. return;
  88. }
  89. // We've exhausted all our options...
  90. $this->uri_string = '';
  91. }
  92. else
  93. {
  94. $uri = strtoupper($this->config->item('uri_protocol'));
  95. if ($uri == 'REQUEST_URI')
  96. {
  97. $this->uri_string = $this->_parse_request_uri();
  98. return;
  99. }
  100. $this->uri_string = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);
  101. }
  102. // If the URI contains only a slash we'll kill it
  103. if ($this->uri_string == '/')
  104. {
  105. $this->uri_string = '';
  106. }
  107. }
  108. // --------------------------------------------------------------------
  109. /**
  110. * Parse the REQUEST_URI
  111. *
  112. * Due to the way REQUEST_URI works it usually contains path info
  113. * that makes it unusable as URI data. We'll trim off the unnecessary
  114. * data, hopefully arriving at a valid URI that we can use.
  115. *
  116. * @access private
  117. * @return string
  118. */
  119. function _parse_request_uri()
  120. {
  121. if ( ! isset($_SERVER['REQUEST_URI']) OR $_SERVER['REQUEST_URI'] == '')
  122. {
  123. return '';
  124. }
  125. $request_uri = preg_replace("|/(.*)|", "\\1", str_replace("\\", "/", $_SERVER['REQUEST_URI']));
  126. if ($request_uri == '' OR $request_uri == SELF)
  127. {
  128. return '';
  129. }
  130. $fc_path = FCPATH;
  131. if (strpos($request_uri, '?') !== FALSE)
  132. {
  133. $fc_path .= '?';
  134. }
  135. $parsed_uri = explode("/", $request_uri);
  136. $i = 0;
  137. foreach(explode("/", $fc_path) as $segment)
  138. {
  139. if (isset($parsed_uri[$i]) AND $segment == $parsed_uri[$i])
  140. {
  141. $i++;
  142. }
  143. }
  144. $parsed_uri = implode("/", array_slice($parsed_uri, $i));
  145. if ($parsed_uri != '')
  146. {
  147. $parsed_uri = '/'.$parsed_uri;
  148. }
  149. return $parsed_uri;
  150. }
  151. // --------------------------------------------------------------------
  152. /**
  153. * Filter segments for malicious characters
  154. *
  155. * @access private
  156. * @param string
  157. * @return string
  158. */
  159. function _filter_uri($str)
  160. {
  161. if ($str != '' AND $this->config->item('permitted_uri_chars') != '')
  162. {
  163. if ( ! preg_match("|^[".($this->config->item('permitted_uri_chars'))."]+$|i", rawurlencode($str)))
  164. {
  165. exit('The URI you submitted has disallowed characters.');
  166. }
  167. }
  168. return $str;
  169. }
  170. // --------------------------------------------------------------------
  171. /**
  172. * Remove the suffix from the URL if needed
  173. *
  174. * @access private
  175. * @return void
  176. */
  177. function _remove_url_suffix()
  178. {
  179. if ($this->config->item('url_suffix') != "")
  180. {
  181. $this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string);
  182. }
  183. }
  184. // --------------------------------------------------------------------
  185. /**
  186. * Explode the URI Segments. The individual segments will
  187. * be stored in the $this->segments array.
  188. *
  189. * @access private
  190. * @return void
  191. */
  192. function _explode_segments()
  193. {
  194. foreach(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
  195. {
  196. // Filter segments for security
  197. $val = trim($this->_filter_uri($val));
  198. if ($val != '')
  199. $this->segments[] = $val;
  200. }
  201. }
  202. // --------------------------------------------------------------------
  203. /**
  204. * Re-index Segments
  205. *
  206. * This function re-indexes the $this->segment array so that it
  207. * starts at 1 rather then 0. Doing so makes it simpler to
  208. * use functions like $this->uri->segment(n) since there is
  209. * a 1:1 relationship between the segment array and the actual segments.
  210. *
  211. * @access private
  212. * @return void
  213. */
  214. function _reindex_segments()
  215. {
  216. $i = 1;
  217. foreach ($this->segments as $val)
  218. {
  219. $this->segments[$i++] = $val;
  220. }
  221. unset($this->segments[0]);
  222. $i = 1;
  223. foreach ($this->rsegments as $val)
  224. {
  225. $this->rsegments[$i++] = $val;
  226. }
  227. unset($this->rsegments[0]);
  228. }
  229. // --------------------------------------------------------------------
  230. /**
  231. * Fetch a URI Segment
  232. *
  233. * This function returns the URI segment based on the number provided.
  234. *
  235. * @access public
  236. * @param integer
  237. * @param bool
  238. * @return string
  239. */
  240. function segment($n, $no_result = FALSE)
  241. {
  242. return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];
  243. }
  244. // --------------------------------------------------------------------
  245. /**
  246. * Fetch a URI "routed" Segment
  247. *
  248. * This function returns the re-routed URI segment (assuming routing rules are used)
  249. * based on the number provided. If there is no routing this function returns the
  250. * same result as $this->segment()
  251. *
  252. * @access public
  253. * @param integer
  254. * @param bool
  255. * @return string
  256. */
  257. function rsegment($n, $no_result = FALSE)
  258. {
  259. return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];
  260. }
  261. // --------------------------------------------------------------------
  262. /**
  263. * Generate a key value pair from the URI string
  264. *
  265. * This function generates and associative array of URI data starting
  266. * at the supplied segment. For example, if this is your URI:
  267. *
  268. * www.your-site.com/user/search/name/joe/location/UK/gender/male
  269. *
  270. * You can use this function to generate an array with this prototype:
  271. *
  272. * array (
  273. * name => joe
  274. * location => UK
  275. * gender => male
  276. * )
  277. *
  278. * @access public
  279. * @param integer the starting segment number
  280. * @param array an array of default values
  281. * @return array
  282. */
  283. function uri_to_assoc($n = 3, $default = array())
  284. {
  285. return $this->_uri_to_assoc($n, $default, 'segment');
  286. }
  287. /**
  288. * Identical to above only it uses the re-routed segment array
  289. *
  290. */
  291. function ruri_to_assoc($n = 3, $default = array())
  292. {
  293. return $this->_uri_to_assoc($n, $default, 'rsegment');
  294. }
  295. // --------------------------------------------------------------------
  296. /**
  297. * Generate a key value pair from the URI string or Re-routed URI string
  298. *
  299. * @access private
  300. * @param integer the starting segment number
  301. * @param array an array of default values
  302. * @param string which array we should use
  303. * @return array
  304. */
  305. function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
  306. {
  307. if ($which == 'segment')
  308. {
  309. $total_segments = 'total_segments';
  310. $segment_array = 'segment_array';
  311. }
  312. else
  313. {
  314. $total_segments = 'total_rsegments';
  315. $segment_array = 'rsegment_array';
  316. }
  317. if ( ! is_numeric($n))
  318. {
  319. return $default;
  320. }
  321. if (isset($this->keyval[$n]))
  322. {
  323. return $this->keyval[$n];
  324. }
  325. if ($this->$total_segments() < $n)
  326. {
  327. if (count($default) == 0)
  328. {
  329. return array();
  330. }
  331. $retval = array();
  332. foreach ($default as $val)
  333. {
  334. $retval[$val] = FALSE;
  335. }
  336. return $retval;
  337. }
  338. $segments = array_slice($this->$segment_array(), ($n - 1));
  339. $i = 0;
  340. $lastval = '';
  341. $retval = array();
  342. foreach ($segments as $seg)
  343. {
  344. if ($i % 2)
  345. {
  346. $retval[$lastval] = $seg;
  347. }
  348. else
  349. {
  350. $retval[$seg] = FALSE;
  351. $lastval = $seg;
  352. }
  353. $i++;
  354. }
  355. if (count($default) > 0)
  356. {
  357. foreach ($default as $val)
  358. {
  359. if ( ! array_key_exists($val, $retval))
  360. {
  361. $retval[$val] = FALSE;
  362. }
  363. }
  364. }
  365. // Cache the array for reuse
  366. $this->keyval[$n] = $retval;
  367. return $retval;
  368. }
  369. // --------------------------------------------------------------------
  370. /**
  371. * Generate a URI string from an associative array
  372. *
  373. *
  374. * @access public
  375. * @param array an associative array of key/values
  376. * @return array
  377. */
  378. function assoc_to_uri($array)
  379. {
  380. $temp = array();
  381. foreach ((array)$array as $key => $val)
  382. {
  383. $temp[] = $key;
  384. $temp[] = $val;
  385. }
  386. return implode('/', $temp);
  387. }
  388. // --------------------------------------------------------------------
  389. /**
  390. * Fetch a URI Segment and add a trailing slash
  391. *
  392. * @access public
  393. * @param integer
  394. * @param string
  395. * @return string
  396. */
  397. function slash_segment($n, $where = 'trailing')
  398. {
  399. return $this->_slash_segment($n, $where, 'segment');
  400. }
  401. // --------------------------------------------------------------------
  402. /**
  403. * Fetch a URI Segment and add a trailing slash
  404. *
  405. * @access public
  406. * @param integer
  407. * @param string
  408. * @return string
  409. */
  410. function slash_rsegment($n, $where = 'trailing')
  411. {
  412. return $this->_slash_segment($n, $where, 'rsegment');
  413. }
  414. // --------------------------------------------------------------------
  415. /**
  416. * Fetch a URI Segment and add a trailing slash - helper function
  417. *
  418. * @access private
  419. * @param integer
  420. * @param string
  421. * @param string
  422. * @return string
  423. */
  424. function _slash_segment($n, $where = 'trailing', $which = 'segment')
  425. {
  426. if ($where == 'trailing')
  427. {
  428. $trailing = '/';
  429. $leading = '';
  430. }
  431. elseif ($where == 'leading')
  432. {
  433. $leading = '/';
  434. $trailing = '';
  435. }
  436. else
  437. {
  438. $leading = '/';
  439. $trailing = '/';
  440. }
  441. return $leading.$this->$which($n).$trailing;
  442. }
  443. // --------------------------------------------------------------------
  444. /**
  445. * Segment Array
  446. *
  447. * @access public
  448. * @return array
  449. */
  450. function segment_array()
  451. {
  452. return $this->segments;
  453. }
  454. // --------------------------------------------------------------------
  455. /**
  456. * Routed Segment Array
  457. *
  458. * @access public
  459. * @return array
  460. */
  461. function rsegment_array()
  462. {
  463. return $this->rsegments;
  464. }
  465. // --------------------------------------------------------------------
  466. /**
  467. * Total number of segments
  468. *
  469. * @access public
  470. * @return integer
  471. */
  472. function total_segments()
  473. {
  474. return count($this->segments);
  475. }
  476. // --------------------------------------------------------------------
  477. /**
  478. * Total number of routed segments
  479. *
  480. * @access public
  481. * @return integer
  482. */
  483. function total_rsegments()
  484. {
  485. return count($this->rsegments);
  486. }
  487. // --------------------------------------------------------------------
  488. /**
  489. * Fetch the entire URI string
  490. *
  491. * @access public
  492. * @return string
  493. */
  494. function uri_string()
  495. {
  496. return $this->uri_string;
  497. }
  498. // --------------------------------------------------------------------
  499. /**
  500. * Fetch the entire Re-routed URI string
  501. *
  502. * @access public
  503. * @return string
  504. */
  505. function ruri_string()
  506. {
  507. return '/'.implode('/', $this->rsegment_array()).'/';
  508. }
  509. }
  510. // END URI Class
  511. /* End of file URI.php */
  512. /* Location: ./system/libraries/URI.php */