Changeset

1995:03ecc636af1e

Merge with trunk.
author Waqas Hussain <waqas20@gmail.com>
date Sun, 18 Oct 2009 05:19:40 +0500
parents 1994:9cc9b096c8f5 (diff) 1984:f2b1f89e1d7c (current diff)
children 1996:3e6b36c6d7b7
files
diffstat 4 files changed, 79 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/core/componentmanager.lua	Sat Oct 17 19:47:01 2009 +0100
+++ b/core/componentmanager.lua	Sun Oct 18 05:19:40 2009 +0500
@@ -67,6 +67,7 @@
 		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 @@
 
 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 @@
 			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
--- a/core/modulemanager.lua	Sat Oct 17 19:47:01 2009 +0100
+++ b/core/modulemanager.lua	Sun Oct 18 05:19:40 2009 +0500
@@ -65,9 +65,11 @@
 	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 @@
 	
 	if not modulemap[host] then
 		modulemap[host] = {};
-		hosts[host].modules = modulemap[host];
 	end
 	
 	if modulemap[host][module_name] then
@@ -127,29 +128,39 @@
 	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
-		
-	return true;
+	if success then
+		return true;
+	else -- load failed, unloading
+		unload(api_instance.host, module_name);
+		return nil, err;
+	end
 end
 
 function get_module(host, name)
@@ -170,7 +181,6 @@
 			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 @@
 		end
 	end
 	hooks:remove(host, name);
+	modulemap[host][name] = nil;
 	return true;
 end
 
--- a/core/stanza_router.lua	Sat Oct 17 19:47:01 2009 +0100
+++ b/core/stanza_router.lua	Sun Oct 18 05:19:40 2009 +0500
@@ -29,13 +29,10 @@
 	-- 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
 
--- a/plugins/muc/muc.lib.lua	Sat Oct 17 19:47:01 2009 +0100
+++ b/plugins/muc/muc.lib.lua	Sun Oct 18 05:19:40 2009 +0500
@@ -106,7 +106,7 @@
 	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 @@
 	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 @@
 			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 @@
 					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 @@
 							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 @@
 				--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 @@
 					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();