PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/net/src/lmbUri.class.php

https://github.com/idler/limb
PHP | 543 lines | 409 code | 92 blank | 42 comment | 71 complexity | e70205d41edad3522a9a0fdb706cb5d1 MD5 | raw file
  1. <?php
  2. /*
  3. * Limb PHP Framework
  4. *
  5. * @link http://limb-project.com
  6. * @copyright Copyright &copy; 2004-2009 BIT(http://bit-creative.com)
  7. * @license LGPL http://www.gnu.org/copyleft/lesser.html
  8. */
  9. lmb_require('limb/core/src/lmbSet.class.php');
  10. lmb_require('limb/core/src/lmbArrayHelper.class.php');
  11. /**
  12. * class lmbUri.
  13. *
  14. * @package net
  15. * @version $Id: lmbUri.class.php 8124 2010-02-03 17:03:21Z 3dmax $
  16. */
  17. class lmbUri extends lmbSet
  18. {
  19. protected $protocol = '';
  20. protected $user = '';
  21. protected $password = '';
  22. protected $host = '';
  23. protected $port = '';
  24. protected $path = '';
  25. protected $anchor = '';
  26. protected $query_items = array();
  27. protected $path_elements = array();
  28. function __construct($str='')
  29. {
  30. if($str)
  31. $this->reset($str);
  32. }
  33. static function addQueryItems($url, $items=array())
  34. {
  35. $str_params = '';
  36. if(strpos($url, '?') === false)
  37. $url .= '?';
  38. else
  39. $url .= '&';
  40. $str_params_arr = array();
  41. foreach($items as $key => $val)
  42. {
  43. $url = preg_replace("/&*{$key}=[^&]*/", '', $url);
  44. $str_params_arr[] = "$key=$val";
  45. }
  46. $items = explode('#', $url);
  47. $url = $items[0];
  48. $fragment = isset($items[1]) ? '#' . $items[1] : '';
  49. return $url . implode('&', $str_params_arr) . $fragment;
  50. }
  51. function reset($str = null)
  52. {
  53. $this->user = '';
  54. $this->password = '';
  55. $this->host = '';
  56. $this->port = '';
  57. $this->path = '';
  58. $this->query_items = array();
  59. $this->anchor = '';
  60. $this->path_elements = array();
  61. if(!$str)
  62. return;
  63. if('file' == substr($str, 0, 4))
  64. $str = $this->_fixFileProtocol($str);
  65. if(!$urlinfo = @parse_url($str))
  66. throw new lmbException("URI '$str' is not valid");
  67. foreach($urlinfo as $key => $value)
  68. {
  69. switch($key)
  70. {
  71. case 'scheme':
  72. $this->setProtocol($value);
  73. break;
  74. case 'user':
  75. $this->setUser($value);
  76. break;
  77. case 'host':
  78. $this->setHost($value);
  79. break;
  80. case 'port':
  81. $this->setPort($value);
  82. break;
  83. case 'pass':
  84. $this->setPassword($value);
  85. break;
  86. case 'path':
  87. $this->setPath($value);
  88. break;
  89. case 'query':
  90. $this->setQueryString($value);
  91. break;
  92. case 'fragment':
  93. $this->setAnchor($value);
  94. break;
  95. }
  96. }
  97. }
  98. /**
  99. * @deprecated
  100. */
  101. function parse($uri)
  102. {
  103. $this->reset($uri);
  104. }
  105. protected function _fixFileProtocol($url)
  106. {
  107. $matches = array();
  108. if(preg_match('!^file://([a-z]?:[\\\/].*)!i', $url, $matches))
  109. $url = 'file:///' . $matches[1];
  110. return $url;
  111. }
  112. function getProtocol()
  113. {
  114. return $this->protocol;
  115. }
  116. function getUser()
  117. {
  118. return $this->user;
  119. }
  120. function getPassword()
  121. {
  122. return $this->password;
  123. }
  124. function getHost()
  125. {
  126. return $this->host;
  127. }
  128. function getPort()
  129. {
  130. return $this->port;
  131. }
  132. function getPath()
  133. {
  134. return $this->path;
  135. }
  136. function getAnchor()
  137. {
  138. return $this->anchor;
  139. }
  140. function setProtocol($protocol)
  141. {
  142. $this->protocol = $protocol;
  143. return $this;
  144. }
  145. function setUser($user)
  146. {
  147. $this->user = $user;
  148. return $this;
  149. }
  150. function setPassword($password)
  151. {
  152. $this->password = $password;
  153. return $this;
  154. }
  155. function setHost($host)
  156. {
  157. $this->host = $host;
  158. return $this;
  159. }
  160. function setPort($port)
  161. {
  162. $this->port = $port;
  163. return $this;
  164. }
  165. function setPath($path)
  166. {
  167. $this->path = $path;
  168. $this->path_elements = explode('/',$this->path);
  169. return $this;
  170. }
  171. function setAnchor($anchor)
  172. {
  173. $this->anchor = $anchor;
  174. return $this;
  175. }
  176. function isAbsolute()
  177. {
  178. if(!strlen($this->path))
  179. return true;
  180. return ('/' == $this->path{0});
  181. }
  182. function isRelative()
  183. {
  184. return !$this->isAbsolute();
  185. }
  186. function countPath()
  187. {
  188. return sizeof($this->path_elements);
  189. }
  190. function countQueryItems()
  191. {
  192. return sizeof($this->query_items);
  193. }
  194. function compare($uri)
  195. {
  196. return (
  197. $this->protocol == $uri->getProtocol() &&
  198. $this->host == $uri->getHost() &&
  199. $this->port == $uri->getPort() &&
  200. $this->user === $uri->getUser() &&
  201. $this->password === $uri->getPassword() &&
  202. $this->compareQuery($uri) &&
  203. $this->comparePath($uri) === 0
  204. );
  205. }
  206. function compareQuery($uri)
  207. {
  208. if ($this->countQueryItems() != $uri->countQueryItems())
  209. return false;
  210. foreach($this->query_items as $name => $value)
  211. {
  212. if( (($item = $uri->getQueryItem($name)) === false) ||
  213. $item != $value)
  214. return false;
  215. }
  216. return true;
  217. }
  218. function comparePath($uri)
  219. {
  220. $count1 = $this->countPath();
  221. $count2 = $uri->countPath();
  222. $iterCount = min($count1, $count2);
  223. for($i=0; $i < $iterCount; $i++)
  224. {
  225. if( $this->getPathElement($i) != $uri->getPathElement($i) )
  226. return false;
  227. }
  228. return ($count1 - $count2);
  229. }
  230. function toString($parts = array('protocol', 'user', 'password', 'host', 'port', 'path', 'query', 'anchor'))
  231. {
  232. $string = '';
  233. if(in_array('protocol', $parts))
  234. $string .= !empty($this->protocol) ? $this->protocol . '://' : '';
  235. if(in_array('user', $parts))
  236. {
  237. $string .= $this->user;
  238. if(in_array('password', $parts))
  239. $string .= (!empty($this->password) ? ':' : '') . $this->password;
  240. $string .= (!empty($this->user) ? '@' : '');
  241. }
  242. if(in_array('host', $parts))
  243. {
  244. $string .= $this->host;
  245. if(in_array('port', $parts))
  246. $string .= (empty($this->port) || ($this->port == '80') ? '' : ':' . $this->port);
  247. }
  248. else
  249. $string = '';
  250. if(in_array('path', $parts))
  251. $string .= $this->getPath();
  252. if(in_array('query', $parts))
  253. {
  254. $query_string = $this->getQueryString();
  255. $string .= !empty($query_string) ? '?' . $query_string : '';
  256. }
  257. if(in_array('anchor', $parts))
  258. $string .= !empty($this->anchor) ? '#' . $this->anchor : '';
  259. return $string;
  260. }
  261. function getPathElement($level)
  262. {
  263. return isset($this->path_elements[$level]) ? $this->path_elements[$level] : '';
  264. }
  265. function getPathElements()
  266. {
  267. return $this->path_elements;
  268. }
  269. function getPathToLevel($level)
  270. {
  271. if(!$this->path_elements || $level >= sizeof($this->path_elements))
  272. return '';
  273. $items = array();
  274. for($i = 0; $i <= $level; $i++)
  275. $items[] = $this->path_elements[$i];
  276. return implode('/', $items);
  277. }
  278. function getPathFromLevel($level)
  279. {
  280. if($level <= 0)
  281. return $this->path;
  282. if(!$this->path_elements || $level >= sizeof($this->path_elements))
  283. return '/';
  284. $items[] = '';
  285. for($i = $level; $i < sizeof($this->path_elements); $i++)
  286. $items[] = $this->path_elements[$i];
  287. return implode('/', $items);
  288. }
  289. function addEncodedQueryItem($name, $value)
  290. {
  291. $this->query_items[$name] = $value;
  292. return $this;
  293. }
  294. function addQueryItem($name, $value)
  295. {
  296. $this->query_items[$name] = $value;
  297. return $this;
  298. }
  299. function getQueryItem($name)
  300. {
  301. if (isset($this->query_items[$name]))
  302. return $this->query_items[$name];
  303. return false;
  304. }
  305. function getQueryItems()
  306. {
  307. return $this->query_items;
  308. }
  309. function setQueryItems($items)
  310. {
  311. $this->query_items = $items;
  312. return $this;
  313. }
  314. /**
  315. * Removes a query_string item
  316. *
  317. */
  318. function removeQueryItem($name)
  319. {
  320. if (isset($this->query_items[$name]))
  321. unset($this->query_items[$name]);
  322. }
  323. /**
  324. * Sets the query_string to literally what you supply
  325. */
  326. function setQueryString($query_string)
  327. {
  328. $this->query_items = $this->_parseQueryString($query_string);
  329. return $this;
  330. }
  331. /**
  332. * Removes query items
  333. */
  334. function removeQueryItems()
  335. {
  336. $this->query_items = array();
  337. return $this;
  338. }
  339. /**
  340. * Returns flat query_string
  341. *
  342. */
  343. function getQueryString()
  344. {
  345. $query_string = '';
  346. $query_items = array();
  347. $flat_array = array();
  348. lmbArrayHelper :: toFlatArray($this->query_items, $flat_array);
  349. ksort($flat_array);
  350. foreach($flat_array as $key => $value)
  351. {
  352. if($value != '' || is_null($value))
  353. $query_items[] = $key . '=' . urlencode($value);
  354. else
  355. $query_items[] = $key;
  356. }
  357. if($query_items)
  358. $query_string = implode('&', $query_items);
  359. return $query_string;
  360. }
  361. /**
  362. * Parses raw query_string and returns an array of it
  363. */
  364. protected function _parseQueryString($query_string)
  365. {
  366. $items = array();
  367. if(!$query_string)
  368. return $items;
  369. $arg_separator = ini_get('arg_separator.input');
  370. foreach(explode($arg_separator, $query_string) as $pair)
  371. {
  372. $parts = explode('=', $pair);
  373. if(!is_array($parts) || count($parts) != 2)
  374. continue;
  375. if($pos = strpos($parts[0], '['))
  376. {
  377. $key = substr($parts[0], 0, $pos);
  378. $subkey = substr($parts[0], $pos + 1, -1);
  379. }
  380. else
  381. {
  382. $key = $parts[0];
  383. $subkey = null;
  384. }
  385. $val = urldecode($parts[1]);
  386. if(isset($items[$key]))
  387. {
  388. if(is_array($items[$key]))
  389. {
  390. if(!is_null($subkey) && $subkey != '')
  391. $items[$key][$subkey] = $val;
  392. else
  393. $items[$key][] = $val;
  394. }
  395. else
  396. $items[$key] = array($items[$key], $val);
  397. }
  398. else
  399. {
  400. if(!is_null($subkey) && $subkey != '')
  401. $items[$key][$subkey] = $val;
  402. elseif(!is_null($subkey) && $subkey == '')
  403. $items[$key][] = $val;
  404. else
  405. $items[$key] = $val;
  406. }
  407. }
  408. ksort($items);
  409. return $items;
  410. }
  411. /**
  412. * Resolves //, ../ and ./ from a path and returns
  413. * the result. Eg:
  414. *
  415. * /foo/bar/../boo.php => /foo/boo.php
  416. * /foo/bar/../../boo.php => /boo.php
  417. * /foo/bar/.././/boo.php => /foo/boo.php
  418. *
  419. */
  420. function normalizePath()
  421. {
  422. $path = $this->path;
  423. $path = explode('/', preg_replace('~[\/]+~', '/', $path));
  424. for ($i=0; $i < sizeof($path); $i++)
  425. {
  426. if ($path[$i] == '.')
  427. {
  428. unset($path[$i]);
  429. $path = array_values($path);
  430. $i--;
  431. }
  432. elseif ($path[$i] == '..' && ($i > 1 || ($i == 1 && $path[0] != '') ) )
  433. {
  434. unset($path[$i]);
  435. unset($path[$i-1]);
  436. $path = array_values($path);
  437. $i -= 2;
  438. }
  439. elseif ($path[$i] == '..' && $i == 1 && $path[0] == '')
  440. {
  441. unset($path[$i]);
  442. $path = array_values($path);
  443. $i--;
  444. }
  445. else
  446. continue;
  447. }
  448. $this->setPath(implode('/', $path));
  449. return $this;
  450. }
  451. }