aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2022-01-09 18:42:22 +0100
committerKim Alvefur <zash@zash.se>2022-01-09 18:42:22 +0100
commit8a53094a7daf29d5dec902353c8ebf7cd7772bfe (patch)
tree9fa9f518b4a44ce1c0007620317f2e2fb857368b
parentd8c9ea741bfd41d5876e564435062b5018971855 (diff)
downloadprosody-8a53094a7daf29d5dec902353c8ebf7cd7772bfe.tar.gz
prosody-8a53094a7daf29d5dec902353c8ebf7cd7772bfe.zip
mod_bookmarks: Broadcast notifications per XEP-0048 and XEP-0411
For compatibility with clients relying on the notifications
-rw-r--r--doc/doap.xml9
-rw-r--r--plugins/mod_bookmarks.lua34
2 files changed, 43 insertions, 0 deletions
diff --git a/doc/doap.xml b/doc/doap.xml
index c03d62ee..0c6eb536 100644
--- a/doc/doap.xml
+++ b/doc/doap.xml
@@ -803,6 +803,15 @@
</implements>
<implements>
<xmpp:SupportedXep>
+ <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0411.html"/>
+ <xmpp:version>1.1.0</xmpp:version>
+ <xmpp:since>0.12.0</xmpp:since>
+ <xmpp:status>complete</xmpp:status>
+ <xmpp:note>mod_bookmarks</xmpp:note>
+ </xmpp:SupportedXep>
+ </implements>
+ <implements>
+ <xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0421.html"/>
<xmpp:version>0.1.0</xmpp:version>
<xmpp:since>0.12.0</xmpp:since>
diff --git a/plugins/mod_bookmarks.lua b/plugins/mod_bookmarks.lua
index ef376104..7797be7d 100644
--- a/plugins/mod_bookmarks.lua
+++ b/plugins/mod_bookmarks.lua
@@ -12,6 +12,7 @@ local private_storage = module:open_store("private", "map");
local namespace = "urn:xmpp:bookmarks:1";
local namespace_private = "jabber:iq:private";
local namespace_legacy = "storage:bookmarks";
+local xmlns_pubsub = "http://jabber.org/protocol/pubsub";
local default_options = {
["persist_items"] = true;
@@ -24,12 +25,16 @@ module:hook("account-disco-info", function (event)
-- This Time it’s Serious!
event.reply:tag("feature", { var = namespace.."#compat" }):up();
event.reply:tag("feature", { var = namespace.."#compat-pep" }):up();
+
+ -- COMPAT XEP-0411
+ event.reply:tag("feature", { var = "urn:xmpp:bookmarks-conversion:0" }):up();
end);
-- This must be declared on the domain JID, not the account JID. Note that
-- this isn’t defined in the XEP.
module:add_feature(namespace_private);
+
local function generate_legacy_storage(items)
local storage = st.stanza("storage", { xmlns = namespace_legacy });
for _, item_id in ipairs(items) do
@@ -417,10 +422,39 @@ end, 1);
if module:get_option_boolean("upgrade_legacy_bookmarks", true) then
module:hook("resource-bind", migrate_legacy_bookmarks);
end
+-- COMPAT XEP-0411 Broadcast as per XEP-0048 + PEP
+local function legacy_broadcast(event)
+ local service = event.service;
+ local ok, bookmarks = service:get_items(namespace, event.actor);
+ if bookmarks == "item-not-found" then ok, bookmarks = true, {} end
+ if not ok then return end
+ local legacy_bookmarks_item = st.stanza("item", { xmlns = xmlns_pubsub; id = "current" })
+ :add_child(generate_legacy_storage(bookmarks));
+ -- FIXME This broadcasts to any and all contacts who sent +notify because the node does not exist, so defaults apply.
+ service:broadcast("items", namespace_legacy, { --[[ no subscribers ]] }, legacy_bookmarks_item, event.actor);
+end
+local function broadcast_legacy_removal(event)
+ if event.node ~= namespace then return end
+ return legacy_broadcast(event);
+end
+module:hook("presence/initial", function (event)
+ -- Broadcasts to all clients with legacy+notify, not just the one coming online.
+ -- Upgrade to XEP-0402 to avoid it
+ local service = mod_pep.get_pep_service(event.origin.username);
+ legacy_broadcast({ service = service, actor = event.origin.full_jid });
+end);
module:handle_items("pep-service", function (event)
local service = event.item.service;
module:hook_object_event(service.events, "node-created", on_node_created);
+ module:hook_object_event(service.events, "item-published/" .. namespace, legacy_broadcast);
+ module:hook_object_event(service.events, "item-retracted", broadcast_legacy_removal);
+ module:hook_object_event(service.events, "node-purged", broadcast_legacy_removal);
+ module:hook_object_event(service.events, "node-deleted", broadcast_legacy_removal);
end, function (event)
local service = event.item.service;
module:unhook_object_event(service.events, "node-created", on_node_created);
+ module:unhook_object_event(service.events, "item-published/" .. namespace, legacy_broadcast);
+ module:unhook_object_event(service.events, "item-retracted", broadcast_legacy_removal);
+ module:unhook_object_event(service.events, "node-purged", broadcast_legacy_removal);
+ module:unhook_object_event(service.events, "node-deleted", broadcast_legacy_removal);
end, true);