mod_privacy: Fix selecting the top resource (fixes #694)
[prosody.git] / plugins / mod_privacy.lua
index e3d38af90cc7135b1d52a7d84c5aac464439528f..f95dfa50a1043588f1a4201177378d96b448aa41 100644 (file)
@@ -7,16 +7,18 @@
 -- COPYING file in the source package for more information.
 --
 
-local prosody = prosody;
+module:add_feature("jabber:iq:privacy");
+
 local st = require "util.stanza";
-local datamanager = require "util.datamanager";
-local bare_sessions, full_sessions = bare_sessions, full_sessions;
+local bare_sessions, full_sessions = prosody.bare_sessions, prosody.full_sessions;
 local util_Jid = require "util.jid";
 local jid_bare = util_Jid.bare;
 local jid_split, jid_join = util_Jid.split, util_Jid.join;
 local load_roster = require "core.rostermanager".load_roster;
 local to_number = tonumber;
 
+local privacy_storage = module:open_store();
+
 function isListUsed(origin, name, privacy_lists)
        local user = bare_sessions[origin.username.."@"..origin.host];
        if user then
@@ -43,28 +45,6 @@ function isAnotherSessionUsingDefaultList(origin)
        end
 end
 
-function sendUnavailable(origin, to, from)
---[[ example unavailable presence stanza
-<presence from="node@host/resource" type="unavailable" to="node@host" >
-       <status>Logged out</status>
-</presence>
-]]--
-       local presence = st.presence({from=from, type="unavailable"});
-       presence:tag("status"):text("Logged out");
-
-       local node, host = jid_bare(to);
-       local bare = node .. "@" .. host;
-       
-       local user = bare_sessions[bare];
-       if user then
-               for resource, session in pairs(user.sessions) do
-                       presence.attr.to = session.full_jid;
-                       module:log("debug", "send unavailable to: %s; from: %s", tostring(presence.attr.to), tostring(presence.attr.from));
-                       origin.send(presence);
-               end
-       end
-end
-
 function declineList(privacy_lists, origin, stanza, which)
        if which == "default" then
                if isAnotherSessionUsingDefaultList(origin) then
@@ -121,7 +101,7 @@ function deleteList(privacy_lists, origin, stanza, name)
        return {"modify", "bad-request", "Not existing list specifed to be deleted."};
 end
 
-function createOrReplaceList (privacy_lists, origin, stanza, name, entries, roster)
+function createOrReplaceList (privacy_lists, origin, stanza, name, entries)
        local bare_jid = origin.username.."@"..origin.host;
        
        if privacy_lists.lists == nil then
@@ -177,7 +157,7 @@ function createOrReplaceList (privacy_lists, origin, stanza, name, entries, rost
                list.items[#list.items + 1] = tmp;
        end
        
-       table.sort(list, function(a, b) return a.order < b.order; end);
+       table.sort(list.items, function(a, b) return a.order < b.order; end);
 
        origin.send(st.reply(stanza));
        if bare_sessions[bare_jid] ~= nil then
@@ -201,7 +181,7 @@ function getList(privacy_lists, origin, stanza, name)
 
        if name == nil then
                if privacy_lists.lists then
-                       if origin.ActivePrivacyList then
+                       if origin.activePrivacyList then
                                reply:tag("active", {name=origin.activePrivacyList}):up();
                        end
                        if privacy_lists.default then
@@ -238,7 +218,7 @@ module:hook("iq/bare/jabber:iq:privacy:query", function(data)
        if stanza.attr.to == nil then -- only service requests to own bare JID
                local query = stanza.tags[1]; -- the query element
                local valid = false;
-               local privacy_lists = datamanager.load(origin.username, origin.host, "privacy") or { lists = {} };
+               local privacy_lists = privacy_storage:get(origin.username) or { lists = {} };
 
                if privacy_lists.lists[1] then -- Code to migrate from old privacy lists format, remove in 0.8
                        module:log("info", "Upgrading format of stored privacy lists for %s@%s", origin.username, origin.host);
@@ -293,7 +273,7 @@ module:hook("iq/bare/jabber:iq:privacy:query", function(data)
                        end
                        origin.send(st.error_reply(stanza, valid[1], valid[2], valid[3]));
                else
-                       datamanager.store(origin.username, origin.host, "privacy", privacy_lists);
+                       privacy_storage:set(origin.username, privacy_lists);
                end
                return true;
        end
@@ -301,7 +281,7 @@ end);
 
 function checkIfNeedToBeBlocked(e, session)
        local origin, stanza = e.origin, e.stanza;
-       local privacy_lists = datamanager.load(session.username, session.host, "privacy") or {};
+       local privacy_lists = privacy_storage:get(session.username) or {};
        local bare_jid = session.username.."@"..session.host;
        local to = stanza.attr.to or bare_jid;
        local from = stanza.attr.from;
@@ -321,7 +301,6 @@ function checkIfNeedToBeBlocked(e, session)
                return; -- from one of a user's resource to another => HANDS OFF!
        end
        
-       local item;
        local listname = session.activePrivacyList;
        if listname == nil then
                listname = privacy_lists.default; -- no active list selected, use default list
@@ -388,6 +367,10 @@ function checkIfNeedToBeBlocked(e, session)
                end
                if apply then
                        if block then
+                               -- drop and not bounce groupchat messages, otherwise users will get kicked
+                               if stanza.attr.type == "groupchat" then
+                                       return true;
+                               end
                                module:log("debug", "stanza blocked: %s, to: %s, from: %s", tostring(stanza.name), tostring(to), tostring(from));
                                if stanza.name == "message" then
                                        origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
@@ -412,10 +395,9 @@ function preCheckIncoming(e)
                end
                if resource == nil then
                        local prio = 0;
-                       local session_;
                        if bare_sessions[node.."@"..host] ~= nil then
                                for resource, session_ in pairs(bare_sessions[node.."@"..host].sessions) do
-                                       if session_.priority ~= nil and session_.priority > prio then
+                                       if session_.priority ~= nil and session_.priority >= prio then
                                                session = session_;
                                                prio = session_.priority;
                                        end