Comparison

plugins/mod_pep_plus.lua @ 8305:ec605946e597

mod_pep_plus: Use local username instead of bare JID for references
author Kim Alvefur <zash@zash.se>
date Sun, 08 Oct 2017 23:49:49 +0200
parent 8304:9f8476c77fa8
child 8306:202b9951b037
comparison
equal deleted inserted replaced
8304:9f8476c77fa8 8305:ec605946e597
1 local pubsub = require "util.pubsub"; 1 local pubsub = require "util.pubsub";
2 local jid_bare = require "util.jid".bare; 2 local jid_bare = require "util.jid".bare;
3 local jid_split = require "util.jid".split; 3 local jid_split = require "util.jid".split;
4 local jid_join = require "util.jid".join;
4 local set_new = require "util.set".new; 5 local set_new = require "util.set".new;
5 local st = require "util.stanza"; 6 local st = require "util.stanza";
6 local calculate_hash = require "util.caps".calculate_hash; 7 local calculate_hash = require "util.caps".calculate_hash;
7 local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed; 8 local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed;
8 9
17 18
18 local services = {}; 19 local services = {};
19 local recipients = {}; 20 local recipients = {};
20 local hash_map = {}; 21 local hash_map = {};
21 22
23 local host = module.host;
24
22 function module.save() 25 function module.save()
23 return { services = services }; 26 return { services = services };
24 end 27 end
25 28
26 function module.restore(data) 29 function module.restore(data)
27 services = data.services; 30 services = data.services;
28 end 31 end
29 32
30 local function subscription_presence(user_bare, recipient) 33 local function subscription_presence(username, recipient)
34 local user_bare = jid_join(username, host);
31 local recipient_bare = jid_bare(recipient); 35 local recipient_bare = jid_bare(recipient);
32 if (recipient_bare == user_bare) then return true; end 36 if (recipient_bare == user_bare) then return true; end
33 local username, host = jid_split(user_bare);
34 return is_contact_subscribed(username, host, recipient_bare); 37 return is_contact_subscribed(username, host, recipient_bare);
35 end 38 end
36 39
37 local function simple_itemstore(user) 40 local function simple_itemstore(username)
38 return function (config, node) 41 return function (config, node)
39 module:log("debug", "new simple_itemstore(%q, %q)", user, node); 42 module:log("debug", "new simple_itemstore(%q, %q)", username, node);
40 local archive = module:open_store("pep_"..node, "archive"); 43 local archive = module:open_store("pep_"..node, "archive");
41 return lib_pubsub.simple_itemstore(archive, config, user, node, false); 44 return lib_pubsub.simple_itemstore(archive, config, username, node, false);
42 end 45 end
43 end 46 end
44 47
45 local function get_broadcaster(name) 48 local function get_broadcaster(username)
49 local user_bare = jid_join(username, host);
46 local function simple_broadcast(kind, node, jids, item) 50 local function simple_broadcast(kind, node, jids, item)
47 if item then 51 if item then
48 item = st.clone(item); 52 item = st.clone(item);
49 item.attr.xmlns = nil; -- Clear the pubsub namespace 53 item.attr.xmlns = nil; -- Clear the pubsub namespace
50 end 54 end
51 local message = st.message({ from = name, type = "headline" }) 55 local message = st.message({ from = user_bare, type = "headline" })
52 :tag("event", { xmlns = xmlns_pubsub_event }) 56 :tag("event", { xmlns = xmlns_pubsub_event })
53 :tag(kind, { node = node }) 57 :tag(kind, { node = node })
54 :add_child(item); 58 :add_child(item);
55 for jid in pairs(jids) do 59 for jid in pairs(jids) do
56 module:log("debug", "Sending notification to %s from %s: %s", jid, name, tostring(item)); 60 module:log("debug", "Sending notification to %s from %s: %s", jid, user_bare, tostring(item));
57 message.attr.to = jid; 61 message.attr.to = jid;
58 module:send(message); 62 module:send(message);
59 end 63 end
60 end 64 end
61 return simple_broadcast; 65 return simple_broadcast;
62 end 66 end
63 67
64 function get_pep_service(name) 68 function get_pep_service(username)
65 module:log("debug", "get_pep_service(%q)"); 69 module:log("debug", "get_pep_service(%q)", username);
66 local service = services[name]; 70 local user_bare = jid_join(username, host);
71 local service = services[username];
67 if service then 72 if service then
68 return service; 73 return service;
69 end 74 end
70 service = pubsub.new({ 75 service = pubsub.new({
71 capabilities = { 76 capabilities = {
167 }; 172 };
168 173
169 autocreate_on_publish = true; 174 autocreate_on_publish = true;
170 autocreate_on_subscribe = true; 175 autocreate_on_subscribe = true;
171 176
172 itemstore = simple_itemstore(name); 177 itemstore = simple_itemstore(username);
173 broadcaster = get_broadcaster(name); 178 broadcaster = get_broadcaster(username);
174 get_affiliation = function (jid) 179 get_affiliation = function (jid)
175 if jid_bare(jid) == name then 180 if jid_bare(jid) == user_bare then
176 return "owner"; 181 return "owner";
177 elseif subscription_presence(name, jid) then 182 elseif subscription_presence(username, jid) then
178 return "subscriber"; 183 return "subscriber";
179 end 184 end
180 end; 185 end;
181 186
182 normalize_jid = jid_bare; 187 normalize_jid = jid_bare;
183 }); 188 });
184 services[name] = service; 189 services[username] = service;
185 module:add_item("pep-service", { service = service, jid = name }); 190 module:add_item("pep-service", { service = service, jid = user_bare });
186 return service; 191 return service;
187 end 192 end
188 193
189 function handle_pubsub_iq(event) 194 function handle_pubsub_iq(event)
190 local origin, stanza = event.origin, event.stanza; 195 local origin, stanza = event.origin, event.stanza;
191 local pubsub_tag = stanza.tags[1]; 196 local pubsub_tag = stanza.tags[1];
192 local action = pubsub_tag.tags[1]; 197 local action = pubsub_tag.tags[1];
193 if not action then 198 if not action then
194 return origin.send(st.error_reply(stanza, "cancel", "bad-request")); 199 return origin.send(st.error_reply(stanza, "cancel", "bad-request"));
195 end 200 end
196 local service_name = stanza.attr.to or origin.username.."@"..origin.host 201 local service_name = origin.username;
202 if stanza.attr.to ~= nil then
203 service_name = jid_split(stanza.attr.to);
204 end
197 local service = get_pep_service(service_name); 205 local service = get_pep_service(service_name);
198 local handler = handlers[stanza.attr.type.."_"..action.name]; 206 local handler = handlers[stanza.attr.type.."_"..action.name];
199 if handler then 207 if handler then
200 handler(origin, stanza, action, service); 208 handler(origin, stanza, action, service);
201 return true; 209 return true;
275 end 283 end
276 284
277 module:hook("presence/bare", function(event) 285 module:hook("presence/bare", function(event)
278 -- inbound presence to bare JID recieved 286 -- inbound presence to bare JID recieved
279 local origin, stanza = event.origin, event.stanza; 287 local origin, stanza = event.origin, event.stanza;
280 local user = stanza.attr.to or (origin.username..'@'..origin.host);
281 local t = stanza.attr.type; 288 local t = stanza.attr.type;
282 local is_self = not stanza.attr.to; 289 local is_self = not stanza.attr.to;
290 local username = jid_split(stanza.attr.to);
291 local user_bare = jid_bare(stanza.attr.to);
292 if is_self then
293 username = origin.username;
294 user_bare = jid_join(username, host);
295 end
283 296
284 if not t then -- available presence 297 if not t then -- available presence
285 if is_self or subscription_presence(user, stanza.attr.from) then 298 if is_self or subscription_presence(username, stanza.attr.from) then
286 local recipient = stanza.attr.from; 299 local recipient = stanza.attr.from;
287 local current = recipients[user] and recipients[user][recipient]; 300 local current = recipients[username] and recipients[username][recipient];
288 local hash, query_node = get_caps_hash_from_presence(stanza, current); 301 local hash, query_node = get_caps_hash_from_presence(stanza, current);
289 if current == hash or (current and current == hash_map[hash]) then return; end 302 if current == hash or (current and current == hash_map[hash]) then return; end
290 if not hash then 303 if not hash then
291 update_subscriptions(recipient, user); 304 update_subscriptions(recipient, username);
292 else 305 else
293 recipients[user] = recipients[user] or {}; 306 recipients[username] = recipients[username] or {};
294 if hash_map[hash] then 307 if hash_map[hash] then
295 update_subscriptions(recipient, user, hash_map[hash]); 308 update_subscriptions(recipient, username, hash_map[hash]);
296 else 309 else
297 recipients[user][recipient] = hash; 310 recipients[username][recipient] = hash;
298 local from_bare = origin.type == "c2s" and origin.username.."@"..origin.host; 311 local from_bare = origin.type == "c2s" and origin.username.."@"..origin.host;
299 if is_self or origin.type ~= "c2s" or (recipients[from_bare] and recipients[from_bare][origin.full_jid]) ~= hash then 312 if is_self or origin.type ~= "c2s" or (recipients[from_bare] and recipients[from_bare][origin.full_jid]) ~= hash then
300 -- COMPAT from ~= stanza.attr.to because OneTeam can't deal with missing from attribute 313 -- COMPAT from ~= stanza.attr.to because OneTeam can't deal with missing from attribute
301 origin.send( 314 origin.send(
302 st.stanza("iq", {from=user, to=stanza.attr.from, id="disco", type="get"}) 315 st.stanza("iq", {from=user_bare, to=stanza.attr.from, id="disco", type="get"})
303 :tag("query", {xmlns = "http://jabber.org/protocol/disco#info", node = query_node}) 316 :tag("query", {xmlns = "http://jabber.org/protocol/disco#info", node = query_node})
304 ); 317 );
305 end 318 end
306 end 319 end
307 end 320 end
308 end 321 end
309 elseif t == "unavailable" then 322 elseif t == "unavailable" then
310 update_subscriptions(stanza.attr.from, user); 323 update_subscriptions(stanza.attr.from, username);
311 elseif not is_self and t == "unsubscribe" then 324 elseif not is_self and t == "unsubscribe" then
312 local from = jid_bare(stanza.attr.from); 325 local from = jid_bare(stanza.attr.from);
313 local subscriptions = recipients[user]; 326 local subscriptions = recipients[username];
314 if subscriptions then 327 if subscriptions then
315 for subscriber in pairs(subscriptions) do 328 for subscriber in pairs(subscriptions) do
316 if jid_bare(subscriber) == from then 329 if jid_bare(subscriber) == from then
317 update_subscriptions(subscriber, user); 330 update_subscriptions(subscriber, username);
318 end 331 end
319 end 332 end
320 end 333 end
321 end 334 end
322 end, 10); 335 end, 10);
327 if not disco then 340 if not disco then
328 return; 341 return;
329 end 342 end
330 343
331 -- Process disco response 344 -- Process disco response
332 local is_self = not stanza.attr.to; 345 local is_self = stanza.attr.to == nil;
333 local user = stanza.attr.to or (origin.username..'@'..origin.host); 346 local username = jid_split(stanza.attr.to);
347 if is_self then
348 username = origin.username;
349 end
334 local contact = stanza.attr.from; 350 local contact = stanza.attr.from;
335 local current = recipients[user] and recipients[user][contact]; 351 local current = recipients[username] and recipients[username][contact];
336 if type(current) ~= "string" then return; end -- check if waiting for recipient's response 352 if type(current) ~= "string" then return; end -- check if waiting for recipient's response
337 local ver = current; 353 local ver = current;
338 if not string.find(current, "#") then 354 if not string.find(current, "#") then
339 ver = calculate_hash(disco.tags); -- calculate hash 355 ver = calculate_hash(disco.tags); -- calculate hash
340 end 356 end
354 update_subscriptions(contact, jid, notify); 370 update_subscriptions(contact, jid, notify);
355 end 371 end
356 end 372 end
357 end 373 end
358 end 374 end
359 update_subscriptions(contact, user, notify); 375 update_subscriptions(contact, username, notify);
360 end); 376 end);
361 377
362 module:hook("account-disco-info-node", function(event) 378 module:hook("account-disco-info-node", function(event)
363 local reply, stanza, origin = event.reply, event.stanza, event.origin; 379 local reply, stanza, origin = event.reply, event.stanza, event.origin;
364 local service_name = stanza.attr.to or origin.username.."@"..origin.host 380 local service_name = origin.username;
381 if stanza.attr.to ~= nil then
382 service_name = jid_split(stanza.attr.to);
383 end
365 local service = get_pep_service(service_name); 384 local service = get_pep_service(service_name);
366 local node = event.node; 385 local node = event.node;
367 local ok = service:get_items(node, jid_bare(stanza.attr.from) or true); 386 local ok = service:get_items(node, jid_bare(stanza.attr.from) or true);
368 if not ok then return; end 387 if not ok then return; end
369 event.exists = true; 388 event.exists = true;
377 end); 396 end);
378 397
379 module:hook("account-disco-items-node", function(event) 398 module:hook("account-disco-items-node", function(event)
380 local reply, stanza, origin = event.reply, event.stanza, event.origin; 399 local reply, stanza, origin = event.reply, event.stanza, event.origin;
381 local node = event.node; 400 local node = event.node;
382 local service_name = stanza.attr.to or origin.username.."@"..origin.host 401 local service_name = origin.username;
402 if stanza.attr.to ~= nil then
403 service_name = jid_split(stanza.attr.to);
404 end
383 local service = get_pep_service(service_name); 405 local service = get_pep_service(service_name);
384 local ok, ret = service:get_items(node, jid_bare(stanza.attr.from) or true); 406 local ok, ret = service:get_items(node, jid_bare(stanza.attr.from) or true);
385 if not ok then return; end 407 if not ok then return; end
386 event.exists = true; 408 event.exists = true;
387 for _, id in ipairs(ret) do 409 for _, id in ipairs(ret) do
390 end); 412 end);
391 413
392 module:hook("account-disco-items", function(event) 414 module:hook("account-disco-items", function(event)
393 local reply, stanza, origin = event.reply, event.stanza, event.origin; 415 local reply, stanza, origin = event.reply, event.stanza, event.origin;
394 416
395 local service_name = reply.attr.from or origin.username.."@"..origin.host 417 local service_name = origin.username;
418 if stanza.attr.to ~= nil then
419 service_name = jid_split(stanza.attr.to);
420 end
396 local service = get_pep_service(service_name); 421 local service = get_pep_service(service_name);
397 local ok, ret = service:get_nodes(jid_bare(stanza.attr.from)); 422 local ok, ret = service:get_nodes(jid_bare(stanza.attr.from));
398 if not ok then return; end 423 if not ok then return; end
399 424
400 for node, node_obj in pairs(ret) do 425 for node, node_obj in pairs(ret) do