Comparison

mod_mam_muc/mod_mam_muc.lua @ 1138:5c97ee75cadb

mod_mam_muc: Switch to iq-get hook and drop some indentation
author Kim Alvefur <zash@zash.se>
date Sat, 10 Aug 2013 21:05:38 +0200
parent 820:005037032d65
child 1139:b32d65e41755
comparison
equal deleted inserted replaced
1137:431627b07b9f 1138:5c97ee75cadb
27 -- TODO Should be possible to enforce it too 27 -- TODO Should be possible to enforce it too
28 28
29 local archive_store = "archive2"; 29 local archive_store = "archive2";
30 30
31 -- Handle archive queries 31 -- Handle archive queries
32 module:hook("iq/bare/"..xmlns_mam..":query", function(event) 32 module:hook("iq-get/bare/"..xmlns_mam..":query", function(event)
33 local origin, stanza = event.origin, event.stanza; 33 local origin, stanza = event.origin, event.stanza;
34 local room = jid_split(stanza.attr.to); 34 local room = jid_split(stanza.attr.to);
35 local query = stanza.tags[1]; 35 local query = stanza.tags[1];
36 36
37 local room_obj = hosts[module.host].modules.muc.rooms[jid_bare(stanza.attr.to)]; 37 local room_obj = hosts[module.host].modules.muc.rooms[jid_bare(stanza.attr.to)];
43 if room_obj._affiliations[from] == "outcast" 43 if room_obj._affiliations[from] == "outcast"
44 or room_obj._data.members_only and not room_obj._affiliations[from] then 44 or room_obj._data.members_only and not room_obj._affiliations[from] then
45 return -- FIXME unauth 45 return -- FIXME unauth
46 end 46 end
47 47
48 if stanza.attr.type == "get" then 48 local qid = query.attr.queryid;
49 local qid = query.attr.queryid; 49
50 50 -- Search query parameters
51 -- Search query parameters 51 local qwith = query:get_child_text("with");
52 local qwith = query:get_child_text("with"); 52 local qstart = query:get_child_text("start");
53 local qstart = query:get_child_text("start"); 53 local qend = query:get_child_text("end");
54 local qend = query:get_child_text("end"); 54 local qset = rsm.get(query);
55 local qset = rsm.get(query); 55 module:log("debug", "Archive query, id %s with %s from %s until %s)",
56 module:log("debug", "Archive query, id %s with %s from %s until %s)", 56 tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now");
57 tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now"); 57
58 58 if qstart or qend then -- Validate timestamps
59 if qstart or qend then -- Validate timestamps 59 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend))
60 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) 60 if (qstart and not vstart) or (qend and not vend) then
61 if (qstart and not vstart) or (qend and not vend) then 61 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid timestamp"))
62 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid timestamp")) 62 return true
63 return true 63 end
64 qstart, qend = vstart, vend;
65 end
66
67 local qres;
68 if qwith then -- Validate the 'with' jid
69 local pwith = qwith and jid_prep(qwith);
70 if pwith and not qwith then -- it failed prepping
71 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid JID"))
72 return true
73 end
74 local _, _, resource = jid_split(qwith);
75 qwith = jid_bare(pwith);
76 qres = resource;
77 end
78
79 -- Load all the data!
80 local data, err = dm_list_load(room, module.host, archive_store);
81 if not data then
82 if (not err) then
83 module:log("debug", "The archive was empty.");
84 origin.send(st.reply(stanza));
85 else
86 origin.send(st.error_reply(stanza, "cancel", "internal-server-error", "Error loading archive: "..tostring(err)));
87 end
88 return true
89 end
90
91 -- RSM stuff
92 local qmax = m_min(qset and qset.max or default_max_items, max_max_items);
93 local qset_matches = not (qset and qset.after);
94 local first, last, index;
95 local n = 0;
96 local start = qset and qset.index or 1;
97
98 module:log("debug", "Loaded %d items, about to filter", #data);
99 for i=start,#data do
100 local item = data[i];
101 local when, nick = item.when, item.resource;
102 local id = item.id;
103 --module:log("debug", "id is %s", id);
104
105 -- RSM pre-send-checking
106 if qset then
107 if qset.before == id then
108 module:log("debug", "End of matching range found");
109 qset_matches = false;
110 break;
64 end 111 end
65 qstart, qend = vstart, vend; 112 end
66 end 113
67 114 --module:log("debug", "message with %s at %s", with, when or "???");
68 local qres; 115 -- Apply query filter
69 if qwith then -- Validate the 'with' jid 116 if (not qres or (qres == nick))
70 local pwith = qwith and jid_prep(qwith); 117 and (not qstart or when >= qstart)
71 if pwith and not qwith then -- it failed prepping 118 and (not qend or when <= qend)
72 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid JID")) 119 and (not qset or qset_matches) then
73 return true 120 local fwd_st = st.message{ to = stanza.attr.from }
121 :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }):up()
122 :tag("forwarded", { xmlns = xmlns_forward })
123 :tag("delay", { xmlns = xmlns_delay, stamp = timestamp(when) }):up();
124 local orig_stanza = st.deserialize(item.stanza);
125 orig_stanza.attr.xmlns = "jabber:client";
126 fwd_st:add_child(orig_stanza);
127 origin.send(fwd_st);
128 if not first then
129 index = i;
130 first = id;
74 end 131 end
75 local _, _, resource = jid_split(qwith); 132 last = id;
76 qwith = jid_bare(pwith); 133 n = n + 1;
77 qres = resource; 134 elseif (qend and when > qend) then
78 end 135 module:log("debug", "We have passed into messages more recent than requested");
79 136 break -- We have passed into messages more recent than requested
80 -- Load all the data! 137 end
81 local data, err = dm_list_load(room, module.host, archive_store); 138
82 if not data then 139 -- RSM post-send-checking
83 if (not err) then 140 if qset then
84 module:log("debug", "The archive was empty."); 141 if qset.after == id then
85 origin.send(st.reply(stanza)); 142 module:log("debug", "Start of matching range found");
86 else 143 qset_matches = true;
87 origin.send(st.error_reply(stanza, "cancel", "internal-server-error", "Error loading archive: "..tostring(err)));
88 end 144 end
89 return true 145 end
90 end 146 if n >= qmax then
91 147 module:log("debug", "Max number of items matched");
92 -- RSM stuff 148 break
93 local qmax = m_min(qset and qset.max or default_max_items, max_max_items); 149 end
94 local qset_matches = not (qset and qset.after); 150 end
95 local first, last, index; 151 -- That's all folks!
96 local n = 0; 152 module:log("debug", "Archive query %s completed", tostring(qid));
97 local start = qset and qset.index or 1; 153
98 154 local reply = st.reply(stanza);
99 module:log("debug", "Loaded %d items, about to filter", #data); 155 if last then
100 for i=start,#data do 156 -- This is a bit redundant, isn't it?
101 local item = data[i]; 157 reply:query(xmlns_mam):add_child(rsm.generate{first = first, last = last, count = n});
102 local when, nick = item.when, item.resource; 158 end
103 local id = item.id; 159 origin.send(reply);
104 --module:log("debug", "id is %s", id); 160 return true
105
106 -- RSM pre-send-checking
107 if qset then
108 if qset.before == id then
109 module:log("debug", "End of matching range found");
110 qset_matches = false;
111 break;
112 end
113 end
114
115 --module:log("debug", "message with %s at %s", with, when or "???");
116 -- Apply query filter
117 if (not qres or (qres == nick))
118 and (not qstart or when >= qstart)
119 and (not qend or when <= qend)
120 and (not qset or qset_matches) then
121 local fwd_st = st.message{ to = stanza.attr.from }
122 :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }):up()
123 :tag("forwarded", { xmlns = xmlns_forward })
124 :tag("delay", { xmlns = xmlns_delay, stamp = timestamp(when) }):up();
125 local orig_stanza = st.deserialize(item.stanza);
126 orig_stanza.attr.xmlns = "jabber:client";
127 fwd_st:add_child(orig_stanza);
128 origin.send(fwd_st);
129 if not first then
130 index = i;
131 first = id;
132 end
133 last = id;
134 n = n + 1;
135 elseif (qend and when > qend) then
136 module:log("debug", "We have passed into messages more recent than requested");
137 break -- We have passed into messages more recent than requested
138 end
139
140 -- RSM post-send-checking
141 if qset then
142 if qset.after == id then
143 module:log("debug", "Start of matching range found");
144 qset_matches = true;
145 end
146 end
147 if n >= qmax then
148 module:log("debug", "Max number of items matched");
149 break
150 end
151 end
152 -- That's all folks!
153 module:log("debug", "Archive query %s completed", tostring(qid));
154
155 local reply = st.reply(stanza);
156 if last then
157 -- This is a bit redundant, isn't it?
158 reply:query(xmlns_mam):add_child(rsm.generate{first = first, last = last, count = n});
159 end
160 origin.send(reply);
161 return true
162 end
163 end); 161 end);
164 162
165 -- Handle messages 163 -- Handle messages
166 local function message_handler(event) 164 local function message_handler(event)
167 local origin, stanza = event.origin, event.stanza; 165 local origin, stanza = event.origin, event.stanza;