URL.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?php
  2. // +-----------------------------------------------------------------------+
  3. // | Copyright (c) 2002-2004, Richard Heyes |
  4. // | All rights reserved. |
  5. // | |
  6. // | Redistribution and use in source and binary forms, with or without |
  7. // | modification, are permitted provided that the following conditions |
  8. // | are met: |
  9. // | |
  10. // | o Redistributions of source code must retain the above copyright |
  11. // | notice, this list of conditions and the following disclaimer. |
  12. // | o Redistributions in binary form must reproduce the above copyright |
  13. // | notice, this list of conditions and the following disclaimer in the |
  14. // | documentation and/or other materials provided with the distribution.|
  15. // | o The names of the authors may not be used to endorse or promote |
  16. // | products derived from this software without specific prior written |
  17. // | permission. |
  18. // | |
  19. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
  20. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
  21. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  22. // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
  23. // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  24. // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
  25. // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  26. // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  27. // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
  28. // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  29. // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
  30. // | |
  31. // +-----------------------------------------------------------------------+
  32. // | Author: Richard Heyes <richard@php.net> |
  33. // +-----------------------------------------------------------------------+
  34. // $Id: URL.php,v 1.31 2004/01/17 15:52:50 pajoye Exp $
  35. //
  36. // Net_URL Class
  37. class Net_URL
  38. {
  39. /**
  40. * Full url
  41. * @var string
  42. */
  43. var $url;
  44. /**
  45. * Protocol
  46. * @var string
  47. */
  48. var $protocol;
  49. /**
  50. * Username
  51. * @var string
  52. */
  53. var $username;
  54. /**
  55. * Password
  56. * @var string
  57. */
  58. var $password;
  59. /**
  60. * Host
  61. * @var string
  62. */
  63. var $host;
  64. /**
  65. * Port
  66. * @var integer
  67. */
  68. var $port;
  69. /**
  70. * Path
  71. * @var string
  72. */
  73. var $path;
  74. /**
  75. * Query string
  76. * @var array
  77. */
  78. var $querystring;
  79. /**
  80. * Anchor
  81. * @var string
  82. */
  83. var $anchor;
  84. /**
  85. * Whether to use []
  86. * @var bool
  87. */
  88. var $useBrackets;
  89. /**
  90. * Constructor
  91. *
  92. * Parses the given url and stores the various parts
  93. * Defaults are used in certain cases
  94. *
  95. * @param string $url Optional URL
  96. * @param bool $useBrackets Whether to use square brackets when
  97. * multiple querystrings with the same name
  98. * exist
  99. */
  100. function Net_URL($url = null, $useBrackets = true)
  101. {
  102. global $HTTP_SERVER_VARS;
  103. $this->useBrackets = $useBrackets;
  104. $this->url = $url;
  105. $this->user = '';
  106. $this->pass = '';
  107. $this->host = '';
  108. $this->port = 80;
  109. $this->path = '';
  110. $this->querystring = array();
  111. $this->anchor = '';
  112. // Only use defaults if not an absolute URL given
  113. if (!preg_match('/^[a-z0-9]+:\/\//i', $url)) {
  114. /**
  115. * Figure out host/port
  116. */
  117. if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) {
  118. $host = $matches[1];
  119. if (!empty($matches[3])) {
  120. $port = $matches[3];
  121. } else {
  122. $port = '80';
  123. }
  124. }
  125. $this->protocol = 'http' . (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 's' : '');
  126. $this->user = '';
  127. $this->pass = '';
  128. $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
  129. $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : 80);
  130. $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
  131. $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
  132. $this->anchor = '';
  133. }
  134. // Parse the url and store the various parts
  135. if (!empty($url)) {
  136. $urlinfo = parse_url($url);
  137. // Default querystring
  138. $this->querystring = array();
  139. foreach ($urlinfo as $key => $value) {
  140. switch ($key) {
  141. case 'scheme':
  142. $this->protocol = $value;
  143. break;
  144. case 'user':
  145. case 'pass':
  146. case 'host':
  147. case 'port':
  148. $this->$key = $value;
  149. break;
  150. case 'path':
  151. if ($value{0} == '/') {
  152. $this->path = $value;
  153. } else {
  154. $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
  155. $this->path = sprintf('%s/%s', $path, $value);
  156. }
  157. break;
  158. case 'query':
  159. $this->querystring = $this->_parseRawQueryString($value);
  160. break;
  161. case 'fragment':
  162. $this->anchor = $value;
  163. break;
  164. }
  165. }
  166. }
  167. }
  168. /**
  169. * Returns full url
  170. *
  171. * @return string Full url
  172. * @access public
  173. */
  174. function getURL()
  175. {
  176. $querystring = $this->getQueryString();
  177. $this->url = $this->protocol . '://'
  178. . $this->user . (!empty($this->pass) ? ':' : '')
  179. . $this->pass . (!empty($this->user) ? '@' : '')
  180. . $this->host . ($this->port == '80' ? '' : ':' . $this->port)
  181. . $this->path
  182. . (!empty($querystring) ? '?' . $querystring : '')
  183. . (!empty($this->anchor) ? '#' . $this->anchor : '');
  184. return $this->url;
  185. }
  186. /**
  187. * Adds a querystring item
  188. *
  189. * @param string $name Name of item
  190. * @param string $value Value of item
  191. * @param bool $preencoded Whether value is urlencoded or not, default = not
  192. * @access public
  193. */
  194. function addQueryString($name, $value, $preencoded = false)
  195. {
  196. if ($preencoded) {
  197. $this->querystring[$name] = $value;
  198. } else {
  199. $this->querystring[$name] = is_array($value)? array_map('rawurlencode', $value): rawurlencode($value);
  200. }
  201. }
  202. /**
  203. * Removes a querystring item
  204. *
  205. * @param string $name Name of item
  206. * @access public
  207. */
  208. function removeQueryString($name)
  209. {
  210. if (isset($this->querystring[$name])) {
  211. unset($this->querystring[$name]);
  212. }
  213. }
  214. /**
  215. * Sets the querystring to literally what you supply
  216. *
  217. * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc
  218. * @access public
  219. */
  220. function addRawQueryString($querystring)
  221. {
  222. $this->querystring = $this->_parseRawQueryString($querystring);
  223. }
  224. /**
  225. * Returns flat querystring
  226. *
  227. * @return string Querystring
  228. * @access public
  229. */
  230. function getQueryString()
  231. {
  232. if (!empty($this->querystring)) {
  233. foreach ($this->querystring as $name => $value) {
  234. if (is_array($value)) {
  235. foreach ($value as $k => $v) {
  236. $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
  237. }
  238. } elseif (!is_null($value)) {
  239. $querystring[] = $name . '=' . $value;
  240. } else {
  241. $querystring[] = $name;
  242. }
  243. }
  244. $querystring = implode('&', $querystring);
  245. } else {
  246. $querystring = '';
  247. }
  248. return $querystring;
  249. }
  250. /**
  251. * Parses raw querystring and returns an array of it
  252. *
  253. * @param string $querystring The querystring to parse
  254. * @return array An array of the querystring data
  255. * @access private
  256. */
  257. function _parseRawQuerystring($querystring)
  258. {
  259. $parts = preg_split('/&/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
  260. $return = array();
  261. foreach ($parts as $part) {
  262. if (strpos($part, '=') !== false) {
  263. $value = substr($part, strpos($part, '=') + 1);
  264. $key = substr($part, 0, strpos($part, '='));
  265. } else {
  266. $value = null;
  267. $key = $part;
  268. }
  269. if (substr($key, -2) == '[]') {
  270. $key = substr($key, 0, -2);
  271. if (@!is_array($return[$key])) {
  272. $return[$key] = array();
  273. $return[$key][] = $value;
  274. } else {
  275. $return[$key][] = $value;
  276. }
  277. } elseif (!$this->useBrackets AND !empty($return[$key])) {
  278. $return[$key] = (array)$return[$key];
  279. $return[$key][] = $value;
  280. } else {
  281. $return[$key] = $value;
  282. }
  283. }
  284. return $return;
  285. }
  286. /**
  287. * Resolves //, ../ and ./ from a path and returns
  288. * the result. Eg:
  289. *
  290. * /foo/bar/../boo.php => /foo/boo.php
  291. * /foo/bar/../../boo.php => /boo.php
  292. * /foo/bar/.././/boo.php => /foo/boo.php
  293. *
  294. * This method can also be called statically.
  295. *
  296. * @param string $url URL path to resolve
  297. * @return string The result
  298. */
  299. function resolvePath($path)
  300. {
  301. $path = explode('/', str_replace('//', '/', $path));
  302. for ($i=0; $i<count($path); $i++) {
  303. if ($path[$i] == '.') {
  304. unset($path[$i]);
  305. $path = array_values($path);
  306. $i--;
  307. } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
  308. unset($path[$i]);
  309. unset($path[$i-1]);
  310. $path = array_values($path);
  311. $i -= 2;
  312. } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
  313. unset($path[$i]);
  314. $path = array_values($path);
  315. $i--;
  316. } else {
  317. continue;
  318. }
  319. }
  320. return implode('/', $path);
  321. }
  322. }
  323. ?>