1 -- Copyright (C) 2009-2010 Florian Zeitz
3 -- This file is MIT/X11 licensed. Please see the
4 -- COPYING file in the source package for more information.
7 local st
, uuid
= require
"util.stanza", require
"util.uuid";
9 local xmlns_cmd
= "http://jabber.org/protocol/commands";
15 local function _cmdtag(desc
, status
, sessionid
, action
)
16 local cmd
= st
.stanza("command", { xmlns
= xmlns_cmd
, node
= desc
.node
, status
= status
});
17 if sessionid
then cmd
.attr
.sessionid
= sessionid
; end
18 if action
then cmd
.attr
.action
= action
; end
23 function _M
.new(name
, node
, handler
, permission
)
24 return { name
= name
, node
= node
, handler
= handler
, cmdtag
= _cmdtag
, permission
= (permission
or "user") };
27 function _M
.handle_cmd(command
, origin
, stanza
)
28 local cmdtag
= stanza
.tags
[1]
29 local sessionid
= cmdtag
.attr
.sessionid
or uuid
.generate();
32 from
= stanza
.attr
.from
;
33 action
= cmdtag
.attr
.action
or "execute";
34 form
= cmdtag
:get_child("x", "jabber:x:data");
37 local data
, state
= command
:handler(dataIn
, states
[sessionid
]);
38 states
[sessionid
] = state
;
40 if data
.status
== "completed" then
41 states
[sessionid
] = nil;
42 cmdreply
= command
:cmdtag("completed", sessionid
);
43 elseif data
.status
== "canceled" then
44 states
[sessionid
] = nil;
45 cmdreply
= command
:cmdtag("canceled", sessionid
);
46 elseif data
.status
== "error" then
47 states
[sessionid
] = nil;
48 local reply
= st
.error_reply(stanza
, data
.error.type, data
.error.condition
, data
.error.message
);
52 cmdreply
= command
:cmdtag("executing", sessionid
);
53 data
.actions
= data
.actions
or { "complete" };
56 for name
, content
in pairs(data
) do
57 if name
== "info" then
58 cmdreply
:tag("note", {type="info"}):text(content
):up();
59 elseif name
== "warn" then
60 cmdreply
:tag("note", {type="warn"}):text(content
):up();
61 elseif name
== "error" then
62 cmdreply
:tag("note", {type="error"}):text(content
.message
):up();
63 elseif name
== "actions" then
64 local actions
= st
.stanza("actions", { execute = content
.default
});
65 for _
, action
in ipairs(content
) do
66 if (action
== "prev") or (action
== "next") or (action
== "complete") then
67 actions
:tag(action
):up();
69 module
:log("error", "Command %q at node %q provided an invalid action %q",
70 command
.name
, command
.node
, action
);
73 cmdreply
:add_child(actions
);
74 elseif name
== "form" then
75 cmdreply
:add_child((content
.layout
or content
):form(content
.values
));
76 elseif name
== "result" then
77 cmdreply
:add_child((content
.layout
or content
):form(content
.values
, "result"));
78 elseif name
== "other" then
79 cmdreply
:add_child(content
);
82 local reply
= st
.reply(stanza
);
83 reply
:add_child(cmdreply
);