summaryrefslogtreecommitdiff
path: root/modules/rpc/xmlrpc.cpp
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2025-02-18 16:15:58 +0000
committerSadie Powell <sadie@witchery.services>2025-02-18 16:15:58 +0000
commit98320d130f6c74793d416526e892b11ca5619b91 (patch)
tree4e0ecde92ac8a7d4a1bf09f3dff82389fb48a666 /modules/rpc/xmlrpc.cpp
parent37f21a2e1eae792aa30a397f64e93a624c39631e (diff)
Rewrite the xmlrpc module using libxmlrpc-c.
Diffstat (limited to 'modules/rpc/xmlrpc.cpp')
-rw-r--r--modules/rpc/xmlrpc.cpp275
1 files changed, 0 insertions, 275 deletions
diff --git a/modules/rpc/xmlrpc.cpp b/modules/rpc/xmlrpc.cpp
deleted file mode 100644
index 2ecf00410..000000000
--- a/modules/rpc/xmlrpc.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- *
- * (C) 2010-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "module.h"
-#include "modules/rpc.h"
-#include "modules/httpd.h"
-
-static struct special_chars final
-{
- Anope::string character;
- Anope::string replace;
-
- special_chars(const Anope::string &c, const Anope::string &r) : character(c), replace(r) { }
-}
-special[] = {
- special_chars("&", "&amp;"),
- special_chars("\"", "&quot;"),
- special_chars("<", "&lt;"),
- special_chars(">", "&qt;"),
- special_chars("'", "&#39;"),
- special_chars("\n", "&#xA;"),
- special_chars("\002", ""), // bold
- special_chars("\003", ""), // color
- special_chars("\035", ""), // italics
- special_chars("\037", ""), // underline
- special_chars("\026", ""), // reverses
- special_chars("", "")
-};
-
-class MyXMLRPCServiceInterface final
- : public RPCServiceInterface
- , public HTTPPage
-{
- std::deque<RPCEvent *> events;
-
-public:
- MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname) : RPCServiceInterface(creator, sname), HTTPPage("/xmlrpc", "text/xml") { }
-
- void Register(RPCEvent *event) override
- {
- this->events.push_back(event);
- }
-
- void Unregister(RPCEvent *event) override
- {
- std::deque<RPCEvent *>::iterator it = std::find(this->events.begin(), this->events.end(), event);
-
- if (it != this->events.end())
- this->events.erase(it);
- }
-
- static Anope::string Sanitize(const Anope::string &string)
- {
- Anope::string ret = string;
- for (int i = 0; !special[i].character.empty(); ++i)
- ret = ret.replace_all_cs(special[i].character, special[i].replace);
- return ret;
- }
-
- static Anope::string Unescape(const Anope::string &string)
- {
- Anope::string ret = string;
- for (int i = 0; !special[i].character.empty(); ++i)
- if (!special[i].replace.empty())
- ret = ret.replace_all_cs(special[i].replace, special[i].character);
-
- for (size_t i, last = 0; (i = string.find("&#", last)) != Anope::string::npos;)
- {
- last = i + 1;
-
- size_t end = string.find(';', i);
- if (end == Anope::string::npos)
- break;
-
- Anope::string ch = string.substr(i + 2, end - (i + 2));
-
- if (ch.empty())
- continue;
-
- long l;
- if (!ch.empty() && ch[0] == 'x')
- l = strtol(ch.substr(1).c_str(), NULL, 16);
- else
- l = strtol(ch.c_str(), NULL, 10);
-
- if (l > 0 && l < 256)
- ret = ret.replace_all_cs("&#" + ch + ";", Anope::string(l));
- }
-
- return ret;
- }
-
-private:
- static bool GetData(Anope::string &content, Anope::string &tag, Anope::string &data)
- {
- if (content.empty())
- return false;
-
- Anope::string prev, cur;
- bool istag;
-
- do
- {
- prev = cur;
- cur.clear();
-
- size_t len = 0;
- istag = false;
-
- if (content[0] == '<')
- {
- len = content.find_first_of('>');
- istag = true;
- }
- else if (content[0] != '>')
- {
- len = content.find_first_of('<');
- }
-
- // len must advance
- if (len == Anope::string::npos || len == 0)
- break;
-
- if (istag)
- {
- cur = content.substr(1, len - 1);
- content.erase(0, len + 1);
- while (!content.empty() && content[0] == ' ')
- content.erase(content.begin());
- }
- else
- {
- cur = content.substr(0, len);
- content.erase(0, len);
- }
- }
- while (istag && !content.empty());
-
- tag = Unescape(prev);
- data = Unescape(cur);
- return !istag && !data.empty();
- }
-
-public:
- bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) override
- {
- Anope::string content = message.content, tname, data;
- RPCRequest request(reply);
-
- while (GetData(content, tname, data))
- {
- Log(LOG_DEBUG) << "xmlrpc: Tag name: " << tname << ", data: " << data;
- if (tname == "methodName")
- request.name = data;
- else if (tname == "name" && data == "id")
- {
- GetData(content, tname, data);
- request.id = data;
- }
- else if (tname == "string")
- request.data.push_back(data);
- }
-
- for (auto *e : this->events)
- {
- if (!e->Run(this, client, request))
- return false;
- else if (!request.GetReplies().empty())
- {
- this->Reply(request);
- return true;
- }
- }
-
- reply.error = HTTP_PAGE_NOT_FOUND;
- reply.Write("Unrecognized query");
- return true;
- }
-
- void Reply(RPCRequest &request) override
- {
- if (!request.id.empty())
- request.Reply("id", request.id);
-
- Anope::string xml =
- "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
- "<methodResponse>\n";
-
- if (request.GetError())
- {
- xml +=
- "<fault>\n"
- " <value>\n"
- " <struct>\n"
- " <member>\n"
- " <name>faultCode</name>\n"
- " <value>\n"
- " <int>" + Anope::ToString(request.GetError()->first) + "</int>\n"
- " </value>\n"
- " </member>\n"
- " <member>\n"
- " <name>faultString</name>\n"
- " <value>\n"
- " <string>" + this->Sanitize(request.GetError()->second) + "</string>\n"
- " </value>\n"
- " </member>\n"
- " </struct>\n"
- " </value>\n"
- "</fault>\n";
- }
- else
- {
- xml +=
- "<params>\n"
- " <param>\n"
- " <value>\n"
- " <struct>\n";
- for (const auto &[name, value] : request.GetReplies())
- {
- xml +=
- "<member>\n"
- " <name>" + this->Sanitize(name) + "</name>\n"
- " <value>\n"
- " <string>" + this->Sanitize(value) + "</string>\n"
- " </value>\n"
- "</member>\n";
- }
- xml +=
- " </struct>\n"
- " </value>\n"
- " </param>\n"
- "</params>\n";
- }
- xml += "</methodResponse>";
-
- request.reply.Write(xml);
- }
-};
-
-class ModuleXMLRPC final
- : public Module
-{
- ServiceReference<HTTPProvider> httpref;
-public:
- MyXMLRPCServiceInterface xmlrpcinterface;
-
- ModuleXMLRPC(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
- xmlrpcinterface(this, "rpc")
- {
-
- }
-
- ~ModuleXMLRPC() override
- {
- if (httpref)
- httpref->UnregisterPage(&xmlrpcinterface);
- }
-
- void OnReload(Configuration::Conf *conf) override
- {
- if (httpref)
- httpref->UnregisterPage(&xmlrpcinterface);
- this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", conf->GetModule(this)->Get<const Anope::string>("server", "httpd/main"));
- if (!httpref)
- throw ConfigException("Unable to find http reference, is httpd loaded?");
- httpref->RegisterPage(&xmlrpcinterface);
- }
-};
-
-MODULE_INIT(ModuleXMLRPC)