plugins/mod_pep.lua

changeset 2329
5839f303addf
parent 2328
814eaba0c777
child 2384
7bec10f26082
child 2923
b7049746bd29
--- a/plugins/mod_pep.lua	Sat Dec 05 09:43:53 2009 -0800
+++ b/plugins/mod_pep.lua	Sat Dec 05 10:26:43 2009 -0800
@@ -37,7 +37,14 @@
 module:add_identity("pubsub", "pep", "Prosody");
 module:add_feature("http://jabber.org/protocol/pubsub#publish");
 
-local function publish(session, node, item)
+local function subscription_presence(user_bare, recipient)
+	local recipient_bare = jid_bare(recipient);
+	if (recipient_bare == user_bare) then return true end
+	local item = load_roster(jid_split(user_bare))[recipient_bare];
+	return item and (item.subscription == 'from' or item.subscription == 'both');
+end
+
+local function publish(session, node, id, item)
 	item.attr.xmlns = nil;
 	local disable = #item.tags ~= 1 or #item.tags[1] == 0;
 	if #item.tags == 0 then item.name = "retract"; end
@@ -58,9 +65,9 @@
 		end
 	else
 		if not user_data then user_data = {}; data[bare] = user_data; end
-		user_data[node] = stanza;
+		user_data[node] = {id or "1", item};
 	end
-	
+
 	-- broadcast
 	for recipient, notify in pairs(recipients[bare] or NULL) do
 		if notify[node] then
@@ -74,10 +81,14 @@
 	local notify = recipients[user] and recipients[user][recipient];
 	if d and notify then
 		for node in pairs(notify) do
-			local message = d[node];
-			if message then
-				message.attr.to = recipient;
-				session.send(message);
+			if d[node] then
+				local id, item = unpack(d[node]);
+				session.send(st.message({from=user, to=recipient, type='headline'})
+					:tag('event', {xmlns='http://jabber.org/protocol/pubsub#event'})
+						:tag('items', {node=node})
+							:add_child(item)
+						:up()
+					:up());
 			end
 		end
 	end
@@ -106,11 +117,9 @@
 module:hook("presence/bare", function(event)
 	-- inbound presence to bare JID recieved
 	local origin, stanza = event.origin, event.stanza;
-	
 	local user = stanza.attr.to or (origin.username..'@'..origin.host);
-	local bare = jid_bare(stanza.attr.from);
-	local item = load_roster(jid_split(user))[bare];
-	if not stanza.attr.to or (item and (item.subscription == 'from' or item.subscription == 'both')) then
+
+	if not stanza.attr.to or subscription_presence(user, stanza.attr.from) then
 		local recipient = stanza.attr.from;
 		local current = recipients[user] and recipients[user][recipient];
 		local hash = get_caps_hash_from_presence(stanza, current);
@@ -135,19 +144,63 @@
 
 module:hook("iq/bare/http://jabber.org/protocol/pubsub:pubsub", function(event)
 	local session, stanza = event.origin, event.stanza;
+	local payload = stanza.tags[1];
+
 	if stanza.attr.type == 'set' and (not stanza.attr.to or jid_bare(stanza.attr.from) == stanza.attr.to) then
-		local payload = stanza.tags[1];
-		if payload.name == 'pubsub' then -- <pubsub xmlns='http://jabber.org/protocol/pubsub'>
+		payload = payload.tags[1];
+		if payload and (payload.name == 'publish' or payload.name == 'retract') and payload.attr.node then -- <publish node='http://jabber.org/protocol/tune'>
+			local node = payload.attr.node;
+			payload = payload.tags[1];
+			if payload and payload.name == "item" then -- <item>
+				local id = payload.attr.id;
+				session.send(st.reply(stanza));
+				publish(session, node, id, st.clone(payload));
+				return true;
+			end
+		end
+	elseif stanza.attr.type == 'get' then
+		local user = stanza.attr.to and jid_bare(stanza.attr.to) or session.username..'@'..session.host;
+		if subscription_presence(user, stanza.attr.from) then
+			local user_data = data[user];
+			local node, requested_id;
 			payload = payload.tags[1];
-			if payload and (payload.name == 'publish' or payload.name == 'retract') and payload.attr.node then -- <publish node='http://jabber.org/protocol/tune'>
-				local node = payload.attr.node;
-				payload = payload.tags[1];
-				if payload and payload.name == "item" then -- <item>
-					session.send(st.reply(stanza));
-					publish(session, node, st.clone(payload));
+			if payload and payload.name == 'items' then
+				node = payload.attr.node;
+				local item = payload.tags[1];
+				if item and item.name == "item" then
+					requested_id = item.attr.id;
+				end
+			end
+			if node and user_data and user_data[node] then -- Send the last item
+				local id, item = unpack(user_data[node]);
+				if not requested_id or id == requested_id then
+					local stanza = st.reply(stanza)
+						:tag('pubsub', {xmlns='http://jabber.org/protocol/pubsub'})
+							:tag('items', {node=node})
+								:add_child(item)
+							:up()
+						:up();
+					session.send(stanza);
+					return true;
+				else -- requested item doesn't exist
+					local stanza = st.reply(stanza)
+						:tag('pubsub', {xmlns='http://jabber.org/protocol/pubsub'})
+							:tag('items', {node=node})
+						:up();
+					session.send(stanza);
 					return true;
 				end
+			elseif node then -- node doesn't exist
+				session.send(st.error_reply(stanza, 'cancel', 'item-not-found'));
+				return true;
+			else --invalid request
+				session.send(st.error_reply(stanza, 'modify', 'bad-request'));
+				return true;
 			end
+		else --no presence subscription
+			session.send(st.error_reply(stanza, 'auth', 'not-authorized')
+				:tag('presence-subscription-required', {xmlns='http://jabber.org/protocol/pubsub#errors'}));
+			return true;
 		end
 	end
 end);

mercurial