Fix all integrations
This commit is contained in:
138
utilities/prosody/modules/mod_privileged_carbons.lua
Normal file
138
utilities/prosody/modules/mod_privileged_carbons.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
local st = require "prosody.util.stanza";
|
||||
local jid_bare = require "prosody.util.jid".bare;
|
||||
|
||||
local xmlns_privilege = "urn:xmpp:privilege:2";
|
||||
local xmlns_forward = "urn:xmpp:forward:0";
|
||||
local xmlns_carbons = "urn:xmpp:carbons:2";
|
||||
local bare_sessions = prosody.bare_sessions;
|
||||
|
||||
local allowed_component_jid = module:get_option_string("privileged_entity_jid");
|
||||
|
||||
module:log("info", "mod_privileged_carbons loaded for host=%s privileged_entity_jid=%s", module.host or "?", allowed_component_jid or "");
|
||||
|
||||
local function iter_sessions(user_sessions)
|
||||
if not user_sessions or not user_sessions.sessions then
|
||||
return function() return nil end;
|
||||
end
|
||||
return pairs(user_sessions.sessions);
|
||||
end
|
||||
|
||||
local function unwrap_forwarded_message(stanza)
|
||||
local privilege = stanza:get_child("privilege", xmlns_privilege);
|
||||
if not privilege then
|
||||
return nil;
|
||||
end
|
||||
local forwarded = privilege:get_child("forwarded", xmlns_forward);
|
||||
if not forwarded then
|
||||
return nil;
|
||||
end
|
||||
for _, tag in ipairs(forwarded.tags or {}) do
|
||||
if tag.name == "message" then
|
||||
return tag;
|
||||
end
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
local function is_carbon_delivery(inner)
|
||||
if not inner then
|
||||
return false;
|
||||
end
|
||||
return inner:get_child("sent", xmlns_carbons) ~= nil
|
||||
or inner:get_child("received", xmlns_carbons) ~= nil;
|
||||
end
|
||||
|
||||
local function build_sent_carbon(inner, user_bare)
|
||||
local function rebuild_stanza(node)
|
||||
if type(node) ~= "table" or not node.name then
|
||||
return node;
|
||||
end
|
||||
local attr = {};
|
||||
for k, v in pairs(node.attr or {}) do
|
||||
attr[k] = v;
|
||||
end
|
||||
local rebuilt = st.stanza(node.name, attr);
|
||||
for _, child in ipairs(node) do
|
||||
if type(child) == "table" and child.name then
|
||||
rebuilt:add_direct_child(rebuild_stanza(child));
|
||||
elseif type(child) == "string" then
|
||||
rebuilt:add_direct_child(child);
|
||||
end
|
||||
end
|
||||
return rebuilt;
|
||||
end
|
||||
local copy = rebuild_stanza(inner);
|
||||
local function normalize_client_ns(node)
|
||||
if not node then
|
||||
return;
|
||||
end
|
||||
if node.attr then
|
||||
if node.attr.xmlns == nil or node.attr.xmlns == "jabber:component:accept" then
|
||||
node.attr.xmlns = "jabber:client";
|
||||
end
|
||||
end
|
||||
if node.tags then
|
||||
for _, child in ipairs(node.tags) do
|
||||
normalize_client_ns(child);
|
||||
end
|
||||
end
|
||||
end
|
||||
normalize_client_ns(copy);
|
||||
return st.message({ from = user_bare, type = inner.attr.type or "chat", xmlns = "jabber:client" })
|
||||
:tag("sent", { xmlns = xmlns_carbons })
|
||||
:tag("forwarded", { xmlns = xmlns_forward })
|
||||
:add_child(copy):reset();
|
||||
end
|
||||
|
||||
local function deliver_carbon_to_user_sessions(bare_jid, inner)
|
||||
local user_sessions = bare_sessions[bare_jid];
|
||||
if not user_sessions then
|
||||
module:log("debug", "Privileged carbon skipped for offline user %s", bare_jid);
|
||||
return true;
|
||||
end
|
||||
local carbon = build_sent_carbon(inner, bare_jid);
|
||||
local delivered = false;
|
||||
for _, session in iter_sessions(user_sessions) do
|
||||
if session.full_jid and session.send then
|
||||
local copy = st.clone(carbon);
|
||||
copy.attr.xmlns = "jabber:client";
|
||||
copy.attr.to = session.full_jid;
|
||||
session.rawsend(tostring(copy));
|
||||
delivered = true;
|
||||
end
|
||||
end
|
||||
module:log("info", "Privileged carbon delivered user=%s delivered=%s", bare_jid, tostring(delivered));
|
||||
return true;
|
||||
end
|
||||
|
||||
local function handle_privileged_carbon(event)
|
||||
local origin, stanza = event.origin, event.stanza;
|
||||
if not origin or origin.type ~= "component" then
|
||||
return nil;
|
||||
end
|
||||
if allowed_component_jid and allowed_component_jid ~= "" and origin.host ~= allowed_component_jid then
|
||||
module:log("debug", "Ignoring privileged message from unexpected component %s", origin.host or "?");
|
||||
return nil;
|
||||
end
|
||||
|
||||
local inner = unwrap_forwarded_message(stanza);
|
||||
if not inner then
|
||||
module:log("debug", "Ignoring privileged message without forwarded payload from %s", origin.host or "?");
|
||||
return nil;
|
||||
end
|
||||
|
||||
local bare_from = jid_bare(inner.attr.from);
|
||||
if not bare_from or bare_from == "" then
|
||||
module:log("warn", "Rejected malformed privileged carbon from %s", origin.host or "?");
|
||||
return true;
|
||||
end
|
||||
if bare_from:match("@(.+)$") ~= module.host then
|
||||
module:log("debug", "Ignoring privileged carbon for remote host %s", bare_from);
|
||||
return nil;
|
||||
end
|
||||
|
||||
return deliver_carbon_to_user_sessions(bare_from, inner);
|
||||
end
|
||||
|
||||
module:hook("pre-message/host", handle_privileged_carbon, 10);
|
||||
module:hook("message/host", handle_privileged_carbon, 10);
|
||||
Reference in New Issue
Block a user