summaryrefslogtreecommitdiff
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
parent0c4701704689f0452cdaa540d744c231c48f3aa8 (diff)
Made m_xmlrpc use m_httpd
-rw-r--r--data/modules.example.conf14
-rw-r--r--docs/XMLRPC/xmlrpc.php29
-rw-r--r--modules/extra/m_httpd.cpp54
-rw-r--r--modules/extra/m_xmlrpc.cpp329
-rw-r--r--modules/extra/m_xmlrpc_main.cpp159
-rw-r--r--modules/extra/xmlrpc.h50
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("&", "&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)
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;
};