summaryrefslogtreecommitdiff
path: root/src/mod_configure.erl
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2006-01-19 02:17:31 +0000
committerAlexey Shchepin <alexey@process-one.net>2006-01-19 02:17:31 +0000
commit568909d5bb454fab2023e7ab1a7cf62eff8dcd39 (patch)
tree562acb2d39d04393e19bda367791a2d8f04e6289 /src/mod_configure.erl
parent* src/odbc/ejabberd_odbc.erl: Added a way to retry database (diff)
* src/aclocal.m4: Updated for zlib support
* src/configure.ac: Likewise * src/mod_muc/mod_muc_room.erl: Weakened presence filtering, added warning in non-anonymous rooms, room destroying updated to latest JEP-0045, added a number of occupants and room name in room's disco#info reply, miscellaneous internal changes (thanks to Sergei Golovan) * src/mod_muc/mod_muc.erl: Better support for nick unregistration (thanks to Sergei Golovan) * src/ejabberd_zlib/ejabberd_zlib.erl: Zlib support (thanks to Sergei Golovan) * src/ejabberd_zlib/ejabberd_zlib_drv.c: Likewise * src/ejabberd_zlib/Makefile.in: Likewise * src/ejabberd_c2s.erl: Stream compression support (JEP-0138) * src/ejabberd_receiver.erl: Likewise * src/mod_disco.erl: Don't split node name before calling hooks (thanks to Sergei Golovan) * src/mod_configure.erl: Support for configuration using ad-hoc commands (thanks to Sergei Golovan) * src/mod_announce.erl: Support for sending announce messages using ad-hoc commands (thanks to Sergei Golovan) * src/mod_adhoc.erl: Ad-hoc support (JEP-0050) (thanks to Magnus Henoch) * src/adhoc.erl: Likewise * src/adhoc.hrl: Likewise * src/jlib.hrl: Updated (thanks to Sergei Golovan) * src/gen_mod.erl: Added function is_loaded/2 (thanks to Sergei Golovan) * src/ejabberd_service.erl: Changed error message on handshake error (thanks to Sergei Golovan) * src/ejabberd.cfg.example: Updated (thanks to Sergei Golovan) SVN Revision: 486
Diffstat (limited to '')
-rw-r--r--src/mod_configure.erl674
1 files changed, 423 insertions, 251 deletions
diff --git a/src/mod_configure.erl b/src/mod_configure.erl
index 07868674..0a21e02b 100644
--- a/src/mod_configure.erl
+++ b/src/mod_configure.erl
@@ -17,136 +17,212 @@
get_local_identity/5,
get_local_features/5,
get_local_items/5,
+ adhoc_local_items/4,
+ adhoc_local_commands/4,
+ get_sm_identity/5,
get_sm_features/5,
get_sm_items/5,
- process_local_iq/3,
- process_sm_iq/3]).
+ adhoc_sm_items/4,
+ adhoc_sm_commands/4]).
-include("ejabberd.hrl").
-include("jlib.hrl").
+-include("adhoc.hrl").
-start(Host, Opts) ->
- IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_EJABBERD_CONFIG,
- ?MODULE, process_local_iq, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_EJABBERD_CONFIG,
- ?MODULE, process_sm_iq, IQDisc),
+start(Host, _Opts) ->
ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_local_items, 50),
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_local_features, 50),
ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, get_local_identity, 50),
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, get_sm_items, 50),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
+ ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, get_sm_identity, 50),
+ ejabberd_hooks:add(adhoc_local_items, Host, ?MODULE, adhoc_local_items, 50),
+ ejabberd_hooks:add(adhoc_local_commands, Host, ?MODULE, adhoc_local_commands, 50),
+ ejabberd_hooks:add(adhoc_sm_items, Host, ?MODULE, adhoc_sm_items, 50),
+ ejabberd_hooks:add(adhoc_sm_commands, Host, ?MODULE, adhoc_sm_commands, 50),
ok.
stop(Host) ->
+ ejabberd_hooks:delete(adhoc_sm_commands, Host, ?MODULE, adhoc_sm_commands, 50),
+ ejabberd_hooks:delete(adhoc_sm_items, Host, ?MODULE, adhoc_sm_items, 50),
+ ejabberd_hooks:delete(adhoc_local_commands, Host, ?MODULE, adhoc_local_commands, 50),
+ ejabberd_hooks:delete(adhoc_local_items, Host, ?MODULE, adhoc_local_items, 50),
+ ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 50),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 50),
ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, get_local_identity, 50),
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_local_features, 50),
ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, get_local_items, 50),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_EJABBERD_CONFIG),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_EJABBERD_CONFIG).
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_COMMANDS),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_COMMANDS).
+%%%-----------------------------------------------------------------------
--define(EMPTY_INFO_RESULT, {result, Feats}).
+-define(INFO_IDENTITY(Category, Type, Name, Lang),
+ [{xmlelement, "identity",
+ [{"category", Category},
+ {"type", Type},
+ {"name", translate:translate(Lang, Name)}], []}]).
-get_sm_features({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
- Acc;
+-define(INFO_COMMAND(Name, Lang),
+ ?INFO_IDENTITY("automation", "command-node", Name, Lang)).
-get_sm_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) ->
- case {acl:match_rule(LServer, configure, From), Node} of
- {allow, []} ->
- case Acc of
- {result, Features} ->
- {result, [?NS_EJABBERD_CONFIG | Features]};
- empty ->
- {result, [?NS_EJABBERD_CONFIG]}
- end;
+get_sm_identity(Acc, _From, _To, Node, Lang) ->
+ case Node of
+ "config" ->
+ ?INFO_COMMAND("Configuration", Lang);
_ ->
Acc
end.
-get_local_identity(Acc, _From, _To, Node, _Lang) ->
- case Node of
+get_local_identity(Acc, _From, _To, Node, Lang) ->
+ LNode = string:tokens(Node, "/"),
+ case LNode of
["running nodes", ENode] ->
- [{xmlelement, "identity",
- [{"category", "ejabberd"},
- {"type", "node"},
- {"name", ENode}], []}];
+ ?INFO_IDENTITY("ejabberd", "node", ENode, Lang);
+ ["running nodes", _ENode, "DB"] ->
+ ?INFO_COMMAND("DB", Lang);
+ ["running nodes", _ENode, "modules", "start"] ->
+ ?INFO_COMMAND("Start Modules", Lang);
+ ["running nodes", _ENode, "modules", "stop"] ->
+ ?INFO_COMMAND("Stop Modules", Lang);
+ ["running nodes", _ENode, "backup", "backup"] ->
+ ?INFO_COMMAND("Backup", Lang);
+ ["running nodes", _ENode, "backup", "restore"] ->
+ ?INFO_COMMAND("Restore", Lang);
+ ["running nodes", _ENode, "backup", "textfile"] ->
+ ?INFO_COMMAND("Dump to Text File", Lang);
+ ["running nodes", _ENode, "import", "file"] ->
+ ?INFO_COMMAND("Import File", Lang);
+ ["running nodes", _ENode, "import", "dir"] ->
+ ?INFO_COMMAND("Import Directory", Lang);
+ ["config", "hostname"] ->
+ ?INFO_COMMAND("Host Name", Lang);
+ ["config", "acls"] ->
+ ?INFO_COMMAND("Access Control Lists", Lang);
+ ["config", "access"] ->
+ ?INFO_COMMAND("Access Rules", Lang);
_ ->
Acc
end.
-get_local_features({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
- Acc;
+%%%-----------------------------------------------------------------------
+
+-define(INFO_RESULT(Allow, Feats),
+ case Allow of
+ deny ->
+ {error, ?ERR_FORBIDDEN};
+ allow ->
+ {result, Feats}
+ end).
-get_local_features(Acc, _From, _To, [], _Lang) ->
- Acc;
+get_sm_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) ->
+ case gen_mod:is_loaded(LServer, mod_adhoc) of
+ false ->
+ Acc;
+ _ ->
+ Allow = acl:match_rule(LServer, configure, From),
+ case Node of
+ "config" ->
+ ?INFO_RESULT(Allow, [?NS_COMMANDS]);
+ _ ->
+ Acc
+ end
+ end.
get_local_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) ->
- Feats = case Acc of
- {result, Features} -> Features;
- empty -> []
- end,
- case {acl:match_rule(LServer, configure, From), Node} of
- {deny, _} ->
- {error, ?ERR_NOT_ALLOWED};
- {allow, ["config"]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["online users"]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["all users"]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["all users", [$@ | _]]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["outgoing s2s" | _]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["running nodes"]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["stopped nodes"]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["running nodes", _ENode]} ->
- {result, [?NS_STATS | Feats]};
- {allow, ["running nodes", _ENode, "DB"]} ->
- {result, [?NS_EJABBERD_CONFIG | Feats]};
- {allow, ["running nodes", _ENode, "modules"]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["running nodes", _ENode, "modules", _]} ->
- {result, [?NS_EJABBERD_CONFIG | Feats]};
- {allow, ["running nodes", _ENode, "backup"]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["running nodes", _ENode, "backup", _]} ->
- {result, [?NS_EJABBERD_CONFIG | Feats]};
- {allow, ["running nodes", _ENode, "import"]} ->
- ?EMPTY_INFO_RESULT;
- {allow, ["running nodes", _ENode, "import", _]} ->
- {result, [?NS_EJABBERD_CONFIG | Feats]};
- {allow, ["config", _]} ->
- {result, [?NS_EJABBERD_CONFIG | Feats]};
+ case gen_mod:is_loaded(LServer, mod_adhoc) of
+ false ->
+ Acc;
_ ->
- Acc
+ LNode = string:tokens(Node, "/"),
+ Allow = acl:match_rule(LServer, configure, From),
+ case LNode of
+ ["config"] ->
+ ?INFO_RESULT(Allow, []);
+ ["online users"] ->
+ ?INFO_RESULT(Allow, []);
+ ["all users"] ->
+ ?INFO_RESULT(Allow, []);
+ ["all users", [$@ | _]] ->
+ ?INFO_RESULT(Allow, []);
+ ["outgoing s2s" | _] ->
+ ?INFO_RESULT(Allow, []);
+ ["running nodes"] ->
+ ?INFO_RESULT(Allow, []);
+ ["stopped nodes"] ->
+ ?INFO_RESULT(Allow, []);
+ ["running nodes", _ENode] ->
+ ?INFO_RESULT(Allow, [?NS_STATS]);
+ ["running nodes", _ENode, "DB"] ->
+ ?INFO_RESULT(Allow, [?NS_COMMANDS]);
+ ["running nodes", _ENode, "modules"] ->
+ ?INFO_RESULT(Allow, []);
+ ["running nodes", _ENode, "modules", _] ->
+ ?INFO_RESULT(Allow, [?NS_COMMANDS]);
+ ["running nodes", _ENode, "backup"] ->
+ ?INFO_RESULT(Allow, []);
+ ["running nodes", _ENode, "backup", _] ->
+ ?INFO_RESULT(Allow, [?NS_COMMANDS]);
+ ["running nodes", _ENode, "import"] ->
+ ?INFO_RESULT(Allow, []);
+ ["running nodes", _ENode, "import", _] ->
+ ?INFO_RESULT(Allow, [?NS_COMMANDS]);
+ ["config", _] ->
+ ?INFO_RESULT(Allow, [?NS_COMMANDS]);
+ _ ->
+ Acc
+ end
end.
-get_sm_items({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
- Acc;
+%%%-----------------------------------------------------------------------
-get_sm_items(Acc, From,
- #jid{user = User, server = Server, lserver = LServer} = _To,
- Node, _Lang) ->
- case {acl:match_rule(LServer, configure, From), Node} of
- {allow, []} ->
+adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To, Lang) ->
+ case acl:match_rule(LServer, configure, From) of
+ allow ->
Items = case Acc of
- {result, Its} ->
- Its;
- empty ->
- []
+ {result, Its} -> Its;
+ empty -> []
end,
- {result, Items ++ get_user_resources(User, Server)};
+ Nodes = [{xmlelement, "item",
+ [{"jid", jlib:jid_to_string(To)},
+ {"name", translate:translate(Lang, "Configuration")},
+ {"node", "config"}], []}],
+ {result, Items ++ Nodes};
_ ->
Acc
end.
+%%%-----------------------------------------------------------------------
+
+get_sm_items(Acc, From,
+ #jid{user = User, server = Server, lserver = LServer} = To,
+ Node, Lang) ->
+ case gen_mod:is_loaded(LServer, mod_adhoc) of
+ false ->
+ Acc;
+ _ ->
+ Items = case Acc of
+ {result, Its} -> Its;
+ empty -> []
+ end,
+ case {acl:match_rule(LServer, configure, From), Node} of
+ {allow, ""} ->
+ Nodes = [{xmlelement, "item",
+ [{"jid", jlib:jid_to_string(To)},
+ {"name", translate:translate(Lang, "Configuration")},
+ {"node", "config"}], []}],
+ {result, Items ++ Nodes ++ get_user_resources(User, Server)};
+ {allow, "config"} ->
+ {result, []};
+ {_, "config"} ->
+ {error, ?ERR_FORBIDDEN};
+ _ ->
+ Acc
+ end
+ end.
+
get_user_resources(User, Server) ->
Rs = ejabberd_sm:get_user_resources(User, Server),
lists:map(fun(R) ->
@@ -155,31 +231,149 @@ get_user_resources(User, Server) ->
{"name", User}], []}
end, lists:sort(Rs)).
-get_local_items({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
- Acc;
+%%%-----------------------------------------------------------------------
-get_local_items(Acc, From, #jid{lserver = LServer} = To, Node, Lang) ->
- Items = case Acc of
- {result, Its} ->
- Its;
- empty ->
+adhoc_local_items(Acc, From, #jid{lserver = LServer, server = Server} = To,
+ Lang) ->
+ case acl:match_rule(LServer, configure, From) of
+ allow ->
+ Items = case Acc of
+ {result, Its} -> Its;
+ empty -> []
+ end,
+ %% Recursively get all configure commands
+ Nodes = recursively_get_local_items(LServer, "", Server, Lang),
+ Nodes1 = lists:filter(
+ fun(N) ->
+ Nd = xml:get_tag_attr_s("node", N),
+ F = get_local_features([], From, To, Nd, Lang),
+ case F of
+ {result, [?NS_COMMANDS]} ->
+ true;
+ _ ->
+ false
+ end
+ end, Nodes),
+ {result, Items ++ Nodes1};
+ _ ->
+ Acc
+ end.
+
+recursively_get_local_items(_LServer, "online users", _Server, _Lang) ->
+ [];
+
+recursively_get_local_items(_LServer, "all users", _Server, _Lang) ->
+ [];
+
+recursively_get_local_items(LServer, Node, Server, Lang) ->
+ LNode = string:tokens(Node, "/"),
+ Items = case get_local_items(LServer, LNode, Server, Lang) of
+ {result, Res} ->
+ Res;
+ {error, _Error} ->
[]
end,
- case acl:match_rule(LServer, configure, From) of
- deny when Node /= [] ->
- {error, ?ERR_NOT_ALLOWED};
+ Nodes = lists:flatten(
+ lists:map(
+ fun(N) ->
+ S = xml:get_tag_attr_s("jid", N),
+ Nd = xml:get_tag_attr_s("node", N),
+ if (S /= Server) or (Nd == "") ->
+ [];
+ true ->
+ [N, recursively_get_local_items(
+ LServer, Nd, Server, Lang)]
+ end
+ end, Items)),
+ Nodes.
+
+%%%-----------------------------------------------------------------------
+
+-define(ITEMS_RESULT(Allow, LNode, Fallback),
+ case Allow of
deny ->
- {result, Items};
- _ ->
- case get_local_items(To#jid.lserver, Node,
+ Fallback;
+ allow ->
+ case get_local_items(LServer, LNode,
jlib:jid_to_string(To), Lang) of
{result, Res} ->
- {result, Items ++ Res};
+ {result, Res};
{error, Error} ->
- {error, Error}
+ {error, Error}
+ end
+ end).
+
+get_local_items(Acc, From, #jid{lserver = LServer} = To, "", Lang) ->
+ case gen_mod:is_loaded(LServer, mod_adhoc) of
+ false ->
+ Acc;
+ _ ->
+ Items = case Acc of
+ {result, Its} -> Its;
+ empty -> []
+ end,
+ Allow = acl:match_rule(LServer, configure, From),
+ case Allow of
+ deny ->
+ {result, Items};
+ allow ->
+ case get_local_items(LServer, [],
+ jlib:jid_to_string(To), Lang) of
+ {result, Res} ->
+ {result, Items ++ Res};
+ {error, _Error} ->
+ {result, Items}
+ end
+ end
+ end;
+
+get_local_items(Acc, From, #jid{lserver = LServer} = To, Node, Lang) ->
+ case gen_mod:is_loaded(LServer, mod_adhoc) of
+ false ->
+ Acc;
+ _ ->
+ LNode = string:tokens(Node, "/"),
+ Allow = acl:match_rule(LServer, configure, From),
+ case LNode of
+ ["config"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["online users"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["all users"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["all users", [$@ | _]] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["outgoing s2s" | _] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["stopped nodes"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes", _ENode] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes", _ENode, "DB"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes", _ENode, "modules"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes", _ENode, "modules", _] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes", _ENode, "backup"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes", _ENode, "backup", _] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes", _ENode, "import"] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["running nodes", _ENode, "import", _] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ ["config", _] ->
+ ?ITEMS_RESULT(Allow, LNode, {error, ?ERR_FORBIDDEN});
+ _ ->
+ Acc
end
end.
+%%%-----------------------------------------------------------------------
+
-define(NODE(Name, Node),
{xmlelement, "item",
[{"jid", Server},
@@ -422,72 +616,86 @@ get_stopped_nodes(_Lang) ->
end, lists:sort(DBNodes))
end.
+%-------------------------------------------------------------------------
-
-process_local_iq(From, To, #iq{type = Type, xmlns = XMLNS,
- lang = Lang, sub_el = SubEl} = IQ) ->
- case acl:match_rule(To#jid.lserver, configure, From) of
+-define(COMMANDS_RESULT(Allow, From, To, Request),
+ case Allow of
deny ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ {error, ?ERR_FORBIDDEN};
allow ->
- case Type of
- set ->
- XDataEl = find_xdata_el(SubEl),
- case XDataEl of
- false ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ACCEPTABLE]};
- {xmlelement, _Name, Attrs, _SubEls} ->
- case xml:get_attr_s("type", Attrs) of
- "cancel" ->
- IQ#iq{type = result,
- sub_el = [{xmlelement, "query",
- [{"xmlns", XMLNS}], []}]};
- "submit" ->
- XData = jlib:parse_xdata_submit(XDataEl),
- case XData of
- invalid ->
- IQ#iq{type = error,
- sub_el = [SubEl, ?ERR_BAD_REQUEST]};
- _ ->
- Node =
- string:tokens(
- xml:get_tag_attr_s("node", SubEl),
- "/"),
- case set_form(Node, Lang, XData) of
- {result, Res} ->
- IQ#iq{type = result,
- sub_el =
- [{xmlelement, "query",
- [{"xmlns", XMLNS}],
- Res
- }]};
- {error, Error} ->
- IQ#iq{type = error,
- sub_el = [SubEl, Error]}
- end
- end;
- _ ->
- IQ#iq{type = error,
- sub_el = [SubEl, ?ERR_BAD_REQUEST]}
- end
- end;
- get ->
- Node =
- string:tokens(xml:get_tag_attr_s("node", SubEl), "/"),
- case get_form(Node, Lang) of
- {result, Res} ->
- IQ#iq{type = result,
- sub_el =
- [{xmlelement, "query", [{"xmlns", XMLNS}],
- Res
- }]};
+ adhoc_local_commands(From, To, Request)
+ end).
+
+adhoc_local_commands(Acc, From, #jid{lserver = LServer} = To,
+ #adhoc_request{node = Node} = Request) ->
+ LNode = string:tokens(Node, "/"),
+ Allow = acl:match_rule(LServer, configure, From),
+ case LNode of
+ ["running nodes", _ENode, "DB"] ->
+ ?COMMANDS_RESULT(Allow, From, To, Request);
+ ["running nodes", _ENode, "modules", _] ->
+ ?COMMANDS_RESULT(Allow, From, To, Request);
+ ["running nodes", _ENode, "backup", _] ->
+ ?COMMANDS_RESULT(Allow, From, To, Request);
+ ["running nodes", _ENode, "import", _] ->
+ ?COMMANDS_RESULT(Allow, From, To, Request);
+ ["config", _] ->
+ ?COMMANDS_RESULT(Allow, From, To, Request);
+ _ ->
+ Acc
+ end.
+
+adhoc_local_commands(_From, _To,
+ #adhoc_request{lang = Lang,
+ node = Node,
+ sessionid = SessionID,
+ action = Action,
+ xdata = XData} = Request) ->
+ LNode = string:tokens(Node, "/"),
+ %% If the "action" attribute is not present, it is
+ %% understood as "execute". If there was no <actions/>
+ %% element in the first response (which there isn't in our
+ %% case), "execute" and "complete" are equivalent.
+ ActionIsExecute = lists:member(Action,
+ ["", "execute", "complete"]),
+ if Action == "cancel" ->
+ %% User cancels request
+ adhoc:produce_response(
+ Request,
+ #adhoc_response{status = canceled});
+ XData == false, ActionIsExecute ->
+ %% User requests form
+ case get_form(LNode, Lang) of
+ {result, Form} ->
+ adhoc:produce_response(
+ Request,
+ #adhoc_response{status = executing,
+ elements = Form});
+ {error, Error} ->
+ {error, Error}
+ end;
+ XData /= false, ActionIsExecute ->
+ %% User returns form.
+ case jlib:parse_xdata_submit(XData) of
+ invalid ->
+ {error, ?ERR_BAD_REQUEST};
+ Fields ->
+ case set_form(LNode, Lang, Fields) of
+ {result, _Res} ->
+ adhoc:produce_response(
+ #adhoc_response{lang = Lang,
+ node = Node,
+ sessionid = SessionID,
+ status = completed});
{error, Error} ->
- IQ#iq{type = error,
- sub_el = [SubEl, Error]}
+ {error, Error}
end
- end
+ end;
+ true ->
+ {error, ?ERR_BAD_REQUEST}
end.
+
-define(TLFIELD(Type, Label, Var),
{xmlelement, "field", [{"type", Type},
{"label", translate:translate(Lang, Label)},
@@ -1107,83 +1315,60 @@ search_running_node(SNode, [Node | Nodes]) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-process_sm_iq(From, To,
- #iq{type = Type, xmlns = XMLNS, lang = Lang, sub_el = SubEl} = IQ) ->
- case acl:match_rule(To#jid.lserver, configure, From) of
+adhoc_sm_commands(_Acc, From,
+ #jid{user = User, server = Server, lserver = LServer} = _To,
+ #adhoc_request{lang = Lang,
+ node = "config",
+ action = Action,
+ xdata = XData} = Request) ->
+ case acl:match_rule(LServer, configure, From) of
deny ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
+ {error, ?ERR_FORBIDDEN};
allow ->
- #jid{user = User, server = Server} = To,
- case Type of
- set ->
- XDataEl = find_xdata_el(SubEl),
- case XDataEl of
- false ->
- IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ACCEPTABLE]};
- {xmlelement, _Name, Attrs, _SubEls} ->
- case xml:get_attr_s("type", Attrs) of
- "cancel" ->
- IQ#iq{type = result,
- sub_el = [{xmlelement, "query",
- [{"xmlns", XMLNS}], []}]};
- "submit" ->
- XData = jlib:parse_xdata_submit(XDataEl),
- case XData of
- invalid ->
- IQ#iq{type = error,
- sub_el = [SubEl, ?ERR_BAD_REQUEST]};
- _ ->
- Node =
- string:tokens(
- xml:get_tag_attr_s("node", SubEl),
- "/"),
- case set_sm_form(
- User, Server, Node,
- Lang, XData) of
- {result, Res} ->
- IQ#iq{type = result,
- sub_el =
- [{xmlelement, "query",
- [{"xmlns", XMLNS}],
- Res
- }]};
- {error, Error} ->
- IQ#iq{type = error,
- sub_el = [SubEl, Error]}
- end
- end;
- _ ->
- IQ#iq{type = error,
- sub_el = [SubEl, ?ERR_BAD_REQUEST]}
- end
- end;
- get ->
- Node =
- string:tokens(xml:get_tag_attr_s("node", SubEl), "/"),
- case get_sm_form(User, Server, Node, Lang) of
- {result, Res} ->
- IQ#iq{type = result,
- sub_el =
- [{xmlelement, "query", [{"xmlns", XMLNS}],
- Res
- }]};
+ %% If the "action" attribute is not present, it is
+ %% understood as "execute". If there was no <actions/>
+ %% element in the first response (which there isn't in our
+ %% case), "execute" and "complete" are equivalent.
+ ActionIsExecute = lists:member(Action,
+ ["", "execute", "complete"]),
+ if Action == "cancel" ->
+ %% User cancels request
+ adhoc:produce_response(
+ Request,
+ #adhoc_response{status = canceled});
+ XData == false, ActionIsExecute ->
+ %% User requests form
+ case get_sm_form(User, Server, "config", Lang) of
+ {result, Form} ->
+ adhoc:produce_response(
+ Request,
+ #adhoc_response{status = executing,
+ elements = Form});
{error, Error} ->
- IQ#iq{type = error, sub_el = [SubEl, Error]}
- end
+ {error, Error}
+ end;
+ XData /= false, ActionIsExecute ->
+ %% User returns form.
+ case jlib:parse_xdata_submit(XData) of
+ invalid ->
+ {error, ?ERR_BAD_REQUEST};
+ Fields ->
+ set_sm_form(User, Server, "config", Request, Fields)
+ end;
+ true ->
+ {error, ?ERR_BAD_REQUEST}
end
- end.
+ end;
+adhoc_sm_commands(Acc, _From, _To, _Request) ->
+ Acc.
-get_sm_form(User, Server, [], Lang) ->
+get_sm_form(User, Server, "config", Lang) ->
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
[{xmlelement, "title", [],
[{xmlcdata,
translate:translate(
Lang, "Administration of ") ++ User}]},
- %{xmlelement, "instructions", [],
- % [{xmlcdata,
- % translate:translate(
- % Lang, "Choose host name")}]},
{xmlelement, "field",
[{"type", "list-single"},
{"label", translate:translate(Lang, "Action on user")},
@@ -1198,49 +1383,36 @@ get_sm_form(User, Server, [], Lang) ->
]},
?XFIELD("text-private", "Password", "password",
ejabberd_auth:get_password_s(User, Server))
- %{xmlelement, "field", [{"type", "text-single"},
- % {"label",
- % translate:translate(Lang, "Host name")},
- % {"var", "hostname"}],
- % [{xmlelement, "value", [], [{xmlcdata, ?MYNAME}]}]}
]}]};
get_sm_form(_User, _Server, _Node, _Lang) ->
{error, ?ERR_SERVICE_UNAVAILABLE}.
-set_sm_form(User, Server, [], _Lang, XData) ->
+set_sm_form(User, Server, "config",
+ #adhoc_request{lang = Lang,
+ node = Node,
+ sessionid = SessionID}, XData) ->
+ Response = #adhoc_response{lang = Lang,
+ node = Node,
+ sessionid = SessionID,
+ status = completed},
case lists:keysearch("action", 1, XData) of
{value, {_, ["edit"]}} ->
case lists:keysearch("password", 1, XData) of
{value, {_, [Password]}} ->
ejabberd_auth:set_password(User, Server, Password),
- {result, []};
+ adhoc:produce_response(Response);
_ ->
- {error, ?ERR_BAD_REQUEST}
+ {error, ?ERR_NOT_ACCEPTABLE}
end;
{value, {_, ["remove"]}} ->
catch ejabberd_auth:remove_user(User, Server),
- {result, []};
+ adhoc:produce_response(Response);
_ ->
- {error, ?ERR_BAD_REQUEST}
+ {error, ?ERR_NOT_ACCEPTABLE}
end;
-set_sm_form(_User, _Server, _Node, _Lang, _XData) ->
- {error, ?ERR_SERVICE_UNAVAILABLE}.
-find_xdata_el({xmlelement, _Name, _Attrs, SubEls}) ->
- find_xdata_el1(SubEls).
-
-find_xdata_el1([]) ->
- false;
-
-find_xdata_el1([{xmlelement, Name, Attrs, SubEls} | Els]) ->
- case xml:get_attr_s("xmlns", Attrs) of
- ?NS_XDATA ->
- {xmlelement, Name, Attrs, SubEls};
- _ ->
- find_xdata_el1(Els)
- end;
+set_sm_form(_User, _Server, _Node, _Request, _Fields) ->
+ {error, ?ERR_SERVICE_UNAVAILABLE}.
-find_xdata_el1([_ | Els]) ->
- find_xdata_el1(Els).