diff options
author | Sadie Powell <sadie@witchery.services> | 2025-02-20 12:33:59 +0000 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2025-02-20 12:53:15 +0000 |
commit | b498f4f4d91ff09120bfce6a10f7362fc40a011a (patch) | |
tree | ab773a5316a1d33c291441e8f882930b37222d1b /modules/extra/xmlrpc.cpp | |
parent | 8330cd119ac390036cb5cadd51019e6b496c1bfc (diff) |
Add support for more RPC data types.
Diffstat (limited to 'modules/extra/xmlrpc.cpp')
-rw-r--r-- | modules/extra/xmlrpc.cpp | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/modules/extra/xmlrpc.cpp b/modules/extra/xmlrpc.cpp index 63ed55433..2051f35e1 100644 --- a/modules/extra/xmlrpc.cpp +++ b/modules/extra/xmlrpc.cpp @@ -15,6 +15,9 @@ #include "modules/rpc.h" #include "modules/httpd.h" +template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; +template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; + class MyXMLRPCServiceInterface final : public RPCServiceInterface , public HTTPPage @@ -22,7 +25,7 @@ class MyXMLRPCServiceInterface final private: Anope::map<RPCEvent *> events; - void SendError(HTTPReply &reply, xmlrpc_env &env) + static void SendError(HTTPReply &reply, xmlrpc_env &env) { Log(LOG_DEBUG) << "XML-RPC error " << env.fault_code << ": " << env.fault_string; @@ -39,6 +42,59 @@ private: xmlrpc_env_clean(&env); } + static void SerializeObject(xmlrpc_env &env, xmlrpc_value *value, const RPCBlock &block) + { + for (const auto &[k, v] : block.GetReplies()) + { + xmlrpc_value *elem; + std::visit(overloaded + { + [&env, &elem](const RPCBlock &b) + { + elem = xmlrpc_struct_new(&env); + SerializeObject(env, elem, b); + }, + [&env, &elem](const Anope::string &s) + { + elem = xmlrpc_string_new_lp(&env, s.length(), s.c_str()); + }, + [&env, &elem](std::nullptr_t) + { + elem = xmlrpc_nil_new(&env); + }, + [&env, &elem](bool b) + { + elem = xmlrpc_bool_new(&env, b); + }, + [&env, &elem](double d) + { + elem = xmlrpc_double_new(&env, d); + }, + [&env, &elem](int64_t i) + { + elem = xmlrpc_i8_new(&env, i); + }, + [&env, &elem](uint64_t u) + { + // XML-RPC does not support unsigned data types. + if (u > INT64_MAX) + { + // We need to convert this to a string. + auto s = Anope::ToString(u); + elem = xmlrpc_string_new_lp(&env, s.length(), s.c_str()); + } + else + { + // We can fit this into a i8. + elem = xmlrpc_i8_new(&env, u); + } + }, + }, v); + + xmlrpc_struct_set_value_n(&env, value, k.c_str(), k.length(), elem); + } + } + public: MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname) : RPCServiceInterface(creator, sname) @@ -138,11 +194,7 @@ public: } auto *value = xmlrpc_struct_new(&env); - for (const auto &[k, v] : request.GetReplies()) - { - auto *str = xmlrpc_string_new_lp(&env, v.length(), v.c_str()); - xmlrpc_struct_set_value_n(&env, value, k.c_str(), k.length(), str); - } + SerializeObject(env, value, request); auto *response = xmlrpc_mem_block_new(&env, 0); xmlrpc_serialize_response(&env, response, value); |