comparison plugins/mod_carbons.lua @ 11200:bf8f2da84007

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Thu, 05 Nov 2020 22:31:25 +0100
parents e0a09d3af563
children 08b397c21805
comparison
equal deleted inserted replaced
11199:6c7c50a4de32 11200:bf8f2da84007
3 -- 3 --
4 -- This file is MIT/X11 licensed. 4 -- This file is MIT/X11 licensed.
5 5
6 local st = require "util.stanza"; 6 local st = require "util.stanza";
7 local jid_bare = require "util.jid".bare; 7 local jid_bare = require "util.jid".bare;
8 local jid_resource = require "util.jid".resource;
8 local xmlns_carbons = "urn:xmpp:carbons:2"; 9 local xmlns_carbons = "urn:xmpp:carbons:2";
9 local xmlns_forward = "urn:xmpp:forward:0"; 10 local xmlns_forward = "urn:xmpp:forward:0";
10 local full_sessions, bare_sessions = prosody.full_sessions, prosody.bare_sessions; 11 local full_sessions, bare_sessions = prosody.full_sessions, prosody.bare_sessions;
12
13 local function is_bare(jid)
14 return not jid_resource(jid);
15 end
11 16
12 local function toggle_carbons(event) 17 local function toggle_carbons(event)
13 local origin, stanza = event.origin, event.stanza; 18 local origin, stanza = event.origin, event.stanza;
14 local state = stanza.tags[1].name; 19 local state = stanza.tags[1].name;
15 module:log("debug", "%s %sd carbons", origin.full_jid, state); 20 module:log("debug", "%s %sd carbons", origin.full_jid, state);
18 return true; 23 return true;
19 end 24 end
20 module:hook("iq-set/self/"..xmlns_carbons..":disable", toggle_carbons); 25 module:hook("iq-set/self/"..xmlns_carbons..":disable", toggle_carbons);
21 module:hook("iq-set/self/"..xmlns_carbons..":enable", toggle_carbons); 26 module:hook("iq-set/self/"..xmlns_carbons..":enable", toggle_carbons);
22 27
28 local function should_copy(stanza, c2s, user_bare) --> boolean, reason: string
29 local st_type = stanza.attr.type or "normal";
30 if stanza:get_child("private", xmlns_carbons) then
31 return false, "private";
32 end
33
34 if stanza:get_child("no-copy", "urn:xmpp:hints") then
35 return false, "hint";
36 end
37
38 if not c2s and stanza.attr.to ~= user_bare and stanza:get_child("x", "http://jabber.org/protocol/muc#user") then
39 -- MUC PMs are normally sent to full JIDs
40 return false, "muc-pm";
41 end
42
43 if st_type == "chat" then
44 return true, "type";
45 end
46
47 if st_type == "normal" and stanza:get_child("body") then
48 return true, "type";
49 end
50
51 -- Normal outgoing chat messages are sent to=bare JID. This clause should
52 -- match the error bounces from those, which would have from=bare JID and
53 -- be incoming (not c2s).
54 if st_type == "error" and not c2s and is_bare(stanza.attr.from) then
55 return true, "bounce";
56 end
57
58 if stanza:get_child(nil, "urn:xmpp:jingle-message:0") then
59 -- XXX Experimental XEP stuck in Proposed for almost a year at the time of this comment
60 return true, "jingle call";
61 end
62
63 for archived in stanza:childtags("stanza-id", "urn:xmpp:sid:0") do
64 if archived and archived.attr.by == user_bare then
65 return true, "archived";
66 end
67 end
68
69 return false, "default";
70 end
71
23 local function message_handler(event, c2s) 72 local function message_handler(event, c2s)
24 local origin, stanza = event.origin, event.stanza; 73 local origin, stanza = event.origin, event.stanza;
25 local orig_type = stanza.attr.type or "normal"; 74 local orig_type = stanza.attr.type or "normal";
26 local orig_from = stanza.attr.from; 75 local orig_from = stanza.attr.from;
27 local bare_from = jid_bare(orig_from); 76 local bare_from = jid_bare(orig_from);
28 local orig_to = stanza.attr.to; 77 local orig_to = stanza.attr.to;
29 local bare_to = jid_bare(orig_to); 78 local bare_to = jid_bare(orig_to);
30
31 if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body"))) then
32 return -- Only chat type messages
33 end
34 79
35 -- Stanza sent by a local client 80 -- Stanza sent by a local client
36 local bare_jid = bare_from; -- JID of the local user 81 local bare_jid = bare_from; -- JID of the local user
37 local target_session = origin; 82 local target_session = origin;
38 local top_priority = false; 83 local top_priority = false;
54 if not user_sessions then 99 if not user_sessions then
55 module:log("debug", "Skip carbons for offline user"); 100 module:log("debug", "Skip carbons for offline user");
56 return -- No use in sending carbons to an offline user 101 return -- No use in sending carbons to an offline user
57 end 102 end
58 103
59 if stanza:get_child("private", xmlns_carbons) then 104 local should, why = should_copy(stanza, c2s, bare_jid);
60 if not c2s then 105
106 if not should then
107 module:log("debug", "Not copying stanza: %s (%s)", stanza:top_tag(), why);
108 if why == "private" and not c2s then
61 stanza:maptags(function(tag) 109 stanza:maptags(function(tag)
62 if not ( tag.attr.xmlns == xmlns_carbons and tag.name == "private" ) then 110 if not ( tag.attr.xmlns == xmlns_carbons and tag.name == "private" ) then
63 return tag; 111 return tag;
64 end 112 end
65 end); 113 end);
66 end 114 end
67 module:log("debug", "Message tagged private, ignoring"); 115 return;
68 return
69 elseif stanza:get_child("no-copy", "urn:xmpp:hints") then
70 module:log("debug", "Message has no-copy hint, ignoring");
71 return
72 elseif not c2s and bare_jid ~= orig_to and stanza:get_child("x", "http://jabber.org/protocol/muc#user") then
73 module:log("debug", "MUC PM, ignoring");
74 return
75 end 116 end
76 117
77 -- Create the carbon copy and wrap it as per the Stanza Forwarding XEP 118 local carbon;
78 local copy = st.clone(stanza);
79 if c2s and not orig_to then
80 stanza.attr.to = bare_from;
81 end
82 copy.attr.xmlns = "jabber:client";
83 local carbon = st.message{ from = bare_jid, type = orig_type, }
84 :tag(c2s and "sent" or "received", { xmlns = xmlns_carbons })
85 :tag("forwarded", { xmlns = xmlns_forward })
86 :add_child(copy):reset();
87
88 user_sessions = user_sessions and user_sessions.sessions; 119 user_sessions = user_sessions and user_sessions.sessions;
89 for _, session in pairs(user_sessions) do 120 for _, session in pairs(user_sessions) do
90 -- Carbons are sent to resources that have enabled it 121 -- Carbons are sent to resources that have enabled it
91 if session.want_carbons 122 if session.want_carbons
92 -- but not the resource that sent the message, or the one that it's directed to 123 -- but not the resource that sent the message, or the one that it's directed to
93 and session ~= target_session 124 and session ~= target_session
94 -- and isn't among the top resources that would receive the message per standard routing rules 125 -- and isn't among the top resources that would receive the message per standard routing rules
95 and (c2s or session.priority ~= top_priority) then 126 and (c2s or session.priority ~= top_priority) then
127 if not carbon then
128 -- Create the carbon copy and wrap it as per the Stanza Forwarding XEP
129 local copy = st.clone(stanza);
130 if c2s and not orig_to then
131 stanza.attr.to = bare_from;
132 end
133 copy.attr.xmlns = "jabber:client";
134 carbon = st.message{ from = bare_jid, type = orig_type, }
135 :tag(c2s and "sent" or "received", { xmlns = xmlns_carbons })
136 :tag("forwarded", { xmlns = xmlns_forward })
137 :add_child(copy):reset();
138
139 end
140
96 carbon.attr.to = session.full_jid; 141 carbon.attr.to = session.full_jid;
97 module:log("debug", "Sending carbon to %s", session.full_jid); 142 module:log("debug", "Sending carbon to %s", session.full_jid);
98 session.send(carbon); 143 session.send(carbon);
99 end 144 end
100 end 145 end