2009-12-26 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Added system.multicall XML-RPC method.
	* src/XmlRpcMethod.cc
	* src/XmlRpcMethod.h
	* src/XmlRpcMethodFactory.cc
	* src/XmlRpcMethodImpl.cc
	* src/XmlRpcMethodImpl.h
	* test/XmlRpcMethodTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-12-26 10:16:56 +00:00
parent 838fcbbecd
commit af20aea88c
7 changed files with 135 additions and 1 deletions

View File

@ -1,3 +1,13 @@
2009-12-26 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added system.multicall XML-RPC method.
* src/XmlRpcMethod.cc
* src/XmlRpcMethod.h
* src/XmlRpcMethodFactory.cc
* src/XmlRpcMethodImpl.cc
* src/XmlRpcMethodImpl.h
* test/XmlRpcMethodTest.cc
2009-12-25 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Check structure depth when decoding.

View File

@ -56,7 +56,7 @@ XmlRpcMethod::XmlRpcMethod():
_optionParser(OptionParser::getInstance()),
_logger(LogFactory::getInstance()) {}
static BDE createErrorResponse(const Exception& e)
BDE XmlRpcMethod::createErrorResponse(const Exception& e)
{
BDE params = BDE::dict();
params["faultCode"] = BDE(1);

View File

@ -48,6 +48,7 @@ class OptionParser;
class BDE;
class Logger;
class Option;
class Exception;
namespace xmlrpc {
@ -88,6 +89,8 @@ protected:
// Copy options which is changeable in XML-RPC changeGlobalOption
// command to dest.
void applyChangeableGlobalOption(Option* dest, Option* src) const;
BDE createErrorResponse(const Exception& e);
public:
XmlRpcMethod();

View File

@ -89,6 +89,8 @@ XmlRpcMethodFactory::create(const std::string& methodName)
return SharedHandle<XmlRpcMethod>(new PurgeDownloadResultXmlRpcMethod());
} else if(methodName == "aria2.getVersion") {
return SharedHandle<XmlRpcMethod>(new GetVersionXmlRpcMethod());
} else if(methodName == "system.multicall") {
return SharedHandle<XmlRpcMethod>(new SystemMulticallXmlRpcMethod());
} else {
return SharedHandle<XmlRpcMethod>(new NoSuchMethodXmlRpcMethod());
}

View File

@ -59,6 +59,8 @@
#include "message.h"
#include "FeatureConfig.h"
#include "array_fun.h"
#include "XmlRpcMethodFactory.h"
#include "XmlRpcResponse.h"
#ifdef ENABLE_BITTORRENT
# include "bittorrent_helper.h"
# include "BtRegistry.h"
@ -111,6 +113,8 @@ const std::string KEY_LENGTH = "length";
const std::string KEY_URI = "uri";
const std::string KEY_VERSION = "version";
const std::string KEY_ENABLED_FEATURES = "enabledFeatures";
const std::string KEY_METHOD_NAME = "methodName";
const std::string KEY_PARAMS = "params";
}
static BDE createGIDResponse(int32_t gid)
@ -815,6 +819,50 @@ BDE ChangePositionXmlRpcMethod::process
return result;
}
BDE SystemMulticallXmlRpcMethod::process
(const XmlRpcRequest& req, DownloadEngine* e)
{
const BDE& params = req._params;
assert(params.isList());
if(params.size() != 1) {
throw DL_ABORT_EX("Illegal argument. One item list is expected.");
}
const BDE& methodSpecs = params[0];
BDE list = BDE::list();
for(BDE::List::const_iterator i = methodSpecs.listBegin();
i != methodSpecs.listEnd(); ++i) {
if(!(*i).isDict()) {
list << createErrorResponse
(DL_ABORT_EX("system.multicall expected struct."));
continue;
}
if(!(*i).containsKey(KEY_METHOD_NAME) ||
!(*i).containsKey(KEY_PARAMS)) {
list << createErrorResponse
(DL_ABORT_EX("Missing methodName or params."));
continue;
}
const std::string& methodName = (*i)[KEY_METHOD_NAME].s();
if(methodName == "system.multicall") {
list << createErrorResponse
(DL_ABORT_EX("Recursive system.multicall forbidden."));
continue;
}
SharedHandle<XmlRpcMethod> method = XmlRpcMethodFactory::create(methodName);
XmlRpcRequest innerReq(methodName, (*i)[KEY_PARAMS]);
XmlRpcResponse res = method->execute(innerReq, e);
if(res._code == 0) {
BDE l = BDE::list();
l << res._param;
list << l;
} else {
list << res._param;
}
}
return list;
}
BDE NoSuchMethodXmlRpcMethod::process
(const XmlRpcRequest& req, DownloadEngine* e)
{

View File

@ -140,6 +140,11 @@ protected:
virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
};
class SystemMulticallXmlRpcMethod:public XmlRpcMethod {
protected:
virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
};
class NoSuchMethodXmlRpcMethod:public XmlRpcMethod {
protected:
virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);

View File

@ -69,6 +69,8 @@ class XmlRpcMethodTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testGatherProgressCommon);
CPPUNIT_TEST(testChangePosition);
CPPUNIT_TEST(testChangePosition_fail);
CPPUNIT_TEST(testSystemMulticall);
CPPUNIT_TEST(testSystemMulticall_fail);
CPPUNIT_TEST_SUITE_END();
private:
SharedHandle<DownloadEngine> _e;
@ -123,6 +125,8 @@ public:
void testGatherProgressCommon();
void testChangePosition();
void testChangePosition_fail();
void testSystemMulticall();
void testSystemMulticall_fail();
};
@ -712,6 +716,68 @@ void XmlRpcMethodTest::testChangePosition_fail()
CPPUNIT_ASSERT_EQUAL(1, res._code);
}
void XmlRpcMethodTest::testSystemMulticall()
{
SystemMulticallXmlRpcMethod m;
XmlRpcRequest req("system.multicall", BDE::list());
BDE reqparams = BDE::list();
req._params << reqparams;
for(int i = 0; i < 2; ++i) {
BDE dict = BDE::dict();
dict["methodName"] = std::string("aria2.addUri");
BDE params = BDE::list();
params << BDE::list();
params[0] << BDE("http://localhost/"+util::itos(i));
dict["params"] = params;
reqparams << dict;
}
{
BDE dict = BDE::dict();
dict["methodName"] = std::string("not exists");
dict["params"] = BDE::list();
reqparams << dict;
}
{
reqparams << std::string("not struct");
}
{
BDE dict = BDE::dict();
dict["methodName"] = std::string("system.multicall");
dict["params"] = BDE::list();
reqparams << dict;
}
{
// missing params
BDE dict = BDE::dict();
dict["methodName"] = std::string("aria2.getVersion");
reqparams << dict;
}
{
BDE dict = BDE::dict();
dict["methodName"] = std::string("aria2.getVersion");
dict["params"] = BDE::list();
reqparams << dict;
}
XmlRpcResponse res = m.execute(req, _e.get());
CPPUNIT_ASSERT_EQUAL(0, res._code);
CPPUNIT_ASSERT_EQUAL((size_t)7, res._param.size());
CPPUNIT_ASSERT_EQUAL(std::string("1"), res._param[0][0].s());
CPPUNIT_ASSERT_EQUAL(std::string("2"), res._param[1][0].s());
CPPUNIT_ASSERT_EQUAL((int64_t)1, res._param[2]["faultCode"].i());
CPPUNIT_ASSERT_EQUAL((int64_t)1, res._param[3]["faultCode"].i());
CPPUNIT_ASSERT_EQUAL((int64_t)1, res._param[4]["faultCode"].i());
CPPUNIT_ASSERT_EQUAL((int64_t)1, res._param[5]["faultCode"].i());
CPPUNIT_ASSERT(res._param[6].isList());
}
void XmlRpcMethodTest::testSystemMulticall_fail()
{
SystemMulticallXmlRpcMethod m;
XmlRpcRequest req("system.multicall", BDE::list());
XmlRpcResponse res = m.execute(req, _e.get());
CPPUNIT_ASSERT_EQUAL(1, res._code);
}
} // namespace xmlrpc
} // namespace aria2