Skip to content

Commit

Permalink
Remove parse_str() its buggy and wrong.
Browse files Browse the repository at this point in the history
parse_str() replaces `.` with _ and drops duplicated keys, which is
incorrect.  Replace parse_str with an updated version of parseQuery
from 1.x

Fixes #2629
Fixes #2647
  • Loading branch information
markstory committed Mar 9, 2012
1 parent 621b086 commit 150c9fc
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
53 changes: 52 additions & 1 deletion lib/Cake/Network/Http/HttpSocket.php
Expand Up @@ -768,7 +768,58 @@ protected function _parseQuery($query) {
if (is_array($query)) {
return $query;
}
parse_str(ltrim($query, '?'), $parsedQuery);

if (is_array($query)) {
return $query;
}
$parsedQuery = array();

if (is_string($query) && !empty($query)) {
$query = preg_replace('/^\?/', '', $query);
$items = explode('&', $query);

foreach ($items as $item) {
if (strpos($item, '=') !== false) {
list($key, $value) = explode('=', $item, 2);
} else {
$key = $item;
$value = null;
}

$key = urldecode($key);
$value = urldecode($value);

if (preg_match_all('/\[([^\[\]]*)\]/iUs', $key, $matches)) {
$subKeys = $matches[1];
$rootKey = substr($key, 0, strpos($key, '['));
if (!empty($rootKey)) {
array_unshift($subKeys, $rootKey);
}
$queryNode =& $parsedQuery;

foreach ($subKeys as $subKey) {
if (!is_array($queryNode)) {
$queryNode = array();
}

if ($subKey === '') {
$queryNode[] = array();
end($queryNode);
$subKey = key($queryNode);
}
$queryNode =& $queryNode[$subKey];
}
$queryNode = $value;
continue;
}
if (!isset($parsedQuery[$key])) {
$parsedQuery[$key] = $value;
} else {
$parsedQuery[$key] = (array)$parsedQuery[$key];
$parsedQuery[$key][] = $value;
}
}
}
return $parsedQuery;
}

Expand Down
10 changes: 9 additions & 1 deletion lib/Cake/Test/Case/Network/Http/HttpSocketTest.php
Expand Up @@ -1450,7 +1450,15 @@ public function testParseQuery() {
),
'empty' => ''
);
$this->assertEquals($query, $expectedQuery);
$this->assertEquals($expectedQuery, $query);

$query = 'openid.ns=example.com&foo=bar&foo=baz';
$result = $this->Socket->parseQuery($query);
$expected = array(
'openid.ns' => 'example.com',
'foo' => array('bar', 'baz')
);
$this->assertEquals($expected, $result);
}

/**
Expand Down

0 comments on commit 150c9fc

Please sign in to comment.