prosodyctl check: Warn about invalid domain names in the config file
This ensures that domain names of virtual hosts and components are valid in
XMPP, and that they are encoded correctly.
local pairs = pairs;
local setmetatable = setmetatable;
local st = require "util.stanza";
local util = module:require "muc/util";
local function get_filtered_presence(stanza)
return util.filter_muc_x(st.clone(stanza));
end
local occupant_mt = {};
occupant_mt.__index = occupant_mt;
local function new_occupant(bare_real_jid, nick)
return setmetatable({
bare_jid = bare_real_jid;
nick = nick; -- in-room jid
sessions = {}; -- hash from real_jid to presence stanzas. stanzas should not be modified
role = nil;
jid = nil; -- Primary session
}, occupant_mt);
end
-- Deep copy an occupant
local function copy_occupant(occupant)
local sessions = {};
for full_jid, presence_stanza in pairs(occupant.sessions) do
-- Don't keep unavailable presences, as they'll accumulate; unless they're the primary session
if presence_stanza.attr.type ~= "unavailable" or full_jid == occupant.jid then
sessions[full_jid] = presence_stanza;
end
end
return setmetatable({
bare_jid = occupant.bare_jid;
nick = occupant.nick;
sessions = sessions;
role = occupant.role;
jid = occupant.jid;
}, occupant_mt);
end
-- finds another session to be the primary (there might not be one)
function occupant_mt:choose_new_primary()
for jid, pr in self:each_session() do
if pr.attr.type == nil then
return jid;
end
end
return nil;
end
function occupant_mt:set_session(real_jid, presence_stanza, replace_primary)
local pr = get_filtered_presence(presence_stanza);
pr.attr.from = self.nick;
pr.attr.to = real_jid;
self.sessions[real_jid] = pr;
if replace_primary then
self.jid = real_jid;
elseif self.jid == nil or (pr.attr.type == "unavailable" and self.jid == real_jid) then
-- Only leave an unavailable presence as primary when there are no other options
self.jid = self:choose_new_primary() or real_jid;
end
end
function occupant_mt:remove_session(real_jid)
-- Delete original session
self.sessions[real_jid] = nil;
if self.jid == real_jid then
self.jid = self:choose_new_primary();
end
end
function occupant_mt:each_session()
return pairs(self.sessions)
end
function occupant_mt:get_presence(real_jid)
return self.sessions[real_jid or self.jid]
end
return {
new = new_occupant;
copy = copy_occupant;
mt = occupant_mt;
}