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

RedirectMiddleware.php

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


001  <?php
002  namespace GuzzleHttp;
003   
004  use GuzzleHttp\Exception\BadResponseException;
005  use GuzzleHttp\Exception\TooManyRedirectsException;
006  use GuzzleHttp\Promise\PromiseInterface;
007  use GuzzleHttp\Psr7;
008  use Psr\Http\Message\RequestInterface;
009  use Psr\Http\Message\ResponseInterface;
010  use Psr\Http\Message\UriInterface;
011   
012  /**
013   * Request redirect middleware.
014   *
015   * Apply this middleware like other middleware using
016   * {@see \GuzzleHttp\Middleware::redirect()}.
017   */
018  class RedirectMiddleware
019  {
020      const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
021   
022      const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
023   
024      public static $defaultSettings = [
025          'max'             => 5,
026          'protocols'       => ['http', 'https'],
027          'strict'          => false,
028          'referer'         => false,
029          'track_redirects' => false,
030      ];
031   
032      /** @var callable  */
033      private $nextHandler;
034   
035      /**
036       * @param callable $nextHandler Next handler to invoke.
037       */
038      public function __construct(callable $nextHandler)
039      {
040          $this->nextHandler = $nextHandler;
041      }
042   
043      /**
044       * @param RequestInterface $request
045       * @param array            $options
046       *
047       * @return PromiseInterface
048       */
049      public function __invoke(RequestInterface $request, array $options)
050      {
051          $fn = $this->nextHandler;
052   
053          if (empty($options['allow_redirects'])) {
054              return $fn($request, $options);
055          }
056   
057          if ($options['allow_redirects'] === true) {
058              $options['allow_redirects'] = self::$defaultSettings;
059          } elseif (!is_array($options['allow_redirects'])) {
060              throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
061          } else {
062              // Merge the default settings with the provided settings
063              $options['allow_redirects'] += self::$defaultSettings;
064          }
065   
066          if (empty($options['allow_redirects']['max'])) {
067              return $fn($request, $options);
068          }
069   
070          return $fn($request, $options)
071              ->then(function (ResponseInterface $response) use ($request, $options) {
072                  return $this->checkRedirect($request, $options, $response);
073              });
074      }
075   
076      /**
077       * @param RequestInterface  $request
078       * @param array             $options
079       * @param ResponseInterface $response
080       *
081       * @return ResponseInterface|PromiseInterface
082       */
083      public function checkRedirect(
084          RequestInterface $request,
085          array $options,
086          ResponseInterface $response
087      ) {
088          if (substr($response->getStatusCode(), 0, 1) != '3'
089              || !$response->hasHeader('Location')
090          ) {
091              return $response;
092          }
093   
094          $this->guardMax($request, $options);
095          $nextRequest = $this->modifyRequest($request, $options, $response);
096   
097          // If authorization is handled by curl, unset it if URI is cross-origin.
098          if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && defined('\CURLOPT_HTTPAUTH')) {
099              unset(
100                  $options['curl'][\CURLOPT_HTTPAUTH],
101                  $options['curl'][\CURLOPT_USERPWD]
102              );
103          }
104   
105          if (isset($options['allow_redirects']['on_redirect'])) {
106              call_user_func(
107                  $options['allow_redirects']['on_redirect'],
108                  $request,
109                  $response,
110                  $nextRequest->getUri()
111              );
112          }
113   
114          /** @var PromiseInterface|ResponseInterface $promise */
115          $promise = $this($nextRequest, $options);
116   
117          // Add headers to be able to track history of redirects.
118          if (!empty($options['allow_redirects']['track_redirects'])) {
119              return $this->withTracking(
120                  $promise,
121                  (string) $nextRequest->getUri(),
122                  $response->getStatusCode()
123              );
124          }
125   
126          return $promise;
127      }
128   
129      /**
130       * Enable tracking on promise.
131       *
132       * @return PromiseInterface
133       */
134      private function withTracking(PromiseInterface $promise, $uri, $statusCode)
135      {
136          return $promise->then(
137              function (ResponseInterface $response) use ($uri, $statusCode) {
138                  // Note that we are pushing to the front of the list as this
139                  // would be an earlier response than what is currently present
140                  // in the history header.
141                  $historyHeader = $response->getHeader(self::HISTORY_HEADER);
142                  $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
143                  array_unshift($historyHeader, $uri);
144                  array_unshift($statusHeader, $statusCode);
145                  return $response->withHeader(self::HISTORY_HEADER, $historyHeader)
146                                  ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
147              }
148          );
149      }
150   
151      /**
152       * Check for too many redirects.
153       *
154       * @return void
155       *
156       * @throws TooManyRedirectsException Too many redirects.
157       */
158      private function guardMax(RequestInterface $request, array &$options)
159      {
160          $current = isset($options['__redirect_count'])
161              ? $options['__redirect_count']
162              : 0;
163          $options['__redirect_count'] = $current + 1;
164          $max = $options['allow_redirects']['max'];
165   
166          if ($options['__redirect_count'] > $max) {
167              throw new TooManyRedirectsException(
168                  "Will not follow more than {$max} redirects",
169                  $request
170              );
171          }
172      }
173   
174      /**
175       * @param RequestInterface  $request
176       * @param array             $options
177       * @param ResponseInterface $response
178       *
179       * @return RequestInterface
180       */
181      public function modifyRequest(
182          RequestInterface $request,
183          array $options,
184          ResponseInterface $response
185      ) {
186          // Request modifications to apply.
187          $modify = [];
188          $protocols = $options['allow_redirects']['protocols'];
189   
190          // Use a GET request if this is an entity enclosing request and we are
191          // not forcing RFC compliance, but rather emulating what all browsers
192          // would do.
193          $statusCode = $response->getStatusCode();
194          if ($statusCode == 303 ||
195              ($statusCode <= 302 && !$options['allow_redirects']['strict'])
196          ) {
197              $modify['method'] = 'GET';
198              $modify['body'] = '';
199          }
200   
201          $uri = self::redirectUri($request, $response, $protocols);
202          if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) {
203              $idnOptions = ($options['idn_conversion'] === true) ? IDNA_DEFAULT : $options['idn_conversion'];
204              $uri = Utils::idnUriConvert($uri, $idnOptions);
205          }
206   
207          $modify['uri'] = $uri;
208          Psr7\rewind_body($request);
209   
210          // Add the Referer header if it is told to do so and only
211          // add the header if we are not redirecting from https to http.
212          if ($options['allow_redirects']['referer']
213              && $modify['uri']->getScheme() === $request->getUri()->getScheme()
214          ) {
215              $uri = $request->getUri()->withUserInfo('');
216              $modify['set_headers']['Referer'] = (string) $uri;
217          } else {
218              $modify['remove_headers'][] = 'Referer';
219          }
220   
221          // Remove Authorization and Cookie headers if URI is cross-origin.
222          if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) {
223              $modify['remove_headers'][] = 'Authorization';
224              $modify['remove_headers'][] = 'Cookie';
225          }
226   
227          return Psr7\modify_request($request, $modify);
228      }
229   
230      /**
231       * Set the appropriate URL on the request based on the location header.
232       *
233       * @param RequestInterface  $request
234       * @param ResponseInterface $response
235       * @param array             $protocols
236       *
237       * @return UriInterface
238       */
239      private static function redirectUri(
240          RequestInterface $request,
241          ResponseInterface $response,
242          array $protocols
243      ) {
244          $location = Psr7\UriResolver::resolve(
245              $request->getUri(),
246              new Psr7\Uri($response->getHeaderLine('Location'))
247          );
248   
249          // Ensure that the redirect URI is allowed based on the protocols.
250          if (!in_array($location->getScheme(), $protocols)) {
251              throw new BadResponseException(
252                  sprintf(
253                      'Redirect URI, %s, does not use one of the allowed redirect protocols: %s',
254                      $location,
255                      implode(', ', $protocols)
256                  ),
257                  $request,
258                  $response
259              );
260          }
261   
262          return $location;
263      }
264  }
265