diff --git a/resources/prosody-plugins/mod_muc_displayname.lua b/resources/prosody-plugins/mod_muc_displayname.lua index c15f6433d2..437e74de3c 100644 --- a/resources/prosody-plugins/mod_muc_displayname.lua +++ b/resources/prosody-plugins/mod_muc_displayname.lua @@ -1,19 +1,23 @@ +--- This module removes identity information from presence stanzas when the +--- hideDisplayNameForAll or hideDisplayNameForGuests options are enabled +--- for a room. + --- To be enabled under the main muc component local filters = require 'util.filters'; local st = require 'util.stanza'; local util = module:require 'util'; +local filter_identity_from_presence = util.filter_identity_from_presence; local get_room_by_name_and_subdomain = util.get_room_by_name_and_subdomain; local is_admin = util.is_admin; local ends_with = util.ends_with; local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite; -local NICK_NS = 'http://jabber.org/protocol/nick'; - -- we need to get the shared resource for joining moderators, as participants are marked as moderators -- after joining which is after the filter for stanza/out, but we need to know will this participant be a moderator local joining_moderator_participants = module:shared('moderators/joining_moderator_participants'); +--- Filter presence sent to non-moderator members of a room when the hideDisplayNameForGuests option is set. function filter_stanza_out(stanza, session) if stanza.name ~= 'presence' or stanza.attr.type == 'error' or stanza.attr.type == 'unavailable' or ends_with(stanza.attr.from, '/focus') then @@ -34,15 +38,14 @@ function filter_stanza_out(stanza, session) end if occupant.role ~= 'moderator' and not joining_moderator_participants[occupant.bare_jid] then - local st_clone = st.clone(stanza); - st_clone:remove_children('nick', NICK_NS); - return st_clone; + return filter_identity_from_presence(stanza); end end return stanza; end +--- Filter presence received from anyone in a room when the hideDisplayNameForAll option is set. function filter_stanza_in(stanza, session) if stanza.name ~= 'presence' or stanza.attr.type == 'error' or stanza.attr.type == 'unavailable' then return stanza; @@ -51,12 +54,10 @@ function filter_stanza_in(stanza, session) local room = get_room_by_name_and_subdomain(session.jitsi_web_query_room, session.jitsi_web_query_prefix); -- if hideDisplayNameForAll we want to drop any display name from the presence stanza - if not room or room._data.hideDisplayNameForAll ~= true then - return stanza; + if room and room._data.hideDisplayNameForAll == true then + return filter_identity_from_presence(stanza); end - stanza:remove_children('nick', NICK_NS); - return stanza; end diff --git a/resources/prosody-plugins/mod_visitors.lua b/resources/prosody-plugins/mod_visitors.lua index 687c0e1c91..ecac1a1bf9 100644 --- a/resources/prosody-plugins/mod_visitors.lua +++ b/resources/prosody-plugins/mod_visitors.lua @@ -12,12 +12,16 @@ local st = require 'util.stanza'; local jid = require 'util.jid'; local new_id = require 'util.id'.medium; local util = module:require 'util'; +local filter_identity_from_presence = util.filter_identity_from_presence; local is_admin = util.is_admin; local presence_check_status = util.presence_check_status; local process_host_module = util.process_host_module; local is_transcriber_jigasi = util.is_transcriber_jigasi; local json = require 'cjson.safe'; +-- Debug flag +local DEBUG = false; + local MUC_NS = 'http://jabber.org/protocol/muc'; -- required parameter for custom muc component prefix, defaults to 'conference' @@ -97,6 +101,25 @@ local function send_visitors_iq(conference_service, room, type) module:send(visitors_iq); end +-- Filter out identity information (nick name, email, etc) from a presence stanza, +-- if the hideDisplayNameForGuests option for the room is set (note that the +-- hideDisplayNameForAll option is implemented in a diffrent way and does not +-- require filtering here) +-- This is applied to presence of main room participants before it is sent out to +-- vnodes. +local function filter_stanza_nick_if_needed(stanza, room) + if not stanza or stanza.name ~= 'presence' or stanza.attr.type == 'error' or stanza.attr.type == 'unavailable' then + return stanza; + end + + -- if hideDisplayNameForGuests we want to drop any display name from the presence stanza + if room and room._data.hideDisplayNameForGuests == true then + return filter_identity_from_presence(stanza); + end + + return stanza; +end + -- an event received from visitors component, which receives iqs from jicofo local function connect_vnode(event) local room, vnode = event.room, event.vnode; @@ -123,7 +146,7 @@ local function connect_vnode(event) for _, o in room:each_occupant() do if not is_admin(o.bare_jid) then - local fmuc_pr = st.clone(o:get_presence()); + local fmuc_pr = filter_stanza_nick_if_needed(st.clone(o:get_presence()), room); local user, _, res = jid.split(o.nick); fmuc_pr.attr.to = jid.join(user, conference_service , res); fmuc_pr.attr.from = o.jid; @@ -206,7 +229,8 @@ end, 900); process_host_module(main_muc_component_config, function(host_module, host) -- detects presence change in a main participant and propagate it to the used visitor nodes host_module:hook('muc-occupant-pre-change', function (event) - local room, stanza, occupant = event.room, event.stanza, event.dest_occupant; + local room, stanzaEv, occupant = event.room, event.stanza, event.dest_occupant; + local stanza = filter_stanza_nick_if_needed(stanzaEv, room); -- filter focus and configured domains (used for jibri and transcribers) if is_admin(stanza.attr.from) or visitors_nodes[room.jid] == nil @@ -227,7 +251,8 @@ process_host_module(main_muc_component_config, function(host_module, host) -- when a main participant leaves inform the visitor nodes host_module:hook('muc-occupant-left', function (event) - local room, stanza, occupant = event.room, event.stanza, event.occupant; + local room, stanzaEv, occupant = event.room, event.stanza, event.occupant; + local stanza = filter_stanza_nick_if_needed(stanzaEv, room); -- ignore configured domains (jibri and transcribers) if is_admin(occupant.bare_jid) or visitors_nodes[room.jid] == nil or visitors_nodes[room.jid].nodes == nil @@ -270,7 +295,8 @@ process_host_module(main_muc_component_config, function(host_module, host) -- detects new participants joining main room and sending them to the visitor nodes host_module:hook('muc-occupant-joined', function (event) - local room, stanza, occupant = event.room, event.stanza, event.occupant; + local room, stanzaEv, occupant = event.room, event.stanza, event.occupant; + local stanza = filter_stanza_nick_if_needed(stanzaEv, room); -- filter focus, ignore configured domains (jibri and transcribers) if is_admin(stanza.attr.from) or visitors_nodes[room.jid] == nil @@ -294,7 +320,8 @@ process_host_module(main_muc_component_config, function(host_module, host) end); -- forwards messages from main participants to vnodes host_module:hook('muc-occupant-groupchat', function(event) - local room, stanza, occupant = event.room, event.stanza, event.occupant; + local room, stanzaEv, occupant = event.room, event.stanza, event.occupant; + local stanza = filter_stanza_nick_if_needed(stanzaEv, room); -- filter sending messages from transcribers/jibris to visitors if not visitors_nodes[room.jid] then @@ -314,7 +341,8 @@ process_host_module(main_muc_component_config, function(host_module, host) -- receiving messages from visitor nodes and forward them to local main participants -- and forward them to the rest of visitor nodes host_module:hook('muc-occupant-groupchat', function(event) - local occupant, room, stanza = event.occupant, event.room, event.stanza; + local occupant, room, stanzaEv = event.occupant, event.room, event.stanza; + local stanza = filter_stanza_nick_if_needed(stanzaEv, room); local to = stanza.attr.to; local from = stanza.attr.from; local from_vnode = jid.host(from); diff --git a/resources/prosody-plugins/util.lib.lua b/resources/prosody-plugins/util.lib.lua index ac185546cf..1b61b7dc7c 100644 --- a/resources/prosody-plugins/util.lib.lua +++ b/resources/prosody-plugins/util.lib.lua @@ -685,11 +685,36 @@ local function is_admin(_jid) return false; end +-- Filter out identity information (nick name, email, etc) from a presence stanza. +local function filter_identity_from_presence(stanza) + stanza:remove_children('nick', 'http://jabber.org/protocol/nick'); + stanza:remove_children('email'); + stanza:remove_children('stats-id'); + stanza:tag('email'):text('guest@guest.com'):up(); + local identity = stanza:get_child('identity'); + if identity then + local user = identity:get_child('user'); + local name = identity:get_child('name'); + if user then + user:remove_children('email'); + user:tag('email'):text('guest@guest.com'):up(); + user:remove_children('name'); + end + if name then + name:remove_children('name'); -- Remove name with no namespace + name:tag('name'):text('Guest'):up(); -- Add new name with guest value + end + end + + return stanza; +end + return { OUTBOUND_SIP_JIBRI_PREFIXES = OUTBOUND_SIP_JIBRI_PREFIXES; INBOUND_SIP_JIBRI_PREFIXES = INBOUND_SIP_JIBRI_PREFIXES; RECORDER_PREFIXES = RECORDER_PREFIXES; extract_subdomain = extract_subdomain; + filter_identity_from_presence = filter_identity_from_presence; is_admin = is_admin; is_feature_allowed = is_feature_allowed; is_jibri = is_jibri;