PageRenderTime 36ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/system/core/URI.php

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