Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Uri.php

Zuletzt modifiziert: 01.05.2026, 11:26 - Dateigröße: 22.36 KiB


 001  <?php
 002   
 003  namespace GuzzleHttp\Psr7;
 004   
 005  use Psr\Http\Message\UriInterface;
 006   
 007  /**
 008   * PSR-7 URI implementation.
 009   *
 010   * @author Michael Dowling
 011   * @author Tobias Schultze
 012   * @author Matthew Weier O'Phinney
 013   */
 014  class Uri implements UriInterface
 015  {
 016      /**
 017       * Absolute http and https URIs require a host per RFC 7230 Section 2.7
 018       * but in generic URIs the host can be empty. So for http(s) URIs
 019       * we apply this default host when no host is given yet to form a
 020       * valid URI.
 021       */
 022      const HTTP_DEFAULT_HOST = 'localhost';
 023   
 024      private static $defaultPorts = [
 025          'http'  => 80,
 026          'https' => 443,
 027          'ftp' => 21,
 028          'gopher' => 70,
 029          'nntp' => 119,
 030          'news' => 119,
 031          'telnet' => 23,
 032          'tn3270' => 23,
 033          'imap' => 143,
 034          'pop' => 110,
 035          'ldap' => 389,
 036      ];
 037   
 038      private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
 039      private static $charSubDelims = '!\$&\'\(\)\*\+,;=';
 040      private static $replaceQuery = ['=' => '%3D', '&' => '%26'];
 041   
 042      /** @var string Uri scheme. */
 043      private $scheme = '';
 044   
 045      /** @var string Uri user info. */
 046      private $userInfo = '';
 047   
 048      /** @var string Uri host. */
 049      private $host = '';
 050   
 051      /** @var int|null Uri port. */
 052      private $port;
 053   
 054      /** @var string Uri path. */
 055      private $path = '';
 056   
 057      /** @var string Uri query string. */
 058      private $query = '';
 059   
 060      /** @var string Uri fragment. */
 061      private $fragment = '';
 062   
 063      /**
 064       * @param string $uri URI to parse
 065       */
 066      public function __construct($uri = '')
 067      {
 068          // weak type check to also accept null until we can add scalar type hints
 069          if ($uri != '') {
 070              $parts = self::parse($uri);
 071              if ($parts === false) {
 072                  throw new \InvalidArgumentException("Unable to parse URI: $uri");
 073              }
 074              $this->applyParts($parts);
 075          }
 076      }
 077   
 078      /**
 079       * UTF-8 aware \parse_url() replacement.
 080       *
 081       * The internal function produces broken output for non ASCII domain names
 082       * (IDN) when used with locales other than "C".
 083       *
 084       * On the other hand, cURL understands IDN correctly only when UTF-8 locale
 085       * is configured ("C.UTF-8", "en_US.UTF-8", etc.).
 086       *
 087       * @see https://bugs.php.net/bug.php?id=52923
 088       * @see https://www.php.net/manual/en/function.parse-url.php#114817
 089       * @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING
 090       *
 091       * @param string $url
 092       *
 093       * @return array|false
 094       */
 095      private static function parse($url)
 096      {
 097          // If IPv6
 098          $prefix = '';
 099          if (preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)) {
 100              $prefix = $matches[1];
 101              $url = $matches[2];
 102          }
 103   
 104          $encodedUrl = preg_replace_callback(
 105              '%[^:/@?&=#]+%usD',
 106              static function ($matches) {
 107                  return urlencode($matches[0]);
 108              },
 109              $url
 110          );
 111   
 112          $result = parse_url($prefix . $encodedUrl);
 113   
 114          if ($result === false) {
 115              return false;
 116          }
 117   
 118          return array_map('urldecode', $result);
 119      }
 120   
 121      public function __toString()
 122      {
 123          return self::composeComponents(
 124              $this->scheme,
 125              $this->getAuthority(),
 126              $this->path,
 127              $this->query,
 128              $this->fragment
 129          );
 130      }
 131   
 132      /**
 133       * Composes a URI reference string from its various components.
 134       *
 135       * Usually this method does not need to be called manually but instead is used indirectly via
 136       * `Psr\Http\Message\UriInterface::__toString`.
 137       *
 138       * PSR-7 UriInterface treats an empty component the same as a missing component as
 139       * getQuery(), getFragment() etc. always return a string. This explains the slight
 140       * difference to RFC 3986 Section 5.3.
 141       *
 142       * Another adjustment is that the authority separator is added even when the authority is missing/empty
 143       * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with
 144       * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But
 145       * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to
 146       * that format).
 147       *
 148       * @param string $scheme
 149       * @param string $authority
 150       * @param string $path
 151       * @param string $query
 152       * @param string $fragment
 153       *
 154       * @return string
 155       *
 156       * @link https://tools.ietf.org/html/rfc3986#section-5.3
 157       */
 158      public static function composeComponents($scheme, $authority, $path, $query, $fragment)
 159      {
 160          $uri = '';
 161   
 162          // weak type checks to also accept null until we can add scalar type hints
 163          if ($scheme != '') {
 164              $uri .= $scheme . ':';
 165          }
 166   
 167          if ($authority != ''|| $scheme === 'file') {
 168              $uri .= '//' . $authority;
 169          }
 170   
 171          $uri .= $path;
 172   
 173          if ($query != '') {
 174              $uri .= '?' . $query;
 175          }
 176   
 177          if ($fragment != '') {
 178              $uri .= '#' . $fragment;
 179          }
 180   
 181          return $uri;
 182      }
 183   
 184      /**
 185       * Whether the URI has the default port of the current scheme.
 186       *
 187       * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used
 188       * independently of the implementation.
 189       *
 190       * @param UriInterface $uri
 191       *
 192       * @return bool
 193       */
 194      public static function isDefaultPort(UriInterface $uri)
 195      {
 196          return $uri->getPort() === null
 197              || (isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]);
 198      }
 199   
 200      /**
 201       * Whether the URI is absolute, i.e. it has a scheme.
 202       *
 203       * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
 204       * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
 205       * to another URI, the base URI. Relative references can be divided into several forms:
 206       * - network-path references, e.g. '//example.com/path'
 207       * - absolute-path references, e.g. '/path'
 208       * - relative-path references, e.g. 'subpath'
 209       *
 210       * @param UriInterface $uri
 211       *
 212       * @return bool
 213       *
 214       * @see Uri::isNetworkPathReference
 215       * @see Uri::isAbsolutePathReference
 216       * @see Uri::isRelativePathReference
 217       * @link https://tools.ietf.org/html/rfc3986#section-4
 218       */
 219      public static function isAbsolute(UriInterface $uri)
 220      {
 221          return $uri->getScheme() !== '';
 222      }
 223   
 224      /**
 225       * Whether the URI is a network-path reference.
 226       *
 227       * A relative reference that begins with two slash characters is termed an network-path reference.
 228       *
 229       * @param UriInterface $uri
 230       *
 231       * @return bool
 232       *
 233       * @link https://tools.ietf.org/html/rfc3986#section-4.2
 234       */
 235      public static function isNetworkPathReference(UriInterface $uri)
 236      {
 237          return $uri->getScheme() === '' && $uri->getAuthority() !== '';
 238      }
 239   
 240      /**
 241       * Whether the URI is a absolute-path reference.
 242       *
 243       * A relative reference that begins with a single slash character is termed an absolute-path reference.
 244       *
 245       * @param UriInterface $uri
 246       *
 247       * @return bool
 248       *
 249       * @link https://tools.ietf.org/html/rfc3986#section-4.2
 250       */
 251      public static function isAbsolutePathReference(UriInterface $uri)
 252      {
 253          return $uri->getScheme() === ''
 254              && $uri->getAuthority() === ''
 255              && isset($uri->getPath()[0])
 256              && $uri->getPath()[0] === '/';
 257      }
 258   
 259      /**
 260       * Whether the URI is a relative-path reference.
 261       *
 262       * A relative reference that does not begin with a slash character is termed a relative-path reference.
 263       *
 264       * @param UriInterface $uri
 265       *
 266       * @return bool
 267       *
 268       * @link https://tools.ietf.org/html/rfc3986#section-4.2
 269       */
 270      public static function isRelativePathReference(UriInterface $uri)
 271      {
 272          return $uri->getScheme() === ''
 273              && $uri->getAuthority() === ''
 274              && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
 275      }
 276   
 277      /**
 278       * Whether the URI is a same-document reference.
 279       *
 280       * A same-document reference refers to a URI that is, aside from its fragment
 281       * component, identical to the base URI. When no base URI is given, only an empty
 282       * URI reference (apart from its fragment) is considered a same-document reference.
 283       *
 284       * @param UriInterface      $uri  The URI to check
 285       * @param UriInterface|null $base An optional base URI to compare against
 286       *
 287       * @return bool
 288       *
 289       * @link https://tools.ietf.org/html/rfc3986#section-4.4
 290       */
 291      public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null)
 292      {
 293          if ($base !== null) {
 294              $uri = UriResolver::resolve($base, $uri);
 295   
 296              return ($uri->getScheme() === $base->getScheme())
 297                  && ($uri->getAuthority() === $base->getAuthority())
 298                  && ($uri->getPath() === $base->getPath())
 299                  && ($uri->getQuery() === $base->getQuery());
 300          }
 301   
 302          return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
 303      }
 304   
 305      /**
 306       * Removes dot segments from a path and returns the new path.
 307       *
 308       * @param string $path
 309       *
 310       * @return string
 311       *
 312       * @deprecated since version 1.4. Use UriResolver::removeDotSegments instead.
 313       * @see UriResolver::removeDotSegments
 314       */
 315      public static function removeDotSegments($path)
 316      {
 317          return UriResolver::removeDotSegments($path);
 318      }
 319   
 320      /**
 321       * Converts the relative URI into a new URI that is resolved against the base URI.
 322       *
 323       * @param UriInterface        $base Base URI
 324       * @param string|UriInterface $rel  Relative URI
 325       *
 326       * @return UriInterface
 327       *
 328       * @deprecated since version 1.4. Use UriResolver::resolve instead.
 329       * @see UriResolver::resolve
 330       */
 331      public static function resolve(UriInterface $base, $rel)
 332      {
 333          if (!($rel instanceof UriInterface)) {
 334              $rel = new self($rel);
 335          }
 336   
 337          return UriResolver::resolve($base, $rel);
 338      }
 339   
 340      /**
 341       * Creates a new URI with a specific query string value removed.
 342       *
 343       * Any existing query string values that exactly match the provided key are
 344       * removed.
 345       *
 346       * @param UriInterface $uri URI to use as a base.
 347       * @param string       $key Query string key to remove.
 348       *
 349       * @return UriInterface
 350       */
 351      public static function withoutQueryValue(UriInterface $uri, $key)
 352      {
 353          $result = self::getFilteredQueryString($uri, [$key]);
 354   
 355          return $uri->withQuery(implode('&', $result));
 356      }
 357   
 358      /**
 359       * Creates a new URI with a specific query string value.
 360       *
 361       * Any existing query string values that exactly match the provided key are
 362       * removed and replaced with the given key value pair.
 363       *
 364       * A value of null will set the query string key without a value, e.g. "key"
 365       * instead of "key=value".
 366       *
 367       * @param UriInterface $uri   URI to use as a base.
 368       * @param string       $key   Key to set.
 369       * @param string|null  $value Value to set
 370       *
 371       * @return UriInterface
 372       */
 373      public static function withQueryValue(UriInterface $uri, $key, $value)
 374      {
 375          $result = self::getFilteredQueryString($uri, [$key]);
 376   
 377          $result[] = self::generateQueryString($key, $value);
 378   
 379          return $uri->withQuery(implode('&', $result));
 380      }
 381   
 382      /**
 383       * Creates a new URI with multiple specific query string values.
 384       *
 385       * It has the same behavior as withQueryValue() but for an associative array of key => value.
 386       *
 387       * @param UriInterface $uri           URI to use as a base.
 388       * @param array        $keyValueArray Associative array of key and values
 389       *
 390       * @return UriInterface
 391       */
 392      public static function withQueryValues(UriInterface $uri, array $keyValueArray)
 393      {
 394          $result = self::getFilteredQueryString($uri, array_keys($keyValueArray));
 395   
 396          foreach ($keyValueArray as $key => $value) {
 397              $result[] = self::generateQueryString($key, $value);
 398          }
 399   
 400          return $uri->withQuery(implode('&', $result));
 401      }
 402   
 403      /**
 404       * Creates a URI from a hash of `parse_url` components.
 405       *
 406       * @param array $parts
 407       *
 408       * @return UriInterface
 409       *
 410       * @link http://php.net/manual/en/function.parse-url.php
 411       *
 412       * @throws \InvalidArgumentException If the components do not form a valid URI.
 413       */
 414      public static function fromParts(array $parts)
 415      {
 416          $uri = new self();
 417          $uri->applyParts($parts);
 418          $uri->validateState();
 419   
 420          return $uri;
 421      }
 422   
 423      public function getScheme()
 424      {
 425          return $this->scheme;
 426      }
 427   
 428      public function getAuthority()
 429      {
 430          $authority = $this->host;
 431          if ($this->userInfo !== '') {
 432              $authority = $this->userInfo . '@' . $authority;
 433          }
 434   
 435          if ($this->port !== null) {
 436              $authority .= ':' . $this->port;
 437          }
 438   
 439          return $authority;
 440      }
 441   
 442      public function getUserInfo()
 443      {
 444          return $this->userInfo;
 445      }
 446   
 447      public function getHost()
 448      {
 449          return $this->host;
 450      }
 451   
 452      public function getPort()
 453      {
 454          return $this->port;
 455      }
 456   
 457      public function getPath()
 458      {
 459          return $this->path;
 460      }
 461   
 462      public function getQuery()
 463      {
 464          return $this->query;
 465      }
 466   
 467      public function getFragment()
 468      {
 469          return $this->fragment;
 470      }
 471   
 472      public function withScheme($scheme)
 473      {
 474          $scheme = $this->filterScheme($scheme);
 475   
 476          if ($this->scheme === $scheme) {
 477              return $this;
 478          }
 479   
 480          $new = clone $this;
 481          $new->scheme = $scheme;
 482          $new->removeDefaultPort();
 483          $new->validateState();
 484   
 485          return $new;
 486      }
 487   
 488      public function withUserInfo($user, $password = null)
 489      {
 490          $info = $this->filterUserInfoComponent($user);
 491          if ($password !== null) {
 492              $info .= ':' . $this->filterUserInfoComponent($password);
 493          }
 494   
 495          if ($this->userInfo === $info) {
 496              return $this;
 497          }
 498   
 499          $new = clone $this;
 500          $new->userInfo = $info;
 501          $new->validateState();
 502   
 503          return $new;
 504      }
 505   
 506      public function withHost($host)
 507      {
 508          $host = $this->filterHost($host);
 509   
 510          if ($this->host === $host) {
 511              return $this;
 512          }
 513   
 514          $new = clone $this;
 515          $new->host = $host;
 516          $new->validateState();
 517   
 518          return $new;
 519      }
 520   
 521      public function withPort($port)
 522      {
 523          $port = $this->filterPort($port);
 524   
 525          if ($this->port === $port) {
 526              return $this;
 527          }
 528   
 529          $new = clone $this;
 530          $new->port = $port;
 531          $new->removeDefaultPort();
 532          $new->validateState();
 533   
 534          return $new;
 535      }
 536   
 537      public function withPath($path)
 538      {
 539          $path = $this->filterPath($path);
 540   
 541          if ($this->path === $path) {
 542              return $this;
 543          }
 544   
 545          $new = clone $this;
 546          $new->path = $path;
 547          $new->validateState();
 548   
 549          return $new;
 550      }
 551   
 552      public function withQuery($query)
 553      {
 554          $query = $this->filterQueryAndFragment($query);
 555   
 556          if ($this->query === $query) {
 557              return $this;
 558          }
 559   
 560          $new = clone $this;
 561          $new->query = $query;
 562   
 563          return $new;
 564      }
 565   
 566      public function withFragment($fragment)
 567      {
 568          $fragment = $this->filterQueryAndFragment($fragment);
 569   
 570          if ($this->fragment === $fragment) {
 571              return $this;
 572          }
 573   
 574          $new = clone $this;
 575          $new->fragment = $fragment;
 576   
 577          return $new;
 578      }
 579   
 580      /**
 581       * Apply parse_url parts to a URI.
 582       *
 583       * @param array $parts Array of parse_url parts to apply.
 584       */
 585      private function applyParts(array $parts)
 586      {
 587          $this->scheme = isset($parts['scheme'])
 588              ? $this->filterScheme($parts['scheme'])
 589              : '';
 590          $this->userInfo = isset($parts['user'])
 591              ? $this->filterUserInfoComponent($parts['user'])
 592              : '';
 593          $this->host = isset($parts['host'])
 594              ? $this->filterHost($parts['host'])
 595              : '';
 596          $this->port = isset($parts['port'])
 597              ? $this->filterPort($parts['port'])
 598              : null;
 599          $this->path = isset($parts['path'])
 600              ? $this->filterPath($parts['path'])
 601              : '';
 602          $this->query = isset($parts['query'])
 603              ? $this->filterQueryAndFragment($parts['query'])
 604              : '';
 605          $this->fragment = isset($parts['fragment'])
 606              ? $this->filterQueryAndFragment($parts['fragment'])
 607              : '';
 608          if (isset($parts['pass'])) {
 609              $this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']);
 610          }
 611   
 612          $this->removeDefaultPort();
 613      }
 614   
 615      /**
 616       * @param string $scheme
 617       *
 618       * @return string
 619       *
 620       * @throws \InvalidArgumentException If the scheme is invalid.
 621       */
 622      private function filterScheme($scheme)
 623      {
 624          if (!is_string($scheme)) {
 625              throw new \InvalidArgumentException('Scheme must be a string');
 626          }
 627   
 628          return \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
 629      }
 630   
 631      /**
 632       * @param string $component
 633       *
 634       * @return string
 635       *
 636       * @throws \InvalidArgumentException If the user info is invalid.
 637       */
 638      private function filterUserInfoComponent($component)
 639      {
 640          if (!is_string($component)) {
 641              throw new \InvalidArgumentException('User info must be a string');
 642          }
 643   
 644          return preg_replace_callback(
 645              '/(?:[^%' . self::$charUnreserved . self::$charSubDelims . ']+|%(?![A-Fa-f0-9]{2}))/',
 646              [$this, 'rawurlencodeMatchZero'],
 647              $component
 648          );
 649      }
 650   
 651      /**
 652       * @param string $host
 653       *
 654       * @return string
 655       *
 656       * @throws \InvalidArgumentException If the host is invalid.
 657       */
 658      private function filterHost($host)
 659      {
 660          if (!is_string($host)) {
 661              throw new \InvalidArgumentException('Host must be a string');
 662          }
 663   
 664          return \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
 665      }
 666   
 667      /**
 668       * @param int|null $port
 669       *
 670       * @return int|null
 671       *
 672       * @throws \InvalidArgumentException If the port is invalid.
 673       */
 674      private function filterPort($port)
 675      {
 676          if ($port === null) {
 677              return null;
 678          }
 679   
 680          $port = (int) $port;
 681          if (0 > $port || 0xffff < $port) {
 682              throw new \InvalidArgumentException(
 683                  sprintf('Invalid port: %d. Must be between 0 and 65535', $port)
 684              );
 685          }
 686   
 687          return $port;
 688      }
 689   
 690      /**
 691       * @param UriInterface $uri
 692       * @param array        $keys
 693       *
 694       * @return array
 695       */
 696      private static function getFilteredQueryString(UriInterface $uri, array $keys)
 697      {
 698          $current = $uri->getQuery();
 699   
 700          if ($current === '') {
 701              return [];
 702          }
 703   
 704          $decodedKeys = array_map('rawurldecode', $keys);
 705   
 706          return array_filter(explode('&', $current), function ($part) use ($decodedKeys) {
 707              return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true);
 708          });
 709      }
 710   
 711      /**
 712       * @param string      $key
 713       * @param string|null $value
 714       *
 715       * @return string
 716       */
 717      private static function generateQueryString($key, $value)
 718      {
 719          // Query string separators ("=", "&") within the key or value need to be encoded
 720          // (while preventing double-encoding) before setting the query string. All other
 721          // chars that need percent-encoding will be encoded by withQuery().
 722          $queryString = strtr($key, self::$replaceQuery);
 723   
 724          if ($value !== null) {
 725              $queryString .= '=' . strtr($value, self::$replaceQuery);
 726          }
 727   
 728          return $queryString;
 729      }
 730   
 731      private function removeDefaultPort()
 732      {
 733          if ($this->port !== null && self::isDefaultPort($this)) {
 734              $this->port = null;
 735          }
 736      }
 737   
 738      /**
 739       * Filters the path of a URI
 740       *
 741       * @param string $path
 742       *
 743       * @return string
 744       *
 745       * @throws \InvalidArgumentException If the path is invalid.
 746       */
 747      private function filterPath($path)
 748      {
 749          if (!is_string($path)) {
 750              throw new \InvalidArgumentException('Path must be a string');
 751          }
 752   
 753          return preg_replace_callback(
 754              '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/',
 755              [$this, 'rawurlencodeMatchZero'],
 756              $path
 757          );
 758      }
 759   
 760      /**
 761       * Filters the query string or fragment of a URI.
 762       *
 763       * @param string $str
 764       *
 765       * @return string
 766       *
 767       * @throws \InvalidArgumentException If the query or fragment is invalid.
 768       */
 769      private function filterQueryAndFragment($str)
 770      {
 771          if (!is_string($str)) {
 772              throw new \InvalidArgumentException('Query and fragment must be a string');
 773          }
 774   
 775          return preg_replace_callback(
 776              '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/',
 777              [$this, 'rawurlencodeMatchZero'],
 778              $str
 779          );
 780      }
 781   
 782      private function rawurlencodeMatchZero(array $match)
 783      {
 784          return rawurlencode($match[0]);
 785      }
 786   
 787      private function validateState()
 788      {
 789          if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
 790              $this->host = self::HTTP_DEFAULT_HOST;
 791          }
 792   
 793          if ($this->getAuthority() === '') {
 794              if (0 === strpos($this->path, '//')) {
 795                  throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"');
 796              }
 797              if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) {
 798                  throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon');
 799              }
 800          } elseif (isset($this->path[0]) && $this->path[0] !== '/') {
 801              @trigger_error(
 802                  'The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' .
 803                  'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.',
 804                  E_USER_DEPRECATED
 805              );
 806              $this->path = '/' . $this->path;
 807              //throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty');
 808          }
 809      }
 810  }
 811