aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2022-08-29 14:59:46 +0100
committerMatthew Wild <mwild1@gmail.com>2022-08-29 14:59:46 +0100
commitb02ab508d51481e19991053645ed48dcb819c4d9 (patch)
treeb6170b388a991545f78cad3ce3b1a730b784dd70
parenta2cabe641854d887bd5814ddf3037a3c4cd7440d (diff)
downloadprosody-b02ab508d51481e19991053645ed48dcb819c4d9.tar.gz
prosody-b02ab508d51481e19991053645ed48dcb819c4d9.zip
util.stanza: Add add_error() to simplify adding error tags to existing stanzas
Some fiddling is required now in error_reply() to ensure the cursor is in the same place as before this change (a lot of code apparently uses that feature).
-rw-r--r--spec/util_stanza_spec.lua14
-rw-r--r--util/stanza.lua56
2 files changed, 45 insertions, 25 deletions
diff --git a/spec/util_stanza_spec.lua b/spec/util_stanza_spec.lua
index 8732a111..e11c70dd 100644
--- a/spec/util_stanza_spec.lua
+++ b/spec/util_stanza_spec.lua
@@ -314,6 +314,20 @@ describe("util.stanza", function()
end)
end)
+ describe("#add_error()", function ()
+ describe("basics", function ()
+ local s = st.stanza("custom", { xmlns = "urn:example:foo" });
+ local e = s:add_error("cancel", "not-acceptable", "UNACCEPTABLE!!!! ONE MILLION YEARS DUNGEON!")
+ :tag("dungeon", { xmlns = "urn:uuid:c9026187-5b05-4e70-b265-c3b6338a7d0f", period="1000000years"});
+ assert.equal(s, e);
+ local typ, cond, text, extra = e:get_error();
+ assert.equal("cancel", typ);
+ assert.equal("not-acceptable", cond);
+ assert.equal("UNACCEPTABLE!!!! ONE MILLION YEARS DUNGEON!", text);
+ assert.is_nil(extra);
+ end)
+ end)
+
describe("should reject #invalid", function ()
local invalid_names = {
["empty string"] = "", ["characters"] = "<>";
diff --git a/util/stanza.lua b/util/stanza.lua
index b75a1f32..24f3cb33 100644
--- a/util/stanza.lua
+++ b/util/stanza.lua
@@ -29,6 +29,7 @@ local valid_utf8 = require "util.encodings".utf8.valid;
local do_pretty_printing, termcolours = pcall(require, "util.termcolours");
local xmlns_stanzas = "urn:ietf:params:xml:ns:xmpp-stanzas";
+local xmpp_stanzas_attr = { xmlns = xmlns_stanzas };
local _ENV = nil;
-- luacheck: std none
@@ -396,6 +397,33 @@ function stanza_mt.get_error(stanza)
return error_type, condition or "undefined-condition", text, extra_tag;
end
+function stanza_mt.add_error(stanza, error_type, condition, error_message, error_by)
+ local extra;
+ if type(error_type) == "table" then -- an util.error or similar object
+ if type(error_type.extra) == "table" then
+ extra = error_type.extra;
+ end
+ if type(error_type.context) == "table" and type(error_type.context.by) == "string" then error_by = error_type.context.by; end
+ error_type, condition, error_message = error_type.type, error_type.condition, error_type.text;
+ end
+ if stanza.attr.from == error_by then
+ error_by = nil;
+ end
+ stanza:tag("error", {type = error_type, by = error_by}) --COMPAT: Some day xmlns:stanzas goes here
+ :tag(condition, xmpp_stanzas_attr);
+ if extra and condition == "gone" and type(extra.uri) == "string" then
+ stanza:text(extra.uri);
+ end
+ stanza:up();
+ if error_message then stanza:text_tag("text", error_message, xmpp_stanzas_attr); end
+ if extra and is_stanza(extra.tag) then
+ stanza:add_child(extra.tag);
+ elseif extra and extra.namespace and extra.condition then
+ stanza:tag(extra.condition, { xmlns = extra.namespace }):up();
+ end
+ return stanza:up();
+end
+
local function preserialize(stanza)
local s = { name = stanza.name, attr = stanza.attr };
for _, child in ipairs(stanza) do
@@ -470,7 +498,6 @@ local function reply(orig)
});
end
-local xmpp_stanzas_attr = { xmlns = xmlns_stanzas };
local function error_reply(orig, error_type, condition, error_message, error_by)
if not is_stanza(orig) then
error("bad argument to error_reply: expected stanza, got "..type(orig));
@@ -479,30 +506,9 @@ local function error_reply(orig, error_type, condition, error_message, error_by)
end
local t = reply(orig);
t.attr.type = "error";
- local extra;
- if type(error_type) == "table" then -- an util.error or similar object
- if type(error_type.extra) == "table" then
- extra = error_type.extra;
- end
- if type(error_type.context) == "table" and type(error_type.context.by) == "string" then error_by = error_type.context.by; end
- error_type, condition, error_message = error_type.type, error_type.condition, error_type.text;
- end
- if t.attr.from == error_by then
- error_by = nil;
- end
- t:tag("error", {type = error_type, by = error_by}) --COMPAT: Some day xmlns:stanzas goes here
- :tag(condition, xmpp_stanzas_attr);
- if extra and condition == "gone" and type(extra.uri) == "string" then
- t:text(extra.uri);
- end
- t:up();
- if error_message then t:text_tag("text", error_message, xmpp_stanzas_attr); end
- if extra and is_stanza(extra.tag) then
- t:add_child(extra.tag);
- elseif extra and extra.namespace and extra.condition then
- t:tag(extra.condition, { xmlns = extra.namespace }):up();
- end
- return t; -- stanza ready for adding app-specific errors
+ t:add_error(error_type, condition, error_message, error_by);
+ t.last_add = { t[1] }; -- ready to add application-specific errors
+ return t;
end
local function presence(attr)