[HttpFoundation] Use parse_str() for query strings normalization
This commit is contained in:
parent
7101893b51
commit
513353644b
@ -4,6 +4,7 @@ CHANGELOG
|
|||||||
4.1.0
|
4.1.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* Query string normalization uses `parse_str()` instead of custom parsing logic.
|
||||||
* Passing the file size to the constructor of the `UploadedFile` class is deprecated.
|
* Passing the file size to the constructor of the `UploadedFile` class is deprecated.
|
||||||
* The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead.
|
* The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead.
|
||||||
* added `RedisSessionHandler` to use Redis as a session storage
|
* added `RedisSessionHandler` to use Redis as a session storage
|
||||||
|
@ -629,31 +629,10 @@ class Request
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$parts = array();
|
parse_str($qs, $qs);
|
||||||
$order = array();
|
ksort($qs);
|
||||||
|
|
||||||
foreach (explode('&', $qs) as $param) {
|
return http_build_query($qs, '', '&', PHP_QUERY_RFC3986);
|
||||||
if ('' === $param || '=' === $param[0]) {
|
|
||||||
// Ignore useless delimiters, e.g. "x=y&".
|
|
||||||
// Also ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway.
|
|
||||||
// PHP also does not include them when building _GET.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$keyValuePair = explode('=', $param, 2);
|
|
||||||
|
|
||||||
// GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded).
|
|
||||||
// PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. This is why we use urldecode and then normalize to
|
|
||||||
// RFC 3986 with rawurlencode.
|
|
||||||
$parts[] = isset($keyValuePair[1]) ?
|
|
||||||
rawurlencode(urldecode($keyValuePair[0])).'='.rawurlencode(urldecode($keyValuePair[1])) :
|
|
||||||
rawurlencode(urldecode($keyValuePair[0]));
|
|
||||||
$order[] = urldecode($keyValuePair[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
array_multisort($order, SORT_ASC, $parts);
|
|
||||||
|
|
||||||
return implode('&', $parts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -675,7 +675,7 @@ class RequestTest extends TestCase
|
|||||||
public function getQueryStringNormalizationData()
|
public function getQueryStringNormalizationData()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array('foo', 'foo', 'works with valueless parameters'),
|
array('foo', 'foo=', 'works with valueless parameters'),
|
||||||
array('foo=', 'foo=', 'includes a dangling equal sign'),
|
array('foo=', 'foo=', 'includes a dangling equal sign'),
|
||||||
array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'),
|
array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'),
|
||||||
array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'),
|
array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'),
|
||||||
@ -684,18 +684,24 @@ class RequestTest extends TestCase
|
|||||||
// PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str.
|
// PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str.
|
||||||
array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'),
|
array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'),
|
||||||
|
|
||||||
array('foo[]=1&foo[]=2', 'foo%5B%5D=1&foo%5B%5D=2', 'allows array notation'),
|
array('foo[]=1&foo[]=2', 'foo%5B0%5D=1&foo%5B1%5D=2', 'allows array notation'),
|
||||||
array('foo=1&foo=2', 'foo=1&foo=2', 'allows repeated parameters'),
|
array('foo=1&foo=2', 'foo=2', 'merges repeated parameters'),
|
||||||
array('pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'),
|
array('pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'),
|
||||||
array('0', '0', 'allows "0"'),
|
array('0', '0=', 'allows "0"'),
|
||||||
array('Jane Doe&John%20Doe', 'Jane%20Doe&John%20Doe', 'normalizes encoding in keys'),
|
array('Jane Doe&John%20Doe', 'Jane_Doe=&John_Doe=', 'normalizes encoding in keys'),
|
||||||
array('her=Jane Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes encoding in values'),
|
array('her=Jane Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes encoding in values'),
|
||||||
array('foo=bar&&&test&&', 'foo=bar&test', 'removes unneeded delimiters'),
|
array('foo=bar&&&test&&', 'foo=bar&test=', 'removes unneeded delimiters'),
|
||||||
array('formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'),
|
array('formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'),
|
||||||
|
|
||||||
// Ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway.
|
// Ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway.
|
||||||
// PHP also does not include them when building _GET.
|
// PHP also does not include them when building _GET.
|
||||||
array('foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'),
|
array('foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'),
|
||||||
|
|
||||||
|
// Don't reorder nested query string keys
|
||||||
|
array('foo[]=Z&foo[]=A', 'foo%5B0%5D=Z&foo%5B1%5D=A', 'keeps order of values'),
|
||||||
|
array('foo[Z]=B&foo[A]=B', 'foo%5BZ%5D=B&foo%5BA%5D=B', 'keeps order of keys'),
|
||||||
|
|
||||||
|
array('utf8=✓', 'utf8=%E2%9C%93', 'encodes UTF-8'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user