PageRenderTime 61ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/inc/app/siteinvoice/lib/PEAR/Net/URL.php

https://github.com/lux/siteforge
PHP | 410 lines | 202 code | 44 blank | 164 comment | 37 complexity | 6abcc6fcdf581ae5ef5ba48c45a71898 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0
  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 at php net> |
  33. // +-----------------------------------------------------------------------+
  34. //
  35. // $Id: URL.php,v 1.1 2005/07/02 21:12:30 lux Exp $
  36. //
  37. // Net_URL Class
  38. class Net_URL
  39. {
  40. /**
  41. * Full url
  42. * @var string
  43. */
  44. var $url;
  45. /**
  46. * Protocol
  47. * @var string
  48. */
  49. var $protocol;
  50. /**
  51. * Username
  52. * @var string
  53. */
  54. var $username;
  55. /**
  56. * Password
  57. * @var string
  58. */
  59. var $password;
  60. /**
  61. * Host
  62. * @var string
  63. */
  64. var $host;
  65. /**
  66. * Port
  67. * @var integer
  68. */
  69. var $port;
  70. /**
  71. * Path
  72. * @var string
  73. */
  74. var $path;
  75. /**
  76. * Query string
  77. * @var array
  78. */
  79. var $querystring;
  80. /**
  81. * Anchor
  82. * @var string
  83. */
  84. var $anchor;
  85. /**
  86. * Whether to use []
  87. * @var bool
  88. */
  89. var $useBrackets;
  90. /**
  91. * PHP4 Constructor
  92. *
  93. * @see __construct()
  94. */
  95. function Net_URL($url = null, $useBrackets = true)
  96. {
  97. $this->__construct($url, $useBrackets);
  98. }
  99. /**
  100. * PHP5 Constructor
  101. *
  102. * Parses the given url and stores the various parts
  103. * Defaults are used in certain cases
  104. *
  105. * @param string $url Optional URL
  106. * @param bool $useBrackets Whether to use square brackets when
  107. * multiple querystrings with the same name
  108. * exist
  109. */
  110. function __construct($url = null, $useBrackets = true)
  111. {
  112. $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
  113. $this->useBrackets = $useBrackets;
  114. $this->url = $url;
  115. $this->user = '';
  116. $this->pass = '';
  117. $this->host = '';
  118. $this->port = 80;
  119. $this->path = '';
  120. $this->querystring = array();
  121. $this->anchor = '';
  122. // Only use defaults if not an absolute URL given
  123. if (!preg_match('/^[a-z0-9]+:\/\//i', $url)) {
  124. $this->protocol = (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http');
  125. /**
  126. * Figure out host/port
  127. */
  128. if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) {
  129. $host = $matches[1];
  130. if (!empty($matches[3])) {
  131. $port = $matches[3];
  132. } else {
  133. $port = $this->getStandardPort($this->protocol);
  134. }
  135. }
  136. $this->user = '';
  137. $this->pass = '';
  138. $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
  139. $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
  140. $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
  141. $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
  142. $this->anchor = '';
  143. }
  144. // Parse the url and store the various parts
  145. if (!empty($url)) {
  146. $urlinfo = parse_url($url);
  147. // Default querystring
  148. $this->querystring = array();
  149. foreach ($urlinfo as $key => $value) {
  150. switch ($key) {
  151. case 'scheme':
  152. $this->protocol = $value;
  153. $this->port = $this->getStandardPort($value);
  154. break;
  155. case 'user':
  156. case 'pass':
  157. case 'host':
  158. case 'port':
  159. $this->$key = $value;
  160. break;
  161. case 'path':
  162. if ($value{0} == '/') {
  163. $this->path = $value;
  164. } else {
  165. $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
  166. $this->path = sprintf('%s/%s', $path, $value);
  167. }
  168. break;
  169. case 'query':
  170. $this->querystring = $this->_parseRawQueryString($value);
  171. break;
  172. case 'fragment':
  173. $this->anchor = $value;
  174. break;
  175. }
  176. }
  177. }
  178. }
  179. /**
  180. * Returns full url
  181. *
  182. * @return string Full url
  183. * @access public
  184. */
  185. function getURL()
  186. {
  187. $querystring = $this->getQueryString();
  188. $this->url = $this->protocol . '://'
  189. . $this->user . (!empty($this->pass) ? ':' : '')
  190. . $this->pass . (!empty($this->user) ? '@' : '')
  191. . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
  192. . $this->path
  193. . (!empty($querystring) ? '?' . $querystring : '')
  194. . (!empty($this->anchor) ? '#' . $this->anchor : '');
  195. return $this->url;
  196. }
  197. /**
  198. * Adds a querystring item
  199. *
  200. * @param string $name Name of item
  201. * @param string $value Value of item
  202. * @param bool $preencoded Whether value is urlencoded or not, default = not
  203. * @access public
  204. */
  205. function addQueryString($name, $value, $preencoded = false)
  206. {
  207. if ($preencoded) {
  208. $this->querystring[$name] = $value;
  209. } else {
  210. $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
  211. }
  212. }
  213. /**
  214. * Removes a querystring item
  215. *
  216. * @param string $name Name of item
  217. * @access public
  218. */
  219. function removeQueryString($name)
  220. {
  221. if (isset($this->querystring[$name])) {
  222. unset($this->querystring[$name]);
  223. }
  224. }
  225. /**
  226. * Sets the querystring to literally what you supply
  227. *
  228. * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc
  229. * @access public
  230. */
  231. function addRawQueryString($querystring)
  232. {
  233. $this->querystring = $this->_parseRawQueryString($querystring);
  234. }
  235. /**
  236. * Returns flat querystring
  237. *
  238. * @return string Querystring
  239. * @access public
  240. */
  241. function getQueryString()
  242. {
  243. if (!empty($this->querystring)) {
  244. foreach ($this->querystring as $name => $value) {
  245. if (is_array($value)) {
  246. foreach ($value as $k => $v) {
  247. $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
  248. }
  249. } elseif (!is_null($value)) {
  250. $querystring[] = $name . '=' . $value;
  251. } else {
  252. $querystring[] = $name;
  253. }
  254. }
  255. $querystring = implode(ini_get('arg_separator.output'), $querystring);
  256. } else {
  257. $querystring = '';
  258. }
  259. return $querystring;
  260. }
  261. /**
  262. * Parses raw querystring and returns an array of it
  263. *
  264. * @param string $querystring The querystring to parse
  265. * @return array An array of the querystring data
  266. * @access private
  267. */
  268. function _parseRawQuerystring($querystring)
  269. {
  270. $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
  271. $return = array();
  272. foreach ($parts as $part) {
  273. if (strpos($part, '=') !== false) {
  274. $value = substr($part, strpos($part, '=') + 1);
  275. $key = substr($part, 0, strpos($part, '='));
  276. } else {
  277. $value = null;
  278. $key = $part;
  279. }
  280. if (substr($key, -2) == '[]') {
  281. $key = substr($key, 0, -2);
  282. if (@!is_array($return[$key])) {
  283. $return[$key] = array();
  284. $return[$key][] = $value;
  285. } else {
  286. $return[$key][] = $value;
  287. }
  288. } elseif (!$this->useBrackets AND !empty($return[$key])) {
  289. $return[$key] = (array)$return[$key];
  290. $return[$key][] = $value;
  291. } else {
  292. $return[$key] = $value;
  293. }
  294. }
  295. return $return;
  296. }
  297. /**
  298. * Resolves //, ../ and ./ from a path and returns
  299. * the result. Eg:
  300. *
  301. * /foo/bar/../boo.php => /foo/boo.php
  302. * /foo/bar/../../boo.php => /boo.php
  303. * /foo/bar/.././/boo.php => /foo/boo.php
  304. *
  305. * This method can also be called statically.
  306. *
  307. * @param string $url URL path to resolve
  308. * @return string The result
  309. */
  310. function resolvePath($path)
  311. {
  312. $path = explode('/', str_replace('//', '/', $path));
  313. for ($i=0; $i<count($path); $i++) {
  314. if ($path[$i] == '.') {
  315. unset($path[$i]);
  316. $path = array_values($path);
  317. $i--;
  318. } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
  319. unset($path[$i]);
  320. unset($path[$i-1]);
  321. $path = array_values($path);
  322. $i -= 2;
  323. } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
  324. unset($path[$i]);
  325. $path = array_values($path);
  326. $i--;
  327. } else {
  328. continue;
  329. }
  330. }
  331. return implode('/', $path);
  332. }
  333. /**
  334. * Returns the standard port number for a protocol
  335. *
  336. * @param string $scheme The protocol to lookup
  337. * @return integer Port number or NULL if no scheme matches
  338. *
  339. * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
  340. */
  341. function getStandardPort($scheme)
  342. {
  343. switch (strtolower($scheme)) {
  344. case 'http': return 80;
  345. case 'https': return 443;
  346. case 'ftp': return 21;
  347. case 'imap': return 143;
  348. case 'imaps': return 993;
  349. case 'pop3': return 110;
  350. case 'pop3s': return 995;
  351. default: return null;
  352. }
  353. }
  354. /**
  355. * Forces the URL to a particular protocol
  356. *
  357. * @param string $protocol Protocol to force the URL to
  358. * @param integer $port Optional port (standard port is used by default)
  359. */
  360. function setProtocol($protocol, $port = null)
  361. {
  362. $this->protocol = $protocol;
  363. $this->port = is_null($port) ? $this->getStandardPort() : $port;
  364. }
  365. }
  366. ?>