summaryrefslogtreecommitdiff
path: root/modules/m_xmlrpc.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2014-01-02 11:02:14 -0500
committerAdam <Adam@anope.org>2014-01-02 11:03:33 -0500
commit004c4cbe5f4c37cf455cb6d0caa434fbbb3406ea (patch)
tree0e6675dfe28a829f5786b0b2f993566c61662de7 /modules/m_xmlrpc.cpp
parent072202c181943901c727782e64881adadf13d7dd (diff)
Move modules out of extras that dont have external dependencies
Diffstat (limited to 'modules/m_xmlrpc.cpp')
-rw-r--r--modules/m_xmlrpc.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/modules/m_xmlrpc.cpp b/modules/m_xmlrpc.cpp
new file mode 100644
index 000000000..36401b800
--- /dev/null
+++ b/modules/m_xmlrpc.cpp
@@ -0,0 +1,186 @@
+
+#include "module.h"
+#include "modules/xmlrpc.h"
+#include "modules/httpd.h"
+
+static struct special_chars
+{
+ 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 : public XMLRPCServiceInterface, public HTTPPage
+{
+ std::deque<XMLRPCEvent *> events;
+
+ public:
+ MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname) : XMLRPCServiceInterface(creator, sname), HTTPPage("/xmlrpc", "text/xml") { }
+
+ void Register(XMLRPCEvent *event)
+ {
+ this->events.push_back(event);
+ }
+
+ void Unregister(XMLRPCEvent *event)
+ {
+ std::deque<XMLRPCEvent *>::iterator it = std::find(this->events.begin(), this->events.end(), event);
+
+ if (it != this->events.end())
+ this->events.erase(it);
+ }
+
+ Anope::string Sanitize(const Anope::string &string) anope_override
+ {
+ Anope::string ret = string;
+ for (int i = 0; special[i].character.empty() == false; ++i)
+ ret = ret.replace_all_cs(special[i].character, special[i].replace);
+ 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();
+
+ int len = 0;
+ istag = false;
+
+ if (content[0] == '<')
+ {
+ len = content.find_first_of('>');
+ istag = true;
+ }
+ else if (content[0] != '>')
+ {
+ len = content.find_first_of('<');
+ }
+
+ if (len)
+ {
+ 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 = prev;
+ data = cur;
+ return !istag && !data.empty();
+ }
+
+ public:
+ bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override
+ {
+ Anope::string content = message.content, tname, data;
+ XMLRPCRequest request(reply);
+
+ while (GetData(content, tname, data))
+ {
+ Log(LOG_DEBUG) << "m_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 (unsigned i = 0; i < this->events.size(); ++i)
+ {
+ XMLRPCEvent *e = this->events[i];
+
+ if (!e->Run(this, client, request))
+ return false;
+ else if (!request.get_replies().empty())
+ {
+ this->Reply(request);
+ return true;
+ }
+ }
+
+ reply.error = HTTP_PAGE_NOT_FOUND;
+ reply.Write("Unrecognized query");
+ return true;
+ }
+
+ void Reply(XMLRPCRequest &request)
+ {
+ if (!request.id.empty())
+ request.reply("id", request.id);
+
+ Anope::string r = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<methodCall>\n<methodName>" + request.name + "</methodName>\n<params>\n<param>\n<value>\n<struct>\n";
+ for (std::map<Anope::string, Anope::string>::const_iterator it = request.get_replies().begin(); it != request.get_replies().end(); ++it)
+ r += "<member>\n<name>" + it->first + "</name>\n<value>\n<string>" + this->Sanitize(it->second) + "</string>\n</value>\n</member>\n";
+ r += "</struct>\n</value>\n</param>\n</params>\n</methodCall>";
+
+ request.r.Write(r);
+ }
+};
+
+class ModuleXMLRPC : public Module
+{
+ ServiceReference<HTTPProvider> httpref;
+ public:
+ MyXMLRPCServiceInterface xmlrpcinterface;
+
+ ModuleXMLRPC(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
+ httpref("HTTPProvider", "httpd/main"), xmlrpcinterface(this, "xmlrpc")
+ {
+ if (!httpref)
+ throw ModuleException("Unable to find http reference, is m_httpd loaded?");
+ httpref->RegisterPage(&xmlrpcinterface);
+
+ }
+
+ ~ModuleXMLRPC()
+ {
+ if (httpref)
+ httpref->UnregisterPage(&xmlrpcinterface);
+ }
+
+ void OnReload(Configuration::Conf *conf) anope_override
+ {
+ this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", conf->GetModule(this)->Get<const Anope::string>("server", "httpd/main"));
+ }
+};
+
+MODULE_INIT(ModuleXMLRPC)
+