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<RpcMethod> noSuchRpcMethod; } // namespace +namespace { +std::vector<std::string> 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<std::string>& allMethodNames() { return rpcMethodNames; } + namespace { std::unique_ptr<RpcMethod> createMethod(const std::string& methodName) { @@ -192,6 +216,10 @@ std::unique_ptr<RpcMethod> createMethod(const std::string& methodName) return make_unique<SystemMulticallRpcMethod>(); } + if (methodName == SystemListMethodsRpcMethod::getMethodName()) { + return make_unique<SystemListMethodsRpcMethod>(); + } + 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 <string> #include <memory> +#include <vector> namespace aria2 { @@ -46,6 +47,8 @@ namespace rpc { class RpcMethod; +const std::vector<std::string>& 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<ValueBase> 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<ValueBase> 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<ValueBase> 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<ValueBase> 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<DownloadEngine> 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<List>(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<String>(resParams->get(i)); + CPPUNIT_ASSERT(s); + CPPUNIT_ASSERT_EQUAL(allNames[i], s->s()); + } +} + } // namespace rpc } // namespace aria2