[HttpFoundation] fix query string normalization

This commit is contained in:
Tobias Schultze 2012-07-04 03:10:48 +02:00
parent f9ec2ea3be
commit c40a4e50a9

View File

@ -466,32 +466,41 @@ class Request
/** /**
* Normalizes a query string. * Normalizes a query string.
* *
* It builds a normalized query string, where keys/value pairs are alphabetized * It builds a normalized query string, where keys/value pairs are alphabetized,
* and have consistent escaping. * have consistent escaping and unneeded delimiters are removed.
* *
* @param string $qs Query string * @param string $qs Query string
* *
* @return string|null A normalized query string for the Request * @return string A normalized query string for the Request
*/ */
static public function normalizeQueryString($qs = null) static public function normalizeQueryString($qs)
{ {
if (!$qs) { if ('' == $qs) {
return null; return '';
} }
$parts = array(); $parts = array();
$order = array(); $order = array();
foreach (explode('&', $qs) as $segment) { foreach (explode('&', $qs) as $param) {
if (false === strpos($segment, '=')) { if ('' === $param || '=' === $param[0]) {
$parts[] = $segment; // Ignore useless delimiters, e.g. "x=y&".
$order[] = $segment; // Also ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway.
} else { // PHP also does not include them when building _GET.
$tmp = explode('=', rawurldecode($segment), 2); continue;
$parts[] = rawurlencode($tmp[0]).'='.rawurlencode($tmp[1]);
$order[] = $tmp[0];
} }
$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); array_multisort($order, SORT_ASC, $parts);
return implode('&', $parts); return implode('&', $parts);
@ -843,7 +852,8 @@ class Request
*/ */
public function getQueryString() public function getQueryString()
{ {
return static::normalizeQueryString($this->server->get('QUERY_STRING')); $qs = static::normalizeQueryString($this->server->get('QUERY_STRING'));
return '' === $qs ? null : $qs;
} }
/** /**