mod_posix: Move everything to util.startup
This allows greater control over the order of events.
Notably, the internal ordering between daemonization, initialization of
libunbound and setup of signal handling is sensitive.
libunbound starts a separate thread for processing DNS requests.
If this thread is started before signal handling has been set up, it
will not inherit the signal handlers and instead behave as it would have
before signal handlers were set up, i.e. cause the whole process to
immediately exit.
libunbound is usually initialized on the first DNS request, usually
triggered by an outgoing s2s connection attempt.
If daemonization happens before signals have been set up, signals may
not be processed at all.
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local groups;
local members;
local datamanager = require "prosody.util.datamanager";
local jid_prep = require "prosody.util.jid".prep;
local module_host = module:get_host();
function inject_roster_contacts(event)
local username, host= event.username, event.host;
--module:log("debug", "Injecting group members to roster");
local bare_jid = username.."@"..host;
if not members[bare_jid] and not members[false] then return; end -- Not a member of any groups
local roster = event.roster;
local function import_jids_to_roster(group_name)
for jid in pairs(groups[group_name]) do
-- Add them to roster
--module:log("debug", "processing jid %s in group %s", jid, group_name);
if jid ~= bare_jid then
if not roster[jid] then roster[jid] = {}; end
roster[jid].subscription = "both";
if groups[group_name][jid] then
roster[jid].name = groups[group_name][jid];
end
if not roster[jid].groups then
roster[jid].groups = { [group_name] = true };
end
roster[jid].groups[group_name] = true;
roster[jid].persist = false;
end
end
end
-- Find groups this JID is a member of
if members[bare_jid] then
for _, group_name in ipairs(members[bare_jid]) do
--module:log("debug", "Importing group %s", group_name);
import_jids_to_roster(group_name);
end
end
-- Import public groups
if members[false] then
for _, group_name in ipairs(members[false]) do
--module:log("debug", "Importing group %s", group_name);
import_jids_to_roster(group_name);
end
end
if roster[false] then
roster[false].version = true;
end
end
function remove_virtual_contacts(username, host, datastore, data)
if host == module_host and datastore == "roster" then
local new_roster = {};
for jid, contact in pairs(data) do
if contact.persist ~= false then
new_roster[jid] = contact;
end
end
if new_roster[false] then
new_roster[false].version = nil; -- Version is void
end
return username, host, datastore, new_roster;
end
return username, host, datastore, data;
end
function module.load()
local groups_file = module:get_option_path("groups_file", nil, "config");
if not groups_file then return; end
module:hook("roster-load", inject_roster_contacts);
datamanager.add_callback(remove_virtual_contacts);
groups = { default = {} };
members = { };
local curr_group = "default";
for line in io.lines(groups_file) do
if line:match("^%s*%[.-%]%s*$") then
curr_group = line:match("^%s*%[(.-)%]%s*$");
if curr_group:match("^%+") then
curr_group = curr_group:gsub("^%+", "");
if not members[false] then
members[false] = {};
end
members[false][#members[false]+1] = curr_group; -- Is a public group
end
module:log("debug", "New group: %s", curr_group);
groups[curr_group] = groups[curr_group] or {};
else
-- Add JID
local entryjid, name = line:match("([^=]*)=?(.*)");
module:log("debug", "entryjid = '%s', name = '%s'", entryjid, name);
local jid;
jid = jid_prep(entryjid:match("%S+"));
if jid then
module:log("debug", "New member of %s: %s", curr_group, jid);
groups[curr_group][jid] = name or false;
members[jid] = members[jid] or {};
members[jid][#members[jid]+1] = curr_group;
elseif entryjid:match("%S") then
module:log("warn", "Invalid JID: %q", entryjid);
end
end
end
module:log("info", "Groups loaded successfully");
end
function module.unload()
datamanager.remove_callback(remove_virtual_contacts);
end
-- Public for other modules to access
function group_contains(group_name, jid)
return groups[group_name][jid];
end