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

UriResolver.php

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


001  <?php
002   
003  namespace GuzzleHttp\Psr7;
004   
005  use Psr\Http\Message\UriInterface;
006   
007  /**
008   * Resolves a URI reference in the context of a base URI and the opposite way.
009   *
010   * @author Tobias Schultze
011   *
012   * @link https://tools.ietf.org/html/rfc3986#section-5
013   */
014  final class UriResolver
015  {
016      /**
017       * Removes dot segments from a path and returns the new path.
018       *
019       * @param string $path
020       *
021       * @return string
022       *
023       * @link http://tools.ietf.org/html/rfc3986#section-5.2.4
024       */
025      public static function removeDotSegments($path)
026      {
027          if ($path === '' || $path === '/') {
028              return $path;
029          }
030   
031          $results = [];
032          $segments = explode('/', $path);
033          foreach ($segments as $segment) {
034              if ($segment === '..') {
035                  array_pop($results);
036              } elseif ($segment !== '.') {
037                  $results[] = $segment;
038              }
039          }
040   
041          $newPath = implode('/', $results);
042   
043          if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) {
044              // Re-add the leading slash if necessary for cases like "/.."
045              $newPath = '/' . $newPath;
046          } elseif ($newPath !== '' && ($segment === '.' || $segment === '..')) {
047              // Add the trailing slash if necessary
048              // If newPath is not empty, then $segment must be set and is the last segment from the foreach
049              $newPath .= '/';
050          }
051   
052          return $newPath;
053      }
054   
055      /**
056       * Converts the relative URI into a new URI that is resolved against the base URI.
057       *
058       * @param UriInterface $base Base URI
059       * @param UriInterface $rel  Relative URI
060       *
061       * @return UriInterface
062       *
063       * @link http://tools.ietf.org/html/rfc3986#section-5.2
064       */
065      public static function resolve(UriInterface $base, UriInterface $rel)
066      {
067          if ((string) $rel === '') {
068              // we can simply return the same base URI instance for this same-document reference
069              return $base;
070          }
071   
072          if ($rel->getScheme() != '') {
073              return $rel->withPath(self::removeDotSegments($rel->getPath()));
074          }
075   
076          if ($rel->getAuthority() != '') {
077              $targetAuthority = $rel->getAuthority();
078              $targetPath = self::removeDotSegments($rel->getPath());
079              $targetQuery = $rel->getQuery();
080          } else {
081              $targetAuthority = $base->getAuthority();
082              if ($rel->getPath() === '') {
083                  $targetPath = $base->getPath();
084                  $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery();
085              } else {
086                  if ($rel->getPath()[0] === '/') {
087                      $targetPath = $rel->getPath();
088                  } else {
089                      if ($targetAuthority != '' && $base->getPath() === '') {
090                          $targetPath = '/' . $rel->getPath();
091                      } else {
092                          $lastSlashPos = strrpos($base->getPath(), '/');
093                          if ($lastSlashPos === false) {
094                              $targetPath = $rel->getPath();
095                          } else {
096                              $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath();
097                          }
098                      }
099                  }
100                  $targetPath = self::removeDotSegments($targetPath);
101                  $targetQuery = $rel->getQuery();
102              }
103          }
104   
105          return new Uri(Uri::composeComponents(
106              $base->getScheme(),
107              $targetAuthority,
108              $targetPath,
109              $targetQuery,
110              $rel->getFragment()
111          ));
112      }
113   
114      /**
115       * Returns the target URI as a relative reference from the base URI.
116       *
117       * This method is the counterpart to resolve():
118       *
119       *    (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
120       *
121       * One use-case is to use the current request URI as base URI and then generate relative links in your documents
122       * to reduce the document size or offer self-contained downloadable document archives.
123       *
124       *    $base = new Uri('http://example.com/a/b/');
125       *    echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c'));  // prints 'c'.
126       *    echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y'));  // prints '../x/y'.
127       *    echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
128       *    echo UriResolver::relativize($base, new Uri('http://example.org/a/b/'));   // prints '//example.org/a/b/'.
129       *
130       * This method also accepts a target that is already relative and will try to relativize it further. Only a
131       * relative-path reference will be returned as-is.
132       *
133       *    echo UriResolver::relativize($base, new Uri('/a/b/c'));  // prints 'c' as well
134       *
135       * @param UriInterface $base   Base URI
136       * @param UriInterface $target Target URI
137       *
138       * @return UriInterface The relative URI reference
139       */
140      public static function relativize(UriInterface $base, UriInterface $target)
141      {
142          if ($target->getScheme() !== '' &&
143              ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')
144          ) {
145              return $target;
146          }
147   
148          if (Uri::isRelativePathReference($target)) {
149              // As the target is already highly relative we return it as-is. It would be possible to resolve
150              // the target with `$target = self::resolve($base, $target);` and then try make it more relative
151              // by removing a duplicate query. But let's not do that automatically.
152              return $target;
153          }
154   
155          if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {
156              return $target->withScheme('');
157          }
158   
159          // We must remove the path before removing the authority because if the path starts with two slashes, the URI
160          // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
161          // invalid.
162          $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');
163   
164          if ($base->getPath() !== $target->getPath()) {
165              return $emptyPathUri->withPath(self::getRelativePath($base, $target));
166          }
167   
168          if ($base->getQuery() === $target->getQuery()) {
169              // Only the target fragment is left. And it must be returned even if base and target fragment are the same.
170              return $emptyPathUri->withQuery('');
171          }
172   
173          // If the base URI has a query but the target has none, we cannot return an empty path reference as it would
174          // inherit the base query component when resolving.
175          if ($target->getQuery() === '') {
176              $segments = explode('/', $target->getPath());
177              $lastSegment = end($segments);
178   
179              return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
180          }
181   
182          return $emptyPathUri;
183      }
184   
185      private static function getRelativePath(UriInterface $base, UriInterface $target)
186      {
187          $sourceSegments = explode('/', $base->getPath());
188          $targetSegments = explode('/', $target->getPath());
189          array_pop($sourceSegments);
190          $targetLastSegment = array_pop($targetSegments);
191          foreach ($sourceSegments as $i => $segment) {
192              if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {
193                  unset($sourceSegments[$i], $targetSegments[$i]);
194              } else {
195                  break;
196              }
197          }
198          $targetSegments[] = $targetLastSegment;
199          $relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments);
200   
201          // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./".
202          // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
203          // as the first segment of a relative-path reference, as it would be mistaken for a scheme name.
204          if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) {
205              $relativePath = "./$relativePath";
206          } elseif ('/' === $relativePath[0]) {
207              if ($base->getAuthority() != '' && $base->getPath() === '') {
208                  // In this case an extra slash is added by resolve() automatically. So we must not add one here.
209                  $relativePath = ".$relativePath";
210              } else {
211                  $relativePath = "./$relativePath";
212              }
213          }
214   
215          return $relativePath;
216      }
217   
218      private function __construct()
219      {
220          // cannot be instantiated
221      }
222  }
223