aboutsummaryrefslogtreecommitdiff
path: root/src/mod_configure.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_configure.erl')
-rw-r--r--src/mod_configure.erl2182
1 files changed, 755 insertions, 1427 deletions
diff --git a/src/mod_configure.erl b/src/mod_configure.erl
index d0e0166a4..1a327064e 100644
--- a/src/mod_configure.erl
+++ b/src/mod_configure.erl
@@ -5,7 +5,7 @@
%%% Created : 19 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
-%%% ejabberd, Copyright (C) 2002-2016 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2019 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -31,21 +31,18 @@
-behaviour(gen_mod).
--export([start/2, stop/1, get_local_identity/5,
+-export([start/2, stop/1, reload/3, 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,
- adhoc_sm_items/4, adhoc_sm_commands/4, mod_opt_type/1,
+ adhoc_sm_items/4, adhoc_sm_commands/4, mod_options/1,
depends/2]).
--include("ejabberd.hrl").
-include("logger.hrl").
-
--include("jlib.hrl").
+-include("xmpp.hrl").
-include("ejabberd_sm.hrl").
--include("adhoc.hrl").
-
--define(T(Lang, Text), translate:translate(Lang, Text)).
+-include("translate.hrl").
+-include_lib("stdlib/include/ms_transform.hrl").
start(Host, _Opts) ->
ejabberd_hooks:add(disco_local_items, Host, ?MODULE,
@@ -90,11 +87,10 @@ stop(Host) ->
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_COMMANDS),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
- ?NS_COMMANDS).
+ get_local_items, 50).
+
+reload(_Host, _NewOpts, _OldOpts) ->
+ ok.
depends(_Host, _Opts) ->
[{mod_adhoc, hard}, {mod_last, soft}].
@@ -102,29 +98,19 @@ depends(_Host, _Opts) ->
%%%-----------------------------------------------------------------------
-define(INFO_IDENTITY(Category, Type, Name, Lang),
- [#xmlel{name = <<"identity">>,
- attrs =
- [{<<"category">>, Category}, {<<"type">>, Type},
- {<<"name">>, ?T(Lang, Name)}],
- children = []}]).
+ [#identity{category = Category, type = Type, name = tr(Lang, Name)}]).
-define(INFO_COMMAND(Name, Lang),
?INFO_IDENTITY(<<"automation">>, <<"command-node">>,
Name, Lang)).
-define(NODEJID(To, Name, Node),
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>, jid:to_string(To)},
- {<<"name">>, ?T(Lang, Name)}, {<<"node">>, Node}],
- children = []}).
+ #disco_item{jid = To, name = tr(Lang, Name), node = Node}).
-define(NODE(Name, Node),
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>, Server}, {<<"name">>, ?T(Lang, Name)},
- {<<"node">>, Node}],
- children = []}).
+ #disco_item{jid = jid:make(Server),
+ node = Node,
+ name = tr(Lang, Name)}).
-define(NS_ADMINX(Sub),
<<(?NS_ADMIN)/binary, "#", Sub/binary>>).
@@ -133,70 +119,63 @@ depends(_Host, _Opts) ->
[<<"http:">>, <<"jabber.org">>, <<"protocol">>,
<<"admin">>, Sub]).
+-spec tokenize(binary()) -> [binary()].
tokenize(Node) -> str:tokens(Node, <<"/#">>).
+-spec get_sm_identity([identity()], jid(), jid(), binary(), binary()) -> [identity()].
get_sm_identity(Acc, _From, _To, Node, Lang) ->
case Node of
<<"config">> ->
- ?INFO_COMMAND(<<"Configuration">>, Lang);
+ ?INFO_COMMAND(?T("Configuration"), Lang);
_ -> Acc
end.
+-spec get_local_identity([identity()], jid(), jid(), binary(), binary()) -> [identity()].
get_local_identity(Acc, _From, _To, Node, Lang) ->
LNode = tokenize(Node),
case LNode of
[<<"running nodes">>, ENode] ->
?INFO_IDENTITY(<<"ejabberd">>, <<"node">>, ENode, Lang);
[<<"running nodes">>, _ENode, <<"DB">>] ->
- ?INFO_COMMAND(<<"Database">>, Lang);
- [<<"running nodes">>, _ENode, <<"modules">>,
- <<"start">>] ->
- ?INFO_COMMAND(<<"Start Modules">>, Lang);
- [<<"running nodes">>, _ENode, <<"modules">>,
- <<"stop">>] ->
- ?INFO_COMMAND(<<"Stop Modules">>, Lang);
+ ?INFO_COMMAND(?T("Database"), Lang);
[<<"running nodes">>, _ENode, <<"backup">>,
<<"backup">>] ->
- ?INFO_COMMAND(<<"Backup">>, Lang);
+ ?INFO_COMMAND(?T("Backup"), Lang);
[<<"running nodes">>, _ENode, <<"backup">>,
<<"restore">>] ->
- ?INFO_COMMAND(<<"Restore">>, Lang);
+ ?INFO_COMMAND(?T("Restore"), Lang);
[<<"running nodes">>, _ENode, <<"backup">>,
<<"textfile">>] ->
- ?INFO_COMMAND(<<"Dump to Text File">>, Lang);
+ ?INFO_COMMAND(?T("Dump to Text File"), Lang);
[<<"running nodes">>, _ENode, <<"import">>,
<<"file">>] ->
- ?INFO_COMMAND(<<"Import File">>, Lang);
+ ?INFO_COMMAND(?T("Import File"), Lang);
[<<"running nodes">>, _ENode, <<"import">>,
<<"dir">>] ->
- ?INFO_COMMAND(<<"Import Directory">>, Lang);
+ ?INFO_COMMAND(?T("Import Directory"), Lang);
[<<"running nodes">>, _ENode, <<"restart">>] ->
- ?INFO_COMMAND(<<"Restart Service">>, Lang);
+ ?INFO_COMMAND(?T("Restart Service"), Lang);
[<<"running nodes">>, _ENode, <<"shutdown">>] ->
- ?INFO_COMMAND(<<"Shut Down Service">>, Lang);
+ ?INFO_COMMAND(?T("Shut Down Service"), Lang);
?NS_ADMINL(<<"add-user">>) ->
- ?INFO_COMMAND(<<"Add User">>, Lang);
+ ?INFO_COMMAND(?T("Add User"), Lang);
?NS_ADMINL(<<"delete-user">>) ->
- ?INFO_COMMAND(<<"Delete User">>, Lang);
+ ?INFO_COMMAND(?T("Delete User"), Lang);
?NS_ADMINL(<<"end-user-session">>) ->
- ?INFO_COMMAND(<<"End User Session">>, Lang);
+ ?INFO_COMMAND(?T("End User Session"), Lang);
?NS_ADMINL(<<"get-user-password">>) ->
- ?INFO_COMMAND(<<"Get User Password">>, Lang);
+ ?INFO_COMMAND(?T("Get User Password"), Lang);
?NS_ADMINL(<<"change-user-password">>) ->
- ?INFO_COMMAND(<<"Change User Password">>, Lang);
+ ?INFO_COMMAND(?T("Change User Password"), Lang);
?NS_ADMINL(<<"get-user-lastlogin">>) ->
- ?INFO_COMMAND(<<"Get User Last Login Time">>, Lang);
+ ?INFO_COMMAND(?T("Get User Last Login Time"), Lang);
?NS_ADMINL(<<"user-stats">>) ->
- ?INFO_COMMAND(<<"Get User Statistics">>, Lang);
+ ?INFO_COMMAND(?T("Get User Statistics"), Lang);
?NS_ADMINL(<<"get-registered-users-num">>) ->
- ?INFO_COMMAND(<<"Get Number of Registered Users">>,
+ ?INFO_COMMAND(?T("Get Number of Registered Users"),
Lang);
?NS_ADMINL(<<"get-online-users-num">>) ->
- ?INFO_COMMAND(<<"Get Number of Online Users">>, Lang);
- [<<"config">>, <<"acls">>] ->
- ?INFO_COMMAND(<<"Access Control Lists">>, Lang);
- [<<"config">>, <<"access">>] ->
- ?INFO_COMMAND(<<"Access Rules">>, Lang);
+ ?INFO_COMMAND(?T("Get Number of Online Users"), Lang);
_ -> Acc
end.
@@ -204,10 +183,12 @@ get_local_identity(Acc, _From, _To, Node, Lang) ->
-define(INFO_RESULT(Allow, Feats, Lang),
case Allow of
- deny -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)};
+ deny -> {error, xmpp:err_forbidden(?T("Access denied by service policy"), Lang)};
allow -> {result, Feats}
end).
+-spec get_sm_features(mod_disco:features_acc(), jid(), jid(),
+ binary(), binary()) -> mod_disco:features_acc().
get_sm_features(Acc, From,
#jid{lserver = LServer} = _To, Node, Lang) ->
case gen_mod:is_loaded(LServer, mod_adhoc) of
@@ -220,6 +201,8 @@ get_sm_features(Acc, From,
end
end.
+-spec get_local_features(mod_disco:features_acc(), jid(), jid(),
+ binary(), binary()) -> mod_disco:features_acc().
get_local_features(Acc, From,
#jid{lserver = LServer} = _To, Node, Lang) ->
case gen_mod:is_loaded(LServer, mod_adhoc) of
@@ -241,10 +224,6 @@ get_local_features(Acc, From,
?INFO_RESULT(Allow, [?NS_STATS], Lang);
[<<"running nodes">>, _ENode, <<"DB">>] ->
?INFO_RESULT(Allow, [?NS_COMMANDS], Lang);
- [<<"running nodes">>, _ENode, <<"modules">>] ->
- ?INFO_RESULT(Allow, [], Lang);
- [<<"running nodes">>, _ENode, <<"modules">>, _] ->
- ?INFO_RESULT(Allow, [?NS_COMMANDS], Lang);
[<<"running nodes">>, _ENode, <<"backup">>] ->
?INFO_RESULT(Allow, [], Lang);
[<<"running nodes">>, _ENode, <<"backup">>, _] ->
@@ -282,7 +261,8 @@ get_local_features(Acc, From,
end.
%%%-----------------------------------------------------------------------
-
+-spec adhoc_sm_items(mod_disco:items_acc(),
+ jid(), jid(), binary()) -> mod_disco:items_acc().
adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To,
Lang) ->
case acl:match_rule(LServer, configure, From) of
@@ -291,18 +271,15 @@ adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To,
{result, Its} -> Its;
empty -> []
end,
- Nodes = [#xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>, jid:to_string(To)},
- {<<"name">>, ?T(Lang, <<"Configuration">>)},
- {<<"node">>, <<"config">>}],
- children = []}],
+ Nodes = [#disco_item{jid = To, node = <<"config">>,
+ name = tr(Lang, ?T("Configuration"))}],
{result, Items ++ Nodes};
_ -> Acc
end.
%%%-----------------------------------------------------------------------
-
+-spec get_sm_items(mod_disco:items_acc(), jid(), jid(),
+ binary(), binary()) -> mod_disco:items_acc().
get_sm_items(Acc, From,
#jid{user = User, server = Server, lserver = LServer} =
To,
@@ -316,33 +293,31 @@ get_sm_items(Acc, From,
end,
case {acl:match_rule(LServer, configure, From), Node} of
{allow, <<"">>} ->
- Nodes = [?NODEJID(To, <<"Configuration">>,
+ Nodes = [?NODEJID(To, ?T("Configuration"),
<<"config">>),
- ?NODEJID(To, <<"User Management">>, <<"user">>)],
+ ?NODEJID(To, ?T("User Management"), <<"user">>)],
{result,
Items ++ Nodes ++ get_user_resources(User, Server)};
{allow, <<"config">>} -> {result, []};
{_, <<"config">>} ->
- {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)};
+ {error, xmpp:err_forbidden(?T("Access denied by service policy"), Lang)};
_ -> Acc
end
end.
+-spec get_user_resources(binary(), binary()) -> [disco_item()].
get_user_resources(User, Server) ->
Rs = ejabberd_sm:get_user_resources(User, Server),
lists:map(fun (R) ->
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>,
- <<User/binary, "@", Server/binary, "/",
- R/binary>>},
- {<<"name">>, User}],
- children = []}
+ #disco_item{jid = jid:make(User, Server, R),
+ name = User}
end,
lists:sort(Rs)).
%%%-----------------------------------------------------------------------
+-spec adhoc_local_items(mod_disco:items_acc(),
+ jid(), jid(), binary()) -> mod_disco:items_acc().
adhoc_local_items(Acc, From,
#jid{lserver = LServer, server = Server} = To, Lang) ->
case acl:match_rule(LServer, configure, From) of
@@ -354,20 +329,21 @@ adhoc_local_items(Acc, From,
PermLev = get_permission_level(From),
Nodes = recursively_get_local_items(PermLev, LServer,
<<"">>, Server, Lang),
- Nodes1 = lists:filter(fun (N) ->
- Nd = fxml: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),
+ Nodes1 = lists:filter(
+ fun (#disco_item{node = Nd}) ->
+ F = get_local_features(empty, From, To, Nd, Lang),
+ case F of
+ {result, [?NS_COMMANDS]} -> true;
+ _ -> false
+ end
+ end,
+ Nodes),
{result, Items ++ Nodes1};
_ -> Acc
end.
+-spec recursively_get_local_items(global | vhost, binary(), binary(),
+ binary(), binary()) -> [disco_item()].
recursively_get_local_items(_PermLev, _LServer,
<<"online users">>, _Server, _Lang) ->
[];
@@ -383,26 +359,21 @@ recursively_get_local_items(PermLev, LServer, Node,
{result, Res} -> Res;
{error, _Error} -> []
end,
- Nodes = lists:flatten(lists:map(fun (N) ->
- S = fxml:get_tag_attr_s(<<"jid">>,
- N),
- Nd = fxml:get_tag_attr_s(<<"node">>,
- N),
- if (S /= Server) or
- (Nd == <<"">>) ->
- [];
- true ->
- [N,
- recursively_get_local_items(PermLev,
- LServer,
- Nd,
- Server,
- Lang)]
- end
- end,
- Items)),
- Nodes.
+ lists:flatten(
+ lists:map(
+ fun(#disco_item{jid = #jid{server = S}, node = Nd} = Item) ->
+ if (S /= Server) or
+ (Nd == <<"">>) ->
+ [];
+ true ->
+ [Item,
+ recursively_get_local_items(
+ PermLev, LServer, Nd, Server, Lang)]
+ end
+ end,
+ Items)).
+-spec get_permission_level(jid()) -> global | vhost.
get_permission_level(JID) ->
case acl:match_rule(global, configure, JID) of
allow -> global;
@@ -417,13 +388,15 @@ get_permission_level(JID) ->
allow ->
PermLev = get_permission_level(From),
case get_local_items({PermLev, LServer}, LNode,
- jid:to_string(To), Lang)
+ jid:encode(To), Lang)
of
{result, Res} -> {result, Res};
{error, Error} -> {error, Error}
end
end).
+-spec get_local_items(mod_disco:items_acc(), jid(), jid(),
+ binary(), binary()) -> mod_disco:items_acc().
get_local_items(Acc, From, #jid{lserver = LServer} = To,
<<"">>, Lang) ->
case gen_mod:is_loaded(LServer, mod_adhoc) of
@@ -439,7 +412,7 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To,
allow ->
PermLev = get_permission_level(From),
case get_local_items({PermLev, LServer}, [],
- jid:to_string(To), Lang)
+ jid:encode(To), Lang)
of
{result, Res} -> {result, Items ++ Res};
{error, _Error} -> {result, Items}
@@ -453,7 +426,7 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To,
_ ->
LNode = tokenize(Node),
Allow = acl:match_rule(LServer, configure, From),
- Err = ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>),
+ Err = xmpp:err_forbidden(?T("Access denied by service policy"), Lang),
case LNode of
[<<"config">>] ->
?ITEMS_RESULT(Allow, LNode, {error, Err});
@@ -475,10 +448,6 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To,
?ITEMS_RESULT(Allow, LNode, {error, Err});
[<<"running nodes">>, _ENode, <<"DB">>] ->
?ITEMS_RESULT(Allow, LNode, {error, Err});
- [<<"running nodes">>, _ENode, <<"modules">>] ->
- ?ITEMS_RESULT(Allow, LNode, {error, Err});
- [<<"running nodes">>, _ENode, <<"modules">>, _] ->
- ?ITEMS_RESULT(Allow, LNode, {error, Err});
[<<"running nodes">>, _ENode, <<"backup">>] ->
?ITEMS_RESULT(Allow, LNode, {error, Err});
[<<"running nodes">>, _ENode, <<"backup">>, _] ->
@@ -516,45 +485,39 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To,
end.
%%%-----------------------------------------------------------------------
-
-%% @spec ({PermissionLevel, Host}, [string()], Server::string(), Lang)
-%% -> {result, [xmlelement()]}
-%% PermissionLevel = global | vhost
+-spec get_local_items({global | vhost, binary()}, [binary()],
+ binary(), binary()) -> {result, [disco_item()]} | {error, stanza_error()}.
get_local_items(_Host, [], Server, Lang) ->
{result,
- [?NODE(<<"Configuration">>, <<"config">>),
- ?NODE(<<"User Management">>, <<"user">>),
- ?NODE(<<"Online Users">>, <<"online users">>),
- ?NODE(<<"All Users">>, <<"all users">>),
- ?NODE(<<"Outgoing s2s Connections">>,
+ [?NODE(?T("Configuration"), <<"config">>),
+ ?NODE(?T("User Management"), <<"user">>),
+ ?NODE(?T("Online Users"), <<"online users">>),
+ ?NODE(?T("All Users"), <<"all users">>),
+ ?NODE(?T("Outgoing s2s Connections"),
<<"outgoing s2s">>),
- ?NODE(<<"Running Nodes">>, <<"running nodes">>),
- ?NODE(<<"Stopped Nodes">>, <<"stopped nodes">>)]};
-get_local_items(_Host, [<<"config">>], Server, Lang) ->
- {result,
- [?NODE(<<"Access Control Lists">>, <<"config/acls">>),
- ?NODE(<<"Access Rules">>, <<"config/access">>)]};
+ ?NODE(?T("Running Nodes"), <<"running nodes">>),
+ ?NODE(?T("Stopped Nodes"), <<"stopped nodes">>)]};
get_local_items(_Host, [<<"config">>, _], _Server,
_Lang) ->
{result, []};
get_local_items(_Host, [<<"user">>], Server, Lang) ->
{result,
- [?NODE(<<"Add User">>, (?NS_ADMINX(<<"add-user">>))),
- ?NODE(<<"Delete User">>,
+ [?NODE(?T("Add User"), (?NS_ADMINX(<<"add-user">>))),
+ ?NODE(?T("Delete User"),
(?NS_ADMINX(<<"delete-user">>))),
- ?NODE(<<"End User Session">>,
+ ?NODE(?T("End User Session"),
(?NS_ADMINX(<<"end-user-session">>))),
- ?NODE(<<"Get User Password">>,
+ ?NODE(?T("Get User Password"),
(?NS_ADMINX(<<"get-user-password">>))),
- ?NODE(<<"Change User Password">>,
+ ?NODE(?T("Change User Password"),
(?NS_ADMINX(<<"change-user-password">>))),
- ?NODE(<<"Get User Last Login Time">>,
+ ?NODE(?T("Get User Last Login Time"),
(?NS_ADMINX(<<"get-user-lastlogin">>))),
- ?NODE(<<"Get User Statistics">>,
+ ?NODE(?T("Get User Statistics"),
(?NS_ADMINX(<<"user-stats">>))),
- ?NODE(<<"Get Number of Registered Users">>,
+ ?NODE(?T("Get Number of Registered Users"),
(?NS_ADMINX(<<"get-registered-users-num">>))),
- ?NODE(<<"Get Number of Online Users">>,
+ ?NODE(?T("Get Number of Online Users"),
(?NS_ADMINX(<<"get-online-users-num">>)))]};
get_local_items(_Host, [<<"http:">> | _], _Server,
_Lang) ->
@@ -568,29 +531,20 @@ get_local_items({_, Host}, [<<"all users">>], _Server,
get_local_items({_, Host},
[<<"all users">>, <<$@, Diap/binary>>], _Server,
_Lang) ->
- Users = ejabberd_auth:get_vh_registered_users(Host),
+ Users = ejabberd_auth:get_users(Host),
SUsers = lists:sort([{S, U} || {U, S} <- Users]),
- case catch begin
- [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>),
- N1 = jlib:binary_to_integer(S1),
- N2 = jlib:binary_to_integer(S2),
- Sub = lists:sublist(SUsers, N1, N2 - N1 + 1),
- lists:map(fun ({S, U}) ->
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>,
- <<U/binary, "@",
- S/binary>>},
- {<<"name">>,
- <<U/binary, "@",
- S/binary>>}],
- children = []}
- end,
- Sub)
- end
- of
- {'EXIT', _Reason} -> ?ERR_NOT_ACCEPTABLE;
- Res -> {result, Res}
+ try
+ [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>),
+ N1 = binary_to_integer(S1),
+ N2 = binary_to_integer(S2),
+ Sub = lists:sublist(SUsers, N1, N2 - N1 + 1),
+ {result, lists:map(
+ fun({S, U}) ->
+ #disco_item{jid = jid:make(U, S),
+ name = <<U/binary, $@, S/binary>>}
+ end, Sub)}
+ catch _:_ ->
+ {error, xmpp:err_not_acceptable()}
end;
get_local_items({_, Host}, [<<"outgoing s2s">>],
_Server, Lang) ->
@@ -607,48 +561,29 @@ get_local_items(_Host, [<<"stopped nodes">>], _Server,
get_local_items({global, _Host},
[<<"running nodes">>, ENode], Server, Lang) ->
{result,
- [?NODE(<<"Database">>,
+ [?NODE(?T("Database"),
<<"running nodes/", ENode/binary, "/DB">>),
- ?NODE(<<"Modules">>,
- <<"running nodes/", ENode/binary, "/modules">>),
- ?NODE(<<"Backup Management">>,
+ ?NODE(?T("Backup Management"),
<<"running nodes/", ENode/binary, "/backup">>),
- ?NODE(<<"Import Users From jabberd14 Spool Files">>,
+ ?NODE(?T("Import Users From jabberd14 Spool Files"),
<<"running nodes/", ENode/binary, "/import">>),
- ?NODE(<<"Restart Service">>,
+ ?NODE(?T("Restart Service"),
<<"running nodes/", ENode/binary, "/restart">>),
- ?NODE(<<"Shut Down Service">>,
+ ?NODE(?T("Shut Down Service"),
<<"running nodes/", ENode/binary, "/shutdown">>)]};
-get_local_items({vhost, _Host},
- [<<"running nodes">>, ENode], Server, Lang) ->
- {result,
- [?NODE(<<"Modules">>,
- <<"running nodes/", ENode/binary, "/modules">>)]};
get_local_items(_Host,
[<<"running nodes">>, _ENode, <<"DB">>], _Server,
_Lang) ->
{result, []};
get_local_items(_Host,
- [<<"running nodes">>, ENode, <<"modules">>], Server,
- Lang) ->
- {result,
- [?NODE(<<"Start Modules">>,
- <<"running nodes/", ENode/binary, "/modules/start">>),
- ?NODE(<<"Stop Modules">>,
- <<"running nodes/", ENode/binary, "/modules/stop">>)]};
-get_local_items(_Host,
- [<<"running nodes">>, _ENode, <<"modules">>, _],
- _Server, _Lang) ->
- {result, []};
-get_local_items(_Host,
[<<"running nodes">>, ENode, <<"backup">>], Server,
Lang) ->
{result,
- [?NODE(<<"Backup">>,
+ [?NODE(?T("Backup"),
<<"running nodes/", ENode/binary, "/backup/backup">>),
- ?NODE(<<"Restore">>,
+ ?NODE(?T("Restore"),
<<"running nodes/", ENode/binary, "/backup/restore">>),
- ?NODE(<<"Dump to Text File">>,
+ ?NODE(?T("Dump to Text File"),
<<"running nodes/", ENode/binary,
"/backup/textfile">>)]};
get_local_items(_Host,
@@ -659,9 +594,9 @@ get_local_items(_Host,
[<<"running nodes">>, ENode, <<"import">>], Server,
Lang) ->
{result,
- [?NODE(<<"Import File">>,
+ [?NODE(?T("Import File"),
<<"running nodes/", ENode/binary, "/import/file">>),
- ?NODE(<<"Import Directory">>,
+ ?NODE(?T("Import Directory"),
<<"running nodes/", ENode/binary, "/import/dir">>)]};
get_local_items(_Host,
[<<"running nodes">>, _ENode, <<"import">>, _], _Server,
@@ -676,173 +611,120 @@ get_local_items(_Host,
_Lang) ->
{result, []};
get_local_items(_Host, _, _Server, _Lang) ->
- {error, ?ERR_ITEM_NOT_FOUND}.
+ {error, xmpp:err_item_not_found()}.
+-spec get_online_vh_users(binary()) -> [disco_item()].
get_online_vh_users(Host) ->
- case catch ejabberd_sm:get_vh_session_list(Host) of
- {'EXIT', _Reason} -> [];
- USRs ->
- SURs = lists:sort([{S, U, R} || {U, S, R} <- USRs]),
- lists:map(fun ({S, U, R}) ->
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>,
- <<U/binary, "@", S/binary, "/",
- R/binary>>},
- {<<"name">>,
- <<U/binary, "@", S/binary>>}],
- children = []}
- end,
- SURs)
- end.
-
+ USRs = ejabberd_sm:get_vh_session_list(Host),
+ SURs = lists:sort([{S, U, R} || {U, S, R} <- USRs]),
+ lists:map(
+ fun({S, U, R}) ->
+ #disco_item{jid = jid:make(U, S, R),
+ name = <<U/binary, "@", S/binary>>}
+ end, SURs).
+
+-spec get_all_vh_users(binary()) -> [disco_item()].
get_all_vh_users(Host) ->
- case catch ejabberd_auth:get_vh_registered_users(Host)
- of
- {'EXIT', _Reason} -> [];
- Users ->
- SUsers = lists:sort([{S, U} || {U, S} <- Users]),
- case length(SUsers) of
- N when N =< 100 ->
- lists:map(fun ({S, U}) ->
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>,
- <<U/binary, "@", S/binary>>},
- {<<"name">>,
- <<U/binary, "@", S/binary>>}],
- children = []}
- end,
- SUsers);
- N ->
- NParts = trunc(math:sqrt(N * 6.17999999999999993783e-1))
- + 1,
- M = trunc(N / NParts) + 1,
- lists:map(fun (K) ->
- L = K + M - 1,
- Node = <<"@",
- (iolist_to_binary(integer_to_list(K)))/binary,
- "-",
- (iolist_to_binary(integer_to_list(L)))/binary>>,
- {FS, FU} = lists:nth(K, SUsers),
- {LS, LU} = if L < N -> lists:nth(L, SUsers);
- true -> lists:last(SUsers)
- end,
- Name = <<FU/binary, "@", FS/binary, " -- ",
- LU/binary, "@", LS/binary>>,
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>, Host},
- {<<"node">>,
- <<"all users/", Node/binary>>},
- {<<"name">>, Name}],
- children = []}
- end,
- lists:seq(1, N, M))
- end
+ Users = ejabberd_auth:get_users(Host),
+ SUsers = lists:sort([{S, U} || {U, S} <- Users]),
+ case length(SUsers) of
+ N when N =< 100 ->
+ lists:map(fun({S, U}) ->
+ #disco_item{jid = jid:make(U, S),
+ name = <<U/binary, $@, S/binary>>}
+ end, SUsers);
+ N ->
+ NParts = trunc(math:sqrt(N * 6.17999999999999993783e-1)) + 1,
+ M = trunc(N / NParts) + 1,
+ lists:map(
+ fun (K) ->
+ L = K + M - 1,
+ Node = <<"@",
+ (integer_to_binary(K))/binary,
+ "-",
+ (integer_to_binary(L))/binary>>,
+ {FS, FU} = lists:nth(K, SUsers),
+ {LS, LU} = if L < N -> lists:nth(L, SUsers);
+ true -> lists:last(SUsers)
+ end,
+ Name = <<FU/binary, "@", FS/binary, " -- ",
+ LU/binary, "@", LS/binary>>,
+ #disco_item{jid = jid:make(Host),
+ node = <<"all users/", Node/binary>>,
+ name = Name}
+ end, lists:seq(1, N, M))
end.
+-spec get_outgoing_s2s(binary(), binary()) -> [disco_item()].
get_outgoing_s2s(Host, Lang) ->
- case catch ejabberd_s2s:dirty_get_connections() of
- {'EXIT', _Reason} -> [];
- Connections ->
- DotHost = <<".", Host/binary>>,
- TConns = [TH
- || {FH, TH} <- Connections,
- Host == FH orelse str:suffix(DotHost, FH)],
- lists:map(fun (T) ->
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>, Host},
- {<<"node">>,
- <<"outgoing s2s/", T/binary>>},
- {<<"name">>,
- iolist_to_binary(io_lib:format(?T(Lang,
- <<"To ~s">>),
- [T]))}],
- children = []}
- end,
- lists:usort(TConns))
- end.
-
+ Connections = ejabberd_s2s:dirty_get_connections(),
+ DotHost = <<".", Host/binary>>,
+ TConns = [TH || {FH, TH} <- Connections,
+ Host == FH orelse str:suffix(DotHost, FH)],
+ lists:map(
+ fun (T) ->
+ Name = str:format(tr(Lang, ?T("To ~ts")),[T]),
+ #disco_item{jid = jid:make(Host),
+ node = <<"outgoing s2s/", T/binary>>,
+ name = Name}
+ end, lists:usort(TConns)).
+
+-spec get_outgoing_s2s(binary(), binary(), binary()) -> [disco_item()].
get_outgoing_s2s(Host, Lang, To) ->
- case catch ejabberd_s2s:dirty_get_connections() of
- {'EXIT', _Reason} -> [];
- Connections ->
- lists:map(fun ({F, _T}) ->
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>, Host},
- {<<"node">>,
- <<"outgoing s2s/", To/binary, "/",
- F/binary>>},
- {<<"name">>,
- iolist_to_binary(io_lib:format(?T(Lang,
- <<"From ~s">>),
- [F]))}],
- children = []}
- end,
- lists:keysort(1,
- lists:filter(fun (E) -> element(2, E) == To
- end,
- Connections)))
- end.
-
+ Connections = ejabberd_s2s:dirty_get_connections(),
+ lists:map(
+ fun ({F, _T}) ->
+ Node = <<"outgoing s2s/", To/binary, "/", F/binary>>,
+ Name = str:format(tr(Lang, ?T("From ~ts")), [F]),
+ #disco_item{jid = jid:make(Host), node = Node, name = Name}
+ end,
+ lists:keysort(
+ 1,
+ lists:filter(fun (E) -> element(2, E) == To end,
+ Connections))).
+
+-spec get_running_nodes(binary(), binary()) -> [disco_item()].
get_running_nodes(Server, _Lang) ->
- case catch mnesia:system_info(running_db_nodes) of
- {'EXIT', _Reason} -> [];
- DBNodes ->
- lists:map(fun (N) ->
- S = iolist_to_binary(atom_to_list(N)),
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>, Server},
- {<<"node">>,
- <<"running nodes/", S/binary>>},
- {<<"name">>, S}],
- children = []}
- end,
- lists:sort(DBNodes))
- end.
-
+ DBNodes = mnesia:system_info(running_db_nodes),
+ lists:map(
+ fun (N) ->
+ S = iolist_to_binary(atom_to_list(N)),
+ #disco_item{jid = jid:make(Server),
+ node = <<"running nodes/", S/binary>>,
+ name = S}
+ end, lists:sort(DBNodes)).
+
+-spec get_stopped_nodes(binary()) -> [disco_item()].
get_stopped_nodes(_Lang) ->
- case catch lists:usort(mnesia:system_info(db_nodes) ++
- mnesia:system_info(extra_db_nodes))
- -- mnesia:system_info(running_db_nodes)
- of
- {'EXIT', _Reason} -> [];
- DBNodes ->
- lists:map(fun (N) ->
- S = iolist_to_binary(atom_to_list(N)),
- #xmlel{name = <<"item">>,
- attrs =
- [{<<"jid">>, ?MYNAME},
- {<<"node">>,
- <<"stopped nodes/", S/binary>>},
- {<<"name">>, S}],
- children = []}
- end,
- lists:sort(DBNodes))
- end.
+ DBNodes = lists:usort(mnesia:system_info(db_nodes) ++
+ mnesia:system_info(extra_db_nodes))
+ -- mnesia:system_info(running_db_nodes),
+ lists:map(
+ fun (N) ->
+ S = iolist_to_binary(atom_to_list(N)),
+ #disco_item{jid = jid:make(ejabberd_config:get_myname()),
+ node = <<"stopped nodes/", S/binary>>,
+ name = S}
+ end, lists:sort(DBNodes)).
%%-------------------------------------------------------------------------
-define(COMMANDS_RESULT(LServerOrGlobal, From, To,
Request, Lang),
case acl:match_rule(LServerOrGlobal, configure, From) of
- deny -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)};
+ deny -> {error, xmpp:err_forbidden(?T("Access denied by service policy"), Lang)};
allow -> adhoc_local_commands(From, To, Request)
end).
+-spec adhoc_local_commands(adhoc_command(), jid(), jid(), adhoc_command()) ->
+ adhoc_command() | {error, stanza_error()}.
adhoc_local_commands(Acc, From,
#jid{lserver = LServer} = To,
- #adhoc_request{node = Node, lang = Lang} = Request) ->
+ #adhoc_command{node = Node, lang = Lang} = Request) ->
LNode = tokenize(Node),
case LNode of
[<<"running nodes">>, _ENode, <<"DB">>] ->
?COMMANDS_RESULT(global, From, To, Request, Lang);
- [<<"running nodes">>, _ENode, <<"modules">>, _] ->
- ?COMMANDS_RESULT(LServer, From, To, Request, Lang);
[<<"running nodes">>, _ENode, <<"backup">>, _] ->
?COMMANDS_RESULT(global, From, To, Request, Lang);
[<<"running nodes">>, _ENode, <<"import">>, _] ->
@@ -858,366 +740,190 @@ adhoc_local_commands(Acc, From,
_ -> Acc
end.
+-spec adhoc_local_commands(jid(), jid(), adhoc_command()) -> adhoc_command() | {error, stanza_error()}.
adhoc_local_commands(From,
#jid{lserver = LServer} = _To,
- #adhoc_request{lang = Lang, node = Node,
- sessionid = SessionID, action = Action,
- xdata = XData} =
- Request) ->
+ #adhoc_command{lang = Lang, node = Node,
+ sid = SessionID, action = Action,
+ xdata = XData} = Request) ->
LNode = tokenize(Node),
- ActionIsExecute = lists:member(Action,
- [<<"">>, <<"execute">>, <<"complete">>]),
- if Action == <<"cancel">> ->
- adhoc:produce_response(Request,
- #adhoc_response{status = canceled});
- XData == false, ActionIsExecute ->
+ ActionIsExecute = Action == execute orelse Action == complete,
+ if Action == cancel ->
+ #adhoc_command{status = canceled, lang = Lang,
+ node = Node, sid = SessionID};
+ XData == undefined, ActionIsExecute ->
case get_form(LServer, LNode, Lang) of
{result, Form} ->
- adhoc:produce_response(Request,
- #adhoc_response{status = executing,
- elements = Form});
+ xmpp_util:make_adhoc_response(
+ Request,
+ #adhoc_command{status = executing, xdata = Form});
{result, Status, Form} ->
- adhoc:produce_response(Request,
- #adhoc_response{status = Status,
- elements = Form});
+ xmpp_util:make_adhoc_response(
+ Request,
+ #adhoc_command{status = Status, xdata = Form});
{error, Error} -> {error, Error}
end;
- XData /= false, ActionIsExecute ->
- case jlib:parse_xdata_submit(XData) of
- invalid ->
- {error, ?ERRT_BAD_REQUEST(Lang, <<"Incorrect data form">>)};
- Fields ->
- case catch set_form(From, LServer, LNode, Lang, Fields)
- of
- {result, Res} ->
- adhoc:produce_response(#adhoc_response{lang = Lang,
- node = Node,
- sessionid =
- SessionID,
- elements = Res,
- status =
- completed});
- {'EXIT', _} -> {error, ?ERR_BAD_REQUEST};
- {error, Error} -> {error, Error}
- end
- end;
+ XData /= undefined, ActionIsExecute ->
+ case set_form(From, LServer, LNode, Lang, XData) of
+ {result, Res} ->
+ xmpp_util:make_adhoc_response(
+ Request,
+ #adhoc_command{xdata = Res, status = completed});
+ %%{'EXIT', _} -> {error, xmpp:err_bad_request()};
+ {error, Error} -> {error, Error}
+ end;
true ->
- {error, ?ERRT_BAD_REQUEST(Lang, <<"Incorrect action or data form">>)}
+ {error, xmpp:err_bad_request(?T("Unexpected action"), Lang)}
end.
-define(TVFIELD(Type, Var, Val),
- #xmlel{name = <<"field">>,
- attrs = [{<<"type">>, Type}, {<<"var">>, Var}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, Val}]}]}).
+ #xdata_field{type = Type, var = Var, values = [Val]}).
-define(HFIELD(),
- ?TVFIELD(<<"hidden">>, <<"FORM_TYPE">>, (?NS_ADMIN))).
+ ?TVFIELD(hidden, <<"FORM_TYPE">>, (?NS_ADMIN))).
-define(TLFIELD(Type, Label, Var),
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, Type}, {<<"label">>, ?T(Lang, Label)},
- {<<"var">>, Var}],
- children = []}).
+ #xdata_field{type = Type, label = tr(Lang, Label), var = Var}).
-define(XFIELD(Type, Label, Var, Val),
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, Type}, {<<"label">>, ?T(Lang, Label)},
- {<<"var">>, Var}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, Val}]}]}).
+ #xdata_field{type = Type, label = tr(Lang, Label),
+ var = Var, values = [Val]}).
-define(XMFIELD(Type, Label, Var, Vals),
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, Type}, {<<"label">>, ?T(Lang, Label)},
- {<<"var">>, Var}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, Val}]}
- || Val <- Vals]}).
+ #xdata_field{type = Type, label = tr(Lang, Label),
+ var = Var, values = Vals}).
-define(TABLEFIELD(Table, Val),
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"list-single">>},
- {<<"label">>, iolist_to_binary(atom_to_list(Table))},
- {<<"var">>, iolist_to_binary(atom_to_list(Table))}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children =
- [{xmlcdata,
- iolist_to_binary(atom_to_list(Val))}]},
- #xmlel{name = <<"option">>,
- attrs = [{<<"label">>, ?T(Lang, <<"RAM copy">>)}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children =
- [{xmlcdata, <<"ram_copies">>}]}]},
- #xmlel{name = <<"option">>,
- attrs =
- [{<<"label">>,
- ?T(Lang, <<"RAM and disc copy">>)}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children =
- [{xmlcdata, <<"disc_copies">>}]}]},
- #xmlel{name = <<"option">>,
- attrs =
- [{<<"label">>, ?T(Lang, <<"Disc only copy">>)}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children =
- [{xmlcdata,
- <<"disc_only_copies">>}]}]},
- #xmlel{name = <<"option">>,
- attrs = [{<<"label">>, ?T(Lang, <<"Remote copy">>)}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children =
- [{xmlcdata, <<"unknown">>}]}]}]}).
-
+ #xdata_field{
+ type = 'list-single',
+ label = iolist_to_binary(atom_to_list(Table)),
+ var = iolist_to_binary(atom_to_list(Table)),
+ values = [iolist_to_binary(atom_to_list(Val))],
+ options = [#xdata_option{label = tr(Lang, ?T("RAM copy")),
+ value = <<"ram_copies">>},
+ #xdata_option{label = tr(Lang, ?T("RAM and disc copy")),
+ value = <<"disc_copies">>},
+ #xdata_option{label = tr(Lang, ?T("Disc only copy")),
+ value = <<"disc_only_copies">>},
+ #xdata_option{label = tr(Lang, ?T("Remote copy")),
+ value = <<"unknown">>}]}).
+
+-spec get_form(binary(), [binary()], binary()) -> {result, xdata()} |
+ {result, completed, xdata()} |
+ {error, stanza_error()}.
get_form(_Host, [<<"running nodes">>, ENode, <<"DB">>],
Lang) ->
case search_running_node(ENode) of
false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
+ Txt = ?T("No running node found"),
+ {error, xmpp:err_item_not_found(Txt, Lang)};
Node ->
case ejabberd_cluster:call(Node, mnesia, system_info, [tables]) of
{badrpc, Reason} ->
?ERROR_MSG("RPC call mnesia:system_info(tables) on node "
- "~s failed: ~p", [Node, Reason]),
- {error, ?ERR_INTERNAL_SERVER_ERROR};
+ "~ts failed: ~p", [Node, Reason]),
+ {error, xmpp:err_internal_server_error()};
Tables ->
STables = lists:sort(Tables),
- {result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang,
- <<"Database Tables Configuration at ">>))/binary,
- ENode/binary>>}]},
- #xmlel{name = <<"instructions">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang,
- <<"Choose storage type of tables">>)}]}
- | lists:map(fun (Table) ->
- case ejabberd_cluster:call(Node, mnesia,
- table_info,
- [Table,
- storage_type])
- of
- {badrpc, _} ->
- ?TABLEFIELD(Table,
- unknown);
- Type ->
- ?TABLEFIELD(Table, Type)
- end
- end,
- STables)]}]}
- end
- end;
-get_form(Host,
- [<<"running nodes">>, ENode, <<"modules">>, <<"stop">>],
- Lang) ->
- case search_running_node(ENode) of
- false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
- Node ->
- case ejabberd_cluster:call(Node, gen_mod, loaded_modules, [Host]) of
- {badrpc, Reason} ->
- ?ERROR_MSG("RPC call gen_mod:loaded_modules(~s) on node "
- "~s failed: ~p", [Host, Node, Reason]),
- {error, ?ERR_INTERNAL_SERVER_ERROR};
- Modules ->
- SModules = lists:sort(Modules),
- {result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang,
- <<"Stop Modules at ">>))/binary,
- ENode/binary>>}]},
- #xmlel{name = <<"instructions">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang,
- <<"Choose modules to stop">>)}]}
- | lists:map(fun (M) ->
- S = jlib:atom_to_binary(M),
- ?XFIELD(<<"boolean">>, S, S,
- <<"0">>)
- end,
- SModules)]}]}
+ Title = <<(tr(Lang, ?T("Database Tables Configuration at ")))/binary,
+ ENode/binary>>,
+ Instr = tr(Lang, ?T("Choose storage type of tables")),
+ try
+ Fs = lists:map(
+ fun(Table) ->
+ case ejabberd_cluster:call(
+ Node, mnesia, table_info,
+ [Table, storage_type]) of
+ Type when is_atom(Type) ->
+ ?TABLEFIELD(Table, Type)
+ end
+ end, STables),
+ {result, #xdata{title = Title,
+ type = form,
+ instructions = [Instr],
+ fields = [?HFIELD()|Fs]}}
+ catch _:{case_clause, {badrpc, Reason}} ->
+ ?ERROR_MSG("RPC call mnesia:table_info/2 "
+ "on node ~ts failed: ~p", [Node, Reason]),
+ {error, xmpp:err_internal_server_error()}
+ end
end
end;
get_form(_Host,
- [<<"running nodes">>, ENode, <<"modules">>,
- <<"start">>],
- Lang) ->
- {result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang, <<"Start Modules at ">>))/binary,
- ENode/binary>>}]},
- #xmlel{name = <<"instructions">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang,
- <<"Enter list of {Module, [Options]}">>)}]},
- ?XFIELD(<<"text-multi">>,
- <<"List of modules to start">>, <<"modules">>,
- <<"[].">>)]}]};
-get_form(_Host,
[<<"running nodes">>, ENode, <<"backup">>,
<<"backup">>],
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang, <<"Backup to File at ">>))/binary,
- ENode/binary>>}]},
- #xmlel{name = <<"instructions">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang, <<"Enter path to backup file">>)}]},
- ?XFIELD(<<"text-single">>, <<"Path to File">>,
- <<"path">>, <<"">>)]}]};
+ #xdata{title = <<(tr(Lang, ?T("Backup to File at ")))/binary, ENode/binary>>,
+ type = form,
+ instructions = [tr(Lang, ?T("Enter path to backup file"))],
+ fields = [?HFIELD(),
+ ?XFIELD('text-single', ?T("Path to File"),
+ <<"path">>, <<"">>)]}};
get_form(_Host,
[<<"running nodes">>, ENode, <<"backup">>,
<<"restore">>],
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang,
- <<"Restore Backup from File at ">>))/binary,
- ENode/binary>>}]},
- #xmlel{name = <<"instructions">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang, <<"Enter path to backup file">>)}]},
- ?XFIELD(<<"text-single">>, <<"Path to File">>,
- <<"path">>, <<"">>)]}]};
+ #xdata{title = <<(tr(Lang, ?T("Restore Backup from File at ")))/binary,
+ ENode/binary>>,
+ type = form,
+ instructions = [tr(Lang, ?T("Enter path to backup file"))],
+ fields = [?HFIELD(),
+ ?XFIELD('text-single', ?T("Path to File"),
+ <<"path">>, <<"">>)]}};
get_form(_Host,
[<<"running nodes">>, ENode, <<"backup">>,
<<"textfile">>],
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang,
- <<"Dump Backup to Text File at ">>))/binary,
- ENode/binary>>}]},
- #xmlel{name = <<"instructions">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang, <<"Enter path to text file">>)}]},
- ?XFIELD(<<"text-single">>, <<"Path to File">>,
- <<"path">>, <<"">>)]}]};
+ #xdata{title = <<(tr(Lang, ?T("Dump Backup to Text File at ")))/binary,
+ ENode/binary>>,
+ type = form,
+ instructions = [tr(Lang, ?T("Enter path to text file"))],
+ fields = [?HFIELD(),
+ ?XFIELD('text-single', ?T("Path to File"),
+ <<"path">>, <<"">>)]}};
get_form(_Host,
[<<"running nodes">>, ENode, <<"import">>, <<"file">>],
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang,
- <<"Import User from File at ">>))/binary,
- ENode/binary>>}]},
- #xmlel{name = <<"instructions">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang,
- <<"Enter path to jabberd14 spool file">>)}]},
- ?XFIELD(<<"text-single">>, <<"Path to File">>,
- <<"path">>, <<"">>)]}]};
+ #xdata{title = <<(tr(Lang, ?T("Import User from File at ")))/binary,
+ ENode/binary>>,
+ type = form,
+ instructions = [tr(Lang, ?T("Enter path to jabberd14 spool file"))],
+ fields = [?HFIELD(),
+ ?XFIELD('text-single', ?T("Path to File"),
+ <<"path">>, <<"">>)]}};
get_form(_Host,
[<<"running nodes">>, ENode, <<"import">>, <<"dir">>],
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang,
- <<"Import Users from Dir at ">>))/binary,
- ENode/binary>>}]},
- #xmlel{name = <<"instructions">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang,
- <<"Enter path to jabberd14 spool dir">>)}]},
- ?XFIELD(<<"text-single">>, <<"Path to Dir">>,
- <<"path">>, <<"">>)]}]};
+ #xdata{title = <<(tr(Lang, ?T("Import Users from Dir at ")))/binary,
+ ENode/binary>>,
+ type = form,
+ instructions = [tr(Lang, ?T("Enter path to jabberd14 spool dir"))],
+ fields = [?HFIELD(),
+ ?XFIELD('text-single', ?T("Path to Dir"),
+ <<"path">>, <<"">>)]}};
get_form(_Host,
[<<"running nodes">>, _ENode, <<"restart">>], Lang) ->
- Make_option = fun (LabelNum, LabelUnit, Value) ->
- #xmlel{name = <<"option">>,
- attrs =
- [{<<"label">>,
- <<LabelNum/binary,
- (?T(Lang, LabelUnit))/binary>>}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, Value}]}]}
- end,
+ Make_option =
+ fun (LabelNum, LabelUnit, Value) ->
+ #xdata_option{
+ label = <<LabelNum/binary, (tr(Lang, LabelUnit))/binary>>,
+ value = Value}
+ end,
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata, ?T(Lang, <<"Restart Service">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"list-single">>},
- {<<"label">>, ?T(Lang, <<"Time delay">>)},
- {<<"var">>, <<"delay">>}],
- children =
+ #xdata{title = tr(Lang, ?T("Restart Service")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{
+ type = 'list-single',
+ label = tr(Lang, ?T("Time delay")),
+ var = <<"delay">>,
+ required = true,
+ options =
[Make_option(<<"">>, <<"immediately">>, <<"1">>),
Make_option(<<"15 ">>, <<"seconds">>, <<"15">>),
Make_option(<<"30 ">>, <<"seconds">>, <<"30">>),
@@ -1229,55 +935,35 @@ get_form(_Host,
Make_option(<<"5 ">>, <<"minutes">>, <<"300">>),
Make_option(<<"10 ">>, <<"minutes">>, <<"600">>),
Make_option(<<"15 ">>, <<"minutes">>, <<"900">>),
- Make_option(<<"30 ">>, <<"minutes">>, <<"1800">>),
- #xmlel{name = <<"required">>, attrs = [],
- children = []}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"fixed">>},
- {<<"label">>,
- ?T(Lang,
- <<"Send announcement to all online users "
- "on all hosts">>)}],
- children = []},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"var">>, <<"subject">>},
- {<<"type">>, <<"text-single">>},
- {<<"label">>, ?T(Lang, <<"Subject">>)}],
- children = []},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"var">>, <<"announcement">>},
- {<<"type">>, <<"text-multi">>},
- {<<"label">>, ?T(Lang, <<"Message body">>)}],
- children = []}]}]};
+ Make_option(<<"30 ">>, <<"minutes">>, <<"1800">>)]},
+ #xdata_field{type = fixed,
+ label = tr(Lang,
+ ?T("Send announcement to all online users "
+ "on all hosts"))},
+ #xdata_field{var = <<"subject">>,
+ type = 'text-single',
+ label = tr(Lang, ?T("Subject"))},
+ #xdata_field{var = <<"announcement">>,
+ type = 'text-multi',
+ label = tr(Lang, ?T("Message body"))}]}};
get_form(_Host,
[<<"running nodes">>, _ENode, <<"shutdown">>], Lang) ->
- Make_option = fun (LabelNum, LabelUnit, Value) ->
- #xmlel{name = <<"option">>,
- attrs =
- [{<<"label">>,
- <<LabelNum/binary,
- (?T(Lang, LabelUnit))/binary>>}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, Value}]}]}
- end,
+ Make_option =
+ fun (LabelNum, LabelUnit, Value) ->
+ #xdata_option{
+ label = <<LabelNum/binary, (tr(Lang, LabelUnit))/binary>>,
+ value = Value}
+ end,
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata, ?T(Lang, <<"Shut Down Service">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"list-single">>},
- {<<"label">>, ?T(Lang, <<"Time delay">>)},
- {<<"var">>, <<"delay">>}],
- children =
+ #xdata{title = tr(Lang, ?T("Shut Down Service")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{
+ type = 'list-single',
+ label = tr(Lang, ?T("Time delay")),
+ var = <<"delay">>,
+ required = true,
+ options =
[Make_option(<<"">>, <<"immediately">>, <<"1">>),
Make_option(<<"15 ">>, <<"seconds">>, <<"15">>),
Make_option(<<"30 ">>, <<"seconds">>, <<"30">>),
@@ -1289,511 +975,290 @@ get_form(_Host,
Make_option(<<"5 ">>, <<"minutes">>, <<"300">>),
Make_option(<<"10 ">>, <<"minutes">>, <<"600">>),
Make_option(<<"15 ">>, <<"minutes">>, <<"900">>),
- Make_option(<<"30 ">>, <<"minutes">>, <<"1800">>),
- #xmlel{name = <<"required">>, attrs = [],
- children = []}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"fixed">>},
- {<<"label">>,
- ?T(Lang,
- <<"Send announcement to all online users "
- "on all hosts">>)}],
- children = []},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"var">>, <<"subject">>},
- {<<"type">>, <<"text-single">>},
- {<<"label">>, ?T(Lang, <<"Subject">>)}],
- children = []},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"var">>, <<"announcement">>},
- {<<"type">>, <<"text-multi">>},
- {<<"label">>, ?T(Lang, <<"Message body">>)}],
- children = []}]}]};
-get_form(Host, [<<"config">>, <<"acls">>], Lang) ->
- {result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang,
- <<"Access Control List Configuration">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"text-multi">>},
- {<<"label">>,
- ?T(Lang, <<"Access control lists">>)},
- {<<"var">>, <<"acls">>}],
- children =
- lists:map(fun (S) ->
- #xmlel{name = <<"value">>,
- attrs = [],
- children =
- [{xmlcdata, S}]}
- end,
- str:tokens(iolist_to_binary(io_lib:format("~p.",
- [ets:select(acl,
- [{{acl,
- {'$1',
- '$2'},
- '$3'},
- [{'==',
- '$2',
- Host}],
- [{{acl,
- '$1',
- '$3'}}]}])])),
- <<"\n">>))}]}]};
-get_form(Host, [<<"config">>, <<"access">>], Lang) ->
- {result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang, <<"Access Configuration">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"text-multi">>},
- {<<"label">>, ?T(Lang, <<"Access rules">>)},
- {<<"var">>, <<"access">>}],
- children =
- lists:map(fun (S) ->
- #xmlel{name = <<"value">>,
- attrs = [],
- children =
- [{xmlcdata, S}]}
- end,
- str:tokens(iolist_to_binary(io_lib:format("~p.",
- [ets:select(access,
- [{{access,
- {'$1',
- '$2'},
- '$3'},
- [{'==',
- '$2',
- Host}],
- [{{access,
- '$1',
- '$3'}}]}])])),
- <<"\n">>))}]}]};
+ Make_option(<<"30 ">>, <<"minutes">>, <<"1800">>)]},
+ #xdata_field{type = fixed,
+ label = tr(Lang,
+ ?T("Send announcement to all online users "
+ "on all hosts"))},
+ #xdata_field{var = <<"subject">>,
+ type = 'text-single',
+ label = tr(Lang, ?T("Subject"))},
+ #xdata_field{var = <<"announcement">>,
+ type = 'text-multi',
+ label = tr(Lang, ?T("Message body"))}]}};
get_form(_Host, ?NS_ADMINL(<<"add-user">>), Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children = [{xmlcdata, ?T(Lang, <<"Add User">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"jid-single">>},
- {<<"label">>, ?T(Lang, <<"Jabber ID">>)},
- {<<"var">>, <<"accountjid">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"text-private">>},
- {<<"label">>, ?T(Lang, <<"Password">>)},
- {<<"var">>, <<"password">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"text-private">>},
- {<<"label">>,
- ?T(Lang, <<"Password Verification">>)},
- {<<"var">>, <<"password-verify">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]}]}]};
+ #xdata{title = tr(Lang, ?T("Add User")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'jid-single',
+ label = tr(Lang, ?T("Jabber ID")),
+ required = true,
+ var = <<"accountjid">>},
+ #xdata_field{type = 'text-private',
+ label = tr(Lang, ?T("Password")),
+ required = true,
+ var = <<"password">>},
+ #xdata_field{type = 'text-private',
+ label = tr(Lang, ?T("Password Verification")),
+ required = true,
+ var = <<"password-verify">>}]}};
get_form(_Host, ?NS_ADMINL(<<"delete-user">>), Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children = [{xmlcdata, ?T(Lang, <<"Delete User">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"jid-multi">>},
- {<<"label">>, ?T(Lang, <<"Jabber ID">>)},
- {<<"var">>, <<"accountjids">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]}]}]};
+ #xdata{title = tr(Lang, ?T("Delete User")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'jid-multi',
+ label = tr(Lang, ?T("Jabber ID")),
+ required = true,
+ var = <<"accountjids">>}]}};
get_form(_Host, ?NS_ADMINL(<<"end-user-session">>),
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata, ?T(Lang, <<"End User Session">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"jid-single">>},
- {<<"label">>, ?T(Lang, <<"Jabber ID">>)},
- {<<"var">>, <<"accountjid">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]}]}]};
+ #xdata{title = tr(Lang, ?T("End User Session")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'jid-single',
+ label = tr(Lang, ?T("Jabber ID")),
+ required = true,
+ var = <<"accountjid">>}]}};
get_form(_Host, ?NS_ADMINL(<<"get-user-password">>),
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata, ?T(Lang, <<"Get User Password">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"jid-single">>},
- {<<"label">>, ?T(Lang, <<"Jabber ID">>)},
- {<<"var">>, <<"accountjid">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]}]}]};
+ #xdata{title = tr(Lang, ?T("Get User Password")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'jid-single',
+ label = tr(Lang, ?T("Jabber ID")),
+ var = <<"accountjid">>,
+ required = true}]}};
get_form(_Host, ?NS_ADMINL(<<"change-user-password">>),
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata, ?T(Lang, <<"Get User Password">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"jid-single">>},
- {<<"label">>, ?T(Lang, <<"Jabber ID">>)},
- {<<"var">>, <<"accountjid">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"text-private">>},
- {<<"label">>, ?T(Lang, <<"Password">>)},
- {<<"var">>, <<"password">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]}]}]};
+ #xdata{title = tr(Lang, ?T("Change User Password")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'jid-single',
+ label = tr(Lang, ?T("Jabber ID")),
+ required = true,
+ var = <<"accountjid">>},
+ #xdata_field{type = 'text-private',
+ label = tr(Lang, ?T("Password")),
+ required = true,
+ var = <<"password">>}]}};
get_form(_Host, ?NS_ADMINL(<<"get-user-lastlogin">>),
Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- ?T(Lang, <<"Get User Last Login Time">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"jid-single">>},
- {<<"label">>, ?T(Lang, <<"Jabber ID">>)},
- {<<"var">>, <<"accountjid">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]}]}]};
+ #xdata{title = tr(Lang, ?T("Get User Last Login Time")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'jid-single',
+ label = tr(Lang, ?T("Jabber ID")),
+ var = <<"accountjid">>,
+ required = true}]}};
get_form(_Host, ?NS_ADMINL(<<"user-stats">>), Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata, ?T(Lang, <<"Get User Statistics">>)}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"jid-single">>},
- {<<"label">>, ?T(Lang, <<"Jabber ID">>)},
- {<<"var">>, <<"accountjid">>}],
- children =
- [#xmlel{name = <<"required">>, attrs = [],
- children = []}]}]}]};
+ #xdata{title = tr(Lang, ?T("Get User Statistics")),
+ type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'jid-single',
+ label = tr(Lang, ?T("Jabber ID")),
+ var = <<"accountjid">>,
+ required = true}]}};
get_form(Host,
?NS_ADMINL(<<"get-registered-users-num">>), Lang) ->
- Num = list_to_binary(
- io_lib:format("~p",
- [ejabberd_auth:get_vh_registered_users_number(Host)])),
+ Num = integer_to_binary(ejabberd_auth:count_users(Host)),
{result, completed,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"text-single">>},
- {<<"label">>,
- ?T(Lang, <<"Number of registered users">>)},
- {<<"var">>, <<"registeredusersnum">>}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, Num}]}]}]}]};
+ #xdata{type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'text-single',
+ label = tr(Lang, ?T("Number of registered users")),
+ var = <<"registeredusersnum">>,
+ values = [Num]}]}};
get_form(Host, ?NS_ADMINL(<<"get-online-users-num">>),
Lang) ->
- Num = list_to_binary(
- io_lib:format("~p",
- [length(ejabberd_sm:get_vh_session_list(Host))])),
+ Num = integer_to_binary(ejabberd_sm:get_vh_session_number(Host)),
{result, completed,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"text-single">>},
- {<<"label">>,
- ?T(Lang, <<"Number of online users">>)},
- {<<"var">>, <<"onlineusersnum">>}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, Num}]}]}]}]};
+ #xdata{type = form,
+ fields = [?HFIELD(),
+ #xdata_field{type = 'text-single',
+ label = tr(Lang, ?T("Number of online users")),
+ var = <<"onlineusersnum">>,
+ values = [Num]}]}};
get_form(_Host, _, _Lang) ->
- {error, ?ERR_SERVICE_UNAVAILABLE}.
+ {error, xmpp:err_service_unavailable()}.
+-spec set_form(jid(), binary(), [binary()], binary(), xdata()) -> {result, xdata() | undefined} |
+ {error, stanza_error()}.
set_form(_From, _Host,
[<<"running nodes">>, ENode, <<"DB">>], Lang, XData) ->
case search_running_node(ENode) of
false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
- Node ->
- lists:foreach(fun ({SVar, SVals}) ->
- Table = jlib:binary_to_atom(SVar),
- Type = case SVals of
- [<<"unknown">>] -> unknown;
- [<<"ram_copies">>] -> ram_copies;
- [<<"disc_copies">>] -> disc_copies;
- [<<"disc_only_copies">>] ->
- disc_only_copies;
- _ -> false
- end,
- if Type == false -> ok;
- Type == unknown ->
- mnesia:del_table_copy(Table, Node);
- true ->
- case mnesia:add_table_copy(Table, Node,
- Type)
- of
- {aborted, _} ->
- mnesia:change_table_copy_type(Table,
- Node,
- Type);
- _ -> ok
- end
- end
- end,
- XData),
- {result, []}
- end;
-set_form(_From, Host,
- [<<"running nodes">>, ENode, <<"modules">>, <<"stop">>],
- Lang, XData) ->
- case search_running_node(ENode) of
- false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
- Node ->
- lists:foreach(fun ({Var, Vals}) ->
- case Vals of
- [<<"1">>] ->
- Module = jlib:binary_to_atom(Var),
- ejabberd_cluster:call(Node, gen_mod, stop_module,
- [Host, Module]);
- _ -> ok
- end
- end,
- XData),
- {result, []}
- end;
-set_form(_From, Host,
- [<<"running nodes">>, ENode, <<"modules">>,
- <<"start">>],
- Lang, XData) ->
- case search_running_node(ENode) of
- false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
+ Txt = ?T("No running node found"),
+ {error, xmpp:err_item_not_found(Txt, Lang)};
Node ->
- case lists:keysearch(<<"modules">>, 1, XData) of
- false ->
- Txt = <<"No 'modules' found in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)};
- {value, {_, Strings}} ->
- String = lists:foldl(fun (S, Res) ->
- <<Res/binary, S/binary, "\n">>
- end,
- <<"">>, Strings),
- case erl_scan:string(binary_to_list(String)) of
- {ok, Tokens, _} ->
- case erl_parse:parse_term(Tokens) of
- {ok, Modules} ->
- lists:foreach(fun ({Module, Args}) ->
- ejabberd_cluster:call(Node, gen_mod,
- start_module,
- [Host, Module, Args])
- end,
- Modules),
- {result, []};
- _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Parse failed">>)}
- end;
- _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Scan failed">>)}
- end
- end
+ lists:foreach(
+ fun(#xdata_field{var = SVar, values = SVals}) ->
+ Table = misc:binary_to_atom(SVar),
+ Type = case SVals of
+ [<<"unknown">>] -> unknown;
+ [<<"ram_copies">>] -> ram_copies;
+ [<<"disc_copies">>] -> disc_copies;
+ [<<"disc_only_copies">>] -> disc_only_copies;
+ _ -> false
+ end,
+ if Type == false -> ok;
+ Type == unknown ->
+ mnesia:del_table_copy(Table, Node);
+ true ->
+ case mnesia:add_table_copy(Table, Node, Type) of
+ {aborted, _} ->
+ mnesia:change_table_copy_type(
+ Table, Node, Type);
+ _ -> ok
+ end
+ end
+ end, XData#xdata.fields),
+ {result, undefined}
end;
set_form(_From, _Host,
[<<"running nodes">>, ENode, <<"backup">>,
<<"backup">>],
Lang, XData) ->
case search_running_node(ENode) of
- false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
- Node ->
- case lists:keysearch(<<"path">>, 1, XData) of
- false ->
- Txt = <<"No 'path' found in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)};
- {value, {_, [String]}} ->
- case ejabberd_cluster:call(Node, mnesia, backup, [String]) of
- {badrpc, Reason} ->
- ?ERROR_MSG("RPC call mnesia:backup(~s) to node ~s "
- "failed: ~p", [String, Node, Reason]),
- {error, ?ERR_INTERNAL_SERVER_ERROR};
- {error, Reason} ->
- ?ERROR_MSG("RPC call mnesia:backup(~s) to node ~s "
- "failed: ~p", [String, Node, Reason]),
- {error, ?ERR_INTERNAL_SERVER_ERROR};
- _ -> {result, []}
- end;
- _ ->
- Txt = <<"Incorrect value of 'path' in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
- end
+ false ->
+ Txt = ?T("No running node found"),
+ {error, xmpp:err_item_not_found(Txt, Lang)};
+ Node ->
+ case xmpp_util:get_xdata_values(<<"path">>, XData) of
+ [] ->
+ Txt = ?T("No 'path' found in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)};
+ [String] ->
+ case ejabberd_cluster:call(
+ Node, mnesia, backup, [binary_to_list(String)],
+ timer:minutes(10)) of
+ {badrpc, Reason} ->
+ ?ERROR_MSG("RPC call mnesia:backup(~ts) to node ~ts "
+ "failed: ~p", [String, Node, Reason]),
+ {error, xmpp:err_internal_server_error()};
+ {error, Reason} ->
+ ?ERROR_MSG("RPC call mnesia:backup(~ts) to node ~ts "
+ "failed: ~p", [String, Node, Reason]),
+ {error, xmpp:err_internal_server_error()};
+ _ ->
+ {result, undefined}
+ end;
+ _ ->
+ Txt = ?T("Incorrect value of 'path' in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)}
+ end
end;
set_form(_From, _Host,
[<<"running nodes">>, ENode, <<"backup">>,
<<"restore">>],
Lang, XData) ->
case search_running_node(ENode) of
- false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
- Node ->
- case lists:keysearch(<<"path">>, 1, XData) of
- false ->
- Txt = <<"No 'path' found in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)};
- {value, {_, [String]}} ->
- case ejabberd_cluster:call(Node, ejabberd_admin, restore, [String])
- of
- {badrpc, Reason} ->
- ?ERROR_MSG("RPC call ejabberd_admin:restore(~s) to node "
- "~s failed: ~p", [String, Node, Reason]),
- {error, ?ERR_INTERNAL_SERVER_ERROR};
- {error, Reason} ->
- ?ERROR_MSG("RPC call ejabberd_admin:restore(~s) to node "
- "~s failed: ~p", [String, Node, Reason]),
- {error, ?ERR_INTERNAL_SERVER_ERROR};
- _ -> {result, []}
- end;
- _ ->
- Txt = <<"Incorrect value of 'path' in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
- end
+ false ->
+ Txt = ?T("No running node found"),
+ {error, xmpp:err_item_not_found(Txt, Lang)};
+ Node ->
+ case xmpp_util:get_xdata_values(<<"path">>, XData) of
+ [] ->
+ Txt = ?T("No 'path' found in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)};
+ [String] ->
+ case ejabberd_cluster:call(
+ Node, ejabberd_admin, restore,
+ [String], timer:minutes(10)) of
+ {badrpc, Reason} ->
+ ?ERROR_MSG("RPC call ejabberd_admin:restore(~ts) to node "
+ "~ts failed: ~p", [String, Node, Reason]),
+ {error, xmpp:err_internal_server_error()};
+ {error, Reason} ->
+ ?ERROR_MSG("RPC call ejabberd_admin:restore(~ts) to node "
+ "~ts failed: ~p", [String, Node, Reason]),
+ {error, xmpp:err_internal_server_error()};
+ _ ->
+ {result, undefined}
+ end;
+ _ ->
+ Txt = ?T("Incorrect value of 'path' in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)}
+ end
end;
set_form(_From, _Host,
[<<"running nodes">>, ENode, <<"backup">>,
<<"textfile">>],
Lang, XData) ->
case search_running_node(ENode) of
- false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
- Node ->
- case lists:keysearch(<<"path">>, 1, XData) of
- false ->
- Txt = <<"No 'path' found in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)};
- {value, {_, [String]}} ->
- case ejabberd_cluster:call(Node, ejabberd_admin, dump_to_textfile,
- [String])
- of
- {badrpc, Reason} ->
- ?ERROR_MSG("RPC call ejabberd_admin:dump_to_textfile(~s) "
- "to node ~s failed: ~p", [String, Node, Reason]),
- {error, ?ERR_INTERNAL_SERVER_ERROR};
- {error, Reason} ->
- ?ERROR_MSG("RPC call ejabberd_admin:dump_to_textfile(~s) "
- "to node ~s failed: ~p", [String, Node, Reason]),
- {error, ?ERR_INTERNAL_SERVER_ERROR};
- _ -> {result, []}
- end;
- _ ->
- Txt = <<"Incorrect value of 'path' in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
- end
+ false ->
+ Txt = ?T("No running node found"),
+ {error, xmpp:err_item_not_found(Txt, Lang)};
+ Node ->
+ case xmpp_util:get_xdata_values(<<"path">>, XData) of
+ [] ->
+ Txt = ?T("No 'path' found in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)};
+ [String] ->
+ case ejabberd_cluster:call(
+ Node, ejabberd_admin, dump_to_textfile,
+ [String], timer:minutes(10)) of
+ {badrpc, Reason} ->
+ ?ERROR_MSG("RPC call ejabberd_admin:dump_to_textfile(~ts) "
+ "to node ~ts failed: ~p", [String, Node, Reason]),
+ {error, xmpp:err_internal_server_error()};
+ {error, Reason} ->
+ ?ERROR_MSG("RPC call ejabberd_admin:dump_to_textfile(~ts) "
+ "to node ~ts failed: ~p", [String, Node, Reason]),
+ {error, xmpp:err_internal_server_error()};
+ _ ->
+ {result, undefined}
+ end;
+ _ ->
+ Txt = ?T("Incorrect value of 'path' in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)}
+ end
end;
set_form(_From, _Host,
[<<"running nodes">>, ENode, <<"import">>, <<"file">>],
Lang, XData) ->
case search_running_node(ENode) of
- false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
- Node ->
- case lists:keysearch(<<"path">>, 1, XData) of
- false ->
- Txt = <<"No 'path' found in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)};
- {value, {_, [String]}} ->
- ejabberd_cluster:call(Node, jd2ejd, import_file, [String]),
- {result, []};
- _ ->
- Txt = <<"Incorrect value of 'path' in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
- end
+ false ->
+ Txt = ?T("No running node found"),
+ {error, xmpp:err_item_not_found(Txt, Lang)};
+ Node ->
+ case xmpp_util:get_xdata_values(<<"path">>, XData) of
+ [] ->
+ Txt = ?T("No 'path' found in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)};
+ [String] ->
+ ejabberd_cluster:call(Node, jd2ejd, import_file, [String]),
+ {result, undefined};
+ _ ->
+ Txt = ?T("Incorrect value of 'path' in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)}
+ end
end;
set_form(_From, _Host,
[<<"running nodes">>, ENode, <<"import">>, <<"dir">>],
Lang, XData) ->
case search_running_node(ENode) of
- false ->
- Txt = <<"No running node found">>,
- {error, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)};
- Node ->
- case lists:keysearch(<<"path">>, 1, XData) of
- false ->
- Txt = <<"No 'path' found in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)};
- {value, {_, [String]}} ->
- ejabberd_cluster:call(Node, jd2ejd, import_dir, [String]),
- {result, []};
- _ ->
- Txt = <<"Incorrect value of 'path' in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
- end
+ false ->
+ Txt = ?T("No running node found"),
+ {error, xmpp:err_item_not_found(Txt, Lang)};
+ Node ->
+ case xmpp_util:get_xdata_values(<<"path">>, XData) of
+ [] ->
+ Txt = ?T("No 'path' found in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)};
+ [String] ->
+ ejabberd_cluster:call(Node, jd2ejd, import_dir, [String]),
+ {result, undefined};
+ _ ->
+ Txt = ?T("Incorrect value of 'path' in data form"),
+ {error, xmpp:err_bad_request(Txt, Lang)}
+ end
end;
set_form(From, Host,
[<<"running nodes">>, ENode, <<"restart">>], _Lang,
@@ -1803,149 +1268,58 @@ set_form(From, Host,
[<<"running nodes">>, ENode, <<"shutdown">>], _Lang,
XData) ->
stop_node(From, Host, ENode, stop, XData);
-set_form(_From, Host, [<<"config">>, <<"acls">>], Lang,
- XData) ->
- case lists:keysearch(<<"acls">>, 1, XData) of
- {value, {_, Strings}} ->
- String = lists:foldl(fun (S, Res) ->
- <<Res/binary, S/binary, "\n">>
- end,
- <<"">>, Strings),
- case erl_scan:string(binary_to_list(String)) of
- {ok, Tokens, _} ->
- case erl_parse:parse_term(Tokens) of
- {ok, ACLs} ->
- acl:add_list(Host, ACLs, true),
- {result, []};
- _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Parse failed">>)}
- end;
- _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Scan failed">>)}
- end;
- _ ->
- Txt = <<"No 'acls' found in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
- end;
-set_form(_From, Host, [<<"config">>, <<"access">>],
- Lang, XData) ->
- SetAccess = fun (Rs) ->
- mnesia:transaction(fun () ->
- Os = mnesia:select(access,
- [{{access,
- {'$1',
- '$2'},
- '$3'},
- [{'==',
- '$2',
- Host}],
- ['$_']}]),
- lists:foreach(fun (O) ->
- mnesia:delete_object(O)
- end,
- Os),
- lists:foreach(fun ({access,
- Name,
- Rules}) ->
- mnesia:write({access,
- {Name,
- Host},
- Rules})
- end,
- Rs)
- end)
- end,
- case lists:keysearch(<<"access">>, 1, XData) of
- {value, {_, Strings}} ->
- String = lists:foldl(fun (S, Res) ->
- <<Res/binary, S/binary, "\n">>
- end,
- <<"">>, Strings),
- case erl_scan:string(binary_to_list(String)) of
- {ok, Tokens, _} ->
- case erl_parse:parse_term(Tokens) of
- {ok, Rs} ->
- case SetAccess(Rs) of
- {atomic, _} -> {result, []};
- _ -> {error, ?ERR_BAD_REQUEST}
- end;
- _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Parse failed">>)}
- end;
- _ -> {error, ?ERRT_BAD_REQUEST(Lang, <<"Scan failed">>)}
- end;
- _ ->
- Txt = <<"No 'access' found in data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
- end;
set_form(From, Host, ?NS_ADMINL(<<"add-user">>), _Lang,
XData) ->
AccountString = get_value(<<"accountjid">>, XData),
Password = get_value(<<"password">>, XData),
Password = get_value(<<"password-verify">>, XData),
- AccountJID = jid:from_string(AccountString),
+ AccountJID = jid:decode(AccountString),
User = AccountJID#jid.luser,
Server = AccountJID#jid.lserver,
- true = lists:member(Server, ?MYHOSTS),
+ true = lists:member(Server, ejabberd_option:hosts()),
true = Server == Host orelse
get_permission_level(From) == global,
- ejabberd_auth:try_register(User, Server, Password),
- {result, []};
+ case ejabberd_auth:try_register(User, Server, Password) of
+ ok -> {result, undefined};
+ {error, exists} -> {error, xmpp:err_conflict()};
+ {error, not_allowed} -> {error, xmpp:err_not_allowed()}
+ end;
set_form(From, Host, ?NS_ADMINL(<<"delete-user">>),
_Lang, XData) ->
AccountStringList = get_values(<<"accountjids">>,
XData),
[_ | _] = AccountStringList,
ASL2 = lists:map(fun (AccountString) ->
- JID = jid:from_string(AccountString),
+ JID = jid:decode(AccountString),
User = JID#jid.luser,
Server = JID#jid.lserver,
true = Server == Host orelse
get_permission_level(From) == global,
- true = ejabberd_auth:is_user_exists(User, Server),
+ true = ejabberd_auth:user_exists(User, Server),
{User, Server}
end,
AccountStringList),
[ejabberd_auth:remove_user(User, Server)
|| {User, Server} <- ASL2],
- {result, []};
+ {result, undefined};
set_form(From, Host, ?NS_ADMINL(<<"end-user-session">>),
- Lang, XData) ->
+ _Lang, XData) ->
AccountString = get_value(<<"accountjid">>, XData),
- JID = jid:from_string(AccountString),
- LUser = JID#jid.luser,
+ JID = jid:decode(AccountString),
LServer = JID#jid.lserver,
true = LServer == Host orelse
get_permission_level(From) == global,
- Xmlelement = ?SERRT_POLICY_VIOLATION(Lang, <<"has been kicked">>),
case JID#jid.lresource of
- <<>> ->
- SIs = mnesia:dirty_select(session,
- [{#session{usr = {LUser, LServer, '_'},
- sid = '$1',
- info = '$2',
- _ = '_'},
- [], [{{'$1', '$2'}}]}]),
- Pids = [P || {{_, P}, Info} <- SIs,
- not proplists:get_bool(offline, Info)],
- lists:foreach(fun(Pid) ->
- Pid ! {kick, kicked_by_admin, Xmlelement}
- end, Pids);
- R ->
- [{{_, Pid}, Info}] = mnesia:dirty_select(
- session,
- [{#session{usr = {LUser, LServer, R},
- sid = '$1',
- info = '$2',
- _ = '_'},
- [], [{{'$1', '$2'}}]}]),
- case proplists:get_bool(offline, Info) of
- true -> ok;
- false -> Pid ! {kick, kicked_by_admin, Xmlelement}
- end
+ <<>> ->
+ ejabberd_sm:kick_user(JID#jid.luser, JID#jid.lserver);
+ R ->
+ ejabberd_sm:kick_user(JID#jid.luser, JID#jid.lserver, R)
end,
- {result, []};
+ {result, undefined};
set_form(From, Host,
?NS_ADMINL(<<"get-user-password">>), Lang, XData) ->
AccountString = get_value(<<"accountjid">>, XData),
- JID = jid:from_string(AccountString),
+ JID = jid:decode(AccountString),
User = JID#jid.luser,
Server = JID#jid.lserver,
true = Server == Host orelse
@@ -1953,30 +1327,28 @@ set_form(From, Host,
Password = ejabberd_auth:get_password(User, Server),
true = is_binary(Password),
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- ?XFIELD(<<"jid-single">>, <<"Jabber ID">>,
- <<"accountjid">>, AccountString),
- ?XFIELD(<<"text-single">>, <<"Password">>,
- <<"password">>, Password)]}]};
+ #xdata{type = form,
+ fields = [?HFIELD(),
+ ?XFIELD('jid-single', ?T("Jabber ID"),
+ <<"accountjid">>, AccountString),
+ ?XFIELD('text-single', ?T("Password"),
+ <<"password">>, Password)]}};
set_form(From, Host,
?NS_ADMINL(<<"change-user-password">>), _Lang, XData) ->
AccountString = get_value(<<"accountjid">>, XData),
Password = get_value(<<"password">>, XData),
- JID = jid:from_string(AccountString),
+ JID = jid:decode(AccountString),
User = JID#jid.luser,
Server = JID#jid.lserver,
true = Server == Host orelse
get_permission_level(From) == global,
- true = ejabberd_auth:is_user_exists(User, Server),
+ true = ejabberd_auth:user_exists(User, Server),
ejabberd_auth:set_password(User, Server, Password),
- {result, []};
+ {result, undefined};
set_form(From, Host,
?NS_ADMINL(<<"get-user-lastlogin">>), Lang, XData) ->
AccountString = get_value(<<"accountjid">>, XData),
- JID = jid:from_string(AccountString),
+ JID = jid:decode(AccountString),
User = JID#jid.luser,
Server = JID#jid.lserver,
true = Server == Host orelse
@@ -1986,32 +1358,29 @@ set_form(From, Host,
of
[] ->
case get_last_info(User, Server) of
- not_found -> ?T(Lang, <<"Never">>);
+ not_found -> tr(Lang, ?T("Never"));
{ok, Timestamp, _Status} ->
Shift = Timestamp,
TimeStamp = {Shift div 1000000, Shift rem 1000000, 0},
{{Year, Month, Day}, {Hour, Minute, Second}} =
calendar:now_to_local_time(TimeStamp),
- iolist_to_binary(io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
+ (str:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
[Year, Month, Day, Hour,
Minute, Second]))
end;
- _ -> ?T(Lang, <<"Online">>)
+ _ -> tr(Lang, ?T("Online"))
end,
{result,
- [#xmlel{name = <<"x">>,
- attrs =
- [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}],
- children =
- [?HFIELD(),
- ?XFIELD(<<"jid-single">>, <<"Jabber ID">>,
- <<"accountjid">>, AccountString),
- ?XFIELD(<<"text-single">>, <<"Last login">>,
- <<"lastlogin">>, FLast)]}]};
+ #xdata{type = form,
+ fields = [?HFIELD(),
+ ?XFIELD('jid-single', ?T("Jabber ID"),
+ <<"accountjid">>, AccountString),
+ ?XFIELD('text-single', ?T("Last login"),
+ <<"lastlogin">>, FLast)]}};
set_form(From, Host, ?NS_ADMINL(<<"user-stats">>), Lang,
XData) ->
AccountString = get_value(<<"accountjid">>, XData),
- JID = jid:from_string(AccountString),
+ JID = jid:decode(AccountString),
User = JID#jid.luser,
Server = JID#jid.lserver,
true = Server == Host orelse
@@ -2020,99 +1389,79 @@ set_form(From, Host, ?NS_ADMINL(<<"user-stats">>), Lang,
Server),
IPs1 = [ejabberd_sm:get_user_ip(User, Server, Resource)
|| Resource <- Resources],
- IPs = [<<(jlib:ip_to_list(IP))/binary, ":",
- (jlib:integer_to_binary(Port))/binary>>
+ IPs = [<<(misc:ip_to_list(IP))/binary, ":",
+ (integer_to_binary(Port))/binary>>
|| {IP, Port} <- IPs1],
Items = ejabberd_hooks:run_fold(roster_get, Server, [],
[{User, Server}]),
- Rostersize = jlib:integer_to_binary(erlang:length(Items)),
+ Rostersize = integer_to_binary(erlang:length(Items)),
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- ?XFIELD(<<"jid-single">>, <<"Jabber ID">>,
- <<"accountjid">>, AccountString),
- ?XFIELD(<<"text-single">>, <<"Roster size">>,
- <<"rostersize">>, Rostersize),
- ?XMFIELD(<<"text-multi">>, <<"IP addresses">>,
- <<"ipaddresses">>, IPs),
- ?XMFIELD(<<"text-multi">>, <<"Resources">>,
- <<"onlineresources">>, Resources)]}]};
+ #xdata{type = form,
+ fields = [?HFIELD(),
+ ?XFIELD('jid-single', ?T("Jabber ID"),
+ <<"accountjid">>, AccountString),
+ ?XFIELD('text-single', ?T("Roster size"),
+ <<"rostersize">>, Rostersize),
+ ?XMFIELD('text-multi', ?T("IP addresses"),
+ <<"ipaddresses">>, IPs),
+ ?XMFIELD('text-multi', ?T("Resources"),
+ <<"onlineresources">>, Resources)]}};
set_form(_From, _Host, _, _Lang, _XData) ->
- {error, ?ERR_SERVICE_UNAVAILABLE}.
+ {error, xmpp:err_service_unavailable()}.
-get_value(Field, XData) -> hd(get_values(Field, XData)).
+-spec get_value(binary(), xdata()) -> binary().
+get_value(Field, XData) ->
+ hd(get_values(Field, XData)).
+-spec get_values(binary(), xdata()) -> [binary()].
get_values(Field, XData) ->
- {value, {_, ValueList}} = lists:keysearch(Field, 1,
- XData),
- ValueList.
+ xmpp_util:get_xdata_values(Field, XData).
+-spec search_running_node(binary()) -> false | node().
search_running_node(SNode) ->
search_running_node(SNode,
mnesia:system_info(running_db_nodes)).
+-spec search_running_node(binary(), [node()]) -> false | node().
search_running_node(_, []) -> false;
search_running_node(SNode, [Node | Nodes]) ->
- case iolist_to_binary(atom_to_list(Node)) of
- SNode -> Node;
- _ -> search_running_node(SNode, Nodes)
+ case atom_to_binary(Node, utf8) of
+ SNode -> Node;
+ _ -> search_running_node(SNode, Nodes)
end.
+-spec stop_node(jid(), binary(), binary(), restart | stop, xdata()) -> {result, undefined}.
stop_node(From, Host, ENode, Action, XData) ->
- Delay = jlib:binary_to_integer(get_value(<<"delay">>,
- XData)),
- Subject = case get_value(<<"subject">>, XData) of
- <<"">> -> [];
- S ->
- [#xmlel{name = <<"field">>,
- attrs = [{<<"var">>, <<"subject">>}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, S}]}]}]
+ Delay = binary_to_integer(get_value(<<"delay">>, XData)),
+ Subject = case get_values(<<"subject">>, XData) of
+ [] ->
+ [];
+ [S|_] ->
+ [#xdata_field{var = <<"subject">>, values = [S]}]
end,
- Announcement = case get_values(<<"announcement">>,
- XData)
- of
- [] -> [];
- As ->
- [#xmlel{name = <<"field">>,
- attrs = [{<<"var">>, <<"body">>}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, Line}]}
- || Line <- As]}]
+ Announcement = case get_values(<<"announcement">>, XData) of
+ [] ->
+ [];
+ As ->
+ [#xdata_field{var = <<"body">>, values = As}]
end,
case Subject ++ Announcement of
- [] -> ok;
- SubEls ->
- Request = #adhoc_request{node =
- ?NS_ADMINX(<<"announce-allhosts">>),
- action = <<"complete">>,
- xdata =
- #xmlel{name = <<"x">>,
- attrs =
- [{<<"xmlns">>,
- ?NS_XDATA},
- {<<"type">>, <<"submit">>}],
- children = SubEls},
- others =
- [#xmlel{name = <<"x">>,
- attrs =
- [{<<"xmlns">>,
- ?NS_XDATA},
- {<<"type">>, <<"submit">>}],
- children = SubEls}]},
- To = jid:make(<<"">>, Host, <<"">>),
- mod_announce:announce_commands(empty, From, To, Request)
+ [] ->
+ ok;
+ Fields ->
+ Request = #adhoc_command{node = ?NS_ADMINX(<<"announce-allhosts">>),
+ action = complete,
+ xdata = #xdata{type = submit,
+ fields = Fields}},
+ To = jid:make(Host),
+ mod_announce:announce_commands(empty, From, To, Request)
end,
Time = timer:seconds(Delay),
- Node = jlib:binary_to_atom(ENode),
- {ok, _} = timer:apply_after(Time, rpc, call,
- [Node, init, Action, []]),
- {result, []}.
+ Node = misc:binary_to_atom(ENode),
+ {ok, _} = timer:apply_after(Time, ejabberd_cluster, call, [Node, init, Action, []]),
+ {result, undefined}.
+-spec get_last_info(binary(), binary()) -> {ok, non_neg_integer(), binary()} | not_found.
get_last_info(User, Server) ->
case gen_mod:is_loaded(Server, mod_last) of
true -> mod_last:get_last_info(User, Server);
@@ -2120,113 +1469,92 @@ get_last_info(User, Server) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+-spec adhoc_sm_commands(adhoc_command(), jid(), jid(), adhoc_command()) -> adhoc_command() |
+ {error, stanza_error()}.
adhoc_sm_commands(_Acc, From,
- #jid{user = User, server = Server, lserver = LServer} =
- _To,
- #adhoc_request{lang = Lang, node = <<"config">>,
- action = Action, xdata = XData} =
- Request) ->
+ #jid{user = User, server = Server, lserver = LServer},
+ #adhoc_command{lang = Lang, node = <<"config">>,
+ action = Action, xdata = XData} = Request) ->
case acl:match_rule(LServer, configure, From) of
- deny -> {error, ?ERRT_FORBIDDEN(Lang, <<"Denied by ACL">>)};
- allow ->
- ActionIsExecute = lists:member(Action,
- [<<"">>, <<"execute">>,
- <<"complete">>]),
- if Action == <<"cancel">> ->
- adhoc:produce_response(Request,
- #adhoc_response{status = canceled});
- XData == false, ActionIsExecute ->
- case get_sm_form(User, Server, <<"config">>, Lang) of
- {result, Form} ->
- adhoc:produce_response(Request,
- #adhoc_response{status =
- executing,
- elements = Form});
- {error, Error} -> {error, Error}
- end;
- XData /= false, ActionIsExecute ->
- case jlib:parse_xdata_submit(XData) of
- invalid ->
- Txt = <<"Incorrect data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)};
- Fields ->
- set_sm_form(User, Server, <<"config">>, Request, Fields)
- end;
- true ->
- Txt = <<"Incorrect action or data form">>,
- {error, ?ERRT_BAD_REQUEST(Lang, Txt)}
- end
+ deny ->
+ {error, xmpp:err_forbidden(?T("Access denied by service policy"), Lang)};
+ allow ->
+ ActionIsExecute = Action == execute orelse Action == complete,
+ if Action == cancel ->
+ xmpp_util:make_adhoc_response(
+ Request, #adhoc_command{status = canceled});
+ XData == undefined, ActionIsExecute ->
+ case get_sm_form(User, Server, <<"config">>, Lang) of
+ {result, Form} ->
+ xmpp_util:make_adhoc_response(
+ Request, #adhoc_command{status = executing,
+ xdata = Form});
+ {error, Error} ->
+ {error, Error}
+ end;
+ XData /= undefined, ActionIsExecute ->
+ set_sm_form(User, Server, <<"config">>, Request);
+ true ->
+ Txt = ?T("Unexpected action"),
+ {error, xmpp:err_bad_request(Txt, Lang)}
+ end
end;
adhoc_sm_commands(Acc, _From, _To, _Request) -> Acc.
+-spec get_sm_form(binary(), binary(), binary(), binary()) -> {result, xdata()} |
+ {error, stanza_error()}.
get_sm_form(User, Server, <<"config">>, Lang) ->
{result,
- [#xmlel{name = <<"x">>,
- attrs = [{<<"xmlns">>, ?NS_XDATA}],
- children =
- [?HFIELD(),
- #xmlel{name = <<"title">>, attrs = [],
- children =
- [{xmlcdata,
- <<(?T(Lang, <<"Administration of ">>))/binary,
- User/binary>>}]},
- #xmlel{name = <<"field">>,
- attrs =
- [{<<"type">>, <<"list-single">>},
- {<<"label">>, ?T(Lang, <<"Action on user">>)},
- {<<"var">>, <<"action">>}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children = [{xmlcdata, <<"edit">>}]},
- #xmlel{name = <<"option">>,
- attrs =
- [{<<"label">>,
- ?T(Lang, <<"Edit Properties">>)}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children =
- [{xmlcdata,
- <<"edit">>}]}]},
- #xmlel{name = <<"option">>,
- attrs =
- [{<<"label">>,
- ?T(Lang, <<"Remove User">>)}],
- children =
- [#xmlel{name = <<"value">>, attrs = [],
- children =
- [{xmlcdata,
- <<"remove">>}]}]}]},
- ?XFIELD(<<"text-private">>, <<"Password">>,
- <<"password">>,
- (ejabberd_auth:get_password_s(User, Server)))]}]};
+ #xdata{type = form,
+ title = <<(tr(Lang, ?T("Administration of ")))/binary, User/binary>>,
+ fields =
+ [?HFIELD(),
+ #xdata_field{
+ type = 'list-single',
+ label = tr(Lang, ?T("Action on user")),
+ var = <<"action">>,
+ values = [<<"edit">>],
+ options = [#xdata_option{
+ label = tr(Lang, ?T("Edit Properties")),
+ value = <<"edit">>},
+ #xdata_option{
+ label = tr(Lang, ?T("Remove User")),
+ value = <<"remove">>}]},
+ ?XFIELD('text-private', ?T("Password"),
+ <<"password">>,
+ ejabberd_auth:get_password_s(User, Server))]}};
get_sm_form(_User, _Server, _Node, _Lang) ->
- {error, ?ERR_SERVICE_UNAVAILABLE}.
+ {error, xmpp:err_service_unavailable()}.
+-spec set_sm_form(binary(), binary(), binary(), adhoc_command()) -> adhoc_command() |
+ {error, stanza_error()}.
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),
- adhoc:produce_response(Response);
- _ ->
- Txt = <<"No 'password' found in data form">>,
- {error, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)}
- end;
- {value, {_, [<<"remove">>]}} ->
- catch ejabberd_auth:remove_user(User, Server),
- adhoc:produce_response(Response);
- _ ->
- Txt = <<"Incorrect value of 'action' in data form">>,
- {error, ?ERRT_NOT_ACCEPTABLE(Lang, Txt)}
+ #adhoc_command{lang = Lang, node = Node,
+ sid = SessionID, xdata = XData}) ->
+ Response = #adhoc_command{lang = Lang, node = Node,
+ sid = SessionID, status = completed},
+ case xmpp_util:get_xdata_values(<<"action">>, XData) of
+ [<<"edit">>] ->
+ case xmpp_util:get_xdata_values(<<"password">>, XData) of
+ [Password] ->
+ ejabberd_auth:set_password(User, Server, Password),
+ xmpp_util:make_adhoc_response(Response);
+ _ ->
+ Txt = ?T("No 'password' found in data form"),
+ {error, xmpp:err_not_acceptable(Txt, Lang)}
+ end;
+ [<<"remove">>] ->
+ ejabberd_auth:remove_user(User, Server),
+ xmpp_util:make_adhoc_response(Response);
+ _ ->
+ Txt = ?T("Incorrect value of 'action' in data form"),
+ {error, xmpp:err_not_acceptable(Txt, Lang)}
end;
-set_sm_form(_User, _Server, _Node, _Request, _Fields) ->
- {error, ?ERR_SERVICE_UNAVAILABLE}.
+set_sm_form(_User, _Server, _Node, _Request) ->
+ {error, xmpp:err_service_unavailable()}.
+
+-spec tr(binary(), binary()) -> binary().
+tr(Lang, Text) ->
+ translate:translate(Lang, Text).
-mod_opt_type(_) -> [].
+mod_options(_) -> [].