Advertisement
Guest User

Untitled

a guest
Jul 2nd, 2017
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.50 KB | None | 0 0
  1. <?php
  2. /**
  3. * @version $Id: uri.php 19058 2010-10-08 04:15:39Z dextercowley $
  4. * @package Joomla.Framework
  5. * @subpackage Environment
  6. * @copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
  7. * @license GNU/GPL, see LICENSE.php
  8. * Joomla! is free software. This version may have been modified pursuant
  9. * to the GNU General Public License, and as distributed it includes or
  10. * is derivative of works licensed under the GNU General Public License or
  11. * other free or open source software licenses.
  12. * See COPYRIGHT.php for copyright notices and details.
  13. */
  14.  
  15. // Check to ensure this file is within the rest of the framework
  16. defined('JPATH_BASE') or die();
  17.  
  18. /**
  19. * JURI Class
  20. *
  21. * This class serves two purposes. First to parse a URI and provide a common interface
  22. * for the Joomla Framework to access and manipulate a URI. Second to attain the URI of
  23. * the current executing script from the server regardless of server.
  24. *
  25. * @package Joomla.Framework
  26. * @subpackage Environment
  27. * @since 1.5
  28. */
  29. class JURI extends JObject
  30. {
  31. /**
  32. * Original URI
  33. *
  34. * @var string
  35. */
  36. var $_uri = null;
  37.  
  38. /**
  39. * Protocol
  40. *
  41. * @var string
  42. */
  43. var $_scheme = null;
  44.  
  45. /**
  46. * Host
  47. *
  48. * @var string
  49. */
  50. var $_host = null;
  51.  
  52. /**
  53. * Port
  54. *
  55. * @var integer
  56. */
  57. var $_port = null;
  58.  
  59. /**
  60. * Username
  61. *
  62. * @var string
  63. */
  64. var $_user = null;
  65.  
  66. /**
  67. * Password
  68. *
  69. * @var string
  70. */
  71. var $_pass = null;
  72.  
  73. /**
  74. * Path
  75. *
  76. * @var string
  77. */
  78. var $_path = null;
  79.  
  80. /**
  81. * Query
  82. *
  83. * @var string
  84. */
  85. var $_query = null;
  86.  
  87. /**
  88. * Anchor
  89. *
  90. * @var string
  91. */
  92. var $_fragment = null;
  93.  
  94. /**
  95. * Query variable hash
  96. *
  97. * @var array
  98. */
  99. var $_vars = array ();
  100.  
  101. /**
  102. * Constructor.
  103. * You can pass a URI string to the constructor to initialize a specific URI.
  104. *
  105. * @param string $uri The optional URI string
  106. */
  107. function __construct($uri = null)
  108. {
  109. if ($uri !== null) {
  110. $this->parse($uri);
  111. }
  112. }
  113.  
  114. /**
  115. * Returns a reference to a global JURI object, only creating it
  116. * if it doesn't already exist.
  117. *
  118. * This method must be invoked as:
  119. * <pre> $uri =& JURI::getInstance([$uri]);</pre>
  120. *
  121. * @static
  122. * @param string $uri The URI to parse. [optional: if null uses script URI]
  123. * @return JURI The URI object.
  124. * @since 1.5
  125. */
  126. function &getInstance($uri = 'SERVER')
  127. {
  128. static $instances = array();
  129.  
  130. if (!isset ($instances[$uri]))
  131. {
  132. // Are we obtaining the URI from the server?
  133. if ($uri == 'SERVER')
  134. {
  135. // Determine if the request was over SSL (HTTPS)
  136. if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) {
  137. $https = 's://';
  138. } else {
  139. $https = '://';
  140. }
  141.  
  142. /*
  143. * Since we are assigning the URI from the server variables, we first need
  144. * to determine if we are running on apache or IIS. If PHP_SELF and REQUEST_URI
  145. * are present, we will assume we are running on apache.
  146. */
  147. if (!empty ($_SERVER['PHP_SELF']) && !empty ($_SERVER['REQUEST_URI'])) {
  148.  
  149. /*
  150. * To build the entire URI we need to prepend the protocol, and the http host
  151. * to the URI string.
  152. */
  153. $theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  154.  
  155. /*
  156. * Since we do not have REQUEST_URI to work with, we will assume we are
  157. * running on IIS and will therefore need to work some magic with the SCRIPT_NAME and
  158. * QUERY_STRING environment variables.
  159. */
  160.  
  161. if (strlen($_SERVER['QUERY_STRING']) && strpos($_SERVER['REQUEST_URI'], $_SERVER['QUERY_STRING']) === false) {
  162. $theURI .= '?'.$_SERVER['QUERY_STRING'];
  163. }
  164.  
  165. }
  166. else
  167. {
  168. // IIS uses the SCRIPT_NAME variable instead of a REQUEST_URI variable... thanks, MS
  169. $theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'];
  170.  
  171. // If the query string exists append it to the URI string
  172. if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) {
  173. $theURI .= '?' . $_SERVER['QUERY_STRING'];
  174. }
  175. }
  176.  
  177. // Now we need to clean what we got since we can't trust the server var
  178. // Need to check that the URI is fully decoded in case of multiple-encoded attack vectors.
  179. $halt = 0;
  180. while (true)
  181. {
  182. $last = $theURI;
  183. $theURI = urldecode($theURI);
  184.  
  185. // Check whether the last decode is equal to the first.
  186. if ($theURI == $last) {
  187. // Break out of the while if the URI is stable.
  188. break;
  189. }
  190. else if (++$halt > 10) {
  191. // Runaway check. URI has been seriously compromised.
  192. jexit();
  193. }
  194. }
  195.  
  196. $theURI = str_replace('"', '"',$theURI);
  197. $theURI = str_replace('<', '<',$theURI);
  198. $theURI = str_replace('>', '>',$theURI);
  199. $theURI = preg_replace('/eval\((.*)\)/', '', $theURI);
  200. $theURI = preg_replace('/[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']/', '""', $theURI);
  201. }
  202. else
  203. {
  204. // We were given a URI
  205. $theURI = $uri;
  206. }
  207.  
  208. // Create the new JURI instance
  209. $instances[$uri] = new JURI($theURI);
  210. }
  211. return $instances[$uri];
  212. }
  213.  
  214. /**
  215. * Returns the base URI for the request.
  216. *
  217. * @access public
  218. * @static
  219. * @param boolean $pathonly If false, prepend the scheme, host and port information. Default is false.
  220. * @return string The base URI string
  221. * @since 1.5
  222. */
  223. function base($pathonly = false)
  224. {
  225. static $base;
  226.  
  227. // Get the base request path
  228. if (!isset($base))
  229. {
  230. $config =& JFactory::getConfig();
  231. $live_site = $config->getValue('config.live_site');
  232. if(trim($live_site) != '') {
  233. $uri =& JURI::getInstance($live_site);
  234. $base['prefix'] = $uri->toString( array('scheme', 'host', 'port'));
  235. $base['path'] = rtrim($uri->toString( array('path')), '/\\');
  236. if(JPATH_BASE == JPATH_ADMINISTRATOR) {
  237. $base['path'] .= '/administrator';
  238. }
  239. } else {
  240. $uri =& JURI::getInstance();
  241. $base['prefix'] = $uri->toString( array('scheme', 'host', 'port'));
  242.  
  243. if (strpos(php_sapi_name(), 'cgi') !== false && !empty($_SERVER['REQUEST_URI'])) {
  244. //Apache CGI
  245. $base['path'] = rtrim(dirname(str_replace(array('"', '<', '>', "'"), '', $_SERVER["PHP_SELF"])), '/\\');
  246. } else {
  247. //Others
  248. $base['path'] = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\');
  249. }
  250. }
  251. }
  252.  
  253. return $pathonly === false ? $base['prefix'].$base['path'].'/' : $base['path'];
  254. }
  255.  
  256. /**
  257. * Returns the root URI for the request.
  258. *
  259. * @access public
  260. * @static
  261. * @param boolean $pathonly If false, prepend the scheme, host and port information. Default is false.
  262. * @return string The root URI string
  263. * @since 1.5
  264. */
  265. function root($pathonly = false, $path = null)
  266. {
  267. static $root;
  268.  
  269. // Get the scheme
  270. if(!isset($root))
  271. {
  272. $uri =& JURI::getInstance(JURI::base());
  273. $root['prefix'] = $uri->toString( array('scheme', 'host', 'port') );
  274. $root['path'] = rtrim($uri->toString( array('path') ), '/\\');
  275. }
  276.  
  277. // Get the scheme
  278. if(isset($path)) {
  279. $root['path'] = $path;
  280. }
  281.  
  282. return $pathonly === false ? $root['prefix'].$root['path'].'/' : $root['path'];
  283. }
  284.  
  285. /**
  286. * Returns the URL for the request, minus the query
  287. *
  288. * @access public
  289. * @return string
  290. * @since 1.5
  291. */
  292. function current()
  293. {
  294. static $current;
  295.  
  296. // Get the current URL
  297. if (!isset($current))
  298. {
  299. $uri = & JURI::getInstance();
  300. $current = $uri->toString( array('scheme', 'host', 'port', 'path'));
  301. }
  302.  
  303. return $current;
  304. }
  305.  
  306. /**
  307. * Parse a given URI and populate the class fields
  308. *
  309. * @access public
  310. * @param string $uri The URI string to parse
  311. * @return boolean True on success
  312. * @since 1.5
  313. */
  314. function parse($uri)
  315. {
  316. //Initialize variables
  317. $retval = false;
  318.  
  319. // Set the original URI to fall back on
  320. $this->_uri = $uri;
  321.  
  322. /*
  323. * Parse the URI and populate the object fields. If URI is parsed properly,
  324. * set method return value to true.
  325. */
  326. if ($_parts = $this->_parseURL($uri)) {
  327. $retval = true;
  328. }
  329.  
  330. //We need to replace & with & for parse_str to work right...
  331. if(isset ($_parts['query']) && strpos($_parts['query'], '&')) {
  332. $_parts['query'] = str_replace('&', '&', $_parts['query']);
  333. }
  334.  
  335. $this->_scheme = isset ($_parts['scheme']) ? $_parts['scheme'] : null;
  336. $this->_user = isset ($_parts['user']) ? $_parts['user'] : null;
  337. $this->_pass = isset ($_parts['pass']) ? $_parts['pass'] : null;
  338. $this->_host = isset ($_parts['host']) ? $_parts['host'] : null;
  339. $this->_port = isset ($_parts['port']) ? $_parts['port'] : null;
  340. $this->_path = isset ($_parts['path']) ? $_parts['path'] : null;
  341. $this->_query = isset ($_parts['query'])? $_parts['query'] : null;
  342. $this->_fragment = isset ($_parts['fragment']) ? $_parts['fragment'] : null;
  343.  
  344. //parse the query
  345.  
  346. if(isset ($_parts['query'])) parse_str($_parts['query'], $this->_vars);
  347. return $retval;
  348. }
  349.  
  350. /**
  351. * Returns full uri string
  352. *
  353. * @access public
  354. * @param array $parts An array specifying the parts to render
  355. * @return string The rendered URI string
  356. * @since 1.5
  357. */
  358. function toString($parts = array('scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'))
  359. {
  360. $query = $this->getQuery(); //make sure the query is created
  361.  
  362. $uri = '';
  363. $uri .= in_array('scheme', $parts) ? (!empty($this->_scheme) ? $this->_scheme.'://' : '') : '';
  364. $uri .= in_array('user', $parts) ? $this->_user : '';
  365. $uri .= in_array('pass', $parts) ? (!empty ($this->_pass) ? ':' : '') .$this->_pass. (!empty ($this->_user) ? '@' : '') : '';
  366. $uri .= in_array('host', $parts) ? $this->_host : '';
  367. $uri .= in_array('port', $parts) ? (!empty ($this->_port) ? ':' : '').$this->_port : '';
  368. $uri .= in_array('path', $parts) ? $this->_path : '';
  369. $uri .= in_array('query', $parts) ? (!empty ($query) ? '?'.$query : '') : '';
  370. $uri .= in_array('fragment', $parts)? (!empty ($this->_fragment) ? '#'.$this->_fragment : '') : '';
  371.  
  372. return $uri;
  373. }
  374.  
  375. /**
  376. * Adds a query variable and value, replacing the value if it
  377. * already exists and returning the old value.
  378. *
  379. * @access public
  380. * @param string $name Name of the query variable to set
  381. * @param string $value Value of the query variable
  382. * @return string Previous value for the query variable
  383. * @since 1.5
  384. */
  385. function setVar($name, $value)
  386. {
  387. $tmp = @$this->_vars[$name];
  388. $this->_vars[$name] = $value;
  389.  
  390. //empty the query
  391. $this->_query = null;
  392.  
  393. return $tmp;
  394. }
  395.  
  396. /**
  397. * Returns a query variable by name
  398. *
  399. * @access public
  400. * @param string $name Name of the query variable to get
  401. * @return array Query variables
  402. * @since 1.5
  403. */
  404. function getVar($name = null, $default=null)
  405. {
  406. if(isset($this->_vars[$name])) {
  407. return $this->_vars[$name];
  408. }
  409. return $default;
  410. }
  411.  
  412. /**
  413. * Removes an item from the query string variables if it exists
  414. *
  415. * @access public
  416. * @param string $name Name of variable to remove
  417. * @since 1.5
  418. */
  419. function delVar($name)
  420. {
  421. if (in_array($name, array_keys($this->_vars)))
  422. {
  423. unset ($this->_vars[$name]);
  424.  
  425. //empty the query
  426. $this->_query = null;
  427. }
  428. }
  429.  
  430. /**
  431. * Sets the query to a supplied string in format:
  432. * foo=bar&x=y
  433. *
  434. * @access public
  435. * @param mixed (array|string) $query The query string
  436. * @since 1.5
  437. */
  438. function setQuery($query)
  439. {
  440. if(!is_array($query)) {
  441. if(strpos($query, '&') !== false)
  442. {
  443. $query = str_replace('&','&',$query);
  444. }
  445. parse_str($query, $this->_vars);
  446. }
  447.  
  448. if(is_array($query)) {
  449. $this->_vars = $query;
  450. }
  451.  
  452. //empty the query
  453. $this->_query = null;
  454. }
  455.  
  456. /**
  457. * Returns flat query string
  458. *
  459. * @access public
  460. * @return string Query string
  461. * @since 1.5
  462. */
  463. function getQuery($toArray = false)
  464. {
  465. if($toArray) {
  466. return $this->_vars;
  467. }
  468.  
  469. //If the query is empty build it first
  470. if(is_null($this->_query)) {
  471. $this->_query = $this->buildQuery($this->_vars);
  472. }
  473.  
  474. return $this->_query;
  475. }
  476.  
  477. /**
  478. * Build a query from a array (reverse of the PHP parse_str())
  479. *
  480. * @access public
  481. * @return string The resulting query string
  482. * @since 1.5
  483. * @see parse_str()
  484. */
  485. function buildQuery ($params, $akey = null)
  486. {
  487. if ( !is_array($params) || count($params) == 0 ) {
  488. return false;
  489. }
  490.  
  491. $out = array();
  492.  
  493. //reset in case we are looping
  494. if( !isset($akey) && !count($out) ) {
  495. unset($out);
  496. $out = array();
  497. }
  498.  
  499. foreach ( $params as $key => $val )
  500. {
  501. if ( is_array($val) ) {
  502. $out[] = JURI::buildQuery($val,$key);
  503. continue;
  504. }
  505.  
  506. $thekey = ( !$akey ) ? $key : $akey.'['.$key.']';
  507. $out[] = $thekey."=".urlencode($val);
  508. }
  509.  
  510. return implode("&",$out);
  511. }
  512.  
  513. /**
  514. * Get URI scheme (protocol)
  515. * ie. http, https, ftp, etc...
  516. *
  517. * @access public
  518. * @return string The URI scheme
  519. * @since 1.5
  520. */
  521. function getScheme() {
  522. return $this->_scheme;
  523. }
  524.  
  525. /**
  526. * Set URI scheme (protocol)
  527. * ie. http, https, ftp, etc...
  528. *
  529. * @access public
  530. * @param string $scheme The URI scheme
  531. * @since 1.5
  532. */
  533. function setScheme($scheme) {
  534. $this->_scheme = $scheme;
  535. }
  536.  
  537. /**
  538. * Get URI username
  539. * returns the username, or null if no username was specified
  540. *
  541. * @access public
  542. * @return string The URI username
  543. * @since 1.5
  544. */
  545. function getUser() {
  546. return $this->_user;
  547. }
  548.  
  549. /**
  550. * Set URI username
  551. *
  552. * @access public
  553. * @param string $user The URI username
  554. * @since 1.5
  555. */
  556. function setUser($user) {
  557. $this->_user = $user;
  558. }
  559.  
  560. /**
  561. * Get URI password
  562. * returns the password, or null if no password was specified
  563. *
  564. * @access public
  565. * @return string The URI password
  566. * @since 1.5
  567. */
  568. function getPass() {
  569. return $this->_pass;
  570. }
  571.  
  572. /**
  573. * Set URI password
  574. *
  575. * @access public
  576. * @param string $pass The URI password
  577. * @since 1.5
  578. */
  579. function setPass($pass) {
  580. $this->_pass = $pass;
  581. }
  582.  
  583. /**
  584. * Get URI host
  585. * returns the hostname/ip, or null if no hostname/ip was specified
  586. *
  587. * @access public
  588. * @return string The URI host
  589. * @since 1.5
  590. */
  591. function getHost() {
  592. return $this->_host;
  593. }
  594.  
  595. /**
  596. * Set URI host
  597. *
  598. * @access public
  599. * @param string $host The URI host
  600. * @since 1.5
  601. */
  602. function setHost($host) {
  603. $this->_host = $host;
  604. }
  605.  
  606. /**
  607. * Get URI port
  608. * returns the port number, or null if no port was specified
  609. *
  610. * @access public
  611. * @return int The URI port number
  612. */
  613. function getPort() {
  614. return (isset ($this->_port)) ? $this->_port : null;
  615. }
  616.  
  617. /**
  618. * Set URI port
  619. *
  620. * @access public
  621. * @param int $port The URI port number
  622. * @since 1.5
  623. */
  624. function setPort($port) {
  625. $this->_port = $port;
  626. }
  627.  
  628. /**
  629. * Gets the URI path string
  630. *
  631. * @access public
  632. * @return string The URI path string
  633. * @since 1.5
  634. */
  635. function getPath() {
  636. return $this->_path;
  637. }
  638.  
  639. /**
  640. * Set the URI path string
  641. *
  642. * @access public
  643. * @param string $path The URI path string
  644. * @since 1.5
  645. */
  646. function setPath($path) {
  647. $this->_path = $this->_cleanPath($path);
  648. }
  649.  
  650. /**
  651. * Get the URI archor string
  652. * everything after the "#"
  653. *
  654. * @access public
  655. * @return string The URI anchor string
  656. * @since 1.5
  657. */
  658. function getFragment() {
  659. return $this->_fragment;
  660. }
  661.  
  662. /**
  663. * Set the URI anchor string
  664. * everything after the "#"
  665. *
  666. * @access public
  667. * @param string $anchor The URI anchor string
  668. * @since 1.5
  669. */
  670. function setFragment($anchor) {
  671. $this->_fragment = $anchor;
  672. }
  673.  
  674. /**
  675. * Checks whether the current URI is using HTTPS
  676. *
  677. * @access public
  678. * @return boolean True if using SSL via HTTPS
  679. * @since 1.5
  680. */
  681. function isSSL() {
  682. return $this->getScheme() == 'https' ? true : false;
  683. }
  684.  
  685. /**
  686. * Checks if the supplied URL is internal
  687. *
  688. * @access public
  689. * @param string $url The URL to check
  690. * @return boolean True if Internal
  691. * @since 1.5
  692. */
  693. function isInternal($url) {
  694. $uri =& JURI::getInstance($url);
  695. $base = $uri->toString(array('scheme', 'host', 'port', 'path'));
  696. $host = $uri->toString(array('scheme', 'host', 'port'));
  697. if(stripos($base, JURI::base()) !== 0 && !empty($host)) {
  698. return false;
  699. }
  700. return true;
  701. }
  702.  
  703. /**
  704. * Resolves //, ../ and ./ from a path and returns
  705. * the result. Eg:
  706. *
  707. * /foo/bar/../boo.php => /foo/boo.php
  708. * /foo/bar/../../boo.php => /boo.php
  709. * /foo/bar/.././/boo.php => /foo/boo.php
  710. *
  711. * @access private
  712. * @param string $uri The URI path to clean
  713. * @return string Cleaned and resolved URI path
  714. * @since 1.5
  715. */
  716. function _cleanPath($path)
  717. {
  718. $path = explode('/', preg_replace('#(/+)#', '/', $path));
  719.  
  720. for ($i = 0; $i < count($path); $i ++) {
  721. if ($path[$i] == '.') {
  722. unset ($path[$i]);
  723. $path = array_values($path);
  724. $i --;
  725.  
  726. }
  727. elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != ''))) {
  728. unset ($path[$i]);
  729. unset ($path[$i -1]);
  730. $path = array_values($path);
  731. $i -= 2;
  732.  
  733. }
  734. elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
  735. unset ($path[$i]);
  736. $path = array_values($path);
  737. $i --;
  738.  
  739. } else {
  740. continue;
  741. }
  742. }
  743.  
  744. return implode('/', $path);
  745. }
  746.  
  747. /**
  748. * Backwards compatibility function for parse_url function
  749. *
  750. * This function solves different bugs in PHP versions lower then
  751. * 4.4, will be deprecated in future versions.
  752. *
  753. * @access private
  754. * @return array Associative array containing the URL parts
  755. * @since 1.5
  756. * @see parse_url()
  757. */
  758. function _parseURL($uri)
  759. {
  760. $parts = array();
  761. if (version_compare( phpversion(), '4.4' ) < 0)
  762. {
  763. $regex = "<^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?>";
  764. $matches = array();
  765. preg_match($regex, $uri, $matches, PREG_OFFSET_CAPTURE);
  766.  
  767. $authority = @$matches[4][0];
  768. if (strpos($authority, '@') !== false) {
  769. $authority = explode('@', $authority);
  770. @list($parts['user'], $parts['pass']) = explode(':', $authority[0]);
  771. $authority = $authority[1];
  772. }
  773.  
  774. if (strpos($authority, ':') !== false) {
  775. $authority = explode(':', $authority);
  776. $parts['host'] = $authority[0];
  777. $parts['port'] = $authority[1];
  778. } else {
  779. $parts['host'] = $authority;
  780. }
  781.  
  782. $parts['scheme'] = @$matches[2][0];
  783. $parts['path'] = @$matches[5][0];
  784. $parts['query'] = @$matches[7][0];
  785. $parts['fragment'] = @$matches[9][0];
  786. }
  787. else
  788. {
  789. $parts = @parse_url($uri);
  790. }
  791. return $parts;
  792. }
  793.  
  794.  
  795. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement