mod_tls: Only negotiate TLS on outgoing s2s connections if we have an SSL context...
[prosody.git] / plugins / mod_disco.lua
index 73e1921aa51fccb978fe55a28064d6b7975c5114..f7e51b83e3dbadaa1a5714fab2b3a3bf76d5d1da 100644 (file)
@@ -6,21 +6,35 @@
 -- COPYING file in the source package for more information.
 --
 
-local discomanager_handle = require "core.discomanager".handle;
 local componentmanager_get_children = require "core.componentmanager".get_children;
+local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed;
+local jid_split = require "util.jid".split;
+local jid_bare = require "util.jid".bare;
+local st = require "util.stanza"
+
+local disco_items = module:get_option("disco_items") or {};
+do -- validate disco_items
+       for _, item in ipairs(disco_items) do
+               local err;
+               if type(item) ~= "table" then
+                       err = "item is not a table";
+               elseif type(item[1]) ~= "string" then
+                       err = "item jid is not a string";
+               elseif item[2] and type(item[2]) ~= "string" then
+                       err = "item name is not a string";
+               end
+               if err then
+                       module:log("error", "option disco_items is malformed: %s", err);
+                       disco_items = {}; -- TODO clean up data instead of removing it?
+                       break;
+               end
+       end
+end
 
+module:add_identity("server", "im", "Prosody"); -- FIXME should be in the non-existing mod_router
 module:add_feature("http://jabber.org/protocol/disco#info");
 module:add_feature("http://jabber.org/protocol/disco#items");
 
-module:add_iq_handler({"c2s", "s2sin"}, "http://jabber.org/protocol/disco#info", function (session, stanza)
-       session.send(discomanager_handle(stanza));
-end);
-module:add_iq_handler({"c2s", "s2sin"}, "http://jabber.org/protocol/disco#items", function (session, stanza)
-       session.send(discomanager_handle(stanza));
-end);
-
-module:add_identity("server", "im", "Prosody");
-local st = require "util.stanza"
 module:hook("iq/host/http://jabber.org/protocol/disco#info:query", function(event)
        local origin, stanza = event.origin, event.stanza;
        if stanza.attr.type ~= "get" then return; end
@@ -55,6 +69,37 @@ module:hook("iq/host/http://jabber.org/protocol/disco#items:query", function(eve
        for jid in pairs(componentmanager_get_children(module.host)) do
                reply:tag("item", {jid = jid}):up();
        end
+       for _, item in ipairs(disco_items) do
+               reply:tag("item", {jid=item[1], name=item[2]}):up();
+       end
        origin.send(reply);
        return true;
 end);
+module:hook("iq/bare/http://jabber.org/protocol/disco#info:query", function(event)
+       local origin, stanza = event.origin, event.stanza;
+       if stanza.attr.type ~= "get" then return; end
+       local node = stanza.tags[1].attr.node;
+       if node and node ~= "" then return; end -- TODO fire event?
+       local username = jid_split(stanza.attr.to) or origin.username;
+       if not stanza.attr.to or is_contact_subscribed(username, module.host, jid_bare(stanza.attr.from)) then
+               local reply = st.reply(stanza):tag('query', {xmlns='http://jabber.org/protocol/disco#info'});
+               if not reply.attr.from then reply.attr.from = origin.username.."@"..origin.host; end -- COMPAT To satisfy Psi when querying own account
+               module:fire_event("account-disco-info", { session = origin, stanza = reply });
+               origin.send(reply);
+               return true;
+       end
+end);
+module:hook("iq/bare/http://jabber.org/protocol/disco#items:query", function(event)
+       local origin, stanza = event.origin, event.stanza;
+       if stanza.attr.type ~= "get" then return; end
+       local node = stanza.tags[1].attr.node;
+       if node and node ~= "" then return; end -- TODO fire event?
+       local username = jid_split(stanza.attr.to) or origin.username;
+       if not stanza.attr.to or is_contact_subscribed(username, module.host, jid_bare(stanza.attr.from)) then
+               local reply = st.reply(stanza):tag('query', {xmlns='http://jabber.org/protocol/disco#items'});
+               if not reply.attr.from then reply.attr.from = origin.username.."@"..origin.host; end -- COMPAT To satisfy Psi when querying own account
+               module:fire_event("account-disco-items", { session = origin, stanza = reply });
+               origin.send(reply);
+               return true;
+       end
+end);