net.http.server: Properly handle persistent connections
[prosody.git] / plugins / adhoc / mod_adhoc.lua
index 6f91a61bcac808253063ed5e72dbdcfba748d494..69b2c8da9903e101afce81f053f4d00d7a0197d6 100644 (file)
@@ -1,5 +1,6 @@
 -- Copyright (C) 2009 Thilo Cestonaro
--- 
+-- Copyright (C) 2009-2011 Florian Zeitz
+--
 -- This file is MIT/X11 licensed. Please see the
 -- COPYING file in the source package for more information.
 --
@@ -13,18 +14,51 @@ local commands = {};
 
 module:add_feature(xmlns_cmd);
 
+module:hook("iq/host/"..xmlns_disco.."#info:query", function (event)
+       local origin, stanza = event.origin, event.stanza;
+       local node = stanza.tags[1].attr.node;
+       if stanza.attr.type == "get" and node then
+               if commands[node] then
+                       local privileged = is_admin(stanza.attr.from, stanza.attr.to);
+                       if (commands[node].permission == "admin" and privileged)
+                           or (commands[node].permission == "user") then
+                               reply = st.reply(stanza);
+                               reply:tag("query", { xmlns = xmlns_disco.."#info",
+                                   node = node });
+                               reply:tag("identity", { name = commands[node].name,
+                                   category = "automation", type = "command-node" }):up();
+                               reply:tag("feature", { var = xmlns_cmd }):up();
+                               reply:tag("feature", { var = "jabber:x:data" }):up();
+                       else
+                               reply = st.error_reply(stanza, "auth", "forbidden", "This item is not available to you");
+                       end
+                       origin.send(reply);
+                       return true;
+               elseif node == xmlns_cmd then
+                       reply = st.reply(stanza);
+                       reply:tag("query", { xmlns = xmlns_disco.."#info",
+                           node = node });
+                       reply:tag("identity", { name = "Ad-Hoc Commands",
+                           category = "automation", type = "command-list" }):up();
+                       origin.send(reply);
+                       return true;
+
+               end
+       end
+end);
+
 module:hook("iq/host/"..xmlns_disco.."#items:query", function (event)
        local origin, stanza = event.origin, event.stanza;
-       -- TODO: Is this correct, or should is_admin be changed?
-       local privileged = is_admin(stanza.attr.from)
-           or is_admin(stanza.attr.from, stanza.attr.to); 
        if stanza.attr.type == "get" and stanza.tags[1].attr.node
            and stanza.tags[1].attr.node == xmlns_cmd then
+               local admin = is_admin(stanza.attr.from, stanza.attr.to);
+               local global_admin = is_admin(stanza.attr.from);
                reply = st.reply(stanza);
                reply:tag("query", { xmlns = xmlns_disco.."#items",
                    node = xmlns_cmd });
                for node, command in pairs(commands) do
-                       if (command.permission == "admin" and privileged)
+                       if (command.permission == "admin" and admin)
+                           or (command.permission == "global_admin" and global_admin)
                            or (command.permission == "user") then
                                reply:tag("item", { name = command.name,
                                    node = node, jid = module:get_host() });
@@ -36,17 +70,15 @@ module:hook("iq/host/"..xmlns_disco.."#items:query", function (event)
        end
 end, 500);
 
-module:hook("iq/host", function (event)
+module:hook("iq/host/"..xmlns_cmd..":command", function (event)
        local origin, stanza = event.origin, event.stanza;
-       if stanza.attr.type == "set" and stanza.tags[1]
-           and stanza.tags[1].name == "command" then 
+       if stanza.attr.type == "set" then
                local node = stanza.tags[1].attr.node
-               -- TODO: Is this correct, or should is_admin be changed?
-               local privileged = is_admin(event.stanza.attr.from)
-                   or is_admin(stanza.attr.from, stanza.attr.to);
                if commands[node] then
-                       if commands[node].permission == "admin"
-                           and not privileged then
+                       local admin = is_admin(stanza.attr.from, stanza.attr.to);
+                       local global_admin = is_admin(stanza.attr.from);
+                       if (commands[node].permission == "admin" and not admin)
+                           or (commands[node].permission == "global_admin" and not global_admin) then
                                origin.send(st.error_reply(stanza, "auth", "forbidden", "You don't have permission to execute this command"):up()
                                    :add_child(commands[node]:cmdtag("canceled")
                                        :tag("note", {type="error"}):text("You don't have permission to execute this command")));
@@ -58,19 +90,14 @@ module:hook("iq/host", function (event)
        end
 end, 500);
 
-local function handle_item_added(item)
+local function adhoc_added(event)
+       local item = event.item;
        commands[item.node] = item;
 end
 
-module:hook("item-added/adhoc", function (event)
-       return handle_item_added(event.item);
-end, 500);
-
-module:hook("item-removed/adhoc", function (event)
+local function adhoc_removed(event)
        commands[event.item.node] = nil;
-end, 500);
-
--- Pick up any items that are already added
-for _, item in ipairs(module:get_host_items("adhoc")) do
-       handle_item_added(item);
 end
+
+module:handle_items("adhoc", adhoc_added, adhoc_removed);
+module:handle_items("adhoc-provider", adhoc_added, adhoc_removed);