PageRenderTime 31ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/w3-total-cache/lib/Microsoft/Uri/Http.php

https://gitlab.com/endomorphosis/jeffersonsmithmayor
PHP | 764 lines | 349 code | 99 blank | 316 comment | 44 complexity | d4cb668351b48da7c4fdce66294c18ea MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Microsoft
  16. * @package Microsoft_Uri
  17. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Http.php 19041 2009-11-19 15:19:07Z sgehrig $
  20. */
  21. if (!defined('W3TC')) {
  22. die();
  23. }
  24. /**
  25. * @see Microsoft_Uri
  26. */
  27. require_once 'Microsoft/Uri.php';
  28. /**
  29. * HTTP(S) URI handler
  30. *
  31. * @category Microsoft
  32. * @package Microsoft_Uri
  33. * @uses Microsoft_Uri
  34. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  35. * @license http://framework.zend.com/license/new-bsd New BSD License
  36. */
  37. class Microsoft_Uri_Http extends Microsoft_Uri
  38. {
  39. /**
  40. * Character classes for validation regular expressions
  41. */
  42. const CHAR_ALNUM = 'A-Za-z0-9';
  43. const CHAR_MARK = '-_.!~*\'()\[\]';
  44. const CHAR_RESERVED = ';\/?:@&=+$,';
  45. const CHAR_SEGMENT = ':@&=+$,;';
  46. const CHAR_UNWISE = '{}|\\\\^`';
  47. /**
  48. * HTTP username
  49. *
  50. * @var string
  51. */
  52. protected $_username = '';
  53. /**
  54. * HTTP password
  55. *
  56. * @var string
  57. */
  58. protected $_password = '';
  59. /**
  60. * HTTP host
  61. *
  62. * @var string
  63. */
  64. protected $_host = '';
  65. /**
  66. * HTTP post
  67. *
  68. * @var string
  69. */
  70. protected $_port = '';
  71. /**
  72. * HTTP part
  73. *
  74. * @var string
  75. */
  76. protected $_path = '';
  77. /**
  78. * HTTP query
  79. *
  80. * @var string
  81. */
  82. protected $_query = '';
  83. /**
  84. * HTTP fragment
  85. *
  86. * @var string
  87. */
  88. protected $_fragment = '';
  89. /**
  90. * Regular expression grammar rules for validation; values added by constructor
  91. *
  92. * @var array
  93. */
  94. protected $_regex = array();
  95. /**
  96. * Constructor accepts a string $scheme (e.g., http, https) and a scheme-specific part of the URI
  97. * (e.g., example.com/path/to/resource?query=param#fragment)
  98. *
  99. * @param string $scheme The scheme of the URI
  100. * @param string $schemeSpecific The scheme-specific part of the URI
  101. * @throws Microsoft_Uri_Exception When the URI is not valid
  102. */
  103. protected function __construct($scheme, $schemeSpecific = '')
  104. {
  105. // Set the scheme
  106. $this->_scheme = $scheme;
  107. // Set up grammar rules for validation via regular expressions. These
  108. // are to be used with slash-delimited regular expression strings.
  109. // Escaped special characters (eg. '%25' for '%')
  110. $this->_regex['escaped'] = '%[[:xdigit:]]{2}';
  111. // Unreserved characters
  112. $this->_regex['unreserved'] = '[' . self::CHAR_ALNUM . self::CHAR_MARK . ']';
  113. // Segment can use escaped, unreserved or a set of additional chars
  114. $this->_regex['segment'] = '(?:' . $this->_regex['escaped'] . '|[' .
  115. self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_SEGMENT . '])*';
  116. // Path can be a series of segmets char strings seperated by '/'
  117. $this->_regex['path'] = '(?:\/(?:' . $this->_regex['segment'] . ')?)+';
  118. // URI characters can be escaped, alphanumeric, mark or reserved chars
  119. $this->_regex['uric'] = '(?:' . $this->_regex['escaped'] . '|[' .
  120. self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_RESERVED .
  121. // If unwise chars are allowed, add them to the URI chars class
  122. (self::$_config['allow_unwise'] ? self::CHAR_UNWISE : '') . '])';
  123. // If no scheme-specific part was supplied, the user intends to create
  124. // a new URI with this object. No further parsing is required.
  125. if (strlen($schemeSpecific) === 0) {
  126. return;
  127. }
  128. // Parse the scheme-specific URI parts into the instance variables.
  129. $this->_parseUri($schemeSpecific);
  130. // Validate the URI
  131. if ($this->valid() === false) {
  132. require_once 'Microsoft/Uri/Exception.php';
  133. throw new Microsoft_Uri_Exception('Invalid URI supplied');
  134. }
  135. }
  136. /**
  137. * Creates a Microsoft_Uri_Http from the given string
  138. *
  139. * @param string $uri String to create URI from, must start with
  140. * 'http://' or 'https://'
  141. * @throws InvalidArgumentException When the given $uri is not a string or
  142. * does not start with http:// or https://
  143. * @throws Microsoft_Uri_Exception When the given $uri is invalid
  144. * @return Microsoft_Uri_Http
  145. */
  146. public static function fromString($uri)
  147. {
  148. if (is_string($uri) === false) {
  149. require_once 'Microsoft/Uri/Exception.php';
  150. throw new Microsoft_Uri_Exception('$uri is not a string');
  151. }
  152. $uri = explode(':', $uri, 2);
  153. $scheme = strtolower($uri[0]);
  154. $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
  155. if (in_array($scheme, array('http', 'https')) === false) {
  156. require_once 'Microsoft/Uri/Exception.php';
  157. throw new Microsoft_Uri_Exception("Invalid scheme: '$scheme'");
  158. }
  159. $schemeHandler = new Microsoft_Uri_Http($scheme, $schemeSpecific);
  160. return $schemeHandler;
  161. }
  162. /**
  163. * Parse the scheme-specific portion of the URI and place its parts into instance variables.
  164. *
  165. * @param string $schemeSpecific The scheme-specific portion to parse
  166. * @throws Microsoft_Uri_Exception When scheme-specific decoposition fails
  167. * @throws Microsoft_Uri_Exception When authority decomposition fails
  168. * @return void
  169. */
  170. protected function _parseUri($schemeSpecific)
  171. {
  172. // High-level decomposition parser
  173. $pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~';
  174. $status = @preg_match($pattern, $schemeSpecific, $matches);
  175. if ($status === false) {
  176. require_once 'Microsoft/Uri/Exception.php';
  177. throw new Microsoft_Uri_Exception('Internal error: scheme-specific decomposition failed');
  178. }
  179. // Failed decomposition; no further processing needed
  180. if ($status === false) {
  181. return;
  182. }
  183. // Save URI components that need no further decomposition
  184. $this->_path = isset($matches[4]) === true ? $matches[4] : '';
  185. $this->_query = isset($matches[6]) === true ? $matches[6] : '';
  186. $this->_fragment = isset($matches[8]) === true ? $matches[8] : '';
  187. // Additional decomposition to get username, password, host, and port
  188. $combo = isset($matches[3]) === true ? $matches[3] : '';
  189. $pattern = '~^(([^:@]*)(:([^@]*))?@)?([^:]+)(:(.*))?$~';
  190. $status = @preg_match($pattern, $combo, $matches);
  191. if ($status === false) {
  192. require_once 'Microsoft/Uri/Exception.php';
  193. throw new Microsoft_Uri_Exception('Internal error: authority decomposition failed');
  194. }
  195. // Failed decomposition; no further processing needed
  196. if ($status === false) {
  197. return;
  198. }
  199. // Save remaining URI components
  200. $this->_username = isset($matches[2]) === true ? $matches[2] : '';
  201. $this->_password = isset($matches[4]) === true ? $matches[4] : '';
  202. $this->_host = isset($matches[5]) === true ? $matches[5] : '';
  203. $this->_port = isset($matches[7]) === true ? $matches[7] : '';
  204. }
  205. /**
  206. * Returns a URI based on current values of the instance variables. If any
  207. * part of the URI does not pass validation, then an exception is thrown.
  208. *
  209. * @throws Microsoft_Uri_Exception When one or more parts of the URI are invalid
  210. * @return string
  211. */
  212. public function getUri()
  213. {
  214. if ($this->valid() === false) {
  215. require_once 'Microsoft/Uri/Exception.php';
  216. throw new Microsoft_Uri_Exception('One or more parts of the URI are invalid');
  217. }
  218. $password = strlen($this->_password) > 0 ? ":$this->_password" : '';
  219. $auth = strlen($this->_username) > 0 ? "$this->_username$password@" : '';
  220. $port = strlen($this->_port) > 0 ? ":$this->_port" : '';
  221. $query = strlen($this->_query) > 0 ? "?$this->_query" : '';
  222. $fragment = strlen($this->_fragment) > 0 ? "#$this->_fragment" : '';
  223. return $this->_scheme
  224. . '://'
  225. . $auth
  226. . $this->_host
  227. . $port
  228. . $this->_path
  229. . $query
  230. . $fragment;
  231. }
  232. /**
  233. * Validate the current URI from the instance variables. Returns true if and only if all
  234. * parts pass validation.
  235. *
  236. * @return boolean
  237. */
  238. public function valid()
  239. {
  240. // Return true if and only if all parts of the URI have passed validation
  241. return $this->validateUsername()
  242. and $this->validatePassword()
  243. and $this->validateHost()
  244. and $this->validatePort()
  245. and $this->validatePath()
  246. and $this->validateQuery()
  247. and $this->validateFragment();
  248. }
  249. /**
  250. * Returns the username portion of the URL, or FALSE if none.
  251. *
  252. * @return string
  253. */
  254. public function getUsername()
  255. {
  256. return strlen($this->_username) > 0 ? $this->_username : false;
  257. }
  258. /**
  259. * Returns true if and only if the username passes validation. If no username is passed,
  260. * then the username contained in the instance variable is used.
  261. *
  262. * @param string $username The HTTP username
  263. * @throws Microsoft_Uri_Exception When username validation fails
  264. * @return boolean
  265. * @link http://www.faqs.org/rfcs/rfc2396.html
  266. */
  267. public function validateUsername($username = null)
  268. {
  269. if ($username === null) {
  270. $username = $this->_username;
  271. }
  272. // If the username is empty, then it is considered valid
  273. if (strlen($username) === 0) {
  274. return true;
  275. }
  276. // Check the username against the allowed values
  277. $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
  278. self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $username);
  279. if ($status === false) {
  280. require_once 'Microsoft/Uri/Exception.php';
  281. throw new Microsoft_Uri_Exception('Internal error: username validation failed');
  282. }
  283. return $status === 1;
  284. }
  285. /**
  286. * Sets the username for the current URI, and returns the old username
  287. *
  288. * @param string $username The HTTP username
  289. * @throws Microsoft_Uri_Exception When $username is not a valid HTTP username
  290. * @return string
  291. */
  292. public function setUsername($username)
  293. {
  294. if ($this->validateUsername($username) === false) {
  295. require_once 'Microsoft/Uri/Exception.php';
  296. throw new Microsoft_Uri_Exception("Username \"$username\" is not a valid HTTP username");
  297. }
  298. $oldUsername = $this->_username;
  299. $this->_username = $username;
  300. return $oldUsername;
  301. }
  302. /**
  303. * Returns the password portion of the URL, or FALSE if none.
  304. *
  305. * @return string
  306. */
  307. public function getPassword()
  308. {
  309. return strlen($this->_password) > 0 ? $this->_password : false;
  310. }
  311. /**
  312. * Returns true if and only if the password passes validation. If no password is passed,
  313. * then the password contained in the instance variable is used.
  314. *
  315. * @param string $password The HTTP password
  316. * @throws Microsoft_Uri_Exception When password validation fails
  317. * @return boolean
  318. * @link http://www.faqs.org/rfcs/rfc2396.html
  319. */
  320. public function validatePassword($password = null)
  321. {
  322. if ($password === null) {
  323. $password = $this->_password;
  324. }
  325. // If the password is empty, then it is considered valid
  326. if (strlen($password) === 0) {
  327. return true;
  328. }
  329. // If the password is nonempty, but there is no username, then it is considered invalid
  330. if (strlen($password) > 0 and strlen($this->_username) === 0) {
  331. return false;
  332. }
  333. // Check the password against the allowed values
  334. $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
  335. self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $password);
  336. if ($status === false) {
  337. require_once 'Microsoft/Uri/Exception.php';
  338. throw new Microsoft_Uri_Exception('Internal error: password validation failed.');
  339. }
  340. return $status == 1;
  341. }
  342. /**
  343. * Sets the password for the current URI, and returns the old password
  344. *
  345. * @param string $password The HTTP password
  346. * @throws Microsoft_Uri_Exception When $password is not a valid HTTP password
  347. * @return string
  348. */
  349. public function setPassword($password)
  350. {
  351. if ($this->validatePassword($password) === false) {
  352. require_once 'Microsoft/Uri/Exception.php';
  353. throw new Microsoft_Uri_Exception("Password \"$password\" is not a valid HTTP password.");
  354. }
  355. $oldPassword = $this->_password;
  356. $this->_password = $password;
  357. return $oldPassword;
  358. }
  359. /**
  360. * Returns the domain or host IP portion of the URL, or FALSE if none.
  361. *
  362. * @return string
  363. */
  364. public function getHost()
  365. {
  366. return strlen($this->_host) > 0 ? $this->_host : false;
  367. }
  368. /**
  369. * Returns true if and only if the host string passes validation. If no host is passed,
  370. * then the host contained in the instance variable is used.
  371. *
  372. * @param string $host The HTTP host
  373. * @return boolean
  374. * @uses Microsoft_Filter
  375. */
  376. public function validateHost($host = null)
  377. {
  378. if ($host === null) {
  379. $host = $this->_host;
  380. }
  381. // If the host is empty, then it is considered invalid
  382. if (strlen($host) === 0) {
  383. return false;
  384. }
  385. return true;
  386. }
  387. /**
  388. * Sets the host for the current URI, and returns the old host
  389. *
  390. * @param string $host The HTTP host
  391. * @throws Microsoft_Uri_Exception When $host is nota valid HTTP host
  392. * @return string
  393. */
  394. public function setHost($host)
  395. {
  396. if ($this->validateHost($host) === false) {
  397. require_once 'Microsoft/Uri/Exception.php';
  398. throw new Microsoft_Uri_Exception("Host \"$host\" is not a valid HTTP host");
  399. }
  400. $oldHost = $this->_host;
  401. $this->_host = $host;
  402. return $oldHost;
  403. }
  404. /**
  405. * Returns the TCP port, or FALSE if none.
  406. *
  407. * @return string
  408. */
  409. public function getPort()
  410. {
  411. return strlen($this->_port) > 0 ? $this->_port : false;
  412. }
  413. /**
  414. * Returns true if and only if the TCP port string passes validation. If no port is passed,
  415. * then the port contained in the instance variable is used.
  416. *
  417. * @param string $port The HTTP port
  418. * @return boolean
  419. */
  420. public function validatePort($port = null)
  421. {
  422. if ($port === null) {
  423. $port = $this->_port;
  424. }
  425. // If the port is empty, then it is considered valid
  426. if (strlen($port) === 0) {
  427. return true;
  428. }
  429. // Check the port against the allowed values
  430. return ctype_digit((string) $port) and 1 <= $port and $port <= 65535;
  431. }
  432. /**
  433. * Sets the port for the current URI, and returns the old port
  434. *
  435. * @param string $port The HTTP port
  436. * @throws Microsoft_Uri_Exception When $port is not a valid HTTP port
  437. * @return string
  438. */
  439. public function setPort($port)
  440. {
  441. if ($this->validatePort($port) === false) {
  442. require_once 'Microsoft/Uri/Exception.php';
  443. throw new Microsoft_Uri_Exception("Port \"$port\" is not a valid HTTP port.");
  444. }
  445. $oldPort = $this->_port;
  446. $this->_port = $port;
  447. return $oldPort;
  448. }
  449. /**
  450. * Returns the path and filename portion of the URL, or FALSE if none.
  451. *
  452. * @return string
  453. */
  454. public function getPath()
  455. {
  456. return strlen($this->_path) > 0 ? $this->_path : '/';
  457. }
  458. /**
  459. * Returns true if and only if the path string passes validation. If no path is passed,
  460. * then the path contained in the instance variable is used.
  461. *
  462. * @param string $path The HTTP path
  463. * @throws Microsoft_Uri_Exception When path validation fails
  464. * @return boolean
  465. */
  466. public function validatePath($path = null)
  467. {
  468. if ($path === null) {
  469. $path = $this->_path;
  470. }
  471. // If the path is empty, then it is considered valid
  472. if (strlen($path) === 0) {
  473. return true;
  474. }
  475. // Determine whether the path is well-formed
  476. $pattern = '/^' . $this->_regex['path'] . '$/';
  477. $status = @preg_match($pattern, $path);
  478. if ($status === false) {
  479. require_once 'Microsoft/Uri/Exception.php';
  480. throw new Microsoft_Uri_Exception('Internal error: path validation failed');
  481. }
  482. return (boolean) $status;
  483. }
  484. /**
  485. * Sets the path for the current URI, and returns the old path
  486. *
  487. * @param string $path The HTTP path
  488. * @throws Microsoft_Uri_Exception When $path is not a valid HTTP path
  489. * @return string
  490. */
  491. public function setPath($path)
  492. {
  493. if ($this->validatePath($path) === false) {
  494. require_once 'Microsoft/Uri/Exception.php';
  495. throw new Microsoft_Uri_Exception("Path \"$path\" is not a valid HTTP path");
  496. }
  497. $oldPath = $this->_path;
  498. $this->_path = $path;
  499. return $oldPath;
  500. }
  501. /**
  502. * Returns the query portion of the URL (after ?), or FALSE if none.
  503. *
  504. * @return string
  505. */
  506. public function getQuery()
  507. {
  508. return strlen($this->_query) > 0 ? $this->_query : false;
  509. }
  510. /**
  511. * Returns the query portion of the URL (after ?) as a
  512. * key-value-array. If the query is empty an empty array
  513. * is returned
  514. *
  515. * @return array
  516. */
  517. public function getQueryAsArray()
  518. {
  519. $query = $this->getQuery();
  520. $querryArray = array();
  521. if ($query !== false) {
  522. parse_str($query, $querryArray);
  523. }
  524. return $querryArray;
  525. }
  526. /**
  527. * Returns true if and only if the query string passes validation. If no query is passed,
  528. * then the query string contained in the instance variable is used.
  529. *
  530. * @param string $query The query to validate
  531. * @throws Microsoft_Uri_Exception When query validation fails
  532. * @return boolean
  533. * @link http://www.faqs.org/rfcs/rfc2396.html
  534. */
  535. public function validateQuery($query = null)
  536. {
  537. if ($query === null) {
  538. $query = $this->_query;
  539. }
  540. // If query is empty, it is considered to be valid
  541. if (strlen($query) === 0) {
  542. return true;
  543. }
  544. // Determine whether the query is well-formed
  545. $pattern = '/^' . $this->_regex['uric'] . '*$/';
  546. $status = @preg_match($pattern, $query);
  547. if ($status === false) {
  548. require_once 'Microsoft/Uri/Exception.php';
  549. throw new Microsoft_Uri_Exception('Internal error: query validation failed');
  550. }
  551. return $status == 1;
  552. }
  553. /**
  554. * Add or replace params in the query string for the current URI, and
  555. * return the old query.
  556. *
  557. * @param array $queryParams
  558. * @return string Old query string
  559. */
  560. public function addReplaceQueryParameters(array $queryParams)
  561. {
  562. $queryParams = array_merge($this->getQueryAsArray(), $queryParams);
  563. return $this->setQuery($queryParams);
  564. }
  565. /**
  566. * Remove params in the query string for the current URI, and
  567. * return the old query.
  568. *
  569. * @param array $queryParamKeys
  570. * @return string Old query string
  571. */
  572. public function removeQueryParameters(array $queryParamKeys)
  573. {
  574. $queryParams = array_diff_key($this->getQueryAsArray(), array_fill_keys($queryParamKeys, 0));
  575. return $this->setQuery($queryParams);
  576. }
  577. /**
  578. * Set the query string for the current URI, and return the old query
  579. * string This method accepts both strings and arrays.
  580. *
  581. * @param string|array $query The query string or array
  582. * @throws Microsoft_Uri_Exception When $query is not a valid query string
  583. * @return string Old query string
  584. */
  585. public function setQuery($query)
  586. {
  587. $oldQuery = $this->_query;
  588. // If query is empty, set an empty string
  589. if (empty($query) === true) {
  590. $this->_query = '';
  591. return $oldQuery;
  592. }
  593. // If query is an array, make a string out of it
  594. if (is_array($query) === true) {
  595. $query = http_build_query($query, '', '&');
  596. } else {
  597. // If it is a string, make sure it is valid. If not parse and encode it
  598. $query = (string) $query;
  599. if ($this->validateQuery($query) === false) {
  600. parse_str($query, $queryArray);
  601. $query = http_build_query($queryArray, '', '&');
  602. }
  603. }
  604. // Make sure the query is valid, and set it
  605. if ($this->validateQuery($query) === false) {
  606. require_once 'Microsoft/Uri/Exception.php';
  607. throw new Microsoft_Uri_Exception("'$query' is not a valid query string");
  608. }
  609. $this->_query = $query;
  610. return $oldQuery;
  611. }
  612. /**
  613. * Returns the fragment portion of the URL (after #), or FALSE if none.
  614. *
  615. * @return string|false
  616. */
  617. public function getFragment()
  618. {
  619. return strlen($this->_fragment) > 0 ? $this->_fragment : false;
  620. }
  621. /**
  622. * Returns true if and only if the fragment passes validation. If no fragment is passed,
  623. * then the fragment contained in the instance variable is used.
  624. *
  625. * @param string $fragment Fragment of an URI
  626. * @throws Microsoft_Uri_Exception When fragment validation fails
  627. * @return boolean
  628. * @link http://www.faqs.org/rfcs/rfc2396.html
  629. */
  630. public function validateFragment($fragment = null)
  631. {
  632. if ($fragment === null) {
  633. $fragment = $this->_fragment;
  634. }
  635. // If fragment is empty, it is considered to be valid
  636. if (strlen($fragment) === 0) {
  637. return true;
  638. }
  639. // Determine whether the fragment is well-formed
  640. $pattern = '/^' . $this->_regex['uric'] . '*$/';
  641. $status = @preg_match($pattern, $fragment);
  642. if ($status === false) {
  643. require_once 'Microsoft/Uri/Exception.php';
  644. throw new Microsoft_Uri_Exception('Internal error: fragment validation failed');
  645. }
  646. return (boolean) $status;
  647. }
  648. /**
  649. * Sets the fragment for the current URI, and returns the old fragment
  650. *
  651. * @param string $fragment Fragment of the current URI
  652. * @throws Microsoft_Uri_Exception When $fragment is not a valid HTTP fragment
  653. * @return string
  654. */
  655. public function setFragment($fragment)
  656. {
  657. if ($this->validateFragment($fragment) === false) {
  658. require_once 'Microsoft/Uri/Exception.php';
  659. throw new Microsoft_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
  660. }
  661. $oldFragment = $this->_fragment;
  662. $this->_fragment = $fragment;
  663. return $oldFragment;
  664. }
  665. }