| 1 | -- Copyright (C) 2009 Thilo Cestonaro |
| 2 | -- Copyright (C) 2009-2010 Florian Zeitz |
| 3 | -- |
| 4 | -- This file is MIT/X11 licensed. Please see the |
| 5 | -- COPYING file in the source package for more information. |
| 6 | -- |
| 7 | |
| 8 | local st = require "util.stanza"; |
| 9 | local is_admin = require "core.usermanager".is_admin; |
| 10 | local adhoc_handle_cmd = module:require "adhoc".handle_cmd; |
| 11 | local xmlns_cmd = "http://jabber.org/protocol/commands"; |
| 12 | local xmlns_disco = "http://jabber.org/protocol/disco"; |
| 13 | local commands = {}; |
| 14 | |
| 15 | module:add_feature(xmlns_cmd); |
| 16 | |
| 17 | module:hook("iq/host/"..xmlns_disco.."#info:query", function (event) |
| 18 | local origin, stanza = event.origin, event.stanza; |
| 19 | local node = stanza.tags[1].attr.node; |
| 20 | if stanza.attr.type == "get" and node then |
| 21 | if commands[node] then |
| 22 | local privileged = is_admin(stanza.attr.from, stanza.attr.to); |
| 23 | if (commands[node].permission == "admin" and privileged) |
| 24 | or (commands[node].permission == "user") then |
| 25 | reply = st.reply(stanza); |
| 26 | reply:tag("query", { xmlns = xmlns_disco.."#info", |
| 27 | node = node }); |
| 28 | reply:tag("identity", { name = commands[node].name, |
| 29 | category = "automation", type = "command-node" }):up(); |
| 30 | reply:tag("feature", { var = xmlns_cmd }):up(); |
| 31 | reply:tag("feature", { var = "jabber:x:data" }):up(); |
| 32 | else |
| 33 | reply = st.error_reply(stanza, "auth", "forbidden", "This item is not available to you"); |
| 34 | end |
| 35 | origin.send(reply); |
| 36 | return true; |
| 37 | elseif node == xmlns_cmd then |
| 38 | reply = st.reply(stanza); |
| 39 | reply:tag("query", { xmlns = xmlns_disco.."#info", |
| 40 | node = node }); |
| 41 | reply:tag("identity", { name = "Ad-Hoc Commands", |
| 42 | category = "automation", type = "command-list" }):up(); |
| 43 | origin.send(reply); |
| 44 | return true; |
| 45 | |
| 46 | end |
| 47 | end |
| 48 | end); |
| 49 | |
| 50 | module:hook("iq/host/"..xmlns_disco.."#items:query", function (event) |
| 51 | local origin, stanza = event.origin, event.stanza; |
| 52 | if stanza.attr.type == "get" and stanza.tags[1].attr.node |
| 53 | and stanza.tags[1].attr.node == xmlns_cmd then |
| 54 | local privileged = is_admin(stanza.attr.from, stanza.attr.to); |
| 55 | reply = st.reply(stanza); |
| 56 | reply:tag("query", { xmlns = xmlns_disco.."#items", |
| 57 | node = xmlns_cmd }); |
| 58 | for node, command in pairs(commands) do |
| 59 | if (command.permission == "admin" and privileged) |
| 60 | or (command.permission == "user") then |
| 61 | reply:tag("item", { name = command.name, |
| 62 | node = node, jid = module:get_host() }); |
| 63 | reply:up(); |
| 64 | end |
| 65 | end |
| 66 | origin.send(reply); |
| 67 | return true; |
| 68 | end |
| 69 | end, 500); |
| 70 | |
| 71 | module:hook("iq/host/"..xmlns_cmd..":command", function (event) |
| 72 | local origin, stanza = event.origin, event.stanza; |
| 73 | if stanza.attr.type == "set" then |
| 74 | local node = stanza.tags[1].attr.node |
| 75 | if commands[node] then |
| 76 | local privileged = is_admin(stanza.attr.from, stanza.attr.to); |
| 77 | if commands[node].permission == "admin" |
| 78 | and not privileged then |
| 79 | origin.send(st.error_reply(stanza, "auth", "forbidden", "You don't have permission to execute this command"):up() |
| 80 | :add_child(commands[node]:cmdtag("canceled") |
| 81 | :tag("note", {type="error"}):text("You don't have permission to execute this command"))); |
| 82 | return true |
| 83 | end |
| 84 | -- User has permission now execute the command |
| 85 | return adhoc_handle_cmd(commands[node], origin, stanza); |
| 86 | end |
| 87 | end |
| 88 | end, 500); |
| 89 | |
| 90 | local function handle_item_added(item) |
| 91 | commands[item.node] = item; |
| 92 | end |
| 93 | |
| 94 | module:hook("item-added/adhoc", function (event) |
| 95 | return handle_item_added(event.item); |
| 96 | end, 500); |
| 97 | |
| 98 | module:hook("item-removed/adhoc", function (event) |
| 99 | commands[event.item.node] = nil; |
| 100 | end, 500); |
| 101 | |
| 102 | -- Pick up any items that are already added |
| 103 | for _, item in ipairs(module:get_host_items("adhoc")) do |
| 104 | handle_item_added(item); |
| 105 | end |