Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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

UriNormalizer.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 8.14 KiB


001  <?php
002   
003  namespace GuzzleHttp\Psr7;
004   
005  use Psr\Http\Message\UriInterface;
006   
007  /**
008   * Provides methods to normalize and compare URIs.
009   *
010   * @author Tobias Schultze
011   *
012   * @link https://tools.ietf.org/html/rfc3986#section-6
013   */
014  final class UriNormalizer
015  {
016      /**
017       * Default normalizations which only include the ones that preserve semantics.
018       *
019       * self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH |
020       * self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS
021       */
022      const PRESERVING_NORMALIZATIONS = 63;
023   
024      /**
025       * All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
026       *
027       * Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b
028       */
029      const CAPITALIZE_PERCENT_ENCODING = 1;
030   
031      /**
032       * Decodes percent-encoded octets of unreserved characters.
033       *
034       * For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39),
035       * hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and,
036       * when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers.
037       *
038       * Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/
039       */
040      const DECODE_UNRESERVED_CHARACTERS = 2;
041   
042      /**
043       * Converts the empty path to "/" for http and https URIs.
044       *
045       * Example: http://example.org → http://example.org/
046       */
047      const CONVERT_EMPTY_PATH = 4;
048   
049      /**
050       * Removes the default host of the given URI scheme from the URI.
051       *
052       * Only the "file" scheme defines the default host "localhost".
053       * All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile`
054       * are equivalent according to RFC 3986. The first format is not accepted
055       * by PHPs stream functions and thus already normalized implicitly to the
056       * second format in the Uri class. See `GuzzleHttp\Psr7\Uri::composeComponents`.
057       *
058       * Example: file://localhost/myfile → file:///myfile
059       */
060      const REMOVE_DEFAULT_HOST = 8;
061   
062      /**
063       * Removes the default port of the given URI scheme from the URI.
064       *
065       * Example: http://example.org:80/ → http://example.org/
066       */
067      const REMOVE_DEFAULT_PORT = 16;
068   
069      /**
070       * Removes unnecessary dot-segments.
071       *
072       * Dot-segments in relative-path references are not removed as it would
073       * change the semantics of the URI reference.
074       *
075       * Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html
076       */
077      const REMOVE_DOT_SEGMENTS = 32;
078   
079      /**
080       * Paths which include two or more adjacent slashes are converted to one.
081       *
082       * Webservers usually ignore duplicate slashes and treat those URIs equivalent.
083       * But in theory those URIs do not need to be equivalent. So this normalization
084       * may change the semantics. Encoded slashes (%2F) are not removed.
085       *
086       * Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html
087       */
088      const REMOVE_DUPLICATE_SLASHES = 64;
089   
090      /**
091       * Sort query parameters with their values in alphabetical order.
092       *
093       * However, the order of parameters in a URI may be significant (this is not defined by the standard).
094       * So this normalization is not safe and may change the semantics of the URI.
095       *
096       * Example: ?lang=en&article=fred → ?article=fred&lang=en
097       *
098       * Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the
099       * purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly.
100       */
101      const SORT_QUERY_PARAMETERS = 128;
102   
103      /**
104       * Returns a normalized URI.
105       *
106       * The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
107       * This methods adds additional normalizations that can be configured with the $flags parameter.
108       *
109       * PSR-7 UriInterface cannot distinguish between an empty component and a missing component as
110       * getQuery(), getFragment() etc. always return a string. This means the URIs "/?#" and "/" are
111       * treated equivalent which is not necessarily true according to RFC 3986. But that difference
112       * is highly uncommon in reality. So this potential normalization is implied in PSR-7 as well.
113       *
114       * @param UriInterface $uri   The URI to normalize
115       * @param int          $flags A bitmask of normalizations to apply, see constants
116       *
117       * @return UriInterface The normalized URI
118       *
119       * @link https://tools.ietf.org/html/rfc3986#section-6.2
120       */
121      public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS)
122      {
123          if ($flags & self::CAPITALIZE_PERCENT_ENCODING) {
124              $uri = self::capitalizePercentEncoding($uri);
125          }
126   
127          if ($flags & self::DECODE_UNRESERVED_CHARACTERS) {
128              $uri = self::decodeUnreservedCharacters($uri);
129          }
130   
131          if ($flags & self::CONVERT_EMPTY_PATH && $uri->getPath() === '' &&
132              ($uri->getScheme() === 'http' || $uri->getScheme() === 'https')
133          ) {
134              $uri = $uri->withPath('/');
135          }
136   
137          if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') {
138              $uri = $uri->withHost('');
139          }
140   
141          if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) {
142              $uri = $uri->withPort(null);
143          }
144   
145          if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) {
146              $uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath()));
147          }
148   
149          if ($flags & self::REMOVE_DUPLICATE_SLASHES) {
150              $uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath()));
151          }
152   
153          if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {
154              $queryKeyValues = explode('&', $uri->getQuery());
155              sort($queryKeyValues);
156              $uri = $uri->withQuery(implode('&', $queryKeyValues));
157          }
158   
159          return $uri;
160      }
161   
162      /**
163       * Whether two URIs can be considered equivalent.
164       *
165       * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also
166       * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be
167       * resolved against the same base URI. If this is not the case, determination of equivalence or difference of
168       * relative references does not mean anything.
169       *
170       * @param UriInterface $uri1           An URI to compare
171       * @param UriInterface $uri2           An URI to compare
172       * @param int          $normalizations A bitmask of normalizations to apply, see constants
173       *
174       * @return bool
175       *
176       * @link https://tools.ietf.org/html/rfc3986#section-6.1
177       */
178      public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS)
179      {
180          return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);
181      }
182   
183      private static function capitalizePercentEncoding(UriInterface $uri)
184      {
185          $regex = '/(?:%[A-Fa-f0-9]{2})++/';
186   
187          $callback = function (array $match) {
188              return strtoupper($match[0]);
189          };
190   
191          return
192              $uri->withPath(
193                  preg_replace_callback($regex, $callback, $uri->getPath())
194              )->withQuery(
195                  preg_replace_callback($regex, $callback, $uri->getQuery())
196              );
197      }
198   
199      private static function decodeUnreservedCharacters(UriInterface $uri)
200      {
201          $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';
202   
203          $callback = function (array $match) {
204              return rawurldecode($match[0]);
205          };
206   
207          return
208              $uri->withPath(
209                  preg_replace_callback($regex, $callback, $uri->getPath())
210              )->withQuery(
211                  preg_replace_callback($regex, $callback, $uri->getQuery())
212              );
213      }
214   
215      private function __construct()
216      {
217          // cannot be instantiated
218      }
219  }
220