diff options
| author | Adam <Adam@anope.org> | 2012-11-03 22:04:19 -0400 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2012-11-03 22:04:19 -0400 |
| commit | fb56b3a53f0dc54cc36af5c9caf189bb71a3d5e9 (patch) | |
| tree | 8b6f52f844d5f9d93e072d4e5b8527f6d2c04fc7 /modules/extra/m_xmlrpc.cpp | |
| parent | 0c4701704689f0452cdaa540d744c231c48f3aa8 (diff) | |
Made m_xmlrpc use m_httpd
Diffstat (limited to 'modules/extra/m_xmlrpc.cpp')
| -rw-r--r-- | modules/extra/m_xmlrpc.cpp | 329 |
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("&", "&"), + special_chars("\"", """), + special_chars("<", "<"), + special_chars(">", "&qt;"), + special_chars("'", "'"), + special_chars("\n", "
"), + 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("&", "&"), - special_chars("\"", """), - special_chars("<", "<"), - special_chars(">", "&qt;"), - special_chars("'", "'"), - special_chars("\n", "
"), - 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) |
