Diff

mod_mam/mod_mam.lua @ 1324:853a382c9bd6

mod_turncredentials: Advertise the XEP-0215 feature (thanks Gryffus)
author Kim Alvefur <zash@zash.se>
date Fri, 28 Feb 2014 15:36:06 +0100
parent 1187:d677d1807bb0
child 1325:b21236b6b8d8
line wrap: on
line diff
--- a/mod_mam/mod_mam.lua	Wed Feb 26 13:08:47 2014 -0800
+++ b/mod_mam/mod_mam.lua	Fri Feb 28 15:36:06 2014 +0100
@@ -1,9 +1,9 @@
 -- XEP-0313: Message Archive Management for Prosody
--- Copyright (C) 2011-2012 Kim Alvefur
+-- Copyright (C) 2011-2014 Kim Alvefur
 --
 -- This file is MIT/X11 licensed.
 
-local xmlns_mam     = "urn:xmpp:mam:tmp";
+local xmlns_mam     = "urn:xmpp:mam:0" or ":1";
 local xmlns_delay   = "urn:xmpp:delay";
 local xmlns_forward = "urn:xmpp:forward:0";
 
@@ -16,6 +16,7 @@
 local jid_bare = require "util.jid".bare;
 local jid_split = require "util.jid".split;
 local jid_prep = require "util.jid".prep;
+local dataform = require "util.dataforms".new;
 local host = module.host;
 
 local rm_load_roster = require "core.rostermanager".load_roster;
@@ -61,18 +62,37 @@
 	end
 end);
 
+local query_form = dataform {
+	{ name = "FORM_TYPE"; type = "hidden"; value = "urn:xmpp:mam:0"; };
+	{ name = "with"; type = "jid-single"; };
+	{ name = "start"; type = "text-single" };
+	{ name = "end"; type = "text-single"; };
+};
+
+-- Serve form
+module:hook("iq-get/self/"..xmlns_mam..":query", function(event)
+	local origin, stanza = event.origin, event.stanza;
+	return origin.send(st.reply(stanza):add_child(query_form:form()));
+end);
+
 -- Handle archive queries
-module:hook("iq-get/self/"..xmlns_mam..":query", function(event)
+module:hook("iq-set/self/"..xmlns_mam..":query", function(event)
 	local origin, stanza = event.origin, event.stanza;
 	local query = stanza.tags[1];
 	local qid = query.attr.queryid;
 
 	-- Search query parameters
-	local qwith = query:get_child_text("with");
-	local qstart = query:get_child_text("start");
-	local qend = query:get_child_text("end");
-	module:log("debug", "Archive query, id %s with %s from %s until %s)",
-		tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now");
+	local qwith, qstart, qend;
+	local form = query:get_child("x", "jabber:x:data");
+	if form then
+		local err;
+		form, err = query_form:data(form);
+		if err then
+			return origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err))))
+		end
+		qwith, qstart, qend = form["with"], form["start"], form["end"];
+		qwith = qwith and jid_bare(qwith);
+	end
 
 	if qstart or qend then -- Validate timestamps
 		local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend))
@@ -83,14 +103,8 @@
 		qstart, qend = vstart, vend;
 	end
 
-	if qwith then -- Validate the 'with' jid
-		local pwith = qwith and jid_prep(qwith);
-		if pwith and not qwith then -- it failed prepping
-			origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid JID"))
-			return true
-		end
-		qwith = jid_bare(pwith);
-	end
+	module:log("debug", "Archive query, id %s with %s from %s until %s)",
+		tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now");
 
 	-- RSM stuff
 	local qset = rsm.get(query);
@@ -116,7 +130,7 @@
 	local count = err;
 
 	-- Wrap it in stuff and deliver
-	local first, last;
+	local first_id, last_id, first_time, last_time;
 	for id, item, when in data do
 		local fwd_st = st.message{ to = origin.full_jid }
 			:tag("result", { xmlns = xmlns_mam, queryid = qid, id = id })
@@ -129,18 +143,27 @@
 		item.attr.xmlns = "jabber:client";
 		fwd_st:add_child(item);
 
-		if not first then first = id; end
-		last = id;
+		if not first_id then
+			first_id = id;
+			first_time = when;
+		end
+		last_id = id;
+		last_time = when;
 
 		origin.send(fwd_st);
 	end
 	-- That's all folks!
 	module:log("debug", "Archive query %s completed", tostring(qid));
 
-	if reverse then first, last = last, first; end
+	if reverse then
+		first_id, last_id, first_time, last_time =
+		last_id, first_id, last_time, first_time;
+	end
 	return origin.send(st.reply(stanza)
-		:query(xmlns_mam):add_child(rsm.generate {
-			first = first, last = last, count = count }));
+		:query(xmlns_mam)
+			:add_child(query_form:form({ start = timestamp(first_time), ["end"] = timestamp(last_time), with = qwith  }))
+			:add_child(rsm.generate {
+				first = first_id, last = last_id, count = count }));
 end);
 
 local function has_in_roster(user, who)