Update some modules to work with ejabberd 19.08 (#277)
This commit is contained in:
parent
4753268b5f
commit
857d350a71
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
mod_cron - Execute scheduled commands
|
mod_cron - Execute scheduled commands
|
||||||
|
|
||||||
|
Requires: ejabberd 19.08 or higher
|
||||||
http://www.ejabberd.im/mod_cron
|
http://www.ejabberd.im/mod_cron
|
||||||
Author: Badlop
|
Author: Badlop
|
||||||
|
|
||||||
|
|
|
@ -11,19 +11,18 @@
|
||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([
|
-export([start/2, stop/1, depends/2, mod_options/1, mod_opt_type/1]).
|
||||||
cron_list/1, cron_del/1,
|
-export([cron_list/1, cron_del/1,
|
||||||
run_task/3,
|
run_task/3,
|
||||||
web_menu_host/3, web_page_host/3,
|
web_menu_host/3, web_page_host/3,
|
||||||
start/2,
|
|
||||||
apply_interval/3,
|
apply_interval/3,
|
||||||
apply_interval1/3,
|
apply_interval1/3]).
|
||||||
stop/1]).
|
|
||||||
|
|
||||||
-include("ejabberd_commands.hrl").
|
-include("ejabberd_commands.hrl").
|
||||||
-include("ejabberd_http.hrl").
|
-include("ejabberd_http.hrl").
|
||||||
-include("ejabberd_web_admin.hrl").
|
-include("ejabberd_web_admin.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
-include("translate.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
-record(task, {taskid, timerref, host, task}).
|
-record(task, {taskid, timerref, host, task}).
|
||||||
|
@ -36,7 +35,7 @@ start(Host, Opts) ->
|
||||||
ejabberd_commands:register_commands(commands()),
|
ejabberd_commands:register_commands(commands()),
|
||||||
ejabberd_hooks:add(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50),
|
ejabberd_hooks:add(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50),
|
||||||
ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, web_page_host, 50),
|
ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, web_page_host, 50),
|
||||||
Tasks = gen_mod:get_opt(tasks, Opts, []),
|
Tasks = gen_mod:get_opt(tasks, Opts),
|
||||||
catch ets:new(cron_tasks, [ordered_set, named_table, public, {keypos, 2}]),
|
catch ets:new(cron_tasks, [ordered_set, named_table, public, {keypos, 2}]),
|
||||||
[add_task(Host, Task) || Task <- Tasks],
|
[add_task(Host, Task) || Task <- Tasks],
|
||||||
ok.
|
ok.
|
||||||
|
@ -49,6 +48,14 @@ stop(Host) ->
|
||||||
[delete_task(Task) || Task <- get_tasks(Host)],
|
[delete_task(Task) || Task <- get_tasks(Host)],
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
depends(_Host, _Opts) ->
|
||||||
|
[].
|
||||||
|
|
||||||
|
mod_opt_type(tasks) ->
|
||||||
|
econf:list(econf:any()).
|
||||||
|
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[{tasks, []}].
|
||||||
|
|
||||||
%% ---------------------
|
%% ---------------------
|
||||||
%% Task management
|
%% Task management
|
||||||
|
@ -231,7 +238,7 @@ cron_del(TaskId) ->
|
||||||
%% ---------------------
|
%% ---------------------
|
||||||
|
|
||||||
web_menu_host(Acc, _Host, Lang) ->
|
web_menu_host(Acc, _Host, Lang) ->
|
||||||
[{<<"cron">>, ?T(<<"Cron Tasks">>)} | Acc].
|
[{<<"cron">>, translate:translate(Lang, ?T("Cron Tasks"))} | Acc].
|
||||||
|
|
||||||
web_page_host(_, Host,
|
web_page_host(_, Host,
|
||||||
#request{path = [<<"cron">>],
|
#request{path = [<<"cron">>],
|
||||||
|
@ -245,9 +252,13 @@ web_page_host(Acc, _, _) -> Acc.
|
||||||
make_tasks_table(Tasks, Lang) ->
|
make_tasks_table(Tasks, Lang) ->
|
||||||
TList = lists:map(
|
TList = lists:map(
|
||||||
fun(T) ->
|
fun(T) ->
|
||||||
{Time_num, Time_unit, Mod, Fun, Args} = T#task.task,
|
[TimeNum, TimeUnit, Mod, Fun, Args, InTimerType] =
|
||||||
|
[proplists:get_value(Key, T#task.task)
|
||||||
|
|| Key <- [time, units, module, function, arguments, timer_type]],
|
||||||
?XE(<<"tr">>,
|
?XE(<<"tr">>,
|
||||||
[?XC(<<"td">>, list_to_binary(integer_to_list(Time_num) ++" " ++ atom_to_list(Time_unit))),
|
[?XC(<<"td">>, list_to_binary(integer_to_list(TimeNum)++" "
|
||||||
|
++atom_to_list(TimeUnit)++" "
|
||||||
|
++atom_to_list(InTimerType))),
|
||||||
?XC(<<"td">>, list_to_binary(atom_to_list(Mod))),
|
?XC(<<"td">>, list_to_binary(atom_to_list(Mod))),
|
||||||
?XC(<<"td">>, list_to_binary(atom_to_list(Fun))),
|
?XC(<<"td">>, list_to_binary(atom_to_list(Fun))),
|
||||||
?XC(<<"td">>, list_to_binary(io_lib:format("~p", [Args])))])
|
?XC(<<"td">>, list_to_binary(io_lib:format("~p", [Args])))])
|
||||||
|
|
|
@ -10,13 +10,10 @@
|
||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2,
|
-export([start/2, stop/1, depends/2, mod_opt_type/1, mod_options/1]).
|
||||||
init/1,
|
-export([init/1,
|
||||||
stop/1,
|
|
||||||
depends/2,
|
|
||||||
log_packet_send/1,
|
log_packet_send/1,
|
||||||
log_packet_receive/1,
|
log_packet_receive/1]).
|
||||||
mod_opt_type/1]).
|
|
||||||
|
|
||||||
-ifndef(LAGER).
|
-ifndef(LAGER).
|
||||||
-define(LAGER, 1).
|
-define(LAGER, 1).
|
||||||
|
@ -33,7 +30,7 @@
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
?DEBUG(" ~p ~p~n", [Host, Opts]),
|
?DEBUG(" ~p ~p~n", [Host, Opts]),
|
||||||
case gen_mod:get_opt(host_config, Opts, []) of
|
case gen_mod:get_opt(host_config, Opts) of
|
||||||
[] ->
|
[] ->
|
||||||
start_vh(Host, Opts);
|
start_vh(Host, Opts);
|
||||||
HostConfig ->
|
HostConfig ->
|
||||||
|
@ -51,8 +48,8 @@ start_vhs(Host, [{_VHost, _Opts}| Tail]) ->
|
||||||
?DEBUG("start_vhs ~p ~p~n", [Host, [{_VHost, _Opts}| Tail]]),
|
?DEBUG("start_vhs ~p ~p~n", [Host, [{_VHost, _Opts}| Tail]]),
|
||||||
start_vhs(Host, Tail).
|
start_vhs(Host, Tail).
|
||||||
start_vh(Host, Opts) ->
|
start_vh(Host, Opts) ->
|
||||||
Path = gen_mod:get_opt(path, Opts, ?DEFAULT_PATH),
|
Path = gen_mod:get_opt(path, Opts),
|
||||||
Format = gen_mod:get_opt(format, Opts, ?DEFAULT_FORMAT),
|
Format = gen_mod:get_opt(format, Opts),
|
||||||
ejabberd_hooks:add(user_send_packet, Host, ?MODULE, log_packet_send, 55),
|
ejabberd_hooks:add(user_send_packet, Host, ?MODULE, log_packet_send, 55),
|
||||||
ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, log_packet_receive, 55),
|
ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, log_packet_receive, 55),
|
||||||
register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
register(gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
|
@ -79,10 +76,6 @@ stop(Host) ->
|
||||||
gen_mod:get_module_proc(Host, ?PROCNAME) ! stop,
|
gen_mod:get_module_proc(Host, ?PROCNAME) ! stop,
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
|
|
||||||
depends(_Host, _Opts) ->
|
|
||||||
[].
|
|
||||||
|
|
||||||
log_packet_send({Packet, C2SState}) ->
|
log_packet_send({Packet, C2SState}) ->
|
||||||
From = xmpp:get_from(Packet),
|
From = xmpp:get_from(Packet),
|
||||||
To = xmpp:get_to(Packet),
|
To = xmpp:get_to(Packet),
|
||||||
|
@ -103,10 +96,10 @@ log_packet_receive({Packet, C2SState}) ->
|
||||||
|
|
||||||
log_packet(From, To, #message{type = Type} = Packet, Host) ->
|
log_packet(From, To, #message{type = Type} = Packet, Host) ->
|
||||||
case Type of
|
case Type of
|
||||||
<<"groupchat">> -> %% mod_muc_log already does it
|
groupchat -> %% mod_muc_log already does it
|
||||||
?DEBUG("dropping groupchat: ~s", [fxml:element_to_binary(Packet)]),
|
?DEBUG("dropping groupchat: ~s", [fxml:element_to_binary(Packet)]),
|
||||||
ok;
|
ok;
|
||||||
<<"error">> -> %% we don't log errors
|
error -> %% we don't log errors
|
||||||
?DEBUG("dropping error: ~s", [fxml:element_to_binary(Packet)]),
|
?DEBUG("dropping error: ~s", [fxml:element_to_binary(Packet)]),
|
||||||
ok;
|
ok;
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -286,8 +279,15 @@ css() ->
|
||||||
".messagetext {color: black; margin: 0.2em; clear: both; display: block;}~n"++
|
".messagetext {color: black; margin: 0.2em; clear: both; display: block;}~n"++
|
||||||
"//-->~n</style>~n".
|
"//-->~n</style>~n".
|
||||||
|
|
||||||
|
depends(_Host, _Opts) ->
|
||||||
|
[].
|
||||||
|
|
||||||
|
mod_opt_type(host_config) -> econf:list(econf:any());
|
||||||
mod_opt_type(path) -> fun iolist_to_binary/1;
|
mod_opt_type(path) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(format) ->
|
mod_opt_type(format) ->
|
||||||
fun (A) when is_atom(A) -> A end;
|
fun (A) when is_atom(A) -> A end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[path, format].
|
mod_options(_Host) ->
|
||||||
|
[{host_config, []},
|
||||||
|
{path, ?DEFAULT_PATH},
|
||||||
|
{format, ?DEFAULT_FORMAT}].
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
mod_logsession - Log session connections to file
|
mod_logsession - Log session connections to file
|
||||||
|
|
||||||
|
Requirements: ejabberd 19.08 or higher
|
||||||
Homepage: http://www.ejabberd.im/mod_logsession
|
Homepage: http://www.ejabberd.im/mod_logsession
|
||||||
Author: Badlop
|
Author: Badlop
|
||||||
Requirements: ejabberd 17.01 or newer
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
|
@ -29,14 +29,11 @@
|
||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([
|
-export([start/2, stop/1, depends/2, mod_options/1, mod_opt_type/1]).
|
||||||
start/2,
|
-export([loop/3,
|
||||||
stop/1,
|
|
||||||
loop/3,
|
|
||||||
reopen_log/1,
|
reopen_log/1,
|
||||||
failed_auth/3,
|
failed_auth/3,
|
||||||
forbidden/1
|
forbidden/1]).
|
||||||
]).
|
|
||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("ejabberd_commands.hrl").
|
-include("ejabberd_commands.hrl").
|
||||||
|
@ -54,9 +51,7 @@ start(Host, Opts) ->
|
||||||
ejabberd_commands:register_commands(commands()),
|
ejabberd_commands:register_commands(commands()),
|
||||||
Filename1 = gen_mod:get_opt(
|
Filename1 = gen_mod:get_opt(
|
||||||
sessionlog,
|
sessionlog,
|
||||||
Opts,
|
Opts),
|
||||||
fun(S) -> S end,
|
|
||||||
"/tmp/ejabberd_logsession_@HOST@.log"),
|
|
||||||
Filename = replace_host(Host, Filename1),
|
Filename = replace_host(Host, Filename1),
|
||||||
File = open_file(Filename),
|
File = open_file(Filename),
|
||||||
register(get_process_name(Host), spawn(?MODULE, loop, [Filename, File, Host])),
|
register(get_process_name(Host), spawn(?MODULE, loop, [Filename, File, Host])),
|
||||||
|
@ -70,6 +65,15 @@ stop(Host) ->
|
||||||
exit(whereis(Proc), stop),
|
exit(whereis(Proc), stop),
|
||||||
{wait, Proc}.
|
{wait, Proc}.
|
||||||
|
|
||||||
|
depends(_Host, _Opts) ->
|
||||||
|
[].
|
||||||
|
|
||||||
|
mod_opt_type(sessionlog) ->
|
||||||
|
econf:string().
|
||||||
|
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[{sessionlog, "/tmp/ejabberd_logsession_@HOST@.log"}].
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% REQUEST HANDLERS
|
%%% REQUEST HANDLERS
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
|
@ -83,8 +87,8 @@ forbidden(JID) ->
|
||||||
|
|
||||||
failed_auth(State, true, _) ->
|
failed_auth(State, true, _) ->
|
||||||
State;
|
State;
|
||||||
failed_auth(#{lserver := Host, ip := IPPT} = State, false, U) ->
|
failed_auth(#{lserver := Host, ip := IPPT} = State, {false, Reason}, U) ->
|
||||||
get_process_name(Host) ! {log, {failed_auth, U, IPPT}},
|
get_process_name(Host) ! {log, {failed_auth, U, IPPT, Reason}},
|
||||||
State.
|
State.
|
||||||
|
|
||||||
commands() ->
|
commands() ->
|
||||||
|
@ -144,10 +148,10 @@ make_date(Date) ->
|
||||||
io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
|
||||||
[Y, Mo, D, H, Mi, S]).
|
[Y, Mo, D, H, Mi, S]).
|
||||||
|
|
||||||
make_message(Host, {failed_auth, Username, {IPTuple, IPPort}}) ->
|
make_message(Host, {failed_auth, Username, {IPTuple, IPPort}, Reason}) ->
|
||||||
IPString = inet_parse:ntoa(IPTuple),
|
IPString = inet_parse:ntoa(IPTuple),
|
||||||
io_lib:format("Failed authentication for ~s@~s from ~s port ~p",
|
io_lib:format("Failed authentication for ~s@~s from ~s port ~p: ~s",
|
||||||
[Username, Host, IPString, IPPort]);
|
[Username, Host, IPString, IPPort, Reason]);
|
||||||
make_message(_Host, {forbidden, JID}) ->
|
make_message(_Host, {forbidden, JID}) ->
|
||||||
io_lib:format("Forbidden session for ~s",
|
io_lib:format("Forbidden session for ~s",
|
||||||
[jlib:jid_to_string(JID)]).
|
[jlib:jid_to_string(JID)]).
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
Homepage: http://www.ejabberd.im/mod_logxml
|
Homepage: http://www.ejabberd.im/mod_logxml
|
||||||
Author: Badlop
|
Author: Badlop
|
||||||
Module for ejabberd git master
|
Requires: ejabberd 19.08 or higher
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
@ -38,15 +38,15 @@ show_ip:
|
||||||
Default value: false
|
Default value: false
|
||||||
rotate_days:
|
rotate_days:
|
||||||
Rotate logs every X days
|
Rotate logs every X days
|
||||||
Put 'no' to disable this limit.
|
Put 0 to disable this limit.
|
||||||
Default value: 1
|
Default value: 1
|
||||||
rotate_megs:
|
rotate_megs:
|
||||||
Rotate when the logfile size is higher than this, in megabytes.
|
Rotate when the logfile size is higher than this, in megabytes.
|
||||||
Put 'no' to disable this limit.
|
Put 0 to disable this limit.
|
||||||
Default value: 10
|
Default value: 10
|
||||||
rotate_kpackets:
|
rotate_kpackets:
|
||||||
Rotate every *1000 XMPP packets logged
|
Rotate every *1000 XMPP packets logged
|
||||||
Put 'no' to disable this limit.
|
Put 0 to disable this limit.
|
||||||
Default value: 10
|
Default value: 10
|
||||||
check_rotate_kpackets:
|
check_rotate_kpackets:
|
||||||
Check rotation every *1000 packets
|
Check rotation every *1000 packets
|
||||||
|
@ -72,7 +72,7 @@ modules:
|
||||||
show_ip: false
|
show_ip: false
|
||||||
rotate_days: 1
|
rotate_days: 1
|
||||||
rotate_megs: 100
|
rotate_megs: 100
|
||||||
rotate_kpackets: no
|
rotate_kpackets: 0
|
||||||
check_rotate_kpackets: 1
|
check_rotate_kpackets: 1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,5 +12,5 @@ modules:
|
||||||
show_ip: false
|
show_ip: false
|
||||||
rotate_days: 1
|
rotate_days: 1
|
||||||
rotate_megs: 100
|
rotate_megs: 100
|
||||||
rotate_kpackets: no
|
rotate_kpackets: 0
|
||||||
check_rotate_kpackets: 1
|
check_rotate_kpackets: 1
|
||||||
|
|
|
@ -26,13 +26,16 @@
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
Logdir = gen_mod:get_opt(logdir, Opts),
|
Logdir = gen_mod:get_opt(logdir, Opts),
|
||||||
|
|
||||||
Rd = gen_mod:get_opt(rotate_days, Opts),
|
Rd = case gen_mod:get_opt(rotate_days, Opts) of
|
||||||
|
0 -> no;
|
||||||
|
Rd1 -> Rd1
|
||||||
|
end,
|
||||||
Rf = case gen_mod:get_opt(rotate_megs, Opts) of
|
Rf = case gen_mod:get_opt(rotate_megs, Opts) of
|
||||||
no -> no;
|
0 -> no;
|
||||||
Rf1 -> Rf1*1024*1024
|
Rf1 -> Rf1*1024*1024
|
||||||
end,
|
end,
|
||||||
Rp = case gen_mod:get_opt(rotate_kpackets, Opts) of
|
Rp = case gen_mod:get_opt(rotate_kpackets, Opts) of
|
||||||
no -> no;
|
0 -> no;
|
||||||
Rp1 -> Rp1*1000
|
Rp1 -> Rp1*1000
|
||||||
end,
|
end,
|
||||||
RotateO = {Rd, Rf, Rp},
|
RotateO = {Rd, Rf, Rp},
|
||||||
|
@ -111,7 +114,7 @@ filter(FilterO, E) ->
|
||||||
FilterO,
|
FilterO,
|
||||||
{Orientation, From, To, Packet} = E,
|
{Orientation, From, To, Packet} = E,
|
||||||
Stanza = element(1, Packet),
|
Stanza = element(1, Packet),
|
||||||
Hosts_all = ejabberd_config:get_global_option(hosts, fun(A) -> A end),
|
Hosts_all = ejabberd_config:get_option(hosts),
|
||||||
{Host_local, Host_remote} = case Orientation of
|
{Host_local, Host_remote} = case Orientation of
|
||||||
send -> {From#jid.lserver, To#jid.lserver};
|
send -> {From#jid.lserver, To#jid.lserver};
|
||||||
recv -> {To#jid.lserver, From#jid.lserver}
|
recv -> {To#jid.lserver, From#jid.lserver}
|
||||||
|
@ -267,29 +270,23 @@ calc_div(_A, _B) ->
|
||||||
0.5. %% This ensures that no rotation is performed
|
0.5. %% This ensures that no rotation is performed
|
||||||
|
|
||||||
mod_opt_type(stanza) ->
|
mod_opt_type(stanza) ->
|
||||||
fun (L) when is_list(L) -> [] = L -- [iq, message, presence, other], L end;
|
econf:list(econf:enum([iq, message, presence, other]));
|
||||||
mod_opt_type(direction) ->
|
mod_opt_type(direction) ->
|
||||||
fun (L) when is_list(L) -> [] = L -- [internal, vhosts, external], L end;
|
econf:list(econf:enum([internal, vhosts, external]));
|
||||||
mod_opt_type(orientation) ->
|
mod_opt_type(orientation) ->
|
||||||
fun (L) when is_list(L) -> [] = L -- [send, recv], L end;
|
econf:list(econf:enum([send, recv]));
|
||||||
mod_opt_type(logdir) ->
|
mod_opt_type(logdir) ->
|
||||||
fun iolist_to_binary/1;
|
econf:directory();
|
||||||
mod_opt_type(show_ip) ->
|
mod_opt_type(show_ip) ->
|
||||||
fun (A) when is_boolean(A) -> A end;
|
econf:bool();
|
||||||
mod_opt_type(rotate_days) ->
|
mod_opt_type(rotate_days) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I;
|
econf:non_neg_int();
|
||||||
(no) -> no
|
|
||||||
end;
|
|
||||||
mod_opt_type(rotate_megs) ->
|
mod_opt_type(rotate_megs) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I;
|
econf:non_neg_int();
|
||||||
(no) -> no
|
|
||||||
end;
|
|
||||||
mod_opt_type(rotate_kpackets) ->
|
mod_opt_type(rotate_kpackets) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I;
|
econf:non_neg_int();
|
||||||
(no) -> no
|
|
||||||
end;
|
|
||||||
mod_opt_type(check_rotate_kpackets) ->
|
mod_opt_type(check_rotate_kpackets) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I end.
|
econf:non_neg_int().
|
||||||
|
|
||||||
mod_options(_Host) ->
|
mod_options(_Host) ->
|
||||||
[{stanza, [iq, message, presence, other]},
|
[{stanza, [iq, message, presence, other]},
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
mod_muc_log_http - Serve MUC logs on the web
|
mod_muc_log_http - Serve MUC logs on the web
|
||||||
|
|
||||||
|
Requires: ejabberd 19.08 or higher
|
||||||
Homepage: http://ejabberd.im/mod_muc_log_http
|
Homepage: http://ejabberd.im/mod_muc_log_http
|
||||||
Author: Badlop
|
Author: Badlop
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,9 @@
|
||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([
|
-export([start/2, stop/1, depends/2, mod_options/1]).
|
||||||
start/2,
|
|
||||||
stop/1,
|
-export([process/2]).
|
||||||
process/2
|
|
||||||
]).
|
|
||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("ejabberd_http.hrl").
|
-include("ejabberd_http.hrl").
|
||||||
|
@ -38,7 +36,7 @@ process(LocalPath, Request) ->
|
||||||
serve(LocalPath, Request).
|
serve(LocalPath, Request).
|
||||||
|
|
||||||
serve(LocalPathBin, #request{host = Host} = Request) ->
|
serve(LocalPathBin, #request{host = Host} = Request) ->
|
||||||
DocRoot = binary_to_list(gen_mod:get_module_opt(Host, mod_muc_log, outdir, <<"www/muc">>)),
|
DocRoot = binary_to_list(gen_mod:get_module_opt(Host, mod_muc_log, outdir)),
|
||||||
LocalPath = [binary_to_list(LPB) || LPB <- LocalPathBin],
|
LocalPath = [binary_to_list(LPB) || LPB <- LocalPathBin],
|
||||||
FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
|
FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
|
||||||
case file:read_file(FileName) of
|
case file:read_file(FileName) of
|
||||||
|
@ -230,3 +228,9 @@ start(_Host, _Opts) ->
|
||||||
|
|
||||||
stop(_Host) ->
|
stop(_Host) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
depends(_Host, _Opts) ->
|
||||||
|
[{mod_muc_log, hard}].
|
||||||
|
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[].
|
||||||
|
|
|
@ -60,9 +60,9 @@ filterMessageText2(Lang, MessageText) ->
|
||||||
string:join(filterWords(MessageTerms), " ").
|
string:join(filterWords(MessageTerms), " ").
|
||||||
|
|
||||||
start(_Host, Opts) ->
|
start(_Host, Opts) ->
|
||||||
Blacklists = gen_mod:get_opt(blacklists, Opts, fun(A) -> A end, []),
|
Blacklists = gen_mod:get_opt(blacklists, Opts),
|
||||||
lists:map(fun bloom_gen_server:start/1, Blacklists),
|
lists:map(fun bloom_gen_server:start/1, Blacklists),
|
||||||
CharMaps = gen_mod:get_opt(charmaps, Opts, fun(A) -> A end, []),
|
CharMaps = gen_mod:get_opt(charmaps, Opts),
|
||||||
lists:map(fun normalize_leet_gen_server:start/1, CharMaps),
|
lists:map(fun normalize_leet_gen_server:start/1, CharMaps),
|
||||||
ejabberd_hooks:add(filter_packet, global, ?MODULE, on_filter_packet, 0),
|
ejabberd_hooks:add(filter_packet, global, ?MODULE, on_filter_packet, 0),
|
||||||
ok.
|
ok.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
mod_rest - HTTP interface to POST stanzas into ejabberd
|
mod_rest - HTTP interface to POST stanzas into ejabberd
|
||||||
|
|
||||||
|
Requires: ejabberd 19.08 or higher
|
||||||
Author: Nolan Eakins <sneakin@semanticgap.com>
|
Author: Nolan Eakins <sneakin@semanticgap.com>
|
||||||
Copyright (C) 2008 Nolan Eakins
|
Copyright (C) 2008 Nolan Eakins
|
||||||
|
|
||||||
|
@ -40,8 +41,6 @@ With that configuration, you can send HTTP POST requests to the URL:
|
||||||
Configurable options:
|
Configurable options:
|
||||||
|
|
||||||
allowed_ips: IP addresses that can use the rest service.
|
allowed_ips: IP addresses that can use the rest service.
|
||||||
Allowed values: 'all' or a list of Erlang strings.
|
|
||||||
Default value: all
|
|
||||||
Notice that the IP address is checked after the connection is established.
|
Notice that the IP address is checked after the connection is established.
|
||||||
If you want to restrict the IP address that listens connections, and
|
If you want to restrict the IP address that listens connections, and
|
||||||
only allow a certain IP to be able to connect to the port, then the
|
only allow a certain IP to be able to connect to the port, then the
|
||||||
|
@ -49,18 +48,13 @@ Configurable options:
|
||||||
listening IP address in the ejabberd listeners (see the ejabberd Guide).
|
listening IP address in the ejabberd listeners (see the ejabberd Guide).
|
||||||
|
|
||||||
allowed_destinations: Allowed destination Jabber ID addresses in the stanza.
|
allowed_destinations: Allowed destination Jabber ID addresses in the stanza.
|
||||||
Allowed values: 'all' or a list of strings.
|
|
||||||
Default value: all
|
|
||||||
|
|
||||||
allowed_stanza_types: Allowed stanza types of the posted stanza.
|
allowed_stanza_types: Allowed stanza types of the posted stanza.
|
||||||
Allowed values: 'all' or a list of strings.
|
|
||||||
Default value: all
|
|
||||||
|
|
||||||
access_commands: Access restrictions to execute ejabberd commands.
|
access_commands: Access restrictions to execute ejabberd commands.
|
||||||
This option is similar to the option ejabberdctl_access_commands that
|
This option is similar to the option ejabberdctl_access_commands that
|
||||||
is documented in the ejabberd Guide.
|
is documented in the ejabberd Guide.
|
||||||
There is more information about AccessCommands in the ejabberd Guide.
|
There is more information about AccessCommands in the ejabberd Guide.
|
||||||
Default value: []
|
|
||||||
|
|
||||||
Complex example configuration:
|
Complex example configuration:
|
||||||
|
|
||||||
|
@ -88,7 +82,7 @@ modules:
|
||||||
- "presence"
|
- "presence"
|
||||||
- "iq"
|
- "iq"
|
||||||
access_commands:
|
access_commands:
|
||||||
restaccess:
|
- restaccess:
|
||||||
- registered_users
|
- registered_users
|
||||||
- connected_users
|
- connected_users
|
||||||
|
|
||||||
|
|
|
@ -70,19 +70,19 @@ maybe_post_request(<<$<,_/binary>> = Data, Host, ClientIp) ->
|
||||||
Stanza = {xmlel, _, _, _} = fxml_stream:parse_element(Data),
|
Stanza = {xmlel, _, _, _} = fxml_stream:parse_element(Data),
|
||||||
Pkt = xmpp:decode(Stanza),
|
Pkt = xmpp:decode(Stanza),
|
||||||
allowed = check_stanza(Pkt, Host),
|
allowed = check_stanza(Pkt, Host),
|
||||||
?INFO_MSG("Got valid request with IP ~p:~n~p",
|
?DEBUG("Got valid request with IP ~p:~n~p",
|
||||||
[ClientIp,
|
[ClientIp,
|
||||||
Pkt]),
|
Pkt]),
|
||||||
post_request(Pkt)
|
post_request(Pkt)
|
||||||
catch
|
catch
|
||||||
error:{badmatch, _} = Error ->
|
error:{badmatch, _} = Error ->
|
||||||
?DEBUG("Error when processing REST request: ~nData: ~p~nError: ~p", [Data, Error]),
|
?INFO_MSG("Error when processing REST request: ~nData: ~p~nError: ~p", [Data, Error]),
|
||||||
{406, [], "Error: REST request is rejected by service."};
|
{406, [], "Error: REST request is rejected by service."};
|
||||||
error:{Reason, _} = Error ->
|
error:{Reason, _} = Error ->
|
||||||
?DEBUG("Error when processing REST request: ~nData: ~p~nError: ~p", [Data, Error]),
|
?INFO_MSG("Error when processing REST request: ~nData: ~p~nError: ~p", [Data, Error]),
|
||||||
{500, [], "Error: " ++ atom_to_list(Reason)};
|
{500, [], "Error: " ++ atom_to_list(Reason)};
|
||||||
Error ->
|
Error ->
|
||||||
?DEBUG("Error when processing REST request: ~nData: ~p~nError: ~p", [Data, Error]),
|
?INFO_MSG("Error when processing REST request: ~nData: ~p~nError: ~p", [Data, Error]),
|
||||||
{500, [], "Error"}
|
{500, [], "Error"}
|
||||||
end;
|
end;
|
||||||
maybe_post_request(Data, Host, _ClientIp) ->
|
maybe_post_request(Data, Host, _ClientIp) ->
|
||||||
|
@ -107,39 +107,38 @@ ensure_auth_is_provided(Args) ->
|
||||||
["--auth", "", "", "" | Args].
|
["--auth", "", "", "" | Args].
|
||||||
|
|
||||||
%% This function throws an error if the module is not started in that VHost.
|
%% This function throws an error if the module is not started in that VHost.
|
||||||
try_get_option(Host, OptionName, DefaultValue) ->
|
try_get_option(Host, OptionName) ->
|
||||||
case gen_mod:is_loaded(Host, ?MODULE) of
|
case gen_mod:is_loaded(Host, ?MODULE) of
|
||||||
true -> ok;
|
true -> ok;
|
||||||
_ -> throw({module_must_be_started_in_vhost, ?MODULE, Host})
|
_ -> throw({module_must_be_started_in_vhost, ?MODULE, Host})
|
||||||
end,
|
end,
|
||||||
gen_mod:get_module_opt(Host, ?MODULE, OptionName, fun(I) -> I end, DefaultValue).
|
gen_mod:get_module_opt(Host, ?MODULE, OptionName).
|
||||||
|
|
||||||
get_option_access(Host) ->
|
get_option_access(Host) ->
|
||||||
try_get_option(Host, access_commands, []).
|
try_get_option(Host, access_commands).
|
||||||
|
|
||||||
%% This function crashes if the stanza does not satisfy configured restrictions
|
%% This function crashes if the stanza does not satisfy configured restrictions
|
||||||
check_stanza(Pkt, Host) ->
|
check_stanza(Pkt, Host) ->
|
||||||
To = xmpp:get_to(Pkt),
|
To = xmpp:get_to(Pkt),
|
||||||
check_member_option(Host, jid:encode(To), allowed_destinations),
|
check_member_option(Host, To, allowed_destinations),
|
||||||
%%+++ {xmlel, StanzaType, _Attrs, _Kids} = Stanza,
|
Name = xmpp:get_name(Pkt),
|
||||||
%%+++ check_member_option(Host, StanzaType, allowed_stanza_types),
|
check_member_option(Host, Name, allowed_stanza_types),
|
||||||
allowed.
|
allowed.
|
||||||
|
|
||||||
check_member_option(Host, ClientIp, allowed_ips) ->
|
check_member_option(Host, ClientIp, allowed_ips) ->
|
||||||
true = case try_get_option(Host, allowed_ips, all) of
|
true = case try_get_option(Host, allowed_ips) of
|
||||||
all -> true;
|
[] -> true;
|
||||||
AllowedValues -> ip_matches(ClientIp, AllowedValues)
|
AllowedValues -> ip_matches(ClientIp, AllowedValues)
|
||||||
end;
|
end;
|
||||||
check_member_option(Host, Element, Option) ->
|
check_member_option(Host, Element, Option) ->
|
||||||
true = case try_get_option(Host, Option, all) of
|
true = case try_get_option(Host, Option) of
|
||||||
all -> true;
|
[] -> true;
|
||||||
AllowedValues -> lists:member(Element, AllowedValues)
|
AllowedValues -> lists:member(Element, AllowedValues)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
ip_matches(ClientIp, AllowedValues) ->
|
ip_matches(ClientIp, AllowedValues) ->
|
||||||
lists:any(fun(El) ->
|
lists:any(fun({Net, Mask}) ->
|
||||||
{ok, Net, Mask} = acl:parse_ip_netmask(El),
|
acl:match_acl(useless_host, {ip,{Net,Mask}}, #{ip => {ClientIp,useless_port}})
|
||||||
acl:acl_rule_matches({ip,{Net,Mask}}, #{ip => {ClientIp,port}}, host)
|
|
||||||
end,
|
end,
|
||||||
AllowedValues).
|
AllowedValues).
|
||||||
|
|
||||||
|
@ -178,16 +177,16 @@ splitend([92, 34, 32 | Line], Res) -> {Line, Res};
|
||||||
splitend([Char | Line], Res) -> splitend(Line, [Char | Res]).
|
splitend([Char | Line], Res) -> splitend(Line, [Char | Res]).
|
||||||
|
|
||||||
mod_opt_type(allowed_ips) ->
|
mod_opt_type(allowed_ips) ->
|
||||||
fun (all) -> all; (A) when is_list(A) -> A end;
|
econf:list(econf:ip_mask());
|
||||||
mod_opt_type(allowed_destinations) ->
|
mod_opt_type(allowed_destinations) ->
|
||||||
fun (all) -> all; (A) when is_list(A) -> A end;
|
econf:list(econf:jid());
|
||||||
mod_opt_type(allowed_stanza_types) ->
|
mod_opt_type(allowed_stanza_types) ->
|
||||||
fun (all) -> all; (A) when is_list(A) -> A end;
|
econf:list(econf:enum([<<"iq">>, <<"message">>, <<"presence">>]));
|
||||||
mod_opt_type(access_commands) ->
|
mod_opt_type(access_commands) ->
|
||||||
fun (A) when is_list(A) -> A end.
|
fun (A) when is_list(A) -> A end.
|
||||||
|
|
||||||
mod_options(_Host) ->
|
mod_options(_Host) ->
|
||||||
[{allowed_ips, all},
|
[{allowed_ips, []},
|
||||||
{allowed_destinations, all},
|
{allowed_destinations, []},
|
||||||
{allowed_stanza_types, all},
|
{allowed_stanza_types, []},
|
||||||
{access_commands, []}].
|
{access_commands, []}].
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
case whereis(?PROCNAME) of
|
case whereis(?PROCNAME) of
|
||||||
undefined ->
|
undefined ->
|
||||||
Filename = gen_mod:get_opt(filename, Opts, ?DEFAULT_FILENAME),
|
Filename = gen_mod:get_opt(filename, Opts),
|
||||||
case filelib:ensure_dir(Filename) of
|
case filelib:ensure_dir(Filename) of
|
||||||
ok ->
|
ok ->
|
||||||
register(?PROCNAME,
|
register(?PROCNAME,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
mod_shcommands - Execute shell commands
|
mod_shcommands - Execute shell commands
|
||||||
|
|
||||||
|
Requires: ejabberd 19.08 or higher
|
||||||
Author: Badlop
|
Author: Badlop
|
||||||
http://ejabberd.im/mod_shcommands
|
http://ejabberd.im/mod_shcommands
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,13 @@
|
||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([web_menu_node/3, web_page_node/5,
|
-export([start/2, stop/1, depends/2, mod_options/1]).
|
||||||
start/2, stop/1]).
|
-export([web_menu_node/3, web_page_node/5]).
|
||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("ejabberd_http.hrl").
|
-include("ejabberd_http.hrl").
|
||||||
-include("ejabberd_web_admin.hrl").
|
-include("ejabberd_web_admin.hrl").
|
||||||
|
-include("translate.hrl").
|
||||||
|
|
||||||
%%-------------------
|
%%-------------------
|
||||||
%% gen_mod functions
|
%% gen_mod functions
|
||||||
|
@ -32,19 +33,25 @@ stop(_Host) ->
|
||||||
ejabberd_hooks:delete(webadmin_page_node, ?MODULE, web_page_node, 50),
|
ejabberd_hooks:delete(webadmin_page_node, ?MODULE, web_page_node, 50),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
depends(_Host, _Opts) ->
|
||||||
|
[].
|
||||||
|
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[].
|
||||||
|
|
||||||
%%-------------------
|
%%-------------------
|
||||||
%% Web Admin Menu
|
%% Web Admin Menu
|
||||||
%%-------------------
|
%%-------------------
|
||||||
|
|
||||||
web_menu_node(Acc, _Node, Lang) ->
|
web_menu_node(Acc, _Node, Lang) ->
|
||||||
Acc ++ [{<<"shcommands">>, ?T(<<"Shell Commands">>)}].
|
Acc ++ [{<<"shcommands">>, translate:translate(Lang, ?T("Shell Commands"))}].
|
||||||
|
|
||||||
%%-------------------
|
%%-------------------
|
||||||
%% Web Admin Page
|
%% Web Admin Page
|
||||||
%%-------------------
|
%%-------------------
|
||||||
|
|
||||||
web_page_node(_, Node, [<<"shcommands">>], Query, Lang) ->
|
web_page_node(_, Node, [<<"shcommands">>], Query, Lang) ->
|
||||||
Res = [?XC(<<"h1">>, <<"Shell Commands">>) | get_content(Node, Query, Lang)],
|
Res = [?XC(<<"h1">>, translate:translate(Lang, ?T("Shell Commands"))) | get_content(Node, Query, Lang)],
|
||||||
{stop, Res};
|
{stop, Res};
|
||||||
web_page_node(Acc, _, _, _, _) -> Acc.
|
web_page_node(Acc, _, _, _, _) -> Acc.
|
||||||
|
|
||||||
|
@ -53,14 +60,15 @@ web_page_node(Acc, _, _, _, _) -> Acc.
|
||||||
%%-------------------
|
%%-------------------
|
||||||
|
|
||||||
get_content(Node, Query, Lang) ->
|
get_content(Node, Query, Lang) ->
|
||||||
Instruct = ?T("Type a command in a textbox and click Execute."),
|
Instruct = translate:translate(Lang, ?T("Type a command in a textbox and click Execute.")),
|
||||||
{{CommandCtl, CommandErl, CommandShell}, Res} = case catch parse_and_execute(Query, Node) of
|
{{CommandCtl, CommandErl, CommandShell}, Res} = case catch parse_and_execute(Query, Node) of
|
||||||
{'EXIT', _} -> {{"", "", ""}, Instruct};
|
{'EXIT', _} -> {{"", "", ""}, Instruct};
|
||||||
Result_tuple -> Result_tuple
|
Result_tuple -> Result_tuple
|
||||||
end,
|
end,
|
||||||
TitleHTML = [
|
TitleHTML = [
|
||||||
?XC(<<"p">>, ?T(<<"Type a command in a textbox and click Execute. Use only commands which immediately return a result.">>)),
|
?XC(<<"p">>, translate:translate(Lang, ?T("Type a command in a textbox and click Execute."))),
|
||||||
?XC(<<"p">>, ?T(<<"WARNING: Use this only if you know what you are doing.">>))
|
?XC(<<"p">>, translate:translate(Lang, ?T("Use only commands which immediately return a result."))),
|
||||||
|
?XC(<<"p">>, translate:translate(Lang, ?T("WARNING: Use this only if you know what you are doing.")))
|
||||||
],
|
],
|
||||||
CommandHTML =
|
CommandHTML =
|
||||||
[?XAE(<<"form">>, [{<<"method">>, <<"post">>}],
|
[?XAE(<<"form">>, [{<<"method">>, <<"post">>}],
|
||||||
|
@ -70,21 +78,21 @@ get_content(Node, Query, Lang) ->
|
||||||
[?X(<<"td">>),
|
[?X(<<"td">>),
|
||||||
?XCT(<<"td">>, <<"ejabberd_ctl">>),
|
?XCT(<<"td">>, <<"ejabberd_ctl">>),
|
||||||
?XE(<<"td">>, [?INPUTS(<<"text">>, <<"commandctl">>, list_to_binary(CommandCtl), <<"70">>),
|
?XE(<<"td">>, [?INPUTS(<<"text">>, <<"commandctl">>, list_to_binary(CommandCtl), <<"70">>),
|
||||||
?INPUTT(<<"submit">>, <<"executectl">>, <<"Execute">>)])
|
?INPUTT(<<"submit">>, <<"executectl">>, translate:translate(Lang, ?T("Execute")))])
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
?XE(<<"tr">>,
|
?XE(<<"tr">>,
|
||||||
[?X(<<"td">>),
|
[?X(<<"td">>),
|
||||||
?XCT(<<"td">>, <<"erlang shell">>),
|
?XCT(<<"td">>, <<"erlang shell">>),
|
||||||
?XE(<<"td">>, [?INPUTS(<<"text">>, <<"commanderl">>, list_to_binary(CommandErl), <<"70">>),
|
?XE(<<"td">>, [?INPUTS(<<"text">>, <<"commanderl">>, list_to_binary(CommandErl), <<"70">>),
|
||||||
?INPUTT(<<"submit">>, <<"executeerl">>, <<"Execute">>)])
|
?INPUTT(<<"submit">>, <<"executeerl">>, translate:translate(Lang, ?T("Execute")))])
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
?XE(<<"tr">>,
|
?XE(<<"tr">>,
|
||||||
[?X(<<"td">>),
|
[?X(<<"td">>),
|
||||||
?XCT(<<"td">>, <<"system shell">>),
|
?XCT(<<"td">>, <<"system shell">>),
|
||||||
?XE(<<"td">>, [?INPUTS(<<"text">>, <<"commandshe">>, list_to_binary(CommandShell), <<"70">>),
|
?XE(<<"td">>, [?INPUTS(<<"text">>, <<"commandshe">>, list_to_binary(CommandShell), <<"70">>),
|
||||||
?INPUTT(<<"submit">>, <<"executeshe">>, <<"Execute">>)])
|
?INPUTT(<<"submit">>, <<"executeshe">>, translate:translate(Lang, ?T("Execute")))])
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
@ -93,7 +101,7 @@ get_content(Node, Query, Lang) ->
|
||||||
ResHTML =
|
ResHTML =
|
||||||
[?XAC(<<"textarea">>, [{<<"wrap">>, <<"off">>}, {<<"style">>, <<"font-family:monospace;">>},
|
[?XAC(<<"textarea">>, [{<<"wrap">>, <<"off">>}, {<<"style">>, <<"font-family:monospace;">>},
|
||||||
{<<"name">>, <<"result">>}, {<<"rows">>, <<"30">>}, {<<"cols">>, <<"80">>}],
|
{<<"name">>, <<"result">>}, {<<"rows">>, <<"30">>}, {<<"cols">>, <<"80">>}],
|
||||||
list_to_binary(Res))
|
Res)
|
||||||
],
|
],
|
||||||
TitleHTML ++ CommandHTML ++ ResHTML.
|
TitleHTML ++ CommandHTML ++ ResHTML.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
mod_statsdx - Calculates and gathers statistics actively
|
mod_statsdx - Calculates and gathers statistics actively
|
||||||
|
|
||||||
|
Requires: ejabberd 19.08 or higher
|
||||||
Homepage: http://www.ejabberd.im/mod_statsdx
|
Homepage: http://www.ejabberd.im/mod_statsdx
|
||||||
Author: Badlop
|
Author: Badlop
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, loop/5, stop/1]).
|
|
||||||
|
-export([start/2, stop/1, depends/2, mod_opt_type/1, mod_options/1]).
|
||||||
|
-export([loop/5]).
|
||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("mod_roster.hrl").
|
-include("mod_roster.hrl").
|
||||||
|
@ -26,19 +28,17 @@
|
||||||
start(_Host, Opts) ->
|
start(_Host, Opts) ->
|
||||||
case whereis(?PROCNAME) of
|
case whereis(?PROCNAME) of
|
||||||
undefined ->
|
undefined ->
|
||||||
Interval = gen_mod:get_opt(interval, Opts, fun(O) -> O end, 5),
|
Interval = gen_mod:get_opt(interval, Opts),
|
||||||
I = Interval*60*1000,
|
I = Interval*60*1000,
|
||||||
%I = 9000, %+++
|
%I = 9000, %+++
|
||||||
|
|
||||||
Type = gen_mod:get_opt(type, Opts, fun(O) -> O end, html),
|
Type = gen_mod:get_opt(type, Opts),
|
||||||
|
|
||||||
Split = gen_mod:get_opt(split, Opts, fun(O) -> O end, false),
|
Split = gen_mod:get_opt(split, Opts),
|
||||||
|
|
||||||
BaseFilename = binary_to_list(gen_mod:get_opt(basefilename, Opts, fun(O) -> O end, "/tmp/ejasta")),
|
BaseFilename = gen_mod:get_opt(basefilename, Opts),
|
||||||
|
|
||||||
Hosts_all = ejabberd_config:get_global_option(hosts, fun(O) -> O end),
|
Hosts = gen_mod:get_opt(hosts, Opts),
|
||||||
Hosts1 = gen_mod:get_opt(hosts, Opts, fun(O) -> O end, Hosts_all),
|
|
||||||
Hosts = [binary_to_list(H) || H <- Hosts1],
|
|
||||||
|
|
||||||
register(?PROCNAME, spawn(?MODULE, loop, [I, Hosts, BaseFilename, Type, Split]));
|
register(?PROCNAME, spawn(?MODULE, loop, [I, Hosts, BaseFilename, Type, Split]));
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -61,6 +61,26 @@ stop(_Host) ->
|
||||||
?PROCNAME ! stop
|
?PROCNAME ! stop
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
depends(_Host, _Opts) ->
|
||||||
|
[{mod_statsdx, hard}].
|
||||||
|
|
||||||
|
mod_opt_type(interval) ->
|
||||||
|
econf:pos_int();
|
||||||
|
mod_opt_type(type) ->
|
||||||
|
econf:enum([html, txt, dat]);
|
||||||
|
mod_opt_type(split) ->
|
||||||
|
econf:bool();
|
||||||
|
mod_opt_type(basefilename) ->
|
||||||
|
econf:string();
|
||||||
|
mod_opt_type(hosts) ->
|
||||||
|
econf:list(econf:domain()).
|
||||||
|
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[{interval, 5},
|
||||||
|
{type, html},
|
||||||
|
{split, false},
|
||||||
|
{basefilename, "/tmp/ejasta"},
|
||||||
|
{hosts, ejabberd_config:get_option(hosts)}].
|
||||||
|
|
||||||
%% -------------------
|
%% -------------------
|
||||||
%% write_stat*
|
%% write_stat*
|
||||||
|
@ -96,13 +116,18 @@ write_statsfiles(true, I, Hs, O, T) ->
|
||||||
Hs).
|
Hs).
|
||||||
|
|
||||||
write_statsfile(I, Class, Name, O, T) ->
|
write_statsfile(I, Class, Name, O, T) ->
|
||||||
Fn = filename:flatten([O, "-", Class, "-", Name, ".", T]),
|
Fn = filename:flatten([O, "-", Class, "-", to_string(Name), ".", T]),
|
||||||
{ok, F} = file:open(Fn, [write]),
|
{ok, F} = file:open(Fn, [write]),
|
||||||
fwini(F, T),
|
fwini(F, T),
|
||||||
write_stats(I, Class, Name, F, T),
|
write_stats(I, Class, Name, F, T),
|
||||||
fwend(F, T),
|
fwend(F, T),
|
||||||
file:close(F).
|
file:close(F).
|
||||||
|
|
||||||
|
to_string(B) when is_binary(B) ->
|
||||||
|
binary_to_list(B);
|
||||||
|
to_string(S) ->
|
||||||
|
S.
|
||||||
|
|
||||||
write_stats(I, server, _Name, F, T) ->
|
write_stats(I, server, _Name, F, T) ->
|
||||||
fwh(F, "Server statistics", 1, T),
|
fwh(F, "Server statistics", 1, T),
|
||||||
fwbl1(F, T),
|
fwbl1(F, T),
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, loop/1, stop/1, mod_opt_type/1, get_statistic/2,
|
-export([start/2, stop/1, depends/2, mod_opt_type/1, mod_options/1]).
|
||||||
|
-export([loop/1, get_statistic/2,
|
||||||
received_response/3,
|
received_response/3,
|
||||||
%% Commands
|
%% Commands
|
||||||
getstatsdx/1, getstatsdx/2,
|
getstatsdx/1, getstatsdx/2,
|
||||||
|
@ -34,22 +35,21 @@
|
||||||
-include("mod_roster.hrl").
|
-include("mod_roster.hrl").
|
||||||
-include("ejabberd_http.hrl").
|
-include("ejabberd_http.hrl").
|
||||||
-include("ejabberd_web_admin.hrl").
|
-include("ejabberd_web_admin.hrl").
|
||||||
|
-include("translate.hrl").
|
||||||
|
|
||||||
-define(XCTB(Name, Text), ?XCT(list_to_binary(Name), list_to_binary(Text))).
|
-define(XCTB(Name, Text), ?XCT(list_to_binary(Name), list_to_binary(Text))).
|
||||||
|
|
||||||
-define(PROCNAME, ejabberd_mod_statsdx).
|
-define(PROCNAME, ejabberd_mod_statsdx).
|
||||||
|
|
||||||
%% Copied from ejabberd_s2s.erl Used in function get_s2sconnections/1
|
%% Copied from ejabberd_s2s.erl Used in function get_s2sconnections/1
|
||||||
-record(s2s, {fromto, pid, key}).
|
-record(s2s, {fromto :: {binary(), binary()},
|
||||||
|
pid :: pid()}).
|
||||||
|
|
||||||
%%%==================================
|
%%%==================================
|
||||||
%%%% Module control
|
%%%% Module control
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
Hooks = gen_mod:get_opt(hooks, Opts,
|
Hooks = gen_mod:get_opt(hooks, Opts),
|
||||||
fun(O) when is_boolean(O) -> O;
|
|
||||||
(traffic) -> traffic
|
|
||||||
end, false),
|
|
||||||
%% Default value for the counters
|
%% Default value for the counters
|
||||||
CD = case Hooks of
|
CD = case Hooks of
|
||||||
true -> 0;
|
true -> 0;
|
||||||
|
@ -79,8 +79,17 @@ stop(Host) ->
|
||||||
_ -> ?PROCNAME ! {stop, Host}
|
_ -> ?PROCNAME ! {stop, Host}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
mod_opt_type(hooks) -> fun (B) when is_boolean(B) or (B==traffic) -> B end;
|
depends(_Host, _Opts) ->
|
||||||
mod_opt_type(_) -> [hooks].
|
[].
|
||||||
|
|
||||||
|
mod_opt_type(hooks) ->
|
||||||
|
econf:enum([false, true, traffic]);
|
||||||
|
mod_opt_type(sessionlog) ->
|
||||||
|
econf:string().
|
||||||
|
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[{hooks, false},
|
||||||
|
{sessionlog, "/tmp/ejabberd_logsession_@HOST@.log"}].
|
||||||
|
|
||||||
%%%==================================
|
%%%==================================
|
||||||
%%%% Stats Server
|
%%%% Stats Server
|
||||||
|
@ -764,7 +773,7 @@ user_logout(User, Host, Resource, _Status) ->
|
||||||
ets:update_counter(TableServer, {user_logout, server}, 1),
|
ets:update_counter(TableServer, {user_logout, server}, 1),
|
||||||
ets:update_counter(TableHost, {user_logout, Host}, 1),
|
ets:update_counter(TableHost, {user_logout, Host}, 1),
|
||||||
|
|
||||||
JID = jlib:make_jid(User, Host, Resource),
|
JID = jid:make(User, Host, Resource),
|
||||||
case ets:lookup(TableHost, {session, JID}) of
|
case ets:lookup(TableHost, {session, JID}) of
|
||||||
[{_, Client_id, OS_id, Lang, ConnType, _Client, _Version, _OS}] ->
|
[{_, Client_id, OS_id, Lang, ConnType, _Client, _Version, _OS}] ->
|
||||||
ets:delete(TableHost, {session, JID}),
|
ets:delete(TableHost, {session, JID}),
|
||||||
|
@ -791,7 +800,7 @@ request_iqversion(User, Host, Resource) ->
|
||||||
IQ = #iq{type = get,
|
IQ = #iq{type = get,
|
||||||
from = From,
|
from = From,
|
||||||
to = To,
|
to = To,
|
||||||
id = randoms:get_string(),
|
id = p1_rand:get_string(),
|
||||||
sub_els = [Query]},
|
sub_els = [Query]},
|
||||||
HandleResponse = fun(#iq{type = result} = IQr) ->
|
HandleResponse = fun(#iq{type = result} = IQr) ->
|
||||||
spawn(?MODULE, received_response,
|
spawn(?MODULE, received_response,
|
||||||
|
@ -848,7 +857,7 @@ received_response(From, #iq{type = Type, lang = Lang1, sub_els = Elc}) ->
|
||||||
update_counter_create(TableHost, {client_conntype, Host, Client_id, ConnType}, 1),
|
update_counter_create(TableHost, {client_conntype, Host, Client_id, ConnType}, 1),
|
||||||
update_counter_create(TableServer, {client_conntype, server, Client_id, ConnType}, 1),
|
update_counter_create(TableServer, {client_conntype, server, Client_id, ConnType}, 1),
|
||||||
|
|
||||||
JID = jlib:make_jid(User, Host, Resource),
|
JID = jid:make(User, Host, Resource),
|
||||||
ets:insert(TableHost, {{session, JID}, Client_id, OS_id, Lang, ConnType, Client, Version, OS}).
|
ets:insert(TableHost, {{session, JID}, Client_id, OS_id, Lang, ConnType, Client, Version, OS}).
|
||||||
|
|
||||||
get_connection_type(User, Host, Resource) ->
|
get_connection_type(User, Host, Resource) ->
|
||||||
|
@ -1004,19 +1013,19 @@ localtime_to_string({{Y, Mo, D},{H, Mi, S}}) ->
|
||||||
%%%% Web Admin Menu
|
%%%% Web Admin Menu
|
||||||
|
|
||||||
web_menu_main(Acc, Lang) ->
|
web_menu_main(Acc, Lang) ->
|
||||||
Acc ++ [{<<"statsdx">>, <<(?T(<<"Statistics">>))/binary, " Dx">>}].
|
Acc ++ [{<<"statsdx">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>}].
|
||||||
|
|
||||||
web_menu_node(Acc, _Node, Lang) ->
|
web_menu_node(Acc, _Node, Lang) ->
|
||||||
Acc ++ [{<<"statsdx">>, <<(?T(<<"Statistics">>))/binary, " Dx">>}].
|
Acc ++ [{<<"statsdx">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>}].
|
||||||
|
|
||||||
web_menu_host(Acc, _Host, Lang) ->
|
web_menu_host(Acc, _Host, Lang) ->
|
||||||
Acc ++ [{<<"statsdx">>, <<(?T(<<"Statistics">>))/binary, " Dx">>}].
|
Acc ++ [{<<"statsdx">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>}].
|
||||||
|
|
||||||
%%%==================================
|
%%%==================================
|
||||||
%%%% Web Admin Page
|
%%%% Web Admin Page
|
||||||
|
|
||||||
web_page_main(_, #request{path=[<<"statsdx">>], lang = Lang} = _Request) ->
|
web_page_main(_, #request{path=[<<"statsdx">>], lang = Lang} = _Request) ->
|
||||||
Res = [?XC(<<"h1">>, <<(?T(<<"Statistics">>))/binary, " Dx">>),
|
Res = [?XC(<<"h1">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>),
|
||||||
?XC(<<"h3">>, <<"Accounts">>),
|
?XC(<<"h3">>, <<"Accounts">>),
|
||||||
?XAE(<<"table">>, [],
|
?XAE(<<"table">>, [],
|
||||||
[?XE(<<"tbody">>, [
|
[?XE(<<"tbody">>, [
|
||||||
|
@ -1124,7 +1133,7 @@ web_page_main(_, #request{path=[<<"statsdx">>], lang = Lang} = _Request) ->
|
||||||
],
|
],
|
||||||
{stop, Res};
|
{stop, Res};
|
||||||
web_page_main(_, #request{path=[<<"statsdx">>, <<"top">>, Topic, Topnumber], q = _Q, lang = Lang} = _Request) ->
|
web_page_main(_, #request{path=[<<"statsdx">>, <<"top">>, Topic, Topnumber], q = _Q, lang = Lang} = _Request) ->
|
||||||
Res = [?XC(<<"h1">>, <<(?T(<<"Statistics">>))/binary, " Dx">>),
|
Res = [?XC(<<"h1">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>),
|
||||||
case Topic of
|
case Topic of
|
||||||
<<"offlinemsg">> -> ?XCT(<<"h2">>, <<"Top offline message queues">>);
|
<<"offlinemsg">> -> ?XCT(<<"h2">>, <<"Top offline message queues">>);
|
||||||
<<"vcard">> -> ?XCT(<<"h2">>, <<"Top vCard sizes">>);
|
<<"vcard">> -> ?XCT(<<"h2">>, <<"Top vCard sizes">>);
|
||||||
|
@ -1144,7 +1153,7 @@ web_page_main(_, #request{path=[<<"statsdx">> | FilterURL], q = Q, lang = Lang}
|
||||||
Filter = parse_url_filter(FilterURL),
|
Filter = parse_url_filter(FilterURL),
|
||||||
Sort_query = get_sort_query(Q),
|
Sort_query = get_sort_query(Q),
|
||||||
FilterS = io_lib:format("~p", [Filter]),
|
FilterS = io_lib:format("~p", [Filter]),
|
||||||
Res = [?XC(<<"h1">>, <<(?T(<<"Statistics">>))/binary, " Dx">>),
|
Res = [?XC(<<"h1">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>),
|
||||||
?XC(<<"h2">>, list_to_binary("Sessions with: " ++ FilterS)),
|
?XC(<<"h2">>, list_to_binary("Sessions with: " ++ FilterS)),
|
||||||
?XE(<<"table">>,
|
?XE(<<"table">>,
|
||||||
[
|
[
|
||||||
|
@ -1156,7 +1165,7 @@ web_page_main(_, #request{path=[<<"statsdx">> | FilterURL], q = Q, lang = Lang}
|
||||||
web_page_main(Acc, _) -> Acc.
|
web_page_main(Acc, _) -> Acc.
|
||||||
|
|
||||||
do_top_table(_Node, Lang, Topic, TopnumberBin, Host) ->
|
do_top_table(_Node, Lang, Topic, TopnumberBin, Host) ->
|
||||||
List = get_top_users(Host, jlib:binary_to_integer(TopnumberBin), Topic),
|
List = get_top_users(Host, binary_to_integer(TopnumberBin), Topic),
|
||||||
%% get_top_users(Topnumber, "roster")
|
%% get_top_users(Topnumber, "roster")
|
||||||
{List2, _} = lists:mapfoldl(
|
{List2, _} = lists:mapfoldl(
|
||||||
fun({Value, UserB, ServerB}, Counter) ->
|
fun({Value, UserB, ServerB}, Counter) ->
|
||||||
|
@ -1238,7 +1247,7 @@ web_page_node(_, Node, [<<"statsdx">>], _Query, Lang) ->
|
||||||
rpc:call(Node, mnesia, system_info, [transaction_log_writes]),
|
rpc:call(Node, mnesia, system_info, [transaction_log_writes]),
|
||||||
|
|
||||||
Res =
|
Res =
|
||||||
[?XC(<<"h1">>, list_to_binary(io_lib:format(?T("~p statistics"), [Node]))),
|
[?XC(<<"h1">>, list_to_binary(io_lib:format(translate:translate(Lang, ?T("~p statistics")), [Node]))),
|
||||||
?XC(<<"h3">>, <<"Connections">>),
|
?XC(<<"h3">>, <<"Connections">>),
|
||||||
?XAE(<<"table">>, [],
|
?XAE(<<"table">>, [],
|
||||||
[?XE(<<"tbody">>, [
|
[?XE(<<"tbody">>, [
|
||||||
|
@ -1335,7 +1344,7 @@ web_page_node(Acc, _, _, _, _) -> Acc.
|
||||||
web_page_host(_, Host,
|
web_page_host(_, Host,
|
||||||
#request{path = [<<"statsdx">>],
|
#request{path = [<<"statsdx">>],
|
||||||
lang = Lang} = _Request) ->
|
lang = Lang} = _Request) ->
|
||||||
Res = [?XC(<<"h1">>, <<(?T(<<"Statistics">>))/binary, " Dx">>),
|
Res = [?XC(<<"h1">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>),
|
||||||
?XC(<<"h2">>, Host),
|
?XC(<<"h2">>, Host),
|
||||||
?XC(<<"h3">>, <<"Accounts">>),
|
?XC(<<"h3">>, <<"Accounts">>),
|
||||||
?XAE(<<"table">>, [],
|
?XAE(<<"table">>, [],
|
||||||
|
@ -1466,7 +1475,7 @@ web_page_host(_, Host,
|
||||||
],
|
],
|
||||||
{stop, Res};
|
{stop, Res};
|
||||||
web_page_host(_, Host, #request{path=[<<"statsdx">>, <<"top">>, Topic, Topnumber], q = _Q, lang = Lang} = _Request) ->
|
web_page_host(_, Host, #request{path=[<<"statsdx">>, <<"top">>, Topic, Topnumber], q = _Q, lang = Lang} = _Request) ->
|
||||||
Res = [?XC(<<"h1">>, <<(?T(<<"Statistics">>))/binary, " Dx">>),
|
Res = [?XC(<<"h1">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>),
|
||||||
case Topic of
|
case Topic of
|
||||||
<<"offlinemsg">> -> ?XCT(<<"h2">>, <<"Top offline message queues">>);
|
<<"offlinemsg">> -> ?XCT(<<"h2">>, <<"Top offline message queues">>);
|
||||||
<<"vcard">> -> ?XCT(<<"h2">>, <<"Top vCard sizes">>);
|
<<"vcard">> -> ?XCT(<<"h2">>, <<"Top vCard sizes">>);
|
||||||
|
@ -1486,7 +1495,7 @@ web_page_host(_, Host, #request{path=[<<"statsdx">> | FilterURL], q = Q,
|
||||||
lang = Lang} = _Request) ->
|
lang = Lang} = _Request) ->
|
||||||
Filter = parse_url_filter(FilterURL),
|
Filter = parse_url_filter(FilterURL),
|
||||||
Sort_query = get_sort_query(Q),
|
Sort_query = get_sort_query(Q),
|
||||||
Res = [?XC(<<"h1">>, <<(?T(<<"Statistics">>))/binary, " Dx">>),
|
Res = [?XC(<<"h1">>, <<(translate:translate(Lang, ?T("Statistics")))/binary, " Dx">>),
|
||||||
?XC(<<"h2">>, list_to_binary("Sessions with: "++io_lib:format("~p", [Filter]))),
|
?XC(<<"h2">>, list_to_binary("Sessions with: "++io_lib:format("~p", [Filter]))),
|
||||||
?XAE(<<"table">>, [],
|
?XAE(<<"table">>, [],
|
||||||
[?XE(<<"tbody">>,
|
[?XE(<<"tbody">>,
|
||||||
|
@ -1550,7 +1559,7 @@ do_sessions_table(_Node, _Lang, Filter, {Sort_direction, Sort_column}, Host) ->
|
||||||
Server = binary_to_list(JID#jid.lserver),
|
Server = binary_to_list(JID#jid.lserver),
|
||||||
UserURL = "/admin/server/" ++ Server ++ "/user/" ++ User ++ "/",
|
UserURL = "/admin/server/" ++ Server ++ "/user/" ++ User ++ "/",
|
||||||
?XE(<<"tr">>, [
|
?XE(<<"tr">>, [
|
||||||
?XE(<<"td">>, [?AC(list_to_binary(UserURL), jlib:jid_to_string(JID))]),
|
?XE(<<"td">>, [?AC(list_to_binary(UserURL), jid:encode(JID))]),
|
||||||
?XCTB("td", atom_to_list(Client_id)),
|
?XCTB("td", atom_to_list(Client_id)),
|
||||||
?XCTB("td", atom_to_list(OS_id)),
|
?XCTB("td", atom_to_list(OS_id)),
|
||||||
?XCTB("td", LangS),
|
?XCTB("td", LangS),
|
||||||
|
@ -1584,12 +1593,12 @@ get_sessions_filtered(Filter, server) ->
|
||||||
ejabberd_config:get_myhosts());
|
ejabberd_config:get_myhosts());
|
||||||
get_sessions_filtered(Filter, Host) ->
|
get_sessions_filtered(Filter, Host) ->
|
||||||
Match = case Filter of
|
Match = case Filter of
|
||||||
[{<<"client">>, Client}] -> {{session, '$1'}, jlib:binary_to_atom(Client), '$2', '$3', '$4', '$5', '$6', '$7'};
|
[{<<"client">>, Client}] -> {{session, '$1'}, misc:binary_to_atom(Client), '$2', '$3', '$4', '$5', '$6', '$7'};
|
||||||
[{<<"os">>, OS}] -> {{session, '$1'}, '$2', jlib:binary_to_atom(OS), '$3', '$4', '$5', '$6', '$7'};
|
[{<<"os">>, OS}] -> {{session, '$1'}, '$2', misc:binary_to_atom(OS), '$3', '$4', '$5', '$6', '$7'};
|
||||||
[{<<"conntype">>, ConnType}] -> {{session, '$1'}, '$2', '$3', '$4', jlib:binary_to_atom(ConnType), '$5', '$6', '$7'};
|
[{<<"conntype">>, ConnType}] -> {{session, '$1'}, '$2', '$3', '$4', misc:binary_to_atom(ConnType), '$5', '$6', '$7'};
|
||||||
[{<<"languages">>, Lang}] -> {{session, '$1'}, '$2', '$3', binary_to_list(Lang), '$4', '$5', '$6', '$7'};
|
[{<<"languages">>, Lang}] -> {{session, '$1'}, '$2', '$3', binary_to_list(Lang), '$4', '$5', '$6', '$7'};
|
||||||
[{<<"client">>, Client}, {<<"os">>, OS}] -> {{session, '$1'}, jlib:binary_to_atom(Client), jlib:binary_to_atom(OS), '$3', '$4', '$5', '$6', '$7'};
|
[{<<"client">>, Client}, {<<"os">>, OS}] -> {{session, '$1'}, misc:binary_to_atom(Client), misc:binary_to_atom(OS), '$3', '$4', '$5', '$6', '$7'};
|
||||||
[{<<"client">>, Client}, {<<"conntype">>, ConnType}] -> {{session, '$1'}, jlib:binary_to_atom(Client), '$2', '$3', jlib:binary_to_atom(ConnType), '$5', '$6', '$7'};
|
[{<<"client">>, Client}, {<<"conntype">>, ConnType}] -> {{session, '$1'}, misc:binary_to_atom(Client), '$2', '$3', misc:binary_to_atom(ConnType), '$5', '$6', '$7'};
|
||||||
_ -> {{session, '$1'}, '$2', '$3', '$4', '$5'}
|
_ -> {{session, '$1'}, '$2', '$3', '$4', '$5'}
|
||||||
end,
|
end,
|
||||||
ets:match_object(table_name(Host), Match).
|
ets:match_object(table_name(Host), Match).
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
mod_webpresence - Presence on the Web
|
mod_webpresence - Presence on the Web
|
||||||
|
|
||||||
|
Requires: ejabberd 19.08 or higher
|
||||||
Authors: Igor Goryachev, Badlop, runcom
|
Authors: Igor Goryachev, Badlop, runcom
|
||||||
http://www.ejabberd.im/mod_webpresence
|
http://www.ejabberd.im/mod_webpresence
|
||||||
|
|
||||||
|
@ -69,20 +70,12 @@ pixmaps_path:
|
||||||
Remember to put the correct path to the pixmaps directory,
|
Remember to put the correct path to the pixmaps directory,
|
||||||
and make sure the user than runs ejabberd has read access to that directory.
|
and make sure the user than runs ejabberd has read access to that directory.
|
||||||
Default value: "./pixmaps"
|
Default value: "./pixmaps"
|
||||||
port:
|
|
||||||
This informational option is used only when sending a message to the user.
|
|
||||||
If you set a different port in the 'listen' section, set this option too.
|
|
||||||
Default value: 5280
|
|
||||||
path:
|
|
||||||
This informational option is used only when sending a message to the user.
|
|
||||||
If you set a different path in the 'listen' section, set this option too.
|
|
||||||
Default value: "presence"
|
|
||||||
baseurl:
|
baseurl:
|
||||||
This informational option is used only when sending a message to the user
|
This informational option is used only when sending a message to the user
|
||||||
and when building the JavaScript code.
|
and when building the JavaScript code.
|
||||||
It is the base part of the URL of the webpresence HTTP content.
|
It is the base part of the URL of the webpresence HTTP content.
|
||||||
You can use the keyword @HOST@.
|
You can use the keyword @HOST@.
|
||||||
If the option is not specified, it takes as default value: http://host:port/path/
|
If the option is not specified, it takes as default value: http://host:52080/presence/
|
||||||
|
|
||||||
|
|
||||||
AUTOMATIC ENABLE
|
AUTOMATIC ENABLE
|
||||||
|
@ -144,8 +137,6 @@ modules:
|
||||||
host: "webstatus.@HOST@"
|
host: "webstatus.@HOST@"
|
||||||
access: local
|
access: local
|
||||||
pixmaps_path: "/path/to/pixmaps"
|
pixmaps_path: "/path/to/pixmaps"
|
||||||
port: 80
|
|
||||||
path: "status"
|
|
||||||
baseurl: "http://www.example.org/status/"
|
baseurl: "http://www.example.org/status/"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
-include("translate.hrl").
|
||||||
-include("ejabberd_web_admin.hrl").
|
-include("ejabberd_web_admin.hrl").
|
||||||
-include("ejabberd_http.hrl").
|
-include("ejabberd_http.hrl").
|
||||||
|
|
||||||
|
@ -53,11 +54,7 @@ start_link() ->
|
||||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
Default_dir = case code:priv_dir(ejabberd) of
|
Dir = gen_mod:get_opt(pixmaps_path, Opts),
|
||||||
{error, _} -> ?PIXMAPS_DIR;
|
|
||||||
Path -> filename:join([Path, ?PIXMAPS_DIR])
|
|
||||||
end,
|
|
||||||
Dir = gen_mod:get_opt(pixmaps_path, Opts, fun(D) -> D end, Default_dir),
|
|
||||||
catch ets:new(pixmaps_dirs, [named_table, public]),
|
catch ets:new(pixmaps_dirs, [named_table, public]),
|
||||||
ets:insert(pixmaps_dirs, {directory, Dir}),
|
ets:insert(pixmaps_dirs, {directory, Dir}),
|
||||||
case gen_mod:start_child(?MODULE, Host, Opts) of
|
case gen_mod:start_child(?MODULE, Host, Opts) of
|
||||||
|
@ -75,19 +72,23 @@ stop(Host) ->
|
||||||
gen_mod:stop_child(?MODULE, Host),
|
gen_mod:stop_child(?MODULE, Host),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec mod_opt_type(atom()) -> fun((term()) -> term()).
|
mod_opt_type(host) ->
|
||||||
mod_opt_type(host) -> fun iolist_to_binary/1;
|
econf:host();
|
||||||
mod_opt_type(access) -> fun acl:access_rules_validator/1;
|
mod_opt_type(access) ->
|
||||||
mod_opt_type(pixmaps_path) -> fun iolist_to_binary/1;
|
econf:acl();
|
||||||
|
mod_opt_type(pixmaps_path) ->
|
||||||
|
econf:directory();
|
||||||
mod_opt_type(port) ->
|
mod_opt_type(port) ->
|
||||||
fun(I) when is_integer(I), I>0, I<65536 -> I end;
|
econf:pos_int();
|
||||||
mod_opt_type(path) -> fun iolist_to_binary/1;
|
mod_opt_type(path) ->
|
||||||
mod_opt_type(baseurl) -> fun iolist_to_binary/1.
|
econf:binary();
|
||||||
|
mod_opt_type(baseurl) ->
|
||||||
|
econf:binary().
|
||||||
|
|
||||||
-spec mod_options(binary()) -> [{atom(), any()}].
|
-spec mod_options(binary()) -> [{atom(), any()}].
|
||||||
mod_options(Host) ->
|
mod_options(Host) ->
|
||||||
[{host, <<"webpresence.@HOST@">>},
|
[{host, <<"webpresence.", Host/binary>>},
|
||||||
{access, none},
|
{access, local},
|
||||||
{pixmaps_path, ?PIXMAPS_DIR},
|
{pixmaps_path, ?PIXMAPS_DIR},
|
||||||
{port, 5280},
|
{port, 5280},
|
||||||
{path, <<"presence">>},
|
{path, <<"presence">>},
|
||||||
|
@ -114,12 +115,9 @@ init([Host, Opts]) ->
|
||||||
{attributes, record_info(fields, webpresence)}]),
|
{attributes, record_info(fields, webpresence)}]),
|
||||||
mnesia:add_table_index(webpresence, ridurl),
|
mnesia:add_table_index(webpresence, ridurl),
|
||||||
update_table(),
|
update_table(),
|
||||||
MyHost = gen_mod:get_opt_host(Host, Opts, <<"webpresence.@HOST@">>),
|
MyHost = gen_mod:get_opt(host, Opts),
|
||||||
Access = gen_mod:get_opt(access, Opts, fun(O) -> O end, local),
|
Access = gen_mod:get_opt(access, Opts),
|
||||||
Port = gen_mod:get_opt(port, Opts, fun(O) -> O end, 5280),
|
BaseURL1 = gen_mod:get_opt(baseurl, Opts),
|
||||||
Path = gen_mod:get_opt(path, Opts, fun(O) -> O end, <<"presence">>),
|
|
||||||
BaseURL1 = gen_mod:get_opt(baseurl, Opts, fun(O) -> O end,
|
|
||||||
iolist_to_binary(io_lib:format(<<"http://~s:~p/~s/">>, [Host, Port, Path]))),
|
|
||||||
BaseURL2 = ejabberd_regexp:greplace(BaseURL1, <<"@HOST@">>, Host),
|
BaseURL2 = ejabberd_regexp:greplace(BaseURL1, <<"@HOST@">>, Host),
|
||||||
register_iq_handlers(MyHost),
|
register_iq_handlers(MyHost),
|
||||||
ejabberd_router:register_route(MyHost, Host),
|
ejabberd_router:register_route(MyHost, Host),
|
||||||
|
@ -304,7 +302,7 @@ process_disco_items(#iq{lang = Lang} = IQ) ->
|
||||||
name = <<"field">>,
|
name = <<"field">>,
|
||||||
attrs = [
|
attrs = [
|
||||||
{<<"type">>, Type},
|
{<<"type">>, Type},
|
||||||
{<<"label">>, ?T(Label)},
|
{<<"label">>, translate:translate(Lang, ?T(Label))},
|
||||||
{<<"var">>, Var}
|
{<<"var">>, Var}
|
||||||
],
|
],
|
||||||
children = Vals
|
children = Vals
|
||||||
|
@ -445,7 +443,7 @@ send_message_registered(WP, To, Host, BaseURL, Lang) ->
|
||||||
false -> <<"">>;
|
false -> <<"">>;
|
||||||
true -> ?BC([
|
true -> ?BC([
|
||||||
<<" text\n"
|
<<" text\n"
|
||||||
" text/res/<">>, ?T(<<"Resource">>), <<">\n">>
|
" text/res/<">>, translate:translate(Lang, ?T("Resource")), <<">\n">>
|
||||||
])
|
])
|
||||||
end,
|
end,
|
||||||
Oimage = case WP#webpresence.icon of
|
Oimage = case WP#webpresence.icon of
|
||||||
|
@ -455,9 +453,9 @@ send_message_registered(WP, To, Host, BaseURL, Lang) ->
|
||||||
<<" image\n"
|
<<" image\n"
|
||||||
" image/example.php\n"
|
" image/example.php\n"
|
||||||
" image/mypresence.png\n"
|
" image/mypresence.png\n"
|
||||||
" image/res/<">>, ?T(<<"Resource">>), <<">\n"
|
" image/res/<">>, translate:translate(Lang, ?T("Resource")), <<">\n"
|
||||||
" image/theme/<">>, ?T(<<"Icon Theme">>), <<">\n"
|
" image/theme/<">>, translate:translate(Lang, ?T("Icon Theme")), <<">\n"
|
||||||
" image/theme/<">>, ?T(<<"Icon Theme">>), <<">/res/<">>, ?T(<<"Resource">>), <<">\n">>
|
" image/theme/<">>, translate:translate(Lang, ?T("Icon Theme")), <<">/res/<">>, translate:translate(Lang, ?T("Resource")), <<">\n">>
|
||||||
])
|
])
|
||||||
end,
|
end,
|
||||||
Oxml = case WP#webpresence.xml of
|
Oxml = case WP#webpresence.xml of
|
||||||
|
@ -484,24 +482,24 @@ send_message_registered(WP, To, Host, BaseURL, Lang) ->
|
||||||
RIDT = ?BC([<<"rid/">>, RID]),
|
RIDT = ?BC([<<"rid/">>, RID]),
|
||||||
{?BC([<<" ">>, RIDT, <<"\n">>]),
|
{?BC([<<" ">>, RIDT, <<"\n">>]),
|
||||||
?BC([<<" ">>, BaseURL, RIDT, <<"/">>, Allowed_type, <<"/\n">>]),
|
?BC([<<" ">>, BaseURL, RIDT, <<"/">>, Allowed_type, <<"/\n">>]),
|
||||||
?BC([?T(<<"If you forget your RandomID, register again to receive this message.">>), <<"\n">>,
|
?BC([translate:translate(Lang, ?T("If you forget your RandomID, register again to receive this message.")), <<"\n">>,
|
||||||
?T(<<"To get a new RandomID, disable the option and register again.">>), <<"\n">>])
|
translate:translate(Lang, ?T("To get a new RandomID, disable the option and register again.")), <<"\n">>])
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
Subject = ?BC([?T(<<"Web Presence">>), <<": ">>, ?T(<<"registered">>)]),
|
Subject = ?BC([translate:translate(Lang, ?T("Web Presence")), <<": ">>, translate:translate(Lang, ?T("registered"))]),
|
||||||
Body = ?BC([?T(<<"You have registered:">>), <<" ">>, JIDS, <<"\n\n">>,
|
Body = ?BC([translate:translate(Lang, ?T("You have registered:")), <<" ">>, JIDS, <<"\n\n">>,
|
||||||
?T(<<"Use URLs like:">>), <<"\n">>,
|
translate:translate(Lang, ?T("Use URLs like:")), <<"\n">>,
|
||||||
<<" ">>, BaseURL, <<"USERID/OUTPUT/\n">>,
|
<<" ">>, BaseURL, <<"USERID/OUTPUT/\n">>,
|
||||||
<<"\n">>,
|
<<"\n">>,
|
||||||
<<"USERID:\n">>, USERID_jid, USERID_rid, <<"\n">>,
|
<<"USERID:\n">>, USERID_jid, USERID_rid, <<"\n">>,
|
||||||
<<"OUTPUT:\n">>, Oimage, Oxml, Ojs, Otext, Oavatar, <<"\n">>,
|
<<"OUTPUT:\n">>, Oimage, Oxml, Ojs, Otext, Oavatar, <<"\n">>,
|
||||||
?T(<<"Example:">>), <<"\n">>, Example_jid, Example_rid, <<"\n">>,
|
translate:translate(Lang, ?T("Example:")), <<"\n">>, Example_jid, Example_rid, <<"\n">>,
|
||||||
Text_rid]),
|
Text_rid]),
|
||||||
send_headline(Host, To, Subject, Body).
|
send_headline(Host, To, Subject, Body).
|
||||||
|
|
||||||
send_message_unregistered(To, Host, Lang) ->
|
send_message_unregistered(To, Host, Lang) ->
|
||||||
Subject = ?BC([?T(<<"Web Presence">>), <<": ">>, ?T(<<"unregistered">>)]),
|
Subject = ?BC([translate:translate(Lang, ?T("Web Presence")), <<": ">>, translate:translate(Lang, ?T("unregistered"))]),
|
||||||
Body = ?BC([?T(<<"You have unregistered.">>), <<"\n\n">>]),
|
Body = ?BC([translate:translate(Lang, ?T("You have unregistered.")), <<"\n\n">>]),
|
||||||
send_headline(Host, To, Subject, Body).
|
send_headline(Host, To, Subject, Body).
|
||||||
|
|
||||||
send_headline(Host, To, Subject, Body) ->
|
send_headline(Host, To, Subject, Body) ->
|
||||||
|
@ -704,12 +702,12 @@ make_js(WP, Prs, Show_us, Lang, Q) ->
|
||||||
end,
|
end,
|
||||||
?BC([US_string, <<"var jabber_resources=[\n">>, R_string, <<"];">>, CB_string]).
|
?BC([US_string, <<"var jabber_resources=[\n">>, R_string, <<"];">>, CB_string]).
|
||||||
|
|
||||||
long_show(<<"available">>, Lang) -> ?T(<<"available">>);
|
long_show(<<"available">>, Lang) -> translate:translate(Lang, ?T("available"));
|
||||||
long_show(<<"chat">>, Lang) -> ?T(<<"free for chat">>);
|
long_show(<<"chat">>, Lang) -> translate:translate(Lang, ?T("free for chat"));
|
||||||
long_show(<<"away">>, Lang) -> ?T(<<"away">>);
|
long_show(<<"away">>, Lang) -> translate:translate(Lang, ?T("away"));
|
||||||
long_show(<<"xa">>, Lang) -> ?T(<<"extended away">>);
|
long_show(<<"xa">>, Lang) -> translate:translate(Lang, ?T("extended away"));
|
||||||
long_show(<<"dnd">>, Lang) -> ?T(<<"do not disturb">>);
|
long_show(<<"dnd">>, Lang) -> translate:translate(Lang, ?T("do not disturb"));
|
||||||
long_show(_, Lang) -> ?T(<<"unavailable">>).
|
long_show(_, Lang) -> translate:translate(Lang, ?T("unavailable")).
|
||||||
|
|
||||||
intund2string(undefined) -> intund2string(0);
|
intund2string(undefined) -> intund2string(0);
|
||||||
intund2string(Int) when is_integer(Int) -> list_to_binary(integer_to_list(Int)).
|
intund2string(Int) when is_integer(Int) -> list_to_binary(integer_to_list(Int)).
|
||||||
|
@ -887,20 +885,20 @@ process(LocalPath, Request) ->
|
||||||
|
|
||||||
process2([], #request{lang = Lang1}) ->
|
process2([], #request{lang = Lang1}) ->
|
||||||
Lang = parse_lang(Lang1),
|
Lang = parse_lang(Lang1),
|
||||||
Title = [?XC(<<"title">>, ?T(<<"Web Presence">>))],
|
Title = [?XC(<<"title">>, translate:translate(Lang, ?T("Web Presence")))],
|
||||||
Desc = [?XC(<<"p">>, ?BC([ ?T(<<"To publish your presence using this system you need a Jabber account in this Jabber server.">>), <<" ">>,
|
Desc = [?XC(<<"p">>, ?BC([ translate:translate(Lang, ?T("To publish your presence using this system you need a Jabber account in this Jabber server.")), <<" ">>,
|
||||||
?T(<<"Login with a Jabber client, open the Service Discovery and register in Web Presence.">>),
|
translate:translate(Lang, ?T("Login with a Jabber client, open the Service Discovery and register in Web Presence.")),
|
||||||
?T(<<"You will receive a message with further instructions.">>)]))],
|
translate:translate(Lang, ?T("You will receive a message with further instructions."))]))],
|
||||||
Link_themes = [?AC(<<"themes">>, ?T(<<"Icon Theme">>))],
|
Link_themes = [?AC(<<"themes">>, translate:translate(Lang, ?T("Icon Theme")))],
|
||||||
Body = [?XC(<<"h1">>, ?T(<<"Web Presence">>))] ++ Desc ++ Link_themes,
|
Body = [?XC(<<"h1">>, translate:translate(Lang, ?T("Web Presence")))] ++ Desc ++ Link_themes,
|
||||||
make_xhtml(Title, Body);
|
make_xhtml(Title, Body);
|
||||||
|
|
||||||
process2([<<"themes">>], #request{lang = Lang1}) ->
|
process2([<<"themes">>], #request{lang = Lang1}) ->
|
||||||
Lang = parse_lang(Lang1),
|
Lang = parse_lang(Lang1),
|
||||||
Title = [?XC(<<"title">>, ?BC([?T(<<"Web Presence">>), <<" - ">>, ?T("Icon Theme")]))],
|
Title = [?XC(<<"title">>, ?BC([translate:translate(Lang, ?T("Web Presence")), <<" - ">>, translate:translate(Lang, ?T("Icon Theme"))]))],
|
||||||
Themes = available_themes(list),
|
Themes = available_themes(list),
|
||||||
Icon_themes = themes_to_xhtml(Themes),
|
Icon_themes = themes_to_xhtml(Themes),
|
||||||
Body = [?XC(<<"h1">>, ?T(<<"Icon Theme">>))] ++ Icon_themes,
|
Body = [?XC(<<"h1">>, translate:translate(Lang, ?T("Icon Theme")))] ++ Icon_themes,
|
||||||
make_xhtml(Title, Body);
|
make_xhtml(Title, Body);
|
||||||
|
|
||||||
process2([<<"image">>, Theme, Show], #request{} = _Request) ->
|
process2([<<"image">>, Theme, Show], #request{} = _Request) ->
|
||||||
|
@ -958,7 +956,7 @@ serve_web_presence(TypeURL, User, Server, Tail, #request{lang = Lang1, q = Q}) -
|
||||||
%%%% ---------------------
|
%%%% ---------------------
|
||||||
|
|
||||||
web_menu_host(Acc, _Host, Lang) ->
|
web_menu_host(Acc, _Host, Lang) ->
|
||||||
[{<<"webpresence">>, ?T(<<"Web Presence">>)} | Acc].
|
[{<<"webpresence">>, translate:translate(Lang, ?T("Web Presence"))} | Acc].
|
||||||
|
|
||||||
web_page_host(_, _Host,
|
web_page_host(_, _Host,
|
||||||
#request{path = [<<"webpresence">>],
|
#request{path = [<<"webpresence">>],
|
||||||
|
|
Loading…
Reference in New Issue