From b2f0349c7e420ab78734ebcc74155fe79a7f6514 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 5 Dec 2015 22:46:50 +0100 Subject: mod_blocklist: Clear second level cache when user is deleted --- plugins/mod_blocklist.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index 65fc70b7..e37bc4df 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -186,6 +186,7 @@ module:hook("iq-set/self/urn:xmpp:blocking:unblock", edit_blocklist); -- Cache invalidation, solved! module:hook_global("user-deleted", function (event) if event.host == module.host then + cache:set(event.username, nil); cache[event.username] = nil; end end); -- cgit v1.2.3 From 0ec9e20543e2daeadc3bfca1cfc0c3f63e02d65c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:07:15 +0100 Subject: mod_blocklist: Rename variable for clarity --- plugins/mod_blocklist.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index e37bc4df..b68c08d1 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -123,9 +123,9 @@ local function edit_blocklist(event) new[jid] = is_contact_subscribed(username, module.host, jid) or false; end - local mode = action.name == "block" or nil; + local is_blocking = action.name == "block" or nil; -- nil if unblocking - if mode and not next(new) then + if is_blocking and not next(new) then -- element does not contain at least one child element origin.send(st_error_reply(stanza, "modify", "bad-request")); return true; @@ -135,12 +135,12 @@ local function edit_blocklist(event) local new_blocklist = {}; - if mode or next(new) then + if is_blocking or next(new) then for jid in pairs(blocklist) do new_blocklist[jid] = true; end for jid in pairs(new) do - new_blocklist[jid] = mode; + new_blocklist[jid] = is_blocking; end -- else empty the blocklist end @@ -154,7 +154,7 @@ local function edit_blocklist(event) return true; end - if mode then + if is_blocking then for jid, in_roster in pairs(new) do if not blocklist[jid] and in_roster and sessions[username] then for _, session in pairs(sessions[username].sessions) do -- cgit v1.2.3 From 4b1ba49a85adf72d3cbdb2b8cb83e52b1ed4e9e6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:08:24 +0100 Subject: mod_blocklist: Add comment about compliance issue #575 --- plugins/mod_blocklist.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index b68c08d1..add7abb3 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -277,6 +277,9 @@ module:hook("pre-message/bare", bounce_outgoing, prio_out); module:hook("pre-message/full", bounce_outgoing, prio_out); module:hook("pre-message/host", bounce_outgoing, prio_out); +-- Note: MUST bounce these, but we don't because this would produce +-- lots of error replies due to server-generated presence. +-- FIXME some day, likely needing changes to mod_presence module:hook("pre-presence/bare", drop_outgoing, prio_out); module:hook("pre-presence/full", drop_outgoing, prio_out); module:hook("pre-presence/host", drop_outgoing, prio_out); -- cgit v1.2.3 From 8920afaf2fb1d0b724f9528d009c0bc226c3adbc Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:09:52 +0100 Subject: mod_blocklist: Expand comments on caching of blocklists --- plugins/mod_blocklist.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index add7abb3..a38d2a0f 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -19,11 +19,17 @@ local jid_split = require"util.jid".split; local storage = module:open_store(); local sessions = prosody.hosts[module.host].sessions; --- Cache of blocklists by username may randomly expire at any time +-- First level cache of blocklists by username. +-- Weak table so may randomly expire at any time. local cache = setmetatable({}, { __mode = "v" }); --- Second level of caching, keeps a fixed number of items, --- also anchors items in the above cache +-- Second level of caching, keeps a fixed number of items, also anchors +-- items in the above cache. +-- +-- The size of this affects how often we will need to load a blocklist from +-- disk, which we want to avoid during routing. On the other hand, we don't +-- want to use too much memory either, so this can be tuned by advanced +-- users. TODO use science to figure out a better default, 64 is just a guess. local cache_size = module:get_option_number("blocklist_cache_size", 64); local cache2 = require"util.cache".new(cache_size); -- cgit v1.2.3 From 66b75a0f2ca9d9acbebe12486a50e3341a7c9512 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:12:28 +0100 Subject: mod_blocklist: Add comments describing some variables --- plugins/mod_blocklist.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index a38d2a0f..a870d278 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -116,8 +116,8 @@ end); local function edit_blocklist(event) local origin, stanza = event.origin, event.stanza; local username = origin.username; - local action = stanza.tags[1]; - local new = {}; + local action = stanza.tags[1]; -- "block" or "unblock" + local new = {}; -- JIDs to block depending or unblock on action for item in action:childtags("item") do local jid = jid_prep(item.attr.jid); -- cgit v1.2.3 From b4679e21888856879422f78b57b5740315362d23 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:19:04 +0100 Subject: mod_blocklist: session[username] can't possibly be unset if that user is sending queries --- plugins/mod_blocklist.lua | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index a870d278..d5e263b1 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -162,7 +162,7 @@ local function edit_blocklist(event) if is_blocking then for jid, in_roster in pairs(new) do - if not blocklist[jid] and in_roster and sessions[username] then + if not blocklist[jid] and in_roster then for _, session in pairs(sessions[username].sessions) do if session.presence then module:send(st.presence({ type = "unavailable", to = jid, from = session.full_jid })); @@ -171,15 +171,14 @@ local function edit_blocklist(event) end end end - if sessions[username] then - local blocklist_push = st.iq({ type = "set", id = "blocklist-push" }) - :add_child(action); -- I am lazy - - for _, session in pairs(sessions[username].sessions) do - if session.interested_blocklist then - blocklist_push.attr.to = session.full_jid; - session.send(blocklist_push); - end + + local blocklist_push = st.iq({ type = "set", id = "blocklist-push" }) + :add_child(action); -- I am lazy + + for _, session in pairs(sessions[username].sessions) do + if session.interested_blocklist then + blocklist_push.attr.to = session.full_jid; + session.send(blocklist_push); end end -- cgit v1.2.3 From 4fb06ad84f91761e45c87e832a95f2d5c57b2d39 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:22:49 +0100 Subject: mod_blocklist: Restructure how we keep track of where to send unavailable presence --- plugins/mod_blocklist.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index d5e263b1..c5d0a6bb 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -119,6 +119,13 @@ local function edit_blocklist(event) local action = stanza.tags[1]; -- "block" or "unblock" local new = {}; -- JIDs to block depending or unblock on action + -- XEP-0191 sayeth: + -- > When the user blocks communications with the contact, the user's + -- > server MUST send unavailable presence information to the contact (but + -- > 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 = {}; + for item in action:childtags("item") do local jid = jid_prep(item.attr.jid); if not jid then @@ -126,7 +133,10 @@ local function edit_blocklist(event) return true; end item.attr.jid = jid; -- echo back prepped - new[jid] = is_contact_subscribed(username, module.host, jid) or false; + new[jid] = true; + if is_contact_subscribed(username, module.host, jid) then + send_unavailable[jid] = true; + end end local is_blocking = action.name == "block" or nil; -- nil if unblocking @@ -161,8 +171,8 @@ local function edit_blocklist(event) end if is_blocking then - for jid, in_roster in pairs(new) do - if not blocklist[jid] and in_roster then + for jid in pairs(send_unavailable) do + if not blocklist[jid] then for _, session in pairs(sessions[username].sessions) do if session.presence then module:send(st.presence({ type = "unavailable", to = jid, from = session.full_jid })); -- cgit v1.2.3 From 7c2da2da9f71323ebfc5791582ac53f0255a1e4e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:30:21 +0100 Subject: mod_blocklist: When blocking someone who sent a subscription request, forget that request since the user would be unable to deny it while blocked (Fixes #574) --- plugins/mod_blocklist.lua | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index c5d0a6bb..d7476cb5 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -10,7 +10,11 @@ -- local user_exists = require"core.usermanager".user_exists; -local is_contact_subscribed = require"core.rostermanager".is_contact_subscribed; +local rostermanager = require"core.rostermanager"; +local is_contact_subscribed = rostermanager.is_contact_subscribed; +local is_contact_pending_in = rostermanager.is_contact_pending_in; +local load_roster = rostermanager.load_roster; +local save_roster = rostermanager.save_roster; local st = require"util.stanza"; local st_error_reply = st.error_reply; local jid_prep = require"util.jid".prep; @@ -126,6 +130,10 @@ local function edit_blocklist(event) -- So contacts we need to do that for are added to the set below. local send_unavailable = {}; + -- Because blocking someone currently also blocks the ability to reject + -- subscription requests, we'll preemptively reject such + local remove_pending = {}; + for item in action:childtags("item") do local jid = jid_prep(item.attr.jid); if not jid then @@ -136,6 +144,8 @@ local function edit_blocklist(event) new[jid] = true; if is_contact_subscribed(username, module.host, jid) then send_unavailable[jid] = true; + elseif is_contact_pending_in(username, module.host, jid) then + remove_pending[jid] = true; end end @@ -180,6 +190,15 @@ local function edit_blocklist(event) end end end + + if next(remove_pending) then + local roster = load_roster(username, module.host); + for jid in pairs(remove_pending) do + roster[false].pending[jid] = nil; + end + save_roster(username, module.host, roster); + -- Not much we can do about save failing here + end end local blocklist_push = st.iq({ type = "set", id = "blocklist-push" }) -- cgit v1.2.3 From 589b736095eb90220ebfeaa3c091c4bd7cec0924 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:32:16 +0100 Subject: mod_blocklist: Skip creating some tables and some processing if unblocking --- plugins/mod_blocklist.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index d7476cb5..8bcd7700 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -121,6 +121,7 @@ local function edit_blocklist(event) local origin, stanza = event.origin, event.stanza; local username = origin.username; local action = stanza.tags[1]; -- "block" or "unblock" + local is_blocking = action.name == "block" or nil; -- nil if unblocking local new = {}; -- JIDs to block depending or unblock on action -- XEP-0191 sayeth: @@ -128,11 +129,11 @@ local function edit_blocklist(event) -- > server MUST send unavailable presence information to the contact (but -- > 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 = {}; + local send_unavailable = is_blocking and {}; -- Because blocking someone currently also blocks the ability to reject -- subscription requests, we'll preemptively reject such - local remove_pending = {}; + local remove_pending = is_blocking and {}; for item in action:childtags("item") do local jid = jid_prep(item.attr.jid); @@ -142,15 +143,15 @@ local function edit_blocklist(event) end item.attr.jid = jid; -- echo back prepped new[jid] = true; - if is_contact_subscribed(username, module.host, jid) then - send_unavailable[jid] = true; - elseif is_contact_pending_in(username, module.host, jid) then - remove_pending[jid] = true; + if is_blocking then + if is_contact_subscribed(username, module.host, jid) then + send_unavailable[jid] = true; + elseif is_contact_pending_in(username, module.host, jid) then + remove_pending[jid] = true; + end end end - local is_blocking = action.name == "block" or nil; -- nil if unblocking - if is_blocking and not next(new) then -- element does not contain at least one child element origin.send(st_error_reply(stanza, "modify", "bad-request")); -- cgit v1.2.3 From 730986f23cc5ce84a0a16c664165653f0aabbf94 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Dec 2015 02:32:29 +0100 Subject: mod_blocklist: Update Copyright header --- plugins/mod_blocklist.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index 8bcd7700..e2ed626b 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -1,7 +1,7 @@ -- Prosody IM -- Copyright (C) 2009-2010 Matthew Wild -- Copyright (C) 2009-2010 Waqas Hussain --- Copyright (C) 2014 Kim Alvefur +-- Copyright (C) 2014-2015 Kim Alvefur -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- cgit v1.2.3