summaryrefslogtreecommitdiff
path: root/modules/extra/m_xmlrpc.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-11-03 22:04:19 -0400
committerAdam <Adam@anope.org>2012-11-03 22:04:19 -0400
commitfb56b3a53f0dc54cc36af5c9caf189bb71a3d5e9 (patch)
tree8b6f52f844d5f9d93e072d4e5b8527f6d2c04fc7 /modules/extra/m_xmlrpc.cpp
parent0c4701704689f0452cdaa540d744c231c48f3aa8 (diff)
Made m_xmlrpc use m_httpd
Diffstat (limited to 'modules/extra/m_xmlrpc.cpp')
-rw-r--r--modules/extra/m_xmlrpc.cpp329
1 files changed, 95 insertions, 234 deletions
diff --git a/modules/extra/m_xmlrpc.cpp b/modules/extra/m_xmlrpc.cpp
index ad1c2756b..2ff648812 100644
--- a/modules/extra/m_xmlrpc.cpp
+++ b/modules/extra/m_xmlrpc.cpp
@@ -1,41 +1,62 @@
#include "module.h"
-#include "ssl.h"
#include "xmlrpc.h"
+#include "httpd.h"
-std::vector<XMLRPCListenSocket *> listen_sockets;
-
-class MyXMLRPCClientSocket : public XMLRPCClientSocket
+class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
{
- /* Used to skip the (optional) HTTP header, which we really don't care about */
- bool in_query;
+ std::deque<XMLRPCEvent *> events;
+
public:
- MyXMLRPCClientSocket(XMLRPCListenSocket *ls, int fd, const sockaddrs &addr) : Socket(fd, ls->IsIPv6()), XMLRPCClientSocket(ls, addr), in_query(false)
+ MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname) : XMLRPCServiceInterface(creator, sname), HTTPPage("/xmlrpc", "text/xml") { }
+
+ void Register(XMLRPCEvent *event)
{
+ this->events.push_back(event);
}
- bool Read(const Anope::string &message) anope_override
+ void Unregister(XMLRPCEvent *event)
{
- if (message.find("xml version") != Anope::string::npos)
- this->in_query = true;
- else if (!this->in_query)
- return true;
+ std::deque<XMLRPCEvent *>::iterator it = std::find(this->events.begin(), this->events.end(), event);
- this->query += message;
- Log(LOG_DEBUG) << "m_xmlrpc: " << message;
+ if (it != this->events.end())
+ this->events.erase(it);
+ }
- if (message.find("</methodCall>") != Anope::string::npos)
+ Anope::string Sanitize(const Anope::string &string) anope_override
+ {
+ static struct special_chars
{
- Log(LOG_DEBUG) << "m_xmlrpc: Processing message";
- this->HandleMessage();
+ 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("", "")
+ };
- return true;
+ 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;
}
- bool GetData(Anope::string &tag, Anope::string &data)
+ private:
+ static bool GetData(Anope::string &content, Anope::string &tag, Anope::string &data)
{
- if (this->query.empty())
+ if (content.empty())
return false;
Anope::string prev, cur;
@@ -49,282 +70,122 @@ class MyXMLRPCClientSocket : public XMLRPCClientSocket
int len = 0;
istag = false;
- if (this->query[0] == '<')
+ if (content[0] == '<')
{
- len = this->query.find_first_of('>');
+ len = content.find_first_of('>');
istag = true;
}
- else if (this->query[0] != '>')
+ else if (content[0] != '>')
{
- len = this->query.find_first_of('<');
+ len = content.find_first_of('<');
}
if (len)
{
if (istag)
{
- cur = this->query.substr(1, len - 1);
- this->query.erase(0, len + 1);
- while (!this->query.empty() && this->query[0] == ' ')
- this->query.erase(this->query.begin());
+ cur = content.substr(1, len - 1);
+ content.erase(0, len + 1);
+ while (!content.empty() && content[0] == ' ')
+ content.erase(content.begin());
}
else
{
- cur = this->query.substr(0,len);
- this->query.erase(0, len);
+ cur = content.substr(0,len);
+ content.erase(0, len);
}
}
}
- while (istag && !this->query.empty());
+ while (istag && !content.empty());
tag = prev;
data = cur;
return !istag && !data.empty();
}
-
- void HandleMessage();
-};
-class MyXMLRPCListenSocket : public XMLRPCListenSocket
-{
public:
- MyXMLRPCListenSocket(const Anope::string &bindip, int port, bool ipv6, const Anope::string &u, const Anope::string &p, const std::vector<Anope::string> &a) : Socket(-1, ipv6), XMLRPCListenSocket(bindip, port, ipv6, u, p, a)
- {
- listen_sockets.push_back(this);
- }
-
- ~MyXMLRPCListenSocket()
- {
- std::vector<XMLRPCListenSocket *>::iterator it = std::find(listen_sockets.begin(), listen_sockets.end(), this);
- if (it != listen_sockets.end())
- listen_sockets.erase(it);
- }
-
- ClientSocket *OnAccept(int fd, const sockaddrs &addr) anope_override
+ bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override
{
- MyXMLRPCClientSocket *socket = new MyXMLRPCClientSocket(this, fd, addr);
+ Anope::string content = message.content, tname, data;
+ XMLRPCRequest request(reply);
- socket->SetFlag(SF_DEAD);
- for (unsigned i = 0, j = this->allowed.size(); i < j; ++i)
+ while (GetData(content, tname, data))
{
- try
+ Log(LOG_DEBUG) << "m_xmlrpc: Tag name: " << tname << ", data: " << data;
+ if (tname == "methodName")
+ request.name = data;
+ else if (tname == "name" && data == "id")
{
- cidr cidr_mask(this->allowed[i]);
- if (cidr_mask.match(socket->clientaddr))
- {
- Log() << "m_xmlrpc: Accepted connection " << fd << " from " << addr.addr();
- socket->UnsetFlag(SF_DEAD);
- break;
- }
- }
- catch (const SocketException &ex)
- {
- Log() << "m_xmlrpc: Error checking incoming connection against mask " << this->allowed[i] << ": " << ex.GetReason();
+ GetData(content, tname, data);
+ request.id = data;
}
+ else if (tname == "string")
+ request.data.push_back(data);
}
- if (socket->HasFlag(SF_DEAD))
- Log() << "m_xmlrpc: Dropping disallowed connection " << fd << " from " << addr.addr();
-
- return socket;
- }
-};
-
-class MyXMLRPCServiceInterface : public XMLRPCServiceInterface
-{
- std::deque<XMLRPCEvent *> events;
-
- public:
- MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname) : XMLRPCServiceInterface(creator, sname) { }
-
- 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);
- }
-
- void Reply(XMLRPCClientSocket *source, XMLRPCRequest *request) anope_override
- {
- if (!request->id.empty())
- request->reply("id", request->id);
-
- Anope::string reply = "<?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)
- {
- reply += "<member>\n<name>" + it->first + "</name>\n<value>\n<string>" + this->Sanitize(it->second) + "</string>\n</value>\n</member>\n";
- }
- reply += "</struct>\n</value>\n</param>\n</params>\n</methodCall>";
-
- source->Write("HTTP/1.1 200 OK");
- source->Write("Connection: close");
- source->Write("Content-Type: text/xml");
- source->Write("Content-Length: " + stringify(reply.length()));
- source->Write("Server: Anope IRC Services version " + Anope::VersionShort());
- source->Write("");
-
- source->Write(reply);
-
- Log(LOG_DEBUG) << reply;
- }
-
- Anope::string Sanitize(const Anope::string &string) anope_override
- {
- static struct special_chars
+ for (unsigned i = 0; i < this->events.size(); ++i)
{
- Anope::string character;
- Anope::string replace;
+ XMLRPCEvent *e = this->events[i];
- special_chars(const Anope::string &c, const Anope::string &r) : character(c), replace(r) { }
+ if (!e->Run(this, client, request))
+ return false;
+ else if (!request.get_replies().empty())
+ {
+ this->Reply(request);
+ return true;
+ }
}
- 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("", "")
- };
- 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;
+ reply.error = HTTP_PAGE_NOT_FOUND;
+ reply.Write("Unrecognized query");
+ return true;
}
- void RunXMLRPC(XMLRPCClientSocket *source, XMLRPCRequest *request) anope_override
+ void Reply(XMLRPCRequest &request)
{
- for (unsigned i = 0; i < this->events.size(); ++i)
- {
- XMLRPCEvent *e = this->events[i];
+ if (!request.id.empty())
+ request.reply("id", request.id);
- e->Run(this, source, request);
- if (!request->get_replies().empty())
- this->Reply(source, request);
- }
+ 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;
-static ModuleXMLRPC *me;
class ModuleXMLRPC : public Module
{
- service_reference<SSLService> sslref;
-
+ service_reference<HTTPProvider> httpref;
public:
MyXMLRPCServiceInterface xmlrpcinterface;
- ModuleXMLRPC(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), sslref("SSLService", "ssl"), xmlrpcinterface(this, "xmlrpc")
+ ModuleXMLRPC(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), xmlrpcinterface(this, "xmlrpc")
{
- me = this;
+ OnReload();
+ if (!httpref)
+ throw ModuleException("Unable to find http reference, is m_httpd loaded?");
+
+ httpref->RegisterPage(&xmlrpcinterface);
Implementation i[] = { I_OnReload };
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
-
- OnReload();
}
~ModuleXMLRPC()
{
- /* Clean up our sockets and our listening sockets */
- for (std::map<int, Socket *>::const_iterator it = SocketEngine::Sockets.begin(), it_end = SocketEngine::Sockets.end(); it != it_end;)
- {
- Socket *s = it->second;
- ++it;
-
- ClientSocket *cs = dynamic_cast<ClientSocket *>(s);
- if (cs != NULL)
- {
- for (unsigned i = 0; i < listen_sockets.size(); ++i)
- if (cs->LS == listen_sockets[i])
- {
- delete cs;
- break;
- }
- }
- }
-
- for (unsigned i = 0; i < listen_sockets.size(); ++i)
- delete listen_sockets[i];
- listen_sockets.clear();
+ if (httpref)
+ httpref->UnregisterPage(&xmlrpcinterface);
}
void OnReload() anope_override
{
ConfigReader config;
-
- for (unsigned i = 0; i < listen_sockets.size(); ++i)
- delete listen_sockets[i];
- listen_sockets.clear();
-
- for (int i = 0; i < config.Enumerate("m_xmlrpc"); ++i)
- {
- Anope::string bindip = config.ReadValue("m_xmlrpc", "bindip", "0.0.0.0", i);
- int port = config.ReadInteger("m_xmlrpc", "port", 0, i);
- bool ipv6 = config.ReadFlag("m_xmlrpc", "ipv6", "no", i);
- bool ssl = config.ReadFlag("m_xmlrpc", "ssl", "no", i);
- Anope::string allowed = config.ReadValue("m_xmlrpc", "allowed", "127.0.0.1", i);
- Anope::string username = config.ReadValue("m_xmlrpc", "username", "", i);
- Anope::string password = config.ReadValue("m_xmlrpc", "password", "", i);
- std::vector<Anope::string> allowed_vector = BuildStringVector(allowed, ' ');
-
- if (bindip.empty() || port < 1)
- continue;
-
- if (ssl && !sslref)
- {
- Log(this) << "Could not enable SSL, is m_ssl loaded?";
- ssl = false;
- }
-
- try
- {
- MyXMLRPCListenSocket *xmls = new MyXMLRPCListenSocket(bindip, port, ipv6, username, password, allowed_vector);
- if (ssl)
- sslref->Init(xmls);
- }
- catch (const SocketException &ex)
- {
- Log(this) << ex.GetReason();
- }
- }
+ httpref = service_reference<HTTPProvider>("HTTPProvider", "httpd/main");
}
};
-void MyXMLRPCClientSocket::HandleMessage()
-{
- Anope::string name, data;
- XMLRPCRequest request;
-
- while (this->GetData(name, data))
- {
- Log(LOG_DEBUG) << "m_xmlrpc: Tag name: " << name << ", data: " << data;
- if (name == "methodName")
- request.name = data;
- else if (name == "name" && data == "id")
- {
- this->GetData(name, data);
- request.id = data;
- }
- else if (name == "string")
- request.data.push_back(data);
- }
-
- me->xmlrpcinterface.RunXMLRPC(this, &request);
-}
-
MODULE_INIT(ModuleXMLRPC)