%%%---------------------------------------------------------------------- %%% File : mod_chatcommands.erl %%% Author : %%% Purpose : Executes commands received by chat, returns result %%% Created : 30 July 2005 %%% Id : 0.1.2 %%%---------------------------------------------------------------------- %%% INSTALL: %%% 1. Copy mod_chatcommands.erl to ejabberd/src %%% 2. Add on ejabberd.cfg: %%% {access, chatcommands, [{allow, admin}]}. %%% 3. And add on 'modules' section: %%% {mod_chatcommands, [{access, chatcommands}]}, %%% 4. Recompile ejabberd and restart it. %%% %%% USAGE: %%% 1. Login to your Jabber server with an admin account %%% 2. Send a message to localhost/commands. Example: uname %%% If the message ends with a dot, it will be executed as an Erlang command. %%% Example: node(). %%% 3. The module will send the answer as a chat. %%% %%% PROBLEMS: %%% - Since it waits for the proccess to end, don't start heavy proccesses. %%% - There's no check on input, so don't use that module on a production server %%% if you don't know what you are doing. %%% CHANGELOG: %%% 0.1.2 - 1 February 2006 %%% * Added call to spawn() %%% %%% 0.1 - 30 July 2005 %%% * Initial version -module(mod_chatcommands). -author(''). -behaviour(gen_mod). -export([start/2, init/0, stop/1, execute/1, shell2/4, shell/3]). -include("ejabberd.hrl"). -include("jlib.hrl"). -define(PROCNAME, ejabberd_chatcommands). start(Host, _) -> ejabberd_hooks:add(local_send_to_resource_hook, Host, ?MODULE, shell, 50), register(gen_mod:get_module_proc(Host, ?PROCNAME), proc_lib:spawn(?MODULE, init, [])). init() -> loop(). loop() -> receive {shell, From, To, Packet, Host} -> spawn(?MODULE, shell2, [From, To, Packet, Host]), loop(); _ -> loop() end. stop(Host) -> exit(whereis(gen_mod:get_module_proc(Host, ?PROCNAME)), stop). shell(From, To, Packet) -> case To of #jid{luser = "", lresource = Res} -> {xmlelement, Name, _Attrs, _Els} = Packet, case {Res, Name} of {"commands", "message"} -> Host = To#jid.server, gen_mod:get_module_proc(Host, ?PROCNAME) ! {shell, From, To, Packet, Host}, stop; _ -> ok end; _ -> ok end. shell2(From, To, Packet, Host) -> Access = gen_mod:get_module_opt(Host, ?MODULE, access, none), case acl:match_rule(Host, Access, From) of deny -> Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED), ejabberd_router:route(To, From, Err); allow -> SubEl1 = xml:get_subtag(Packet, "body"), Text1 = xml:get_tag_cdata(SubEl1), Text2 = execute(Text1), SubEl2 = [{xmlelement, "body", [], [{xmlcdata, Text2}]}], Re = {xmlelement, "message", [{"type", "chat"}], SubEl2}, ejabberd_router:route(To, From, Re) end. execute(C) -> case regexp:match(C, "^.*\\.$") of {match, _, _} -> exece(C); nomatch -> exec(C) end. exece(C) -> {ok, A2, _} = erl_scan:string(C), {ok, A3} = erl_parse:parse_exprs(A2), {value, Res, _} = erl_eval:exprs(A3, []), io_lib:format("~w", [Res]). exec(C) -> Res = os:cmd(C), io_lib:format("~s", [Res]).