1
0
mirror of https://github.com/anope/anope.git synced 2026-07-05 02:53:12 +02:00

Use RPC error responses correctly.

This commit is contained in:
Sadie Powell
2025-02-14 20:33:13 +00:00
parent 84b0859e8d
commit 420f83bbbf
5 changed files with 96 additions and 26 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ class AnopeXMLRPC
{
$ret = $this->run("checkAuthentication", [$account, $pass]);
if ($ret && $ret["result"] == "Success") {
if ($ret && array_key_exists("account", $ret)) {
return $ret["account"];
}
+19 -3
View File
@@ -13,16 +13,32 @@
class RPCRequest final
{
private:
std::optional<std::pair<int64_t, Anope::string>> error;
std::map<Anope::string, Anope::string> replies;
public:
Anope::string name;
Anope::string id;
std::deque<Anope::string> data;
HTTPReply &r;
HTTPReply &reply;
RPCRequest(HTTPReply &r)
: reply(r)
{
}
inline void Error(uint64_t errcode, const Anope::string &errstr)
{
this->error.emplace(errcode, errstr);
}
inline void Reply(const Anope::string &dname, const Anope::string &ddata)
{
this->replies.emplace(dname, ddata);
}
inline const auto &GetError() { return this->error; }
RPCRequest(HTTPReply &_r) : r(_r) { }
inline void Reply(const Anope::string &dname, const Anope::string &ddata) { this->replies.emplace(dname, ddata); }
inline const auto &GetReplies() { return this->replies; }
};
+9 -3
View File
@@ -25,7 +25,7 @@ class MyJSONRPCServiceInterface final
private:
std::deque<RPCEvent *> events;
void SendError(HTTPReply &reply, int64_t code, const char *message, const Anope::string &id)
void SendError(HTTPReply &reply, int64_t code, const Anope::string &message, const Anope::string &id)
{
Log(LOG_DEBUG) << "JSON-RPC error " << code << ": " << message;
@@ -37,7 +37,7 @@ private:
auto *error = yyjson_mut_obj(doc);
yyjson_mut_obj_add_sint(doc, error, "code", code);
yyjson_mut_obj_add_str(doc, error, "message", message);
yyjson_mut_obj_add_strn(doc, error, "message", message.c_str(), message.length());
yyjson_mut_obj_add_val(doc, root, "error", error);
yyjson_mut_obj_add_str(doc, root, "jsonrpc", "2.0");
@@ -122,6 +122,12 @@ public:
if (!e->Run(this, client, request))
return false;
else if (request.GetError())
{
SendError(reply, request.GetError()->first, request.GetError()->second, id);
return true;
}
else if (!request.GetReplies().empty())
{
this->Reply(request);
@@ -160,7 +166,7 @@ public:
auto *json = yyjson_mut_write(doc, YYJSON_WRITE_ALLOW_INVALID_UNICODE | YYJSON_WRITE_NEWLINE_AT_END, nullptr);
if (json)
{
request.r.Write(json);
request.reply.Write(json);
free(json);
}
yyjson_mut_doc_free(doc);
+16 -14
View File
@@ -21,20 +21,26 @@ class RPCIdentifyRequest final
Reference<RPCServiceInterface> xinterface;
public:
RPCIdentifyRequest(Module *m, RPCRequest &req, HTTPClient *c, RPCServiceInterface *iface, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), request(req), repl(request.r), client(c), xinterface(iface) { }
RPCIdentifyRequest(Module *m, RPCRequest &req, HTTPClient *c, RPCServiceInterface *iface, const Anope::string &acc, const Anope::string &pass)
: IdentifyRequest(m, acc, pass)
, request(req)
, repl(request.reply)
, client(c)
, xinterface(iface)
{
}
void OnSuccess() override
{
if (!xinterface || !client)
return;
request.r = this->repl;
request.reply = this->repl;
request.Reply("result", "Success");
request.Reply("account", GetAccount());
xinterface->Reply(request);
client->SendReply(&request.r);
client->SendReply(&request.reply);
}
void OnFail() override
@@ -42,12 +48,12 @@ public:
if (!xinterface || !client)
return;
request.r = this->repl;
request.reply = this->repl;
request.Reply("error", "Invalid password");
request.Error(-32000, "Invalid password");
xinterface->Reply(request);
client->SendReply(&request.r);
client->SendReply(&request.reply);
}
};
@@ -83,16 +89,14 @@ private:
Anope::string command = request.data.size() > 2 ? request.data[2] : "";
if (service.empty() || user.empty() || command.empty())
request.Reply("error", "Invalid parameters");
request.Error(-32602, "Invalid parameters");
else
{
BotInfo *bi = BotInfo::Find(service, true);
if (!bi)
request.Reply("error", "Invalid service");
request.Error(-32000, "Invalid service");
else
{
request.Reply("result", "Success");
NickAlias *na = NickAlias::Find(user);
Anope::string out;
@@ -127,7 +131,7 @@ private:
Anope::string password = request.data.size() > 1 ? request.data[1] : "";
if (username.empty() || password.empty())
request.Reply("error", "Invalid parameters");
request.Error(-32602, "Invalid parameters");
else
{
auto *req = new RPCIdentifyRequest(me, request, client, iface, username, password);
@@ -273,8 +277,6 @@ private:
return;
u->SendMessage(bi, message);
request.Reply("result", "Success");
}
};
+51 -5
View File
@@ -187,12 +187,58 @@ public:
if (!request.id.empty())
request.Reply("id", request.id);
Anope::string r = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<methodResponse>\n<params>\n<param>\n<value>\n<struct>\n";
for (const auto &[name, value] : request.GetReplies())
r += "<member>\n<name>" + this->Sanitize(name) + "</name>\n<value>\n<string>" + this->Sanitize(value) + "</string>\n</value>\n</member>\n";
r += "</struct>\n</value>\n</param>\n</params>\n</methodResponse>";
Anope::string xml =
"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
"<methodResponse>\n";
request.r.Write(r);
if (request.GetError())
{
xml +=
"<fault>\n"
" <value>\n"
" <struct>\n"
" <member>\n"
" <name>faultCode</name>\n"
" <value>\n"
" <int>" + Anope::ToString(request.GetError()->first) + "</int>\n"
" </value>\n"
" </member>\n"
" <member>\n"
" <name>faultString</name>\n"
" <value>\n"
" <string>" + this->Sanitize(request.GetError()->second) + "</string>\n"
" </value>\n"
" </member>\n"
" </struct>\n"
" </value>\n"
"</fault>\n";
}
else
{
xml +=
"<params>\n"
" <param>\n"
" <value>\n"
" <struct>\n";
for (const auto &[name, value] : request.GetReplies())
{
xml +=
"<member>\n"
" <name>" + this->Sanitize(name) + "</name>\n"
" <value>\n"
" <string>" + this->Sanitize(value) + "</string>\n"
" </value>\n"
"</member>\n";
}
xml +=
" </struct>\n"
" </value>\n"
" </param>\n"
"</params>\n";
}
xml += "</methodResponse>";
request.reply.Write(xml);
}
};