diff options
-rw-r--r-- | plugins/mod_blocklist.lua | 9 | ||||
-rw-r--r-- | plugins/mod_pep.lua | 59 | ||||
-rw-r--r-- | plugins/muc/muc.lib.lua | 24 | ||||
-rw-r--r-- | spec/scansion/blocking.scs | 160 | ||||
-rw-r--r-- | util/dependencies.lua | 2 |
5 files changed, 231 insertions, 23 deletions
diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index 2193a093..cf8aad80 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -128,6 +128,7 @@ local function edit_blocklist(event) -- > only if the contact is allowed to receive presence notifications [...] -- So contacts we need to do that for are added to the set below. local send_unavailable = is_blocking and {}; + local send_available = not is_blocking and {}; -- Because blocking someone currently also blocks the ability to reject -- subscription requests, we'll preemptively reject such @@ -147,6 +148,8 @@ local function edit_blocklist(event) elseif is_contact_pending_in(username, module.host, jid) then remove_pending[jid] = true; end + elseif is_contact_subscribed(username, module.host, jid) then + send_available[jid] = true; end end @@ -186,6 +189,7 @@ local function edit_blocklist(event) if is_blocking then for jid in pairs(send_unavailable) do + -- Check that this JID isn't already blocked, i.e. this is not a change if not blocklist[jid] then for _, session in pairs(sessions[username].sessions) do if session.presence then @@ -203,6 +207,11 @@ local function edit_blocklist(event) save_roster(username, module.host, roster); -- Not much we can do about save failing here end + else + local user_bare = username .. "@" .. module.host; + for jid in pairs(send_available) do + module:send(st.presence({ type = "probe", to = user_bare, from = jid })); + end end local blocklist_push = st.iq({ type = "set", id = "blocklist-push" }) diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index 815c2e37..54f0451d 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -91,6 +91,21 @@ local function nodestore(username) return data, err; end function store:set(node, data) + if data then + -- Save the data without subscriptions + local subscribers = {}; + for jid, sub in pairs(data.subscribers) do + if type(sub) ~= "table" or not sub.presence then + subscribers[jid] = sub; + end + end + data = { + name = data.name; + config = data.config; + affiliations = data.affiliations; + subscribers = subscribers; + }; + end return node_config:set(username, node, data); end function store:users() @@ -124,7 +139,6 @@ local function get_broadcaster(username) if kind == "retract" then kind = "items"; -- XEP-0060 signals retraction in an <items> container end - if item then item = st.clone(item); item.attr.xmlns = nil; -- Clear the pubsub namespace @@ -144,23 +158,8 @@ local function get_broadcaster(username) message:add_child(item); end - local broadcast_to = {}; for jid in pairs(jids) do - broadcast_to[jid] = true; - end - - local service_recipients = recipients[username]; - if service_recipients then - local service = services[username]; - for recipient, nodes in pairs(service_recipients) do - if nodes:contains(node) and service:may(node, recipient, "subscribe") then - broadcast_to[recipient] = true; - end - end - end - - for jid in pairs(broadcast_to) do - module:log("debug", "Sending notification to %s from %s: %s", jid, user_bare, tostring(item)); + module:log("debug", "Sending notification to %s from %s for node %s", jid, user_bare, node); message.attr.to = jid; module:send(message); end @@ -168,6 +167,21 @@ local function get_broadcaster(username) return simple_broadcast; end +local function on_node_creation(event) + local service = event.service; + local node = event.node; + local username = service.config.pep_username; + + local service_recipients = recipients[username]; + if not service_recipients then return; end + + for recipient, nodes in pairs(service_recipients) do + if nodes:contains(node) then + service:add_subscription(node, recipient, recipient, { presence = true }); + end + end +end + function get_pep_service(username) module:log("debug", "get_pep_service(%q)", username); local user_bare = jid_join(username, host); @@ -226,6 +240,11 @@ function get_pep_service(username) return service; end +module:hook("item-added/pep-service", function (event) + local service = event.item.service; + module:hook_object_event(service.events, "node-created", on_node_creation); +end); + function handle_pubsub_iq(event) local origin, stanza = event.origin, event.stanza; local service_name = origin.username; @@ -240,6 +259,7 @@ end module:hook("iq/bare/"..xmlns_pubsub..":pubsub", handle_pubsub_iq); module:hook("iq/bare/"..xmlns_pubsub_owner..":pubsub", handle_pubsub_iq); + local function get_caps_hash_from_presence(stanza, current) local t = stanza.attr.type; if not t then @@ -288,9 +308,12 @@ local function update_subscriptions(recipient, service_name, nodes) end local service = get_pep_service(service_name); + for node in current - nodes do + service:remove_subscription(node, recipient, recipient); + end for node in nodes - current do - if service:may(node, recipient, "subscribe") then + if service:add_subscription(node, recipient, recipient, { presence = true }) then resend_last_item(recipient, node, service); end end diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index c828d17d..34961558 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -391,7 +391,11 @@ function room_mt:handle_kickable(origin, stanza) -- luacheck: ignore 212 end self:publicise_occupant_status(new_occupant or occupant, x); if is_last_session then - module:fire_event("muc-occupant-left", {room = self; nick = occupant.nick; occupant = occupant;}); + module:fire_event("muc-occupant-left", { + room = self; + nick = occupant.nick; + occupant = occupant; + }); end return true; end @@ -868,7 +872,11 @@ function room_mt:clear(x) end for occupant in pairs(occupants_updated) do self:publicise_occupant_status(occupant, x); - module:fire_event("muc-occupant-left", { room = self; nick = occupant.nick; occupant = occupant;}); + module:fire_event("muc-occupant-left", { + room = self; + nick = occupant.nick; + occupant = occupant; + }); end end @@ -1316,7 +1324,11 @@ function room_mt:set_affiliation(actor, jid, affiliation, reason, data) for occupant, old_role in pairs(occupants_updated) do self:publicise_occupant_status(occupant, x, nil, actor, reason); if occupant.role == nil then - module:fire_event("muc-occupant-left", {room = self; nick = occupant.nick; occupant = occupant;}); + module:fire_event("muc-occupant-left", { + room = self; + nick = occupant.nick; + occupant = occupant; + }); elseif is_semi_anonymous and (old_role == "moderator" and occupant.role ~= "moderator") or (old_role ~= "moderator" and occupant.role == "moderator") then -- Has gained or lost moderator status @@ -1432,7 +1444,11 @@ function room_mt:set_role(actor, occupant_jid, role, reason) self:save_occupant(occupant); self:publicise_occupant_status(occupant, x, nil, actor, reason); if role == nil then - module:fire_event("muc-occupant-left", {room = self; nick = occupant.nick; occupant = occupant;}); + module:fire_event("muc-occupant-left", { + room = self; + nick = occupant.nick; + occupant = occupant; + }); end return true; end diff --git a/spec/scansion/blocking.scs b/spec/scansion/blocking.scs new file mode 100644 index 00000000..6a9f199e --- /dev/null +++ b/spec/scansion/blocking.scs @@ -0,0 +1,160 @@ +# XEP-0191: Blocking Command + +[Client] Romeo + jid: blocker@localhost + password: password + +[Client] Juliet + jid: blockee@localhost + password: password + +----- + +# The parties connect +Romeo connects + +Romeo sends: + <presence/> + +Romeo receives: + <presence from="${Romeo's full JID}"/> + +Juliet connects + +Juliet sends: + <presence/> + +Juliet receives: + <presence from="${Juliet's full JID}"/> + +# They add each other +Romeo sends: + <presence type="subscribe" to="${Juliet's JID}"/> + +Romeo receives: + <presence from="${Juliet's JID}" to="${Romeo's JID}" type="unavailable"/> + +Juliet receives: + <presence type="subscribe" to="${Juliet's JID}" from="${Romeo's JID}"/> + +Juliet sends: + <presence type="subscribed" to="${Romeo's JID}"/> + +Romeo receives: + <presence from="${Juliet's full JID}" to="${Romeo's JID}"> + <delay xmlns="urn:xmpp:delay" stamp="{scansion:any}" from="localhost"/> + </presence> + +Juliet sends: + <presence type="subscribe" to="${Romeo's JID}"/> + +Juliet receives: + <presence from="${Romeo's JID}" to="${Juliet's JID}" type="unavailable"/> + +Romeo receives: + <presence type="subscribe" to="${Romeo's JID}" from="${Juliet's JID}"/> + +Romeo sends: + <presence type="subscribed" to="${Juliet's JID}"/> + +Juliet receives: + <presence from="${Romeo's full JID}" to="${Juliet's JID}"> + <delay xmlns="urn:xmpp:delay" stamp="{scansion:any}" from="localhost"/> + </presence> + +Romeo receives: + <presence from="${Juliet's full JID}" to="${Romeo's JID}"> + <delay xmlns="urn:xmpp:delay" stamp="{scansion:any}" from="localhost"/> + </presence> + +# They can now talk +Juliet sends: + <message type="chat" to="${Romeo's JID}"> + <body>ohai</body> + </message> + +Romeo receives: + <message type="chat" to="${Romeo's JID}" from="${Juliet's full JID}"> + <body>ohai</body> + </message> + +# And now to the blockining + +Romeo sends: + <iq type="set" id="lx2"> + <block xmlns="urn:xmpp:blocking"> + <item jid="${Juliet's JID}"/> + </block> + </iq> + +Romeo receives: + <iq type="result" id="lx2"/> + +Juliet receives: + <presence type="unavailable" to="${Juliet's JID}" from="${Romeo's full JID}"/> + +# Can"t talk anymore +Romeo sends: + <message type="chat" to="${Juliet's JID}"> + <body>hello?</body> + </message> + +Romeo receives: + <message type="error" from="${Juliet's JID}"> + <error type="cancel"> + <not-acceptable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> + <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">You have blocked this JID</text> + <blocked xmlns="urn:xmpp:blocking:errors"/> + </error> + </message> + +Juliet sends: + <message type="chat" to="${Romeo's JID}"/> + +Juliet receives: + <message type="error" from="${Romeo's JID}"> + <error type="cancel"> + <service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> + </error> + </message> + +Romeo sends: + <iq type="set" id="lx3"> + <unblock xmlns="urn:xmpp:blocking"> + <item jid="${Juliet's JID}"/> + </unblock> + </iq> + +Juliet receives: + <presence to="${Juliet's JID}" from="${Romeo's full JID}"> + <delay xmlns="urn:xmpp:delay" stamp="{scansion:any}" from="localhost"/> + </presence> + +Romeo receives: + <iq type="result" id="lx3"/> + +# Can talk again +Romeo sends: + <message type="chat" to="${Juliet's JID}"> + <body>hello!</body> + </message> + +Juliet receives: + <message type="chat" to="${Juliet's JID}" from="${Romeo's full JID}"> + <body>hello!</body> + </message> + +# Bye +Juliet disconnects + +Juliet sends: + <presence type="unavailable"/> + +Romeo receives: + <presence from="${Juliet's full JID}" to="${Romeo's JID}" type="unavailable"/> + +Romeo disconnects + +Romeo sends: + <presence type="unavailable"/> + diff --git a/util/dependencies.lua b/util/dependencies.lua index 7c7b938e..84e2dd5c 100644 --- a/util/dependencies.lua +++ b/util/dependencies.lua @@ -140,7 +140,7 @@ local function check_dependencies() end local function log_warnings() - if _VERSION > "Lua 5.2" then + if _VERSION > "Lua 5.3" then prosody.log("warn", "Support for %s is experimental, please report any issues", _VERSION); end local ssl = softreq"ssl"; |