Changeset

177:606c433955e7

Bug fixes and checks for presence subscriptions, etc
author Waqas Hussain <waqas20@gmail.com>
date Sun, 26 Oct 2008 00:22:18 +0500
parents 176:e5cd2a03891d
children 178:8315cf03f304
files core/rostermanager.lua core/stanza_router.lua plugins/mod_roster.lua util/datamanager.lua
diffstat 4 files changed, 64 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/core/rostermanager.lua	Sat Oct 25 21:16:08 2008 +0500
+++ b/core/rostermanager.lua	Sun Oct 26 00:22:18 2008 +0500
@@ -49,7 +49,7 @@
 end
 
 function roster_push(username, host, jid)
-	if hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster then
+	if jid ~= "pending" and hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster then
 		local item = hosts[host].sessions[username].roster[jid];
 		local stanza = st.iq({type="set"});
 		stanza:tag("query", {xmlns = "jabber:iq:roster"});
@@ -74,19 +74,23 @@
 end
 
 function load_roster(username, host)
+	log("debug", "load_roster: asked for: "..username.."@"..host);
 	if hosts[host] and hosts[host].sessions[username] then
 		local roster = hosts[host].sessions[username].roster;
 		if not roster then
+			log("debug", "load_roster: loading for new user: "..username.."@"..host);
 			roster = datamanager.load(username, host, "roster") or {};
 			hosts[host].sessions[username].roster = roster;
 		end
 		return roster;
 	end
 	-- Attempt to load roster for non-loaded user
+	log("debug", "load_roster: loading for offline user: "..username.."@"..host);
 	return datamanager.load(username, host, "roster") or {};
 end
 
 function save_roster(username, host)
+	log("debug", "save_roster: saving roster for "..username.."@"..host);
 	if hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster then
 		return datamanager.store(username, host, "roster", hosts[host].sessions[username].roster);
 	end
@@ -159,7 +163,7 @@
 
 function is_contact_pending_in(username, host, jid)
 	local roster = load_roster(username, host);
-	return roster.pending or roster.pending[jid];
+	return roster.pending and roster.pending[jid];
 end
 function set_contact_pending_in(username, host, jid, pending)
 	local roster = load_roster(username, host);
@@ -183,10 +187,11 @@
 		return true;
 	end
 	if not item then
-		item = {subscription = "none"};
+		item = {subscription = "none", groups = {}};
 		roster[jid] = item;
 	end
 	item.ask = "subscribe";
+	log("debug", "set_contact_pending_out: saving roster; set "..username.."@"..host..".roster["..jid.."].ask=subscribe");
 	return datamanager.store(username, host, "roster", roster);
 end
 function unsubscribe(username, host, jid)
@@ -211,7 +216,7 @@
 		if item.subscription == "none" then
 			item.subscription = "from";
 		else -- subscription == to
-			item.subsctiption = "both";
+			item.subscription = "both";
 		end
 		roster.pending[jid] = nil;
 		-- TODO maybe remove roster.pending if empty
--- a/core/stanza_router.lua	Sat Oct 25 21:16:08 2008 +0500
+++ b/core/stanza_router.lua	Sun Oct 26 00:22:18 2008 +0500
@@ -60,6 +60,12 @@
 	
 	if not to then
 		core_handle_stanza(origin, stanza);
+	elseif origin.type == "c2s" and stanza.name == "presence" and stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" then
+		local node, host = jid_split(stanza.attr.to);
+		local to_bare = node and (node.."@"..host) or host; -- bare JID
+		local from_node, from_host = jid_split(stanza.attr.from);
+		local from_bare = from_node and (from_node.."@"..from_host) or from_host; -- bare JID
+		handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare);
 	elseif hosts[to] and hosts[to].type == "local" then
 		core_handle_stanza(origin, stanza);
 	elseif stanza.name == "iq" and not select(3, jid_split(to)) then
@@ -196,75 +202,88 @@
 	return count;
 end
 
-function handle_outbound_presence_subscriptions(origin, stanza, from_bare, to_bare)
-	local node, host = jid_split(to_bare);
+function handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare)
+	local node, host = jid_split(from_bare);
+	local st_from, st_to = stanza.attr.from, stanza.attr.to;
+	stanza.attr.from, stanza.attr.to = from_bare, to_bare;
 	if stanza.attr.type == "subscribe" then
+		log("debug", "outbound subscribe from "..from_bare.." for "..to_bare);
 		-- 1. route stanza
 		-- 2. roster push (subscription = none, ask = subscribe)
-		if rostermanager.set_contact_pending_out(node, host, from_bare) then
-			rostermanager.roster_push(node, host, from_bare);
+		if rostermanager.set_contact_pending_out(node, host, to_bare) then
+			rostermanager.roster_push(node, host, to_bare);
 		end -- else file error
-		core_route_stanza(origin, st.presence({from=from_bare, to=to_bare, type="subscribe"}));
+		core_route_stanza(origin, stanza);
 	elseif stanza.attr.type == "unsubscribe" then
+		log("debug", "outbound unsubscribe from "..from_bare.." for "..to_bare);
 		-- 1. route stanza
 		-- 2. roster push (subscription = none or from)
-		if rostermanager.unsubscribe(node, host, from_bare) then
-			rostermanager.roster_push(node, host, from_bare); -- FIXME do roster push when roster has in fact not changed?
+		if rostermanager.unsubscribe(node, host, to_bare) then
+			rostermanager.roster_push(node, host, to_bare); -- FIXME do roster push when roster has in fact not changed?
 		end -- else file error
-		core_route_stanza(origin, st.presence({from=from_bare, to=to_bare, type="unsubscribe"}));
+		core_route_stanza(origin, stanza);
 	elseif stanza.attr.type == "subscribed" then
+		log("debug", "outbound subscribed from "..from_bare.." for "..to_bare);
 		-- 1. route stanza
 		-- 2. roster_push ()
 		-- 3. send_presence_of_available_resources
-		if rostermanager.subscribed(node, host, from_bare) then
-			rostermanager.roster_push(node, host, from_bare);
-			core_route_stanza(origin, st.presence({from=from_bare, to=to_bare, type="subscribed"}));
-			send_presence_of_available_resources(user, host, from_bare, origin);
+		if rostermanager.subscribed(node, host, to_bare) then
+			rostermanager.roster_push(node, host, to_bare);
+			core_route_stanza(origin, stanza);
+			send_presence_of_available_resources(node, host, to_bare, origin);
 		end
 	elseif stanza.attr.type == "unsubscribed" then
+		log("debug", "outbound unsubscribed from "..from_bare.." for "..to_bare);
 		-- 1. route stanza
 		-- 2. roster push (subscription = none or to)
-		if rostermanager.unsubscribed(node, host, from_bare) then
-			rostermanager.roster_push(node, host, from_bare);
-			core_route_stanza(origin, st.presence({from=from_bare, to=to_bare, type="unsubscribed"}));
+		if rostermanager.unsubscribed(node, host, to_bare) then
+			rostermanager.roster_push(node, host, to_bare);
+			core_route_stanza(origin, stanza);
 		end
 	end
+	stanza.attr.from, stanza.attr.to = st_from, st_to;
 end
 
 function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare)
 	local node, host = jid_split(to_bare);
+	local st_from, st_to = stanza.attr.from, stanza.attr.to;
+	stanza.attr.from, stanza.attr.to = from_bare, to_bare;
 	if stanza.attr.type == "probe" then
 		if rostermanager.is_contact_subscribed(node, host, from_bare) then
 			if 0 == send_presence_of_available_resources(node, host, from_bare, origin) then
 				-- TODO send last recieved unavailable presence (or we MAY do nothing, which is fine too)
 			end
 		else
-			send(origin, st.presence({from=to_bare, to=from_bare, type="unsubscribed"}));
+			core_route_stanza(origin, st.presence({from=to_bare, to=from_bare, type="unsubscribed"}));
 		end
 	elseif stanza.attr.type == "subscribe" then
+		log("debug", "inbound subscribe from "..from_bare.." for "..to_bare);
 		if rostermanager.is_contact_subscribed(node, host, from_bare) then
-			send(origin, st.presence({from=to_bare, to=from_bare, type="subscribed"})); -- already subscribed
+			core_route_stanza(origin, st.presence({from=to_bare, to=from_bare, type="subscribed"})); -- already subscribed
 		else
-			if not rostermanager.is_contact_pending(node, host, from_bare) then
-				if rostermanager.set_contact_pending(node, host, from_bare) then
-					sessionmanager.send_to_available_resources(node, host, st.presence({from=from_bare, type="subscribe"}));
+			if not rostermanager.is_contact_pending_in(node, host, from_bare) then
+				if rostermanager.set_contact_pending_in(node, host, from_bare) then
+					sessionmanager.send_to_available_resources(node, host, stanza);
 				end -- TODO else return error, unable to save
 			end
 		end
 	elseif stanza.attr.type == "unsubscribe" then
+		log("debug", "inbound unsubscribe from "..from_bare.." for "..to_bare);
 		if rostermanager.process_inbound_unsubscribe(node, host, from_bare) then
 			rostermanager.roster_push(node, host, from_bare);
 		end
 	elseif stanza.attr.type == "subscribed" then
+		log("debug", "inbound subscribed from "..from_bare.." for "..to_bare);
 		if rostermanager.process_inbound_subscription_approval(node, host, from_bare) then
 			rostermanager.roster_push(node, host, from_bare);
-			send_presence_of_available_resources(node, host, from_bare, origin);
 		end
 	elseif stanza.attr.type == "unsubscribed" then
+		log("debug", "inbound unsubscribed from "..from_bare.." for "..to_bare);
 		if rostermanager.process_inbound_subscription_approval(node, host, from_bare) then
 			rostermanager.roster_push(node, host, from_bare);
 		end
 	end -- discard any other type
+	stanza.attr.from, stanza.attr.to = st_from, st_to;
 end
 
 function core_route_stanza(origin, stanza)
--- a/plugins/mod_roster.lua	Sat Oct 25 21:16:08 2008 +0500
+++ b/plugins/mod_roster.lua	Sun Oct 26 00:22:18 2008 +0500
@@ -16,14 +16,16 @@
 					local roster = st.reply(stanza)
 								:query("jabber:iq:roster");
 					for jid in pairs(session.roster) do
-						roster:tag("item", {
-							jid = jid,
-							subscription = session.roster[jid].subscription,
-							ask = session.roster[jid].ask,
-							name = session.roster[jid].name,
-						});
-						for group in pairs(session.roster[jid].groups) do
-							roster:tag("group"):text(group):up();
+						if jid ~= "pending" then
+							roster:tag("item", {
+								jid = jid,
+								subscription = session.roster[jid].subscription,
+								ask = session.roster[jid].ask,
+								name = session.roster[jid].name,
+							});
+							for group in pairs(session.roster[jid].groups) do
+								roster:tag("group"):text(group):up();
+							end
 						end
 					end
 					send(session, roster);
@@ -32,7 +34,8 @@
 				elseif stanza.attr.type == "set" then
 					local query = stanza.tags[1];
 					if #query.tags == 1 and query.tags[1].name == "item"
-							and query.tags[1].attr.xmlns == "jabber:iq:roster" and query.tags[1].attr.jid then
+							and query.tags[1].attr.xmlns == "jabber:iq:roster" and query.tags[1].attr.jid
+							and query.tags[1].attr.jid ~= "pending" then
 						local item = query.tags[1];
 						local from_node, from_host = jid_split(stanza.attr.from);
 						local node, host, resource = jid_split(item.attr.jid);
--- a/util/datamanager.lua	Sat Oct 25 21:16:08 2008 +0500
+++ b/util/datamanager.lua	Sun Oct 26 00:22:18 2008 +0500
@@ -6,6 +6,7 @@
 local log = log;
 local io_open = io.open;
 local tostring = tostring;
+local error = error;
 
 module "datamanager"
 
@@ -49,6 +50,8 @@
           f:write(",\n")
         end
         f:write("}\n")
+      elseif type(o) == "boolean" then
+        f:write(o and "true" or "false");
       else
         error("cannot serialize a " .. type(o))
       end