[CORE][Router][Form] Add Router::sanitizeLocalURL and use it in Form::forceRedirect
This commit is contained in:
parent
f540711948
commit
9a9eed1457
|
@ -47,7 +47,6 @@ use Symfony\Component\Form\FormFactoryInterface;
|
||||||
use Symfony\Component\Form\FormInterface as SymfFormInterface;
|
use Symfony\Component\Form\FormInterface as SymfFormInterface;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class converts our own form representation to Symfony's
|
* This class converts our own form representation to Symfony's
|
||||||
|
@ -221,18 +220,14 @@ abstract class Form
|
||||||
public static function forceRedirect(SymfFormInterface $form, Request $request): RedirectResponse
|
public static function forceRedirect(SymfFormInterface $form, Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$next = $form->get('_next')->getData();
|
$next = $form->get('_next')->getData();
|
||||||
try {
|
$url = Router::sanitizeLocalURL($next, ['next' => false]);
|
||||||
if ($pos = mb_strrpos($next, '#')) {
|
if (!\is_null($url)) {
|
||||||
$fragment = mb_substr($next, $pos);
|
return new RedirectResponse(url: $url);
|
||||||
$next = mb_substr($next, 0, $pos);
|
} else {
|
||||||
}
|
|
||||||
Router::match($next);
|
|
||||||
return new RedirectResponse(url: $next . ($fragment ?? ''));
|
|
||||||
} catch (ResourceNotFoundException $e) {
|
|
||||||
$user = Common::user();
|
$user = Common::user();
|
||||||
$user_id = !\is_null($user) ? $user->getId() : '(not logged in)';
|
$user_id = !\is_null($user) ? $user->getId() : '(not logged in)';
|
||||||
Log::warning("Suspicious activity: User with ID {$user_id} submitted a form where the `_next` parameter is not a valid local URL ({$next})");
|
Log::warning("Suspicious activity: User with ID {$user_id} submitted a form where the `_next` parameter is not a valid local URL ({$next})");
|
||||||
throw new ClientException(_m('Invalid form submission'), $e);
|
throw new ClientException(_m('Invalid form submission'), previous: $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ declare(strict_types = 1);
|
||||||
namespace App\Core\Router;
|
namespace App\Core\Router;
|
||||||
|
|
||||||
use App\Core\Log;
|
use App\Core\Log;
|
||||||
|
use App\Util\Common;
|
||||||
|
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
use Symfony\Component\Routing\Router as SymfonyRouter;
|
use Symfony\Component\Routing\Router as SymfonyRouter;
|
||||||
|
|
||||||
|
@ -89,6 +91,26 @@ abstract class Router
|
||||||
return self::$router->generate($id, $args, $type);
|
return self::$router->generate($id, $args, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function sanitizeLocalURL(string $url, array $unset_query_args = []): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$parts = parse_url($url);
|
||||||
|
if ($parts === false || (isset($parts['host']) && $parts['host'] !== Common::config('site', 'server'))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
self::match($parts['path']);
|
||||||
|
if ($unset_query_args !== [] && isset($parts['query'])) {
|
||||||
|
$args = [];
|
||||||
|
parse_str($parts['query'], $args);
|
||||||
|
$args = array_diff_key($args, $unset_query_args);
|
||||||
|
$parts['query'] = http_build_query($args);
|
||||||
|
}
|
||||||
|
return $parts['path'] . (empty($parts['query']) ? '' : ('?' . $parts['query'])) . (empty($parts['fragment']) ? '' : ('#' . $parts['fragment']));
|
||||||
|
} catch (ResourceNotFoundException) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function match($url) throws Symfony\Component\Routing\Exception\ResourceNotFoundException
|
* function match($url) throws Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -148,11 +148,10 @@ abstract class Common
|
||||||
return self::ensureLoggedIn()->getId();
|
return self::ensureLoggedIn()->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function ensureLoggedIn(): LocalUser
|
public static function ensureLoggedIn(?Request $request = null): LocalUser
|
||||||
{
|
{
|
||||||
if (($user = self::user()) == null) {
|
if (\is_null($user = self::user())) {
|
||||||
throw new NoLoggedInUser(self::getRequest());
|
throw new NoLoggedInUser($request ?? self::getRequest());
|
||||||
// TODO Maybe redirect to login page and back
|
|
||||||
} else {
|
} else {
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user