%%%---------------------------------------------------------------------- %%% File : adhoc.erl %%% Author : Magnus Henoch %%% Purpose : Provide helper functions for ad-hoc commands (XEP-0050) %%% Created : 31 Oct 2005 by Magnus Henoch %%% %%% %%% ejabberd, Copyright (C) 2002-2013 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as %%% published by the Free Software Foundation; either version 2 of the %%% License, or (at your option) any later version. %%% %%% This program is distributed in the hope that it will be useful, %%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU %%% General Public License for more details. %%% %%% You should have received a copy of the GNU General Public License along %%% with this program; if not, write to the Free Software Foundation, Inc., %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%---------------------------------------------------------------------- -module(adhoc). -author('henoch@dtek.chalmers.se'). -export([ parse_request/1, produce_response/2, produce_response/1 ]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -include("adhoc.hrl"). %% Parse an ad-hoc request. Return either an adhoc_request record or %% an {error, ErrorType} tuple. %% -spec(parse_request/1 :: ( IQ :: iq_request()) -> adhoc_response() %% | {error, _} ). parse_request(#iq{type = set, lang = Lang, sub_el = SubEl, xmlns = ?NS_COMMANDS}) -> ?DEBUG("entering parse_request...", []), Node = xml:get_tag_attr_s(<<"node">>, SubEl), SessionID = xml:get_tag_attr_s(<<"sessionid">>, SubEl), Action = xml:get_tag_attr_s(<<"action">>, SubEl), XData = find_xdata_el(SubEl), #xmlel{children = AllEls} = SubEl, Others = case XData of false -> AllEls; _ -> lists:delete(XData, AllEls) end, #adhoc_request{ lang = Lang, node = Node, sessionid = SessionID, action = Action, xdata = XData, others = Others }; parse_request(_) -> {error, ?ERR_BAD_REQUEST}. %% Borrowed from mod_vcard.erl find_xdata_el(#xmlel{children = SubEls}) -> find_xdata_el1(SubEls). find_xdata_el1([]) -> false; find_xdata_el1([El | Els]) when is_record(El, xmlel) -> case xml:get_tag_attr_s(<<"xmlns">>, El) of ?NS_XDATA -> El; _ -> find_xdata_el1(Els) end; find_xdata_el1([_ | Els]) -> find_xdata_el1(Els). %% Produce a node to use as response from an adhoc_response %% record, filling in values for language, node and session id from %% the request. %% -spec(produce_response/2 :: ( Adhoc_Request :: adhoc_request(), Adhoc_Response :: adhoc_response()) -> Xmlel::xmlel() ). %% Produce a node to use as response from an adhoc_response %% record. produce_response(#adhoc_request{lang = Lang, node = Node, sessionid = SessionID}, Adhoc_Response) -> produce_response(Adhoc_Response#adhoc_response{ lang = Lang, node = Node, sessionid = SessionID }). %% -spec(produce_response/1 :: ( Adhoc_Response::adhoc_response()) -> Xmlel::xmlel() ). produce_response( #adhoc_response{ %lang = _Lang, node = Node, sessionid = ProvidedSessionID, status = Status, defaultaction = DefaultAction, actions = Actions, notes = Notes, elements = Elements }) -> SessionID = if is_binary(ProvidedSessionID), ProvidedSessionID /= <<"">> -> ProvidedSessionID; true -> jlib:now_to_utc_string(now()) end, case Actions of [] -> ActionsEls = []; _ -> case DefaultAction of <<"">> -> ActionsElAttrs = []; _ -> ActionsElAttrs = [{<<"execute">>, DefaultAction}] end, ActionsEls = [ #xmlel{ name = <<"actions">>, attrs = ActionsElAttrs, children = [ #xmlel{name = Action, attrs = [], children = []} || Action <- Actions] } ] end, NotesEls = lists:map(fun({Type, Text}) -> #xmlel{ name = <<"note">>, attrs = [{<<"type">>, Type}], children = [{xmlcdata, Text}] } end, Notes), #xmlel{ name = <<"command">>, attrs = [ {<<"xmlns">>, ?NS_COMMANDS}, {<<"sessionid">>, SessionID}, {<<"node">>, Node}, {<<"status">>, iolist_to_binary(atom_to_list(Status))} ], children = ActionsEls ++ NotesEls ++ Elements }.