summaryrefslogtreecommitdiff
path: root/src/modules/m_rpc_json.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/m_rpc_json.cpp')
-rw-r--r--src/modules/m_rpc_json.cpp368
1 files changed, 0 insertions, 368 deletions
diff --git a/src/modules/m_rpc_json.cpp b/src/modules/m_rpc_json.cpp
deleted file mode 100644
index e57bb77b5..000000000
--- a/src/modules/m_rpc_json.cpp
+++ /dev/null
@@ -1,368 +0,0 @@
-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
- *
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
- *
- * This program is free but copyrighted software; see
- * the file COPYING for details.
- *
- * ---------------------------------------------------
- */
-
-#include "inspircd.h"
-#include "httpd.h"
-#include "rpc.h"
-#include <exception>
-
-/* $ModDesc: Encode and decode JSON-RPC requests for modules */
-/* $ModDep: httpd.h rpc.h */
-
-class JsonException : public std::exception
-{
- private:
- std::string _what;
- public:
- JsonException(const std::string &swhat)
- : _what(swhat)
- {
- }
-
- virtual ~JsonException() throw() { }
-
- virtual const char *what() const throw()
- {
- return _what.c_str();
- }
-};
-
-class ModuleRpcJson : public Module
-{
- private:
-
- public:
- ModuleRpcJson()
- {
- ServerInstance->Modules->PublishInterface("RPC", this);
- Implementation eventlist[] = { I_OnEvent };
- ServerInstance->Modules->Attach(eventlist, this, 1);
- }
-
- virtual ~ModuleRpcJson()
- {
- ServerInstance->Modules->UnpublishInterface("RPC", this);
- }
-
- virtual Version GetVersion()
- {
- return Version("Encode and decode JSON-RPC requests for modules", VF_SERVICEPROVIDER | VF_VENDOR, API_VERSION);
- }
-
-
- virtual void OnEvent(Event *event)
- {
- if (event->GetEventID() == "httpd_url")
- {
- HTTPRequest *req = (HTTPRequest*) event->GetData();
-
- if ((req->GetURI() == "/rpc/json") || (req->GetURI() == "/rpc/json/"))
- {
- std::stringstream data;
-
- RPCValue *reqobj = NULL;
-
- try
- {
- reqobj = this->JSONParse(req->GetPostData());
-
- if (!reqobj || (reqobj->GetType() != RPCObject))
- throw JsonException("RPC requests must be in the form of a single object");
-
- RPCValue *method = reqobj->GetObject("method");
- if (!method || method->GetType() != RPCString)
- throw JsonException("RPC requests must have a 'method' string field");
-
- RPCValue *params = reqobj->GetObject("params");
- if (!params || params->GetType() != RPCArray)
- throw JsonException("RPC requests must have a 'params' array field");
-
- RPCRequest modreq("json", method->GetString(), params);
- Event mev((char*) &modreq, this, "RPCMethod");
- mev.Send();
-
- if (!modreq.claimed)
- throw JsonException("Unrecognized method");
-
- if (!modreq.error.empty())
- {
- data << "{\"result\":null,\"error\":\"" << modreq.error << "\"";
- }
- else
- {
- data << "{\"result\":";
- this->JSONSerialize(modreq.result, data);
- data << ",\"error\":null";
- }
-
- if (reqobj->GetObject("id"))
- {
- data << ",\"id\":";
- this->JSONSerialize(reqobj->GetObject("id"), data);
- }
- data << "}";
-
- delete reqobj;
- reqobj = NULL;
- }
- catch (std::exception &e)
- {
- if (reqobj)
- delete reqobj;
- data << "{\"result\":null,\"error\":\"" << e.what() << "\"}";
- }
-
- HTTPDocument response(req->sock, &data, 200);
- response.headers.SetHeader("X-Powered-By", "m_rpc_json.so");
- response.headers.SetHeader("Content-Type", "application/json");
- response.headers.SetHeader("Connection", "Keep-Alive");
-
- Request rreq((char*) &response, (Module*) this, event->GetSource());
- rreq.Send();
- }
- }
- }
-
- void AttachToParent(RPCValue *parent, RPCValue *child, const std::string &key = "")
- {
- if (!parent || !child)
- return;
-
- if (parent->GetType() == RPCArray)
- parent->ArrayAdd(child);
- else if (parent->GetType() == RPCObject)
- parent->ObjectAdd(key, child);
- else
- throw JsonException("Cannot add a value to a non-container");
- }
-
- void AttachToParentReset(RPCValue *parent, RPCValue *&child, std::string &key)
- {
- AttachToParent(parent, child, key);
- child = NULL;
- key.clear();
- }
-
- RPCValue *JSONParse(const std::string &data)
- {
- bool pisobject = false;
- bool instring = false;
- std::string stmp;
- std::string vkey;
- std::string pvkey;
- RPCValue *aparent = NULL;
- RPCValue *value = NULL;
-
- for (std::string::const_iterator i = data.begin(); i != data.end(); i++)
- {
- if (instring)
- {
- // TODO escape sequences
- if (*i == '"')
- {
- instring = false;
-
- if (pisobject && vkey.empty())
- vkey = stmp;
- else
- value = new RPCValue(stmp);
-
- stmp.clear();
- }
- else
- stmp += *i;
-
- continue;
- }
-
- if ((*i == ' ') || (*i == '\t') || (*i == '\r') || (*i == '\n'))
- continue;
-
- if (*i == '{')
- {
- // Begin object
- if ((value) || (pisobject && vkey.empty()))
- throw JsonException("Unexpected begin object token ('{')");
-
- RPCValue *nobj = new RPCValue(RPCObject, aparent);
- aparent = nobj;
- pvkey = vkey;
- vkey.clear();
- pisobject = true;
- }
- else if (*i == '}')
- {
- // End object
- if ((!aparent) || (!pisobject) || (!vkey.empty() && !value))
- throw JsonException("Unexpected end object token ('}')");
-
- // End value
- if (value)
- AttachToParentReset(aparent, value, vkey);
-
- if (!aparent->parent)
- return aparent;
-
- value = aparent;
- aparent = aparent->parent;
- vkey = pvkey;
- pvkey.clear();
- pisobject = (aparent->GetType() == RPCObject);
- }
- else if (*i == '"')
- {
- // Begin string
- if (value)
- throw JsonException("Unexpected begin string token ('\"')");
-
- instring = true;
- }
- else if (*i == ':')
- {
- if ((!aparent) || (!pisobject) || (vkey.empty()) || (value))
- throw JsonException("Unexpected object value token (':')");
- }
- else if (*i == ',')
- {
- if ((!aparent) || (!value) || ((pisobject) && (vkey.empty())))
- throw JsonException("Unexpected value seperator token (',')");
-
- AttachToParentReset(aparent, value, vkey);
- }
- else if (*i == '[')
- {
- // Begin array
- if ((value) || (pisobject && vkey.empty()))
- throw JsonException("Unexpected begin array token ('[')");
-
- RPCValue *nar = new RPCValue(RPCArray, aparent);
- aparent = nar;
- pvkey = vkey;
- vkey.clear();
- pisobject = false;
- }
- else if (*i == ']')
- {
- // End array (also an end value delimiter)
- if (!aparent || pisobject)
- throw JsonException("Unexpected end array token (']')");
-
- if (value)
- AttachToParentReset(aparent, value, vkey);
-
- if (!aparent->parent)
- return aparent;
-
- value = aparent;
- aparent = aparent->parent;
- vkey = pvkey;
- pvkey.clear();
- pisobject = (aparent->GetType() == RPCObject);
- }
- else
- {
- // Numbers, false, null, and true fall under this heading.
- if ((*i == 't') && ((i + 3) < data.end()) && (*(i + 1) == 'r') && (*(i + 2) == 'u') && (*(i + 3) == 'e'))
- {
- value = new RPCValue(true);
- i += 3;
- }
- else if ((*i == 'f') && ((i + 4) < data.end()) && (*(i + 1) == 'a') && (*(i + 2) == 'l') && (*(i + 3) == 's') && (*(i + 4) == 'e'))
- {
- value = new RPCValue(false);
- i += 4;
- }
- else if ((*i == 'n') && ((i + 3) < data.end()) && (*(i + 1) == 'u') && (*(i + 2) == 'l') && (*(i + 3) == 'l'))
- {
- value = new RPCValue();
- i += 3;
- }
- else if ((*i == '-') || (*i == '+') || (*i == '.') || ((*i >= '0') && (*i <= '9')))
- {
- std::string ds = std::string(i, data.end());
- char *eds = NULL;
-
- errno = 0;
- double v = strtod(ds.c_str(), &eds);
-
- if (errno != 0)
- throw JsonException("Error parsing numeric value");
-
- value = new RPCValue(v);
-
- i += eds - ds.c_str() - 1;
- }
- else
- throw JsonException("Unknown data in value portion");
- }
- }
-
- if (instring)
- throw JsonException("Unterminated string");
-
- if (aparent && pisobject)
- throw JsonException("Unterminated object");
- else if (aparent && !pisobject)
- throw JsonException("Unterminated array");
-
- if (value)
- return value;
- else
- throw JsonException("No JSON data found");
- }
-
- void JSONSerialize(RPCValue *value, std::stringstream &re)
- {
- int ac;
- switch (value->GetType())
- {
- case RPCNull:
- re << "null";
- break;
- case RPCBoolean:
- re << ((value->GetBool()) ? "true" : "false");
- break;
- case RPCInteger:
- re << value->GetInt();
- break;
- case RPCString:
- re << "\"" << value->GetString() << "\"";
- break;
- case RPCArray:
- re << "[";
- ac = value->ArraySize();
- for (int i = 0; i < ac; i++)
- {
- this->JSONSerialize(value->GetArray(i), re);
- if (i != (ac - 1))
- re << ",";
- }
- re << "]";
- break;
- case RPCObject:
- re << "{";
- std::pair<RPCObjectContainer::iterator,RPCObjectContainer::iterator> its = value->GetObjectIterator();
- while (its.first != its.second)
- {
- re << "\"" << its.first->first << "\":";
- this->JSONSerialize(its.first->second, re);
- if (++its.first != its.second)
- re << ",";
- }
- re << "}";
- break;
- }
- }
-};
-
-MODULE_INIT(ModuleRpcJson)