Software /
code /
prosody
Comparison
util/stanza.lua @ 12687:5b69ecaf3427
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).
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 29 Aug 2022 14:59:46 +0100 |
parent | 12636:e8934ce6ea0f |
child | 12725:12ced5db29b2 |
comparison
equal
deleted
inserted
replaced
12686:5f182bccf33f | 12687:5b69ecaf3427 |
---|---|
27 local valid_utf8 = require "util.encodings".utf8.valid; | 27 local valid_utf8 = require "util.encodings".utf8.valid; |
28 | 28 |
29 local do_pretty_printing, termcolours = pcall(require, "util.termcolours"); | 29 local do_pretty_printing, termcolours = pcall(require, "util.termcolours"); |
30 | 30 |
31 local xmlns_stanzas = "urn:ietf:params:xml:ns:xmpp-stanzas"; | 31 local xmlns_stanzas = "urn:ietf:params:xml:ns:xmpp-stanzas"; |
32 local xmpp_stanzas_attr = { xmlns = xmlns_stanzas }; | |
32 | 33 |
33 local _ENV = nil; | 34 local _ENV = nil; |
34 -- luacheck: std none | 35 -- luacheck: std none |
35 | 36 |
36 local stanza_mt = { __name = "stanza" }; | 37 local stanza_mt = { __name = "stanza" }; |
394 end | 395 end |
395 end | 396 end |
396 return error_type, condition or "undefined-condition", text, extra_tag; | 397 return error_type, condition or "undefined-condition", text, extra_tag; |
397 end | 398 end |
398 | 399 |
400 function stanza_mt.add_error(stanza, error_type, condition, error_message, error_by) | |
401 local extra; | |
402 if type(error_type) == "table" then -- an util.error or similar object | |
403 if type(error_type.extra) == "table" then | |
404 extra = error_type.extra; | |
405 end | |
406 if type(error_type.context) == "table" and type(error_type.context.by) == "string" then error_by = error_type.context.by; end | |
407 error_type, condition, error_message = error_type.type, error_type.condition, error_type.text; | |
408 end | |
409 if stanza.attr.from == error_by then | |
410 error_by = nil; | |
411 end | |
412 stanza:tag("error", {type = error_type, by = error_by}) --COMPAT: Some day xmlns:stanzas goes here | |
413 :tag(condition, xmpp_stanzas_attr); | |
414 if extra and condition == "gone" and type(extra.uri) == "string" then | |
415 stanza:text(extra.uri); | |
416 end | |
417 stanza:up(); | |
418 if error_message then stanza:text_tag("text", error_message, xmpp_stanzas_attr); end | |
419 if extra and is_stanza(extra.tag) then | |
420 stanza:add_child(extra.tag); | |
421 elseif extra and extra.namespace and extra.condition then | |
422 stanza:tag(extra.condition, { xmlns = extra.namespace }):up(); | |
423 end | |
424 return stanza:up(); | |
425 end | |
426 | |
399 local function preserialize(stanza) | 427 local function preserialize(stanza) |
400 local s = { name = stanza.name, attr = stanza.attr }; | 428 local s = { name = stanza.name, attr = stanza.attr }; |
401 for _, child in ipairs(stanza) do | 429 for _, child in ipairs(stanza) do |
402 if type(child) == "table" then | 430 if type(child) == "table" then |
403 t_insert(s, preserialize(child)); | 431 t_insert(s, preserialize(child)); |
468 id = orig.attr.id, | 496 id = orig.attr.id, |
469 type = ((orig.name == "iq" and "result") or orig.attr.type) | 497 type = ((orig.name == "iq" and "result") or orig.attr.type) |
470 }); | 498 }); |
471 end | 499 end |
472 | 500 |
473 local xmpp_stanzas_attr = { xmlns = xmlns_stanzas }; | |
474 local function error_reply(orig, error_type, condition, error_message, error_by) | 501 local function error_reply(orig, error_type, condition, error_message, error_by) |
475 if not is_stanza(orig) then | 502 if not is_stanza(orig) then |
476 error("bad argument to error_reply: expected stanza, got "..type(orig)); | 503 error("bad argument to error_reply: expected stanza, got "..type(orig)); |
477 elseif orig.attr.type == "error" then | 504 elseif orig.attr.type == "error" then |
478 error("bad argument to error_reply: got stanza of type error which must not be replied to"); | 505 error("bad argument to error_reply: got stanza of type error which must not be replied to"); |
479 end | 506 end |
480 local t = reply(orig); | 507 local t = reply(orig); |
481 t.attr.type = "error"; | 508 t.attr.type = "error"; |
482 local extra; | 509 t:add_error(error_type, condition, error_message, error_by); |
483 if type(error_type) == "table" then -- an util.error or similar object | 510 t.last_add = { t[1] }; -- ready to add application-specific errors |
484 if type(error_type.extra) == "table" then | 511 return t; |
485 extra = error_type.extra; | |
486 end | |
487 if type(error_type.context) == "table" and type(error_type.context.by) == "string" then error_by = error_type.context.by; end | |
488 error_type, condition, error_message = error_type.type, error_type.condition, error_type.text; | |
489 end | |
490 if t.attr.from == error_by then | |
491 error_by = nil; | |
492 end | |
493 t:tag("error", {type = error_type, by = error_by}) --COMPAT: Some day xmlns:stanzas goes here | |
494 :tag(condition, xmpp_stanzas_attr); | |
495 if extra and condition == "gone" and type(extra.uri) == "string" then | |
496 t:text(extra.uri); | |
497 end | |
498 t:up(); | |
499 if error_message then t:text_tag("text", error_message, xmpp_stanzas_attr); end | |
500 if extra and is_stanza(extra.tag) then | |
501 t:add_child(extra.tag); | |
502 elseif extra and extra.namespace and extra.condition then | |
503 t:tag(extra.condition, { xmlns = extra.namespace }):up(); | |
504 end | |
505 return t; -- stanza ready for adding app-specific errors | |
506 end | 512 end |
507 | 513 |
508 local function presence(attr) | 514 local function presence(attr) |
509 return new_stanza("presence", attr); | 515 return new_stanza("presence", attr); |
510 end | 516 end |