Software /
code /
prosody
File
util/template.lua @ 12525:8087f5357f53 0.12
mod_smacks: Fix bounce of stanzas directed to full JID on unclean disconnect
Fixes #1758
Introduced in 1ea01660c79a
In e62025f949f9 to and from was inverted since it changed from acting on
a reply to acting on the original stanza (or a clone thereof)
Unsure of the purpose of this check, you don't usually send stanzas to
your own full JID. Perhaps guarding against routing loops?
The check was present in the original commit of mod_smacks,
prosody-modules rev 9a7671720dec
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 27 May 2022 12:05:47 +0200 |
parent | 8555:4f0f5b49bb03 |
child | 12975:d10957394a3c |
line wrap: on
line source
-- luacheck: ignore 213/i local stanza_mt = require "util.stanza".stanza_mt; local setmetatable = setmetatable; local pairs = pairs; local ipairs = ipairs; local error = error; local envload = require "util.envload".envload; local debug = debug; local t_remove = table.remove; local parse_xml = require "util.xml".parse; local _ENV = nil; -- luacheck: std none local function trim_xml(stanza) for i=#stanza,1,-1 do local child = stanza[i]; if child.name then trim_xml(child); else child = child:gsub("^%s*", ""):gsub("%s*$", ""); stanza[i] = child; if child == "" then t_remove(stanza, i); end end end end local function create_string_string(str) str = ("%q"):format(str); str = str:gsub("{([^}]*)}", function(s) return '"..(data["'..s..'"]or"").."'; end); return str; end local function create_attr_string(attr, xmlns) local str = '{'; for name,value in pairs(attr) do if name ~= "xmlns" or value ~= xmlns then str = str..("[%q]=%s;"):format(name, create_string_string(value)); end end return str..'}'; end local function create_clone_string(stanza, lookup, xmlns) if not lookup[stanza] then local s = ('setmetatable({name=%q,attr=%s,tags={'):format(stanza.name, create_attr_string(stanza.attr, xmlns)); -- add tags for i,tag in ipairs(stanza.tags) do s = s..create_clone_string(tag, lookup, stanza.attr.xmlns)..";"; end s = s..'};'; -- add children for i,child in ipairs(stanza) do if child.name then s = s..create_clone_string(child, lookup, stanza.attr.xmlns)..";"; else s = s..create_string_string(child)..";" end end s = s..'}, stanza_mt)'; s = s:gsub('%.%.""', ""):gsub('([=;])""%.%.', "%1"):gsub(';"";', ";"); -- strip empty strings local n = #lookup + 1; lookup[n] = s; lookup[stanza] = "_"..n; end return lookup[stanza]; end local function create_cloner(stanza, chunkname) local lookup = {}; local name = create_clone_string(stanza, lookup, ""); local src = "local setmetatable,stanza_mt=...;return function(data)"; for i=1,#lookup do src = src.."local _"..i.."="..lookup[i]..";"; end src = src.."return "..name..";end"; local f,err = envload(src, chunkname); if not f then error(err); end return f(setmetatable, stanza_mt); end local template_mt = { __tostring = function(t) return t.name end }; local function create_template(templates, text) local stanza, err = parse_xml(text); if not stanza then error(err); end trim_xml(stanza); local info = debug.getinfo(3, "Sl"); info = info and ("template(%s:%d)"):format(info.short_src:match("[^\\/]*$"), info.currentline) or "template(unknown)"; local template = setmetatable({ apply = create_cloner(stanza, info), name = info, text = text }, template_mt); templates[text] = template; return template; end local templates = setmetatable({}, { __mode = 'k', __index = create_template }); return function(text) return templates[text]; end;