Anope IRC Services  Version 2.0
m_xmlrpc.cpp
Go to the documentation of this file.
1 
2 #include "module.h"
3 #include "modules/xmlrpc.h"
4 #include "modules/httpd.h"
5 
6 static struct special_chars
7 {
10 
11  special_chars(const Anope::string &c, const Anope::string &r) : character(c), replace(r) { }
12 }
13 special[] = {
14  special_chars("&", "&"),
15  special_chars("\"", """),
16  special_chars("<", "&lt;"),
17  special_chars(">", "&qt;"),
18  special_chars("'", "&#39;"),
19  special_chars("\n", "&#xA;"),
20  special_chars("\002", ""), // bold
21  special_chars("\003", ""), // color
22  special_chars("\035", ""), // italics
23  special_chars("\037", ""), // underline
24  special_chars("\026", ""), // reverses
25  special_chars("", "")
26 };
27 
29 {
30  std::deque<XMLRPCEvent *> events;
31 
32  public:
33  MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname) : XMLRPCServiceInterface(creator, sname), HTTPPage("/xmlrpc", "text/xml") { }
34 
35  void Register(XMLRPCEvent *event)
36  {
37  this->events.push_back(event);
38  }
39 
40  void Unregister(XMLRPCEvent *event)
41  {
42  std::deque<XMLRPCEvent *>::iterator it = std::find(this->events.begin(), this->events.end(), event);
43 
44  if (it != this->events.end())
45  this->events.erase(it);
46  }
47 
49  {
50  Anope::string ret = string;
51  for (int i = 0; special[i].character.empty() == false; ++i)
53  return ret;
54  }
55 
56  private:
57  static bool GetData(Anope::string &content, Anope::string &tag, Anope::string &data)
58  {
59  if (content.empty())
60  return false;
61 
62  Anope::string prev, cur;
63  bool istag;
64 
65  do
66  {
67  prev = cur;
68  cur.clear();
69 
70  int len = 0;
71  istag = false;
72 
73  if (content[0] == '<')
74  {
75  len = content.find_first_of('>');
76  istag = true;
77  }
78  else if (content[0] != '>')
79  {
80  len = content.find_first_of('<');
81  }
82 
83  if (len)
84  {
85  if (istag)
86  {
87  cur = content.substr(1, len - 1);
88  content.erase(0, len + 1);
89  while (!content.empty() && content[0] == ' ')
90  content.erase(content.begin());
91  }
92  else
93  {
94  cur = content.substr(0,len);
95  content.erase(0, len);
96  }
97  }
98  }
99  while (istag && !content.empty());
100 
101  tag = prev;
102  data = cur;
103  return !istag && !data.empty();
104  }
105 
106  public:
107  bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override
108  {
109  Anope::string content = message.content, tname, data;
110  XMLRPCRequest request(reply);
111 
112  while (GetData(content, tname, data))
113  {
114  Log(LOG_DEBUG) << "m_xmlrpc: Tag name: " << tname << ", data: " << data;
115  if (tname == "methodName")
116  request.name = data;
117  else if (tname == "name" && data == "id")
118  {
119  GetData(content, tname, data);
120  request.id = data;
121  }
122  else if (tname == "string")
123  request.data.push_back(data);
124  }
125 
126  for (unsigned i = 0; i < this->events.size(); ++i)
127  {
128  XMLRPCEvent *e = this->events[i];
129 
130  if (!e->Run(this, client, request))
131  return false;
132  else if (!request.get_replies().empty())
133  {
134  this->Reply(request);
135  return true;
136  }
137  }
138 
139  reply.error = HTTP_PAGE_NOT_FOUND;
140  reply.Write("Unrecognized query");
141  return true;
142  }
143 
144  void Reply(XMLRPCRequest &request)
145  {
146  if (!request.id.empty())
147  request.reply("id", request.id);
148 
149  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";
150  for (std::map<Anope::string, Anope::string>::const_iterator it = request.get_replies().begin(); it != request.get_replies().end(); ++it)
151  r += "<member>\n<name>" + it->first + "</name>\n<value>\n<string>" + this->Sanitize(it->second) + "</string>\n</value>\n</member>\n";
152  r += "</struct>\n</value>\n</param>\n</params>\n</methodCall>";
153 
154  request.r.Write(r);
155  }
156 };
157 
158 class ModuleXMLRPC : public Module
159 {
161  public:
163 
164  ModuleXMLRPC(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
165  httpref("HTTPProvider", "httpd/main"), xmlrpcinterface(this, "xmlrpc")
166  {
167  if (!httpref)
168  throw ModuleException("Unable to find http reference, is m_httpd loaded?");
169  httpref->RegisterPage(&xmlrpcinterface);
170 
171  }
172 
174  {
175  if (httpref)
176  httpref->UnregisterPage(&xmlrpcinterface);
177  }
178 
180  {
181  this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", conf->GetModule(this)->Get<const Anope::string>("server", "httpd/main"));
182  }
183 };
184 
186 
Anope::string replace
Definition: m_xmlrpc.cpp:9
const std::map< Anope::string, Anope::string > & get_replies()
Definition: xmlrpc.h:15
MyXMLRPCServiceInterface xmlrpcinterface
Definition: m_xmlrpc.cpp:162
void clear()
Definition: anope.h:187
virtual bool Run(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request)=0
std::deque< XMLRPCEvent * > events
Definition: m_xmlrpc.cpp:30
void Unregister(XMLRPCEvent *event)
Definition: m_xmlrpc.cpp:40
void OnReload(Configuration::Conf *conf) anope_override
Definition: m_xmlrpc.cpp:179
ModuleXMLRPC(const Anope::string &modname, const Anope::string &creator)
Definition: m_xmlrpc.cpp:164
MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname)
Definition: m_xmlrpc.cpp:33
size_type find_first_of(const string &_str, size_type pos=0) const
Definition: anope.h:202
iterator erase(const iterator &i)
Definition: anope.h:155
string substr(size_type pos=0, size_type n=npos) const
Definition: anope.h:277
Anope::string character
Definition: m_xmlrpc.cpp:8
void reply(const Anope::string &dname, const Anope::string &ddata)
Definition: xmlrpc.h:14
string replace_all_cs(const string &_orig, const string &_repl) const
Definition: anope.h:229
Anope::string name
Definition: xmlrpc.h:8
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
void Reply(XMLRPCRequest &request)
Definition: m_xmlrpc.cpp:144
std::basic_string< char, ci_char_traits, std::allocator< char > > string
Definition: hashcomp.h:133
#define MODULE_INIT(x)
Definition: modules.h:45
Anope::string id
Definition: xmlrpc.h:9
static bool GetData(Anope::string &content, Anope::string &tag, Anope::string &data)
Definition: m_xmlrpc.cpp:57
void Write(const Anope::string &message)
Definition: httpd.h:62
HTTPReply & r
Definition: xmlrpc.h:11
Anope::string Sanitize(const Anope::string &string) anope_override
Definition: m_xmlrpc.cpp:48
std::deque< Anope::string > data
Definition: xmlrpc.h:10
Definition: logger.h:53
Definition: httpd.h:88
bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override
Definition: m_xmlrpc.cpp:107
void Register(XMLRPCEvent *event)
Definition: m_xmlrpc.cpp:35
iterator begin()
Definition: anope.h:282
ServiceReference< HTTPProvider > httpref
Definition: m_xmlrpc.cpp:160
static struct special_chars special[]
Definition: modules.h:163
special_chars(const Anope::string &c, const Anope::string &r)
Definition: m_xmlrpc.cpp:11