mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
* src/web/ejabberd_web_admin.erl: Added hooks to allow plugins to
add their pages without modifying ejabberd_web_admin.erl (thanks to Badlop) * src/web/ejabberd_web_admin.hrl: Macro definitions moved here * src/mod_shared_roster.erl: Updated * src/mod_offline.erl: Likewise * src/mod_offline_odbc.erl: Likewise SVN Revision: 884
This commit is contained in:
parent
106cf7f963
commit
727a70c2cb
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
2007-08-23 Alexey Shchepin <alexey@process-one.net>
|
||||||
|
|
||||||
|
* src/web/ejabberd_web_admin.erl: Added hooks to allow plugins to
|
||||||
|
add their pages without modifying ejabberd_web_admin.erl (thanks
|
||||||
|
to Badlop)
|
||||||
|
* src/web/ejabberd_web_admin.hrl: Macro definitions moved here
|
||||||
|
* src/mod_shared_roster.erl: Updated
|
||||||
|
* src/mod_offline.erl: Likewise
|
||||||
|
* src/mod_offline_odbc.erl: Likewise
|
||||||
|
|
||||||
2007-08-22 Alexey Shchepin <alexey@process-one.net>
|
2007-08-22 Alexey Shchepin <alexey@process-one.net>
|
||||||
|
|
||||||
* src/jlib.erl: Use http_base_64:decode if available
|
* src/jlib.erl: Use http_base_64:decode if available
|
||||||
|
@ -18,10 +18,14 @@
|
|||||||
pop_offline_messages/3,
|
pop_offline_messages/3,
|
||||||
remove_expired_messages/0,
|
remove_expired_messages/0,
|
||||||
remove_old_messages/1,
|
remove_old_messages/1,
|
||||||
remove_user/2]).
|
remove_user/2,
|
||||||
|
webadmin_page/3,
|
||||||
|
webadmin_user/4]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
-include("web/ejabberd_http.hrl").
|
||||||
|
-include("web/ejabberd_web_admin.hrl").
|
||||||
|
|
||||||
-record(offline_msg, {us, timestamp, expire, from, to, packet}).
|
-record(offline_msg, {us, timestamp, expire, from, to, packet}).
|
||||||
|
|
||||||
@ -42,6 +46,10 @@ start(Host, Opts) ->
|
|||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:add(anonymous_purge_hook, Host,
|
ejabberd_hooks:add(anonymous_purge_hook, Host,
|
||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
|
ejabberd_hooks:add(webadmin_page_host, Host,
|
||||||
|
?MODULE, webadmin_page, 50),
|
||||||
|
ejabberd_hooks:add(webadmin_user, Host,
|
||||||
|
?MODULE, webadmin_user, 50),
|
||||||
MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
|
MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
|
||||||
register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
spawn(?MODULE, init, [MaxOfflineMsgs])).
|
spawn(?MODULE, init, [MaxOfflineMsgs])).
|
||||||
@ -106,6 +114,10 @@ stop(Host) ->
|
|||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:delete(anonymous_purge_hook, Host,
|
ejabberd_hooks:delete(anonymous_purge_hook, Host,
|
||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
|
ejabberd_hooks:delete(webadmin_page_host, Host,
|
||||||
|
?MODULE, webadmin_page, 50),
|
||||||
|
ejabberd_hooks:delete(webadmin_user, Host,
|
||||||
|
?MODULE, webadmin_user, 50),
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
exit(whereis(Proc), stop),
|
exit(whereis(Proc), stop),
|
||||||
{wait, Proc}.
|
{wait, Proc}.
|
||||||
@ -420,3 +432,107 @@ discard_warn_sender(Msgs) ->
|
|||||||
To,
|
To,
|
||||||
From, Err)
|
From, Err)
|
||||||
end, Msgs).
|
end, Msgs).
|
||||||
|
|
||||||
|
|
||||||
|
webadmin_page(_, Host,
|
||||||
|
#request{us = _US,
|
||||||
|
path = ["user", U, "queue"],
|
||||||
|
q = Query,
|
||||||
|
lang = Lang} = _Request) ->
|
||||||
|
Res = user_queue(U, Host, Query, Lang),
|
||||||
|
{stop, Res};
|
||||||
|
|
||||||
|
webadmin_page(Acc, _, _) -> Acc.
|
||||||
|
|
||||||
|
user_queue(User, Server, Query, Lang) ->
|
||||||
|
US = {jlib:nodeprep(User), jlib:nameprep(Server)},
|
||||||
|
Res = user_queue_parse_query(US, Query),
|
||||||
|
Msgs = lists:keysort(#offline_msg.timestamp,
|
||||||
|
mnesia:dirty_read({offline_msg, US})),
|
||||||
|
FMsgs =
|
||||||
|
lists:map(
|
||||||
|
fun(#offline_msg{timestamp = TimeStamp, from = From, to = To,
|
||||||
|
packet = {xmlelement, Name, Attrs, Els}} = Msg) ->
|
||||||
|
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
|
||||||
|
{{Year, Month, Day}, {Hour, Minute, Second}} =
|
||||||
|
calendar:now_to_local_time(TimeStamp),
|
||||||
|
Time = lists:flatten(
|
||||||
|
io_lib:format(
|
||||||
|
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
||||||
|
[Year, Month, Day, Hour, Minute, Second])),
|
||||||
|
SFrom = jlib:jid_to_string(From),
|
||||||
|
STo = jlib:jid_to_string(To),
|
||||||
|
Attrs2 = jlib:replace_from_to_attrs(SFrom, STo, Attrs),
|
||||||
|
Packet = {xmlelement, Name, Attrs2, Els},
|
||||||
|
FPacket = ejabberd_web_admin:pretty_print_xml(Packet),
|
||||||
|
?XE("tr",
|
||||||
|
[?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
|
||||||
|
?XAC("td", [{"class", "valign"}], Time),
|
||||||
|
?XAC("td", [{"class", "valign"}], SFrom),
|
||||||
|
?XAC("td", [{"class", "valign"}], STo),
|
||||||
|
?XAE("td", [{"class", "valign"}], [?XC("pre", FPacket)])]
|
||||||
|
)
|
||||||
|
end, Msgs),
|
||||||
|
[?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
|
||||||
|
[us_to_list(US)]))] ++
|
||||||
|
case Res of
|
||||||
|
ok -> [?CT("Submitted"), ?P];
|
||||||
|
nothing -> []
|
||||||
|
end ++
|
||||||
|
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
||||||
|
[?XE("table",
|
||||||
|
[?XE("thead",
|
||||||
|
[?XE("tr",
|
||||||
|
[?X("td"),
|
||||||
|
?XCT("td", "Time"),
|
||||||
|
?XCT("td", "From"),
|
||||||
|
?XCT("td", "To"),
|
||||||
|
?XCT("td", "Packet")
|
||||||
|
])]),
|
||||||
|
?XE("tbody",
|
||||||
|
if
|
||||||
|
FMsgs == [] ->
|
||||||
|
[?XE("tr",
|
||||||
|
[?XAC("td", [{"colspan", "4"}], " ")]
|
||||||
|
)];
|
||||||
|
true ->
|
||||||
|
FMsgs
|
||||||
|
end
|
||||||
|
)]),
|
||||||
|
?BR,
|
||||||
|
?INPUTT("submit", "delete", "Delete Selected")
|
||||||
|
])].
|
||||||
|
|
||||||
|
user_queue_parse_query(US, Query) ->
|
||||||
|
case lists:keysearch("delete", 1, Query) of
|
||||||
|
{value, _} ->
|
||||||
|
Msgs = lists:keysort(#offline_msg.timestamp,
|
||||||
|
mnesia:dirty_read({offline_msg, US})),
|
||||||
|
F = fun() ->
|
||||||
|
lists:foreach(
|
||||||
|
fun(Msg) ->
|
||||||
|
ID = jlib:encode_base64(
|
||||||
|
binary_to_list(term_to_binary(Msg))),
|
||||||
|
case lists:member({"selected", ID}, Query) of
|
||||||
|
true ->
|
||||||
|
mnesia:delete_object(Msg);
|
||||||
|
false ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end, Msgs)
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F),
|
||||||
|
ok;
|
||||||
|
false ->
|
||||||
|
nothing
|
||||||
|
end.
|
||||||
|
|
||||||
|
us_to_list({User, Server}) ->
|
||||||
|
jlib:jid_to_string({User, Server, ""}).
|
||||||
|
|
||||||
|
webadmin_user(Acc, User, Server, Lang) ->
|
||||||
|
US = {jlib:nodeprep(User), jlib:nameprep(Server)},
|
||||||
|
QueueLen = length(mnesia:dirty_read({offline_msg, US})),
|
||||||
|
FQueueLen = [?AC("queue/",
|
||||||
|
integer_to_list(QueueLen))],
|
||||||
|
Acc ++ [?XCT("h3", "Offline Messages:")] ++ FQueueLen.
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
||||||
%%% Purpose :
|
%%% Purpose :
|
||||||
%%% Created : 5 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
|
%%% Created : 5 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
|
||||||
%%% Id : $Id$
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
-module(mod_offline_odbc).
|
-module(mod_offline_odbc).
|
||||||
-author('alexey@sevcom.net').
|
-author('alexey@sevcom.net').
|
||||||
|
|
||||||
@ -15,10 +15,14 @@
|
|||||||
stop/1,
|
stop/1,
|
||||||
store_packet/3,
|
store_packet/3,
|
||||||
pop_offline_messages/3,
|
pop_offline_messages/3,
|
||||||
remove_user/2]).
|
remove_user/2,
|
||||||
|
webadmin_page/3,
|
||||||
|
webadmin_user/4]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
-include("web/ejabberd_http.hrl").
|
||||||
|
-include("web/ejabberd_web_admin.hrl").
|
||||||
|
|
||||||
-record(offline_msg, {user, timestamp, expire, from, to, packet}).
|
-record(offline_msg, {user, timestamp, expire, from, to, packet}).
|
||||||
|
|
||||||
@ -34,6 +38,10 @@ start(Host, _Opts) ->
|
|||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:add(anonymous_purge_hook, Host,
|
ejabberd_hooks:add(anonymous_purge_hook, Host,
|
||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
|
ejabberd_hooks:add(webadmin_page_host, Host,
|
||||||
|
?MODULE, webadmin_page, 50),
|
||||||
|
ejabberd_hooks:add(webadmin_user, Host,
|
||||||
|
?MODULE, webadmin_user, 50),
|
||||||
register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
spawn(?MODULE, init, [Host])).
|
spawn(?MODULE, init, [Host])).
|
||||||
|
|
||||||
@ -98,6 +106,10 @@ stop(Host) ->
|
|||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
ejabberd_hooks:delete(anonymous_purge_hook, Host,
|
ejabberd_hooks:delete(anonymous_purge_hook, Host,
|
||||||
?MODULE, remove_user, 50),
|
?MODULE, remove_user, 50),
|
||||||
|
ejabberd_hooks:delete(webadmin_page_host, Host,
|
||||||
|
?MODULE, webadmin_page, 50),
|
||||||
|
ejabberd_hooks:delete(webadmin_user, Host,
|
||||||
|
?MODULE, webadmin_user, 50),
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
exit(whereis(Proc), stop),
|
exit(whereis(Proc), stop),
|
||||||
ok.
|
ok.
|
||||||
@ -180,8 +192,7 @@ find_x_expire(TimeStamp, [{xmlcdata, _} | Els]) ->
|
|||||||
find_x_expire(TimeStamp, [El | Els]) ->
|
find_x_expire(TimeStamp, [El | Els]) ->
|
||||||
case xml:get_tag_attr_s("xmlns", El) of
|
case xml:get_tag_attr_s("xmlns", El) of
|
||||||
?NS_EXPIRE ->
|
?NS_EXPIRE ->
|
||||||
case xml:get_tag_attr_s("seconds", El) of
|
Val = xml:get_tag_attr_s("seconds", El),
|
||||||
Val ->
|
|
||||||
case catch list_to_integer(Val) of
|
case catch list_to_integer(Val) of
|
||||||
{'EXIT', _} ->
|
{'EXIT', _} ->
|
||||||
never;
|
never;
|
||||||
@ -194,9 +205,6 @@ find_x_expire(TimeStamp, [El | Els]) ->
|
|||||||
_ ->
|
_ ->
|
||||||
never
|
never
|
||||||
end;
|
end;
|
||||||
_ ->
|
|
||||||
never
|
|
||||||
end;
|
|
||||||
_ ->
|
_ ->
|
||||||
find_x_expire(TimeStamp, Els)
|
find_x_expire(TimeStamp, Els)
|
||||||
end.
|
end.
|
||||||
@ -238,3 +246,139 @@ remove_user(User, Server) ->
|
|||||||
Username = ejabberd_odbc:escape(LUser),
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
odbc_queries:del_spool_msg(LServer, Username).
|
odbc_queries:del_spool_msg(LServer, Username).
|
||||||
|
|
||||||
|
|
||||||
|
webadmin_page(_, Host,
|
||||||
|
#request{us = _US,
|
||||||
|
path = ["user", U, "queue"],
|
||||||
|
q = Query,
|
||||||
|
lang = Lang} = _Request) ->
|
||||||
|
Res = user_queue(U, Host, Query, Lang),
|
||||||
|
{stop, Res};
|
||||||
|
|
||||||
|
webadmin_page(Acc, _, _) -> Acc.
|
||||||
|
|
||||||
|
user_queue(User, Server, Query, Lang) ->
|
||||||
|
LUser = jlib:nodeprep(User),
|
||||||
|
LServer = jlib:nameprep(Server),
|
||||||
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
|
US = {LUser, LServer},
|
||||||
|
Res = user_queue_parse_query(Username, LServer, Query),
|
||||||
|
Msgs = case catch ejabberd_odbc:sql_query(
|
||||||
|
LServer,
|
||||||
|
["select username, xml from spool"
|
||||||
|
" where username='", Username, "'"
|
||||||
|
" order by seq;"]) of
|
||||||
|
{selected, ["username", "xml"], Rs} ->
|
||||||
|
lists:flatmap(
|
||||||
|
fun({_, XML}) ->
|
||||||
|
case xml_stream:parse_element(XML) of
|
||||||
|
{error, _Reason} ->
|
||||||
|
[];
|
||||||
|
El ->
|
||||||
|
[El]
|
||||||
|
end
|
||||||
|
end, Rs);
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end,
|
||||||
|
FMsgs =
|
||||||
|
lists:map(
|
||||||
|
fun({xmlelement, Name, Attrs, Els} = Msg) ->
|
||||||
|
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
|
||||||
|
Packet = Msg,
|
||||||
|
FPacket = ejabberd_web_admin:pretty_print_xml(Packet),
|
||||||
|
?XE("tr",
|
||||||
|
[?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
|
||||||
|
?XAE("td", [{"class", "valign"}], [?XC("pre", FPacket)])]
|
||||||
|
)
|
||||||
|
end, Msgs),
|
||||||
|
[?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
|
||||||
|
[us_to_list(US)]))] ++
|
||||||
|
case Res of
|
||||||
|
ok -> [?CT("Submitted"), ?P];
|
||||||
|
nothing -> []
|
||||||
|
end ++
|
||||||
|
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
||||||
|
[?XE("table",
|
||||||
|
[?XE("thead",
|
||||||
|
[?XE("tr",
|
||||||
|
[?X("td"),
|
||||||
|
?XCT("td", "Packet")
|
||||||
|
])]),
|
||||||
|
?XE("tbody",
|
||||||
|
if
|
||||||
|
FMsgs == [] ->
|
||||||
|
[?XE("tr",
|
||||||
|
[?XAC("td", [{"colspan", "4"}], " ")]
|
||||||
|
)];
|
||||||
|
true ->
|
||||||
|
FMsgs
|
||||||
|
end
|
||||||
|
)]),
|
||||||
|
?BR,
|
||||||
|
?INPUTT("submit", "delete", "Delete Selected")
|
||||||
|
])].
|
||||||
|
|
||||||
|
user_queue_parse_query(Username, LServer, Query) ->
|
||||||
|
case lists:keysearch("delete", 1, Query) of
|
||||||
|
{value, _} ->
|
||||||
|
Msgs = case catch ejabberd_odbc:sql_query(
|
||||||
|
LServer,
|
||||||
|
["select xml, seq from spool"
|
||||||
|
" where username='", Username, "'"
|
||||||
|
" order by seq;"]) of
|
||||||
|
{selected, ["xml", "seq"], Rs} ->
|
||||||
|
lists:flatmap(
|
||||||
|
fun({XML, Seq}) ->
|
||||||
|
case xml_stream:parse_element(XML) of
|
||||||
|
{error, _Reason} ->
|
||||||
|
[];
|
||||||
|
El ->
|
||||||
|
[{El, Seq}]
|
||||||
|
end
|
||||||
|
end, Rs);
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end,
|
||||||
|
F = fun() ->
|
||||||
|
lists:foreach(
|
||||||
|
fun({Msg, Seq}) ->
|
||||||
|
ID = jlib:encode_base64(
|
||||||
|
binary_to_list(term_to_binary(Msg))),
|
||||||
|
case lists:member({"selected", ID}, Query) of
|
||||||
|
true ->
|
||||||
|
SSeq = ejabberd_odbc:escape(Seq),
|
||||||
|
catch ejabberd_odbc:sql_query(
|
||||||
|
LServer,
|
||||||
|
["delete from spool"
|
||||||
|
" where username='", Username, "'"
|
||||||
|
" and seq='", SSeq, "';"]);
|
||||||
|
false ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end, Msgs)
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F),
|
||||||
|
ok;
|
||||||
|
false ->
|
||||||
|
nothing
|
||||||
|
end.
|
||||||
|
|
||||||
|
us_to_list({User, Server}) ->
|
||||||
|
jlib:jid_to_string({User, Server, ""}).
|
||||||
|
|
||||||
|
webadmin_user(Acc, User, Server, Lang) ->
|
||||||
|
LUser = jlib:nodeprep(User),
|
||||||
|
LServer = jlib:nameprep(Server),
|
||||||
|
Username = ejabberd_odbc:escape(LUser),
|
||||||
|
QueueLen = case catch ejabberd_odbc:sql_query(
|
||||||
|
LServer,
|
||||||
|
["select count(*) from spool"
|
||||||
|
" where username='", Username, "';"]) of
|
||||||
|
{selected, [_], [{SCount}]} ->
|
||||||
|
SCount;
|
||||||
|
_ ->
|
||||||
|
0
|
||||||
|
end,
|
||||||
|
FQueueLen = [?AC("queue/", QueueLen)],
|
||||||
|
Acc ++ [?XCT("h3", "Offline Messages:")] ++ FQueueLen.
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1,
|
-export([start/2, stop/1,
|
||||||
|
webadmin_menu/2, webadmin_page/3,
|
||||||
get_user_roster/2,
|
get_user_roster/2,
|
||||||
get_subscription_lists/3,
|
get_subscription_lists/3,
|
||||||
get_jid_info/4,
|
get_jid_info/4,
|
||||||
@ -32,6 +33,8 @@
|
|||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
-include("mod_roster.hrl").
|
-include("mod_roster.hrl").
|
||||||
|
-include("web/ejabberd_http.hrl").
|
||||||
|
-include("web/ejabberd_web_admin.hrl").
|
||||||
|
|
||||||
-record(sr_group, {group_host, opts}).
|
-record(sr_group, {group_host, opts}).
|
||||||
-record(sr_user, {us, group_host}).
|
-record(sr_user, {us, group_host}).
|
||||||
@ -45,6 +48,10 @@ start(Host, _Opts) ->
|
|||||||
{type, bag},
|
{type, bag},
|
||||||
{attributes, record_info(fields, sr_user)}]),
|
{attributes, record_info(fields, sr_user)}]),
|
||||||
mnesia:add_table_index(sr_user, group_host),
|
mnesia:add_table_index(sr_user, group_host),
|
||||||
|
ejabberd_hooks:add(webadmin_menu_host, Host,
|
||||||
|
?MODULE, webadmin_menu, 70),
|
||||||
|
ejabberd_hooks:add(webadmin_page_host, Host,
|
||||||
|
?MODULE, webadmin_page, 50),
|
||||||
ejabberd_hooks:add(roster_get, Host,
|
ejabberd_hooks:add(roster_get, Host,
|
||||||
?MODULE, get_user_roster, 70),
|
?MODULE, get_user_roster, 70),
|
||||||
ejabberd_hooks:add(roster_in_subscription, Host,
|
ejabberd_hooks:add(roster_in_subscription, Host,
|
||||||
@ -61,6 +68,10 @@ start(Host, _Opts) ->
|
|||||||
% ?MODULE, remove_user, 50),
|
% ?MODULE, remove_user, 50),
|
||||||
|
|
||||||
stop(Host) ->
|
stop(Host) ->
|
||||||
|
ejabberd_hooks:delete(webadmin_menu_host, Host,
|
||||||
|
?MODULE, webadmin_menu, 70),
|
||||||
|
ejabberd_hooks:delete(webadmin_page_host, Host,
|
||||||
|
?MODULE, webadmin_page, 50),
|
||||||
ejabberd_hooks:delete(roster_get, Host,
|
ejabberd_hooks:delete(roster_get, Host,
|
||||||
?MODULE, get_user_roster, 70),
|
?MODULE, get_user_roster, 70),
|
||||||
ejabberd_hooks:delete(roster_in_subscription, Host,
|
ejabberd_hooks:delete(roster_in_subscription, Host,
|
||||||
@ -352,3 +363,249 @@ remove_user_from_group(Host, US, Group) ->
|
|||||||
mnesia:delete_object(R)
|
mnesia:delete_object(R)
|
||||||
end,
|
end,
|
||||||
mnesia:transaction(F).
|
mnesia:transaction(F).
|
||||||
|
|
||||||
|
|
||||||
|
%%---------------------
|
||||||
|
%% Web Admin
|
||||||
|
%%---------------------
|
||||||
|
|
||||||
|
webadmin_menu(Acc, _Host) ->
|
||||||
|
[{"shared-roster", "Shared Roster"} | Acc].
|
||||||
|
|
||||||
|
webadmin_page(_, Host,
|
||||||
|
#request{us = US,
|
||||||
|
path = ["shared-roster"],
|
||||||
|
q = Query,
|
||||||
|
lang = Lang} = Request) ->
|
||||||
|
Res = list_shared_roster_groups(Host, Query, Lang),
|
||||||
|
{stop, Res};
|
||||||
|
|
||||||
|
webadmin_page(_, Host,
|
||||||
|
#request{us = US,
|
||||||
|
path = ["shared-roster", Group],
|
||||||
|
q = Query,
|
||||||
|
lang = Lang} = Request) ->
|
||||||
|
Res = shared_roster_group(Host, Group, Query, Lang),
|
||||||
|
{stop, Res};
|
||||||
|
|
||||||
|
webadmin_page(Acc, _, _) -> Acc.
|
||||||
|
|
||||||
|
list_shared_roster_groups(Host, Query, Lang) ->
|
||||||
|
Res = list_sr_groups_parse_query(Host, Query),
|
||||||
|
SRGroups = mod_shared_roster:list_groups(Host),
|
||||||
|
FGroups =
|
||||||
|
?XAE("table", [],
|
||||||
|
[?XE("tbody",
|
||||||
|
lists:map(
|
||||||
|
fun(Group) ->
|
||||||
|
?XE("tr",
|
||||||
|
[?XE("td", [?INPUT("checkbox", "selected",
|
||||||
|
Group)]),
|
||||||
|
?XE("td", [?AC(Group ++ "/", Group)])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end, lists:sort(SRGroups)) ++
|
||||||
|
[?XE("tr",
|
||||||
|
[?X("td"),
|
||||||
|
?XE("td", [?INPUT("text", "namenew", "")]),
|
||||||
|
?XE("td", [?INPUTT("submit", "addnew", "Add New")])
|
||||||
|
]
|
||||||
|
)]
|
||||||
|
)]),
|
||||||
|
[?XC("h1", ?T("Shared Roster Groups"))] ++
|
||||||
|
case Res of
|
||||||
|
ok -> [?CT("Submitted"), ?P];
|
||||||
|
error -> [?CT("Bad format"), ?P];
|
||||||
|
nothing -> []
|
||||||
|
end ++
|
||||||
|
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
||||||
|
[FGroups,
|
||||||
|
?BR,
|
||||||
|
?INPUTT("submit", "delete", "Delete Selected")
|
||||||
|
])
|
||||||
|
].
|
||||||
|
|
||||||
|
list_sr_groups_parse_query(Host, Query) ->
|
||||||
|
case lists:keysearch("addnew", 1, Query) of
|
||||||
|
{value, _} ->
|
||||||
|
list_sr_groups_parse_addnew(Host, Query);
|
||||||
|
_ ->
|
||||||
|
case lists:keysearch("delete", 1, Query) of
|
||||||
|
{value, _} ->
|
||||||
|
list_sr_groups_parse_delete(Host, Query);
|
||||||
|
_ ->
|
||||||
|
nothing
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
|
list_sr_groups_parse_addnew(Host, Query) ->
|
||||||
|
case lists:keysearch("namenew", 1, Query) of
|
||||||
|
{value, {_, Group}} when Group /= "" ->
|
||||||
|
mod_shared_roster:create_group(Host, Group),
|
||||||
|
ok;
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end.
|
||||||
|
|
||||||
|
list_sr_groups_parse_delete(Host, Query) ->
|
||||||
|
SRGroups = mod_shared_roster:list_groups(Host),
|
||||||
|
lists:foreach(
|
||||||
|
fun(Group) ->
|
||||||
|
case lists:member({"selected", Group}, Query) of
|
||||||
|
true ->
|
||||||
|
mod_shared_roster:delete_group(Host, Group);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end, SRGroups),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
|
||||||
|
shared_roster_group(Host, Group, Query, Lang) ->
|
||||||
|
Res = shared_roster_group_parse_query(Host, Group, Query),
|
||||||
|
GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
|
||||||
|
Name = get_opt(GroupOpts, name, ""),
|
||||||
|
Description = get_opt(GroupOpts, description, ""),
|
||||||
|
AllUsers = get_opt(GroupOpts, all_users, false),
|
||||||
|
Disabled = false,
|
||||||
|
DisplayedGroups = get_opt(GroupOpts, displayed_groups, []),
|
||||||
|
Members = mod_shared_roster:get_group_explicit_users(Host, Group),
|
||||||
|
FMembers =
|
||||||
|
if
|
||||||
|
AllUsers ->
|
||||||
|
"@all@\n";
|
||||||
|
true ->
|
||||||
|
[]
|
||||||
|
end ++ [[us_to_list(Member), $\n] || Member <- Members],
|
||||||
|
FDisplayedGroups = [[DG, $\n] || DG <- DisplayedGroups],
|
||||||
|
FGroup =
|
||||||
|
?XAE("table", [],
|
||||||
|
[?XE("tbody",
|
||||||
|
[?XE("tr",
|
||||||
|
[?XCT("td", "Name:"),
|
||||||
|
?XE("td", [?INPUT("text", "name", Name)])
|
||||||
|
]
|
||||||
|
),
|
||||||
|
?XE("tr",
|
||||||
|
[?XCT("td", "Description:"),
|
||||||
|
?XE("td", [?XAC("textarea", [{"name", "description"},
|
||||||
|
{"rows", "3"},
|
||||||
|
{"cols", "20"}],
|
||||||
|
Description)])
|
||||||
|
]
|
||||||
|
),
|
||||||
|
?XE("tr",
|
||||||
|
[?XCT("td", "Members:"),
|
||||||
|
?XE("td", [?XAC("textarea", [{"name", "members"},
|
||||||
|
{"rows", "3"},
|
||||||
|
{"cols", "20"}],
|
||||||
|
FMembers)])
|
||||||
|
]
|
||||||
|
),
|
||||||
|
?XE("tr",
|
||||||
|
[?XCT("td", "Displayed Groups:"),
|
||||||
|
?XE("td", [?XAC("textarea", [{"name", "dispgroups"},
|
||||||
|
{"rows", "3"},
|
||||||
|
{"cols", "20"}],
|
||||||
|
FDisplayedGroups)])
|
||||||
|
]
|
||||||
|
)]
|
||||||
|
)]),
|
||||||
|
[?XC("h1", ?T("Shared Roster Groups"))] ++
|
||||||
|
[?XC("h2", ?T("Group ") ++ Group)] ++
|
||||||
|
case Res of
|
||||||
|
ok -> [?CT("Submitted"), ?P];
|
||||||
|
error -> [?CT("Bad format"), ?P];
|
||||||
|
nothing -> []
|
||||||
|
end ++
|
||||||
|
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
||||||
|
[FGroup,
|
||||||
|
?BR,
|
||||||
|
?INPUTT("submit", "submit", "Submit")
|
||||||
|
])
|
||||||
|
].
|
||||||
|
|
||||||
|
shared_roster_group_parse_query(Host, Group, Query) ->
|
||||||
|
case lists:keysearch("submit", 1, Query) of
|
||||||
|
{value, _} ->
|
||||||
|
{value, {_, Name}} = lists:keysearch("name", 1, Query),
|
||||||
|
{value, {_, Description}} = lists:keysearch("description", 1, Query),
|
||||||
|
{value, {_, SMembers}} = lists:keysearch("members", 1, Query),
|
||||||
|
{value, {_, SDispGroups}} = lists:keysearch("dispgroups", 1, Query),
|
||||||
|
NameOpt =
|
||||||
|
if
|
||||||
|
Name == "" -> [];
|
||||||
|
true -> [{name, Name}]
|
||||||
|
end,
|
||||||
|
DescriptionOpt =
|
||||||
|
if
|
||||||
|
Description == "" -> [];
|
||||||
|
true -> [{description, Description}]
|
||||||
|
end,
|
||||||
|
DispGroups = string:tokens(SDispGroups, "\r\n"),
|
||||||
|
DispGroupsOpt =
|
||||||
|
if
|
||||||
|
DispGroups == [] -> [];
|
||||||
|
true -> [{displayed_groups, DispGroups}]
|
||||||
|
end,
|
||||||
|
|
||||||
|
OldMembers = mod_shared_roster:get_group_explicit_users(
|
||||||
|
Host, Group),
|
||||||
|
SJIDs = string:tokens(SMembers, ", \r\n"),
|
||||||
|
NewMembers =
|
||||||
|
lists:foldl(
|
||||||
|
fun(_SJID, error) -> error;
|
||||||
|
(SJID, USs) ->
|
||||||
|
case SJID of
|
||||||
|
"@all@" ->
|
||||||
|
USs;
|
||||||
|
_ ->
|
||||||
|
case jlib:string_to_jid(SJID) of
|
||||||
|
JID when is_record(JID, jid) ->
|
||||||
|
[{JID#jid.luser, JID#jid.lserver} | USs];
|
||||||
|
error ->
|
||||||
|
error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, [], SJIDs),
|
||||||
|
AllUsersOpt =
|
||||||
|
case lists:member("@all@", SJIDs) of
|
||||||
|
true -> [{all_users, true}];
|
||||||
|
false -> []
|
||||||
|
end,
|
||||||
|
|
||||||
|
mod_shared_roster:set_group_opts(
|
||||||
|
Host, Group,
|
||||||
|
NameOpt ++ DispGroupsOpt ++ DescriptionOpt ++ AllUsersOpt),
|
||||||
|
|
||||||
|
if
|
||||||
|
NewMembers == error -> error;
|
||||||
|
true ->
|
||||||
|
AddedMembers = NewMembers -- OldMembers,
|
||||||
|
RemovedMembers = OldMembers -- NewMembers,
|
||||||
|
lists:foreach(
|
||||||
|
fun(US) ->
|
||||||
|
mod_shared_roster:remove_user_from_group(
|
||||||
|
Host, US, Group)
|
||||||
|
end, RemovedMembers),
|
||||||
|
lists:foreach(
|
||||||
|
fun(US) ->
|
||||||
|
mod_shared_roster:add_user_to_group(
|
||||||
|
Host, US, Group)
|
||||||
|
end, AddedMembers),
|
||||||
|
ok
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
nothing
|
||||||
|
end.
|
||||||
|
|
||||||
|
get_opt(Opts, Opt, Default) ->
|
||||||
|
case lists:keysearch(Opt, 1, Opts) of
|
||||||
|
{value, {_, Val}} ->
|
||||||
|
Val;
|
||||||
|
false ->
|
||||||
|
Default
|
||||||
|
end.
|
||||||
|
|
||||||
|
us_to_list({User, Server}) ->
|
||||||
|
jlib:jid_to_string({User, Server, ""}).
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
||||||
%%% Purpose : Administration web interface
|
%%% Purpose : Administration web interface
|
||||||
%%% Created : 9 Apr 2004 by Alexey Shchepin <alexey@sevcom.net>
|
%%% Created : 9 Apr 2004 by Alexey Shchepin <alexey@sevcom.net>
|
||||||
%%% Id : $Id$
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% Copyright (c) 2004-2006 Alexey Shchepin
|
%%% Copyright (c) 2004-2006 Alexey Shchepin
|
||||||
%%% Copyright (c) 2004-2006 Process One
|
%%% Copyright (c) 2004-2006 Process One
|
||||||
@ -15,46 +14,14 @@
|
|||||||
|
|
||||||
%% External exports
|
%% External exports
|
||||||
-export([process/2,
|
-export([process/2,
|
||||||
%% XXX bard: unexported, since it is only called from process/2 now
|
|
||||||
%% process_admin/2,
|
|
||||||
list_users/4,
|
list_users/4,
|
||||||
list_users_in_diapason/4]).
|
list_users_in_diapason/4,
|
||||||
|
pretty_print_xml/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
-include("ejabberd_http.hrl").
|
-include("ejabberd_http.hrl").
|
||||||
|
-include("ejabberd_web_admin.hrl").
|
||||||
-define(X(Name), {xmlelement, Name, [], []}).
|
|
||||||
-define(XA(Name, Attrs), {xmlelement, Name, Attrs, []}).
|
|
||||||
-define(XE(Name, Els), {xmlelement, Name, [], Els}).
|
|
||||||
-define(XAE(Name, Attrs, Els), {xmlelement, Name, Attrs, Els}).
|
|
||||||
-define(C(Text), {xmlcdata, Text}).
|
|
||||||
-define(XC(Name, Text), ?XE(Name, [?C(Text)])).
|
|
||||||
-define(XAC(Name, Attrs, Text), ?XAE(Name, Attrs, [?C(Text)])).
|
|
||||||
|
|
||||||
-define(T(Text), translate:translate(Lang, Text)).
|
|
||||||
-define(CT(Text), ?C(?T(Text))).
|
|
||||||
-define(XCT(Name, Text), ?XC(Name, ?T(Text))).
|
|
||||||
-define(XACT(Name, Attrs, Text), ?XAC(Name, Attrs, ?T(Text))).
|
|
||||||
|
|
||||||
|
|
||||||
-define(LI(Els), ?XE("li", Els)).
|
|
||||||
-define(A(URL, Els), ?XAE("a", [{"href", URL}], Els)).
|
|
||||||
-define(AC(URL, Text), ?A(URL, [?C(Text)])).
|
|
||||||
-define(ACT(URL, Text), ?AC(URL, ?T(Text))).
|
|
||||||
-define(P, ?X("p")).
|
|
||||||
-define(BR, ?X("br")).
|
|
||||||
-define(INPUT(Type, Name, Value),
|
|
||||||
?XA("input", [{"type", Type},
|
|
||||||
{"name", Name},
|
|
||||||
{"value", Value}])).
|
|
||||||
-define(INPUTT(Type, Name, Value), ?INPUT(Type, Name, ?T(Value))).
|
|
||||||
-define(INPUTS(Type, Name, Value, Size),
|
|
||||||
?XA("input", [{"type", Type},
|
|
||||||
{"name", Name},
|
|
||||||
{"value", Value},
|
|
||||||
{"size", Size}])).
|
|
||||||
-define(INPUTST(Type, Name, Value, Size), ?INPUT(Type, Name, ?T(Value), Size)).
|
|
||||||
|
|
||||||
|
|
||||||
process(["server", SHost | RPath], #request{auth = Auth,
|
process(["server", SHost | RPath], #request{auth = Auth,
|
||||||
@ -126,6 +93,8 @@ get_auth(Auth) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
make_xhtml(Els, global, Lang) ->
|
make_xhtml(Els, global, Lang) ->
|
||||||
|
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_main, [], []),
|
||||||
|
MenuItems2 = [?LI([?ACT("/admin/"++MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
|
||||||
{200, [html],
|
{200, [html],
|
||||||
{xmlelement, "html", [{"xmlns", "http://www.w3.org/1999/xhtml"},
|
{xmlelement, "html", [{"xmlns", "http://www.w3.org/1999/xhtml"},
|
||||||
{"xml:lang", Lang},
|
{"xml:lang", Lang},
|
||||||
@ -153,7 +122,7 @@ make_xhtml(Els, global, Lang) ->
|
|||||||
?LI([?ACT("/admin/vhosts/", "Virtual Hosts")]),
|
?LI([?ACT("/admin/vhosts/", "Virtual Hosts")]),
|
||||||
?LI([?ACT("/admin/nodes/", "Nodes")]),
|
?LI([?ACT("/admin/nodes/", "Nodes")]),
|
||||||
?LI([?ACT("/admin/stats/", "Statistics")])
|
?LI([?ACT("/admin/stats/", "Statistics")])
|
||||||
]
|
] ++ MenuItems2
|
||||||
)]),
|
)]),
|
||||||
?XAE("div",
|
?XAE("div",
|
||||||
[{"id", "content"}],
|
[{"id", "content"}],
|
||||||
@ -172,6 +141,8 @@ make_xhtml(Els, global, Lang) ->
|
|||||||
|
|
||||||
make_xhtml(Els, Host, Lang) ->
|
make_xhtml(Els, Host, Lang) ->
|
||||||
Base = "/admin/server/" ++ Host ++ "/",
|
Base = "/admin/server/" ++ Host ++ "/",
|
||||||
|
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host]),
|
||||||
|
MenuItems2 = [?LI([?ACT(Base ++ MI_uri ++ "/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
|
||||||
{200, [html],
|
{200, [html],
|
||||||
{xmlelement, "html", [{"xmlns", "http://www.w3.org/1999/xhtml"},
|
{xmlelement, "html", [{"xmlns", "http://www.w3.org/1999/xhtml"},
|
||||||
{"xml:lang", Lang},
|
{"xml:lang", Lang},
|
||||||
@ -205,14 +176,7 @@ make_xhtml(Els, Host, Lang) ->
|
|||||||
?LI([?ACT(Base ++ "last-activity/", "Last Activity")]),
|
?LI([?ACT(Base ++ "last-activity/", "Last Activity")]),
|
||||||
?LI([?ACT(Base ++ "nodes/", "Nodes")]),
|
?LI([?ACT(Base ++ "nodes/", "Nodes")]),
|
||||||
?LI([?ACT(Base ++ "stats/", "Statistics")])
|
?LI([?ACT(Base ++ "stats/", "Statistics")])
|
||||||
] ++
|
] ++ MenuItems2
|
||||||
case lists:member(mod_shared_roster,
|
|
||||||
gen_mod:loaded_modules(Host)) of
|
|
||||||
true ->
|
|
||||||
[?LI([?ACT(Base ++ "shared-roster/", "Shared Roster")])];
|
|
||||||
false ->
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
)]),
|
)]),
|
||||||
?XAE("div",
|
?XAE("div",
|
||||||
[{"id", "content"}],
|
[{"id", "content"}],
|
||||||
@ -607,6 +571,8 @@ process_admin(global,
|
|||||||
path = [],
|
path = [],
|
||||||
q = Query,
|
q = Query,
|
||||||
lang = Lang} = Request) ->
|
lang = Lang} = Request) ->
|
||||||
|
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_main, [], []),
|
||||||
|
MenuItems2 = [?LI([?ACT("/admin/"++MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
|
||||||
make_xhtml([?XCT("h1", "Administration"),
|
make_xhtml([?XCT("h1", "Administration"),
|
||||||
?XE("ul",
|
?XE("ul",
|
||||||
[?LI([?ACT("/admin/acls/", "Access Control Lists"), ?C(" "),
|
[?LI([?ACT("/admin/acls/", "Access Control Lists"), ?C(" "),
|
||||||
@ -616,7 +582,7 @@ process_admin(global,
|
|||||||
?LI([?ACT("/admin/vhosts/", "Virtual Hosts")]),
|
?LI([?ACT("/admin/vhosts/", "Virtual Hosts")]),
|
||||||
?LI([?ACT("/admin/nodes/", "Nodes")]),
|
?LI([?ACT("/admin/nodes/", "Nodes")]),
|
||||||
?LI([?ACT("/admin/stats/", "Statistics")])
|
?LI([?ACT("/admin/stats/", "Statistics")])
|
||||||
]
|
] ++ MenuItems2
|
||||||
)
|
)
|
||||||
], global, Lang);
|
], global, Lang);
|
||||||
|
|
||||||
@ -626,6 +592,8 @@ process_admin(Host,
|
|||||||
q = Query,
|
q = Query,
|
||||||
lang = Lang} = Request) ->
|
lang = Lang} = Request) ->
|
||||||
Base = "/admin/server/" ++ Host ++ "/",
|
Base = "/admin/server/" ++ Host ++ "/",
|
||||||
|
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host]),
|
||||||
|
MenuItems2 = [?LI([?ACT(Base ++ MI_uri ++ "/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
|
||||||
make_xhtml([?XCT("h1", "Administration"),
|
make_xhtml([?XCT("h1", "Administration"),
|
||||||
?XE("ul",
|
?XE("ul",
|
||||||
[?LI([?ACT(Base ++ "acls/", "Access Control Lists"), ?C(" "),
|
[?LI([?ACT(Base ++ "acls/", "Access Control Lists"), ?C(" "),
|
||||||
@ -637,14 +605,7 @@ process_admin(Host,
|
|||||||
?LI([?ACT(Base ++ "last-activity/", "Last Activity")]),
|
?LI([?ACT(Base ++ "last-activity/", "Last Activity")]),
|
||||||
?LI([?ACT(Base ++ "nodes/", "Nodes")]),
|
?LI([?ACT(Base ++ "nodes/", "Nodes")]),
|
||||||
?LI([?ACT(Base ++ "stats/", "Statistics")])
|
?LI([?ACT(Base ++ "stats/", "Statistics")])
|
||||||
] ++
|
] ++ MenuItems2
|
||||||
case lists:member(mod_shared_roster,
|
|
||||||
gen_mod:loaded_modules(Host)) of
|
|
||||||
true ->
|
|
||||||
[?LI([?ACT(Base ++ "shared-roster/", "Shared Roster")])];
|
|
||||||
false ->
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
)
|
)
|
||||||
], Host, Lang);
|
], Host, Lang);
|
||||||
|
|
||||||
@ -996,14 +957,6 @@ process_admin(Host,
|
|||||||
Res = user_info(U, Host, Query, Lang),
|
Res = user_info(U, Host, Query, Lang),
|
||||||
make_xhtml(Res, Host, Lang);
|
make_xhtml(Res, Host, Lang);
|
||||||
|
|
||||||
process_admin(Host,
|
|
||||||
#request{us = US,
|
|
||||||
path = ["user", U, "queue"],
|
|
||||||
q = Query,
|
|
||||||
lang = Lang} = Request) ->
|
|
||||||
Res = user_queue(U, Host, Query, Lang),
|
|
||||||
make_xhtml(Res, Host, Lang);
|
|
||||||
|
|
||||||
process_admin(Host,
|
process_admin(Host,
|
||||||
#request{us = US,
|
#request{us = US,
|
||||||
path = ["user", U, "roster"],
|
path = ["user", U, "roster"],
|
||||||
@ -1033,25 +986,15 @@ process_admin(Host,
|
|||||||
make_xhtml(Res, Host, Lang)
|
make_xhtml(Res, Host, Lang)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
process_admin(Host,
|
process_admin(Host, #request{lang = Lang} = Request) ->
|
||||||
#request{us = US,
|
{Hook, Opts} = case Host of
|
||||||
path = ["shared-roster"],
|
global -> {webadmin_page_main, [Request]};
|
||||||
q = Query,
|
Host -> {webadmin_page_host, [Host, Request]}
|
||||||
lang = Lang} = Request) ->
|
end,
|
||||||
Res = list_shared_roster_groups(Host, Query, Lang),
|
case ejabberd_hooks:run_fold(Hook, Host, [], Opts) of
|
||||||
make_xhtml(Res, Host, Lang);
|
[] -> setelement(1, make_xhtml([?XC("h1", "Not Found")], Host, Lang), 404);
|
||||||
|
Res -> make_xhtml(Res, Host, Lang)
|
||||||
process_admin(Host,
|
end.
|
||||||
#request{us = US,
|
|
||||||
path = ["shared-roster", Group],
|
|
||||||
q = Query,
|
|
||||||
lang = Lang} = Request) ->
|
|
||||||
Res = shared_roster_group(Host, Group, Query, Lang),
|
|
||||||
make_xhtml(Res, Host, Lang);
|
|
||||||
|
|
||||||
process_admin(Host,
|
|
||||||
#request{lang = Lang}) ->
|
|
||||||
setelement(1, make_xhtml([?XC("h1", "Not Found")], Host, Lang), 404).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1076,8 +1019,6 @@ acls_to_xhtml(ACLs) ->
|
|||||||
)]
|
)]
|
||||||
)]).
|
)]).
|
||||||
|
|
||||||
-define(ACLINPUT(Text), ?XE("td", [?INPUT("text", "value" ++ ID, Text)])).
|
|
||||||
|
|
||||||
acl_spec_to_text({user, U}) ->
|
acl_spec_to_text({user, U}) ->
|
||||||
{user, U};
|
{user, U};
|
||||||
|
|
||||||
@ -1489,7 +1430,8 @@ list_online_users(Host, _Lang) ->
|
|||||||
end, SUsers).
|
end, SUsers).
|
||||||
|
|
||||||
user_info(User, Server, Query, Lang) ->
|
user_info(User, Server, Query, Lang) ->
|
||||||
US = {jlib:nodeprep(User), jlib:nameprep(Server)},
|
LServer = jlib:nameprep(Server),
|
||||||
|
US = {jlib:nodeprep(User), LServer},
|
||||||
Res = user_parse_query(User, Server, Query),
|
Res = user_parse_query(User, Server, Query),
|
||||||
Resources = ejabberd_sm:get_user_resources(User, Server),
|
Resources = ejabberd_sm:get_user_resources(User, Server),
|
||||||
FResources =
|
FResources =
|
||||||
@ -1516,9 +1458,8 @@ user_info(User, Server, Query, Lang) ->
|
|||||||
Password = ejabberd_auth:get_password_s(User, Server),
|
Password = ejabberd_auth:get_password_s(User, Server),
|
||||||
FPassword = [?INPUT("password", "password", Password), ?C(" "),
|
FPassword = [?INPUT("password", "password", Password), ?C(" "),
|
||||||
?INPUTT("submit", "chpassword", "Change Password")],
|
?INPUTT("submit", "chpassword", "Change Password")],
|
||||||
QueueLen = length(mnesia:dirty_read({offline_msg, US})),
|
UserItems = ejabberd_hooks:run_fold(webadmin_user, LServer, [],
|
||||||
FQueueLen = [?AC("queue/",
|
[User, Server, Lang]),
|
||||||
integer_to_list(QueueLen))],
|
|
||||||
[?XC("h1", ?T("User ") ++ us_to_list(US))] ++
|
[?XC("h1", ?T("User ") ++ us_to_list(US))] ++
|
||||||
case Res of
|
case Res of
|
||||||
ok -> [?CT("Submitted"), ?P];
|
ok -> [?CT("Submitted"), ?P];
|
||||||
@ -1528,9 +1469,9 @@ user_info(User, Server, Query, Lang) ->
|
|||||||
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
||||||
[?XCT("h3", "Connected Resources:")] ++ FResources ++
|
[?XCT("h3", "Connected Resources:")] ++ FResources ++
|
||||||
[?XCT("h3", "Password:")] ++ FPassword ++
|
[?XCT("h3", "Password:")] ++ FPassword ++
|
||||||
[?XCT("h3", "Offline Messages:")] ++ FQueueLen ++
|
|
||||||
[?XE("h3", [?ACT("roster/", "Roster")])] ++
|
[?XE("h3", [?ACT("roster/", "Roster")])] ++
|
||||||
[?BR, ?INPUTT("submit", "removeuser", "Remove User")])].
|
UserItems ++
|
||||||
|
[?P, ?INPUTT("submit", "removeuser", "Remove User")])].
|
||||||
|
|
||||||
|
|
||||||
user_parse_query(User, Server, Query) ->
|
user_parse_query(User, Server, Query) ->
|
||||||
@ -1556,89 +1497,6 @@ user_parse_query(User, Server, Query) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
user_queue(User, Server, Query, Lang) ->
|
|
||||||
US = {jlib:nodeprep(User), jlib:nameprep(Server)},
|
|
||||||
Res = user_queue_parse_query(US, Query),
|
|
||||||
Msgs = lists:keysort(3, mnesia:dirty_read({offline_msg, US})),
|
|
||||||
FMsgs =
|
|
||||||
lists:map(
|
|
||||||
fun({offline_msg, _US, TimeStamp, _Expire, From, To,
|
|
||||||
{xmlelement, Name, Attrs, Els}} = Msg) ->
|
|
||||||
ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
|
|
||||||
{{Year, Month, Day}, {Hour, Minute, Second}} =
|
|
||||||
calendar:now_to_local_time(TimeStamp),
|
|
||||||
Time = lists:flatten(
|
|
||||||
io_lib:format(
|
|
||||||
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
|
||||||
[Year, Month, Day, Hour, Minute, Second])),
|
|
||||||
SFrom = jlib:jid_to_string(From),
|
|
||||||
STo = jlib:jid_to_string(To),
|
|
||||||
Attrs2 = jlib:replace_from_to_attrs(SFrom, STo, Attrs),
|
|
||||||
Packet = jlib:remove_attr(
|
|
||||||
"jeai-id", {xmlelement, Name, Attrs2, Els}),
|
|
||||||
FPacket = pretty_print(Packet),
|
|
||||||
?XE("tr",
|
|
||||||
[?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
|
|
||||||
?XAC("td", [{"class", "valign"}], Time),
|
|
||||||
?XAC("td", [{"class", "valign"}], SFrom),
|
|
||||||
?XAC("td", [{"class", "valign"}], STo),
|
|
||||||
?XAE("td", [{"class", "valign"}], [?XC("pre", FPacket)])]
|
|
||||||
)
|
|
||||||
end, Msgs),
|
|
||||||
[?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
|
|
||||||
[us_to_list(US)]))] ++
|
|
||||||
case Res of
|
|
||||||
ok -> [?CT("Submitted"), ?P];
|
|
||||||
nothing -> []
|
|
||||||
end ++
|
|
||||||
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
|
||||||
[?XE("table",
|
|
||||||
[?XE("thead",
|
|
||||||
[?XE("tr",
|
|
||||||
[?X("td"),
|
|
||||||
?XCT("td", "Time"),
|
|
||||||
?XCT("td", "From"),
|
|
||||||
?XCT("td", "To"),
|
|
||||||
?XCT("td", "Packet")
|
|
||||||
])]),
|
|
||||||
?XE("tbody",
|
|
||||||
if
|
|
||||||
FMsgs == [] ->
|
|
||||||
[?XE("tr",
|
|
||||||
[?XAC("td", [{"colspan", "4"}], " ")]
|
|
||||||
)];
|
|
||||||
true ->
|
|
||||||
FMsgs
|
|
||||||
end
|
|
||||||
)]),
|
|
||||||
?BR,
|
|
||||||
?INPUTT("submit", "delete", "Delete Selected")
|
|
||||||
])].
|
|
||||||
|
|
||||||
user_queue_parse_query(US, Query) ->
|
|
||||||
case lists:keysearch("delete", 1, Query) of
|
|
||||||
{value, _} ->
|
|
||||||
Msgs = lists:keysort(3, mnesia:dirty_read({offline_msg, US})),
|
|
||||||
F = fun() ->
|
|
||||||
lists:foreach(
|
|
||||||
fun(Msg) ->
|
|
||||||
ID = jlib:encode_base64(
|
|
||||||
binary_to_list(term_to_binary(Msg))),
|
|
||||||
case lists:member({"selected", ID}, Query) of
|
|
||||||
true ->
|
|
||||||
mnesia:delete_object(Msg);
|
|
||||||
false ->
|
|
||||||
ok
|
|
||||||
end
|
|
||||||
end, Msgs)
|
|
||||||
end,
|
|
||||||
mnesia:transaction(F),
|
|
||||||
ok;
|
|
||||||
false ->
|
|
||||||
nothing
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-record(roster, {usj,
|
-record(roster, {usj,
|
||||||
us,
|
us,
|
||||||
@ -1922,6 +1780,8 @@ search_running_node(SNode, [Node | Nodes]) ->
|
|||||||
|
|
||||||
get_node(global, Node, [], Query, Lang) ->
|
get_node(global, Node, [], Query, Lang) ->
|
||||||
Res = node_parse_query(Node, Query),
|
Res = node_parse_query(Node, Query),
|
||||||
|
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_node, [], [Node]),
|
||||||
|
MenuItems2 = [?LI([?ACT(MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
|
||||||
[?XC("h1", ?T("Node ") ++ atom_to_list(Node))] ++
|
[?XC("h1", ?T("Node ") ++ atom_to_list(Node))] ++
|
||||||
case Res of
|
case Res of
|
||||||
ok -> [?CT("Submitted"), ?P];
|
ok -> [?CT("Submitted"), ?P];
|
||||||
@ -1934,7 +1794,7 @@ get_node(global, Node, [], Query, Lang) ->
|
|||||||
?LI([?ACT("ports/", "Listened Ports")]),
|
?LI([?ACT("ports/", "Listened Ports")]),
|
||||||
?LI([?ACT("stats/", "Statistics")]),
|
?LI([?ACT("stats/", "Statistics")]),
|
||||||
?LI([?ACT("update/", "Update")])
|
?LI([?ACT("update/", "Update")])
|
||||||
]),
|
] ++ MenuItems2),
|
||||||
?XAE("form", [{"action", ""}, {"method", "post"}],
|
?XAE("form", [{"action", ""}, {"method", "post"}],
|
||||||
[?INPUTT("submit", "restart", "Restart"),
|
[?INPUTT("submit", "restart", "Restart"),
|
||||||
?C(" "),
|
?C(" "),
|
||||||
@ -1942,9 +1802,11 @@ get_node(global, Node, [], Query, Lang) ->
|
|||||||
];
|
];
|
||||||
|
|
||||||
get_node(Host, Node, [], Query, Lang) ->
|
get_node(Host, Node, [], Query, Lang) ->
|
||||||
|
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host, [], [Host, Node]),
|
||||||
|
MenuItems2 = [?LI([?ACT(MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
|
||||||
[?XC("h1", ?T("Node ") ++ atom_to_list(Node)),
|
[?XC("h1", ?T("Node ") ++ atom_to_list(Node)),
|
||||||
?XE("ul",
|
?XE("ul",
|
||||||
[?LI([?ACT("modules/", "Modules")])])
|
[?LI([?ACT("modules/", "Modules")])] ++ MenuItems2)
|
||||||
];
|
];
|
||||||
|
|
||||||
get_node(global, Node, ["db"], Query, Lang) ->
|
get_node(global, Node, ["db"], Query, Lang) ->
|
||||||
@ -2176,7 +2038,15 @@ get_node(global, Node, ["update"], Query, Lang) ->
|
|||||||
];
|
];
|
||||||
|
|
||||||
get_node(Host, Node, NPath, Query, Lang) ->
|
get_node(Host, Node, NPath, Query, Lang) ->
|
||||||
[?XCT("h1", "Not Found")].
|
{Hook, Opts} = case Host of
|
||||||
|
global -> {webadmin_page_node, [Node, NPath, Query]};
|
||||||
|
Host -> {webadmin_page_hostnode, [Host, Node, NPath, Query]}
|
||||||
|
end,
|
||||||
|
case ejabberd_hooks:run_fold(Hook, Host, [], Opts) of
|
||||||
|
[] -> [?XC("h1", "Not Found")];
|
||||||
|
Res -> Res
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
node_parse_query(Node, Query) ->
|
node_parse_query(Node, Query) ->
|
||||||
@ -2464,12 +2334,12 @@ node_update_parse_query(Node, Query) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
pretty_print(El) ->
|
pretty_print_xml(El) ->
|
||||||
lists:flatten(pretty_print(El, "")).
|
lists:flatten(pretty_print_xml(El, "")).
|
||||||
|
|
||||||
pretty_print({xmlcdata, CData}, Prefix) ->
|
pretty_print_xml({xmlcdata, CData}, Prefix) ->
|
||||||
[Prefix, CData, $\n];
|
[Prefix, CData, $\n];
|
||||||
pretty_print({xmlelement, Name, Attrs, Els}, Prefix) ->
|
pretty_print_xml({xmlelement, Name, Attrs, Els}, Prefix) ->
|
||||||
[Prefix, $<, Name,
|
[Prefix, $<, Name,
|
||||||
case Attrs of
|
case Attrs of
|
||||||
[] ->
|
[] ->
|
||||||
@ -2499,7 +2369,7 @@ pretty_print({xmlelement, Name, Attrs, Els}, Prefix) ->
|
|||||||
true ->
|
true ->
|
||||||
[$>, $\n,
|
[$>, $\n,
|
||||||
lists:map(fun(E) ->
|
lists:map(fun(E) ->
|
||||||
pretty_print(E, [Prefix, " "])
|
pretty_print_xml(E, [Prefix, " "])
|
||||||
end, Els),
|
end, Els),
|
||||||
Prefix, $<, $/, Name, $>, $\n
|
Prefix, $<, $/, Name, $>, $\n
|
||||||
]
|
]
|
||||||
@ -2507,225 +2377,6 @@ pretty_print({xmlelement, Name, Attrs, Els}, Prefix) ->
|
|||||||
end].
|
end].
|
||||||
|
|
||||||
|
|
||||||
list_shared_roster_groups(Host, Query, Lang) ->
|
|
||||||
Res = list_sr_groups_parse_query(Host, Query),
|
|
||||||
SRGroups = mod_shared_roster:list_groups(Host),
|
|
||||||
FGroups =
|
|
||||||
?XAE("table", [],
|
|
||||||
[?XE("tbody",
|
|
||||||
lists:map(
|
|
||||||
fun(Group) ->
|
|
||||||
?XE("tr",
|
|
||||||
[?XE("td", [?INPUT("checkbox", "selected",
|
|
||||||
Group)]),
|
|
||||||
?XE("td", [?AC(Group ++ "/", Group)])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
end, lists:sort(SRGroups)) ++
|
|
||||||
[?XE("tr",
|
|
||||||
[?X("td"),
|
|
||||||
?XE("td", [?INPUT("text", "namenew", "")]),
|
|
||||||
?XE("td", [?INPUTT("submit", "addnew", "Add New")])
|
|
||||||
]
|
|
||||||
)]
|
|
||||||
)]),
|
|
||||||
[?XC("h1", ?T("Shared Roster Groups"))] ++
|
|
||||||
case Res of
|
|
||||||
ok -> [?CT("Submitted"), ?P];
|
|
||||||
error -> [?CT("Bad format"), ?P];
|
|
||||||
nothing -> []
|
|
||||||
end ++
|
|
||||||
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
|
||||||
[FGroups,
|
|
||||||
?BR,
|
|
||||||
?INPUTT("submit", "delete", "Delete Selected")
|
|
||||||
])
|
|
||||||
].
|
|
||||||
|
|
||||||
list_sr_groups_parse_query(Host, Query) ->
|
|
||||||
case lists:keysearch("addnew", 1, Query) of
|
|
||||||
{value, _} ->
|
|
||||||
list_sr_groups_parse_addnew(Host, Query);
|
|
||||||
_ ->
|
|
||||||
case lists:keysearch("delete", 1, Query) of
|
|
||||||
{value, _} ->
|
|
||||||
list_sr_groups_parse_delete(Host, Query);
|
|
||||||
_ ->
|
|
||||||
nothing
|
|
||||||
end
|
|
||||||
end.
|
|
||||||
|
|
||||||
list_sr_groups_parse_addnew(Host, Query) ->
|
|
||||||
case lists:keysearch("namenew", 1, Query) of
|
|
||||||
{value, {_, Group}} when Group /= "" ->
|
|
||||||
mod_shared_roster:create_group(Host, Group),
|
|
||||||
ok;
|
|
||||||
_ ->
|
|
||||||
error
|
|
||||||
end.
|
|
||||||
|
|
||||||
list_sr_groups_parse_delete(Host, Query) ->
|
|
||||||
SRGroups = mod_shared_roster:list_groups(Host),
|
|
||||||
lists:foreach(
|
|
||||||
fun(Group) ->
|
|
||||||
case lists:member({"selected", Group}, Query) of
|
|
||||||
true ->
|
|
||||||
mod_shared_roster:delete_group(Host, Group);
|
|
||||||
_ ->
|
|
||||||
ok
|
|
||||||
end
|
|
||||||
end, SRGroups),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
|
|
||||||
shared_roster_group(Host, Group, Query, Lang) ->
|
|
||||||
Res = shared_roster_group_parse_query(Host, Group, Query),
|
|
||||||
GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
|
|
||||||
Name = get_opt(GroupOpts, name, ""),
|
|
||||||
Description = get_opt(GroupOpts, description, ""),
|
|
||||||
AllUsers = get_opt(GroupOpts, all_users, false),
|
|
||||||
Disabled = false,
|
|
||||||
DisplayedGroups = get_opt(GroupOpts, displayed_groups, []),
|
|
||||||
Members = mod_shared_roster:get_group_explicit_users(Host, Group),
|
|
||||||
FMembers =
|
|
||||||
if
|
|
||||||
AllUsers ->
|
|
||||||
"@all@\n";
|
|
||||||
true ->
|
|
||||||
[]
|
|
||||||
end ++ [[us_to_list(Member), $\n] || Member <- Members],
|
|
||||||
FDisplayedGroups = [[DG, $\n] || DG <- DisplayedGroups],
|
|
||||||
FGroup =
|
|
||||||
?XAE("table", [],
|
|
||||||
[?XE("tbody",
|
|
||||||
[?XE("tr",
|
|
||||||
[?XCT("td", "Name:"),
|
|
||||||
?XE("td", [?INPUT("text", "name", Name)])
|
|
||||||
]
|
|
||||||
),
|
|
||||||
?XE("tr",
|
|
||||||
[?XCT("td", "Description:"),
|
|
||||||
?XE("td", [?XAC("textarea", [{"name", "description"},
|
|
||||||
{"rows", "3"},
|
|
||||||
{"cols", "20"}],
|
|
||||||
Description)])
|
|
||||||
]
|
|
||||||
),
|
|
||||||
?XE("tr",
|
|
||||||
[?XCT("td", "Members:"),
|
|
||||||
?XE("td", [?XAC("textarea", [{"name", "members"},
|
|
||||||
{"rows", "3"},
|
|
||||||
{"cols", "20"}],
|
|
||||||
FMembers)])
|
|
||||||
]
|
|
||||||
),
|
|
||||||
?XE("tr",
|
|
||||||
[?XCT("td", "Displayed Groups:"),
|
|
||||||
?XE("td", [?XAC("textarea", [{"name", "dispgroups"},
|
|
||||||
{"rows", "3"},
|
|
||||||
{"cols", "20"}],
|
|
||||||
FDisplayedGroups)])
|
|
||||||
]
|
|
||||||
)]
|
|
||||||
)]),
|
|
||||||
[?XC("h1", ?T("Shared Roster Groups"))] ++
|
|
||||||
[?XC("h2", ?T("Group ") ++ Group)] ++
|
|
||||||
case Res of
|
|
||||||
ok -> [?CT("Submitted"), ?P];
|
|
||||||
error -> [?CT("Bad format"), ?P];
|
|
||||||
nothing -> []
|
|
||||||
end ++
|
|
||||||
[?XAE("form", [{"action", ""}, {"method", "post"}],
|
|
||||||
[FGroup,
|
|
||||||
?BR,
|
|
||||||
?INPUTT("submit", "submit", "Submit")
|
|
||||||
])
|
|
||||||
].
|
|
||||||
|
|
||||||
shared_roster_group_parse_query(Host, Group, Query) ->
|
|
||||||
case lists:keysearch("submit", 1, Query) of
|
|
||||||
{value, _} ->
|
|
||||||
{value, {_, Name}} = lists:keysearch("name", 1, Query),
|
|
||||||
{value, {_, Description}} = lists:keysearch("description", 1, Query),
|
|
||||||
{value, {_, SMembers}} = lists:keysearch("members", 1, Query),
|
|
||||||
{value, {_, SDispGroups}} = lists:keysearch("dispgroups", 1, Query),
|
|
||||||
NameOpt =
|
|
||||||
if
|
|
||||||
Name == "" -> [];
|
|
||||||
true -> [{name, Name}]
|
|
||||||
end,
|
|
||||||
DescriptionOpt =
|
|
||||||
if
|
|
||||||
Description == "" -> [];
|
|
||||||
true -> [{description, Description}]
|
|
||||||
end,
|
|
||||||
DispGroups = string:tokens(SDispGroups, "\r\n"),
|
|
||||||
DispGroupsOpt =
|
|
||||||
if
|
|
||||||
DispGroups == [] -> [];
|
|
||||||
true -> [{displayed_groups, DispGroups}]
|
|
||||||
end,
|
|
||||||
|
|
||||||
OldMembers = mod_shared_roster:get_group_explicit_users(
|
|
||||||
Host, Group),
|
|
||||||
SJIDs = string:tokens(SMembers, ", \r\n"),
|
|
||||||
NewMembers =
|
|
||||||
lists:foldl(
|
|
||||||
fun(_SJID, error) -> error;
|
|
||||||
(SJID, USs) ->
|
|
||||||
case SJID of
|
|
||||||
"@all@" ->
|
|
||||||
USs;
|
|
||||||
_ ->
|
|
||||||
case jlib:string_to_jid(SJID) of
|
|
||||||
JID when is_record(JID, jid) ->
|
|
||||||
[{JID#jid.luser, JID#jid.lserver} | USs];
|
|
||||||
error ->
|
|
||||||
error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, [], SJIDs),
|
|
||||||
AllUsersOpt =
|
|
||||||
case lists:member("@all@", SJIDs) of
|
|
||||||
true -> [{all_users, true}];
|
|
||||||
false -> []
|
|
||||||
end,
|
|
||||||
|
|
||||||
mod_shared_roster:set_group_opts(
|
|
||||||
Host, Group,
|
|
||||||
NameOpt ++ DispGroupsOpt ++ DescriptionOpt ++ AllUsersOpt),
|
|
||||||
|
|
||||||
if
|
|
||||||
NewMembers == error -> error;
|
|
||||||
true ->
|
|
||||||
AddedMembers = NewMembers -- OldMembers,
|
|
||||||
RemovedMembers = OldMembers -- NewMembers,
|
|
||||||
lists:foreach(
|
|
||||||
fun(US) ->
|
|
||||||
mod_shared_roster:remove_user_from_group(
|
|
||||||
Host, US, Group)
|
|
||||||
end, RemovedMembers),
|
|
||||||
lists:foreach(
|
|
||||||
fun(US) ->
|
|
||||||
mod_shared_roster:add_user_to_group(
|
|
||||||
Host, US, Group)
|
|
||||||
end, AddedMembers),
|
|
||||||
ok
|
|
||||||
end;
|
|
||||||
_ ->
|
|
||||||
nothing
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
get_opt(Opts, Opt, Default) ->
|
|
||||||
case lists:keysearch(Opt, 1, Opts) of
|
|
||||||
{value, {_, Val}} ->
|
|
||||||
Val;
|
|
||||||
false ->
|
|
||||||
Default
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
url_func({user_diapason, From, To}) ->
|
url_func({user_diapason, From, To}) ->
|
||||||
integer_to_list(From) ++ "-" ++ integer_to_list(To) ++ "/";
|
integer_to_list(From) ++ "-" ++ integer_to_list(To) ++ "/";
|
||||||
url_func({users_queue, Prefix, User, Server}) ->
|
url_func({users_queue, Prefix, User, Server}) ->
|
||||||
|
38
src/web/ejabberd_web_admin.hrl
Normal file
38
src/web/ejabberd_web_admin.hrl
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
%%% File : ejabberd_web_admin.hrl
|
||||||
|
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
||||||
|
%%% Purpose :
|
||||||
|
%%% Created : 22 Aug 2007 by Alexey Shchepin <alexey@process-one.net>
|
||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
|
-define(X(Name), {xmlelement, Name, [], []}).
|
||||||
|
-define(XA(Name, Attrs), {xmlelement, Name, Attrs, []}).
|
||||||
|
-define(XE(Name, Els), {xmlelement, Name, [], Els}).
|
||||||
|
-define(XAE(Name, Attrs, Els), {xmlelement, Name, Attrs, Els}).
|
||||||
|
-define(C(Text), {xmlcdata, Text}).
|
||||||
|
-define(XC(Name, Text), ?XE(Name, [?C(Text)])).
|
||||||
|
-define(XAC(Name, Attrs, Text), ?XAE(Name, Attrs, [?C(Text)])).
|
||||||
|
|
||||||
|
-define(T(Text), translate:translate(Lang, Text)).
|
||||||
|
-define(CT(Text), ?C(?T(Text))).
|
||||||
|
-define(XCT(Name, Text), ?XC(Name, ?T(Text))).
|
||||||
|
-define(XACT(Name, Attrs, Text), ?XAC(Name, Attrs, ?T(Text))).
|
||||||
|
|
||||||
|
-define(LI(Els), ?XE("li", Els)).
|
||||||
|
-define(A(URL, Els), ?XAE("a", [{"href", URL}], Els)).
|
||||||
|
-define(AC(URL, Text), ?A(URL, [?C(Text)])).
|
||||||
|
-define(ACT(URL, Text), ?AC(URL, ?T(Text))).
|
||||||
|
-define(P, ?X("p")).
|
||||||
|
-define(BR, ?X("br")).
|
||||||
|
-define(INPUT(Type, Name, Value),
|
||||||
|
?XA("input", [{"type", Type},
|
||||||
|
{"name", Name},
|
||||||
|
{"value", Value}])).
|
||||||
|
-define(INPUTT(Type, Name, Value), ?INPUT(Type, Name, ?T(Value))).
|
||||||
|
-define(INPUTS(Type, Name, Value, Size),
|
||||||
|
?XA("input", [{"type", Type},
|
||||||
|
{"name", Name},
|
||||||
|
{"value", Value},
|
||||||
|
{"size", Size}])).
|
||||||
|
-define(INPUTST(Type, Name, Value, Size), ?INPUT(Type, Name, ?T(Value), Size)).
|
||||||
|
-define(ACLINPUT(Text), ?XE("td", [?INPUT("text", "value" ++ ID, Text)])).
|
Loading…
Reference in New Issue
Block a user