phpmyadmin/src/UrlRedirector.php
Maurício Meneghini Fauth dc1bd60dd1
Fix boolean usage of the return value of preg_match()
preg_match() and preg_match_all() returns the number of pattern matches
(which might be zero), or false on failure. However, preg_match() always
returns 1 when a pattern is matched as it stops searching after the
first match.

- https://www.php.net/manual/en/function.preg-match.php
- https://www.php.net/manual/en/function.preg-match-all.php

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
2024-07-13 14:43:05 -03:00

52 lines
1.5 KiB
PHP

<?php
declare(strict_types=1);
namespace PhpMyAdmin;
use Fig\Http\Message\StatusCodeInterface;
use PhpMyAdmin\Http\Factory\ResponseFactory;
use PhpMyAdmin\Http\Response;
use function is_string;
use function preg_match;
/**
* URL redirector to avoid leaking Referer with some sensitive information.
*/
final class UrlRedirector
{
public function __construct(
private readonly ResponseRenderer $response,
private readonly Template $template,
private readonly ResponseFactory $responseFactory,
) {
}
public function redirect(mixed $urlParam): Response
{
$response = $this->responseFactory->createResponse();
foreach ($this->response->getHeader()->getHttpHeaders() as $name => $value) {
$response = $response->withHeader($name, $value);
}
$url = is_string($urlParam) ? $urlParam : '';
if (
$url === ''
|| preg_match('/^https:\/\/[^\n\r]*$/', $url) !== 1
|| ! Core::isAllowedDomain($url)
) {
$response = $response->withHeader('Location', $this->response->fixRelativeUrlForRedirect('./'));
return $response->withStatus(StatusCodeInterface::STATUS_FOUND);
}
/**
* JavaScript redirection is necessary. Because if header() is used then web browser sometimes does not change
* the HTTP_REFERER field and so with old URL as Referer, token also goes to external site.
*/
return $response->write($this->template->render('javascript/redirect', ['url' => $url]));
}
}