mod_pep: Fix undefined global access
[prosody.git] / plugins / mod_presence.lua
index 7b521c5096d03962594ca35d4d02a7bbd6d6f3b0..623000625d78276b55f67afe7d076118f6bc6ad1 100644 (file)
@@ -6,9 +6,7 @@
 -- COPYING file in the source package for more information.\r
 --\r
 \r
-\r
-\r
-local log = require "util.logger".init("mod_presence")\r
+local log = module._log;\r
 \r
 local require = require;\r
 local pairs, ipairs = pairs, ipairs;\r
@@ -25,6 +23,20 @@ local rostermanager = require "core.rostermanager";
 local sessionmanager = require "core.sessionmanager";\r
 local offlinemanager = require "core.offlinemanager";\r
 \r
+local _core_route_stanza = core_route_stanza;\r
+local core_route_stanza;\r
+function core_route_stanza(origin, stanza)\r
+       if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then\r
+               local node, host = jid_split(stanza.attr.to);\r
+               host = hosts[host];\r
+               if host and host.type == "local" then\r
+                       handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza);\r
+                       return;\r
+               end\r
+       end\r
+       _core_route_stanza(origin, stanza);\r
+end\r
+\r
 function handle_presence(origin, stanza, from_bare, to_bare, core_route_stanza, inbound)\r
        local type = stanza.attr.type;\r
        if type and type ~= "unavailable" and type ~= "error" then\r
@@ -51,7 +63,7 @@ function handle_normal_presence(origin, stanza, core_route_stanza)
                end\r
                local node, host = jid_split(stanza.attr.from);\r
                for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast to all resources\r
-                       if res ~= origin and res.full_jid then -- to resource. FIXME is res.full_jid the correct check? Maybe it should be res.presence\r
+                       if res ~= origin and res.presence then -- to resource\r
                                stanza.attr.to = res.full_jid;\r
                                core_route_stanza(origin, stanza);\r
                        end\r
@@ -120,7 +132,7 @@ function handle_normal_presence(origin, stanza, core_route_stanza)
                end\r
                stanza.attr.to = nil; -- reset it\r
        else\r
-               log("error", "presence recieved from client with no roster");\r
+               log("warn", "presence recieved from client with no roster");\r
        end\r
 end\r
 \r
@@ -134,16 +146,14 @@ function send_presence_of_available_resources(user, host, jid, recipient_session
                                local pres = session.presence;\r
                                if pres then\r
                                        pres.attr.to = jid;\r
-                                       pres.attr.from = session.full_jid;\r
                                        core_route_stanza(session, pres);\r
                                        pres.attr.to = nil;\r
-                                       pres.attr.from = nil;\r
                                        count = count + 1;\r
                                end\r
                        end\r
                end\r
        end\r
-       log("info", "broadcasted presence of "..count.." resources from "..user.."@"..host.." to "..jid);\r
+       log("debug", "broadcasted presence of "..count.." resources from "..user.."@"..host.." to "..jid);\r
        return count;\r
 end\r
 \r
@@ -238,9 +248,9 @@ local function presence_handler(data)
        if origin.type == "c2s" then\r
                if to ~= nil and not(origin.roster[to_bare] and (origin.roster[to_bare].subscription == "both" or origin.roster[to_bare].subscription == "from")) then -- directed presence\r
                        origin.directed = origin.directed or {};\r
-                       origin.directed[to] = true;\r
+                       origin.directed[to] = true; -- FIXME does it make more sense to add to_bare rather than to?\r
                end\r
-               if to == nil and stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then\r
+               if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then\r
                        handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza);\r
                elseif not to then\r
                        handle_normal_presence(origin, stanza, core_route_stanza);\r
@@ -248,18 +258,87 @@ local function presence_handler(data)
                        core_route_stanza(origin, stanza);\r
                end\r
        elseif (origin.type == "s2sin" or origin.type == "component") and hosts[host] then\r
-               if to == nil and stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then\r
+               if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then\r
                        handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza);\r
                else\r
                        core_route_stanza(origin, stanza);\r
                end\r
        end\r
+       return true;\r
 end\r
 \r
-local add_handler = require "core.eventmanager2".add_handler;\r
-local remove_handler = require "core.eventmanager2".remove_handler;\r
-\r
-add_handler(module:get_host().."/presence", presence_handler);\r
+prosody.events.add_handler(module:get_host().."/presence", presence_handler);\r
 module.unload = function()\r
-       remove_handler(module:get_host().."/presence", presence_handler);\r
+       prosody.events.remove_handler(module:get_host().."/presence", presence_handler);\r
 end\r
+\r
+local outbound_presence_handler = function(data)\r
+       -- outbound presence recieved\r
+       local origin, stanza = data.origin, data.stanza;\r
+\r
+       local to = stanza.attr.to;\r
+       if to then\r
+               local t = stanza.attr.type;\r
+               if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes\r
+                       handle_outbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza);\r
+                       return true;\r
+               end\r
+\r
+               local to_bare = jid_bare(to);\r
+               if not(origin.roster[to_bare] and (origin.roster[to_bare].subscription == "both" or origin.roster[to_bare].subscription == "from")) then -- directed presence\r
+                       origin.directed = origin.directed or {};\r
+                       if t then -- removing from directed presence list on sending an error or unavailable\r
+                               origin.directed[to] = nil; -- FIXME does it make more sense to add to_bare rather than to?\r
+                       else\r
+                               origin.directed[to] = true; -- FIXME does it make more sense to add to_bare rather than to?\r
+                       end\r
+               end\r
+       end -- TODO maybe handle normal presence here, instead of letting it pass to incoming handlers?\r
+end\r
+\r
+module:hook("pre-presence/full", outbound_presence_handler);\r
+module:hook("pre-presence/bare", outbound_presence_handler);\r
+module:hook("pre-presence/host", outbound_presence_handler);\r
+\r
+module:hook("presence/bare", function(data)\r
+       -- inbound presence to bare JID recieved\r
+       local origin, stanza = data.origin, data.stanza;\r
+\r
+       local to = stanza.attr.to;\r
+       local t = stanza.attr.type;\r
+       if to then\r
+               if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes sent to bare JID\r
+                       handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza);\r
+                       return true;\r
+               end\r
+       \r
+               local user = bare_sessions[to];\r
+               if user then\r
+                       for _, session in pairs(user.sessions) do\r
+                               if session.presence then -- only send to available resources\r
+                                       session.send(stanza);\r
+                               end\r
+                       end\r
+               end -- no resources not online, discard\r
+       elseif not t or t == "unavailable" then\r
+               handle_normal_presence(origin, stanza, core_route_stanza);\r
+       end\r
+       return true;\r
+end);\r
+module:hook("presence/full", function(data)\r
+       -- inbound presence to full JID recieved\r
+       local origin, stanza = data.origin, data.stanza;\r
+\r
+       local t = stanza.attr.type;\r
+       if t ~= nil and t ~= "unavailable" and t ~= "error" then -- check for subscriptions and probes sent to full JID\r
+               handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza);\r
+               return true;\r
+       end\r
+\r
+       local session = full_sessions[stanza.attr.to];\r
+       if session then\r
+               -- TODO fire post processing event\r
+               session.send(stanza);\r
+       end -- resource not online, discard\r
+       return true;\r
+end);\r