Mercurial > prosody-modules
comparison 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 |
| parents | d677d1807bb0 |
| children | b21236b6b8d8 |
comparison
equal
deleted
inserted
replaced
| 1323:c84ff82658cb | 1324:853a382c9bd6 |
|---|---|
| 1 -- XEP-0313: Message Archive Management for Prosody | 1 -- XEP-0313: Message Archive Management for Prosody |
| 2 -- Copyright (C) 2011-2012 Kim Alvefur | 2 -- Copyright (C) 2011-2014 Kim Alvefur |
| 3 -- | 3 -- |
| 4 -- This file is MIT/X11 licensed. | 4 -- This file is MIT/X11 licensed. |
| 5 | 5 |
| 6 local xmlns_mam = "urn:xmpp:mam:tmp"; | 6 local xmlns_mam = "urn:xmpp:mam:0" or ":1"; |
| 7 local xmlns_delay = "urn:xmpp:delay"; | 7 local xmlns_delay = "urn:xmpp:delay"; |
| 8 local xmlns_forward = "urn:xmpp:forward:0"; | 8 local xmlns_forward = "urn:xmpp:forward:0"; |
| 9 | 9 |
| 10 local st = require "util.stanza"; | 10 local st = require "util.stanza"; |
| 11 local rsm = module:require "rsm"; | 11 local rsm = module:require "rsm"; |
| 14 local set_prefs, get_prefs = prefs.set, prefs.get; | 14 local set_prefs, get_prefs = prefs.set, prefs.get; |
| 15 local prefs_to_stanza, prefs_from_stanza = prefsxml.tostanza, prefsxml.fromstanza; | 15 local prefs_to_stanza, prefs_from_stanza = prefsxml.tostanza, prefsxml.fromstanza; |
| 16 local jid_bare = require "util.jid".bare; | 16 local jid_bare = require "util.jid".bare; |
| 17 local jid_split = require "util.jid".split; | 17 local jid_split = require "util.jid".split; |
| 18 local jid_prep = require "util.jid".prep; | 18 local jid_prep = require "util.jid".prep; |
| 19 local dataform = require "util.dataforms".new; | |
| 19 local host = module.host; | 20 local host = module.host; |
| 20 | 21 |
| 21 local rm_load_roster = require "core.rostermanager".load_roster; | 22 local rm_load_roster = require "core.rostermanager".load_roster; |
| 22 | 23 |
| 23 local getmetatable = getmetatable; | 24 local getmetatable = getmetatable; |
| 59 end | 60 end |
| 60 return origin.send(st.reply(stanza)); | 61 return origin.send(st.reply(stanza)); |
| 61 end | 62 end |
| 62 end); | 63 end); |
| 63 | 64 |
| 65 local query_form = dataform { | |
| 66 { name = "FORM_TYPE"; type = "hidden"; value = "urn:xmpp:mam:0"; }; | |
| 67 { name = "with"; type = "jid-single"; }; | |
| 68 { name = "start"; type = "text-single" }; | |
| 69 { name = "end"; type = "text-single"; }; | |
| 70 }; | |
| 71 | |
| 72 -- Serve form | |
| 73 module:hook("iq-get/self/"..xmlns_mam..":query", function(event) | |
| 74 local origin, stanza = event.origin, event.stanza; | |
| 75 return origin.send(st.reply(stanza):add_child(query_form:form())); | |
| 76 end); | |
| 77 | |
| 64 -- Handle archive queries | 78 -- Handle archive queries |
| 65 module:hook("iq-get/self/"..xmlns_mam..":query", function(event) | 79 module:hook("iq-set/self/"..xmlns_mam..":query", function(event) |
| 66 local origin, stanza = event.origin, event.stanza; | 80 local origin, stanza = event.origin, event.stanza; |
| 67 local query = stanza.tags[1]; | 81 local query = stanza.tags[1]; |
| 68 local qid = query.attr.queryid; | 82 local qid = query.attr.queryid; |
| 69 | 83 |
| 70 -- Search query parameters | 84 -- Search query parameters |
| 71 local qwith = query:get_child_text("with"); | 85 local qwith, qstart, qend; |
| 72 local qstart = query:get_child_text("start"); | 86 local form = query:get_child("x", "jabber:x:data"); |
| 73 local qend = query:get_child_text("end"); | 87 if form then |
| 74 module:log("debug", "Archive query, id %s with %s from %s until %s)", | 88 local err; |
| 75 tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now"); | 89 form, err = query_form:data(form); |
| 90 if err then | |
| 91 return origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err)))) | |
| 92 end | |
| 93 qwith, qstart, qend = form["with"], form["start"], form["end"]; | |
| 94 qwith = qwith and jid_bare(qwith); | |
| 95 end | |
| 76 | 96 |
| 77 if qstart or qend then -- Validate timestamps | 97 if qstart or qend then -- Validate timestamps |
| 78 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) | 98 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) |
| 79 if (qstart and not vstart) or (qend and not vend) then | 99 if (qstart and not vstart) or (qend and not vend) then |
| 80 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid timestamp")) | 100 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid timestamp")) |
| 81 return true | 101 return true |
| 82 end | 102 end |
| 83 qstart, qend = vstart, vend; | 103 qstart, qend = vstart, vend; |
| 84 end | 104 end |
| 85 | 105 |
| 86 if qwith then -- Validate the 'with' jid | 106 module:log("debug", "Archive query, id %s with %s from %s until %s)", |
| 87 local pwith = qwith and jid_prep(qwith); | 107 tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now"); |
| 88 if pwith and not qwith then -- it failed prepping | |
| 89 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid JID")) | |
| 90 return true | |
| 91 end | |
| 92 qwith = jid_bare(pwith); | |
| 93 end | |
| 94 | 108 |
| 95 -- RSM stuff | 109 -- RSM stuff |
| 96 local qset = rsm.get(query); | 110 local qset = rsm.get(query); |
| 97 local qmax = m_min(qset and qset.max or default_max_items, max_max_items); | 111 local qmax = m_min(qset and qset.max or default_max_items, max_max_items); |
| 98 local reverse = qset and qset.before or false; | 112 local reverse = qset and qset.before or false; |
| 114 return origin.send(st.error_reply(stanza, "cancel", "internal-server-error", err)); | 128 return origin.send(st.error_reply(stanza, "cancel", "internal-server-error", err)); |
| 115 end | 129 end |
| 116 local count = err; | 130 local count = err; |
| 117 | 131 |
| 118 -- Wrap it in stuff and deliver | 132 -- Wrap it in stuff and deliver |
| 119 local first, last; | 133 local first_id, last_id, first_time, last_time; |
| 120 for id, item, when in data do | 134 for id, item, when in data do |
| 121 local fwd_st = st.message{ to = origin.full_jid } | 135 local fwd_st = st.message{ to = origin.full_jid } |
| 122 :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }) | 136 :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }) |
| 123 :tag("forwarded", { xmlns = xmlns_forward }) | 137 :tag("forwarded", { xmlns = xmlns_forward }) |
| 124 :tag("delay", { xmlns = xmlns_delay, stamp = timestamp(when) }):up(); | 138 :tag("delay", { xmlns = xmlns_delay, stamp = timestamp(when) }):up(); |
| 127 item = st.deserialize(item); | 141 item = st.deserialize(item); |
| 128 end | 142 end |
| 129 item.attr.xmlns = "jabber:client"; | 143 item.attr.xmlns = "jabber:client"; |
| 130 fwd_st:add_child(item); | 144 fwd_st:add_child(item); |
| 131 | 145 |
| 132 if not first then first = id; end | 146 if not first_id then |
| 133 last = id; | 147 first_id = id; |
| 148 first_time = when; | |
| 149 end | |
| 150 last_id = id; | |
| 151 last_time = when; | |
| 134 | 152 |
| 135 origin.send(fwd_st); | 153 origin.send(fwd_st); |
| 136 end | 154 end |
| 137 -- That's all folks! | 155 -- That's all folks! |
| 138 module:log("debug", "Archive query %s completed", tostring(qid)); | 156 module:log("debug", "Archive query %s completed", tostring(qid)); |
| 139 | 157 |
| 140 if reverse then first, last = last, first; end | 158 if reverse then |
| 159 first_id, last_id, first_time, last_time = | |
| 160 last_id, first_id, last_time, first_time; | |
| 161 end | |
| 141 return origin.send(st.reply(stanza) | 162 return origin.send(st.reply(stanza) |
| 142 :query(xmlns_mam):add_child(rsm.generate { | 163 :query(xmlns_mam) |
| 143 first = first, last = last, count = count })); | 164 :add_child(query_form:form({ start = timestamp(first_time), ["end"] = timestamp(last_time), with = qwith })) |
| 165 :add_child(rsm.generate { | |
| 166 first = first_id, last = last_id, count = count })); | |
| 144 end); | 167 end); |
| 145 | 168 |
| 146 local function has_in_roster(user, who) | 169 local function has_in_roster(user, who) |
| 147 local roster = rm_load_roster(user, host); | 170 local roster = rm_load_roster(user, host); |
| 148 module:log("debug", "%s has %s in roster? %s", user, who, roster[who] and "yes" or "no"); | 171 module:log("debug", "%s has %s in roster? %s", user, who, roster[who] and "yes" or "no"); |
