PageRenderTime 53ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/league/uri/src/UriParser.php

https://gitlab.com/itlboy/yii2-starter-installed
PHP | 201 lines | 101 code | 29 blank | 71 comment | 7 complexity | df5337631aa5d2eafea126dc33335115 MD5 | raw file
  1. <?php
  2. /**
  3. * League.Uri (http://uri.thephpleague.com)
  4. *
  5. * @package League.uri
  6. * @author Ignace Nyamagana Butera <nyamsprod@gmail.com>
  7. * @copyright 2013-2015 Ignace Nyamagana Butera
  8. * @license https://github.com/thephpleague/uri/blob/master/LICENSE (MIT License)
  9. * @version 4.1.0
  10. * @link https://github.com/thephpleague/uri/
  11. */
  12. namespace League\Uri;
  13. use InvalidArgumentException;
  14. use League\Uri\Components\HostIpTrait;
  15. use League\Uri\Components\HostnameTrait;
  16. use League\Uri\Schemes\Generic\UriBuilderTrait;
  17. use League\Uri\Types\ValidatorTrait;
  18. /**
  19. * a class to parse a URI string according to RFC3986
  20. *
  21. * @package League.uri
  22. * @author Ignace Nyamagana Butera <nyamsprod@gmail.com>
  23. * @since 4.0.0
  24. */
  25. class UriParser
  26. {
  27. use HostIpTrait;
  28. use HostnameTrait;
  29. use UriBuilderTrait;
  30. use ValidatorTrait;
  31. const REGEXP_URI = ',^
  32. ((?<scheme>[^:/?\#]+):)? # URI scheme component
  33. (?<authority>//([^/?\#]*))? # URI authority part
  34. (?<path>[^?\#]*) # URI path component
  35. (?<query>\?([^\#]*))? # URI query component
  36. (?<fragment>\#(.*))? # URI fragment component
  37. ,x';
  38. const REGEXP_AUTHORITY = ',^(?<userinfo>(?<ucontent>.*?)@)?(?<hostname>.*?)?$,';
  39. const REGEXP_REVERSE_HOSTNAME = ',^((?<port>[^(\[\])]*):)?(?<host>.*)?$,';
  40. const REGEXP_SCHEME = ',^([a-z]([-a-z0-9+.]+)?)?$,i';
  41. const REGEXP_INVALID_USER = ',[/?#@:],';
  42. const REGEXP_INVALID_PASS = ',[/?#@],';
  43. /**
  44. * Parse a string as an URI according to the regexp form rfc3986
  45. *
  46. * @param string $uri
  47. *
  48. * @return array
  49. */
  50. public function parse($uri)
  51. {
  52. $parts = $this->extractUriParts($uri);
  53. return $this->normalizeUriHash(array_merge(
  54. $this->parseAuthority($parts['authority']),
  55. [
  56. 'scheme' => '' === $parts['scheme'] ? null : $parts['scheme'],
  57. 'path' => $parts['path'],
  58. 'query' => '' === $parts['query'] ? null : mb_substr($parts['query'], 1, null, 'UTF-8'),
  59. 'fragment' => '' === $parts['fragment'] ? null : mb_substr($parts['fragment'], 1, null, 'UTF-8'),
  60. ]
  61. ));
  62. }
  63. /**
  64. * Parse a string as an URI according to the regexp form rfc3986
  65. *
  66. * @see UriParser::parse
  67. *
  68. * @param string $uri The URI to parse
  69. *
  70. * @return array the array is similar to PHP's parse_url hash response
  71. */
  72. public function __invoke($uri)
  73. {
  74. return $this->parse($uri);
  75. }
  76. /**
  77. * Extract URI parts
  78. *
  79. * @see http://tools.ietf.org/html/rfc3986#appendix-B
  80. *
  81. * @param string $uri The URI to split
  82. *
  83. * @return string[]
  84. */
  85. protected function extractUriParts($uri)
  86. {
  87. preg_match(self::REGEXP_URI, $uri, $parts);
  88. $parts += ['query' => '', 'fragment' => ''];
  89. if (preg_match(self::REGEXP_SCHEME, $parts['scheme'])) {
  90. return $parts;
  91. }
  92. $parts['path'] = $parts['scheme'].':'.$parts['authority'].$parts['path'];
  93. $parts['scheme'] = '';
  94. $parts['authority'] = '';
  95. return $parts;
  96. }
  97. /**
  98. * Parse a URI authority part into its components
  99. *
  100. * @param string $authority
  101. *
  102. * @return array
  103. */
  104. protected function parseAuthority($authority)
  105. {
  106. $res = ['user' => null, 'pass' => null, 'host' => null, 'port' => null];
  107. if ('' === $authority) {
  108. return $res;
  109. }
  110. $content = mb_substr($authority, 2, null, 'UTF-8');
  111. if ('' === $content) {
  112. return ['host' => ''] + $res;
  113. }
  114. preg_match(self::REGEXP_AUTHORITY, $content, $auth);
  115. if ('' !== $auth['userinfo']) {
  116. $userinfo = explode(':', $auth['ucontent'], 2);
  117. $res = ['user' => array_shift($userinfo), 'pass' => array_shift($userinfo)] + $res;
  118. }
  119. return $this->parseHostname($auth['hostname']) + $res;
  120. }
  121. /**
  122. * Parse the hostname into its components Host and Port
  123. *
  124. * No validation is done on the port or host component found
  125. *
  126. * @param string $hostname
  127. *
  128. * @return array
  129. */
  130. protected function parseHostname($hostname)
  131. {
  132. $components = ['host' => null, 'port' => null];
  133. $hostname = strrev($hostname);
  134. if (preg_match(self::REGEXP_REVERSE_HOSTNAME, $hostname, $res)) {
  135. $components['host'] = strrev($res['host']);
  136. $components['port'] = strrev($res['port']);
  137. }
  138. $components['host'] = $this->filterHost($components['host']);
  139. $components['port'] = $this->validatePort($components['port']);
  140. return $components;
  141. }
  142. /**
  143. * validate the host component
  144. *
  145. * @param string $host
  146. *
  147. * @return string
  148. */
  149. protected function filterHost($host)
  150. {
  151. if (empty($this->validateIpHost($host))) {
  152. $this->validateStringHost($host);
  153. }
  154. return $host;
  155. }
  156. /**
  157. * @inheritdoc
  158. */
  159. protected function setIsAbsolute($host)
  160. {
  161. return ('.' === mb_substr($host, -1, 1, 'UTF-8')) ? mb_substr($host, 0, -1, 'UTF-8') : $host;
  162. }
  163. /**
  164. * @inheritdoc
  165. */
  166. protected function assertLabelsCount(array $labels)
  167. {
  168. if (127 <= count($labels)) {
  169. throw new InvalidArgumentException('Invalid Host, verify labels count');
  170. }
  171. }
  172. }