Uri.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. <?php
  2. /**
  3. * @file
  4. * TeamSpeak 3 PHP Framework
  5. *
  6. * $Id: Uri.php 06/06/2016 22:27:13 scp@Svens-iMac $
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. * @package TeamSpeak3
  22. * @version 1.1.24
  23. * @author Sven 'ScP' Paulsen
  24. * @copyright Copyright (c) 2010 by Planet TeamSpeak. All rights reserved.
  25. */
  26. /**
  27. * @class TeamSpeak3_Helper_Uri
  28. * @brief Helper class for URI handling.
  29. */
  30. class TeamSpeak3_Helper_Uri
  31. {
  32. /**
  33. * Stores the URI scheme.
  34. *
  35. * @var string
  36. */
  37. protected $scheme = null;
  38. /**
  39. * Stores the URI username
  40. *
  41. * @var string
  42. */
  43. protected $user = null;
  44. /**
  45. * Stores the URI password.
  46. *
  47. * @var string
  48. */
  49. protected $pass = null;
  50. /**
  51. * Stores the URI host.
  52. *
  53. * @var string
  54. */
  55. protected $host = null;
  56. /**
  57. * Stores the URI port.
  58. *
  59. * @var string
  60. */
  61. protected $port = null;
  62. /**
  63. * Stores the URI path.
  64. *
  65. * @var string
  66. */
  67. protected $path = null;
  68. /**
  69. * Stores the URI query string.
  70. *
  71. * @var string
  72. */
  73. protected $query = null;
  74. /**
  75. * Stores the URI fragment string.
  76. *
  77. * @var string
  78. */
  79. protected $fragment = null;
  80. /**
  81. * Stores grammar rules for validation via regex.
  82. *
  83. * @var array
  84. */
  85. protected $regex = array();
  86. /**
  87. * The TeamSpeak3_Helper_Uri constructor.
  88. *
  89. * @param string $uri
  90. * @throws TeamSpeak3_Helper_Exception
  91. * @return TeamSpeak3_Helper_Uri
  92. */
  93. public function __construct($uri)
  94. {
  95. $uri = explode(":", strval($uri), 2);
  96. $this->scheme = strtolower($uri[0]);
  97. $uriString = isset($uri[1]) ? $uri[1] : "";
  98. if(!ctype_alnum($this->scheme))
  99. {
  100. throw new TeamSpeak3_Helper_Exception("invalid URI scheme '" . $this->scheme . "' supplied");
  101. }
  102. /* grammar rules for validation */
  103. $this->regex["alphanum"] = "[^\W_]";
  104. $this->regex["escaped"] = "(?:%[\da-fA-F]{2})";
  105. $this->regex["mark"] = "[-_.!~*'()\[\]]";
  106. $this->regex["reserved"] = "[;\/?:@&=+$,]";
  107. $this->regex["unreserved"] = "(?:" . $this->regex["alphanum"] . "|" . $this->regex["mark"] . ")";
  108. $this->regex["segment"] = "(?:(?:" . $this->regex["unreserved"] . "|" . $this->regex["escaped"] . "|[:@&=+$,;])*)";
  109. $this->regex["path"] = "(?:\/" . $this->regex["segment"] . "?)+";
  110. $this->regex["uric"] = "(?:" . $this->regex["reserved"] . "|" . $this->regex["unreserved"] . "|" . $this->regex["escaped"] . ")";
  111. if(strlen($uriString) > 0)
  112. {
  113. $this->parseUri($uriString);
  114. }
  115. if(!$this->isValid())
  116. {
  117. throw new TeamSpeak3_Helper_Exception("invalid URI supplied");
  118. }
  119. }
  120. /**
  121. * Parses the scheme-specific portion of the URI and place its parts into instance variables.
  122. *
  123. * @throws TeamSpeak3_Helper_Exception
  124. * @return void
  125. */
  126. protected function parseUri($uriString = '')
  127. {
  128. $status = @preg_match("~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~", $uriString, $matches);
  129. if($status === FALSE)
  130. {
  131. throw new TeamSpeak3_Helper_Exception("URI scheme-specific decomposition failed");
  132. }
  133. if(!$status) return;
  134. $this->path = (isset($matches[4])) ? $matches[4] : '';
  135. $this->query = (isset($matches[6])) ? $matches[6] : '';
  136. $this->fragment = (isset($matches[8])) ? $matches[8] : '';
  137. $status = @preg_match("~^(([^:@]*)(:([^@]*))?@)?((?(?=[[])[[][^]]+[]]|[^:]+))(:(.*))?$~", (isset($matches[3])) ? $matches[3] : "", $matches);
  138. if($status === FALSE)
  139. {
  140. throw new TeamSpeak3_Helper_Exception("URI scheme-specific authority decomposition failed");
  141. }
  142. if(!$status) return;
  143. $this->user = isset($matches[2]) ? $matches[2] : "";
  144. $this->pass = isset($matches[4]) ? $matches[4] : "";
  145. $this->host = isset($matches[5]) === TRUE ? preg_replace('~^\[([^]]+)\]$~', '\1', $matches[5]) : "";
  146. $this->port = isset($matches[7]) ? $matches[7] : "";
  147. }
  148. /**
  149. * Validate the current URI from the instance variables.
  150. *
  151. * @return boolean
  152. */
  153. public function isValid()
  154. {
  155. return ($this->checkUser() && $this->checkPass() && $this->checkHost() && $this->checkPort() && $this->checkPath() && $this->checkQuery() && $this->checkFragment());
  156. }
  157. /**
  158. * Returns TRUE if a given URI is valid.
  159. *
  160. * @param string $uri
  161. * @return boolean
  162. */
  163. public static function check($uri)
  164. {
  165. try
  166. {
  167. $uri = new self(strval($uri));
  168. }
  169. catch(Exception $e)
  170. {
  171. return FALSE;
  172. }
  173. return $uri->valid();
  174. }
  175. /**
  176. * Returns TRUE if the URI has a scheme.
  177. *
  178. * @return boolean
  179. */
  180. public function hasScheme()
  181. {
  182. return strlen($this->scheme) ? TRUE : FALSE;
  183. }
  184. /**
  185. * Returns the scheme.
  186. *
  187. * @param mixed default
  188. * @return TeamSpeak3_Helper_String
  189. */
  190. public function getScheme($default = null)
  191. {
  192. return ($this->hasScheme()) ? new TeamSpeak3_Helper_String($this->scheme) : $default;
  193. }
  194. /**
  195. * Returns TRUE if the username is valid.
  196. *
  197. * @param string $username
  198. * @throws TeamSpeak3_Helper_Exception
  199. * @return boolean
  200. */
  201. public function checkUser($username = null)
  202. {
  203. if($username === null)
  204. {
  205. $username = $this->user;
  206. }
  207. if(strlen($username) == 0)
  208. {
  209. return TRUE;
  210. }
  211. $pattern = "/^(" . $this->regex["alphanum"] . "|" . $this->regex["mark"] . "|" . $this->regex["escaped"] . "|[;:&=+$,])+$/";
  212. $status = @preg_match($pattern, $username);
  213. if($status === FALSE)
  214. {
  215. throw new TeamSpeak3_Helper_Exception("URI username validation failed");
  216. }
  217. return ($status == 1);
  218. }
  219. /**
  220. * Returns TRUE if the URI has a username.
  221. *
  222. * @return boolean
  223. */
  224. public function hasUser()
  225. {
  226. return strlen($this->user) ? TRUE : FALSE;
  227. }
  228. /**
  229. * Returns the username.
  230. *
  231. * @param mixed default
  232. * @return TeamSpeak3_Helper_String
  233. */
  234. public function getUser($default = null)
  235. {
  236. return ($this->hasUser()) ? new TeamSpeak3_Helper_String($this->user) : $default;
  237. }
  238. /**
  239. * Returns TRUE if the password is valid.
  240. *
  241. * @param string $password
  242. * @throws TeamSpeak3_Helper_Exception
  243. * @return boolean
  244. */
  245. public function checkPass($password = null)
  246. {
  247. if($password === null) {
  248. $password = $this->pass;
  249. }
  250. if(strlen($password) == 0)
  251. {
  252. return TRUE;
  253. }
  254. $pattern = "/^(" . $this->regex["alphanum"] . "|" . $this->regex["mark"] . "|" . $this->regex["escaped"] . "|[;:&=+$,])+$/";
  255. $status = @preg_match($pattern, $password);
  256. if($status === FALSE)
  257. {
  258. throw new TeamSpeak3_Helper_Exception("URI password validation failed");
  259. }
  260. return ($status == 1);
  261. }
  262. /**
  263. * Returns TRUE if the URI has a password.
  264. *
  265. * @return boolean
  266. */
  267. public function hasPass()
  268. {
  269. return strlen($this->pass) ? TRUE : FALSE;
  270. }
  271. /**
  272. * Returns the password.
  273. *
  274. * @param mixed default
  275. * @return TeamSpeak3_Helper_String
  276. */
  277. public function getPass($default = null)
  278. {
  279. return ($this->hasPass()) ? new TeamSpeak3_Helper_String($this->pass) : $default;
  280. }
  281. /**
  282. * Returns TRUE if the host is valid.
  283. *
  284. * @param string $host
  285. * @return boolean
  286. */
  287. public function checkHost($host = null)
  288. {
  289. if($host === null)
  290. {
  291. $host = $this->host;
  292. }
  293. return TRUE;
  294. }
  295. /**
  296. * Returns TRUE if the URI has a host.
  297. *
  298. * @return boolean
  299. */
  300. public function hasHost()
  301. {
  302. return strlen($this->host) ? TRUE : FALSE;
  303. }
  304. /**
  305. * Returns the host.
  306. *
  307. * @param mixed default
  308. * @return TeamSpeak3_Helper_String
  309. */
  310. public function getHost($default = null)
  311. {
  312. return ($this->hasHost()) ? new TeamSpeak3_Helper_String($this->host) : $default;
  313. }
  314. /**
  315. * Returns TRUE if the port is valid.
  316. *
  317. * @param integer $port
  318. * @return boolean
  319. */
  320. public function checkPort($port = null)
  321. {
  322. if($port === null)
  323. {
  324. $port = $this->port;
  325. }
  326. return TRUE;
  327. }
  328. /**
  329. * Returns TRUE if the URI has a port.
  330. *
  331. * @return boolean
  332. */
  333. public function hasPort()
  334. {
  335. return strlen($this->port) ? TRUE : FALSE;
  336. }
  337. /**
  338. * Returns the port.
  339. *
  340. * @param mixed default
  341. * @return integer
  342. */
  343. public function getPort($default = null)
  344. {
  345. return ($this->hasPort()) ? intval($this->port) : $default;
  346. }
  347. /**
  348. * Returns TRUE if the path is valid.
  349. *
  350. * @param string $path
  351. * @throws TeamSpeak3_Helper_Exception
  352. * @return boolean
  353. */
  354. public function checkPath($path = null)
  355. {
  356. if($path === null)
  357. {
  358. $path = $this->path;
  359. }
  360. if(strlen($path) == 0)
  361. {
  362. return TRUE;
  363. }
  364. $pattern = "/^" . $this->regex["path"] . "$/";
  365. $status = @preg_match($pattern, $path);
  366. if($status === FALSE)
  367. {
  368. throw new TeamSpeak3_Helper_Exception("URI path validation failed");
  369. }
  370. return ($status == 1);
  371. }
  372. /**
  373. * Returns TRUE if the URI has a path.
  374. *
  375. * @return boolean
  376. */
  377. public function hasPath()
  378. {
  379. return strlen($this->path) ? TRUE : FALSE;
  380. }
  381. /**
  382. * Returns the path.
  383. *
  384. * @param mixed default
  385. * @return TeamSpeak3_Helper_String
  386. */
  387. public function getPath($default = null)
  388. {
  389. return ($this->hasPath()) ? new TeamSpeak3_Helper_String($this->path) : $default;
  390. }
  391. /**
  392. * Returns TRUE if the query string is valid.
  393. *
  394. * @param string $query
  395. * @throws TeamSpeak3_Helper_Exception
  396. * @return boolean
  397. */
  398. public function checkQuery($query = null)
  399. {
  400. if($query === null)
  401. {
  402. $query = $this->query;
  403. }
  404. if(strlen($query) == 0)
  405. {
  406. return TRUE;
  407. }
  408. $pattern = "/^" . $this->regex["uric"] . "*$/";
  409. $status = @preg_match($pattern, $query);
  410. if($status === FALSE)
  411. {
  412. throw new TeamSpeak3_Helper_Exception("URI query string validation failed");
  413. }
  414. return ($status == 1);
  415. }
  416. /**
  417. * Returns TRUE if the URI has a query string.
  418. *
  419. * @return boolean
  420. */
  421. public function hasQuery()
  422. {
  423. return strlen($this->query) ? TRUE : FALSE;
  424. }
  425. /**
  426. * Returns an array containing the query string elements.
  427. *
  428. * @param mixed $default
  429. * @return array
  430. */
  431. public function getQuery($default = array())
  432. {
  433. if(!$this->hasQuery())
  434. {
  435. return $default;
  436. }
  437. parse_str($this->query, $queryArray);
  438. return $queryArray;
  439. }
  440. /**
  441. * Returns TRUE if the URI has a query variable.
  442. *
  443. * @return boolean
  444. */
  445. public function hasQueryVar($key)
  446. {
  447. if(!$this->hasQuery()) return FALSE;
  448. parse_str($this->query, $queryArray);
  449. return array_key_exists($key, $queryArray) ? TRUE : FALSE;
  450. }
  451. /**
  452. * Returns a single variable from the query string.
  453. *
  454. * @param string $key
  455. * @param mixed $default
  456. * @return mixed
  457. */
  458. public function getQueryVar($key, $default = null)
  459. {
  460. if(!$this->hasQuery()) return $default;
  461. parse_str($this->query, $queryArray);
  462. if(array_key_exists($key, $queryArray))
  463. {
  464. $val = $queryArray[$key];
  465. if(ctype_digit($val))
  466. {
  467. return intval($val);
  468. }
  469. elseif(is_string($val))
  470. {
  471. return new TeamSpeak3_Helper_String($val);
  472. }
  473. else
  474. {
  475. return $val;
  476. }
  477. }
  478. return $default;
  479. }
  480. /**
  481. * Returns TRUE if the fragment string is valid.
  482. *
  483. * @param string $fragment
  484. * @throws TeamSpeak3_Helper_Exception
  485. * @return boolean
  486. */
  487. public function checkFragment($fragment = null)
  488. {
  489. if($fragment === null)
  490. {
  491. $fragment = $this->fragment;
  492. }
  493. if(strlen($fragment) == 0)
  494. {
  495. return TRUE;
  496. }
  497. $pattern = "/^" . $this->regex["uric"] . "*$/";
  498. $status = @preg_match($pattern, $fragment);
  499. if($status === FALSE)
  500. {
  501. throw new TeamSpeak3_Helper_Exception("URI fragment validation failed");
  502. }
  503. return ($status == 1);
  504. }
  505. /**
  506. * Returns TRUE if the URI has a fragment string.
  507. *
  508. * @return boolean
  509. */
  510. public function hasFragment()
  511. {
  512. return strlen($this->fragment) ? TRUE : FALSE;
  513. }
  514. /**
  515. * Returns the fragment.
  516. *
  517. * @param mixed default
  518. * @return TeamSpeak3_Helper_String
  519. */
  520. public function getFragment($default = null)
  521. {
  522. return ($this->hasFragment()) ? new TeamSpeak3_Helper_String($this->fragment) : $default;
  523. }
  524. /**
  525. * Returns a specified instance parameter from the $_REQUEST array.
  526. *
  527. * @param string $key
  528. * @param mixed $default
  529. * @return mixed
  530. */
  531. public static function getUserParam($key, $default = null)
  532. {
  533. return (array_key_exists($key, $_REQUEST) && !empty($_REQUEST[$key])) ? self::stripslashesRecursive($_REQUEST[$key]) : $default;
  534. }
  535. /**
  536. * Returns a specified environment parameter from the $_SERVER array.
  537. *
  538. * @param string $key
  539. * @param mixed $default
  540. * @return mixed
  541. */
  542. public static function getHostParam($key, $default = null)
  543. {
  544. return (array_key_exists($key, $_SERVER) && !empty($_SERVER[$key])) ? $_SERVER[$key] : $default;
  545. }
  546. /**
  547. * Returns a specified session parameter from the $_SESSION array.
  548. *
  549. * @param string $key
  550. * @param mixed $default
  551. * @return mixed
  552. */
  553. public static function getSessParam($key, $default = null)
  554. {
  555. return (array_key_exists($key, $_SESSION) && !empty($_SESSION[$key])) ? $_SESSION[$key] : $default;
  556. }
  557. /**
  558. * Returns an array containing the three main parts of a FQDN (Fully Qualified Domain Name), including the
  559. * top-level domain, the second-level domains or hostname and the third-level domain.
  560. *
  561. * @param string $hostname
  562. * @return array
  563. */
  564. public static function getFQDNParts($hostname)
  565. {
  566. if(!preg_match("/^([a-z0-9][a-z0-9-]{0,62}\.)*([a-z0-9][a-z0-9-]{0,62}\.)+([a-z]{2,6})$/i", $hostname, $matches))
  567. {
  568. return array();
  569. }
  570. $parts["tld"] = $matches[3];
  571. $parts["2nd"] = $matches[2];
  572. $parts["3rd"] = $matches[1];
  573. return $parts;
  574. }
  575. /**
  576. * Returns the applications host address.
  577. *
  578. * @return TeamSpeak3_Helper_String
  579. */
  580. public static function getHostUri()
  581. {
  582. $sheme = (self::getHostParam("HTTPS") == "on") ? "https" : "http";
  583. $serverName = new TeamSpeak3_Helper_String(self::getHostParam("HTTP_HOST"));
  584. $serverPort = self::getHostParam("SERVER_PORT");
  585. $serverPort = ($serverPort != 80 && $serverPort != 443) ? ":" . $serverPort : "";
  586. if($serverName->endsWith($serverPort))
  587. {
  588. $serverName = $serverName->replace($serverPort, "");
  589. }
  590. return new TeamSpeak3_Helper_String($sheme . "://" . $serverName . $serverPort);
  591. }
  592. /**
  593. * Returns the applications base address.
  594. *
  595. * @return string
  596. */
  597. public static function getBaseUri()
  598. {
  599. $scriptPath = new TeamSpeak3_Helper_String(dirname(self::getHostParam("SCRIPT_NAME")));
  600. return self::getHostUri()->append(($scriptPath == DIRECTORY_SEPARATOR ? "" : $scriptPath) . "/");
  601. }
  602. /**
  603. * Strips slashes from each element of an array using stripslashes().
  604. *
  605. * @param mixed $var
  606. * @return mixed
  607. */
  608. protected static function stripslashesRecursive($var)
  609. {
  610. if(!is_array($var))
  611. {
  612. return stripslashes(strval($var));
  613. }
  614. foreach($var as $key => $val)
  615. {
  616. $var[$key] = (is_array($val)) ? stripslashesRecursive($val) : stripslashes(strval($val));
  617. }
  618. return $var;
  619. }
  620. }