Software /
code /
prosody
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 |