From 150c9fc6a3be0a86791202e76b5f0f2578c310fd Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 8 Mar 2012 21:05:28 -0500 Subject: [PATCH] Remove parse_str() its buggy and wrong. 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 --- lib/Cake/Network/Http/HttpSocket.php | 53 ++++++++++++++++++- .../Test/Case/Network/Http/HttpSocketTest.php | 10 +++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Network/Http/HttpSocket.php b/lib/Cake/Network/Http/HttpSocket.php index 3dd78cff8..cc9ed8d84 100644 --- a/lib/Cake/Network/Http/HttpSocket.php +++ b/lib/Cake/Network/Http/HttpSocket.php @@ -768,7 +768,58 @@ class HttpSocket extends CakeSocket { 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; } diff --git a/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php b/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php index 6869e83a8..991a9cd87 100644 --- a/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php +++ b/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php @@ -1450,7 +1450,15 @@ class HttpSocketTest extends CakeTestCase { ), '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); } /**