PageRenderTime 33ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/uri/uri.php

https://bitbucket.org/pastor399/newcastleunifc
PHP | 818 lines | 358 code | 77 blank | 383 comment | 55 complexity | db40250c82a6bb354373dba413eee2ba MD5 | raw file
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Uri
  5. *
  6. * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * JURI Class
  12. *
  13. * This class serves two purposes. First it parses a URI and provides a common interface
  14. * for the Joomla Platform to access and manipulate a URI. Second it obtains the URI of
  15. * the current executing script from the server regardless of server.
  16. *
  17. * @package Joomla.Platform
  18. * @subpackage Uri
  19. * @since 11.1
  20. */
  21. class JUri
  22. {
  23. /**
  24. * @var string Original URI
  25. * @since 12.1
  26. */
  27. protected $uri = null;
  28. /**
  29. * @var string Protocol
  30. * @since 12.1
  31. */
  32. protected $scheme = null;
  33. /**
  34. * @var string Host
  35. * @since 12.1
  36. */
  37. protected $host = null;
  38. /**
  39. * @var integer Port
  40. * @since 12.1
  41. */
  42. protected $port = null;
  43. /**
  44. * @var string Username
  45. * @since 12.1
  46. */
  47. protected $user = null;
  48. /**
  49. * @var string Password
  50. * @since 12.1
  51. */
  52. protected $pass = null;
  53. /**
  54. * @var string Path
  55. * @since 12.1
  56. */
  57. protected $path = null;
  58. /**
  59. * @var string Query
  60. * @since 12.1
  61. */
  62. protected $query = null;
  63. /**
  64. * @var string Anchor
  65. * @since 12.1
  66. */
  67. protected $fragment = null;
  68. /**
  69. * @var array Query variable hash
  70. * @since 12.1
  71. */
  72. protected $vars = array();
  73. /**
  74. * @var array An array of JURI instances.
  75. * @since 11.1
  76. */
  77. protected static $instances = array();
  78. /**
  79. * @var array The current calculated base url segments.
  80. * @since 11.1
  81. */
  82. protected static $base = array();
  83. /**
  84. * @var array The current calculated root url segments.
  85. * @since 11.1
  86. */
  87. protected static $root = array();
  88. /**
  89. * @var string The current url.
  90. * @since 11.1
  91. */
  92. protected static $current;
  93. /**
  94. * Constructor.
  95. * You can pass a URI string to the constructor to initialise a specific URI.
  96. *
  97. * @param string $uri The optional URI string
  98. *
  99. * @since 11.1
  100. */
  101. public function __construct($uri = null)
  102. {
  103. if (!is_null($uri))
  104. {
  105. $this->parse($uri);
  106. }
  107. }
  108. /**
  109. * Magic method to get the string representation of the URI object.
  110. *
  111. * @return string
  112. *
  113. * @since 11.1
  114. */
  115. public function __toString()
  116. {
  117. return $this->toString();
  118. }
  119. /**
  120. * Returns the global JURI object, only creating it
  121. * if it doesn't already exist.
  122. *
  123. * @param string $uri The URI to parse. [optional: if null uses script URI]
  124. *
  125. * @return JURI The URI object.
  126. *
  127. * @since 11.1
  128. */
  129. public static function getInstance($uri = 'SERVER')
  130. {
  131. if (empty(self::$instances[$uri]))
  132. {
  133. // Are we obtaining the URI from the server?
  134. if ($uri == 'SERVER')
  135. {
  136. // Determine if the request was over SSL (HTTPS).
  137. if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off'))
  138. {
  139. $https = 's://';
  140. }
  141. else
  142. {
  143. $https = '://';
  144. }
  145. /*
  146. * Since we are assigning the URI from the server variables, we first need
  147. * to determine if we are running on apache or IIS. If PHP_SELF and REQUEST_URI
  148. * are present, we will assume we are running on apache.
  149. */
  150. if (!empty($_SERVER['PHP_SELF']) && !empty($_SERVER['REQUEST_URI']))
  151. {
  152. // To build the entire URI we need to prepend the protocol, and the http host
  153. // to the URI string.
  154. $theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  155. }
  156. else
  157. {
  158. /*
  159. * Since we do not have REQUEST_URI to work with, we will assume we are
  160. * running on IIS and will therefore need to work some magic with the SCRIPT_NAME and
  161. * QUERY_STRING environment variables.
  162. *
  163. * IIS uses the SCRIPT_NAME variable instead of a REQUEST_URI variable... thanks, MS
  164. */
  165. $theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'];
  166. // If the query string exists append it to the URI string
  167. if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']))
  168. {
  169. $theURI .= '?' . $_SERVER['QUERY_STRING'];
  170. }
  171. }
  172. // Check for quotes in the URL to prevent injections through the Host header
  173. if ($theURI !== str_replace(array("'", '"', '<', '>'), '', $theURI))
  174. {
  175. throw new InvalidArgumentException('Invalid URI detected.');
  176. }
  177. }
  178. else
  179. {
  180. // We were given a URI
  181. $theURI = $uri;
  182. }
  183. self::$instances[$uri] = new JURI($theURI);
  184. }
  185. return clone self::$instances[$uri];
  186. }
  187. /**
  188. * Returns the base URI for the request.
  189. *
  190. * @param boolean $pathonly If false, prepend the scheme, host and port information. Default is false.
  191. *
  192. * @return string The base URI string
  193. *
  194. * @since 11.1
  195. */
  196. public static function base($pathonly = false)
  197. {
  198. // Get the base request path.
  199. if (empty(self::$base))
  200. {
  201. $config = JFactory::getConfig();
  202. $live_site = $config->get('live_site');
  203. if (trim($live_site) != '')
  204. {
  205. $uri = self::getInstance($live_site);
  206. self::$base['prefix'] = $uri->toString(array('scheme', 'host', 'port'));
  207. self::$base['path'] = rtrim($uri->toString(array('path')), '/\\');
  208. if (defined('JPATH_BASE') && defined('JPATH_ADMINISTRATOR'))
  209. {
  210. if (JPATH_BASE == JPATH_ADMINISTRATOR)
  211. {
  212. self::$base['path'] .= '/administrator';
  213. }
  214. }
  215. }
  216. else
  217. {
  218. $uri = self::getInstance();
  219. self::$base['prefix'] = $uri->toString(array('scheme', 'host', 'port'));
  220. if (strpos(php_sapi_name(), 'cgi') !== false && !ini_get('cgi.fix_pathinfo') && !empty($_SERVER['REQUEST_URI']))
  221. {
  222. // PHP-CGI on Apache with "cgi.fix_pathinfo = 0"
  223. // We shouldn't have user-supplied PATH_INFO in PHP_SELF in this case
  224. // because PHP will not work with PATH_INFO at all.
  225. $script_name = $_SERVER['PHP_SELF'];
  226. }
  227. else
  228. {
  229. // Others
  230. $script_name = $_SERVER['SCRIPT_NAME'];
  231. }
  232. self::$base['path'] = rtrim(dirname($script_name), '/\\');
  233. }
  234. }
  235. return $pathonly === false ? self::$base['prefix'] . self::$base['path'] . '/' : self::$base['path'];
  236. }
  237. /**
  238. * Returns the root URI for the request.
  239. *
  240. * @param boolean $pathonly If false, prepend the scheme, host and port information. Default is false.
  241. * @param string $path The path
  242. *
  243. * @return string The root URI string.
  244. *
  245. * @since 11.1
  246. */
  247. public static function root($pathonly = false, $path = null)
  248. {
  249. // Get the scheme
  250. if (empty(self::$root))
  251. {
  252. $uri = self::getInstance(self::base());
  253. self::$root['prefix'] = $uri->toString(array('scheme', 'host', 'port'));
  254. self::$root['path'] = rtrim($uri->toString(array('path')), '/\\');
  255. }
  256. // Get the scheme
  257. if (isset($path))
  258. {
  259. self::$root['path'] = $path;
  260. }
  261. return $pathonly === false ? self::$root['prefix'] . self::$root['path'] . '/' : self::$root['path'];
  262. }
  263. /**
  264. * Returns the URL for the request, minus the query.
  265. *
  266. * @return string
  267. *
  268. * @since 11.1
  269. */
  270. public static function current()
  271. {
  272. // Get the current URL.
  273. if (empty(self::$current))
  274. {
  275. $uri = self::getInstance();
  276. self::$current = $uri->toString(array('scheme', 'host', 'port', 'path'));
  277. }
  278. return self::$current;
  279. }
  280. /**
  281. * Method to reset class static members for testing and other various issues.
  282. *
  283. * @return void
  284. *
  285. * @since 11.1
  286. */
  287. public static function reset()
  288. {
  289. self::$instances = array();
  290. self::$base = array();
  291. self::$root = array();
  292. self::$current = '';
  293. }
  294. /**
  295. * Parse a given URI and populate the class fields.
  296. *
  297. * @param string $uri The URI string to parse.
  298. *
  299. * @return boolean True on success.
  300. *
  301. * @since 11.1
  302. */
  303. public function parse($uri)
  304. {
  305. // Set the original URI to fall back on
  306. $this->uri = $uri;
  307. // Parse the URI and populate the object fields. If URI is parsed properly,
  308. // set method return value to true.
  309. $parts = JString::parse_url($uri);
  310. $retval = ($parts) ? true : false;
  311. // We need to replace &amp; with & for parse_str to work right...
  312. if (isset($parts['query']) && strpos($parts['query'], '&amp;'))
  313. {
  314. $parts['query'] = str_replace('&amp;', '&', $parts['query']);
  315. }
  316. $this->scheme = isset($parts['scheme']) ? $parts['scheme'] : null;
  317. $this->user = isset($parts['user']) ? $parts['user'] : null;
  318. $this->pass = isset($parts['pass']) ? $parts['pass'] : null;
  319. $this->host = isset($parts['host']) ? $parts['host'] : null;
  320. $this->port = isset($parts['port']) ? $parts['port'] : null;
  321. $this->path = isset($parts['path']) ? $parts['path'] : null;
  322. $this->query = isset($parts['query']) ? $parts['query'] : null;
  323. $this->fragment = isset($parts['fragment']) ? $parts['fragment'] : null;
  324. // Parse the query
  325. if (isset($parts['query']))
  326. {
  327. parse_str($parts['query'], $this->vars);
  328. }
  329. return $retval;
  330. }
  331. /**
  332. * Returns full uri string.
  333. *
  334. * @param array $parts An array specifying the parts to render.
  335. *
  336. * @return string The rendered URI string.
  337. *
  338. * @since 11.1
  339. */
  340. public function toString(array $parts = array('scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'))
  341. {
  342. // Make sure the query is created
  343. $query = $this->getQuery();
  344. $uri = '';
  345. $uri .= in_array('scheme', $parts) ? (!empty($this->scheme) ? $this->scheme . '://' : '') : '';
  346. $uri .= in_array('user', $parts) ? $this->user : '';
  347. $uri .= in_array('pass', $parts) ? (!empty($this->pass) ? ':' : '') . $this->pass . (!empty($this->user) ? '@' : '') : '';
  348. $uri .= in_array('host', $parts) ? $this->host : '';
  349. $uri .= in_array('port', $parts) ? (!empty($this->port) ? ':' : '') . $this->port : '';
  350. $uri .= in_array('path', $parts) ? $this->path : '';
  351. $uri .= in_array('query', $parts) ? (!empty($query) ? '?' . $query : '') : '';
  352. $uri .= in_array('fragment', $parts) ? (!empty($this->fragment) ? '#' . $this->fragment : '') : '';
  353. return $uri;
  354. }
  355. /**
  356. * Adds a query variable and value, replacing the value if it
  357. * already exists and returning the old value.
  358. *
  359. * @param string $name Name of the query variable to set.
  360. * @param string $value Value of the query variable.
  361. *
  362. * @return string Previous value for the query variable.
  363. *
  364. * @since 11.1
  365. */
  366. public function setVar($name, $value)
  367. {
  368. $tmp = isset($this->vars[$name]) ? $this->vars[$name] : null;
  369. $this->vars[$name] = $value;
  370. // Empty the query
  371. $this->query = null;
  372. return $tmp;
  373. }
  374. /**
  375. * Checks if variable exists.
  376. *
  377. * @param string $name Name of the query variable to check.
  378. *
  379. * @return boolean True if the variable exists.
  380. *
  381. * @since 11.1
  382. */
  383. public function hasVar($name)
  384. {
  385. return array_key_exists($name, $this->vars);
  386. }
  387. /**
  388. * Returns a query variable by name.
  389. *
  390. * @param string $name Name of the query variable to get.
  391. * @param string $default Default value to return if the variable is not set.
  392. *
  393. * @return array Query variables.
  394. *
  395. * @since 11.1
  396. */
  397. public function getVar($name, $default = null)
  398. {
  399. if (array_key_exists($name, $this->vars))
  400. {
  401. return $this->vars[$name];
  402. }
  403. return $default;
  404. }
  405. /**
  406. * Removes an item from the query string variables if it exists.
  407. *
  408. * @param string $name Name of variable to remove.
  409. *
  410. * @return void
  411. *
  412. * @since 11.1
  413. */
  414. public function delVar($name)
  415. {
  416. if (array_key_exists($name, $this->vars))
  417. {
  418. unset($this->vars[$name]);
  419. // Empty the query
  420. $this->query = null;
  421. }
  422. }
  423. /**
  424. * Sets the query to a supplied string in format:
  425. * foo=bar&x=y
  426. *
  427. * @param mixed $query The query string or array.
  428. *
  429. * @return void
  430. *
  431. * @since 11.1
  432. */
  433. public function setQuery($query)
  434. {
  435. if (is_array($query))
  436. {
  437. $this->vars = $query;
  438. }
  439. else
  440. {
  441. if (strpos($query, '&amp;') !== false)
  442. {
  443. $query = str_replace('&amp;', '&', $query);
  444. }
  445. parse_str($query, $this->vars);
  446. }
  447. // Empty the query
  448. $this->query = null;
  449. }
  450. /**
  451. * Returns flat query string.
  452. *
  453. * @param boolean $toArray True to return the query as a key => value pair array.
  454. *
  455. * @return string Query string.
  456. *
  457. * @since 11.1
  458. */
  459. public function getQuery($toArray = false)
  460. {
  461. if ($toArray)
  462. {
  463. return $this->vars;
  464. }
  465. // If the query is empty build it first
  466. if (is_null($this->query))
  467. {
  468. $this->query = self::buildQuery($this->vars);
  469. }
  470. return $this->query;
  471. }
  472. /**
  473. * Build a query from a array (reverse of the PHP parse_str()).
  474. *
  475. * @param array $params The array of key => value pairs to return as a query string.
  476. *
  477. * @return string The resulting query string.
  478. *
  479. * @see parse_str()
  480. * @since 11.1
  481. */
  482. public static function buildQuery(array $params)
  483. {
  484. if (count($params) == 0)
  485. {
  486. return false;
  487. }
  488. return urldecode(http_build_query($params, '', '&'));
  489. }
  490. /**
  491. * Get URI scheme (protocol)
  492. * ie. http, https, ftp, etc...
  493. *
  494. * @return string The URI scheme.
  495. *
  496. * @since 11.1
  497. */
  498. public function getScheme()
  499. {
  500. return $this->scheme;
  501. }
  502. /**
  503. * Set URI scheme (protocol)
  504. * ie. http, https, ftp, etc...
  505. *
  506. * @param string $scheme The URI scheme.
  507. *
  508. * @return void
  509. *
  510. * @since 11.1
  511. */
  512. public function setScheme($scheme)
  513. {
  514. $this->scheme = $scheme;
  515. }
  516. /**
  517. * Get URI username
  518. * Returns the username, or null if no username was specified.
  519. *
  520. * @return string The URI username.
  521. *
  522. * @since 11.1
  523. */
  524. public function getUser()
  525. {
  526. return $this->user;
  527. }
  528. /**
  529. * Set URI username.
  530. *
  531. * @param string $user The URI username.
  532. *
  533. * @return void
  534. *
  535. * @since 11.1
  536. */
  537. public function setUser($user)
  538. {
  539. $this->user = $user;
  540. }
  541. /**
  542. * Get URI password
  543. * Returns the password, or null if no password was specified.
  544. *
  545. * @return string The URI password.
  546. *
  547. * @since 11.1
  548. */
  549. public function getPass()
  550. {
  551. return $this->pass;
  552. }
  553. /**
  554. * Set URI password.
  555. *
  556. * @param string $pass The URI password.
  557. *
  558. * @return void
  559. *
  560. * @since 11.1
  561. */
  562. public function setPass($pass)
  563. {
  564. $this->pass = $pass;
  565. }
  566. /**
  567. * Get URI host
  568. * Returns the hostname/ip or null if no hostname/ip was specified.
  569. *
  570. * @return string The URI host.
  571. *
  572. * @since 11.1
  573. */
  574. public function getHost()
  575. {
  576. return $this->host;
  577. }
  578. /**
  579. * Set URI host.
  580. *
  581. * @param string $host The URI host.
  582. *
  583. * @return void
  584. *
  585. * @since 11.1
  586. */
  587. public function setHost($host)
  588. {
  589. $this->host = $host;
  590. }
  591. /**
  592. * Get URI port
  593. * Returns the port number, or null if no port was specified.
  594. *
  595. * @return integer The URI port number.
  596. *
  597. * @since 11.1
  598. */
  599. public function getPort()
  600. {
  601. return (isset($this->port)) ? $this->port : null;
  602. }
  603. /**
  604. * Set URI port.
  605. *
  606. * @param integer $port The URI port number.
  607. *
  608. * @return void
  609. *
  610. * @since 11.1
  611. */
  612. public function setPort($port)
  613. {
  614. $this->port = $port;
  615. }
  616. /**
  617. * Gets the URI path string.
  618. *
  619. * @return string The URI path string.
  620. *
  621. * @since 11.1
  622. */
  623. public function getPath()
  624. {
  625. return $this->path;
  626. }
  627. /**
  628. * Set the URI path string.
  629. *
  630. * @param string $path The URI path string.
  631. *
  632. * @return void
  633. *
  634. * @since 11.1
  635. */
  636. public function setPath($path)
  637. {
  638. $this->path = $this->_cleanPath($path);
  639. }
  640. /**
  641. * Get the URI archor string
  642. * Everything after the "#".
  643. *
  644. * @return string The URI anchor string.
  645. *
  646. * @since 11.1
  647. */
  648. public function getFragment()
  649. {
  650. return $this->fragment;
  651. }
  652. /**
  653. * Set the URI anchor string
  654. * everything after the "#".
  655. *
  656. * @param string $anchor The URI anchor string.
  657. *
  658. * @return void
  659. *
  660. * @since 11.1
  661. */
  662. public function setFragment($anchor)
  663. {
  664. $this->fragment = $anchor;
  665. }
  666. /**
  667. * Checks whether the current URI is using HTTPS.
  668. *
  669. * @return boolean True if using SSL via HTTPS.
  670. *
  671. * @since 11.1
  672. */
  673. public function isSSL()
  674. {
  675. return $this->getScheme() == 'https' ? true : false;
  676. }
  677. /**
  678. * Checks if the supplied URL is internal
  679. *
  680. * @param string $url The URL to check.
  681. *
  682. * @return boolean True if Internal.
  683. *
  684. * @since 11.1
  685. */
  686. public static function isInternal($url)
  687. {
  688. $uri = self::getInstance($url);
  689. $base = $uri->toString(array('scheme', 'host', 'port', 'path'));
  690. $host = $uri->toString(array('scheme', 'host', 'port'));
  691. if (stripos($base, self::base()) !== 0 && !empty($host))
  692. {
  693. return false;
  694. }
  695. return true;
  696. }
  697. /**
  698. * Resolves //, ../ and ./ from a path and returns
  699. * the result. Eg:
  700. *
  701. * /foo/bar/../boo.php => /foo/boo.php
  702. * /foo/bar/../../boo.php => /boo.php
  703. * /foo/bar/.././/boo.php => /foo/boo.php
  704. *
  705. * @param string $path The URI path to clean.
  706. *
  707. * @return string Cleaned and resolved URI path.
  708. *
  709. * @since 11.1
  710. */
  711. protected function _cleanPath($path)
  712. {
  713. $path = explode('/', preg_replace('#(/+)#', '/', $path));
  714. for ($i = 0, $n = count($path); $i < $n; $i++)
  715. {
  716. if ($path[$i] == '.' || $path[$i] == '..')
  717. {
  718. if (($path[$i] == '.') || ($path[$i] == '..' && $i == 1 && $path[0] == ''))
  719. {
  720. unset($path[$i]);
  721. $path = array_values($path);
  722. $i--;
  723. $n--;
  724. }
  725. elseif ($path[$i] == '..' && ($i > 1 || ($i == 1 && $path[0] != '')))
  726. {
  727. unset($path[$i]);
  728. unset($path[$i - 1]);
  729. $path = array_values($path);
  730. $i -= 2;
  731. $n -= 2;
  732. }
  733. }
  734. }
  735. return implode('/', $path);
  736. }
  737. }