diff options
-rw-r--r-- | core/componentmanager.lua | 4 | ||||
-rw-r--r-- | core/modulemanager.lua | 57 | ||||
-rw-r--r-- | core/stanza_router.lua | 7 | ||||
-rw-r--r-- | plugins/muc/muc.lib.lua | 58 |
4 files changed, 79 insertions, 47 deletions
diff --git a/core/componentmanager.lua b/core/componentmanager.lua index 2d292c8f..833b1fc0 100644 --- a/core/componentmanager.lua +++ b/core/componentmanager.lua @@ -67,6 +67,7 @@ function handle_stanza(origin, stanza) component(origin, stanza, hosts[host]); else log("error", "Component manager recieved a stanza for a non-existing component: "..tostring(stanza)); + default_component_handler(origin, stanza); end end @@ -113,6 +114,7 @@ end function deregister_component(host) if components[host] then + modulemanager.unload(host, "tls"); modulemanager.unload(host, "dialback"); hosts[host].connected = nil; local host_config = configmanager.getconfig()[host]; @@ -121,7 +123,7 @@ function deregister_component(host) components[host] = default_component_handler; else -- Component not in config, or disabled, remove - hosts[host] = nil; + hosts[host] = nil; -- FIXME do proper unload of all modules and other cleanup before removing components[host] = nil; end -- remove from disco_items diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 312ca738..88d07f43 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -65,9 +65,11 @@ function load_modules_for_host(host) end -- Load auto-loaded modules for this host - for _, module in ipairs(autoload_modules) do - if not disabled_set[module] then - load(host, module); + if hosts[host].type == "local" then + for _, module in ipairs(autoload_modules) do + if not disabled_set[module] then + load(host, module); + end end end @@ -104,7 +106,6 @@ function load(host, module_name, config) if not modulemap[host] then modulemap[host] = {}; - hosts[host].modules = modulemap[host]; end if modulemap[host][module_name] then @@ -127,29 +128,39 @@ function load(host, module_name, config) local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); setfenv(mod, pluginenv); - if not hosts[host] then hosts[host] = { type = "component", host = host, connected = false, s2sout = {} }; end - - local success, ret = pcall(mod); - if not success then - log("error", "Error initialising module '%s': %s", module_name or "nil", ret or "nil"); - return nil, ret; + if not hosts[host] then + local create_component = _G.require "core.componentmanager".create_component; + hosts[host] = create_component(host); + hosts[host].connected = false; + log("debug", "Created new component: %s", host); end + hosts[host].modules = modulemap[host]; + modulemap[host][module_name] = pluginenv; - if module_has_method(pluginenv, "load") then - local ok, err = call_module_method(pluginenv, "load"); - if (not ok) and err then - log("warn", "Error loading module '%s' on '%s': %s", module_name, host, err); + local success, err = pcall(mod); + if success then + if module_has_method(pluginenv, "load") then + success, err = call_module_method(pluginenv, "load"); + if not success then + log("warn", "Error loading module '%s' on '%s': %s", module_name, host, err or "nil"); + end end - end - -- Use modified host, if the module set one - modulemap[api_instance.host][module_name] = pluginenv; - - if api_instance.host == "*" and host ~= "*" then - api_instance:set_global(); + -- Use modified host, if the module set one + if api_instance.host == "*" and host ~= "*" then + modulemap[host][module_name] = nil; + modulemap["*"][module_name] = pluginenv; + api_instance:set_global(); + end + else + log("error", "Error initializing module '%s' on '%s': %s", module_name, host, err or "nil"); + end + if success then + return true; + else -- load failed, unloading + unload(api_instance.host, module_name); + return nil, err; end - - return true; end function get_module(host, name) @@ -170,7 +181,6 @@ function unload(host, name, ...) log("warn", "Non-fatal error unloading module '%s' on '%s': %s", name, host, err); end end - modulemap[host][name] = nil; local params = handler_table:get(host, name); -- , {module.host, origin_type, tag, xmlns} for _, param in pairs(params or NULL) do local handlers = stanza_handlers:get(param[1], param[2], param[3], param[4]); @@ -187,6 +197,7 @@ function unload(host, name, ...) end end hooks:remove(host, name); + modulemap[host][name] = nil; return true; end diff --git a/core/stanza_router.lua b/core/stanza_router.lua index ef4f3695..00c37ed7 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -29,13 +29,10 @@ function core_process_stanza(origin, stanza) -- TODO verify validity of stanza (as well as JID validity) if stanza.attr.type == "error" and #stanza.tags == 0 then return; end -- TODO invalid stanza, log if stanza.name == "iq" then - local can_reply = stanza.attr.type == "set" or stanza.attr.type == "get" - local missing_id = not stanza.attr.id; - if can_reply and (#stanza.tags ~= 1 or missing_id) then + if not stanza.attr.id then stanza.attr.id = ""; end -- COMPAT Jabiru doesn't send the id attribute on roster requests + if (stanza.attr.type == "set" or stanza.attr.type == "get") and (#stanza.tags ~= 1) then origin.send(st.error_reply(stanza, "modify", "bad-request")); return; - elseif missing_id then - return; end end diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index 93706b07..7a8e3c8c 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -106,7 +106,7 @@ function room_mt:get_default_role(affiliation) end end -function room_mt:broadcast_presence(stanza, code, nick) +function room_mt:broadcast_presence(stanza, sid, code, nick) stanza = get_filtered_presence(stanza); local occupant = self._occupants[stanza.attr.from]; stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) @@ -118,10 +118,8 @@ function room_mt:broadcast_presence(stanza, code, nick) local me = self._occupants[stanza.attr.from]; if me then stanza:tag("status", {code='110'}); - for jid in pairs(me.sessions) do - stanza.attr.to = jid; - self:route_stanza(stanza); - end + stanza.attr.to = sid; + self:route_stanza(stanza); end end function room_mt:broadcast_message(stanza, historic) @@ -217,19 +215,26 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc if current_nick then log("debug", "%s leaving %s", current_nick, room); local occupant = self._occupants[current_nick]; - local old_session = occupant.sessions[from]; local new_jid = next(occupant.sessions); if new_jid == from then new_jid = next(occupant.sessions, new_jid); end if new_jid then + local jid = occupant.jid; occupant.jid = new_jid; occupant.sessions[from] = nil; - local pr = st.clone(occupant[new_jid]) - :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) - :tag("item", {affiliation=occupant.affiliation, role=occupant.role}); - self:broadcast_except_nick(pr, current_nick); + pr.attr.to = from; + pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) + :tag("item", {affiliation=occupant.affiliation, role='none'}):up() + :tag("status", {code='110'}); + self:route_stanza(pr); + if jid ~= new_jid then + pr = st.clone(occupant.sessions[new_jid]) + :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) + :tag("item", {affiliation=occupant.affiliation, role=occupant.role}); + self:broadcast_except_nick(pr, current_nick); + end else occupant.role = 'none'; - self:broadcast_presence(pr); + self:broadcast_presence(pr, from); self._occupants[current_nick] = nil; end self._jid_nick[from] = nil; @@ -240,9 +245,11 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc if current_nick == to then -- simple presence log("debug", "%s broadcasted presence", current_nick); self._occupants[current_nick].sessions[from] = pr; - self:broadcast_presence(pr); + self:broadcast_presence(pr, from); else -- change nick - if self._occupants[to] then + local occupant = self._occupants[current_nick]; + local is_multisession = next(occupant, next(occupant)); + if self._occupants[to] or is_multisession then log("debug", "%s couldn't change nick", current_nick); local reply = st.error_reply(stanza, "cancel", "conflict"):up(); reply.tags[1].attr.code = "409"; @@ -253,13 +260,13 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc if to_nick then log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to); local p = st.presence({type='unavailable', from=current_nick}); - self:broadcast_presence(p, '303', to_nick); + self:broadcast_presence(p, from, '303', to_nick); self._occupants[current_nick] = nil; self._occupants[to] = data; self._jid_nick[from] = to; pr.attr.from = to; self._occupants[to].sessions[from] = pr; - self:broadcast_presence(pr); + self:broadcast_presence(pr, from); else --TODO malformed-jid end @@ -273,8 +280,12 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc --end else -- enter room local new_nick = to; + local is_merge; if self._occupants[to] then - new_nick = nil; + if jid_bare(from) ~= jid_bare(self._occupants[to].jid) then + new_nick = nil; + end + is_merge = true; end if not new_nick then log("debug", "%s couldn't join due to nick conflict: %s", from, to); @@ -289,11 +300,22 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc local affiliation = self:get_affiliation(from); local role = self:get_default_role(affiliation) if role then -- new occupant - self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}}; + if not is_merge then + self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}}; + else + self._occupants[to].sessions[from] = get_filtered_presence(stanza); + end self._jid_nick[from] = to; self:send_occupant_list(from); pr.attr.from = to; - self:broadcast_presence(pr); + if not is_merge then + self:broadcast_presence(pr, from); + else + pr.attr.to = from; + self:route_stanza(pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) + :tag("item", {affiliation=affiliation, role=role}):up() + :tag("status", {code='110'})); + end self:send_history(from); else -- banned local reply = st.error_reply(stanza, "auth", "forbidden"):up(); |