nette/http

Incorrect parsing URL with decoded semicolon

smesny opened this issue · 1 comments

Version: 3.0.3

Bug Description

With commit Url::parseQuery() accepts separator ;, there is different behavirour PHP vs NETTE regarding parsing URL variables with decoded semicolon. IMHO it wasn't correct even before this commit, because Url::parseQuery() completely ignores php.ini directive "arg_separator.input".

Steps To Reproduce

PHP with default settings (arg_separator.input="&"), these two blocks of code return two different results:

const TEST_URL = 'https://www.example.com/?example=1;2';

//PHP
$values = [];
$url = parse_url(TEST_URL);
parse_str($url['query'], $values);
print_r($values);

//NETTE
$url = new \Nette\Http\Url(TEST_URL);
$query = $url->getQuery();
$values = \Nette\Http\Url::parseQuery($query);
print_r($values);

Expected Behavior

They should both return this:
Array ( [example] => 1;2 )

Possible Solution

Like in eg. \Nette\Routing\Route::constructUrl(), we should apply here "arg_separator.input":

public static function parseQuery(string $s): array
{
$sep = ini_get('arg_separator.input');
if (!$sep) $sep = '&';

$s = str_replace(['%5B', '%5b'], '[', $s);
$s = preg_replace('#(['. $sep .'])([^['. $sep .'=]+)([^'. $sep .']*)#', $sep[0] . '0[$2]$3', $sep[0] . $s);
parse_str($s, $res);
return $res[0] ?? [];
}

Ok, it was fixed meanwhile: e4d8d36