Mercurial > prosody-hg
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 |
| parents | 9f8476c77fa8 |
| children | 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 |
