From d0ccb39880106984975994d83a858b9f596518a1 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 26 Dec 2015 20:57:33 +0900 Subject: [PATCH] Add system.listMethods RPC method system.listMethods just returns the available RPC method names. It can be executed without secret token, because it just returns the method names, and does not alter anything. See GH-437 --- doc/manual-src/en/aria2c.rst | 34 ++++++++++++++++++++++++++++++++++ src/RpcMethodFactory.cc | 28 ++++++++++++++++++++++++++++ src/RpcMethodFactory.h | 3 +++ src/RpcMethodImpl.cc | 18 ++++++++++++++++++ src/RpcMethodImpl.h | 11 +++++++++++ test/RpcMethodTest.cc | 21 +++++++++++++++++++++ 6 files changed, 115 insertions(+) diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst index ef86bd93..d5ef8485 100644 --- a/doc/manual-src/en/aria2c.rst +++ b/doc/manual-src/en/aria2c.rst @@ -2228,6 +2228,10 @@ to provide the token as the first parameter as described above. interface. Therefore it is recommended to prefer Batch or `system.multicall` requests when appropriate. + `system.listMethods` can be executed without token. Since it just + returns the all available methods, and does not alter anything, it + is safe without secret token. + Methods ~~~~~~~ @@ -3429,6 +3433,36 @@ For information on the *secret* parameter, see :ref:`rpc_auth`. >>> tuple(r) ('2089b05ecca3d829', 'd2703803b52216d1') +.. function:: system.listMethods() + + This method returns the all available RPC methods in an array of + string. Unlike other methods, this method does not require secret + token. This is safe because this method jsut returns the available + method names. + + **JSON-RPC Example** + :: + + >>> import urllib2, json + >>> from pprint import pprint + >>> jsonreq = json.dumps({'jsonrpc':'2.0', 'id':'qwer', + ... 'method':'system.listMethods'}) + >>> c = urllib2.urlopen('http://localhost:6800/jsonrpc', jsonreq) + >>> pprint(json.loads(c.read())) + {u'id': u'qwer', + u'jsonrpc': u'2.0', + u'result': [u'aria2.addUri', + u'aria2.addTorrent', + ... + + **XML-RPC Example** + :: + + >>> import xmlrpclib + >>> s = xmlrpclib.ServerProxy('http://localhost:6800/rpc') + >>> s.system.listMethods() + ['aria2.addUri', 'aria2.addTorrent', ... + Error Handling ~~~~~~~~~~~~~~ diff --git a/src/RpcMethodFactory.cc b/src/RpcMethodFactory.cc index 1e505cf5..2b1ce98c 100644 --- a/src/RpcMethodFactory.cc +++ b/src/RpcMethodFactory.cc @@ -49,6 +49,30 @@ namespace { std::unique_ptr noSuchRpcMethod; } // namespace +namespace { +std::vector rpcMethodNames = { + "aria2.addUri", +#ifdef ENABLE_BITTORRENT + "aria2.addTorrent", "aria2.getPeers", +#endif // ENABLE_BITTORRENT +#ifdef ENABLE_METALINK + "aria2.addMetalink", +#endif // ENABLE_METALINK + "aria2.remove", "aria2.pause", "aria2.forcePause", "aria2.pauseAll", + "aria2.forcePauseAll", "aria2.unpause", "aria2.unpauseAll", + "aria2.forceRemove", "aria2.changePosition", "aria2.tellStatus", + "aria2.getUris", "aria2.getFiles", "aria2.getServers", "aria2.tellActive", + "aria2.tellWaiting", "aria2.tellStopped", "aria2.getOption", + "aria2.changeUri", "aria2.changeOption", "aria2.getGlobalOption", + "aria2.changeGlobalOption", "aria2.purgeDownloadResult", + "aria2.removeDownloadResult", "aria2.getVersion", "aria2.getSessionInfo", + "aria2.shutdown", "aria2.forceShutdown", "aria2.getGlobalStat", + "aria2.saveSession", "system.multicall", "system.listMethods", +}; +} // namespace + +const std::vector& allMethodNames() { return rpcMethodNames; } + namespace { std::unique_ptr createMethod(const std::string& methodName) { @@ -192,6 +216,10 @@ std::unique_ptr createMethod(const std::string& methodName) return make_unique(); } + if (methodName == SystemListMethodsRpcMethod::getMethodName()) { + return make_unique(); + } + return nullptr; } } // namespace diff --git a/src/RpcMethodFactory.h b/src/RpcMethodFactory.h index 07f83c58..ebd4a479 100644 --- a/src/RpcMethodFactory.h +++ b/src/RpcMethodFactory.h @@ -39,6 +39,7 @@ #include #include +#include namespace aria2 { @@ -46,6 +47,8 @@ namespace rpc { class RpcMethod; +const std::vector& allMethodNames(); + RpcMethod* getMethod(const std::string& methodName); } // namespace rpc diff --git a/src/RpcMethodImpl.cc b/src/RpcMethodImpl.cc index 7b1b8fbd..8dad61c3 100644 --- a/src/RpcMethodImpl.cc +++ b/src/RpcMethodImpl.cc @@ -1429,6 +1429,24 @@ RpcResponse SystemMulticallRpcMethod::execute(RpcRequest req, DownloadEngine *e) } } +std::unique_ptr SystemListMethodsRpcMethod::process +(const RpcRequest&req, DownloadEngine *e) { + auto list = List::g(); + for (auto &s : allMethodNames()) { + list->append(s); + } + + return list; +} + +RpcResponse SystemListMethodsRpcMethod::execute(RpcRequest req, + DownloadEngine* e) +{ + auto r = process(req, e); + return RpcResponse(0, RpcResponse::AUTHORIZED, std::move(r), + std::move(req.id)); +} + std::unique_ptr NoSuchMethodRpcMethod::process (const RpcRequest& req, DownloadEngine* e) { diff --git a/src/RpcMethodImpl.h b/src/RpcMethodImpl.h index 442303fe..a5f562b1 100644 --- a/src/RpcMethodImpl.h +++ b/src/RpcMethodImpl.h @@ -596,6 +596,17 @@ public: } }; +class SystemListMethodsRpcMethod : public RpcMethod { +protected: + virtual std::unique_ptr process(const RpcRequest& req, + DownloadEngine* e) CXX11_OVERRIDE; + +public: + virtual RpcResponse execute(RpcRequest req, DownloadEngine* e) CXX11_OVERRIDE; + + static const char* getMethodName() { return "system.listMethods"; } +}; + class NoSuchMethodRpcMethod:public RpcMethod { protected: virtual std::unique_ptr process diff --git a/test/RpcMethodTest.cc b/test/RpcMethodTest.cc index eddc1651..e975dd09 100644 --- a/test/RpcMethodTest.cc +++ b/test/RpcMethodTest.cc @@ -20,6 +20,7 @@ #include "array_fun.h" #include "download_helper.h" #include "FileEntry.h" +#include "RpcMethodFactory.h" #ifdef ENABLE_BITTORRENT # include "BtRegistry.h" # include "BtRuntime.h" @@ -78,6 +79,7 @@ class RpcMethodTest:public CppUnit::TestFixture { CPPUNIT_TEST(testPause); CPPUNIT_TEST(testSystemMulticall); CPPUNIT_TEST(testSystemMulticall_fail); + CPPUNIT_TEST(testSystemListMethods); CPPUNIT_TEST_SUITE_END(); private: std::shared_ptr e_; @@ -142,6 +144,7 @@ public: void testPause(); void testSystemMulticall(); void testSystemMulticall_fail(); + void testSystemListMethods(); }; @@ -1363,6 +1366,24 @@ void RpcMethodTest::testSystemMulticall_fail() CPPUNIT_ASSERT_EQUAL(1, res.code); } +void RpcMethodTest::testSystemListMethods() +{ + SystemListMethodsRpcMethod m; + auto res = m.execute(createReq("system.listMethods"), e_.get()); + CPPUNIT_ASSERT_EQUAL(0, res.code); + + const auto resParams = downcast(res.param); + auto &allNames = allMethodNames(); + + CPPUNIT_ASSERT_EQUAL(allNames.size(), resParams->size()); + + for (size_t i = 0; i < allNames.size(); ++i) { + const auto s = downcast(resParams->get(i)); + CPPUNIT_ASSERT(s); + CPPUNIT_ASSERT_EQUAL(allNames[i], s->s()); + } +} + } // namespace rpc } // namespace aria2