Author: bhofmann
Date: Mon Feb 14 15:52:17 2011
New Revision: 1070532
URL: http://svn.apache.org/viewvc?rev=1070532&view=rev
Log:
SHINDIG-1506: fixed incorrect dispatching of parameters in RPC GET requests
Added:
shindig/trunk/php/test/social/JsonRpcServletTest.php
Modified:
shindig/trunk/php/src/social/servlet/JsonRpcServlet.php
Modified: shindig/trunk/php/src/social/servlet/JsonRpcServlet.php
URL:
http://svn.apache.org/viewvc/shindig/trunk/php/src/social/servlet/JsonRpcServlet.php?rev=1070532&r1=1070531&r2=1070532&view=diff
==============================================================================
--- shindig/trunk/php/src/social/servlet/JsonRpcServlet.php (original)
+++ shindig/trunk/php/src/social/servlet/JsonRpcServlet.php Mon Feb 14 15:52:17
2011
@@ -27,7 +27,7 @@ class JsonRpcServlet extends ApiServlet
/**
* Single request through GET
- *
http://api.example.org/rpc?method=people.get&id=myself&userid=@me&groupid=@self
+ *
http://api.example.org/rpc?method=people.get&id=myself¶ms.userId=@me¶ms.groupId=@self
*/
public function doGet() {
$token = $this->getSecurityToken();
@@ -35,12 +35,89 @@ class JsonRpcServlet extends ApiServlet
$this->sendSecurityError();
return;
}
- // Request object == GET params
- $request = $_GET;
+
+ $request = $this->parseGetRequest($_SERVER['QUERY_STRING']);
+
$this->dispatch($request, $token);
}
/**
+ * parses all $_GET parameters according to rpc spec
+ * @see
http://opensocial-resources.googlecode.com/svn/spec/1.1/Core-API-Server.xml#urlAddressing
+ *
+ * @param string $parameters should be $_GET on production
+ * @return array
+ */
+ public function parseGetRequest($parameterString)
+ {
+ // we have to parse the query parameters by hand because parse_str or the
built in
+ // $_GET replace '.' with '_' in parameter keys
+ $parameters = array();
+ $pairs = explode('&', $parameterString);
+ foreach ($pairs as $pair) {
+ if (strpos($pair, '=') !== false) {
+ list($key, $value) = explode('=', $pair);
+ $parameters[$key] = urldecode($value);
+ }
+ }
+ $request = array();
+ foreach($parameters as $key => $value) {
+ // parse value lists like field=1,2,3,4,5
+ if (strpos($value, ',') !== false) {
+ $parsedValue = explode(',', $value);
+ } else {
+ $parsedValue = $value;
+ }
+ // handle multidimensional nested keys like field.nested=value
+ if (strpos($key, '.') > 0) {
+ $keyParts = explode('.', $key);
+ $request = $this->getMultiDimensionalArray($request, $keyParts,
$parsedValue);
+ } else {
+ $request = $this->getMultiDimensionalArray($request, array($key),
$parsedValue);
+ }
+ }
+ return $request;
+ }
+
+ /**
+ * parses a multidimensional parameter
+ * e.g. params.foo=bar to 'params' => array('foo' => 'bar')
+ *
+ * @param array $request
+ * @param array $keyParts
+ * @param mixed $value
+ * @return array
+ */
+ private function getMultiDimensionalArray($request, $keyParts, $value)
+ {
+ if (! $keyParts) {
+ return $value;
+ }
+ $key = array_shift($keyParts);
+
+ $matches = array();
+
+ // handle something like field(0).nested1=value1&field(1).nested2=value2
+ if (preg_match('/^([a-zA-Z0-9]*)\(([0-9]*)\)$/', $key, $matches)) {
+ $key = $matches[1];
+ array_unshift($keyParts, $matches[2]);
+ }
+
+ if (! isset($request[$key])) {
+ $request[$key] = array();
+ }
+ $value = $this->getMultiDimensionalArray($request[$key], $keyParts,
$value);
+
+ if (is_array($value)) {
+ $request[$key] = $value + $request[$key];
+ } else {
+ $request[$key] = $value;
+ }
+
+ return $request;
+ }
+
+ /**
* RPC Post request
*/
public function doPost() {
@@ -107,7 +184,8 @@ class JsonRpcServlet extends ApiServlet
$requestItem = new RpcRequestItem($request, $token);
// Resolve each Future into a response.
// TODO: should use shared deadline across each request
- $response = $this->getResponseItem($this->handleRequestItem($requestItem));
+ $a = $this->handleRequestItem($requestItem);
+ $response = $this->getResponseItem($a);
$result = $this->getJSONResponse($key, $response);
$this->encodeAndSendResponse($result);
}
@@ -160,7 +238,7 @@ class JsonRpcServlet extends ApiServlet
/**
* encodes data to json, adds jsonp callback if requested and sends response
* to client
- *
+ *
* @param array $data
* @return string
*/
Added: shindig/trunk/php/test/social/JsonRpcServletTest.php
URL:
http://svn.apache.org/viewvc/shindig/trunk/php/test/social/JsonRpcServletTest.php?rev=1070532&view=auto
==============================================================================
--- shindig/trunk/php/test/social/JsonRpcServletTest.php (added)
+++ shindig/trunk/php/test/social/JsonRpcServletTest.php Mon Feb 14 15:52:17
2011
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+class JsonRpcServletTest extends PHPUnit_Framework_TestCase {
+
+ public function testParseRPCGetParameters()
+ {
+ $servlet = new JsonRpcServlet();
+
+ $parameters =
'oauth_token=abcdef&method=people.get&id=req¶ms.userId=@me¶ms.groupId=@self&field=1,2,3&fieldtwo(0).nested1=value1&fieldtwo(1).nested2.blub(0)=value2&fieldtwo(1).nested3=value3&f.a.c=foo&f.a.d=bar';
+
+ $result = $servlet->parseGetRequest($parameters);
+
+ $expected = array(
+ 'method' => 'people.get',
+ 'id' => 'req',
+ 'params' => array(
+ 'userId' => '@me',
+ 'groupId' => '@self',
+ ),
+ 'field' => array(1,2,3),
+ 'fieldtwo' => array(
+ 0 => array(
+ 'nested1' => 'value1',
+ ),
+ 1 => array(
+ 'nested2' => array(
+ 'blub' => array(
+ 0 => 'value2',
+ ),
+ ),
+ 'nested3' => 'value3',
+ ),
+ ),
+ 'f' => array(
+ 'a' => array(
+ 'c' => 'foo',
+ 'd' => 'bar',
+ )
+ ),
+ 'oauth_token' => 'abcdef',
+ );
+
+ $this->assertEquals($expected, $result);
+ }
+
+
+ public function testParseRPCGetWithEmptyParameters()
+ {
+ $servlet = new JsonRpcServlet();
+
+ $result = $servlet->parseGetRequest('');
+
+ $this->assertEquals(array(), $result);
+ }
+}