PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/PEAR/Net/URL.php

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