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 | |
parent | 0c4701704689f0452cdaa540d744c231c48f3aa8 (diff) |
Made m_xmlrpc use m_httpd
-rw-r--r-- | data/modules.example.conf | 14 | ||||
-rw-r--r-- | docs/XMLRPC/xmlrpc.php | 29 | ||||
-rw-r--r-- | modules/extra/m_httpd.cpp | 54 | ||||
-rw-r--r-- | modules/extra/m_xmlrpc.cpp | 329 | ||||
-rw-r--r-- | modules/extra/m_xmlrpc_main.cpp | 159 | ||||
-rw-r--r-- | modules/extra/xmlrpc.h | 50 |
6 files changed, 240 insertions, 395 deletions
diff --git a/data/modules.example.conf b/data/modules.example.conf index 753f0f736..299dd1818 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -508,18 +508,8 @@ module { name = "m_statusupdate" } #module { name = "m_xmlrpc" } m_xmlrpc { - /* IP to listen on */ - bindip = "127.0.0.1" - /* Port to listen on */ - port = 26673 - /* Enable for IPv6 */ - ipv6 = no - /* If enabled, requires m_ssl to be loaded */ - ssl = no - /* IPs allowed to connect (separate with spaces), this should be secured. We also recommend you firewall this - * with an outside program to increase security. - */ - allowed = "127.0.0.0/24" + /* Web service to use. Requires m_httpd. */ + server = "httpd/main" } /* diff --git a/docs/XMLRPC/xmlrpc.php b/docs/XMLRPC/xmlrpc.php index 82cc4fa78..199289926 100644 --- a/docs/XMLRPC/xmlrpc.php +++ b/docs/XMLRPC/xmlrpc.php @@ -8,26 +8,11 @@ class AnopeXMLRPC { - private $Host, $Bind, $Port; + private $Host; - private $Socket; - - function __construct($Host, $Port, $Bind = NULL) + function __construct($Host) { $this->Host = $Host; - $this->Port = $Port; - $this->Bind = $Bind; - - $this->Socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - if ($Bind && socket_bind($this->Socket, $this->Bind) == false) - $his->Socket = false; - if (socket_connect($this->Socket, $this->Host, $this->Port) == false) - $this->Socket = false; - } - - function __destruct() - { - @socket_close($this->Socket); } /** Run an XMLRPC command. Name should be a query name and params an array of parameters, eg: @@ -40,10 +25,12 @@ class AnopeXMLRPC function RunXMLRPC($name, $params) { $xmlquery = xmlrpc_encode_request($name, $params); - socket_write($this->Socket, $xmlquery); + $context = stream_context_create(array("http" => array( + "method" => "POST", + "header" => "Content-Type: text/xml", + "content" => $xmlquery))); - $inbuf = socket_read($this->Socket, 4096); - $inbuf = substr($inbuf, strpos($inbuf, "\r\n\r\n") + 4); + $inbuf = file_get_contents($this->Host, false, $context); $response = xmlrpc_decode($inbuf); if (isset($response[0])) @@ -98,4 +85,6 @@ class AnopeXMLRPC } } +$anopexmlrpc = new AnopeXMLRPC("http://127.0.0.1:8080/xmlrpc"); + ?> diff --git a/modules/extra/m_httpd.cpp b/modules/extra/m_httpd.cpp index 4453cf826..f2704d77c 100644 --- a/modules/extra/m_httpd.cpp +++ b/modules/extra/m_httpd.cpp @@ -40,7 +40,7 @@ class MyHTTPClient : public HTTPClient { HTTPProvider *provider; HTTPMessage header; - bool header_done; + bool header_done, served; Anope::string page_name; dynamic_reference<HTTPPage> page; Anope::string ip; @@ -54,6 +54,10 @@ class MyHTTPClient : public HTTPClient void Serve() { + if (this->served) + return; + this->served = true; + if (!this->page) { this->SendError(HTTP_PAGE_NOT_FOUND, "Page not found"); @@ -78,6 +82,7 @@ class MyHTTPClient : public HTTPClient Log(LOG_DEBUG, "httpd") << "m_httpd: Serving page " << this->page_name << " to " << this->ip; HTTPReply reply; + reply.content_type = this->page->GetContentType(); if (this->page->OnRequest(this->provider, this->page_name, this, this->header, reply)) this->SendReply(&reply); @@ -86,7 +91,7 @@ class MyHTTPClient : public HTTPClient public: time_t created; - MyHTTPClient(HTTPProvider *l, int f, const sockaddrs &a) : Socket(f, l->IsIPv6()), HTTPClient(l, f, a), provider(l), header_done(false), ip(a.addr()), action(ACTION_NONE), created(Anope::CurTime) + MyHTTPClient(HTTPProvider *l, int f, const sockaddrs &a) : Socket(f, l->IsIPv6()), HTTPClient(l, f, a), provider(l), header_done(false), served(false), ip(a.addr()), action(ACTION_NONE), created(Anope::CurTime) { Log(LOG_DEBUG, "httpd") << "Accepted connection " << f << " from " << a.addr(); } @@ -176,23 +181,44 @@ class MyHTTPClient : public HTTPClient if (this->action == ACTION_POST) { - Log(LOG_DEBUG_2) << "HTTP POST from " << this->clientaddr.addr() << ": " << this->extrabuf; - - sepstream sep(this->extrabuf, '&'); - Anope::string token; - - while (sep.GetToken(token)) + unsigned content_length = 0; + if (this->header.headers.count("Content-Length")) + try + { + content_length = convertTo<unsigned>(this->header.headers["Content-Length"]); + } + catch (const ConvertException &) { } + + if (this->extrabuf.length() == content_length) { - size_t sz = token.find('='); - if (sz == Anope::string::npos || !sz || sz + 1 >= token.length()) - continue; - this->header.post_data[token.substr(0, sz)] = HTTPUtils::URLDecode(token.substr(sz + 1)); + Log(LOG_DEBUG_2) << "HTTP POST from " << this->clientaddr.addr() << ": " << this->extrabuf; + + sepstream sep(this->extrabuf, '&'); + Anope::string token; + + while (sep.GetToken(token)) + { + size_t sz = token.find('='); + if (sz == Anope::string::npos || !sz || sz + 1 >= token.length()) + continue; + this->header.post_data[token.substr(0, sz)] = HTTPUtils::URLDecode(token.substr(sz + 1)); + } + + this->header.content = this->extrabuf; + this->Serve(); } } - - this->Serve(); + else + this->Serve(); } } + else if (this->action == ACTION_POST) + { + if (buf.empty()) + this->Serve(); + else + this->header.content += buf; + } return true; } 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) diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index f3ed81d4d..4bd9c0ec6 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -6,70 +6,80 @@ static Module *me; class XMLRPCIdentifyRequest : public IdentifyRequest { XMLRPCRequest request; + HTTPReply repl; /* Request holds a reference to the HTTPReply, because we might exist long enough to invalidate it + we'll copy it here then reset the reference before we use it */ + dynamic_reference<HTTPClient> client; dynamic_reference<XMLRPCServiceInterface> xinterface; - dynamic_reference<XMLRPCClientSocket> source; public: - XMLRPCIdentifyRequest(Module *m, XMLRPCRequest& req, XMLRPCServiceInterface* iface, XMLRPCClientSocket* s, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), request(req), xinterface(iface), source(s) { } + XMLRPCIdentifyRequest(Module *m, XMLRPCRequest& req, HTTPClient *c, XMLRPCServiceInterface* iface, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), request(req), repl(request.r), client(c), xinterface(iface) { } void OnSuccess() anope_override { - if (!xinterface || !source) + if (!xinterface || !client) return; + request.r = this->repl; + request.reply("result", "Success"); request.reply("account", GetAccount()); - xinterface->Reply(source, &request); + xinterface->Reply(request); + client->SendReply(&request.r); } void OnFail() anope_override { - if (!xinterface || !source) + if (!xinterface || !client) return; + request.r = this->repl; + request.reply("error", "Invalid password"); - xinterface->Reply(source, &request); + xinterface->Reply(request); + client->SendReply(&request.r); } }; class MyXMLRPCEvent : public XMLRPCEvent { public: - void Run(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) anope_override + bool Run(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) anope_override { - if (request->name == "command") - this->DoCommand(iface, source, request); - else if (request->name == "checkAuthentication") - this->DoCheckAuthentication(iface, source, request); - else if (request->name == "stats") - this->DoStats(iface, source, request); - else if (request->name == "channel") - this->DoChannel(iface, source, request); - else if (request->name == "user") - this->DoUser(iface, source, request); - else if (request->name == "opers") - this->DoOperType(iface, source, request); + if (request.name == "command") + this->DoCommand(iface, client, request); + else if (request.name == "checkAuthentication") + return this->DoCheckAuthentication(iface, client, request); + else if (request.name == "stats") + this->DoStats(iface, client, request); + else if (request.name == "channel") + this->DoChannel(iface, client, request); + else if (request.name == "user") + this->DoUser(iface, client, request); + else if (request.name == "opers") + this->DoOperType(iface, client, request); + + return true; } private: - void DoCommand(XMLRPCServiceInterface *iface, XMLRPCClientSocket *, XMLRPCRequest *request) + void DoCommand(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) { - Anope::string service = request->data.size() > 0 ? request->data[0] : ""; - Anope::string user = request->data.size() > 1 ? request->data[1] : ""; - Anope::string command = request->data.size() > 2 ? request->data[2] : ""; + Anope::string service = request.data.size() > 0 ? request.data[0] : ""; + Anope::string user = request.data.size() > 1 ? request.data[1] : ""; + Anope::string command = request.data.size() > 2 ? request.data[2] : ""; if (service.empty() || user.empty() || command.empty()) - request->reply("error", "Invalid parameters"); + request.reply("error", "Invalid parameters"); else { BotInfo *bi = findbot(service); if (!bi) - request->reply("error", "Invalid service"); + request.reply("error", "Invalid service"); else { - request->reply("result", "Success"); + request.reply("result", "Success"); NickAlias *na = findnick(user); @@ -92,71 +102,74 @@ class MyXMLRPCEvent : public XMLRPCEvent RunCommand(source, command); if (!out.empty()) - request->reply("return", iface->Sanitize(out)); + request.reply("return", iface->Sanitize(out)); } } } - void DoCheckAuthentication(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) + bool DoCheckAuthentication(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) { - Anope::string username = request->data.size() > 0 ? request->data[0] : ""; - Anope::string password = request->data.size() > 1 ? request->data[1] : ""; + Anope::string username = request.data.size() > 0 ? request.data[0] : ""; + Anope::string password = request.data.size() > 1 ? request.data[1] : ""; if (username.empty() || password.empty()) - request->reply("error", "Invalid parameters"); + request.reply("error", "Invalid parameters"); else { - XMLRPCIdentifyRequest *req = new XMLRPCIdentifyRequest(me, *request, iface, source, username, password); + XMLRPCIdentifyRequest *req = new XMLRPCIdentifyRequest(me, request, client, iface, username, password); FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(NULL, req)); req->Dispatch(); + return false; } + + return true; } - void DoStats(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) + void DoStats(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) { - request->reply("uptime", stringify(Anope::CurTime - start_time)); - request->reply("uplinkname", Me->GetLinks().front()->GetName()); + request.reply("uptime", stringify(Anope::CurTime - start_time)); + request.reply("uplinkname", Me->GetLinks().front()->GetName()); { Anope::string buf; for (std::set<Anope::string>::iterator it = Capab.begin(); it != Capab.end(); ++it) buf += " " + *it; if (!buf.empty()) buf.erase(buf.begin()); - request->reply("uplinkcapab", buf); + request.reply("uplinkcapab", buf); } - request->reply("usercount", stringify(usercnt)); - request->reply("maxusercount", stringify(maxusercnt)); - request->reply("channelcount", stringify(ChannelList.size())); + request.reply("usercount", stringify(usercnt)); + request.reply("maxusercount", stringify(maxusercnt)); + request.reply("channelcount", stringify(ChannelList.size())); } - void DoChannel(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) + void DoChannel(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) { - if (request->data.empty()) + if (request.data.empty()) return; - Channel *c = findchan(request->data[0]); + Channel *c = findchan(request.data[0]); - request->reply("name", iface->Sanitize(c ? c->name : request->data[0])); + request.reply("name", iface->Sanitize(c ? c->name : request.data[0])); if (c) { - request->reply("bancount", stringify(c->HasMode(CMODE_BAN))); + request.reply("bancount", stringify(c->HasMode(CMODE_BAN))); int count = 0; std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = c->GetModeList(CMODE_BAN); for (; its.first != its.second; ++its.first) - request->reply("ban" + stringify(++count), iface->Sanitize(its.first->second)); + request.reply("ban" + stringify(++count), iface->Sanitize(its.first->second)); - request->reply("exceptcount", stringify(c->HasMode(CMODE_EXCEPT))); + request.reply("exceptcount", stringify(c->HasMode(CMODE_EXCEPT))); count = 0; its = c->GetModeList(CMODE_EXCEPT); for (; its.first != its.second; ++its.first) - request->reply("except" + stringify(++count), iface->Sanitize(its.first->second)); + request.reply("except" + stringify(++count), iface->Sanitize(its.first->second)); - request->reply("invitecount", stringify(c->HasMode(CMODE_INVITEOVERRIDE))); + request.reply("invitecount", stringify(c->HasMode(CMODE_INVITEOVERRIDE))); count = 0; its = c->GetModeList(CMODE_INVITEOVERRIDE); for (; its.first != its.second; ++its.first) - request->reply("invite" + stringify(++count), iface->Sanitize(its.first->second)); + request.reply("invite" + stringify(++count), iface->Sanitize(its.first->second)); Anope::string users; for (CUserList::const_iterator it = c->users.begin(); it != c->users.end(); ++it) @@ -167,47 +180,47 @@ class MyXMLRPCEvent : public XMLRPCEvent if (!users.empty()) { users.erase(users.length() - 1); - request->reply("users", iface->Sanitize(users)); + request.reply("users", iface->Sanitize(users)); } if (!c->topic.empty()) - request->reply("topic", iface->Sanitize(c->topic)); + request.reply("topic", iface->Sanitize(c->topic)); if (!c->topic_setter.empty()) - request->reply("topicsetter", iface->Sanitize(c->topic_setter)); + request.reply("topicsetter", iface->Sanitize(c->topic_setter)); - request->reply("topictime", stringify(c->topic_time)); - request->reply("topicts", stringify(c->topic_ts)); + request.reply("topictime", stringify(c->topic_time)); + request.reply("topicts", stringify(c->topic_ts)); } } - void DoUser(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) + void DoUser(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) { - if (request->data.empty()) + if (request.data.empty()) return; - User *u = finduser(request->data[0]); + User *u = finduser(request.data[0]); - request->reply("nick", iface->Sanitize(u ? u->nick : request->data[0])); + request.reply("nick", iface->Sanitize(u ? u->nick : request.data[0])); if (u) { - request->reply("ident", iface->Sanitize(u->GetIdent())); - request->reply("vident", iface->Sanitize(u->GetVIdent())); - request->reply("host", iface->Sanitize(u->host)); + request.reply("ident", iface->Sanitize(u->GetIdent())); + request.reply("vident", iface->Sanitize(u->GetVIdent())); + request.reply("host", iface->Sanitize(u->host)); if (!u->vhost.empty()) - request->reply("vhost", iface->Sanitize(u->vhost)); + request.reply("vhost", iface->Sanitize(u->vhost)); if (!u->chost.empty()) - request->reply("chost", iface->Sanitize(u->chost)); + request.reply("chost", iface->Sanitize(u->chost)); if (!u->ip.empty()) - request->reply("ip", u->ip); - request->reply("timestamp", stringify(u->timestamp)); - request->reply("signon", stringify(u->signon)); + request.reply("ip", u->ip); + request.reply("timestamp", stringify(u->timestamp)); + request.reply("signon", stringify(u->signon)); if (u->Account()) { - request->reply("account", iface->Sanitize(u->Account()->display)); + request.reply("account", iface->Sanitize(u->Account()->display)); if (u->Account()->o) - request->reply("opertype", iface->Sanitize(u->Account()->o->ot->GetName())); + request.reply("opertype", iface->Sanitize(u->Account()->o->ot->GetName())); } Anope::string channels; @@ -219,12 +232,12 @@ class MyXMLRPCEvent : public XMLRPCEvent if (!channels.empty()) { channels.erase(channels.length() - 1); - request->reply("channels", channels); + request.reply("channels", channels); } } } - void DoOperType(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) + void DoOperType(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) { for (std::list<OperType *>::const_iterator it = Config->MyOperTypes.begin(), it_end = Config->MyOperTypes.end(); it != it_end; ++it) { @@ -233,7 +246,7 @@ class MyXMLRPCEvent : public XMLRPCEvent perms += " " + *it2; for (std::list<Anope::string>::const_iterator it2 = (*it)->GetCommands().begin(), it2_end = (*it)->GetCommands().end(); it2 != it2_end; ++it2) perms += " " + *it2; - request->reply((*it)->GetName(), perms); + request.reply((*it)->GetName(), perms); } } }; @@ -247,11 +260,11 @@ class ModuleXMLRPCMain : public Module public: ModuleXMLRPCMain(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), xmlrpc("XMLRPCServiceInterface", "xmlrpc") { + me = this; + if (!xmlrpc) throw ModuleException("Unable to find xmlrpc reference, is m_xmlrpc loaded?"); - me = this; - xmlrpc->Register(&stats); } diff --git a/modules/extra/xmlrpc.h b/modules/extra/xmlrpc.h index bc3ba893d..13097f4be 100644 --- a/modules/extra/xmlrpc.h +++ b/modules/extra/xmlrpc.h @@ -1,40 +1,4 @@ - -class XMLRPCClientSocket; -class XMLRPCListenSocket; -class XMLRPCServiceInterface; - -class XMLRPCClientSocket : public ClientSocket, public BufferedSocket, public Base -{ - protected: - Anope::string query; - - public: - XMLRPCClientSocket(ListenSocket *ls, const sockaddrs &addr) : ClientSocket(ls, addr), BufferedSocket() { } - - virtual ~XMLRPCClientSocket() { } - - virtual bool Read(const Anope::string &message) anope_override = 0; - - virtual bool GetData(Anope::string &tag, Anope::string &data) = 0; - - virtual void HandleMessage() = 0; -}; - -class XMLRPCListenSocket : public ListenSocket -{ - protected: - std::vector<Anope::string> allowed; - - public: - Anope::string username; - Anope::string password; - - XMLRPCListenSocket(const Anope::string &bindip, int port, bool ipv6, const Anope::string &u, const Anope::string &p, const std::vector<Anope::string> &a) : ListenSocket(bindip, port, ipv6), allowed(a), username(u), password(p) { } - - virtual ~XMLRPCListenSocket() { } - - virtual ClientSocket *OnAccept(int fd, const sockaddrs &addr) anope_override = 0; -}; +#include "httpd.h" class XMLRPCRequest { @@ -44,15 +8,19 @@ class XMLRPCRequest Anope::string name; Anope::string id; std::deque<Anope::string> data; + HTTPReply& r; + XMLRPCRequest(HTTPReply &_r) : r(_r) { } inline void reply(const Anope::string &dname, const Anope::string &ddata) { this->replies.insert(std::make_pair(dname, ddata)); } inline const std::map<Anope::string, Anope::string> &get_replies() { return this->replies; } }; +class XMLRPCServiceInterface; + class XMLRPCEvent { public: - virtual void Run(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) = 0; + virtual bool Run(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) = 0; }; class XMLRPCServiceInterface : public Service @@ -64,10 +32,8 @@ class XMLRPCServiceInterface : public Service virtual void Unregister(XMLRPCEvent *event) = 0; - virtual void Reply(XMLRPCClientSocket *source, XMLRPCRequest *request) = 0; - virtual Anope::string Sanitize(const Anope::string &string) = 0; - - virtual void RunXMLRPC(XMLRPCClientSocket *source, XMLRPCRequest *request) = 0; + + virtual void Reply(XMLRPCRequest &request) = 0; }; |