mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-28 16:34:13 +01:00
Introduce new gen_mod callback: mod_options/1
The callback is supposed to provide known options and their default values, as long as the documentation. Passing default values into get_mod functions is now deprecated: all defaults should be provided by the Mod:mod_options/1 callback.
This commit is contained in:
parent
c0ef054f6f
commit
ba2b650464
@ -71,16 +71,12 @@
|
|||||||
-define(NS_HTTP_BIND,
|
-define(NS_HTTP_BIND,
|
||||||
<<"http://jabber.org/protocol/httpbind">>).
|
<<"http://jabber.org/protocol/httpbind">>).
|
||||||
|
|
||||||
-define(DEFAULT_MAXPAUSE, 120).
|
|
||||||
|
|
||||||
-define(DEFAULT_WAIT, 300).
|
-define(DEFAULT_WAIT, 300).
|
||||||
|
|
||||||
-define(DEFAULT_HOLD, 1).
|
-define(DEFAULT_HOLD, 1).
|
||||||
|
|
||||||
-define(DEFAULT_POLLING, 2).
|
-define(DEFAULT_POLLING, 2).
|
||||||
|
|
||||||
-define(DEFAULT_INACTIVITY, 30).
|
|
||||||
|
|
||||||
-define(MAX_SHAPED_REQUESTS_QUEUE_LEN, 1000).
|
-define(MAX_SHAPED_REQUESTS_QUEUE_LEN, 1000).
|
||||||
|
|
||||||
-define(SEND_TIMEOUT, 15000).
|
-define(SEND_TIMEOUT, 15000).
|
||||||
@ -102,7 +98,7 @@
|
|||||||
inactivity_timer :: reference() | undefined,
|
inactivity_timer :: reference() | undefined,
|
||||||
wait_timer :: reference() | undefined,
|
wait_timer :: reference() | undefined,
|
||||||
wait_timeout = ?DEFAULT_WAIT :: timeout(),
|
wait_timeout = ?DEFAULT_WAIT :: timeout(),
|
||||||
inactivity_timeout = ?DEFAULT_INACTIVITY :: timeout(),
|
inactivity_timeout :: timeout(),
|
||||||
prev_rid = 0 :: non_neg_integer(),
|
prev_rid = 0 :: non_neg_integer(),
|
||||||
prev_key = <<"">> :: binary(),
|
prev_key = <<"">> :: binary(),
|
||||||
prev_poll :: erlang:timestamp() | undefined,
|
prev_poll :: erlang:timestamp() | undefined,
|
||||||
@ -294,7 +290,7 @@ init([#body{attrs = Attrs}, IP, SID]) ->
|
|||||||
XMPPVer = get_attr('xmpp:version', Attrs),
|
XMPPVer = get_attr('xmpp:version', Attrs),
|
||||||
XMPPDomain = get_attr(to, Attrs),
|
XMPPDomain = get_attr(to, Attrs),
|
||||||
{InBuf, Opts} = case gen_mod:get_module_opt(
|
{InBuf, Opts} = case gen_mod:get_module_opt(
|
||||||
XMPPDomain, mod_bosh, prebind, false) of
|
XMPPDomain, mod_bosh, prebind) of
|
||||||
true ->
|
true ->
|
||||||
JID = make_random_jid(XMPPDomain),
|
JID = make_random_jid(XMPPDomain),
|
||||||
{buf_new(XMPPDomain), [{jid, JID} | Opts2]};
|
{buf_new(XMPPDomain), [{jid, JID} | Opts2]};
|
||||||
@ -306,10 +302,8 @@ init([#body{attrs = Attrs}, IP, SID]) ->
|
|||||||
xmpp_socket:start(ejabberd_c2s, ?MODULE, Socket,
|
xmpp_socket:start(ejabberd_c2s, ?MODULE, Socket,
|
||||||
[{receiver, self()}|Opts]),
|
[{receiver, self()}|Opts]),
|
||||||
Inactivity = gen_mod:get_module_opt(XMPPDomain,
|
Inactivity = gen_mod:get_module_opt(XMPPDomain,
|
||||||
mod_bosh, max_inactivity,
|
mod_bosh, max_inactivity),
|
||||||
?DEFAULT_INACTIVITY),
|
MaxConcat = gen_mod:get_module_opt(XMPPDomain, mod_bosh, max_concat),
|
||||||
MaxConcat = gen_mod:get_module_opt(XMPPDomain, mod_bosh, max_concat,
|
|
||||||
unlimited),
|
|
||||||
ShapedReceivers = buf_new(XMPPDomain, ?MAX_SHAPED_REQUESTS_QUEUE_LEN),
|
ShapedReceivers = buf_new(XMPPDomain, ?MAX_SHAPED_REQUESTS_QUEUE_LEN),
|
||||||
State = #state{host = XMPPDomain, sid = SID, ip = IP,
|
State = #state{host = XMPPDomain, sid = SID, ip = IP,
|
||||||
xmpp_ver = XMPPVer, el_ibuf = InBuf,
|
xmpp_ver = XMPPVer, el_ibuf = InBuf,
|
||||||
@ -354,8 +348,7 @@ wait_for_session(#body{attrs = Attrs} = Req, From,
|
|||||||
true -> {undefined, []}
|
true -> {undefined, []}
|
||||||
end,
|
end,
|
||||||
MaxPause = gen_mod:get_module_opt(State#state.host,
|
MaxPause = gen_mod:get_module_opt(State#state.host,
|
||||||
mod_bosh, max_pause,
|
mod_bosh, max_pause),
|
||||||
?DEFAULT_MAXPAUSE),
|
|
||||||
Resp = #body{attrs =
|
Resp = #body{attrs =
|
||||||
[{sid, State#state.sid}, {wait, Wait},
|
[{sid, State#state.sid}, {wait, Wait},
|
||||||
{ver, ?BOSH_VERSION}, {polling, ?DEFAULT_POLLING},
|
{ver, ?BOSH_VERSION}, {polling, ?DEFAULT_POLLING},
|
||||||
@ -1028,8 +1021,7 @@ buf_new(Host) ->
|
|||||||
|
|
||||||
buf_new(Host, Limit) ->
|
buf_new(Host, Limit) ->
|
||||||
QueueType = gen_mod:get_module_opt(
|
QueueType = gen_mod:get_module_opt(
|
||||||
Host, mod_bosh, queue_type,
|
Host, mod_bosh, queue_type),
|
||||||
ejabberd_config:default_queue_type(Host)),
|
|
||||||
p1_queue:new(QueueType, Limit).
|
p1_queue:new(QueueType, Limit).
|
||||||
|
|
||||||
buf_in(Xs, Buf) ->
|
buf_in(Xs, Buf) ->
|
||||||
|
@ -648,7 +648,7 @@ process_presence_out(#{user := User, server := Server, lserver := LServer,
|
|||||||
#presence{from = From, to = To, type = Type} = Pres) ->
|
#presence{from = From, to = To, type = Type} = Pres) ->
|
||||||
if Type == subscribe; Type == subscribed;
|
if Type == subscribe; Type == subscribed;
|
||||||
Type == unsubscribe; Type == unsubscribed ->
|
Type == unsubscribe; Type == unsubscribed ->
|
||||||
Access = gen_mod:get_module_opt(LServer, mod_roster, access, all),
|
Access = gen_mod:get_module_opt(LServer, mod_roster, access),
|
||||||
MyBareJID = jid:remove_resource(JID),
|
MyBareJID = jid:remove_resource(JID),
|
||||||
case acl:match_rule(LServer, Access, MyBareJID) of
|
case acl:match_rule(LServer, Access, MyBareJID) of
|
||||||
deny ->
|
deny ->
|
||||||
@ -1025,20 +1025,19 @@ listen_opt_type(max_stanza_size) ->
|
|||||||
end;
|
end;
|
||||||
listen_opt_type(max_fsm_queue) ->
|
listen_opt_type(max_fsm_queue) ->
|
||||||
fun(I) when is_integer(I), I>0 -> I end;
|
fun(I) when is_integer(I), I>0 -> I end;
|
||||||
%% The following hack should be removed in future releases: it is intended
|
|
||||||
%% for backward compatibility with ejabberd 17.01 or older
|
|
||||||
listen_opt_type(stream_management) ->
|
listen_opt_type(stream_management) ->
|
||||||
?WARNING_MSG("listening option 'stream_management' is deprecated: "
|
?ERROR_MSG("listening option 'stream_management' is ignored: "
|
||||||
"use mod_stream_mgmt module", []),
|
"use mod_stream_mgmt module", []),
|
||||||
fun(B) when is_boolean(B) -> B end;
|
fun(B) when is_boolean(B) -> B end;
|
||||||
listen_opt_type(O) ->
|
listen_opt_type(O) ->
|
||||||
case mod_stream_mgmt:mod_opt_type(O) of
|
StreamOpts = mod_stream_mgmt:mod_options(?MYNAME),
|
||||||
L when is_list(L) ->
|
case lists:keyfind(O, 1, StreamOpts) of
|
||||||
|
false ->
|
||||||
[access, shaper, certfile, ciphers, dhfile, cafile,
|
[access, shaper, certfile, ciphers, dhfile, cafile,
|
||||||
protocol_options, tls, tls_compression, starttls,
|
protocol_options, tls, tls_compression, starttls,
|
||||||
starttls_required, tls_verify, zlib, max_fsm_queue];
|
starttls_required, tls_verify, zlib, max_fsm_queue];
|
||||||
VFun ->
|
_ ->
|
||||||
?WARNING_MSG("listening option '~s' is deprecated: use '~s' "
|
?ERROR_MSG("Listening option '~s' is ignored: use '~s' "
|
||||||
"option from mod_stream_mgmt module", [O, O]),
|
"option from mod_stream_mgmt module", [O, O]),
|
||||||
VFun
|
mod_stream_mgmt:mod_opt_type(O)
|
||||||
end.
|
end.
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
-export([start/0, load_file/1, reload_file/0, read_file/1,
|
-export([start/0, load_file/1, reload_file/0, read_file/1,
|
||||||
get_option/1, get_option/2, add_option/2, has_option/1,
|
get_option/1, get_option/2, add_option/2, has_option/1,
|
||||||
get_vh_by_auth_method/1,
|
|
||||||
get_version/0, get_myhosts/0, get_mylang/0, get_lang/1,
|
get_version/0, get_myhosts/0, get_mylang/0, get_lang/1,
|
||||||
get_ejabberd_config_path/0, is_using_elixir_config/0,
|
get_ejabberd_config_path/0, is_using_elixir_config/0,
|
||||||
prepare_opt_val/4, transform_options/1, collect_options/1,
|
prepare_opt_val/4, transform_options/1, collect_options/1,
|
||||||
@ -71,8 +70,10 @@
|
|||||||
start() ->
|
start() ->
|
||||||
ConfigFile = get_ejabberd_config_path(),
|
ConfigFile = get_ejabberd_config_path(),
|
||||||
?INFO_MSG("Loading configuration from ~s", [ConfigFile]),
|
?INFO_MSG("Loading configuration from ~s", [ConfigFile]),
|
||||||
p1_options:start_link(ejabberd_options),
|
catch ets:new(ejabberd_options,
|
||||||
p1_options:start_link(ejabberd_db_modules),
|
[named_table, public, {read_concurrency, true}]),
|
||||||
|
catch ets:new(ejabberd_db_modules,
|
||||||
|
[named_table, public, {read_concurrency, true}]),
|
||||||
State1 = load_file(ConfigFile),
|
State1 = load_file(ConfigFile),
|
||||||
UnixTime = p1_time_compat:system_time(seconds),
|
UnixTime = p1_time_compat:system_time(seconds),
|
||||||
SharedKey = case erlang:get_cookie() of
|
SharedKey = case erlang:get_cookie() of
|
||||||
@ -105,8 +106,10 @@ hosts_to_start(State) ->
|
|||||||
%% At the moment, these functions are mainly used to setup unit tests.
|
%% At the moment, these functions are mainly used to setup unit tests.
|
||||||
-spec start(Hosts :: [binary()], Opts :: [acl:acl() | local_config()]) -> ok.
|
-spec start(Hosts :: [binary()], Opts :: [acl:acl() | local_config()]) -> ok.
|
||||||
start(Hosts, Opts) ->
|
start(Hosts, Opts) ->
|
||||||
p1_options:start_link(ejabberd_options),
|
catch ets:new(ejabberd_options,
|
||||||
p1_options:start_link(ejabberd_db_modules),
|
[named_table, public, {read_concurrency, true}]),
|
||||||
|
catch ets:new(ejabberd_db_modules,
|
||||||
|
[named_table, public, {read_concurrency, true}]),
|
||||||
set_opts(set_hosts_in_options(Hosts, #state{opts = Opts})),
|
set_opts(set_hosts_in_options(Hosts, #state{opts = Opts})),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@ -758,17 +761,12 @@ append_option({Opt, Host}, Val, State) ->
|
|||||||
|
|
||||||
set_opts(State) ->
|
set_opts(State) ->
|
||||||
Opts = State#state.opts,
|
Opts = State#state.opts,
|
||||||
ets:select_delete(ejabberd_options,
|
ets:insert(
|
||||||
ets:fun2ms(
|
ejabberd_options,
|
||||||
fun({{node_start, _}, _}) -> false;
|
lists:map(
|
||||||
({{shared_key, _}, _}) -> false;
|
fun(#local_config{key = Key, value = Val}) ->
|
||||||
(_) -> true
|
{Key, Val}
|
||||||
end)),
|
end, Opts)),
|
||||||
lists:foreach(
|
|
||||||
fun(#local_config{key = {Opt, Host}, value = Val}) ->
|
|
||||||
p1_options:insert(ejabberd_options, Opt, Host, Val)
|
|
||||||
end, Opts),
|
|
||||||
p1_options:compile(ejabberd_options),
|
|
||||||
set_log_level().
|
set_log_level().
|
||||||
|
|
||||||
set_log_level() ->
|
set_log_level() ->
|
||||||
@ -784,8 +782,7 @@ add_local_option(Opt, Val) ->
|
|||||||
add_option(Opt, Val) when is_atom(Opt) ->
|
add_option(Opt, Val) when is_atom(Opt) ->
|
||||||
add_option({Opt, global}, Val);
|
add_option({Opt, global}, Val);
|
||||||
add_option({Opt, Host}, Val) ->
|
add_option({Opt, Host}, Val) ->
|
||||||
p1_options:insert(ejabberd_options, Opt, Host, Val),
|
ets:insert(ejabberd_options, {{Opt, Host}, Val}).
|
||||||
p1_options:compile(ejabberd_options).
|
|
||||||
|
|
||||||
-spec prepare_opt_val(any(), any(), check_fun(), any()) -> any().
|
-spec prepare_opt_val(any(), any(), check_fun(), any()) -> any().
|
||||||
|
|
||||||
@ -862,13 +859,12 @@ get_option(Opt, Default) ->
|
|||||||
"format. This is likely a bug", [Opt]),
|
"format. This is likely a bug", [Opt]),
|
||||||
{undefined, global}
|
{undefined, global}
|
||||||
end,
|
end,
|
||||||
case ejabberd_options:is_known(Key) of
|
try ets:lookup_element(ejabberd_options, {Key, Host}, 2)
|
||||||
true ->
|
catch _:badarg when Host /= global ->
|
||||||
case ejabberd_options:Key(Host) of
|
try ets:lookup_element(ejabberd_options, {Key, global}, 2)
|
||||||
{ok, Val} -> Val;
|
catch _:badarg -> Default
|
||||||
undefined -> Default
|
|
||||||
end;
|
end;
|
||||||
false ->
|
_:badarg ->
|
||||||
Default
|
Default
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -878,8 +874,8 @@ has_option(Opt) ->
|
|||||||
|
|
||||||
init_module_db_table(Modules) ->
|
init_module_db_table(Modules) ->
|
||||||
%% Dirty hack for mod_pubsub
|
%% Dirty hack for mod_pubsub
|
||||||
p1_options:insert(ejabberd_db_modules, mod_pubsub, mnesia, true),
|
ets:insert(ejabberd_db_modules, {{mod_pubsub, mnesia}, true}),
|
||||||
p1_options:insert(ejabberd_db_modules, mod_pubsub, sql, true),
|
ets:insert(ejabberd_db_modules, {{mod_pubsub, sql}, true}),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(M) ->
|
fun(M) ->
|
||||||
case re:split(atom_to_list(M), "_", [{return, list}]) of
|
case re:split(atom_to_list(M), "_", [{return, list}]) of
|
||||||
@ -891,14 +887,13 @@ init_module_db_table(Modules) ->
|
|||||||
BareMod = list_to_atom(string:join(lists:reverse(T), "_")),
|
BareMod = list_to_atom(string:join(lists:reverse(T), "_")),
|
||||||
case is_behaviour(BareMod, M) of
|
case is_behaviour(BareMod, M) of
|
||||||
true ->
|
true ->
|
||||||
p1_options:insert(ejabberd_db_modules,
|
ets:insert(ejabberd_db_modules,
|
||||||
BareMod, Suffix, true);
|
{{BareMod, Suffix}, true});
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end, Modules),
|
end, Modules).
|
||||||
p1_options:compile(ejabberd_db_modules).
|
|
||||||
|
|
||||||
is_behaviour(Behav, Mod) ->
|
is_behaviour(Behav, Mod) ->
|
||||||
try Mod:module_info(attributes) of
|
try Mod:module_info(attributes) of
|
||||||
@ -920,20 +915,20 @@ is_behaviour(Behav, Mod) ->
|
|||||||
v_db(Mod, internal) -> v_db(Mod, mnesia);
|
v_db(Mod, internal) -> v_db(Mod, mnesia);
|
||||||
v_db(Mod, odbc) -> v_db(Mod, sql);
|
v_db(Mod, odbc) -> v_db(Mod, sql);
|
||||||
v_db(Mod, Type) ->
|
v_db(Mod, Type) ->
|
||||||
case ejabberd_db_modules:is_known(Mod) of
|
case ets:member(ejabberd_db_modules, {Mod, Type}) of
|
||||||
true ->
|
true -> Type;
|
||||||
case ejabberd_db_modules:Mod(Type) of
|
false -> erlang:error(badarg)
|
||||||
{ok, _} -> Type;
|
|
||||||
_ -> erlang:error(badarg)
|
|
||||||
end;
|
|
||||||
false ->
|
|
||||||
erlang:error(badarg)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec v_dbs(module()) -> [atom()].
|
-spec v_dbs(module()) -> [atom()].
|
||||||
|
|
||||||
v_dbs(Mod) ->
|
v_dbs(Mod) ->
|
||||||
ejabberd_db_modules:get_scope(Mod).
|
ets:select(
|
||||||
|
ejabberd_db_modules,
|
||||||
|
ets:fun2ms(
|
||||||
|
fun({{M, Type}, _}) when M == Mod ->
|
||||||
|
Type
|
||||||
|
end)).
|
||||||
|
|
||||||
-spec v_dbs_mods(module()) -> [module()].
|
-spec v_dbs_mods(module()) -> [module()].
|
||||||
|
|
||||||
@ -1039,26 +1034,6 @@ validate_opts(#state{opts = Opts} = State, ModOpts) ->
|
|||||||
end, Opts),
|
end, Opts),
|
||||||
State#state{opts = NewOpts}.
|
State#state{opts = NewOpts}.
|
||||||
|
|
||||||
-spec get_vh_by_auth_method(atom()) -> [binary()].
|
|
||||||
|
|
||||||
%% Return the list of hosts with a given auth method
|
|
||||||
get_vh_by_auth_method(AuthMethod) ->
|
|
||||||
Hosts = ejabberd_options:get_scope(auth_method),
|
|
||||||
get_vh_by_auth_method(AuthMethod, Hosts, []).
|
|
||||||
|
|
||||||
get_vh_by_auth_method(Method, [Host|Hosts], Result) ->
|
|
||||||
Methods = get_option({auth_method, Host}, []),
|
|
||||||
case lists:member(Method, Methods) of
|
|
||||||
true when Host == global ->
|
|
||||||
get_myhosts();
|
|
||||||
true ->
|
|
||||||
get_vh_by_auth_method(Method, Hosts, [Host|Result]);
|
|
||||||
false ->
|
|
||||||
get_vh_by_auth_method(Method, Hosts, Result)
|
|
||||||
end;
|
|
||||||
get_vh_by_auth_method(_, [], Result) ->
|
|
||||||
Result.
|
|
||||||
|
|
||||||
%% @spec (Path::string()) -> true | false
|
%% @spec (Path::string()) -> true | false
|
||||||
is_file_readable(Path) ->
|
is_file_readable(Path) ->
|
||||||
case file:read_file_info(Path) of
|
case file:read_file_info(Path) of
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
%%%-------------------------------------------------------------------
|
|
||||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%% @doc
|
|
||||||
%%% This is a stub module which will be replaced during
|
|
||||||
%%% configuration load via p1_options:compile/1
|
|
||||||
%%% The only purpose of this file is to shut up xref/dialyzer
|
|
||||||
%%% @end
|
|
||||||
%%% Created : 27 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2018 ProcessOne
|
|
||||||
%%%
|
|
||||||
%%% This program is free software; you can redistribute it and/or
|
|
||||||
%%% modify it under the terms of the GNU General Public License as
|
|
||||||
%%% published by the Free Software Foundation; either version 2 of the
|
|
||||||
%%% License, or (at your option) any later version.
|
|
||||||
%%%
|
|
||||||
%%% This program is distributed in the hope that it will be useful,
|
|
||||||
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
%%% General Public License for more details.
|
|
||||||
%%%
|
|
||||||
%%% You should have received a copy of the GNU General Public License along
|
|
||||||
%%% with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
%%%
|
|
||||||
%%%-------------------------------------------------------------------
|
|
||||||
-module(ejabberd_db_modules).
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([is_known/1, get_scope/1]).
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% API
|
|
||||||
%%%===================================================================
|
|
||||||
is_known(_) ->
|
|
||||||
false.
|
|
||||||
|
|
||||||
get_scope(_) ->
|
|
||||||
[].
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% Internal functions
|
|
||||||
%%%===================================================================
|
|
@ -572,9 +572,16 @@ transform_options({listen, LOpts}, Opts) ->
|
|||||||
transform_options(Opt, Opts) ->
|
transform_options(Opt, Opts) ->
|
||||||
[Opt|Opts].
|
[Opt|Opts].
|
||||||
|
|
||||||
|
known_listen_options(Module) ->
|
||||||
|
try Module:listen_options() of
|
||||||
|
Opts -> [element(1, Opt) || Opt <- Opts]
|
||||||
|
catch _:undef ->
|
||||||
|
Module:listen_opt_type('')
|
||||||
|
end.
|
||||||
|
|
||||||
-spec validate_module_options(module(), [{atom(), any()}]) -> [{atom(), any()}].
|
-spec validate_module_options(module(), [{atom(), any()}]) -> [{atom(), any()}].
|
||||||
validate_module_options(Module, Opts) ->
|
validate_module_options(Module, Opts) ->
|
||||||
try Module:listen_opt_type('') of
|
try known_listen_options(Module) of
|
||||||
_ ->
|
_ ->
|
||||||
maybe_start_zlib(Opts),
|
maybe_start_zlib(Opts),
|
||||||
lists:filtermap(
|
lists:filtermap(
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
%%%-------------------------------------------------------------------
|
|
||||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%% @doc
|
|
||||||
%%% This is a stub module which will be replaced during
|
|
||||||
%%% configuration load via p1_options:compile/1
|
|
||||||
%%% The only purpose of this file is to shut up xref/dialyzer
|
|
||||||
%%% @end
|
|
||||||
%%% Created : 16 Apr 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
|
||||||
%%%
|
|
||||||
%%%
|
|
||||||
%%% ejabberd, Copyright (C) 2002-2018 ProcessOne
|
|
||||||
%%%
|
|
||||||
%%% This program is free software; you can redistribute it and/or
|
|
||||||
%%% modify it under the terms of the GNU General Public License as
|
|
||||||
%%% published by the Free Software Foundation; either version 2 of the
|
|
||||||
%%% License, or (at your option) any later version.
|
|
||||||
%%%
|
|
||||||
%%% This program is distributed in the hope that it will be useful,
|
|
||||||
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
%%% General Public License for more details.
|
|
||||||
%%%
|
|
||||||
%%% You should have received a copy of the GNU General Public License along
|
|
||||||
%%% with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
%%%
|
|
||||||
%%%-------------------------------------------------------------------
|
|
||||||
-module(ejabberd_options).
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([is_known/1, get_scope/1]).
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% API
|
|
||||||
%%%===================================================================
|
|
||||||
is_known(_) ->
|
|
||||||
false.
|
|
||||||
|
|
||||||
get_scope(_) ->
|
|
||||||
[].
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% Internal functions
|
|
||||||
%%%===================================================================
|
|
@ -74,26 +74,20 @@ get_acl_rule([<<"vhosts">>], _) ->
|
|||||||
%% The pages of a vhost are only accesible if the user is admin of that vhost:
|
%% The pages of a vhost are only accesible if the user is admin of that vhost:
|
||||||
get_acl_rule([<<"server">>, VHost | _RPath], Method)
|
get_acl_rule([<<"server">>, VHost | _RPath], Method)
|
||||||
when Method =:= 'GET' orelse Method =:= 'HEAD' ->
|
when Method =:= 'GET' orelse Method =:= 'HEAD' ->
|
||||||
AC = gen_mod:get_module_opt(VHost, ejabberd_web_admin,
|
AC = ejabberd_config:get_option({access, VHost}, configure),
|
||||||
access, configure),
|
ACR = ejabberd_config:get_option({access_readonly, VHost}, webadmin_view),
|
||||||
ACR = gen_mod:get_module_opt(VHost, ejabberd_web_admin,
|
|
||||||
access_readonly, webadmin_view),
|
|
||||||
{VHost, [AC, ACR]};
|
{VHost, [AC, ACR]};
|
||||||
get_acl_rule([<<"server">>, VHost | _RPath], 'POST') ->
|
get_acl_rule([<<"server">>, VHost | _RPath], 'POST') ->
|
||||||
AC = gen_mod:get_module_opt(VHost, ejabberd_web_admin,
|
AC = ejabberd_config:get_option({access, VHost}, configure),
|
||||||
access, configure),
|
|
||||||
{VHost, [AC]};
|
{VHost, [AC]};
|
||||||
%% Default rule: only global admins can access any other random page
|
%% Default rule: only global admins can access any other random page
|
||||||
get_acl_rule(_RPath, Method)
|
get_acl_rule(_RPath, Method)
|
||||||
when Method =:= 'GET' orelse Method =:= 'HEAD' ->
|
when Method =:= 'GET' orelse Method =:= 'HEAD' ->
|
||||||
AC = gen_mod:get_module_opt(global, ejabberd_web_admin,
|
AC = ejabberd_config:get_option(access, configure),
|
||||||
access, configure),
|
ACR = ejabberd_config:get_option(access_readonly, webadmin_view),
|
||||||
ACR = gen_mod:get_module_opt(global, ejabberd_web_admin,
|
|
||||||
access_readonly, webadmin_view),
|
|
||||||
{global, [AC, ACR]};
|
{global, [AC, ACR]};
|
||||||
get_acl_rule(_RPath, 'POST') ->
|
get_acl_rule(_RPath, 'POST') ->
|
||||||
AC = gen_mod:get_module_opt(global, ejabberd_web_admin,
|
AC = ejabberd_config:get_option(access, configure),
|
||||||
access, configure),
|
|
||||||
{global, [AC]}.
|
{global, [AC]}.
|
||||||
|
|
||||||
%%%==================================
|
%%%==================================
|
||||||
@ -1274,7 +1268,7 @@ get_offlinemsg_module(Server) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
get_lastactivity_menuitem_list(Server) ->
|
get_lastactivity_menuitem_list(Server) ->
|
||||||
case gen_mod:db_type(Server, mod_last) of
|
case gen_mod:get_module_opt(Server, mod_last, db_type) of
|
||||||
mnesia -> [{<<"last-activity">>, <<"Last Activity">>}];
|
mnesia -> [{<<"last-activity">>, <<"Last Activity">>}];
|
||||||
_ -> []
|
_ -> []
|
||||||
end.
|
end.
|
||||||
|
@ -1046,8 +1046,6 @@ polish([], Res, Ref) -> {Res, Ref}.
|
|||||||
%%-----------------------------------------------------------------------
|
%%-----------------------------------------------------------------------
|
||||||
connect_bind(S) ->
|
connect_bind(S) ->
|
||||||
Host = next_host(S#eldap.host, S#eldap.hosts),
|
Host = next_host(S#eldap.host, S#eldap.hosts),
|
||||||
?INFO_MSG("LDAP connection on ~s:~p",
|
|
||||||
[Host, S#eldap.port]),
|
|
||||||
Opts = if S#eldap.tls == tls ->
|
Opts = if S#eldap.tls == tls ->
|
||||||
[{packet, asn1}, {active, true}, {keepalive, true},
|
[{packet, asn1}, {active, true}, {keepalive, true},
|
||||||
binary
|
binary
|
||||||
@ -1056,6 +1054,8 @@ connect_bind(S) ->
|
|||||||
[{packet, asn1}, {active, true}, {keepalive, true},
|
[{packet, asn1}, {active, true}, {keepalive, true},
|
||||||
{send_timeout, ?SEND_TIMEOUT}, binary]
|
{send_timeout, ?SEND_TIMEOUT}, binary]
|
||||||
end,
|
end,
|
||||||
|
?DEBUG("Connecting to LDAP server at ~s:~p with options ~p",
|
||||||
|
[Host, S#eldap.port, Opts]),
|
||||||
HostS = binary_to_list(Host),
|
HostS = binary_to_list(Host),
|
||||||
SocketData = case S#eldap.tls of
|
SocketData = case S#eldap.tls of
|
||||||
tls ->
|
tls ->
|
||||||
@ -1080,9 +1080,8 @@ connect_bind(S) ->
|
|||||||
{ok, connecting, NewS#eldap{host = Host}}
|
{ok, connecting, NewS#eldap{host = Host}}
|
||||||
end;
|
end;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?ERROR_MSG("LDAP connection failed:~n** Server: "
|
?ERROR_MSG("LDAP connection to ~s:~b failed: ~s",
|
||||||
"~s:~p~n** Reason: ~p~n** Socket options: ~p",
|
[Host, S#eldap.port, format_error(SockMod, Reason)]),
|
||||||
[Host, S#eldap.port, Reason, Opts]),
|
|
||||||
NewS = close_and_retry(S),
|
NewS = close_and_retry(S),
|
||||||
{ok, connecting, NewS#eldap{host = Host}}
|
{ok, connecting, NewS#eldap{host = Host}}
|
||||||
end.
|
end.
|
||||||
@ -1121,3 +1120,15 @@ bump_id(#eldap{id = Id})
|
|||||||
when Id > (?MAX_TRANSACTION_ID) ->
|
when Id > (?MAX_TRANSACTION_ID) ->
|
||||||
?MIN_TRANSACTION_ID;
|
?MIN_TRANSACTION_ID;
|
||||||
bump_id(#eldap{id = Id}) -> Id + 1.
|
bump_id(#eldap{id = Id}) -> Id + 1.
|
||||||
|
|
||||||
|
format_error(SockMod, Reason) ->
|
||||||
|
Txt = case SockMod of
|
||||||
|
ssl -> ssl:format_error(Reason);
|
||||||
|
gen_tcp -> inet:format_error(Reason)
|
||||||
|
end,
|
||||||
|
case Txt of
|
||||||
|
"unknown POSIX error" ->
|
||||||
|
lists:flatten(io_lib:format("~p", [Reason]));
|
||||||
|
_ ->
|
||||||
|
Txt
|
||||||
|
end.
|
||||||
|
@ -31,7 +31,8 @@
|
|||||||
-export([generate_subfilter/1, find_ldap_attrs/2, check_filter/1,
|
-export([generate_subfilter/1, find_ldap_attrs/2, check_filter/1,
|
||||||
get_ldap_attr/2, get_user_part/2, make_filter/2,
|
get_ldap_attr/2, get_user_part/2, make_filter/2,
|
||||||
get_state/2, case_insensitive_match/2, get_config/2,
|
get_state/2, case_insensitive_match/2, get_config/2,
|
||||||
decode_octet_string/3, uids_domain_subst/2, opt_type/1]).
|
decode_octet_string/3, uids_domain_subst/2, opt_type/1,
|
||||||
|
options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -180,12 +181,16 @@ get_config(Host, Opts) ->
|
|||||||
TLSCertFile = get_opt(ldap_tls_certfile, Host, Opts),
|
TLSCertFile = get_opt(ldap_tls_certfile, Host, Opts),
|
||||||
TLSCAFile = get_opt(ldap_tls_cacertfile, Host, Opts),
|
TLSCAFile = get_opt(ldap_tls_cacertfile, Host, Opts),
|
||||||
TLSDepth = get_opt(ldap_tls_depth, Host, Opts),
|
TLSDepth = get_opt(ldap_tls_depth, Host, Opts),
|
||||||
Port = get_opt(ldap_port, Host, Opts,
|
Port = case get_opt(ldap_port, Host, Opts) of
|
||||||
|
undefined ->
|
||||||
case Encrypt of
|
case Encrypt of
|
||||||
tls -> ?LDAPS_PORT;
|
tls -> ?LDAPS_PORT;
|
||||||
starttls -> ?LDAP_PORT;
|
starttls -> ?LDAP_PORT;
|
||||||
_ -> ?LDAP_PORT
|
_ -> ?LDAP_PORT
|
||||||
end),
|
end;
|
||||||
|
P ->
|
||||||
|
P
|
||||||
|
end,
|
||||||
RootDN = get_opt(ldap_rootdn, Host, Opts, <<"">>),
|
RootDN = get_opt(ldap_rootdn, Host, Opts, <<"">>),
|
||||||
Password = get_opt(ldap_password, Host, Opts, <<"">>),
|
Password = get_opt(ldap_password, Host, Opts, <<"">>),
|
||||||
Base = get_opt(ldap_base, Host, Opts, <<"">>),
|
Base = get_opt(ldap_base, Host, Opts, <<"">>),
|
||||||
@ -348,7 +353,12 @@ collect_parts_bit([],Acc,Uacc) ->
|
|||||||
(ldap_uids) -> fun((uids()) -> uids());
|
(ldap_uids) -> fun((uids()) -> uids());
|
||||||
(atom()) -> [atom()].
|
(atom()) -> [atom()].
|
||||||
opt_type(deref_aliases) ->
|
opt_type(deref_aliases) ->
|
||||||
opt_type(ldap_deref_aliases);
|
fun(unspecified) -> unspecified;
|
||||||
|
(never) -> never;
|
||||||
|
(searching) -> searching;
|
||||||
|
(finding) -> finding;
|
||||||
|
(always) -> always
|
||||||
|
end;
|
||||||
opt_type(ldap_backups) ->
|
opt_type(ldap_backups) ->
|
||||||
fun (L) -> [iolist_to_binary(H) || H <- L] end;
|
fun (L) -> [iolist_to_binary(H) || H <- L] end;
|
||||||
opt_type(ldap_base) -> fun iolist_to_binary/1;
|
opt_type(ldap_base) -> fun iolist_to_binary/1;
|
||||||
@ -365,25 +375,33 @@ opt_type(ldap_encrypt) ->
|
|||||||
end;
|
end;
|
||||||
opt_type(ldap_password) -> fun iolist_to_binary/1;
|
opt_type(ldap_password) -> fun iolist_to_binary/1;
|
||||||
opt_type(ldap_port) ->
|
opt_type(ldap_port) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
fun(undefined) -> undefined;
|
||||||
|
(I) when is_integer(I), I > 0 -> I
|
||||||
|
end;
|
||||||
opt_type(ldap_rootdn) -> fun iolist_to_binary/1;
|
opt_type(ldap_rootdn) -> fun iolist_to_binary/1;
|
||||||
opt_type(ldap_servers) ->
|
opt_type(ldap_servers) ->
|
||||||
fun (L) -> [iolist_to_binary(H) || H <- L] end;
|
fun (L) -> [iolist_to_binary(H) || H <- L] end;
|
||||||
opt_type(ldap_tls_certfile) ->
|
opt_type(ldap_tls_certfile) ->
|
||||||
fun(S) ->
|
fun(undefined) -> undefined;
|
||||||
binary_to_list(ejabberd_pkix:try_certfile(S))
|
(S) -> binary_to_list(ejabberd_pkix:try_certfile(S))
|
||||||
end;
|
end;
|
||||||
opt_type(ldap_tls_cacertfile) ->
|
opt_type(ldap_tls_cacertfile) ->
|
||||||
fun(S) -> binary_to_list(misc:try_read_file(S)) end;
|
fun(undefined) -> undefined;
|
||||||
|
(S) -> binary_to_list(misc:try_read_file(S))
|
||||||
|
end;
|
||||||
opt_type(ldap_tls_depth) ->
|
opt_type(ldap_tls_depth) ->
|
||||||
fun (I) when is_integer(I), I >= 0 -> I end;
|
fun(undefined) -> undefined;
|
||||||
|
(I) when is_integer(I), I >= 0 -> I
|
||||||
|
end;
|
||||||
opt_type(ldap_tls_verify) ->
|
opt_type(ldap_tls_verify) ->
|
||||||
fun (hard) -> hard;
|
fun (hard) -> hard;
|
||||||
(soft) -> soft;
|
(soft) -> soft;
|
||||||
(false) -> false
|
(false) -> false
|
||||||
end;
|
end;
|
||||||
opt_type(ldap_filter) ->
|
opt_type(ldap_filter) ->
|
||||||
fun check_filter/1;
|
fun(<<"">>) -> <<"">>;
|
||||||
|
(F) -> check_filter(F)
|
||||||
|
end;
|
||||||
opt_type(ldap_uids) ->
|
opt_type(ldap_uids) ->
|
||||||
fun (Us) ->
|
fun (Us) ->
|
||||||
lists:map(fun ({U, P}) ->
|
lists:map(fun ({U, P}) ->
|
||||||
@ -399,3 +417,20 @@ opt_type(_) ->
|
|||||||
ldap_port, ldap_rootdn, ldap_servers, ldap_filter,
|
ldap_port, ldap_rootdn, ldap_servers, ldap_filter,
|
||||||
ldap_tls_certfile, ldap_tls_cacertfile, ldap_tls_depth,
|
ldap_tls_certfile, ldap_tls_cacertfile, ldap_tls_depth,
|
||||||
ldap_tls_verify].
|
ldap_tls_verify].
|
||||||
|
|
||||||
|
options(_) ->
|
||||||
|
[{deref_aliases, unspecified},
|
||||||
|
{ldap_backups, []},
|
||||||
|
{ldap_base, <<"">>},
|
||||||
|
{ldap_uids, [{<<"uid">>, <<"%u">>}]},
|
||||||
|
{ldap_deref_aliases, never},
|
||||||
|
{ldap_encrypt, none},
|
||||||
|
{ldap_password, <<"">>},
|
||||||
|
{ldap_port, undefined},
|
||||||
|
{ldap_rootdn, <<"">>},
|
||||||
|
{ldap_servers, [<<"localhost">>]},
|
||||||
|
{ldap_filter, <<"">>},
|
||||||
|
{ldap_tls_certfile, undefined},
|
||||||
|
{ldap_tls_cacertfile, undefined},
|
||||||
|
{ldap_tls_depth, undefined},
|
||||||
|
{ldap_tls_verify, false}].
|
||||||
|
315
src/gen_mod.erl
315
src/gen_mod.erl
@ -34,18 +34,28 @@
|
|||||||
stop_child/1, stop_child/2, config_reloaded/0]).
|
stop_child/1, stop_child/2, config_reloaded/0]).
|
||||||
-export([start_module/2, start_module/3,
|
-export([start_module/2, start_module/3,
|
||||||
stop_module/2, stop_module_keep_config/2,
|
stop_module/2, stop_module_keep_config/2,
|
||||||
get_opt/2, get_opt/3, get_opt_host/3,
|
get_opt/2, get_opt_hosts/2, opt_type/1, is_equal_opt/3,
|
||||||
get_opt_hosts/3, opt_type/1, is_equal_opt/4,
|
get_module_opt/3, get_module_opt_host/3,
|
||||||
get_module_opt/3, get_module_opt/4, get_module_opt_host/3,
|
|
||||||
loaded_modules/1, loaded_modules_with_opts/1,
|
loaded_modules/1, loaded_modules_with_opts/1,
|
||||||
get_hosts/2, get_module_proc/2, is_loaded/2, is_loaded_elsewhere/2,
|
get_hosts/2, get_module_proc/2, is_loaded/2, is_loaded_elsewhere/2,
|
||||||
start_modules/0, start_modules/1, stop_modules/0, stop_modules/1,
|
start_modules/0, start_modules/1, stop_modules/0, stop_modules/1,
|
||||||
db_mod/2, db_mod/3, ram_db_mod/2, ram_db_mod/3,
|
db_mod/2, db_mod/3, ram_db_mod/2, ram_db_mod/3,
|
||||||
db_type/2, db_type/3, ram_db_type/2, ram_db_type/3]).
|
is_db_configured/2]).
|
||||||
|
|
||||||
%% Deprecated functions
|
%% Deprecated functions
|
||||||
-export([get_opt/4, get_module_opt/5]).
|
-export([get_opt/3, get_opt/4, get_module_opt/4, get_module_opt/5,
|
||||||
-deprecated([{get_opt, 4}, {get_module_opt, 5}]).
|
get_opt_host/3, get_opt_hosts/3, db_type/2, db_type/3,
|
||||||
|
ram_db_type/2, ram_db_type/3]).
|
||||||
|
-deprecated([{get_opt, 3},
|
||||||
|
{get_opt, 4},
|
||||||
|
{get_opt_host, 3},
|
||||||
|
{get_opt_hosts, 3},
|
||||||
|
{get_module_opt, 4},
|
||||||
|
{get_module_opt, 5},
|
||||||
|
{db_type, 2},
|
||||||
|
{db_type, 3},
|
||||||
|
{ram_db_type, 2},
|
||||||
|
{ram_db_type, 3}]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -62,9 +72,10 @@
|
|||||||
-callback stop(binary()) -> any().
|
-callback stop(binary()) -> any().
|
||||||
-callback reload(binary(), opts(), opts()) -> ok | {ok, pid()}.
|
-callback reload(binary(), opts(), opts()) -> ok | {ok, pid()}.
|
||||||
-callback mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()].
|
-callback mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()].
|
||||||
|
-callback mod_options(binary()) -> opts().
|
||||||
-callback depends(binary(), opts()) -> [{module(), hard | soft}].
|
-callback depends(binary(), opts()) -> [{module(), hard | soft}].
|
||||||
|
|
||||||
-optional_callbacks([reload/3]).
|
-optional_callbacks([mod_opt_type/1, reload/3]).
|
||||||
|
|
||||||
-export_type([opts/0]).
|
-export_type([opts/0]).
|
||||||
-export_type([db_type/0]).
|
-export_type([db_type/0]).
|
||||||
@ -122,7 +133,7 @@ start_modules() ->
|
|||||||
end, ?MYHOSTS).
|
end, ?MYHOSTS).
|
||||||
|
|
||||||
get_modules_options(Host) ->
|
get_modules_options(Host) ->
|
||||||
ejabberd_config:get_option({modules, Host}, []).
|
sort_modules(Host, ejabberd_config:get_option({modules, Host})).
|
||||||
|
|
||||||
sort_modules(Host, ModOpts) ->
|
sort_modules(Host, ModOpts) ->
|
||||||
G = digraph:new([acyclic]),
|
G = digraph:new([acyclic]),
|
||||||
@ -135,7 +146,7 @@ sort_modules(Host, ModOpts) ->
|
|||||||
case lists:keyfind(DepMod, 1, ModOpts) of
|
case lists:keyfind(DepMod, 1, ModOpts) of
|
||||||
false when Type == hard ->
|
false when Type == hard ->
|
||||||
ErrTxt = io_lib:format(
|
ErrTxt = io_lib:format(
|
||||||
"failed to load module '~s' "
|
"Failed to load module '~s' "
|
||||||
"because it depends on module '~s' "
|
"because it depends on module '~s' "
|
||||||
"which is not found in the config",
|
"which is not found in the config",
|
||||||
[Mod, DepMod]),
|
[Mod, DepMod]),
|
||||||
@ -143,7 +154,7 @@ sort_modules(Host, ModOpts) ->
|
|||||||
digraph:del_vertex(G, Mod),
|
digraph:del_vertex(G, Mod),
|
||||||
maybe_halt_ejabberd(ErrTxt);
|
maybe_halt_ejabberd(ErrTxt);
|
||||||
false when Type == soft ->
|
false when Type == soft ->
|
||||||
?WARNING_MSG("module '~s' is recommended for "
|
?WARNING_MSG("Module '~s' is recommended for "
|
||||||
"module '~s' but is not found in "
|
"module '~s' but is not found in "
|
||||||
"the config",
|
"the config",
|
||||||
[DepMod, Mod]);
|
[DepMod, Mod]);
|
||||||
@ -151,7 +162,7 @@ sort_modules(Host, ModOpts) ->
|
|||||||
digraph:add_vertex(G, DepMod, DepOpts),
|
digraph:add_vertex(G, DepMod, DepOpts),
|
||||||
case digraph:add_edge(G, DepMod, Mod) of
|
case digraph:add_edge(G, DepMod, Mod) of
|
||||||
{error, {bad_edge, Path}} ->
|
{error, {bad_edge, Path}} ->
|
||||||
?WARNING_MSG("cyclic dependency detected "
|
?WARNING_MSG("Cyclic dependency detected "
|
||||||
"between modules: ~p",
|
"between modules: ~p",
|
||||||
[Path]);
|
[Path]);
|
||||||
_ ->
|
_ ->
|
||||||
@ -167,7 +178,7 @@ sort_modules(Host, ModOpts) ->
|
|||||||
-spec start_modules(binary()) -> ok.
|
-spec start_modules(binary()) -> ok.
|
||||||
|
|
||||||
start_modules(Host) ->
|
start_modules(Host) ->
|
||||||
Modules = sort_modules(Host, get_modules_options(Host)),
|
Modules = get_modules_options(Host),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({Module, Opts}) ->
|
fun({Module, Opts}) ->
|
||||||
start_module(Host, Module, Opts)
|
start_module(Host, Module, Opts)
|
||||||
@ -190,12 +201,14 @@ start_module(Host, Module, Opts) ->
|
|||||||
|
|
||||||
-spec start_module(binary(), atom(), opts(), boolean()) -> ok | {ok, pid()}.
|
-spec start_module(binary(), atom(), opts(), boolean()) -> ok | {ok, pid()}.
|
||||||
start_module(Host, Module, Opts0, NeedValidation) ->
|
start_module(Host, Module, Opts0, NeedValidation) ->
|
||||||
?DEBUG("loading ~s at ~s", [Module, Host]),
|
?DEBUG("Loading ~s at ~s", [Module, Host]),
|
||||||
Opts = if NeedValidation ->
|
Res = if NeedValidation ->
|
||||||
validate_opts(Host, Module, Opts0);
|
validate_opts(Host, Module, Opts0);
|
||||||
true ->
|
true ->
|
||||||
Opts0
|
{ok, Opts0}
|
||||||
end,
|
end,
|
||||||
|
case Res of
|
||||||
|
{ok, Opts} ->
|
||||||
store_options(Host, Module, Opts),
|
store_options(Host, Module, Opts),
|
||||||
try case Module:start(Host, Opts) of
|
try case Module:start(Host, Opts) of
|
||||||
ok -> ok;
|
ok -> ok;
|
||||||
@ -212,11 +225,14 @@ start_module(Host, Module, Opts0, NeedValidation) ->
|
|||||||
?CRITICAL_MSG(ErrorText, []),
|
?CRITICAL_MSG(ErrorText, []),
|
||||||
maybe_halt_ejabberd(ErrorText),
|
maybe_halt_ejabberd(ErrorText),
|
||||||
erlang:raise(Class, Reason, erlang:get_stacktrace())
|
erlang:raise(Class, Reason, erlang:get_stacktrace())
|
||||||
|
end;
|
||||||
|
{error, ErrorText} ->
|
||||||
|
maybe_halt_ejabberd(ErrorText)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec reload_modules(binary()) -> ok.
|
-spec reload_modules(binary()) -> ok.
|
||||||
reload_modules(Host) ->
|
reload_modules(Host) ->
|
||||||
NewMods = ejabberd_config:get_option({modules, Host}, []),
|
NewMods = ejabberd_config:get_option({modules, Host}),
|
||||||
OldMods = ets:select(
|
OldMods = ets:select(
|
||||||
ejabberd_modules,
|
ejabberd_modules,
|
||||||
ets:fun2ms(
|
ets:fun2ms(
|
||||||
@ -246,10 +262,12 @@ reload_modules(Host) ->
|
|||||||
case lists:keyfind(Mod, 1, NewMods) of
|
case lists:keyfind(Mod, 1, NewMods) of
|
||||||
{_, NewOpts0} ->
|
{_, NewOpts0} ->
|
||||||
case validate_opts(Host, Mod, NewOpts0) of
|
case validate_opts(Host, Mod, NewOpts0) of
|
||||||
OldOpts ->
|
{ok, OldOpts} ->
|
||||||
ok;
|
ok;
|
||||||
NewOpts ->
|
{ok, NewOpts} ->
|
||||||
reload_module(Host, Mod, NewOpts, OldOpts)
|
reload_module(Host, Mod, NewOpts, OldOpts);
|
||||||
|
{error, _} ->
|
||||||
|
ok
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
@ -260,7 +278,7 @@ reload_modules(Host) ->
|
|||||||
reload_module(Host, Module, NewOpts, OldOpts) ->
|
reload_module(Host, Module, NewOpts, OldOpts) ->
|
||||||
case erlang:function_exported(Module, reload, 3) of
|
case erlang:function_exported(Module, reload, 3) of
|
||||||
true ->
|
true ->
|
||||||
?DEBUG("reloading ~s at ~s", [Module, Host]),
|
?DEBUG("Reloading ~s at ~s", [Module, Host]),
|
||||||
store_options(Host, Module, NewOpts),
|
store_options(Host, Module, NewOpts),
|
||||||
try case Module:reload(Host, NewOpts, OldOpts) of
|
try case Module:reload(Host, NewOpts, OldOpts) of
|
||||||
ok -> ok;
|
ok -> ok;
|
||||||
@ -269,14 +287,14 @@ reload_module(Host, Module, NewOpts, OldOpts) ->
|
|||||||
end
|
end
|
||||||
catch Class:Reason ->
|
catch Class:Reason ->
|
||||||
StackTrace = erlang:get_stacktrace(),
|
StackTrace = erlang:get_stacktrace(),
|
||||||
?CRITICAL_MSG("failed to reload module ~s at ~s:~n"
|
?CRITICAL_MSG("Failed to reload module ~s at ~s:~n"
|
||||||
"** Reason = ~p",
|
"** Reason = ~p",
|
||||||
[Module, Host,
|
[Module, Host,
|
||||||
{Class, {Reason, StackTrace}}]),
|
{Class, {Reason, StackTrace}}]),
|
||||||
erlang:raise(Class, Reason, StackTrace)
|
erlang:raise(Class, Reason, StackTrace)
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
?WARNING_MSG("module ~s doesn't support reloading "
|
?WARNING_MSG("Module ~s doesn't support reloading "
|
||||||
"and will be restarted", [Module]),
|
"and will be restarted", [Module]),
|
||||||
stop_module(Host, Module),
|
stop_module(Host, Module),
|
||||||
start_module(Host, Module, NewOpts, false)
|
start_module(Host, Module, NewOpts, false)
|
||||||
@ -316,7 +334,7 @@ stop_modules() ->
|
|||||||
-spec stop_modules(binary()) -> ok.
|
-spec stop_modules(binary()) -> ok.
|
||||||
|
|
||||||
stop_modules(Host) ->
|
stop_modules(Host) ->
|
||||||
Modules = get_modules_options(Host),
|
Modules = lists:reverse(get_modules_options(Host)),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({Module, _Args}) ->
|
fun({Module, _Args}) ->
|
||||||
stop_module_keep_config(Host, Module)
|
stop_module_keep_config(Host, Module)
|
||||||
@ -325,7 +343,6 @@ stop_modules(Host) ->
|
|||||||
-spec stop_module(binary(), atom()) -> error | {aborted, any()} | {atomic, any()}.
|
-spec stop_module(binary(), atom()) -> error | {aborted, any()} | {atomic, any()}.
|
||||||
|
|
||||||
stop_module(Host, Module) ->
|
stop_module(Host, Module) ->
|
||||||
?DEBUG("stopping ~s at ~s", [Module, Host]),
|
|
||||||
case stop_module_keep_config(Host, Module) of
|
case stop_module_keep_config(Host, Module) of
|
||||||
error -> error;
|
error -> error;
|
||||||
ok -> ok
|
ok -> ok
|
||||||
@ -334,6 +351,7 @@ stop_module(Host, Module) ->
|
|||||||
-spec stop_module_keep_config(binary(), atom()) -> error | ok.
|
-spec stop_module_keep_config(binary(), atom()) -> error | ok.
|
||||||
|
|
||||||
stop_module_keep_config(Host, Module) ->
|
stop_module_keep_config(Host, Module) ->
|
||||||
|
?DEBUG("Stopping ~s at ~s", [Module, Host]),
|
||||||
case catch Module:stop(Host) of
|
case catch Module:stop(Host) of
|
||||||
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), error;
|
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), error;
|
||||||
{wait, ProcList} when is_list(ProcList) ->
|
{wait, ProcList} when is_list(ProcList) ->
|
||||||
@ -367,21 +385,19 @@ wait_for_stop1(MonitorReference) ->
|
|||||||
|
|
||||||
-type check_fun() :: fun((any()) -> any()) | {module(), atom()}.
|
-type check_fun() :: fun((any()) -> any()) | {module(), atom()}.
|
||||||
|
|
||||||
-spec get_opt(atom() | {atom(), binary() | global}, opts()) -> any().
|
-spec get_opt(atom(), opts()) -> any().
|
||||||
get_opt(Opt, Opts) ->
|
get_opt(Opt, Opts) ->
|
||||||
get_opt(Opt, Opts, undefined).
|
case lists:keyfind(Opt, 1, Opts) of
|
||||||
|
{_, Val} -> Val;
|
||||||
|
false ->
|
||||||
|
?DEBUG("Attempt to read unspecified option ~s", [Opt]),
|
||||||
|
undefined
|
||||||
|
end.
|
||||||
|
|
||||||
-spec get_opt(atom() | {atom(), binary()|global}, opts(), check_fun() | any()) -> any().
|
-spec get_opt(atom(), opts(), check_fun() | any()) -> any().
|
||||||
|
|
||||||
get_opt(Opt, Opts, F) when is_function(F) ->
|
get_opt(Opt, Opts, F) when is_function(F) ->
|
||||||
get_opt(Opt, Opts, undefined);
|
get_opt(Opt, Opts, undefined);
|
||||||
get_opt({Opt, Host}, Opts, Default) ->
|
|
||||||
case lists:keyfind(Opt, 1, Opts) of
|
|
||||||
false ->
|
|
||||||
ejabberd_config:get_option({Opt, Host}, Default);
|
|
||||||
{_, Val} ->
|
|
||||||
Val
|
|
||||||
end;
|
|
||||||
get_opt(Opt, Opts, Default) ->
|
get_opt(Opt, Opts, Default) ->
|
||||||
case lists:keyfind(Opt, 1, Opts) of
|
case lists:keyfind(Opt, 1, Opts) of
|
||||||
false ->
|
false ->
|
||||||
@ -442,44 +458,36 @@ get_opt_host(Host, Opts, Default) ->
|
|||||||
Val = get_opt(host, Opts, Default),
|
Val = get_opt(host, Opts, Default),
|
||||||
ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host).
|
ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host).
|
||||||
|
|
||||||
-spec get_opt_hosts(binary(), opts(), binary()) -> [binary()].
|
-spec get_opt_hosts(binary(), opts()) -> [binary()].
|
||||||
|
get_opt_hosts(Host, Opts) ->
|
||||||
|
get_opt_hosts(Host, Opts, undefined).
|
||||||
|
|
||||||
|
-spec get_opt_hosts(binary(), opts(), binary()) -> [binary()].
|
||||||
get_opt_hosts(Host, Opts, Default) ->
|
get_opt_hosts(Host, Opts, Default) ->
|
||||||
Vals = case get_opt(host, Opts, undefined) of
|
Vals = case get_opt(hosts, Opts) of
|
||||||
undefined ->
|
L when L == [] orelse L == undefined ->
|
||||||
case get_opt(hosts, Opts, []) of
|
case get_opt(host, Opts) of
|
||||||
[] -> [Default];
|
undefined -> [Default];
|
||||||
L -> L
|
H -> [H]
|
||||||
end;
|
end;
|
||||||
Val ->
|
L ->
|
||||||
[Val]
|
L
|
||||||
end,
|
end,
|
||||||
[ejabberd_regexp:greplace(V, <<"@HOST@">>, Host) || V <- Vals].
|
[ejabberd_regexp:greplace(V, <<"@HOST@">>, Host) || V <- Vals].
|
||||||
|
|
||||||
-spec get_validators(binary(), module(), opts()) -> dict:dict() | undef.
|
-spec get_validators(binary(), {module(), [module()]}) -> list() | undef.
|
||||||
get_validators(Host, Module, Opts) ->
|
get_validators(Host, {Module, SubMods}) ->
|
||||||
try Module:mod_opt_type('') of
|
Validators =
|
||||||
L ->
|
dict:to_list(
|
||||||
SubMods1 = case lists:member(db_type, L) of
|
|
||||||
true -> [db_mod(Host, Opts, Module)];
|
|
||||||
false -> []
|
|
||||||
end,
|
|
||||||
SubMods2 = case lists:member(ram_db_type, L) of
|
|
||||||
true -> [ram_db_mod(Host, Opts, Module)];
|
|
||||||
false -> []
|
|
||||||
end,
|
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun(Mod, D) ->
|
fun(Mod, D) ->
|
||||||
try Mod:mod_opt_type('') of
|
try list_known_opts(Host, Mod) of
|
||||||
Os ->
|
Os ->
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun({Opt, SubOpt} = O, Acc) ->
|
fun({Opt, SubOpt} = O, Acc) ->
|
||||||
SubF = Mod:mod_opt_type(O),
|
SubF = Mod:mod_opt_type(O),
|
||||||
F = case Mod:mod_opt_type(Opt) of
|
F = try Mod:mod_opt_type(Opt)
|
||||||
F1 when is_function(F1) ->
|
catch _:_ -> fun(X) -> X end
|
||||||
F1;
|
|
||||||
_ ->
|
|
||||||
fun(X) -> X end
|
|
||||||
end,
|
end,
|
||||||
dict:append_list(
|
dict:append_list(
|
||||||
Opt, [F, {SubOpt, [SubF]}], Acc);
|
Opt, [F, {SubOpt, [SubF]}], Acc);
|
||||||
@ -490,77 +498,188 @@ get_validators(Host, Module, Opts) ->
|
|||||||
catch _:undef ->
|
catch _:undef ->
|
||||||
D
|
D
|
||||||
end
|
end
|
||||||
end, dict:new(), [Module|SubMods1 ++ SubMods2])
|
end, dict:new(), [Module|SubMods])),
|
||||||
catch _:undef ->
|
case Validators of
|
||||||
?WARNING_MSG("module '~s' doesn't export mod_opt_type/1",
|
[] ->
|
||||||
[Module]),
|
case have_validators(Module) of
|
||||||
undef
|
false ->
|
||||||
|
?WARNING_MSG("Third-party module '~s' doesn't export "
|
||||||
|
"options validator; consider to upgrade "
|
||||||
|
"the module", [Module]),
|
||||||
|
undef;
|
||||||
|
true ->
|
||||||
|
[]
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
Validators
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec validate_opts(binary(), module(), opts()) -> opts().
|
-spec have_validators(module()) -> boolean().
|
||||||
validate_opts(Host, Module, Opts) ->
|
have_validators(Module) ->
|
||||||
case get_validators(Host, Module, Opts) of
|
erlang:function_exported(Module, mod_options, 1)
|
||||||
|
orelse erlang:function_exported(Module, mod_opt_type, 1).
|
||||||
|
|
||||||
|
-spec validate_opts(binary(), module(), opts()) -> {ok, opts()} | {error, string()}.
|
||||||
|
validate_opts(Host, Module, Opts0) ->
|
||||||
|
SubMods = get_submodules(Host, Module, Opts0),
|
||||||
|
DefaultOpts = lists:flatmap(
|
||||||
|
fun(M) ->
|
||||||
|
try M:mod_options(Host)
|
||||||
|
catch _:undef -> []
|
||||||
|
end
|
||||||
|
end, [Module|SubMods]),
|
||||||
|
Required = lists:filter(fun is_atom/1, DefaultOpts),
|
||||||
|
try
|
||||||
|
Opts = merge_opts(Opts0, DefaultOpts),
|
||||||
|
{ok, case get_validators(Host, {Module, SubMods}) of
|
||||||
undef ->
|
undef ->
|
||||||
Opts;
|
Opts;
|
||||||
Validators ->
|
Validators ->
|
||||||
validate_opts(Host, Module, Opts, dict:to_list(Validators))
|
validate_opts(Host, Module, Opts, Required, Validators)
|
||||||
|
end}
|
||||||
|
catch _:{missing_required_option, Opt} ->
|
||||||
|
ErrTxt = io_lib:format("Module '~s' is missing required option '~s'",
|
||||||
|
[Module, Opt]),
|
||||||
|
?ERROR_MSG(ErrTxt, []),
|
||||||
|
{error, ErrTxt}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
validate_opts(Host, Module, Opts, Validators) when is_list(Opts) ->
|
validate_opts(Host, Module, Opts, Required, Validators) when is_list(Opts) ->
|
||||||
lists:flatmap(
|
lists:flatmap(
|
||||||
fun({Opt, Val}) when is_atom(Opt) ->
|
fun({Opt, Val}) when is_atom(Opt) ->
|
||||||
case lists:keyfind(Opt, 1, Validators) of
|
case lists:keyfind(Opt, 1, Validators) of
|
||||||
{_, L} ->
|
{_, L} ->
|
||||||
case lists:partition(fun is_function/1, L) of
|
case lists:partition(fun is_function/1, L) of
|
||||||
{[VFun|_], []} ->
|
{[VFun|_], []} ->
|
||||||
validate_opt(Module, Opt, Val, VFun);
|
validate_opt(Module, Opt, Val, Required, VFun);
|
||||||
{[VFun|_], SubValidators} ->
|
{[VFun|_], SubValidators} ->
|
||||||
try validate_opts(Host, Module, Val, SubValidators) of
|
try validate_opts(Host, Module, Val, Required, SubValidators) of
|
||||||
SubOpts ->
|
SubOpts ->
|
||||||
validate_opt(Module, Opt, SubOpts, VFun)
|
validate_opt(Module, Opt, SubOpts, Required, VFun)
|
||||||
catch _:bad_option ->
|
catch _:bad_option ->
|
||||||
?ERROR_MSG("ignoring invalid value '~p' for "
|
?ERROR_MSG("Ignoring invalid value '~p' for "
|
||||||
"option '~s' of module '~s'",
|
"option '~s' of module '~s'",
|
||||||
[Val, Opt, Module]),
|
[Val, Opt, Module]),
|
||||||
|
fail_if_option_is_required(Opt, Required),
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
case Validators of
|
case Validators of
|
||||||
[] ->
|
[] ->
|
||||||
?ERROR_MSG("unknown option '~s' for module '~s' "
|
?ERROR_MSG("Ignoring unknown option '~s' of '~s':"
|
||||||
"will be likely ignored because the "
|
" the module doesn't have any options",
|
||||||
"module doesn't have any options",
|
|
||||||
[Opt, Module]);
|
[Opt, Module]);
|
||||||
_ ->
|
_ ->
|
||||||
?ERROR_MSG("unknown option '~s' for module '~s' will be"
|
?ERROR_MSG("Ignoring unknown option '~s' of '~s',"
|
||||||
" likely ignored, available options are: ~s",
|
" available options are: ~s",
|
||||||
[Opt, Module,
|
[Opt, Module,
|
||||||
misc:join_atoms([K || {K, _} <- Validators],
|
misc:join_atoms(
|
||||||
|
[K || {K, _} <- Validators],
|
||||||
<<", ">>)])
|
<<", ">>)])
|
||||||
end,
|
end,
|
||||||
[{Opt, Val}]
|
[]
|
||||||
end;
|
end;
|
||||||
(_) ->
|
(_) ->
|
||||||
erlang:error(bad_option)
|
erlang:error(bad_option)
|
||||||
end, Opts);
|
end, Opts);
|
||||||
validate_opts(_, _, _, _) ->
|
validate_opts(_, _, _, _, _) ->
|
||||||
erlang:error(bad_option).
|
erlang:error(bad_option).
|
||||||
|
|
||||||
-spec validate_opt(module(), atom(), any(),
|
-spec validate_opt(module(), atom(), any(), [atom()],
|
||||||
[{atom(), check_fun(), any()}]) -> [{atom(), any()}].
|
[{atom(), check_fun(), any()}]) -> [{atom(), any()}].
|
||||||
validate_opt(Module, Opt, Val, VFun) ->
|
validate_opt(Module, Opt, Val, Required, VFun) ->
|
||||||
try VFun(Val) of
|
try VFun(Val) of
|
||||||
NewVal -> [{Opt, NewVal}]
|
NewVal -> [{Opt, NewVal}]
|
||||||
catch {invalid_syntax, Error} ->
|
catch {invalid_syntax, Error} ->
|
||||||
?ERROR_MSG("ignoring invalid value '~p' for "
|
?ERROR_MSG("Ignoring invalid value '~p' for "
|
||||||
"option '~s' of module '~s': ~s",
|
"option '~s' of module '~s': ~s",
|
||||||
[Val, Opt, Module, Error]),
|
[Val, Opt, Module, Error]),
|
||||||
|
fail_if_option_is_required(Opt, Required),
|
||||||
[];
|
[];
|
||||||
_:_ ->
|
_:_ ->
|
||||||
?ERROR_MSG("ignoring invalid value '~p' for "
|
?ERROR_MSG("Ignoring invalid value '~p' for "
|
||||||
"option '~s' of module '~s'",
|
"option '~s' of module '~s'",
|
||||||
[Val, Opt, Module]),
|
[Val, Opt, Module]),
|
||||||
|
fail_if_option_is_required(Opt, Required),
|
||||||
|
[]
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec fail_if_option_is_required(atom(), [atom()]) -> ok | no_return().
|
||||||
|
fail_if_option_is_required(Opt, Required) ->
|
||||||
|
case lists:member(Opt, Required) of
|
||||||
|
true -> erlang:error({missing_required_option, Opt});
|
||||||
|
false -> ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec list_known_opts(binary(), module()) -> [atom() | {atom(), atom()}].
|
||||||
|
list_known_opts(Host, Module) ->
|
||||||
|
try Module:mod_options(Host) of
|
||||||
|
DefaultOpts ->
|
||||||
|
lists:flatmap(
|
||||||
|
fun({Opt, [{A, _}|_] = Vals}) when is_atom(A) ->
|
||||||
|
[{Opt, Val} || {Val, _} <- Vals];
|
||||||
|
({Opt, _}) -> [Opt];
|
||||||
|
(Opt) -> [Opt]
|
||||||
|
end, DefaultOpts)
|
||||||
|
catch _:undef ->
|
||||||
|
Module:mod_opt_type('')
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec merge_opts(opts(), opts()) -> opts().
|
||||||
|
merge_opts(Opts, DefaultOpts) ->
|
||||||
|
Result =
|
||||||
|
lists:foldr(
|
||||||
|
fun({Opt, Default}, Acc) ->
|
||||||
|
case lists:keyfind(Opt, 1, Opts) of
|
||||||
|
{_, Val} ->
|
||||||
|
case Default of
|
||||||
|
[{A, _}|_] when is_atom(A) andalso is_list(Val) ->
|
||||||
|
[{Opt, merge_opts(Val, Default)}|Acc];
|
||||||
|
Val ->
|
||||||
|
[{Opt, Default}|Acc];
|
||||||
|
_ ->
|
||||||
|
[{Opt, Val}, {Opt, Default}|Acc]
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
[{Opt, Default}|Acc]
|
||||||
|
end;
|
||||||
|
(Opt, Acc) ->
|
||||||
|
case lists:keyfind(Opt, 1, Opts) of
|
||||||
|
{_, Val} ->
|
||||||
|
[{Opt, Val}|Acc];
|
||||||
|
false ->
|
||||||
|
erlang:error({missing_required_option, Opt})
|
||||||
|
end
|
||||||
|
end, [], DefaultOpts),
|
||||||
|
lists:foldl(
|
||||||
|
fun({Opt, Val}, Acc) ->
|
||||||
|
case lists:keymember(Opt, 1, Result) of
|
||||||
|
true -> Acc;
|
||||||
|
false -> [{Opt, Val}|Acc]
|
||||||
|
end
|
||||||
|
end, Result, Opts).
|
||||||
|
|
||||||
|
-spec get_submodules(binary(), module(), opts()) -> [module()].
|
||||||
|
get_submodules(Host, Module, Opts) ->
|
||||||
|
try Module:mod_options(Host) of
|
||||||
|
DefaultOpts ->
|
||||||
|
Mod1 = case lists:keyfind(db_type, 1, DefaultOpts) of
|
||||||
|
{_, T1} ->
|
||||||
|
DBType = proplists:get_value(db_type, Opts, T1),
|
||||||
|
[db_mod(DBType, Module)];
|
||||||
|
false ->
|
||||||
|
[]
|
||||||
|
end,
|
||||||
|
Mod2 = case lists:keyfind(ram_db_type, 1, DefaultOpts) of
|
||||||
|
{_, T2} ->
|
||||||
|
RamDBType = proplists:get_value(ram_db_type, Opts, T2),
|
||||||
|
[ram_db_mod(RamDBType, Module)];
|
||||||
|
false ->
|
||||||
|
[]
|
||||||
|
end,
|
||||||
|
Mod1 ++ Mod2
|
||||||
|
catch _:undef ->
|
||||||
[]
|
[]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -630,6 +749,22 @@ ram_db_mod(Host, Module) when is_binary(Host) orelse Host == global ->
|
|||||||
ram_db_mod(Host, Opts, Module) when is_list(Opts) ->
|
ram_db_mod(Host, Opts, Module) when is_list(Opts) ->
|
||||||
ram_db_mod(ram_db_type(Host, Opts, Module), Module).
|
ram_db_mod(ram_db_type(Host, Opts, Module), Module).
|
||||||
|
|
||||||
|
is_db_configured(Type, Host) ->
|
||||||
|
lists:any(
|
||||||
|
fun(#ejabberd_module{module_host = {_, H}, opts = Opts})
|
||||||
|
when H == Host orelse Host == global ->
|
||||||
|
case lists:keyfind(db_type, 1, Opts) of
|
||||||
|
{_, Type} -> true;
|
||||||
|
_ ->
|
||||||
|
case lists:keyfind(ram_db_type, 1, Opts) of
|
||||||
|
{_, Type} -> true;
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
(_) ->
|
||||||
|
false
|
||||||
|
end, ets:tab2list(ejabberd_modules)).
|
||||||
|
|
||||||
-spec loaded_modules(binary()) -> [atom()].
|
-spec loaded_modules(binary()) -> [atom()].
|
||||||
|
|
||||||
loaded_modules(Host) ->
|
loaded_modules(Host) ->
|
||||||
@ -689,11 +824,11 @@ config_reloaded() ->
|
|||||||
reload_modules(Host)
|
reload_modules(Host)
|
||||||
end, ?MYHOSTS).
|
end, ?MYHOSTS).
|
||||||
|
|
||||||
-spec is_equal_opt(atom(), opts(), opts(), any()) ->
|
-spec is_equal_opt(atom(), opts(), opts()) ->
|
||||||
true | {false, any(), any()}.
|
true | {false, any(), any()}.
|
||||||
is_equal_opt(Opt, NewOpts, OldOpts, Default) ->
|
is_equal_opt(Opt, NewOpts, OldOpts) ->
|
||||||
NewVal = get_opt(Opt, NewOpts, Default),
|
NewVal = get_opt(Opt, NewOpts),
|
||||||
OldVal = get_opt(Opt, OldOpts, Default),
|
OldVal = get_opt(Opt, OldOpts),
|
||||||
if NewVal /= OldVal ->
|
if NewVal /= OldVal ->
|
||||||
{false, NewVal, OldVal};
|
{false, NewVal, OldVal};
|
||||||
true ->
|
true ->
|
||||||
|
@ -35,14 +35,15 @@
|
|||||||
process_sm_iq/1, get_local_commands/5,
|
process_sm_iq/1, get_local_commands/5,
|
||||||
get_local_identity/5, get_local_features/5,
|
get_local_identity/5, get_local_features/5,
|
||||||
get_sm_commands/5, get_sm_identity/5, get_sm_features/5,
|
get_sm_commands/5, get_sm_identity/5, get_sm_features/5,
|
||||||
ping_item/4, ping_command/4, mod_opt_type/1, depends/2]).
|
ping_item/4, ping_command/4, mod_opt_type/1, depends/2,
|
||||||
|
mod_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
?NS_COMMANDS, ?MODULE, process_local_iq,
|
?NS_COMMANDS, ?MODULE, process_local_iq,
|
||||||
IQDisc),
|
IQDisc),
|
||||||
@ -88,7 +89,7 @@ stop(Host) ->
|
|||||||
?NS_COMMANDS).
|
?NS_COMMANDS).
|
||||||
|
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(Host, NewOpts, OldOpts) ->
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_COMMANDS,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_COMMANDS,
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
@ -104,8 +105,7 @@ get_local_commands(Acc, _From,
|
|||||||
#jid{server = Server, lserver = LServer} = _To, <<"">>,
|
#jid{server = Server, lserver = LServer} = _To, <<"">>,
|
||||||
Lang) ->
|
Lang) ->
|
||||||
Display = gen_mod:get_module_opt(LServer, ?MODULE,
|
Display = gen_mod:get_module_opt(LServer, ?MODULE,
|
||||||
report_commands_node,
|
report_commands_node),
|
||||||
false),
|
|
||||||
case Display of
|
case Display of
|
||||||
false -> Acc;
|
false -> Acc;
|
||||||
_ ->
|
_ ->
|
||||||
@ -133,8 +133,7 @@ get_local_commands(Acc, _From, _To, _Node, _Lang) ->
|
|||||||
get_sm_commands(Acc, _From,
|
get_sm_commands(Acc, _From,
|
||||||
#jid{lserver = LServer} = To, <<"">>, Lang) ->
|
#jid{lserver = LServer} = To, <<"">>, Lang) ->
|
||||||
Display = gen_mod:get_module_opt(LServer, ?MODULE,
|
Display = gen_mod:get_module_opt(LServer, ?MODULE,
|
||||||
report_commands_node,
|
report_commands_node),
|
||||||
false),
|
|
||||||
case Display of
|
case Display of
|
||||||
false -> Acc;
|
false -> Acc;
|
||||||
_ ->
|
_ ->
|
||||||
@ -283,5 +282,8 @@ depends(_Host, _Opts) ->
|
|||||||
|
|
||||||
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
||||||
mod_opt_type(report_commands_node) ->
|
mod_opt_type(report_commands_node) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) -> [iqdisc, report_commands_node].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{report_commands_node, false}].
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, mod_opt_type/1,
|
-export([start/2, stop/1, reload/3, mod_options/1,
|
||||||
get_commands_spec/0, depends/2]).
|
get_commands_spec/0, depends/2]).
|
||||||
|
|
||||||
% Commands API
|
% Commands API
|
||||||
@ -846,7 +846,7 @@ get_sha(AccountPass) ->
|
|||||||
|| X <- binary_to_list(crypto:hash(sha, AccountPass))]).
|
|| X <- binary_to_list(crypto:hash(sha, AccountPass))]).
|
||||||
|
|
||||||
num_active_users(Host, Days) ->
|
num_active_users(Host, Days) ->
|
||||||
DB_Type = gen_mod:db_type(Host, mod_last),
|
DB_Type = gen_mod:get_module_opt(Host, mod_last, db_type),
|
||||||
list_last_activity(Host, true, Days, DB_Type).
|
list_last_activity(Host, true, Days, DB_Type).
|
||||||
|
|
||||||
%% Code based on ejabberd/src/web/ejabberd_web_admin.erl
|
%% Code based on ejabberd/src/web/ejabberd_web_admin.erl
|
||||||
@ -1761,4 +1761,4 @@ is_glob_match(String, <<"!", Glob/binary>>) ->
|
|||||||
is_glob_match(String, Glob) ->
|
is_glob_match(String, Glob) ->
|
||||||
is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
|
is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
|
||||||
|
|
||||||
mod_opt_type(_) -> [].
|
mod_options(_) -> [].
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, mod_opt_type/1,
|
-export([start/2, stop/1, reload/3, mod_options/1,
|
||||||
get_commands_spec/0, depends/2]).
|
get_commands_spec/0, depends/2]).
|
||||||
|
|
||||||
% Commands API
|
% Commands API
|
||||||
@ -362,4 +362,4 @@ sql_query(Host, Query) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
mod_opt_type(_) -> [].
|
mod_options(_) -> [].
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
import_start/2, import/5, announce/1, send_motd/1, disco_identity/5,
|
import_start/2, import/5, announce/1, send_motd/1, disco_identity/5,
|
||||||
disco_features/5, disco_items/5, depends/2,
|
disco_features/5, disco_items/5, depends/2,
|
||||||
send_announcement_to_all/3, announce_commands/4,
|
send_announcement_to_all/3, announce_commands/4,
|
||||||
announce_items/4, mod_opt_type/1, clean_cache/1]).
|
announce_items/4, mod_opt_type/1, mod_options/1, clean_cache/1]).
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
handle_info/2, terminate/2, code_change/3]).
|
handle_info/2, terminate/2, code_change/3]).
|
||||||
-export([announce_all/1,
|
-export([announce_all/1,
|
||||||
@ -834,7 +834,7 @@ send_announcement_to_all(Host, SubjectS, BodyS) ->
|
|||||||
-spec get_access(global | binary()) -> atom().
|
-spec get_access(global | binary()) -> atom().
|
||||||
|
|
||||||
get_access(Host) ->
|
get_access(Host) ->
|
||||||
gen_mod:get_module_opt(Host, ?MODULE, access, none).
|
gen_mod:get_module_opt(Host, ?MODULE, access).
|
||||||
|
|
||||||
-spec add_store_hint(stanza()) -> stanza().
|
-spec add_store_hint(stanza()) -> stanza().
|
||||||
add_store_hint(El) ->
|
add_store_hint(El) ->
|
||||||
@ -850,23 +850,17 @@ route_forbidden_error(Packet) ->
|
|||||||
init_cache(Mod, Host, Opts) ->
|
init_cache(Mod, Host, Opts) ->
|
||||||
case use_cache(Mod, Host) of
|
case use_cache(Mod, Host) of
|
||||||
true ->
|
true ->
|
||||||
CacheOpts = cache_opts(Host, Opts),
|
CacheOpts = cache_opts(Opts),
|
||||||
ets_cache:new(?MOTD_CACHE, CacheOpts);
|
ets_cache:new(?MOTD_CACHE, CacheOpts);
|
||||||
false ->
|
false ->
|
||||||
ets_cache:delete(?MOTD_CACHE)
|
ets_cache:delete(?MOTD_CACHE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -876,10 +870,7 @@ cache_opts(Host, Opts) ->
|
|||||||
use_cache(Mod, Host) ->
|
use_cache(Mod, Host) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 1) of
|
case erlang:function_exported(Mod, use_cache, 1) of
|
||||||
true -> Mod:use_cache(Host);
|
true -> Mod:use_cache(Host);
|
||||||
false ->
|
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
-spec cache_nodes(module(), binary()) -> [node()].
|
||||||
@ -918,7 +909,12 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[access, db_type, cache_life_time, cache_size,
|
mod_options(Host) ->
|
||||||
use_cache, cache_missed].
|
[{access, none},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
%% gen_mod API
|
%% gen_mod API
|
||||||
-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1]).
|
-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1, mod_options/1]).
|
||||||
%% Hooks
|
%% Hooks
|
||||||
-export([pubsub_publish_item/6, vcard_iq_convert/1, vcard_iq_publish/1]).
|
-export([pubsub_publish_item/6, vcard_iq_convert/1, vcard_iq_publish/1]).
|
||||||
|
|
||||||
@ -375,7 +375,7 @@ stop_with_error(Lang, Reason) ->
|
|||||||
|
|
||||||
-spec get_converting_rules(binary()) -> convert_rules().
|
-spec get_converting_rules(binary()) -> convert_rules().
|
||||||
get_converting_rules(LServer) ->
|
get_converting_rules(LServer) ->
|
||||||
gen_mod:get_module_opt(LServer, ?MODULE, convert, []).
|
gen_mod:get_module_opt(LServer, ?MODULE, convert).
|
||||||
|
|
||||||
-spec get_type(binary()) -> eimp:img_type() | unknown.
|
-spec get_type(binary()) -> eimp:img_type() | unknown.
|
||||||
get_type(Data) ->
|
get_type(Data) ->
|
||||||
@ -429,11 +429,13 @@ mod_opt_type({convert, From}) ->
|
|||||||
false ->
|
false ->
|
||||||
fail(From);
|
fail(From);
|
||||||
true ->
|
true ->
|
||||||
case eimp:is_supported(To) of
|
case eimp:is_supported(To) orelse To == undefined of
|
||||||
false -> fail(To);
|
false -> fail(To);
|
||||||
true -> To
|
true -> To
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[{convert, T} || T <- [default|eimp:supported_formats()]].
|
mod_options(_) ->
|
||||||
|
[{convert,
|
||||||
|
[{T, undefined} || T <- [default|eimp:supported_formats()]]}].
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start/2, stop/1, reload/3,
|
-export([start/2, stop/1, reload/3,
|
||||||
depends/2, mod_opt_type/1]).
|
depends/2, mod_opt_type/1, mod_options/1]).
|
||||||
|
|
||||||
-export([filter_packet/1, filter_offline_msg/1]).
|
-export([filter_packet/1, filter_offline_msg/1]).
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ filter_offline_msg({_Action, #message{} = Msg} = Acc) ->
|
|||||||
check_message(#message{from = From, to = To, lang = Lang} = Msg) ->
|
check_message(#message{from = From, to = To, lang = Lang} = Msg) ->
|
||||||
LServer = To#jid.lserver,
|
LServer = To#jid.lserver,
|
||||||
AllowLocalUsers =
|
AllowLocalUsers =
|
||||||
gen_mod:get_module_opt(LServer, ?MODULE, allow_local_users, true),
|
gen_mod:get_module_opt(LServer, ?MODULE, allow_local_users),
|
||||||
case (Msg#message.body == [] andalso
|
case (Msg#message.body == [] andalso
|
||||||
Msg#message.subject == [])
|
Msg#message.subject == [])
|
||||||
orelse ((AllowLocalUsers orelse From#jid.luser == <<"">>) andalso
|
orelse ((AllowLocalUsers orelse From#jid.luser == <<"">>) andalso
|
||||||
@ -90,8 +90,8 @@ check_message(#message{from = From, to = To, lang = Lang} = Msg) ->
|
|||||||
false ->
|
false ->
|
||||||
case check_subscription(From, To) of
|
case check_subscription(From, To) of
|
||||||
none ->
|
none ->
|
||||||
Drop = gen_mod:get_module_opt(LServer, ?MODULE, drop, true),
|
Drop = gen_mod:get_module_opt(LServer, ?MODULE, drop),
|
||||||
Log = gen_mod:get_module_opt(LServer, ?MODULE, log, false),
|
Log = gen_mod:get_module_opt(LServer, ?MODULE, log),
|
||||||
if
|
if
|
||||||
Log ->
|
Log ->
|
||||||
?INFO_MSG("~s message from stranger ~s to ~s",
|
?INFO_MSG("~s message from stranger ~s to ~s",
|
||||||
@ -129,7 +129,7 @@ check_subscription(From, To) ->
|
|||||||
none;
|
none;
|
||||||
{none, _} ->
|
{none, _} ->
|
||||||
case gen_mod:get_module_opt(LocalServer, ?MODULE,
|
case gen_mod:get_module_opt(LocalServer, ?MODULE,
|
||||||
allow_transports, true) of
|
allow_transports) of
|
||||||
true ->
|
true ->
|
||||||
%% Check if the contact's server is in the roster
|
%% Check if the contact's server is in the roster
|
||||||
case ejabberd_hooks:run_fold(
|
case ejabberd_hooks:run_fold(
|
||||||
@ -182,5 +182,10 @@ mod_opt_type(log) ->
|
|||||||
mod_opt_type(allow_local_users) ->
|
mod_opt_type(allow_local_users) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(allow_transports) ->
|
mod_opt_type(allow_transports) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) -> [drop, log, allow_local_users, allow_transports].
|
|
||||||
|
mod_options(_) ->
|
||||||
|
[{drop, true},
|
||||||
|
{log, false},
|
||||||
|
{allow_local_users, true},
|
||||||
|
{allow_transports, true}].
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
-protocol({xep, 191, '1.2'}).
|
-protocol({xep, 191, '1.2'}).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, process_iq/1, mod_opt_type/1, depends/2,
|
-export([start/2, stop/1, reload/3, process_iq/1, mod_opt_type/1, depends/2,
|
||||||
disco_features/5]).
|
disco_features/5, mod_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -40,7 +40,7 @@
|
|||||||
-include("mod_privacy.hrl").
|
-include("mod_privacy.hrl").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50),
|
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
||||||
?NS_BLOCKING, ?MODULE, process_iq, IQDisc).
|
?NS_BLOCKING, ?MODULE, process_iq, IQDisc).
|
||||||
@ -50,7 +50,7 @@ stop(Host) ->
|
|||||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING).
|
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING).
|
||||||
|
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(Host, NewOpts, OldOpts) ->
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING,
|
||||||
?MODULE, process_iq, IQDisc);
|
?MODULE, process_iq, IQDisc);
|
||||||
@ -267,5 +267,7 @@ err_db_failure(#iq{lang = Lang} = IQ) ->
|
|||||||
Txt = <<"Database failure">>,
|
Txt = <<"Database failure">>,
|
||||||
xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang)).
|
xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang)).
|
||||||
|
|
||||||
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
|
||||||
mod_opt_type(_) -> [iqdisc].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)}].
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
-export([start/2, stop/1, reload/3, process/2, open_session/2,
|
-export([start/2, stop/1, reload/3, process/2, open_session/2,
|
||||||
close_session/1, find_session/1, clean_cache/1]).
|
close_session/1, find_session/1, clean_cache/1]).
|
||||||
|
|
||||||
-export([depends/2, mod_opt_type/1]).
|
-export([depends/2, mod_opt_type/1, mod_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -144,7 +144,7 @@ reload(_Host, NewOpts, _OldOpts) ->
|
|||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
start_jiffy(Opts) ->
|
start_jiffy(Opts) ->
|
||||||
case gen_mod:get_opt(json, Opts, false) of
|
case gen_mod:get_opt(json, Opts) of
|
||||||
false ->
|
false ->
|
||||||
ok;
|
ok;
|
||||||
true ->
|
true ->
|
||||||
@ -194,10 +194,20 @@ mod_opt_type(O) when O == cache_size; O == cache_life_time ->
|
|||||||
fun(I) when is_integer(I), I>0 -> I;
|
fun(I) when is_integer(I), I>0 -> I;
|
||||||
(unlimited) -> infinity;
|
(unlimited) -> infinity;
|
||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[json, max_concat, max_inactivity, max_pause, prebind, ram_db_type,
|
mod_options(Host) ->
|
||||||
queue_type, use_cache, cache_size, cache_missed, cache_life_time].
|
[{json, false},
|
||||||
|
{max_concat, unlimited},
|
||||||
|
{max_inactivity, 30},
|
||||||
|
{max_pause, 120},
|
||||||
|
{prebind, false},
|
||||||
|
{ram_db_type, ejabberd_config:default_ram_db(Host, ?MODULE)},
|
||||||
|
{queue_type, ejabberd_config:default_queue_type(Host)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% Cache stuff
|
%%% Cache stuff
|
||||||
@ -215,10 +225,7 @@ init_cache(Mod) ->
|
|||||||
use_cache(Mod) ->
|
use_cache(Mod) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 0) of
|
case erlang:function_exported(Mod, use_cache, 0) of
|
||||||
true -> Mod:use_cache();
|
true -> Mod:use_cache();
|
||||||
false ->
|
false -> gen_mod:get_module_opt(global, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
global, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(global))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module()) -> [node()].
|
-spec cache_nodes(module()) -> [node()].
|
||||||
@ -239,15 +246,9 @@ delete_cache(Mod, SID) ->
|
|||||||
|
|
||||||
-spec cache_opts() -> [proplists:property()].
|
-spec cache_opts() -> [proplists:property()].
|
||||||
cache_opts() ->
|
cache_opts() ->
|
||||||
MaxSize = gen_mod:get_module_opt(
|
MaxSize = gen_mod:get_module_opt(global, ?MODULE, cache_size),
|
||||||
global, ?MODULE, cache_size,
|
CacheMissed = gen_mod:get_module_opt(global, ?MODULE, cache_missed),
|
||||||
ejabberd_config:cache_size(global)),
|
LifeTime = case gen_mod:get_module_opt(global, ?MODULE, cache_life_time) of
|
||||||
CacheMissed = gen_mod:get_module_opt(
|
|
||||||
global, ?MODULE, cache_missed,
|
|
||||||
ejabberd_config:cache_missed(global)),
|
|
||||||
LifeTime = case gen_mod:get_module_opt(
|
|
||||||
global, ?MODULE, cache_life_time,
|
|
||||||
ejabberd_config:cache_life_time(global)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
handle_cast/2, terminate/2, code_change/3]).
|
handle_cast/2, terminate/2, code_change/3]).
|
||||||
|
|
||||||
-export([user_send_packet/1, user_receive_packet/1,
|
-export([user_send_packet/1, user_receive_packet/1,
|
||||||
c2s_presence_in/2, mod_opt_type/1]).
|
c2s_presence_in/2, mod_opt_type/1, mod_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -250,16 +250,14 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
case gen_mod:is_equal_opt(cache_size, NewOpts, OldOpts,
|
case gen_mod:is_equal_opt(cache_size, NewOpts, OldOpts) of
|
||||||
ejabberd_config:cache_size(Host)) of
|
|
||||||
{false, MaxSize, _} ->
|
{false, MaxSize, _} ->
|
||||||
ets_cache:setopts(caps_features_cache, [{max_size, MaxSize}]),
|
ets_cache:setopts(caps_features_cache, [{max_size, MaxSize}]),
|
||||||
ets_cache:setopts(caps_requests_cache, [{max_size, MaxSize}]);
|
ets_cache:setopts(caps_requests_cache, [{max_size, MaxSize}]);
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
case gen_mod:is_equal_opt(cache_life_time, NewOpts, OldOpts,
|
case gen_mod:is_equal_opt(cache_life_time, NewOpts, OldOpts) of
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
{false, Time, _} ->
|
{false, Time, _} ->
|
||||||
LifeTime = case Time of
|
LifeTime = case Time of
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
@ -273,7 +271,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
init([Host, Opts]) ->
|
init([Host, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
init_cache(Host, Opts),
|
init_cache(Opts),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
ejabberd_hooks:add(c2s_presence_in, Host, ?MODULE,
|
ejabberd_hooks:add(c2s_presence_in, Host, ?MODULE,
|
||||||
c2s_presence_in, 75),
|
c2s_presence_in, 75),
|
||||||
@ -478,9 +476,9 @@ is_valid_node(Node) ->
|
|||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
init_cache(Host, Opts) ->
|
init_cache(Opts) ->
|
||||||
CacheOpts = cache_opts(Host, Opts),
|
CacheOpts = cache_opts(Opts),
|
||||||
case use_cache(Host, Opts) of
|
case use_cache(Opts) of
|
||||||
true ->
|
true ->
|
||||||
ets_cache:new(caps_features_cache, CacheOpts);
|
ets_cache:new(caps_features_cache, CacheOpts);
|
||||||
false ->
|
false ->
|
||||||
@ -491,16 +489,13 @@ init_cache(Host, Opts) ->
|
|||||||
[{max_size, CacheSize},
|
[{max_size, CacheSize},
|
||||||
{life_time, timer:seconds(?BAD_HASH_LIFETIME)}]).
|
{life_time, timer:seconds(?BAD_HASH_LIFETIME)}]).
|
||||||
|
|
||||||
use_cache(Host, Opts) ->
|
use_cache(Opts) ->
|
||||||
gen_mod:get_opt(use_cache, Opts, ejabberd_config:use_cache(Host)).
|
gen_mod:get_opt(use_cache, Opts).
|
||||||
|
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(cache_size, Opts,
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
CacheMissed = gen_mod:get_opt(cache_missed, Opts,
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -547,6 +542,11 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|||||||
end;
|
end;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
|
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[cache_life_time, cache_size, use_cache, cache_missed, db_type].
|
mod_options(Host) ->
|
||||||
|
[{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
|
|
||||||
-export([user_send_packet/1, user_receive_packet/1,
|
-export([user_send_packet/1, user_receive_packet/1,
|
||||||
iq_handler/1, remove_connection/4, disco_features/5,
|
iq_handler/1, remove_connection/4, disco_features/5,
|
||||||
is_carbon_copy/1, mod_opt_type/1, depends/2, clean_cache/1]).
|
is_carbon_copy/1, mod_opt_type/1, depends/2, clean_cache/1,
|
||||||
|
mod_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -61,7 +62,7 @@ is_carbon_copy(_) ->
|
|||||||
false.
|
false.
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50),
|
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 50),
|
||||||
Mod = gen_mod:ram_db_mod(Host, ?MODULE),
|
Mod = gen_mod:ram_db_mod(Host, ?MODULE),
|
||||||
init_cache(Mod, Host, Opts),
|
init_cache(Mod, Host, Opts),
|
||||||
@ -91,11 +92,11 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
end,
|
end,
|
||||||
case use_cache(NewMod, Host) of
|
case use_cache(NewMod, Host) of
|
||||||
true ->
|
true ->
|
||||||
ets_cache:new(?CARBONCOPY_CACHE, cache_opts(Host, NewOpts));
|
ets_cache:new(?CARBONCOPY_CACHE, cache_opts(NewOpts));
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2,
|
||||||
?MODULE, iq_handler, IQDisc);
|
?MODULE, iq_handler, IQDisc);
|
||||||
@ -321,22 +322,16 @@ list(User, Server) ->
|
|||||||
init_cache(Mod, Host, Opts) ->
|
init_cache(Mod, Host, Opts) ->
|
||||||
case use_cache(Mod, Host) of
|
case use_cache(Mod, Host) of
|
||||||
true ->
|
true ->
|
||||||
ets_cache:new(?CARBONCOPY_CACHE, cache_opts(Host, Opts));
|
ets_cache:new(?CARBONCOPY_CACHE, cache_opts(Opts));
|
||||||
false ->
|
false ->
|
||||||
ets_cache:delete(?CARBONCOPY_CACHE)
|
ets_cache:delete(?CARBONCOPY_CACHE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -346,10 +341,7 @@ cache_opts(Host, Opts) ->
|
|||||||
use_cache(Mod, Host) ->
|
use_cache(Mod, Host) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 1) of
|
case erlang:function_exported(Mod, use_cache, 1) of
|
||||||
true -> Mod:use_cache(Host);
|
true -> Mod:use_cache(Host);
|
||||||
false ->
|
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
-spec cache_nodes(module(), binary()) -> [node()].
|
||||||
@ -394,6 +386,12 @@ mod_opt_type(O) when O == cache_size; O == cache_life_time ->
|
|||||||
fun(I) when is_integer(I), I>0 -> I;
|
fun(I) when is_integer(I), I>0 -> I;
|
||||||
(unlimited) -> infinity;
|
(unlimited) -> infinity;
|
||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[ram_db_type, iqdisc, use_cache, cache_size, cache_missed, cache_life_time].
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{ram_db_type, ejabberd_config:default_ram_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
-behavior(gen_mod).
|
-behavior(gen_mod).
|
||||||
|
|
||||||
%% gen_mod callbacks.
|
%% gen_mod callbacks.
|
||||||
-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2]).
|
-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2, mod_options/1]).
|
||||||
|
|
||||||
%% ejabberd_hooks callbacks.
|
%% ejabberd_hooks callbacks.
|
||||||
-export([filter_presence/1, filter_chat_states/1,
|
-export([filter_presence/1, filter_chat_states/1,
|
||||||
@ -59,9 +59,9 @@
|
|||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
-spec start(binary(), gen_mod:opts()) -> ok.
|
-spec start(binary(), gen_mod:opts()) -> ok.
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
QueuePresence = gen_mod:get_opt(queue_presence, Opts, true),
|
QueuePresence = gen_mod:get_opt(queue_presence, Opts),
|
||||||
QueueChatStates = gen_mod:get_opt(queue_chat_states, Opts, true),
|
QueueChatStates = gen_mod:get_opt(queue_chat_states, Opts),
|
||||||
QueuePEP = gen_mod:get_opt(queue_pep, Opts, true),
|
QueuePEP = gen_mod:get_opt(queue_pep, Opts),
|
||||||
if QueuePresence; QueueChatStates; QueuePEP ->
|
if QueuePresence; QueueChatStates; QueuePEP ->
|
||||||
register_hooks(Host),
|
register_hooks(Host),
|
||||||
if QueuePresence ->
|
if QueuePresence ->
|
||||||
@ -84,9 +84,9 @@ start(Host, Opts) ->
|
|||||||
|
|
||||||
-spec stop(binary()) -> ok.
|
-spec stop(binary()) -> ok.
|
||||||
stop(Host) ->
|
stop(Host) ->
|
||||||
QueuePresence = gen_mod:get_module_opt(Host, ?MODULE, queue_presence, true),
|
QueuePresence = gen_mod:get_module_opt(Host, ?MODULE, queue_presence),
|
||||||
QueueChatStates = gen_mod:get_module_opt(Host, ?MODULE, queue_chat_states, true),
|
QueueChatStates = gen_mod:get_module_opt(Host, ?MODULE, queue_chat_states),
|
||||||
QueuePEP = gen_mod:get_module_opt(Host, ?MODULE, queue_pep, true),
|
QueuePEP = gen_mod:get_module_opt(Host, ?MODULE, queue_pep),
|
||||||
if QueuePresence; QueueChatStates; QueuePEP ->
|
if QueuePresence; QueueChatStates; QueuePEP ->
|
||||||
unregister_hooks(Host),
|
unregister_hooks(Host),
|
||||||
if QueuePresence ->
|
if QueuePresence ->
|
||||||
@ -109,9 +109,9 @@ stop(Host) ->
|
|||||||
|
|
||||||
-spec reload(binary(), gen_mod:opts(), gen_mod:opts()) -> ok.
|
-spec reload(binary(), gen_mod:opts(), gen_mod:opts()) -> ok.
|
||||||
reload(Host, NewOpts, _OldOpts) ->
|
reload(Host, NewOpts, _OldOpts) ->
|
||||||
QueuePresence = gen_mod:get_opt(queue_presence, NewOpts, true),
|
QueuePresence = gen_mod:get_opt(queue_presence, NewOpts),
|
||||||
QueueChatStates = gen_mod:get_opt(queue_chat_states, NewOpts, true),
|
QueueChatStates = gen_mod:get_opt(queue_chat_states, NewOpts),
|
||||||
QueuePEP = gen_mod:get_opt(queue_pep, NewOpts, true),
|
QueuePEP = gen_mod:get_opt(queue_pep, NewOpts),
|
||||||
if QueuePresence; QueueChatStates; QueuePEP ->
|
if QueuePresence; QueueChatStates; QueuePEP ->
|
||||||
register_hooks(Host);
|
register_hooks(Host);
|
||||||
true ->
|
true ->
|
||||||
@ -145,8 +145,12 @@ mod_opt_type(queue_presence) ->
|
|||||||
mod_opt_type(queue_chat_states) ->
|
mod_opt_type(queue_chat_states) ->
|
||||||
fun(B) when is_boolean(B) -> B end;
|
fun(B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(queue_pep) ->
|
mod_opt_type(queue_pep) ->
|
||||||
fun(B) when is_boolean(B) -> B end;
|
fun(B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) -> [queue_presence, queue_chat_states, queue_pep].
|
|
||||||
|
mod_options(_) ->
|
||||||
|
[{queue_presence, true},
|
||||||
|
{queue_chat_states, true},
|
||||||
|
{queue_pep, true}].
|
||||||
|
|
||||||
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
|
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
|
||||||
depends(_Host, _Opts) ->
|
depends(_Host, _Opts) ->
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
get_local_features/5, get_local_items/5,
|
get_local_features/5, get_local_items/5,
|
||||||
adhoc_local_items/4, adhoc_local_commands/4,
|
adhoc_local_items/4, adhoc_local_commands/4,
|
||||||
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
|
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
|
||||||
adhoc_sm_items/4, adhoc_sm_commands/4, mod_opt_type/1,
|
adhoc_sm_items/4, adhoc_sm_commands/4, mod_options/1,
|
||||||
depends/2]).
|
depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
@ -1809,4 +1809,4 @@ set_sm_form(User, Server, <<"config">>,
|
|||||||
set_sm_form(_User, _Server, _Node, _Request) ->
|
set_sm_form(_User, _Server, _Node, _Request) ->
|
||||||
{error, xmpp:err_service_unavailable()}.
|
{error, xmpp:err_service_unavailable()}.
|
||||||
|
|
||||||
mod_opt_type(_) -> [].
|
mod_options(_) -> [].
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2]).
|
-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2, mod_options/1]).
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
terminate/2, code_change/3]).
|
terminate/2, code_change/3]).
|
||||||
@ -70,9 +70,11 @@ mod_opt_type(namespaces) ->
|
|||||||
Access = proplists:get_value(access, Opts, none),
|
Access = proplists:get_value(access, Opts, none),
|
||||||
{NS, Attrs, Access}
|
{NS, Attrs, Access}
|
||||||
end, L)
|
end, L)
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[namespaces, iqdisc].
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{namespaces, []}].
|
||||||
|
|
||||||
depends(_, _) ->
|
depends(_, _) ->
|
||||||
[].
|
[].
|
||||||
@ -151,7 +153,7 @@ handle_cast({component_connected, Host}, State) ->
|
|||||||
ServerHost = State#state.server_host,
|
ServerHost = State#state.server_host,
|
||||||
To = jid:make(Host),
|
To = jid:make(Host),
|
||||||
NSAttrsAccessList = gen_mod:get_module_opt(
|
NSAttrsAccessList = gen_mod:get_module_opt(
|
||||||
ServerHost, ?MODULE, namespaces, []),
|
ServerHost, ?MODULE, namespaces),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({NS, _Attrs, Access}) ->
|
fun({NS, _Attrs, Access}) ->
|
||||||
case acl:match_rule(ServerHost, Access, To) of
|
case acl:match_rule(ServerHost, Access, To) of
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
get_local_features/5, get_local_services/5,
|
get_local_features/5, get_local_services/5,
|
||||||
process_sm_iq_items/1, process_sm_iq_info/1,
|
process_sm_iq_items/1, process_sm_iq_info/1,
|
||||||
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
|
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
|
||||||
get_info/5, transform_module_options/1, mod_opt_type/1, depends/2]).
|
get_info/5, transform_module_options/1, mod_opt_type/1,
|
||||||
|
mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -50,7 +51,7 @@
|
|||||||
-type items_acc() :: {error, stanza_error()} | {result, [disco_item()]} | empty.
|
-type items_acc() :: {error, stanza_error()} | {result, [disco_item()]} | empty.
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
?NS_DISCO_ITEMS, ?MODULE,
|
?NS_DISCO_ITEMS, ?MODULE,
|
||||||
process_local_iq_items, IQDisc),
|
process_local_iq_items, IQDisc),
|
||||||
@ -66,7 +67,7 @@ start(Host, Opts) ->
|
|||||||
catch ets:new(disco_extra_domains,
|
catch ets:new(disco_extra_domains,
|
||||||
[named_table, ordered_set, public,
|
[named_table, ordered_set, public,
|
||||||
{heir, erlang:group_leader(), none}]),
|
{heir, erlang:group_leader(), none}]),
|
||||||
ExtraDomains = gen_mod:get_opt(extra_domains, Opts, []),
|
ExtraDomains = gen_mod:get_opt(extra_domains, Opts),
|
||||||
lists:foreach(fun (Domain) ->
|
lists:foreach(fun (Domain) ->
|
||||||
register_extra_domain(Host, Domain)
|
register_extra_domain(Host, Domain)
|
||||||
end,
|
end,
|
||||||
@ -115,7 +116,7 @@ stop(Host) ->
|
|||||||
ok.
|
ok.
|
||||||
|
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(Host, NewOpts, OldOpts) ->
|
||||||
case gen_mod:is_equal_opt(extra_domains, NewOpts, OldOpts, []) of
|
case gen_mod:is_equal_opt(extra_domains, NewOpts, OldOpts) of
|
||||||
{false, NewDomains, OldDomains} ->
|
{false, NewDomains, OldDomains} ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Domain) ->
|
fun(Domain) ->
|
||||||
@ -128,7 +129,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
?NS_DISCO_ITEMS, ?MODULE,
|
?NS_DISCO_ITEMS, ?MODULE,
|
||||||
@ -197,7 +198,7 @@ process_local_iq_info(#iq{type = get, lang = Lang,
|
|||||||
binary(), binary()) -> [identity()].
|
binary(), binary()) -> [identity()].
|
||||||
get_local_identity(Acc, _From, To, <<"">>, _Lang) ->
|
get_local_identity(Acc, _From, To, <<"">>, _Lang) ->
|
||||||
Host = To#jid.lserver,
|
Host = To#jid.lserver,
|
||||||
Name = gen_mod:get_module_opt(Host, ?MODULE, name, ?T("ejabberd")),
|
Name = gen_mod:get_module_opt(Host, ?MODULE, name),
|
||||||
Acc ++ [#identity{category = <<"server">>,
|
Acc ++ [#identity{category = <<"server">>,
|
||||||
type = <<"im">>,
|
type = <<"im">>,
|
||||||
name = Name}];
|
name = Name}];
|
||||||
@ -440,7 +441,7 @@ get_info(Acc, _, _, _Node, _) -> Acc.
|
|||||||
|
|
||||||
-spec get_fields(binary(), module()) -> [xdata_field()].
|
-spec get_fields(binary(), module()) -> [xdata_field()].
|
||||||
get_fields(Host, Module) ->
|
get_fields(Host, Module) ->
|
||||||
Fields = gen_mod:get_module_opt(Host, ?MODULE, server_info, []),
|
Fields = gen_mod:get_module_opt(Host, ?MODULE, server_info),
|
||||||
Fields1 = lists:filter(fun ({Modules, _, _}) ->
|
Fields1 = lists:filter(fun ({Modules, _, _}) ->
|
||||||
case Modules of
|
case Modules of
|
||||||
all -> true;
|
all -> true;
|
||||||
@ -468,5 +469,10 @@ mod_opt_type(server_info) ->
|
|||||||
{Mods, Name, URLs}
|
{Mods, Name, URLs}
|
||||||
end,
|
end,
|
||||||
L)
|
L)
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) -> [extra_domains, iqdisc, server_info, name].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{extra_domains, []},
|
||||||
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{server_info, []},
|
||||||
|
{name, ?T("ejabberd")}].
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
handle_info/2, terminate/2, code_change/3,
|
handle_info/2, terminate/2, code_change/3,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, depends/2, mod_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -63,8 +63,10 @@ depends(_Host, _Opts) ->
|
|||||||
|
|
||||||
mod_opt_type(host) -> fun iolist_to_binary/1;
|
mod_opt_type(host) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(hosts) ->
|
mod_opt_type(hosts) ->
|
||||||
fun(L) -> lists:map(fun iolist_to_binary/1, L) end;
|
fun(L) -> lists:map(fun iolist_to_binary/1, L) end.
|
||||||
mod_opt_type(_) -> [host, hosts].
|
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[{host, <<"echo.@HOST@">>}, {hosts, []}].
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
@ -79,8 +81,7 @@ mod_opt_type(_) -> [host, hosts].
|
|||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
init([Host, Opts]) ->
|
init([Host, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
Hosts = gen_mod:get_opt_hosts(Host, Opts,
|
Hosts = gen_mod:get_opt_hosts(Host, Opts),
|
||||||
<<"echo.@HOST@">>),
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(H) ->
|
fun(H) ->
|
||||||
ejabberd_router:register_route(H, Host)
|
ejabberd_router:register_route(H, Host)
|
||||||
@ -106,10 +107,8 @@ handle_call(stop, _From, State) ->
|
|||||||
%% Description: Handling cast messages
|
%% Description: Handling cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
handle_cast({reload, Host, NewOpts, OldOpts}, State) ->
|
handle_cast({reload, Host, NewOpts, OldOpts}, State) ->
|
||||||
NewMyHosts = gen_mod:get_opt_hosts(Host, NewOpts,
|
NewMyHosts = gen_mod:get_opt_hosts(Host, NewOpts),
|
||||||
<<"echo.@HOST@">>),
|
OldMyHosts = gen_mod:get_opt_hosts(Host, OldOpts),
|
||||||
OldMyHosts = gen_mod:get_opt_hosts(Host, OldOpts,
|
|
||||||
<<"echo.@HOST@">>),
|
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(H) ->
|
fun(H) ->
|
||||||
ejabberd_router:unregister_route(H)
|
ejabberd_router:unregister_route(H)
|
||||||
|
@ -34,15 +34,13 @@
|
|||||||
|
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
handle_info/2, terminate/2, code_change/3,
|
handle_info/2, terminate/2, code_change/3,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include_lib("stdlib/include/ms_transform.hrl").
|
-include_lib("stdlib/include/ms_transform.hrl").
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
-define(C2S_AUTH_BAN_LIFETIME, 3600). %% 1 hour
|
|
||||||
-define(C2S_MAX_AUTH_FAILURES, 20).
|
|
||||||
-define(CLEAN_INTERVAL, timer:minutes(10)).
|
-define(CLEAN_INTERVAL, timer:minutes(10)).
|
||||||
|
|
||||||
-record(state, {host = <<"">> :: binary()}).
|
-record(state, {host = <<"">> :: binary()}).
|
||||||
@ -58,11 +56,9 @@ c2s_auth_result(#{ip := {Addr, _}, lserver := LServer} = State, false, _User) ->
|
|||||||
State;
|
State;
|
||||||
false ->
|
false ->
|
||||||
BanLifetime = gen_mod:get_module_opt(
|
BanLifetime = gen_mod:get_module_opt(
|
||||||
LServer, ?MODULE, c2s_auth_ban_lifetime,
|
LServer, ?MODULE, c2s_auth_ban_lifetime),
|
||||||
?C2S_AUTH_BAN_LIFETIME),
|
|
||||||
MaxFailures = gen_mod:get_module_opt(
|
MaxFailures = gen_mod:get_module_opt(
|
||||||
LServer, ?MODULE, c2s_max_auth_failures,
|
LServer, ?MODULE, c2s_max_auth_failures),
|
||||||
?C2S_MAX_AUTH_FAILURES),
|
|
||||||
UnbanTS = p1_time_compat:system_time(seconds) + BanLifetime,
|
UnbanTS = p1_time_compat:system_time(seconds) + BanLifetime,
|
||||||
Attempts = case ets:lookup(failed_auth, Addr) of
|
Attempts = case ets:lookup(failed_auth, Addr) of
|
||||||
[{Addr, N, _, _}] ->
|
[{Addr, N, _, _}] ->
|
||||||
@ -179,7 +175,7 @@ log_and_disconnect(#{ip := {Addr, _}, lang := Lang} = State, Attempts, UnbanTS)
|
|||||||
{stop, ejabberd_c2s:send(State, Err)}.
|
{stop, ejabberd_c2s:send(State, Err)}.
|
||||||
|
|
||||||
is_whitelisted(Host, Addr) ->
|
is_whitelisted(Host, Addr) ->
|
||||||
Access = gen_mod:get_module_opt(Host, ?MODULE, access, none),
|
Access = gen_mod:get_module_opt(Host, ?MODULE, access),
|
||||||
acl:match_rule(Host, Access, Addr) == allow.
|
acl:match_rule(Host, Access, Addr) == allow.
|
||||||
|
|
||||||
seconds_to_now(Secs) ->
|
seconds_to_now(Secs) ->
|
||||||
@ -194,6 +190,9 @@ mod_opt_type(access) ->
|
|||||||
mod_opt_type(c2s_auth_ban_lifetime) ->
|
mod_opt_type(c2s_auth_ban_lifetime) ->
|
||||||
fun (T) when is_integer(T), T > 0 -> T end;
|
fun (T) when is_integer(T), T > 0 -> T end;
|
||||||
mod_opt_type(c2s_max_auth_failures) ->
|
mod_opt_type(c2s_max_auth_failures) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
fun (I) when is_integer(I), I > 0 -> I end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[access, c2s_auth_ban_lifetime, c2s_max_auth_failures].
|
mod_options(_Host) ->
|
||||||
|
[{access, none},
|
||||||
|
{c2s_auth_ban_lifetime, 3600}, %% one hour
|
||||||
|
{c2s_max_auth_failures, 20}].
|
||||||
|
@ -74,7 +74,8 @@
|
|||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, process/2, mod_opt_type/1, depends/2]).
|
-export([start/2, stop/1, reload/3, process/2, mod_opt_type/1, depends/2,
|
||||||
|
mod_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
@ -551,7 +552,7 @@ hide_sensitive_args(NonListArgs) ->
|
|||||||
NonListArgs.
|
NonListArgs.
|
||||||
|
|
||||||
permission_addon() ->
|
permission_addon() ->
|
||||||
Access = gen_mod:get_module_opt(global, ?MODULE, admin_ip_access, none),
|
Access = gen_mod:get_module_opt(global, ?MODULE, admin_ip_access),
|
||||||
Rules = acl:resolve_access(Access, global),
|
Rules = acl:resolve_access(Access, global),
|
||||||
R = case Rules of
|
R = case Rules of
|
||||||
all ->
|
all ->
|
||||||
@ -576,5 +577,5 @@ permission_addon() ->
|
|||||||
end, {1, []}, R),
|
end, {1, []}, R),
|
||||||
Res.
|
Res.
|
||||||
|
|
||||||
mod_opt_type(admin_ip_access) -> fun acl:access_rules_validator/1;
|
mod_opt_type(admin_ip_access) -> fun acl:access_rules_validator/1.
|
||||||
mod_opt_type(_) -> [admin_ip_access].
|
mod_options(_) -> [{admin_ip_access, none}].
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
%% utility for other http modules
|
%% utility for other http modules
|
||||||
-export([content_type/3]).
|
-export([content_type/3]).
|
||||||
|
|
||||||
-export([reopen_log/0, mod_opt_type/1, depends/2]).
|
-export([reopen_log/0, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -69,9 +69,6 @@
|
|||||||
-define(HTTP_ERR_HOST_UNKNOWN,
|
-define(HTTP_ERR_HOST_UNKNOWN,
|
||||||
{-1, 410, [], <<"Host unknown">>}).
|
{-1, 410, [], <<"Host unknown">>}).
|
||||||
|
|
||||||
-define(DEFAULT_CONTENT_TYPE,
|
|
||||||
<<"application/octet-stream">>).
|
|
||||||
|
|
||||||
-define(DEFAULT_CONTENT_TYPES,
|
-define(DEFAULT_CONTENT_TYPES,
|
||||||
[{<<".css">>, <<"text/css">>},
|
[{<<".css">>, <<"text/css">>},
|
||||||
{<<".gif">>, <<"image/gif">>},
|
{<<".gif">>, <<"image/gif">>},
|
||||||
@ -126,24 +123,19 @@ init([Host, Opts]) ->
|
|||||||
|
|
||||||
initialize(Host, Opts) ->
|
initialize(Host, Opts) ->
|
||||||
DocRoot = gen_mod:get_opt(docroot, Opts),
|
DocRoot = gen_mod:get_opt(docroot, Opts),
|
||||||
check_docroot_defined(DocRoot, Host),
|
|
||||||
DRInfo = check_docroot_exists(DocRoot),
|
|
||||||
check_docroot_is_dir(DRInfo, DocRoot),
|
|
||||||
check_docroot_is_readable(DRInfo, DocRoot),
|
|
||||||
AccessLog = gen_mod:get_opt(accesslog, Opts),
|
AccessLog = gen_mod:get_opt(accesslog, Opts),
|
||||||
AccessLogFD = try_open_log(AccessLog, Host),
|
AccessLogFD = try_open_log(AccessLog, Host),
|
||||||
DirectoryIndices = gen_mod:get_opt(directory_indices, Opts, []),
|
DirectoryIndices = gen_mod:get_opt(directory_indices, Opts),
|
||||||
CustomHeaders = gen_mod:get_opt(custom_headers, Opts, []),
|
CustomHeaders = gen_mod:get_opt(custom_headers, Opts),
|
||||||
DefaultContentType = gen_mod:get_opt(default_content_type, Opts,
|
DefaultContentType = gen_mod:get_opt(default_content_type, Opts),
|
||||||
?DEFAULT_CONTENT_TYPE),
|
UserAccess0 = gen_mod:get_opt(must_authenticate_with, Opts),
|
||||||
UserAccess0 = gen_mod:get_opt(must_authenticate_with, Opts, []),
|
|
||||||
UserAccess = case UserAccess0 of
|
UserAccess = case UserAccess0 of
|
||||||
[] -> none;
|
[] -> none;
|
||||||
_ ->
|
_ ->
|
||||||
dict:from_list(UserAccess0)
|
dict:from_list(UserAccess0)
|
||||||
end,
|
end,
|
||||||
ContentTypes = build_list_content_types(
|
ContentTypes = build_list_content_types(
|
||||||
gen_mod:get_opt(content_types, Opts, []),
|
gen_mod:get_opt(content_types, Opts),
|
||||||
?DEFAULT_CONTENT_TYPES),
|
?DEFAULT_CONTENT_TYPES),
|
||||||
?DEBUG("known content types: ~s",
|
?DEBUG("known content types: ~s",
|
||||||
[str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes],
|
[str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes],
|
||||||
@ -173,37 +165,6 @@ build_list_content_types(AdminCTsUnsorted, DefaultCTsUnsorted) ->
|
|||||||
|| {Extension, Value} <- CTsUnfiltered,
|
|| {Extension, Value} <- CTsUnfiltered,
|
||||||
Value /= undefined].
|
Value /= undefined].
|
||||||
|
|
||||||
check_docroot_defined(DocRoot, Host) ->
|
|
||||||
case DocRoot of
|
|
||||||
undefined -> throw({undefined_docroot_option, Host});
|
|
||||||
_ -> ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
check_docroot_exists(DocRoot) ->
|
|
||||||
case filelib:ensure_dir(filename:join(DocRoot, "foo")) of
|
|
||||||
ok ->
|
|
||||||
case file:read_file_info(DocRoot) of
|
|
||||||
{error, Reason} ->
|
|
||||||
throw({error_access_docroot, DocRoot, Reason});
|
|
||||||
{ok, FI} -> FI
|
|
||||||
end;
|
|
||||||
{error, Reason} ->
|
|
||||||
throw({error_access_docroot, DocRoot, Reason})
|
|
||||||
end.
|
|
||||||
|
|
||||||
check_docroot_is_dir(DRInfo, DocRoot) ->
|
|
||||||
case DRInfo#file_info.type of
|
|
||||||
directory -> ok;
|
|
||||||
_ -> throw({docroot_not_directory, DocRoot})
|
|
||||||
end.
|
|
||||||
|
|
||||||
check_docroot_is_readable(DRInfo, DocRoot) ->
|
|
||||||
case DRInfo#file_info.access of
|
|
||||||
read -> ok;
|
|
||||||
read_write -> ok;
|
|
||||||
_ -> throw({docroot_not_readable, DocRoot})
|
|
||||||
end.
|
|
||||||
|
|
||||||
try_open_log(undefined, _Host) ->
|
try_open_log(undefined, _Host) ->
|
||||||
undefined;
|
undefined;
|
||||||
try_open_log(FN, _Host) ->
|
try_open_log(FN, _Host) ->
|
||||||
@ -504,7 +465,10 @@ ip_to_string(Address) when size(Address) == 8 ->
|
|||||||
Parts = lists:map(fun (Int) -> io_lib:format("~.16B", [Int]) end, tuple_to_list(Address)),
|
Parts = lists:map(fun (Int) -> io_lib:format("~.16B", [Int]) end, tuple_to_list(Address)),
|
||||||
string:to_lower(lists:flatten(join(Parts, ":"))).
|
string:to_lower(lists:flatten(join(Parts, ":"))).
|
||||||
|
|
||||||
mod_opt_type(accesslog) -> fun iolist_to_binary/1;
|
mod_opt_type(accesslog) ->
|
||||||
|
fun(undefined) -> undefined;
|
||||||
|
(File) -> iolist_to_binary(File)
|
||||||
|
end;
|
||||||
mod_opt_type(content_types) ->
|
mod_opt_type(content_types) ->
|
||||||
fun(L) when is_list(L) ->
|
fun(L) when is_list(L) ->
|
||||||
lists:map(
|
lists:map(
|
||||||
@ -519,15 +483,32 @@ mod_opt_type(default_content_type) ->
|
|||||||
fun iolist_to_binary/1;
|
fun iolist_to_binary/1;
|
||||||
mod_opt_type(directory_indices) ->
|
mod_opt_type(directory_indices) ->
|
||||||
fun (L) when is_list(L) -> L end;
|
fun (L) when is_list(L) -> L end;
|
||||||
mod_opt_type(docroot) -> fun (A) -> A end;
|
mod_opt_type(docroot) ->
|
||||||
|
fun(S) ->
|
||||||
|
Path = iolist_to_binary(S),
|
||||||
|
case filelib:ensure_dir(filename:join(Path, "foo")) of
|
||||||
|
ok ->
|
||||||
|
Path;
|
||||||
|
{error, Why} ->
|
||||||
|
?ERROR_MSG("Failed to create directory ~s: ~s",
|
||||||
|
[Path, file:format_error(Why)]),
|
||||||
|
erlang:error(badarg)
|
||||||
|
end
|
||||||
|
end;
|
||||||
mod_opt_type(must_authenticate_with) ->
|
mod_opt_type(must_authenticate_with) ->
|
||||||
fun (L) when is_list(L) ->
|
fun (L) when is_list(L) ->
|
||||||
lists:map(fun(UP) when is_binary(UP) ->
|
lists:map(fun(UP) when is_binary(UP) ->
|
||||||
[K, V] = binary:split(UP, <<":">>),
|
[K, V] = binary:split(UP, <<":">>),
|
||||||
{K, V}
|
{K, V}
|
||||||
end, L)
|
end, L)
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[accesslog, content_types, custom_headers,
|
mod_options(_) ->
|
||||||
default_content_type, directory_indices, docroot,
|
[{accesslog, undefined},
|
||||||
must_authenticate_with].
|
{content_types, []},
|
||||||
|
{default_content_type, <<"application/octet-stream">>},
|
||||||
|
{custom_headers, []},
|
||||||
|
{directory_indices, []},
|
||||||
|
{must_authenticate_with, []},
|
||||||
|
%% Required option
|
||||||
|
docroot].
|
||||||
|
@ -66,7 +66,8 @@
|
|||||||
-export([start/2,
|
-export([start/2,
|
||||||
stop/1,
|
stop/1,
|
||||||
depends/2,
|
depends/2,
|
||||||
mod_opt_type/1]).
|
mod_opt_type/1,
|
||||||
|
mod_options/1]).
|
||||||
|
|
||||||
%% gen_server callbacks.
|
%% gen_server callbacks.
|
||||||
-export([init/1,
|
-export([init/1,
|
||||||
@ -126,7 +127,7 @@
|
|||||||
-spec start(binary(), gen_mod:opts()) -> {ok, pid()}.
|
-spec start(binary(), gen_mod:opts()) -> {ok, pid()}.
|
||||||
|
|
||||||
start(ServerHost, Opts) ->
|
start(ServerHost, Opts) ->
|
||||||
case gen_mod:get_opt(rm_on_unregister, Opts, true) of
|
case gen_mod:get_opt(rm_on_unregister, Opts) of
|
||||||
true ->
|
true ->
|
||||||
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE,
|
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE,
|
||||||
remove_user, 50);
|
remove_user, 50);
|
||||||
@ -139,7 +140,7 @@ start(ServerHost, Opts) ->
|
|||||||
-spec stop(binary()) -> ok | {error, any()}.
|
-spec stop(binary()) -> ok | {error, any()}.
|
||||||
|
|
||||||
stop(ServerHost) ->
|
stop(ServerHost) ->
|
||||||
case gen_mod:get_module_opt(ServerHost, ?MODULE, rm_on_unregister, true) of
|
case gen_mod:get_module_opt(ServerHost, ?MODULE, rm_on_unregister) of
|
||||||
true ->
|
true ->
|
||||||
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE,
|
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE,
|
||||||
remove_user, 50);
|
remove_user, 50);
|
||||||
@ -170,9 +171,13 @@ mod_opt_type(jid_in_url) ->
|
|||||||
(node) -> node
|
(node) -> node
|
||||||
end;
|
end;
|
||||||
mod_opt_type(file_mode) ->
|
mod_opt_type(file_mode) ->
|
||||||
fun(Mode) -> ?STR_TO_INT(Mode, 8) end;
|
fun(undefined) -> undefined;
|
||||||
|
(Mode) -> ?STR_TO_INT(Mode, 8)
|
||||||
|
end;
|
||||||
mod_opt_type(dir_mode) ->
|
mod_opt_type(dir_mode) ->
|
||||||
fun(Mode) -> ?STR_TO_INT(Mode, 8) end;
|
fun(undefined) -> undefined;
|
||||||
|
(Mode) -> ?STR_TO_INT(Mode, 8)
|
||||||
|
end;
|
||||||
mod_opt_type(docroot) ->
|
mod_opt_type(docroot) ->
|
||||||
fun iolist_to_binary/1;
|
fun iolist_to_binary/1;
|
||||||
mod_opt_type(put_url) ->
|
mod_opt_type(put_url) ->
|
||||||
@ -181,11 +186,13 @@ mod_opt_type(put_url) ->
|
|||||||
end;
|
end;
|
||||||
mod_opt_type(get_url) ->
|
mod_opt_type(get_url) ->
|
||||||
fun(<<"http://", _/binary>> = URL) -> URL;
|
fun(<<"http://", _/binary>> = URL) -> URL;
|
||||||
(<<"https://", _/binary>> = URL) -> URL
|
(<<"https://", _/binary>> = URL) -> URL;
|
||||||
|
(undefined) -> undefined
|
||||||
end;
|
end;
|
||||||
mod_opt_type(service_url) ->
|
mod_opt_type(service_url) ->
|
||||||
fun(<<"http://", _/binary>> = URL) -> URL;
|
fun(<<"http://", _/binary>> = URL) -> URL;
|
||||||
(<<"https://", _/binary>> = URL) -> URL
|
(<<"https://", _/binary>> = URL) -> URL;
|
||||||
|
(undefined) -> undefined
|
||||||
end;
|
end;
|
||||||
mod_opt_type(custom_headers) ->
|
mod_opt_type(custom_headers) ->
|
||||||
fun(Headers) ->
|
fun(Headers) ->
|
||||||
@ -208,11 +215,25 @@ mod_opt_type(thumbnail) ->
|
|||||||
end;
|
end;
|
||||||
(false) ->
|
(false) ->
|
||||||
false
|
false
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[host, hosts, name, access, max_size, secret_length, jid_in_url, file_mode,
|
mod_options(_Host) ->
|
||||||
dir_mode, docroot, put_url, get_url, service_url, custom_headers,
|
[{host, <<"upload.@HOST@">>},
|
||||||
rm_on_unregister, thumbnail].
|
{hosts, []},
|
||||||
|
{name, ?T("HTTP File Upload")},
|
||||||
|
{access, local},
|
||||||
|
{max_size, 104857600},
|
||||||
|
{secret_length, 40},
|
||||||
|
{jid_in_url, sha1},
|
||||||
|
{file_mode, undefined},
|
||||||
|
{dir_mode, undefined},
|
||||||
|
{docroot, <<"@HOME@/upload">>},
|
||||||
|
{put_url, <<"http://@HOST@:5444">>},
|
||||||
|
{get_url, undefined},
|
||||||
|
{service_url, undefined},
|
||||||
|
{custom_headers, []},
|
||||||
|
{rm_on_unregister, true},
|
||||||
|
{thumbnail, true}].
|
||||||
|
|
||||||
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
|
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
|
||||||
|
|
||||||
@ -227,20 +248,23 @@ depends(_Host, _Opts) ->
|
|||||||
|
|
||||||
init([ServerHost, Opts]) ->
|
init([ServerHost, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"upload.@HOST@">>),
|
Hosts = gen_mod:get_opt_hosts(ServerHost, Opts),
|
||||||
Name = gen_mod:get_opt(name, Opts, ?T("HTTP File Upload")),
|
Name = gen_mod:get_opt(name, Opts),
|
||||||
Access = gen_mod:get_opt(access, Opts, local),
|
Access = gen_mod:get_opt(access, Opts),
|
||||||
MaxSize = gen_mod:get_opt(max_size, Opts, 104857600),
|
MaxSize = gen_mod:get_opt(max_size, Opts),
|
||||||
SecretLength = gen_mod:get_opt(secret_length, Opts, 40),
|
SecretLength = gen_mod:get_opt(secret_length, Opts),
|
||||||
JIDinURL = gen_mod:get_opt(jid_in_url, Opts, sha1),
|
JIDinURL = gen_mod:get_opt(jid_in_url, Opts),
|
||||||
DocRoot = gen_mod:get_opt(docroot, Opts, <<"@HOME@/upload">>),
|
DocRoot = gen_mod:get_opt(docroot, Opts),
|
||||||
FileMode = gen_mod:get_opt(file_mode, Opts),
|
FileMode = gen_mod:get_opt(file_mode, Opts),
|
||||||
DirMode = gen_mod:get_opt(dir_mode, Opts),
|
DirMode = gen_mod:get_opt(dir_mode, Opts),
|
||||||
PutURL = gen_mod:get_opt(put_url, Opts, <<"http://@HOST@:5444">>),
|
PutURL = gen_mod:get_opt(put_url, Opts),
|
||||||
GetURL = gen_mod:get_opt(get_url, Opts, PutURL),
|
GetURL = case gen_mod:get_opt(get_url, Opts) of
|
||||||
|
undefined -> PutURL;
|
||||||
|
URL -> URL
|
||||||
|
end,
|
||||||
ServiceURL = gen_mod:get_opt(service_url, Opts),
|
ServiceURL = gen_mod:get_opt(service_url, Opts),
|
||||||
Thumbnail = gen_mod:get_opt(thumbnail, Opts, true),
|
Thumbnail = gen_mod:get_opt(thumbnail, Opts),
|
||||||
CustomHeaders = gen_mod:get_opt(custom_headers, Opts, []),
|
CustomHeaders = gen_mod:get_opt(custom_headers, Opts),
|
||||||
DocRoot1 = expand_home(str:strip(DocRoot, right, $/)),
|
DocRoot1 = expand_home(str:strip(DocRoot, right, $/)),
|
||||||
DocRoot2 = expand_host(DocRoot1, ServerHost),
|
DocRoot2 = expand_host(DocRoot1, ServerHost),
|
||||||
case DirMode of
|
case DirMode of
|
||||||
@ -463,8 +487,7 @@ process(_LocalPath, #request{method = Method, host = Host, ip = IP}) ->
|
|||||||
-spec get_proc_name(binary(), atom()) -> atom().
|
-spec get_proc_name(binary(), atom()) -> atom().
|
||||||
|
|
||||||
get_proc_name(ServerHost, ModuleName) ->
|
get_proc_name(ServerHost, ModuleName) ->
|
||||||
PutURL = gen_mod:get_module_opt(ServerHost, ?MODULE, put_url,
|
PutURL = gen_mod:get_module_opt(ServerHost, ?MODULE, put_url),
|
||||||
<<"http://@HOST@">>),
|
|
||||||
{ok, {_Scheme, _UserInfo, Host, _Port, Path, _Query}} =
|
{ok, {_Scheme, _UserInfo, Host, _Port, Path, _Query}} =
|
||||||
http_uri:parse(binary_to_list(expand_host(PutURL, ServerHost))),
|
http_uri:parse(binary_to_list(expand_host(PutURL, ServerHost))),
|
||||||
ProcPrefix = list_to_binary(string:strip(Host ++ Path, right, $/)),
|
ProcPrefix = list_to_binary(string:strip(Host ++ Path, right, $/)),
|
||||||
@ -693,7 +716,7 @@ yield_content_type(Type) -> Type.
|
|||||||
-spec iq_disco_info(binary(), binary(), binary(), [xdata()]) -> disco_info().
|
-spec iq_disco_info(binary(), binary(), binary(), [xdata()]) -> disco_info().
|
||||||
|
|
||||||
iq_disco_info(Host, Lang, Name, AddInfo) ->
|
iq_disco_info(Host, Lang, Name, AddInfo) ->
|
||||||
Form = case gen_mod:get_module_opt(Host, ?MODULE, max_size, 104857600) of
|
Form = case gen_mod:get_module_opt(Host, ?MODULE, max_size) of
|
||||||
infinity ->
|
infinity ->
|
||||||
AddInfo;
|
AddInfo;
|
||||||
MaxSize ->
|
MaxSize ->
|
||||||
@ -914,9 +937,8 @@ thumb_el(#media_info{type = T, height = H, width = W}, URI) ->
|
|||||||
|
|
||||||
remove_user(User, Server) ->
|
remove_user(User, Server) ->
|
||||||
ServerHost = jid:nameprep(Server),
|
ServerHost = jid:nameprep(Server),
|
||||||
DocRoot = gen_mod:get_module_opt(ServerHost, ?MODULE, docroot,
|
DocRoot = gen_mod:get_module_opt(ServerHost, ?MODULE, docroot),
|
||||||
<<"@HOME@/upload">>),
|
JIDinURL = gen_mod:get_module_opt(ServerHost, ?MODULE, jid_in_url),
|
||||||
JIDinURL = gen_mod:get_module_opt(ServerHost, ?MODULE, jid_in_url, sha1),
|
|
||||||
DocRoot1 = expand_host(expand_home(DocRoot), ServerHost),
|
DocRoot1 = expand_host(expand_home(DocRoot), ServerHost),
|
||||||
UserStr = make_user_string(jid:make(User, Server), JIDinURL),
|
UserStr = make_user_string(jid:make(User, Server), JIDinURL),
|
||||||
UserDir = str:join([DocRoot1, UserStr], <<$/>>),
|
UserDir = str:join([DocRoot1, UserStr], <<$/>>),
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
-export([start/2,
|
-export([start/2,
|
||||||
stop/1,
|
stop/1,
|
||||||
depends/2,
|
depends/2,
|
||||||
mod_opt_type/1]).
|
mod_opt_type/1,
|
||||||
|
mod_options/1]).
|
||||||
|
|
||||||
%% gen_server callbacks.
|
%% gen_server callbacks.
|
||||||
-export([init/1,
|
-export([init/1,
|
||||||
@ -89,9 +90,12 @@ mod_opt_type(access_hard_quota) ->
|
|||||||
mod_opt_type(max_days) ->
|
mod_opt_type(max_days) ->
|
||||||
fun(I) when is_integer(I), I > 0 -> I;
|
fun(I) when is_integer(I), I > 0 -> I;
|
||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[access_soft_quota, access_hard_quota, max_days].
|
mod_options(_) ->
|
||||||
|
[{access_soft_quota, soft_upload_quota},
|
||||||
|
{access_hard_quota, hard_upload_quota},
|
||||||
|
{max_days, infinity}].
|
||||||
|
|
||||||
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
|
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
|
||||||
|
|
||||||
@ -104,13 +108,10 @@ depends(_Host, _Opts) ->
|
|||||||
|
|
||||||
init([ServerHost, Opts]) ->
|
init([ServerHost, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
AccessSoftQuota = gen_mod:get_opt(access_soft_quota, Opts,
|
AccessSoftQuota = gen_mod:get_opt(access_soft_quota, Opts),
|
||||||
soft_upload_quota),
|
AccessHardQuota = gen_mod:get_opt(access_hard_quota, Opts),
|
||||||
AccessHardQuota = gen_mod:get_opt(access_hard_quota, Opts,
|
MaxDays = gen_mod:get_opt(max_days, Opts),
|
||||||
hard_upload_quota),
|
DocRoot1 = gen_mod:get_module_opt(ServerHost, mod_http_upload, docroot),
|
||||||
MaxDays = gen_mod:get_opt(max_days, Opts, infinity),
|
|
||||||
DocRoot1 = gen_mod:get_module_opt(ServerHost, mod_http_upload, docroot,
|
|
||||||
<<"@HOME@/upload">>),
|
|
||||||
DocRoot2 = mod_http_upload:expand_home(str:strip(DocRoot1, right, $/)),
|
DocRoot2 = mod_http_upload:expand_home(str:strip(DocRoot1, right, $/)),
|
||||||
DocRoot3 = mod_http_upload:expand_host(DocRoot2, ServerHost),
|
DocRoot3 = mod_http_upload:expand_host(DocRoot2, ServerHost),
|
||||||
Timers = if MaxDays == infinity -> [];
|
Timers = if MaxDays == infinity -> [];
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
handle_info/2, terminate/2, code_change/3,
|
handle_info/2, terminate/2, code_change/3,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -47,14 +47,8 @@
|
|||||||
-include("mod_irc.hrl").
|
-include("mod_irc.hrl").
|
||||||
-include("translate.hrl").
|
-include("translate.hrl").
|
||||||
|
|
||||||
-define(DEFAULT_IRC_ENCODING, <<"iso8859-15">>).
|
|
||||||
|
|
||||||
-define(DEFAULT_IRC_PORT, 6667).
|
-define(DEFAULT_IRC_PORT, 6667).
|
||||||
|
|
||||||
-define(DEFAULT_REALNAME, <<"WebIRC-User">>).
|
|
||||||
|
|
||||||
-define(DEFAULT_WEBIRC_PASSWORD, <<"">>).
|
|
||||||
|
|
||||||
-define(POSSIBLE_ENCODINGS,
|
-define(POSSIBLE_ENCODINGS,
|
||||||
[<<"koi8-r">>, <<"iso8859-15">>, <<"iso8859-1">>, <<"iso8859-2">>,
|
[<<"koi8-r">>, <<"iso8859-15">>, <<"iso8859-1">>, <<"iso8859-2">>,
|
||||||
<<"utf-8">>, <<"utf-8+latin-1">>]).
|
<<"utf-8">>, <<"utf-8+latin-1">>]).
|
||||||
@ -100,14 +94,14 @@ depends(_Host, _Opts) ->
|
|||||||
init([Host, Opts]) ->
|
init([Host, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
ejabberd:start_app(iconv),
|
ejabberd:start_app(iconv),
|
||||||
MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"irc.@HOST@">>),
|
MyHosts = gen_mod:get_opt_hosts(Host, Opts),
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
Access = gen_mod:get_opt(access, Opts, all),
|
Access = gen_mod:get_opt(access, Opts),
|
||||||
catch ets:new(irc_connection,
|
catch ets:new(irc_connection,
|
||||||
[named_table, public,
|
[named_table, public,
|
||||||
{keypos, #irc_connection.jid_server_host}]),
|
{keypos, #irc_connection.jid_server_host}]),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(MyHost) ->
|
fun(MyHost) ->
|
||||||
register_hooks(MyHost, IQDisc),
|
register_hooks(MyHost, IQDisc),
|
||||||
@ -136,13 +130,13 @@ handle_call(stop, _From, State) ->
|
|||||||
%% Description: Handling cast messages
|
%% Description: Handling cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
|
handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
|
||||||
NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts, <<"irc.@HOST@">>),
|
NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts),
|
||||||
OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts, <<"irc.@HOST@">>),
|
OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts),
|
||||||
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
|
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts),
|
||||||
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
|
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts),
|
||||||
NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
|
NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
|
||||||
OldMod = gen_mod:db_mod(ServerHost, OldOpts, ?MODULE),
|
OldMod = gen_mod:db_mod(ServerHost, OldOpts, ?MODULE),
|
||||||
Access = gen_mod:get_opt(access, NewOpts, all),
|
Access = gen_mod:get_opt(access, NewOpts),
|
||||||
if NewMod /= OldMod ->
|
if NewMod /= OldMod ->
|
||||||
NewMod:init(ServerHost, NewOpts);
|
NewMod:init(ServerHost, NewOpts);
|
||||||
true ->
|
true ->
|
||||||
@ -166,7 +160,7 @@ handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
|
|||||||
ejabberd_router:unregister_route(OldHost),
|
ejabberd_router:unregister_route(OldHost),
|
||||||
unregister_hooks(OldHost)
|
unregister_hooks(OldHost)
|
||||||
end, OldHosts -- NewHosts),
|
end, OldHosts -- NewHosts),
|
||||||
Access = gen_mod:get_opt(access, NewOpts, all),
|
Access = gen_mod:get_opt(access, NewOpts),
|
||||||
{noreply, State#state{hosts = NewHosts, access = Access}};
|
{noreply, State#state{hosts = NewHosts, access = Access}};
|
||||||
handle_cast(Msg, State) ->
|
handle_cast(Msg, State) ->
|
||||||
?WARNING_MSG("unexpected cast: ~p", [Msg]),
|
?WARNING_MSG("unexpected cast: ~p", [Msg]),
|
||||||
@ -434,7 +428,7 @@ closed_connection(Host, From, Server) ->
|
|||||||
ets:delete(irc_connection, {From, Server, Host}).
|
ets:delete(irc_connection, {From, Server, Host}).
|
||||||
|
|
||||||
iq_disco(ServerHost, <<"">>, Lang) ->
|
iq_disco(ServerHost, <<"">>, Lang) ->
|
||||||
Name = gen_mod:get_module_opt(ServerHost, ?MODULE, name, ?T("IRC Transport")),
|
Name = gen_mod:get_module_opt(ServerHost, ?MODULE, name),
|
||||||
#disco_info{
|
#disco_info{
|
||||||
identities = [#identity{category = <<"conference">>,
|
identities = [#identity{category = <<"conference">>,
|
||||||
type = <<"irc">>,
|
type = <<"irc">>,
|
||||||
@ -595,18 +589,17 @@ get_connection_params(Host, From, IRCServer) ->
|
|||||||
IRCServer).
|
IRCServer).
|
||||||
|
|
||||||
get_default_encoding(ServerHost) ->
|
get_default_encoding(ServerHost) ->
|
||||||
Result = gen_mod:get_module_opt(ServerHost, ?MODULE, default_encoding,
|
Result = gen_mod:get_module_opt(ServerHost, ?MODULE, default_encoding),
|
||||||
?DEFAULT_IRC_ENCODING),
|
|
||||||
?INFO_MSG("The default_encoding configured for "
|
?INFO_MSG("The default_encoding configured for "
|
||||||
"host ~p is: ~p~n",
|
"host ~p is: ~p~n",
|
||||||
[ServerHost, Result]),
|
[ServerHost, Result]),
|
||||||
Result.
|
Result.
|
||||||
|
|
||||||
get_realname(ServerHost) ->
|
get_realname(ServerHost) ->
|
||||||
gen_mod:get_module_opt(ServerHost, ?MODULE, realname, ?DEFAULT_REALNAME).
|
gen_mod:get_module_opt(ServerHost, ?MODULE, realname).
|
||||||
|
|
||||||
get_webirc_password(ServerHost) ->
|
get_webirc_password(ServerHost) ->
|
||||||
gen_mod:get_module_opt(ServerHost, ?MODULE, webirc_password, ?DEFAULT_WEBIRC_PASSWORD).
|
gen_mod:get_module_opt(ServerHost, ?MODULE, webirc_password).
|
||||||
|
|
||||||
get_connection_params(Host, ServerHost, From,
|
get_connection_params(Host, ServerHost, From,
|
||||||
IRCServer) ->
|
IRCServer) ->
|
||||||
@ -993,8 +986,22 @@ mod_opt_type(name) ->
|
|||||||
mod_opt_type(host) -> fun iolist_to_binary/1;
|
mod_opt_type(host) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(hosts) ->
|
mod_opt_type(hosts) ->
|
||||||
fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
|
fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
|
||||||
mod_opt_type(_) ->
|
mod_opt_type(realname) ->
|
||||||
[access, db_type, default_encoding, host, hosts, name].
|
fun iolist_to_binary/1;
|
||||||
|
mod_opt_type(webirc_password) ->
|
||||||
|
fun iolist_to_binary/1;
|
||||||
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
|
||||||
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{access, all},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{default_encoding, <<"iso8859-15">>},
|
||||||
|
{host, <<"irc.@HOST@">>},
|
||||||
|
{hosts, []},
|
||||||
|
{realname, <<"WebIRC-User">>},
|
||||||
|
{webirc_password, <<"">>},
|
||||||
|
{name, ?T("IRC Transport")}].
|
||||||
|
|
||||||
-spec extract_ident(stanza()) -> binary().
|
-spec extract_ident(stanza()) -> binary().
|
||||||
extract_ident(Packet) ->
|
extract_ident(Packet) ->
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
-export([start/2, stop/1, reload/3, process_local_iq/1, export/1,
|
-export([start/2, stop/1, reload/3, process_local_iq/1, export/1,
|
||||||
process_sm_iq/1, on_presence_update/4, import_info/0,
|
process_sm_iq/1, on_presence_update/4, import_info/0,
|
||||||
import/5, import_start/2, store_last_info/4, get_last_info/2,
|
import/5, import_start/2, store_last_info/4, get_last_info/2,
|
||||||
remove_user/2, mod_opt_type/1,
|
remove_user/2, mod_opt_type/1, mod_options/1,
|
||||||
register_user/2, depends/2, privacy_check_packet/4]).
|
register_user/2, depends/2, privacy_check_packet/4]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
@ -59,7 +59,7 @@
|
|||||||
-optional_callbacks([use_cache/1, cache_nodes/1]).
|
-optional_callbacks([use_cache/1, cache_nodes/1]).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
init_cache(Mod, Host, Opts),
|
init_cache(Mod, Host, Opts),
|
||||||
@ -99,7 +99,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
init_cache(NewMod, Host, NewOpts),
|
init_cache(NewMod, Host, NewOpts),
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST,
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
@ -275,23 +275,17 @@ remove_user(User, Server) ->
|
|||||||
init_cache(Mod, Host, Opts) ->
|
init_cache(Mod, Host, Opts) ->
|
||||||
case use_cache(Mod, Host) of
|
case use_cache(Mod, Host) of
|
||||||
true ->
|
true ->
|
||||||
CacheOpts = cache_opts(Host, Opts),
|
CacheOpts = cache_opts(Opts),
|
||||||
ets_cache:new(?LAST_CACHE, CacheOpts);
|
ets_cache:new(?LAST_CACHE, CacheOpts);
|
||||||
false ->
|
false ->
|
||||||
ets_cache:delete(?LAST_CACHE)
|
ets_cache:delete(?LAST_CACHE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -301,10 +295,7 @@ cache_opts(Host, Opts) ->
|
|||||||
use_cache(Mod, Host) ->
|
use_cache(Mod, Host) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 1) of
|
case erlang:function_exported(Mod, use_cache, 1) of
|
||||||
true -> Mod:use_cache(Host);
|
true -> Mod:use_cache(Host);
|
||||||
false ->
|
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
-spec cache_nodes(module(), binary()) -> [node()].
|
||||||
@ -346,6 +337,12 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[db_type, iqdisc, cache_life_time, cache_size, use_cache, cache_missed].
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -45,9 +45,7 @@ init(_Host, _Opts) ->
|
|||||||
use_cache(Host) ->
|
use_cache(Host) ->
|
||||||
case mnesia:table_info(last_activity, storage_type) of
|
case mnesia:table_info(last_activity, storage_type) of
|
||||||
disc_only_copies ->
|
disc_only_copies ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(Host, mod_last, use_cache);
|
||||||
Host, mod_last, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host));
|
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
-protocol({xep, 78, '2.5'}).
|
-protocol({xep, 78, '2.5'}).
|
||||||
|
|
||||||
%% gen_mod API
|
%% gen_mod API
|
||||||
-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1]).
|
-export([start/2, stop/1, reload/3, depends/2, mod_options/1]).
|
||||||
%% hooks
|
%% hooks
|
||||||
-export([c2s_unauthenticated_packet/2, c2s_stream_features/2]).
|
-export([c2s_unauthenticated_packet/2, c2s_stream_features/2]).
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ reload(_Host, _NewOpts, _OldOpts) ->
|
|||||||
depends(_Host, _Opts) ->
|
depends(_Host, _Opts) ->
|
||||||
[].
|
[].
|
||||||
|
|
||||||
mod_opt_type(_) ->
|
mod_options(_) ->
|
||||||
[].
|
[].
|
||||||
|
|
||||||
-spec c2s_unauthenticated_packet(c2s_state(), iq()) ->
|
-spec c2s_unauthenticated_packet(c2s_state(), iq()) ->
|
||||||
|
@ -39,7 +39,8 @@
|
|||||||
disco_sm_features/5, remove_user/2, remove_room/3, mod_opt_type/1,
|
disco_sm_features/5, remove_user/2, remove_room/3, mod_opt_type/1,
|
||||||
muc_process_iq/2, muc_filter_message/3, message_is_archived/3,
|
muc_process_iq/2, muc_filter_message/3, message_is_archived/3,
|
||||||
delete_old_messages/2, get_commands_spec/0, msg_to_el/4,
|
delete_old_messages/2, get_commands_spec/0, msg_to_el/4,
|
||||||
get_room_config/4, set_room_option/3, offline_message/1, export/1]).
|
get_room_config/4, set_room_option/3, offline_message/1, export/1,
|
||||||
|
mod_options/1]).
|
||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -74,7 +75,7 @@
|
|||||||
%%% API
|
%%% API
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
init_cache(Host, Opts),
|
init_cache(Host, Opts),
|
||||||
@ -103,7 +104,7 @@ start(Host, Opts) ->
|
|||||||
get_room_config, 50),
|
get_room_config, 50),
|
||||||
ejabberd_hooks:add(set_room_option, Host, ?MODULE,
|
ejabberd_hooks:add(set_room_option, Host, ?MODULE,
|
||||||
set_room_option, 50),
|
set_room_option, 50),
|
||||||
case gen_mod:get_opt(assume_mam_usage, Opts, false) of
|
case gen_mod:get_opt(assume_mam_usage, Opts) of
|
||||||
true ->
|
true ->
|
||||||
ejabberd_hooks:add(message_is_archived, Host, ?MODULE,
|
ejabberd_hooks:add(message_is_archived, Host, ?MODULE,
|
||||||
message_is_archived, 50);
|
message_is_archived, 50);
|
||||||
@ -117,26 +118,21 @@ use_cache(Host, Opts) ->
|
|||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
case erlang:function_exported(Mod, use_cache, 2) of
|
case erlang:function_exported(Mod, use_cache, 2) of
|
||||||
true -> Mod:use_cache(Host, Opts);
|
true -> Mod:use_cache(Host, Opts);
|
||||||
false ->
|
false -> gen_mod:get_opt(use_cache, Opts)
|
||||||
gen_mod:get_opt(use_cache, Opts,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
init_cache(Host, Opts) ->
|
init_cache(Host, Opts) ->
|
||||||
case use_cache(Host, Opts) of
|
case use_cache(Host, Opts) of
|
||||||
true ->
|
true ->
|
||||||
ets_cache:new(archive_prefs_cache, cache_opts(Host, Opts));
|
ets_cache:new(archive_prefs_cache, cache_opts(Opts));
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(cache_size, Opts,
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
CacheMissed = gen_mod:get_opt(cache_missed, Opts,
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -168,7 +164,7 @@ stop(Host) ->
|
|||||||
get_room_config, 50),
|
get_room_config, 50),
|
||||||
ejabberd_hooks:delete(set_room_option, Host, ?MODULE,
|
ejabberd_hooks:delete(set_room_option, Host, ?MODULE,
|
||||||
set_room_option, 50),
|
set_room_option, 50),
|
||||||
case gen_mod:get_module_opt(Host, ?MODULE, assume_mam_usage, false) of
|
case gen_mod:get_module_opt(Host, ?MODULE, assume_mam_usage) of
|
||||||
true ->
|
true ->
|
||||||
ejabberd_hooks:delete(message_is_archived, Host, ?MODULE,
|
ejabberd_hooks:delete(message_is_archived, Host, ?MODULE,
|
||||||
message_is_archived, 50);
|
message_is_archived, 50);
|
||||||
@ -190,14 +186,14 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
ets_cache:setopts(archive_prefs_cache, cache_opts(Host, NewOpts)),
|
ets_cache:setopts(archive_prefs_cache, cache_opts(NewOpts)),
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
register_iq_handlers(Host, IQDisc);
|
register_iq_handlers(Host, IQDisc);
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
case gen_mod:is_equal_opt(assume_mam_usage, NewOpts, OldOpts, false) of
|
case gen_mod:is_equal_opt(assume_mam_usage, NewOpts, OldOpts) of
|
||||||
{false, true, _} ->
|
{false, true, _} ->
|
||||||
ejabberd_hooks:add(message_is_archived, Host, ?MODULE,
|
ejabberd_hooks:add(message_is_archived, Host, ?MODULE,
|
||||||
message_is_archived, 50);
|
message_is_archived, 50);
|
||||||
@ -463,7 +459,7 @@ disco_sm_features(Acc, _From, _To, _Node, _Lang) ->
|
|||||||
message_is_archived(true, _C2SState, _Pkt) ->
|
message_is_archived(true, _C2SState, _Pkt) ->
|
||||||
true;
|
true;
|
||||||
message_is_archived(false, #{lserver := LServer}, Pkt) ->
|
message_is_archived(false, #{lserver := LServer}, Pkt) ->
|
||||||
case gen_mod:get_module_opt(LServer, ?MODULE, assume_mam_usage, false) of
|
case gen_mod:get_module_opt(LServer, ?MODULE, assume_mam_usage) of
|
||||||
true ->
|
true ->
|
||||||
is_archived(Pkt, LServer);
|
is_archived(Pkt, LServer);
|
||||||
false ->
|
false ->
|
||||||
@ -480,7 +476,7 @@ delete_old_messages(TypeBin, Days) when TypeBin == <<"chat">>;
|
|||||||
DBTypes = lists:usort(
|
DBTypes = lists:usort(
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(Host) ->
|
fun(Host) ->
|
||||||
case gen_mod:db_type(Host, ?MODULE) of
|
case gen_mod:get_module_opt(Host, ?MODULE, db_type) of
|
||||||
sql -> {sql, Host};
|
sql -> {sql, Host};
|
||||||
Other -> {Other, global}
|
Other -> {Other, global}
|
||||||
end
|
end
|
||||||
@ -819,13 +815,13 @@ get_prefs(LUser, LServer) ->
|
|||||||
error ->
|
error ->
|
||||||
ActivateOpt = gen_mod:get_module_opt(
|
ActivateOpt = gen_mod:get_module_opt(
|
||||||
LServer, ?MODULE,
|
LServer, ?MODULE,
|
||||||
request_activates_archiving, false),
|
request_activates_archiving),
|
||||||
case ActivateOpt of
|
case ActivateOpt of
|
||||||
true ->
|
true ->
|
||||||
#archive_prefs{us = {LUser, LServer}, default = never};
|
#archive_prefs{us = {LUser, LServer}, default = never};
|
||||||
false ->
|
false ->
|
||||||
Default = gen_mod:get_module_opt(
|
Default = gen_mod:get_module_opt(
|
||||||
LServer, ?MODULE, default, never),
|
LServer, ?MODULE, default),
|
||||||
#archive_prefs{us = {LUser, LServer}, default = Default}
|
#archive_prefs{us = {LUser, LServer}, default = Default}
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
@ -838,7 +834,7 @@ prefs_el(Default, Always, Never, NS) ->
|
|||||||
|
|
||||||
maybe_activate_mam(LUser, LServer) ->
|
maybe_activate_mam(LUser, LServer) ->
|
||||||
ActivateOpt = gen_mod:get_module_opt(
|
ActivateOpt = gen_mod:get_module_opt(
|
||||||
LServer, ?MODULE, request_activates_archiving, false),
|
LServer, ?MODULE, request_activates_archiving),
|
||||||
case ActivateOpt of
|
case ActivateOpt of
|
||||||
true ->
|
true ->
|
||||||
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
||||||
@ -851,7 +847,7 @@ maybe_activate_mam(LUser, LServer) ->
|
|||||||
ok;
|
ok;
|
||||||
error ->
|
error ->
|
||||||
Default = gen_mod:get_module_opt(
|
Default = gen_mod:get_module_opt(
|
||||||
LServer, ?MODULE, default, never),
|
LServer, ?MODULE, default),
|
||||||
write_prefs(LUser, LServer, LServer, Default, [], [])
|
write_prefs(LUser, LServer, LServer, Default, [], [])
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
@ -1081,7 +1077,15 @@ mod_opt_type(default) ->
|
|||||||
end;
|
end;
|
||||||
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
||||||
mod_opt_type(request_activates_archiving) ->
|
mod_opt_type(request_activates_archiving) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[assume_mam_usage, cache_life_time, cache_size, use_cache, cache_missed,
|
mod_options(Host) ->
|
||||||
db_type, default, iqdisc, request_activates_archiving].
|
[{assume_mam_usage, false},
|
||||||
|
{default, never},
|
||||||
|
{request_activates_archiving, false},
|
||||||
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
-export([start/2, stop/1, mod_opt_type/1, depends/2, reload/3]).
|
-export([start/2, stop/1, mod_opt_type/1, mod_options/1, depends/2, reload/3]).
|
||||||
|
|
||||||
-export([offline_message_hook/1,
|
-export([offline_message_hook/1,
|
||||||
sm_register_connection_hook/3, sm_remove_connection_hook/3,
|
sm_register_connection_hook/3, sm_remove_connection_hook/3,
|
||||||
@ -127,8 +127,8 @@ register_user(_User, Server) ->
|
|||||||
%%====================================================================
|
%%====================================================================
|
||||||
|
|
||||||
push(Host, Probe) ->
|
push(Host, Probe) ->
|
||||||
IP = gen_mod:get_module_opt(Host, ?MODULE, ip, {127,0,0,1}),
|
IP = gen_mod:get_module_opt(Host, ?MODULE, ip),
|
||||||
Port = gen_mod:get_module_opt(Host, ?MODULE, port, 11111),
|
Port = gen_mod:get_module_opt(Host, ?MODULE, port),
|
||||||
send_metrics(Host, Probe, IP, Port).
|
send_metrics(Host, Probe, IP, Port).
|
||||||
|
|
||||||
send_metrics(Host, Probe, Peer, Port) ->
|
send_metrics(Host, Probe, Peer, Port) ->
|
||||||
@ -184,6 +184,7 @@ mod_opt_type(ip) ->
|
|||||||
IP
|
IP
|
||||||
end;
|
end;
|
||||||
mod_opt_type(port) ->
|
mod_opt_type(port) ->
|
||||||
fun(I) when is_integer(I), I>0, I<65536 -> I end;
|
fun(I) when is_integer(I), I>0, I<65536 -> I end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[ip, port].
|
mod_options(_) ->
|
||||||
|
[{ip, <<"127.0.0.1">>}, {port, 11111}].
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
%% API
|
%% API
|
||||||
-export([start/2, stop/1, process_iq/1,
|
-export([start/2, stop/1, process_iq/1,
|
||||||
disco_items/5, disco_identity/5, disco_info/5,
|
disco_items/5, disco_identity/5, disco_info/5,
|
||||||
disco_features/5, mod_opt_type/1, depends/2]).
|
disco_features/5, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
@ -124,8 +124,8 @@ process_iq(#iq{lang = Lang} = IQ) ->
|
|||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
init([ServerHost, Opts]) ->
|
init([ServerHost, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"mix.@HOST@">>),
|
Hosts = gen_mod:get_opt_hosts(ServerHost, Opts),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(ServerHost)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Host) ->
|
fun(Host) ->
|
||||||
ConfigTab = gen_mod:get_module_proc(Host, config),
|
ConfigTab = gen_mod:get_module_proc(Host, config),
|
||||||
@ -319,5 +319,9 @@ depends(_Host, _Opts) ->
|
|||||||
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
||||||
mod_opt_type(host) -> fun iolist_to_binary/1;
|
mod_opt_type(host) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(hosts) ->
|
mod_opt_type(hosts) ->
|
||||||
fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
|
fun (L) -> lists:map(fun iolist_to_binary/1, L) end.
|
||||||
mod_opt_type(_) -> [host, hosts, iqdisc].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{host, <<"mix.@HOST@">>},
|
||||||
|
{hosts, []}].
|
||||||
|
123
src/mod_muc.erl
123
src/mod_muc.erl
@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
handle_info/2, terminate/2, code_change/3,
|
handle_info/2, terminate/2, code_change/3,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -233,7 +233,7 @@ get_online_rooms_by_user(ServerHost, LUser, LServer) ->
|
|||||||
|
|
||||||
init([Host, Opts]) ->
|
init([Host, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
#state{access = Access, hosts = MyHosts,
|
#state{access = Access, hosts = MyHosts,
|
||||||
history_size = HistorySize, queue_type = QueueType,
|
history_size = HistorySize, queue_type = QueueType,
|
||||||
room_shaper = RoomShaper} = State = init_state(Host, Opts),
|
room_shaper = RoomShaper} = State = init_state(Host, Opts),
|
||||||
@ -273,8 +273,8 @@ handle_call({create, Room, Host, From, Nick, Opts}, _From,
|
|||||||
{reply, ok, State}.
|
{reply, ok, State}.
|
||||||
|
|
||||||
handle_cast({reload, ServerHost, NewOpts, OldOpts}, #state{hosts = OldHosts}) ->
|
handle_cast({reload, ServerHost, NewOpts, OldOpts}, #state{hosts = OldHosts}) ->
|
||||||
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
|
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts),
|
||||||
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
|
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts),
|
||||||
NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
|
NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
|
||||||
NewRMod = gen_mod:ram_db_mod(ServerHost, NewOpts, ?MODULE),
|
NewRMod = gen_mod:ram_db_mod(ServerHost, NewOpts, ?MODULE),
|
||||||
OldMod = gen_mod:db_mod(ServerHost, OldOpts, ?MODULE),
|
OldMod = gen_mod:db_mod(ServerHost, OldOpts, ?MODULE),
|
||||||
@ -353,18 +353,16 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
|
|||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
init_state(Host, Opts) ->
|
init_state(Host, Opts) ->
|
||||||
MyHosts = gen_mod:get_opt_hosts(Host, Opts,
|
MyHosts = gen_mod:get_opt_hosts(Host, Opts),
|
||||||
<<"conference.@HOST@">>),
|
Access = gen_mod:get_opt(access, Opts),
|
||||||
Access = gen_mod:get_opt(access, Opts, all),
|
AccessCreate = gen_mod:get_opt(access_create, Opts),
|
||||||
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
|
AccessAdmin = gen_mod:get_opt(access_admin, Opts),
|
||||||
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
|
AccessPersistent = gen_mod:get_opt(access_persistent, Opts),
|
||||||
AccessPersistent = gen_mod:get_opt(access_persistent, Opts, all),
|
HistorySize = gen_mod:get_opt(history_size, Opts),
|
||||||
HistorySize = gen_mod:get_opt(history_size, Opts, 20),
|
MaxRoomsDiscoItems = gen_mod:get_opt(max_rooms_discoitems, Opts),
|
||||||
MaxRoomsDiscoItems = gen_mod:get_opt(max_rooms_discoitems, Opts, 100),
|
DefRoomOpts = gen_mod:get_opt(default_room_options, Opts),
|
||||||
DefRoomOpts = gen_mod:get_opt(default_room_options, Opts, []),
|
QueueType = gen_mod:get_opt(queue_type, Opts),
|
||||||
QueueType = gen_mod:get_opt(queue_type, Opts,
|
RoomShaper = gen_mod:get_opt(room_shaper, Opts),
|
||||||
ejabberd_config:default_queue_type(Host)),
|
|
||||||
RoomShaper = gen_mod:get_opt(room_shaper, Opts, none),
|
|
||||||
#state{hosts = MyHosts,
|
#state{hosts = MyHosts,
|
||||||
server_host = Host,
|
server_host = Host,
|
||||||
access = {Access, AccessCreate, AccessAdmin, AccessPersistent},
|
access = {Access, AccessCreate, AccessAdmin, AccessPersistent},
|
||||||
@ -527,7 +525,7 @@ process_disco_info(#iq{type = get, to = To, lang = Lang,
|
|||||||
Features = [?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
|
Features = [?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
|
||||||
?NS_REGISTER, ?NS_MUC, ?NS_VCARD, ?NS_MUCSUB, ?NS_MUC_UNIQUE
|
?NS_REGISTER, ?NS_MUC, ?NS_VCARD, ?NS_MUCSUB, ?NS_MUC_UNIQUE
|
||||||
| RSMFeatures ++ MAMFeatures],
|
| RSMFeatures ++ MAMFeatures],
|
||||||
Name = gen_mod:get_module_opt(ServerHost, ?MODULE, name, ?T("Chatrooms")),
|
Name = gen_mod:get_module_opt(ServerHost, ?MODULE, name),
|
||||||
Identity = #identity{category = <<"conference">>,
|
Identity = #identity{category = <<"conference">>,
|
||||||
type = <<"text">>,
|
type = <<"text">>,
|
||||||
name = translate:translate(Lang, Name)},
|
name = translate:translate(Lang, Name)},
|
||||||
@ -551,8 +549,7 @@ process_disco_items(#iq{type = get, from = From, to = To, lang = Lang,
|
|||||||
Host = To#jid.lserver,
|
Host = To#jid.lserver,
|
||||||
ServerHost = ejabberd_router:host_of_route(Host),
|
ServerHost = ejabberd_router:host_of_route(Host),
|
||||||
MaxRoomsDiscoItems = gen_mod:get_module_opt(
|
MaxRoomsDiscoItems = gen_mod:get_module_opt(
|
||||||
ServerHost, ?MODULE, max_rooms_discoitems,
|
ServerHost, ?MODULE, max_rooms_discoitems),
|
||||||
100),
|
|
||||||
case iq_disco_items(ServerHost, Host, From, Lang,
|
case iq_disco_items(ServerHost, Host, From, Lang,
|
||||||
MaxRoomsDiscoItems, Node, RSM) of
|
MaxRoomsDiscoItems, Node, RSM) of
|
||||||
{error, Err} ->
|
{error, Err} ->
|
||||||
@ -605,8 +602,8 @@ check_user_can_create_room(ServerHost, AccessCreate,
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
check_create_roomid(ServerHost, RoomID) ->
|
check_create_roomid(ServerHost, RoomID) ->
|
||||||
Max = gen_mod:get_module_opt(ServerHost, ?MODULE, max_room_id, infinity),
|
Max = gen_mod:get_module_opt(ServerHost, ?MODULE, max_room_id),
|
||||||
Regexp = gen_mod:get_module_opt(ServerHost, ?MODULE, regexp_room_id, ""),
|
Regexp = gen_mod:get_module_opt(ServerHost, ?MODULE, regexp_room_id),
|
||||||
(byte_size(RoomID) =< Max) and
|
(byte_size(RoomID) =< Max) and
|
||||||
(re:run(RoomID, Regexp, [unicode, {capture, none}]) == match).
|
(re:run(RoomID, Regexp, [unicode, {capture, none}]) == match).
|
||||||
|
|
||||||
@ -976,34 +973,56 @@ mod_opt_type({default_room_options, presence_broadcast}) ->
|
|||||||
(visitor) -> visitor
|
(visitor) -> visitor
|
||||||
end, L)
|
end, L)
|
||||||
end;
|
end;
|
||||||
mod_opt_type(_) ->
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
|
||||||
[access, access_admin, access_create, access_persistent,
|
|
||||||
db_type, ram_db_type, history_size, host, hosts, name,
|
mod_options(Host) ->
|
||||||
max_room_desc, max_room_id, max_room_name,
|
[{access, all},
|
||||||
max_rooms_discoitems, max_user_conferences, max_users,
|
{access_admin, none},
|
||||||
max_users_admin_threshold, max_users_presence,
|
{access_create, all},
|
||||||
min_message_interval, min_presence_interval, queue_type,
|
{access_persistent, all},
|
||||||
regexp_room_id, room_shaper, user_message_shaper, user_presence_shaper,
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
{default_room_options, allow_change_subj},
|
{ram_db_type, ejabberd_config:default_ram_db(Host, ?MODULE)},
|
||||||
{default_room_options, allow_private_messages},
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
{default_room_options, allow_query_users},
|
{history_size, 20},
|
||||||
{default_room_options, allow_user_invites},
|
{host, <<"conference.@HOST@">>},
|
||||||
{default_room_options, allow_visitor_nickchange},
|
{hosts, []},
|
||||||
{default_room_options, allow_visitor_status},
|
{name, ?T("Chatrooms")},
|
||||||
{default_room_options, anonymous},
|
{max_room_desc, infinity},
|
||||||
{default_room_options, captcha_protected},
|
{max_room_id, infinity},
|
||||||
{default_room_options, logging},
|
{max_room_name, infinity},
|
||||||
{default_room_options, members_by_default},
|
{max_rooms_discoitems, 100},
|
||||||
{default_room_options, members_only},
|
{max_user_conferences, 10},
|
||||||
{default_room_options, moderated},
|
{max_users, 200},
|
||||||
{default_room_options, password_protected},
|
{max_users_admin_threshold, 5},
|
||||||
{default_room_options, persistent},
|
{max_users_presence, 1000},
|
||||||
{default_room_options, public},
|
{min_message_interval, 0},
|
||||||
{default_room_options, public_list},
|
{min_presence_interval, 0},
|
||||||
{default_room_options, mam},
|
{queue_type, ejabberd_config:default_queue_type(Host)},
|
||||||
{default_room_options, allow_subscription},
|
{regexp_room_id, <<"">>},
|
||||||
{default_room_options, password},
|
{room_shaper, none},
|
||||||
{default_room_options, title},
|
{user_message_shaper, none},
|
||||||
{default_room_options, allow_private_messages_from_visitors},
|
{user_presence_shaper, none},
|
||||||
{default_room_options, max_users},
|
{default_room_options,
|
||||||
{default_room_options, presence_broadcast}].
|
[{allow_change_subj,true},
|
||||||
|
{allow_private_messages,true},
|
||||||
|
{allow_query_users,true},
|
||||||
|
{allow_user_invites,false},
|
||||||
|
{allow_visitor_nickchange,true},
|
||||||
|
{allow_visitor_status,true},
|
||||||
|
{anonymous,true},
|
||||||
|
{captcha_protected,false},
|
||||||
|
{logging,false},
|
||||||
|
{members_by_default,true},
|
||||||
|
{members_only,false},
|
||||||
|
{moderated,true},
|
||||||
|
{password_protected,false},
|
||||||
|
{persistent,false},
|
||||||
|
{public,true},
|
||||||
|
{public_list,true},
|
||||||
|
{mam,false},
|
||||||
|
{allow_subscription,false},
|
||||||
|
{password,<<>>},
|
||||||
|
{title,<<>>},
|
||||||
|
{allow_private_messages_from_visitors,anyone},
|
||||||
|
{max_users,200},
|
||||||
|
{presence_broadcast,[moderator,participant,visitor]}]}].
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
set_room_affiliation/4, get_room_affiliations/2,
|
set_room_affiliation/4, get_room_affiliations/2,
|
||||||
web_menu_main/2, web_page_main/2, web_menu_host/3,
|
web_menu_main/2, web_page_main/2, web_menu_host/3,
|
||||||
subscribe_room/4, unsubscribe_room/2, get_subscribers/2,
|
subscribe_room/4, unsubscribe_room/2, get_subscribers/2,
|
||||||
web_page_host/3, mod_opt_type/1, get_commands_spec/0]).
|
web_page_host/3, mod_options/1, get_commands_spec/0]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -578,7 +578,7 @@ create_room_with_opts(Name1, Host1, ServerHost, CustomRoomOpts) ->
|
|||||||
|
|
||||||
%% Get the default room options from the muc configuration
|
%% Get the default room options from the muc configuration
|
||||||
DefRoomOpts = gen_mod:get_module_opt(ServerHost, mod_muc,
|
DefRoomOpts = gen_mod:get_module_opt(ServerHost, mod_muc,
|
||||||
default_room_options, []),
|
default_room_options),
|
||||||
%% Change default room options as required
|
%% Change default room options as required
|
||||||
FormattedRoomOpts = [format_room_option(Opt, Val) || {Opt, Val}<-CustomRoomOpts],
|
FormattedRoomOpts = [format_room_option(Opt, Val) || {Opt, Val}<-CustomRoomOpts],
|
||||||
RoomOpts = lists:ukeymerge(1,
|
RoomOpts = lists:ukeymerge(1,
|
||||||
@ -589,14 +589,13 @@ create_room_with_opts(Name1, Host1, ServerHost, CustomRoomOpts) ->
|
|||||||
mod_muc:store_room(ServerHost, Host, Name, RoomOpts),
|
mod_muc:store_room(ServerHost, Host, Name, RoomOpts),
|
||||||
|
|
||||||
%% Get all remaining mod_muc parameters that might be utilized
|
%% Get all remaining mod_muc parameters that might be utilized
|
||||||
Access = gen_mod:get_module_opt(ServerHost, mod_muc, access, all),
|
Access = gen_mod:get_module_opt(ServerHost, mod_muc, access),
|
||||||
AcCreate = gen_mod:get_module_opt(ServerHost, mod_muc, access_create, all),
|
AcCreate = gen_mod:get_module_opt(ServerHost, mod_muc, access_create),
|
||||||
AcAdmin = gen_mod:get_module_opt(ServerHost, mod_muc, access_admin, none),
|
AcAdmin = gen_mod:get_module_opt(ServerHost, mod_muc, access_admin),
|
||||||
AcPer = gen_mod:get_module_opt(ServerHost, mod_muc, access_persistent, all),
|
AcPer = gen_mod:get_module_opt(ServerHost, mod_muc, access_persistent),
|
||||||
HistorySize = gen_mod:get_module_opt(ServerHost, mod_muc, history_size, 20),
|
HistorySize = gen_mod:get_module_opt(ServerHost, mod_muc, history_size),
|
||||||
RoomShaper = gen_mod:get_module_opt(ServerHost, mod_muc, room_shaper, none),
|
RoomShaper = gen_mod:get_module_opt(ServerHost, mod_muc, room_shaper),
|
||||||
QueueType = gen_mod:get_module_opt(ServerHost, mod_muc, queue_type,
|
QueueType = gen_mod:get_module_opt(ServerHost, mod_muc, queue_type),
|
||||||
ejabberd_config:default_queue_type(ServerHost)),
|
|
||||||
|
|
||||||
%% If the room does not exist yet in the muc_online_room
|
%% If the room does not exist yet in the muc_online_room
|
||||||
case mod_muc:find_online_room(Name, Host) of
|
case mod_muc:find_online_room(Name, Host) of
|
||||||
@ -698,7 +697,7 @@ create_rooms_file(Filename) ->
|
|||||||
file:close(F),
|
file:close(F),
|
||||||
%% Read the default room options defined for the first virtual host
|
%% Read the default room options defined for the first virtual host
|
||||||
DefRoomOpts = gen_mod:get_module_opt(?MYNAME, mod_muc,
|
DefRoomOpts = gen_mod:get_module_opt(?MYNAME, mod_muc,
|
||||||
default_room_options, []),
|
default_room_options),
|
||||||
[muc_create_room(?MYNAME, A, DefRoomOpts) || A <- Rooms],
|
[muc_create_room(?MYNAME, A, DefRoomOpts) || A <- Rooms],
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@ -1215,4 +1214,4 @@ find_hosts(ServerHost) ->
|
|||||||
[]
|
[]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
mod_opt_type(_) -> [].
|
mod_options(_) -> [].
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
handle_info/2, terminate/2, code_change/3,
|
handle_info/2, terminate/2, code_change/3,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -138,16 +138,16 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
|
|||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
init_state(Host, Opts) ->
|
init_state(Host, Opts) ->
|
||||||
OutDir = gen_mod:get_opt(outdir, Opts, <<"www/muc">>),
|
OutDir = gen_mod:get_opt(outdir, Opts),
|
||||||
DirType = gen_mod:get_opt(dirtype, Opts, subdirs),
|
DirType = gen_mod:get_opt(dirtype, Opts),
|
||||||
DirName = gen_mod:get_opt(dirname, Opts, room_jid),
|
DirName = gen_mod:get_opt(dirname, Opts),
|
||||||
FileFormat = gen_mod:get_opt(file_format, Opts, html),
|
FileFormat = gen_mod:get_opt(file_format, Opts),
|
||||||
FilePermissions = gen_mod:get_opt(file_permissions, Opts, {644, 33}),
|
FilePermissions = gen_mod:get_opt(file_permissions, Opts),
|
||||||
CSSFile = gen_mod:get_opt(cssfile, Opts, false),
|
CSSFile = gen_mod:get_opt(cssfile, Opts),
|
||||||
AccessLog = gen_mod:get_opt(access_log, Opts, muc_admin),
|
AccessLog = gen_mod:get_opt(access_log, Opts),
|
||||||
Timezone = gen_mod:get_opt(timezone, Opts, local),
|
Timezone = gen_mod:get_opt(timezone, Opts),
|
||||||
Top_link = gen_mod:get_opt(top_link, Opts, {<<"/">>, <<"Home">>}),
|
Top_link = gen_mod:get_opt(top_link, Opts),
|
||||||
NoFollow = gen_mod:get_opt(spam_prevention, Opts, true),
|
NoFollow = gen_mod:get_opt(spam_prevention, Opts),
|
||||||
Lang = ejabberd_config:get_lang(Host),
|
Lang = ejabberd_config:get_lang(Host),
|
||||||
#logstate{host = Host, out_dir = OutDir,
|
#logstate{host = Host, out_dir = OutDir,
|
||||||
dir_type = DirType, dir_name = DirName,
|
dir_type = DirType, dir_name = DirName,
|
||||||
@ -931,7 +931,10 @@ has_no_permanent_store_hint(Packet) ->
|
|||||||
|
|
||||||
mod_opt_type(access_log) ->
|
mod_opt_type(access_log) ->
|
||||||
fun acl:access_rules_validator/1;
|
fun acl:access_rules_validator/1;
|
||||||
mod_opt_type(cssfile) -> fun misc:try_read_file/1;
|
mod_opt_type(cssfile) ->
|
||||||
|
fun(false) -> false;
|
||||||
|
(File) -> misc:try_read_file(File)
|
||||||
|
end;
|
||||||
mod_opt_type(dirname) ->
|
mod_opt_type(dirname) ->
|
||||||
fun (room_jid) -> room_jid;
|
fun (room_jid) -> room_jid;
|
||||||
(room_name) -> room_name
|
(room_name) -> room_name
|
||||||
@ -963,8 +966,18 @@ mod_opt_type(timezone) ->
|
|||||||
mod_opt_type(top_link) ->
|
mod_opt_type(top_link) ->
|
||||||
fun ([{S1, S2}]) ->
|
fun ([{S1, S2}]) ->
|
||||||
{iolist_to_binary(S1), iolist_to_binary(S2)}
|
{iolist_to_binary(S1), iolist_to_binary(S2)}
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[access_log, cssfile, dirname, dirtype, file_format,
|
mod_options(_) ->
|
||||||
{file_permissions, mode}, {file_permissions, group},
|
[{access_log, muc_admin},
|
||||||
outdir, spam_prevention, timezone, top_link].
|
{cssfile, false},
|
||||||
|
{dirname, room_jid},
|
||||||
|
{dirtype, subdirs},
|
||||||
|
{file_format, html},
|
||||||
|
{file_permissions,
|
||||||
|
[{mode, 644},
|
||||||
|
{group, 33}]},
|
||||||
|
{outdir, <<"www/muc">>},
|
||||||
|
{spam_prevention, true},
|
||||||
|
{timezone, local},
|
||||||
|
{top_link, [{<<"/">>, <<"Home">>}]}].
|
||||||
|
@ -164,8 +164,8 @@ normal_state({route, <<"">>,
|
|||||||
Now = p1_time_compat:system_time(micro_seconds),
|
Now = p1_time_compat:system_time(micro_seconds),
|
||||||
MinMessageInterval = trunc(gen_mod:get_module_opt(
|
MinMessageInterval = trunc(gen_mod:get_module_opt(
|
||||||
StateData#state.server_host,
|
StateData#state.server_host,
|
||||||
mod_muc, min_message_interval,
|
mod_muc, min_message_interval)
|
||||||
0) * 1000000),
|
* 1000000),
|
||||||
Size = element_size(Packet),
|
Size = element_size(Packet),
|
||||||
{MessageShaper, MessageShaperInterval} =
|
{MessageShaper, MessageShaperInterval} =
|
||||||
shaper:update(Activity#activity.message_shaper, Size),
|
shaper:update(Activity#activity.message_shaper, Size),
|
||||||
@ -346,8 +346,8 @@ normal_state({route, Nick, #presence{from = From} = Packet}, StateData) ->
|
|||||||
Now = p1_time_compat:system_time(micro_seconds),
|
Now = p1_time_compat:system_time(micro_seconds),
|
||||||
MinPresenceInterval =
|
MinPresenceInterval =
|
||||||
trunc(gen_mod:get_module_opt(StateData#state.server_host,
|
trunc(gen_mod:get_module_opt(StateData#state.server_host,
|
||||||
mod_muc, min_presence_interval,
|
mod_muc, min_presence_interval)
|
||||||
0) * 1000000),
|
* 1000000),
|
||||||
if (Now >= Activity#activity.presence_time + MinPresenceInterval)
|
if (Now >= Activity#activity.presence_time + MinPresenceInterval)
|
||||||
and (Activity#activity.presence == undefined) ->
|
and (Activity#activity.presence == undefined) ->
|
||||||
NewActivity = Activity#activity{presence_time = Now},
|
NewActivity = Activity#activity{presence_time = Now},
|
||||||
@ -1421,30 +1421,28 @@ get_max_users(StateData) ->
|
|||||||
-spec get_service_max_users(state()) -> pos_integer().
|
-spec get_service_max_users(state()) -> pos_integer().
|
||||||
get_service_max_users(StateData) ->
|
get_service_max_users(StateData) ->
|
||||||
gen_mod:get_module_opt(StateData#state.server_host,
|
gen_mod:get_module_opt(StateData#state.server_host,
|
||||||
mod_muc, max_users,
|
mod_muc, max_users).
|
||||||
?MAX_USERS_DEFAULT).
|
|
||||||
|
|
||||||
-spec get_max_users_admin_threshold(state()) -> pos_integer().
|
-spec get_max_users_admin_threshold(state()) -> pos_integer().
|
||||||
get_max_users_admin_threshold(StateData) ->
|
get_max_users_admin_threshold(StateData) ->
|
||||||
gen_mod:get_module_opt(StateData#state.server_host,
|
gen_mod:get_module_opt(StateData#state.server_host,
|
||||||
mod_muc, max_users_admin_threshold,
|
mod_muc, max_users_admin_threshold).
|
||||||
5).
|
|
||||||
|
|
||||||
-spec room_queue_new(binary(), shaper:shaper(), _) -> p1_queue:queue().
|
-spec room_queue_new(binary(), shaper:shaper(), _) -> p1_queue:queue().
|
||||||
room_queue_new(ServerHost, Shaper, QueueType) ->
|
room_queue_new(ServerHost, Shaper, QueueType) ->
|
||||||
HaveRoomShaper = Shaper /= none,
|
HaveRoomShaper = Shaper /= none,
|
||||||
HaveMessageShaper = gen_mod:get_module_opt(
|
HaveMessageShaper = gen_mod:get_module_opt(
|
||||||
ServerHost, mod_muc, user_message_shaper,
|
ServerHost, mod_muc,
|
||||||
none) /= none,
|
user_message_shaper) /= none,
|
||||||
HavePresenceShaper = gen_mod:get_module_opt(
|
HavePresenceShaper = gen_mod:get_module_opt(
|
||||||
ServerHost, mod_muc, user_presence_shaper,
|
ServerHost, mod_muc,
|
||||||
none) /= none,
|
user_presence_shaper) /= none,
|
||||||
HaveMinMessageInterval = gen_mod:get_module_opt(
|
HaveMinMessageInterval = gen_mod:get_module_opt(
|
||||||
ServerHost, mod_muc, min_message_interval,
|
ServerHost, mod_muc,
|
||||||
0) /= 0,
|
min_message_interval) /= 0,
|
||||||
HaveMinPresenceInterval = gen_mod:get_module_opt(
|
HaveMinPresenceInterval = gen_mod:get_module_opt(
|
||||||
ServerHost, mod_muc, min_presence_interval,
|
ServerHost, mod_muc,
|
||||||
0) /= 0,
|
min_presence_interval) /= 0,
|
||||||
if HaveRoomShaper or HaveMessageShaper or HavePresenceShaper
|
if HaveRoomShaper or HaveMessageShaper or HavePresenceShaper
|
||||||
or HaveMinMessageInterval or HaveMinPresenceInterval ->
|
or HaveMinMessageInterval or HaveMinPresenceInterval ->
|
||||||
p1_queue:new(QueueType);
|
p1_queue:new(QueueType);
|
||||||
@ -1461,12 +1459,10 @@ get_user_activity(JID, StateData) ->
|
|||||||
error ->
|
error ->
|
||||||
MessageShaper =
|
MessageShaper =
|
||||||
shaper:new(gen_mod:get_module_opt(StateData#state.server_host,
|
shaper:new(gen_mod:get_module_opt(StateData#state.server_host,
|
||||||
mod_muc, user_message_shaper,
|
mod_muc, user_message_shaper)),
|
||||||
none)),
|
|
||||||
PresenceShaper =
|
PresenceShaper =
|
||||||
shaper:new(gen_mod:get_module_opt(StateData#state.server_host,
|
shaper:new(gen_mod:get_module_opt(StateData#state.server_host,
|
||||||
mod_muc, user_presence_shaper,
|
mod_muc, user_presence_shaper)),
|
||||||
none)),
|
|
||||||
#activity{message_shaper = MessageShaper,
|
#activity{message_shaper = MessageShaper,
|
||||||
presence_shaper = PresenceShaper}
|
presence_shaper = PresenceShaper}
|
||||||
end.
|
end.
|
||||||
@ -1475,12 +1471,12 @@ get_user_activity(JID, StateData) ->
|
|||||||
store_user_activity(JID, UserActivity, StateData) ->
|
store_user_activity(JID, UserActivity, StateData) ->
|
||||||
MinMessageInterval =
|
MinMessageInterval =
|
||||||
trunc(gen_mod:get_module_opt(StateData#state.server_host,
|
trunc(gen_mod:get_module_opt(StateData#state.server_host,
|
||||||
mod_muc, min_message_interval,
|
mod_muc, min_message_interval)
|
||||||
0) * 1000),
|
* 1000),
|
||||||
MinPresenceInterval =
|
MinPresenceInterval =
|
||||||
trunc(gen_mod:get_module_opt(StateData#state.server_host,
|
trunc(gen_mod:get_module_opt(StateData#state.server_host,
|
||||||
mod_muc, min_presence_interval,
|
mod_muc, min_presence_interval)
|
||||||
0) * 1000),
|
* 1000),
|
||||||
Key = jid:tolower(JID),
|
Key = jid:tolower(JID),
|
||||||
Now = p1_time_compat:system_time(micro_seconds),
|
Now = p1_time_compat:system_time(micro_seconds),
|
||||||
Activity1 = clean_treap(StateData#state.activity,
|
Activity1 = clean_treap(StateData#state.activity,
|
||||||
@ -1788,8 +1784,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
NConferences = tab_count_user(From, StateData),
|
NConferences = tab_count_user(From, StateData),
|
||||||
MaxConferences =
|
MaxConferences =
|
||||||
gen_mod:get_module_opt(StateData#state.server_host,
|
gen_mod:get_module_opt(StateData#state.server_host,
|
||||||
mod_muc, max_user_conferences,
|
mod_muc, max_user_conferences),
|
||||||
10),
|
|
||||||
Collision = nick_collision(From, Nick, StateData),
|
Collision = nick_collision(From, Nick, StateData),
|
||||||
IsSubscribeRequest = not is_record(Packet, presence),
|
IsSubscribeRequest = not is_record(Packet, presence),
|
||||||
case {(ServiceAffiliation == owner orelse
|
case {(ServiceAffiliation == owner orelse
|
||||||
@ -2060,8 +2055,7 @@ filter_history(Queue, Now, Nick,
|
|||||||
is_room_overcrowded(StateData) ->
|
is_room_overcrowded(StateData) ->
|
||||||
MaxUsersPresence = gen_mod:get_module_opt(
|
MaxUsersPresence = gen_mod:get_module_opt(
|
||||||
StateData#state.server_host,
|
StateData#state.server_host,
|
||||||
mod_muc, max_users_presence,
|
mod_muc, max_users_presence),
|
||||||
?DEFAULT_MAX_USERS_PRESENCE),
|
|
||||||
(?DICT):size(StateData#state.users) > MaxUsersPresence.
|
(?DICT):size(StateData#state.users) > MaxUsersPresence.
|
||||||
|
|
||||||
-spec presence_broadcast_allowed(jid(), state()) -> boolean().
|
-spec presence_broadcast_allowed(jid(), state()) -> boolean().
|
||||||
@ -3126,12 +3120,10 @@ is_allowed_room_name_desc_limits(Options, StateData) ->
|
|||||||
RoomDesc = proplists:get_value(roomdesc, Options, <<"">>),
|
RoomDesc = proplists:get_value(roomdesc, Options, <<"">>),
|
||||||
MaxRoomName = gen_mod:get_module_opt(
|
MaxRoomName = gen_mod:get_module_opt(
|
||||||
StateData#state.server_host,
|
StateData#state.server_host,
|
||||||
mod_muc, max_room_name,
|
mod_muc, max_room_name),
|
||||||
infinity),
|
|
||||||
MaxRoomDesc = gen_mod:get_module_opt(
|
MaxRoomDesc = gen_mod:get_module_opt(
|
||||||
StateData#state.server_host,
|
StateData#state.server_host,
|
||||||
mod_muc, max_room_desc,
|
mod_muc, max_room_desc),
|
||||||
infinity),
|
|
||||||
(byte_size(RoomName) =< MaxRoomName)
|
(byte_size(RoomName) =< MaxRoomName)
|
||||||
andalso (byte_size(RoomDesc) =< MaxRoomDesc).
|
andalso (byte_size(RoomDesc) =< MaxRoomDesc).
|
||||||
|
|
||||||
@ -3156,8 +3148,7 @@ is_password_settings_correct(Options, StateData) ->
|
|||||||
get_default_room_maxusers(RoomState) ->
|
get_default_room_maxusers(RoomState) ->
|
||||||
DefRoomOpts =
|
DefRoomOpts =
|
||||||
gen_mod:get_module_opt(RoomState#state.server_host,
|
gen_mod:get_module_opt(RoomState#state.server_host,
|
||||||
mod_muc, default_room_options,
|
mod_muc, default_room_options),
|
||||||
[]),
|
|
||||||
RoomState2 = set_opts(DefRoomOpts, RoomState),
|
RoomState2 = set_opts(DefRoomOpts, RoomState),
|
||||||
(RoomState2#state.config)#config.max_users.
|
(RoomState2#state.config)#config.max_users.
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
-export([init/1, handle_info/2, handle_call/3,
|
-export([init/1, handle_info/2, handle_call/3,
|
||||||
handle_cast/2, terminate/2, code_change/3]).
|
handle_cast/2, terminate/2, code_change/3]).
|
||||||
|
|
||||||
-export([purge_loop/1, mod_opt_type/1, depends/2]).
|
-export([purge_loop/1, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -132,10 +132,9 @@ reload(LServerS, NewOpts, OldOpts) ->
|
|||||||
|
|
||||||
init([LServerS, Opts]) ->
|
init([LServerS, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
LServiceS = gen_mod:get_opt_host(LServerS, Opts,
|
[LServiceS|_] = gen_mod:get_opt_hosts(LServerS, Opts),
|
||||||
<<"multicast.@HOST@">>),
|
Access = gen_mod:get_opt(access, Opts),
|
||||||
Access = gen_mod:get_opt(access, Opts, all),
|
SLimits = build_service_limit_record(gen_mod:get_opt(limits, Opts)),
|
||||||
SLimits = build_service_limit_record(gen_mod:get_opt(limits, Opts, [])),
|
|
||||||
create_cache(),
|
create_cache(),
|
||||||
try_start_loop(),
|
try_start_loop(),
|
||||||
create_pool(),
|
create_pool(),
|
||||||
@ -150,10 +149,9 @@ handle_call(stop, _From, State) ->
|
|||||||
|
|
||||||
handle_cast({reload, NewOpts, NewOpts},
|
handle_cast({reload, NewOpts, NewOpts},
|
||||||
#state{lserver = LServerS, lservice = OldLServiceS} = State) ->
|
#state{lserver = LServerS, lservice = OldLServiceS} = State) ->
|
||||||
Access = gen_mod:get_opt(access, NewOpts, all),
|
Access = gen_mod:get_opt(access, NewOpts),
|
||||||
SLimits = build_service_limit_record(gen_mod:get_opt(limits, NewOpts, [])),
|
SLimits = build_service_limit_record(gen_mod:get_opt(limits, NewOpts)),
|
||||||
NewLServiceS = gen_mod:get_opt_host(LServerS, NewOpts,
|
[NewLServiceS|_] = gen_mod:get_opt_hosts(LServerS, NewOpts),
|
||||||
<<"multicast.@HOST@">>),
|
|
||||||
if NewLServiceS /= OldLServiceS ->
|
if NewLServiceS /= OldLServiceS ->
|
||||||
ejabberd_router:register_route(NewLServiceS, LServerS),
|
ejabberd_router:register_route(NewLServiceS, LServerS),
|
||||||
ejabberd_router:unregister_route(OldLServiceS);
|
ejabberd_router:unregister_route(OldLServiceS);
|
||||||
@ -261,8 +259,7 @@ process_iq(_, _) ->
|
|||||||
-define(FEATURE(Feat), Feat).
|
-define(FEATURE(Feat), Feat).
|
||||||
|
|
||||||
iq_disco_info(From, Lang, State) ->
|
iq_disco_info(From, Lang, State) ->
|
||||||
Name = gen_mod:get_module_opt(State#state.lserver, ?MODULE,
|
Name = gen_mod:get_module_opt(State#state.lserver, ?MODULE, name),
|
||||||
name, ?T("Multicast")),
|
|
||||||
#disco_info{
|
#disco_info{
|
||||||
identities = [#identity{category = <<"service">>,
|
identities = [#identity{category = <<"service">>,
|
||||||
type = <<"multicast">>,
|
type = <<"multicast">>,
|
||||||
@ -1121,6 +1118,8 @@ depends(_Host, _Opts) ->
|
|||||||
mod_opt_type(access) ->
|
mod_opt_type(access) ->
|
||||||
fun acl:access_rules_validator/1;
|
fun acl:access_rules_validator/1;
|
||||||
mod_opt_type(host) -> fun iolist_to_binary/1;
|
mod_opt_type(host) -> fun iolist_to_binary/1;
|
||||||
|
mod_opt_type(hosts) ->
|
||||||
|
fun(L) -> lists:map(fun iolist_to_binary/1, L) end;
|
||||||
mod_opt_type(name) -> fun iolist_to_binary/1;
|
mod_opt_type(name) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type({limits, Type}) when (Type == local) or (Type == remote) ->
|
mod_opt_type({limits, Type}) when (Type == local) or (Type == remote) ->
|
||||||
fun(L) ->
|
fun(L) ->
|
||||||
@ -1130,5 +1129,11 @@ mod_opt_type({limits, Type}) when (Type == local) or (Type == remote) ->
|
|||||||
({message, I} = O) when is_integer(I) -> O;
|
({message, I} = O) when is_integer(I) -> O;
|
||||||
({presence, I} = O) when is_integer(I) -> O
|
({presence, I} = O) when is_integer(I) -> O
|
||||||
end, L)
|
end, L)
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) -> [access, host, {limits, local}, {limits, remote}, name].
|
|
||||||
|
mod_options(_Host) ->
|
||||||
|
[{access, all},
|
||||||
|
{host, <<"multicast.@HOST@">>},
|
||||||
|
{hosts, []},
|
||||||
|
{limits, [{local, []}, {remote, []}]},
|
||||||
|
{name, ?T("Multicast")}].
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
webadmin_user/4,
|
webadmin_user/4,
|
||||||
webadmin_user_parse_query/5]).
|
webadmin_user_parse_query/5]).
|
||||||
|
|
||||||
-export([mod_opt_type/1, depends/2]).
|
-export([mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-deprecated({get_queue_length,2}).
|
-deprecated({get_queue_length,2}).
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ depends(_Host, _Opts) ->
|
|||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
ejabberd_hooks:add(offline_message_hook, Host, ?MODULE,
|
ejabberd_hooks:add(offline_message_hook, Host, ?MODULE,
|
||||||
store_packet, 50),
|
store_packet, 50),
|
||||||
ejabberd_hooks:add(c2s_self_presence, Host, ?MODULE, c2s_self_presence, 50),
|
ejabberd_hooks:add(c2s_self_presence, Host, ?MODULE, c2s_self_presence, 50),
|
||||||
@ -163,7 +163,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_FLEX_OFFLINE,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_FLEX_OFFLINE,
|
||||||
?MODULE, handle_offline_query, IQDisc);
|
?MODULE, handle_offline_query, IQDisc);
|
||||||
@ -187,8 +187,7 @@ store_offline_msg(#offline_msg{us = {User, Server}} = Msg) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
get_max_user_messages(User, Server) ->
|
get_max_user_messages(User, Server) ->
|
||||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access_max_user_messages,
|
Access = gen_mod:get_module_opt(Server, ?MODULE, access_max_user_messages),
|
||||||
max_user_offline_messages),
|
|
||||||
case acl:match_rule(Server, Access, jid:make(User, Server)) of
|
case acl:match_rule(Server, Access, jid:make(User, Server)) of
|
||||||
Max when is_integer(Max) -> Max;
|
Max when is_integer(Max) -> Max;
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
@ -388,8 +387,7 @@ need_to_store(LServer, #message{type = Type} = Packet) ->
|
|||||||
false;
|
false;
|
||||||
none ->
|
none ->
|
||||||
case gen_mod:get_module_opt(
|
case gen_mod:get_module_opt(
|
||||||
LServer, ?MODULE, store_empty_body,
|
LServer, ?MODULE, store_empty_body) of
|
||||||
unless_chat_state) of
|
|
||||||
true ->
|
true ->
|
||||||
true;
|
true;
|
||||||
false ->
|
false ->
|
||||||
@ -850,5 +848,10 @@ mod_opt_type(store_empty_body) ->
|
|||||||
fun (V) when is_boolean(V) -> V;
|
fun (V) when is_boolean(V) -> V;
|
||||||
(unless_chat_state) -> unless_chat_state
|
(unless_chat_state) -> unless_chat_state
|
||||||
end;
|
end;
|
||||||
mod_opt_type(_) ->
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
|
||||||
[access_max_user_messages, db_type, store_empty_body].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{access_max_user_messages, max_user_offline_messages},
|
||||||
|
{store_empty_body, unless_chat_state}].
|
||||||
|
@ -38,10 +38,6 @@
|
|||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
-define(DEFAULT_SEND_PINGS, false).
|
|
||||||
|
|
||||||
-define(DEFAULT_PING_INTERVAL, 60).
|
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start_ping/2, stop_ping/2]).
|
-export([start_ping/2, stop_ping/2]).
|
||||||
|
|
||||||
@ -53,14 +49,14 @@
|
|||||||
handle_cast/2, handle_info/2, code_change/3]).
|
handle_cast/2, handle_info/2, code_change/3]).
|
||||||
|
|
||||||
-export([iq_ping/1, user_online/3, user_offline/3,
|
-export([iq_ping/1, user_online/3, user_offline/3,
|
||||||
user_send/1, mod_opt_type/1, depends/2]).
|
user_send/1, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-record(state,
|
-record(state,
|
||||||
{host = <<"">>,
|
{host = <<"">> :: binary(),
|
||||||
send_pings = ?DEFAULT_SEND_PINGS :: boolean(),
|
send_pings :: boolean(),
|
||||||
ping_interval = ?DEFAULT_PING_INTERVAL :: non_neg_integer(),
|
ping_interval :: non_neg_integer(),
|
||||||
ping_ack_timeout = undefined :: non_neg_integer(),
|
ping_ack_timeout :: undefined | non_neg_integer(),
|
||||||
timeout_action = none :: none | kill,
|
timeout_action ::none | kill,
|
||||||
timers = maps:new() :: map()}).
|
timers = maps:new() :: map()}).
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
@ -95,7 +91,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
init([Host, Opts]) ->
|
init([Host, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
State = init_state(Host, Opts),
|
State = init_state(Host, Opts),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
register_iq_handlers(Host, IQDisc),
|
register_iq_handlers(Host, IQDisc),
|
||||||
case State#state.send_pings of
|
case State#state.send_pings of
|
||||||
true -> register_hooks(Host);
|
true -> register_hooks(Host);
|
||||||
@ -114,7 +110,7 @@ handle_call(_Req, _From, State) ->
|
|||||||
|
|
||||||
handle_cast({reload, Host, NewOpts, OldOpts},
|
handle_cast({reload, Host, NewOpts, OldOpts},
|
||||||
#state{timers = Timers} = OldState) ->
|
#state{timers = Timers} = OldState) ->
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} -> register_iq_handlers(Host, IQDisc);
|
{false, IQDisc, _} -> register_iq_handlers(Host, IQDisc);
|
||||||
true -> ok
|
true -> ok
|
||||||
end,
|
end,
|
||||||
@ -196,10 +192,10 @@ user_send({Packet, #{jid := JID} = C2SState}) ->
|
|||||||
%% Internal functions
|
%% Internal functions
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
init_state(Host, Opts) ->
|
init_state(Host, Opts) ->
|
||||||
SendPings = gen_mod:get_opt(send_pings, Opts, ?DEFAULT_SEND_PINGS),
|
SendPings = gen_mod:get_opt(send_pings, Opts),
|
||||||
PingInterval = gen_mod:get_opt(ping_interval, Opts, ?DEFAULT_PING_INTERVAL),
|
PingInterval = gen_mod:get_opt(ping_interval, Opts),
|
||||||
PingAckTimeout = gen_mod:get_opt(ping_ack_timeout, Opts),
|
PingAckTimeout = gen_mod:get_opt(ping_ack_timeout, Opts),
|
||||||
TimeoutAction = gen_mod:get_opt(timeout_action, Opts, none),
|
TimeoutAction = gen_mod:get_opt(timeout_action, Opts),
|
||||||
#state{host = Host,
|
#state{host = Host,
|
||||||
send_pings = SendPings,
|
send_pings = SendPings,
|
||||||
ping_interval = PingInterval,
|
ping_interval = PingInterval,
|
||||||
@ -271,12 +267,19 @@ mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
|||||||
mod_opt_type(ping_interval) ->
|
mod_opt_type(ping_interval) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
fun (I) when is_integer(I), I > 0 -> I end;
|
||||||
mod_opt_type(ping_ack_timeout) ->
|
mod_opt_type(ping_ack_timeout) ->
|
||||||
fun(I) when is_integer(I), I>0 -> timer:seconds(I) end;
|
fun(undefined) -> undefined;
|
||||||
|
(I) when is_integer(I), I>0 -> timer:seconds(I)
|
||||||
|
end;
|
||||||
mod_opt_type(send_pings) ->
|
mod_opt_type(send_pings) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(timeout_action) ->
|
mod_opt_type(timeout_action) ->
|
||||||
fun (none) -> none;
|
fun (none) -> none;
|
||||||
(kill) -> kill
|
(kill) -> kill
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[iqdisc, ping_interval, ping_ack_timeout, send_pings, timeout_action].
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{ping_interval, 60},
|
||||||
|
{ping_ack_timeout, undefined},
|
||||||
|
{send_pings, false},
|
||||||
|
{timeout_action, none}].
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
-behavior(gen_mod).
|
-behavior(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, check_packet/4,
|
-export([start/2, stop/1, reload/3, check_packet/4,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -79,8 +79,8 @@ check_packet(Acc, _, _, _) ->
|
|||||||
Acc.
|
Acc.
|
||||||
|
|
||||||
update(Server, JID, Dir) ->
|
update(Server, JID, Dir) ->
|
||||||
StormCount = gen_mod:get_module_opt(Server, ?MODULE, count, 5),
|
StormCount = gen_mod:get_module_opt(Server, ?MODULE, count),
|
||||||
TimeInterval = gen_mod:get_module_opt(Server, ?MODULE, interval, 60),
|
TimeInterval = gen_mod:get_module_opt(Server, ?MODULE, interval),
|
||||||
TimeStamp = p1_time_compat:system_time(seconds),
|
TimeStamp = p1_time_compat:system_time(seconds),
|
||||||
case read(Dir) of
|
case read(Dir) of
|
||||||
undefined ->
|
undefined ->
|
||||||
@ -126,5 +126,7 @@ write(K, V) -> put({pres_counter, K}, V).
|
|||||||
mod_opt_type(count) ->
|
mod_opt_type(count) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
fun (I) when is_integer(I), I > 0 -> I end;
|
||||||
mod_opt_type(interval) ->
|
mod_opt_type(interval) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
fun (I) when is_integer(I), I > 0 -> I end.
|
||||||
mod_opt_type(_) -> [count, interval].
|
|
||||||
|
mod_options(_) ->
|
||||||
|
[{count, 5}, {interval, 60}].
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
set_list/1, set_list/4, set_default_list/3,
|
set_list/1, set_list/4, set_default_list/3,
|
||||||
user_send_packet/1, user_receive_packet/1,
|
user_send_packet/1, user_receive_packet/1,
|
||||||
import_start/2, import_stop/2, import/5, import_info/0,
|
import_start/2, import_stop/2, import/5, import_info/0,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -70,7 +70,7 @@
|
|||||||
-optional_callbacks([use_cache/1, cache_nodes/1]).
|
-optional_callbacks([use_cache/1, cache_nodes/1]).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
init_cache(Mod, Host, Opts),
|
init_cache(Mod, Host, Opts),
|
||||||
@ -114,7 +114,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
init_cache(NewMod, Host, NewOpts),
|
init_cache(NewMod, Host, NewOpts),
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY,
|
||||||
?MODULE, process_iq, IQDisc);
|
?MODULE, process_iq, IQDisc);
|
||||||
@ -681,7 +681,7 @@ remove_user(User, Server) ->
|
|||||||
init_cache(Mod, Host, Opts) ->
|
init_cache(Mod, Host, Opts) ->
|
||||||
case use_cache(Mod, Host) of
|
case use_cache(Mod, Host) of
|
||||||
true ->
|
true ->
|
||||||
CacheOpts = cache_opts(Host, Opts),
|
CacheOpts = cache_opts(Opts),
|
||||||
ets_cache:new(?PRIVACY_CACHE, CacheOpts),
|
ets_cache:new(?PRIVACY_CACHE, CacheOpts),
|
||||||
ets_cache:new(?PRIVACY_LIST_CACHE, CacheOpts);
|
ets_cache:new(?PRIVACY_LIST_CACHE, CacheOpts);
|
||||||
false ->
|
false ->
|
||||||
@ -689,17 +689,11 @@ init_cache(Mod, Host, Opts) ->
|
|||||||
ets_cache:delete(?PRIVACY_LIST_CACHE)
|
ets_cache:delete(?PRIVACY_LIST_CACHE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -709,10 +703,7 @@ cache_opts(Host, Opts) ->
|
|||||||
use_cache(Mod, Host) ->
|
use_cache(Mod, Host) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 1) of
|
case erlang:function_exported(Mod, use_cache, 1) of
|
||||||
true -> Mod:use_cache(Host);
|
true -> Mod:use_cache(Host);
|
||||||
false ->
|
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
-spec cache_nodes(module(), binary()) -> [node()].
|
||||||
@ -851,7 +842,12 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[db_type, iqdisc, cache_life_time, cache_size,
|
mod_options(Host) ->
|
||||||
use_cache, cache_missed].
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -47,9 +47,7 @@ init(_Host, _Opts) ->
|
|||||||
use_cache(Host) ->
|
use_cache(Host) ->
|
||||||
case mnesia:table_info(privacy, storage_type) of
|
case mnesia:table_info(privacy, storage_type) of
|
||||||
disc_only_copies ->
|
disc_only_copies ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(Host, mod_privacy, use_cache);
|
||||||
Host, mod_privacy, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host));
|
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
|
|
||||||
-export([start/2, stop/1, reload/3, process_sm_iq/1, import_info/0,
|
-export([start/2, stop/1, reload/3, process_sm_iq/1, import_info/0,
|
||||||
remove_user/2, get_data/2, get_data/3, export/1,
|
remove_user/2, get_data/2, get_data/3, export/1,
|
||||||
import/5, import_start/2, mod_opt_type/1, set_data/3, depends/2]).
|
import/5, import_start/2, mod_opt_type/1, set_data/3,
|
||||||
|
mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -54,7 +55,7 @@
|
|||||||
-optional_callbacks([use_cache/1, cache_nodes/1]).
|
-optional_callbacks([use_cache/1, cache_nodes/1]).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
init_cache(Mod, Host, Opts),
|
init_cache(Mod, Host, Opts),
|
||||||
@ -78,7 +79,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
init_cache(NewMod, Host, NewOpts),
|
init_cache(NewMod, Host, NewOpts),
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE,
|
||||||
?MODULE, process_sm_iq, IQDisc);
|
?MODULE, process_sm_iq, IQDisc);
|
||||||
@ -208,23 +209,17 @@ delete_cache(Mod, LUser, LServer, Data) ->
|
|||||||
init_cache(Mod, Host, Opts) ->
|
init_cache(Mod, Host, Opts) ->
|
||||||
case use_cache(Mod, Host) of
|
case use_cache(Mod, Host) of
|
||||||
true ->
|
true ->
|
||||||
CacheOpts = cache_opts(Host, Opts),
|
CacheOpts = cache_opts(Opts),
|
||||||
ets_cache:new(?PRIVATE_CACHE, CacheOpts);
|
ets_cache:new(?PRIVATE_CACHE, CacheOpts);
|
||||||
false ->
|
false ->
|
||||||
ets_cache:delete(?PRIVATE_CACHE)
|
ets_cache:delete(?PRIVATE_CACHE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -234,10 +229,7 @@ cache_opts(Host, Opts) ->
|
|||||||
use_cache(Mod, Host) ->
|
use_cache(Mod, Host) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 1) of
|
case erlang:function_exported(Mod, use_cache, 1) of
|
||||||
true -> Mod:use_cache(Host);
|
true -> Mod:use_cache(Host);
|
||||||
false ->
|
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
-spec cache_nodes(module(), binary()) -> [node()].
|
||||||
@ -272,6 +264,12 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[db_type, iqdisc, cache_life_time, cache_size, use_cache, cache_missed].
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -46,9 +46,7 @@ init(_Host, _Opts) ->
|
|||||||
use_cache(Host) ->
|
use_cache(Host) ->
|
||||||
case mnesia:table_info(private_storage, storage_type) of
|
case mnesia:table_info(private_storage, storage_type) of
|
||||||
disc_only_copies ->
|
disc_only_copies ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(Host, mod_private, use_cache);
|
||||||
Host, mod_private, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host));
|
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2]).
|
-export([start/2, stop/1, reload/3, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
terminate/2, code_change/3]).
|
terminate/2, code_change/3]).
|
||||||
@ -60,10 +60,12 @@ reload(_Host, _NewOpts, _OldOpts) ->
|
|||||||
|
|
||||||
mod_opt_type({roster, _}) -> fun acl:access_rules_validator/1;
|
mod_opt_type({roster, _}) -> fun acl:access_rules_validator/1;
|
||||||
mod_opt_type({message, _}) -> fun acl:access_rules_validator/1;
|
mod_opt_type({message, _}) -> fun acl:access_rules_validator/1;
|
||||||
mod_opt_type({presence, _}) -> fun acl:access_rules_validator/1;
|
mod_opt_type({presence, _}) -> fun acl:access_rules_validator/1.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[{roster, both}, {roster, get}, {roster, set},
|
mod_options(_) ->
|
||||||
{message, outgoing}, {presence, managed_entity}, {presence, roster}].
|
[{roster, [{both, none}, {get, none}, {set, none}]},
|
||||||
|
{presence, [{managed_entity, none}, {roster, none}]},
|
||||||
|
{message, [{outgoing,none}]}].
|
||||||
|
|
||||||
depends(_, _) ->
|
depends(_, _) ->
|
||||||
[].
|
[].
|
||||||
@ -307,7 +309,7 @@ forward_message(#message{to = To} = Msg) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
get_roster_permission(ServerHost, Host) ->
|
get_roster_permission(ServerHost, Host) ->
|
||||||
Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, roster, []),
|
Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, roster),
|
||||||
case match_rule(ServerHost, Host, Perms, both) of
|
case match_rule(ServerHost, Host, Perms, both) of
|
||||||
allow ->
|
allow ->
|
||||||
both;
|
both;
|
||||||
@ -322,14 +324,14 @@ get_roster_permission(ServerHost, Host) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
get_message_permission(ServerHost, Host) ->
|
get_message_permission(ServerHost, Host) ->
|
||||||
Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, message, []),
|
Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, message),
|
||||||
case match_rule(ServerHost, Host, Perms, outgoing) of
|
case match_rule(ServerHost, Host, Perms, outgoing) of
|
||||||
allow -> outgoing;
|
allow -> outgoing;
|
||||||
deny -> none
|
deny -> none
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_presence_permission(ServerHost, Host) ->
|
get_presence_permission(ServerHost, Host) ->
|
||||||
Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, presence, []),
|
Perms = gen_mod:get_module_opt(ServerHost, ?MODULE, presence),
|
||||||
case match_rule(ServerHost, Host, Perms, roster) of
|
case match_rule(ServerHost, Host, Perms, roster) of
|
||||||
allow ->
|
allow ->
|
||||||
roster;
|
roster;
|
||||||
|
@ -39,10 +39,12 @@
|
|||||||
%% supervisor callbacks.
|
%% supervisor callbacks.
|
||||||
-export([init/1]).
|
-export([init/1]).
|
||||||
|
|
||||||
-export([start_link/2, mod_opt_type/1, depends/2]).
|
-export([start_link/2, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-define(PROCNAME, ejabberd_mod_proxy65).
|
-define(PROCNAME, ejabberd_mod_proxy65).
|
||||||
|
|
||||||
|
-include("translate.hrl").
|
||||||
|
|
||||||
-callback init() -> any().
|
-callback init() -> any().
|
||||||
-callback register_stream(binary(), pid()) -> ok | {error, any()}.
|
-callback register_stream(binary(), pid()) -> ok | {error, any()}.
|
||||||
-callback unregister_stream(binary()) -> ok | {error, any()}.
|
-callback unregister_stream(binary()) -> ok | {error, any()}.
|
||||||
@ -114,9 +116,14 @@ mod_opt_type(access) -> fun acl:access_rules_validator/1;
|
|||||||
mod_opt_type(host) -> fun iolist_to_binary/1;
|
mod_opt_type(host) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(hosts) ->
|
mod_opt_type(hosts) ->
|
||||||
fun(L) -> lists:map(fun iolist_to_binary/1, L) end;
|
fun(L) -> lists:map(fun iolist_to_binary/1, L) end;
|
||||||
mod_opt_type(hostname) -> fun iolist_to_binary/1;
|
mod_opt_type(hostname) ->
|
||||||
|
fun(undefined) -> undefined;
|
||||||
|
(H) -> iolist_to_binary(H)
|
||||||
|
end;
|
||||||
mod_opt_type(ip) ->
|
mod_opt_type(ip) ->
|
||||||
fun (S) ->
|
fun(undefined) ->
|
||||||
|
undefined;
|
||||||
|
(S) ->
|
||||||
{ok, Addr} =
|
{ok, Addr} =
|
||||||
inet_parse:address(binary_to_list(iolist_to_binary(S))),
|
inet_parse:address(binary_to_list(iolist_to_binary(S))),
|
||||||
Addr
|
Addr
|
||||||
@ -130,11 +137,20 @@ mod_opt_type(max_connections) ->
|
|||||||
end;
|
end;
|
||||||
mod_opt_type(ram_db_type) ->
|
mod_opt_type(ram_db_type) ->
|
||||||
fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
|
fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
|
||||||
|
mod_opt_type(iqdisc) ->
|
||||||
|
fun gen_iq_handler:check_type/1;
|
||||||
mod_opt_type(Opt) ->
|
mod_opt_type(Opt) ->
|
||||||
case mod_proxy65_stream:listen_opt_type(Opt) of
|
mod_proxy65_stream:listen_opt_type(Opt).
|
||||||
Opts when is_list(Opts) ->
|
|
||||||
[access, host, hosts, hostname, ip, name, port,
|
mod_options(Host) ->
|
||||||
max_connections, ram_db_type] ++ Opts;
|
[{ram_db_type, ejabberd_config:default_ram_db(Host, ?MODULE)},
|
||||||
Fun ->
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
Fun
|
{access, all},
|
||||||
end.
|
{host, <<"proxy.@HOST@">>},
|
||||||
|
{hosts, []},
|
||||||
|
{hostname, undefined},
|
||||||
|
{ip, undefined},
|
||||||
|
{port, 7777},
|
||||||
|
{name, ?T("SOCKS5 Bytestreams")},
|
||||||
|
{max_connections, infinity}] ++
|
||||||
|
mod_proxy65_stream:listen_options().
|
||||||
|
@ -61,8 +61,8 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
|
|
||||||
init([Host, Opts]) ->
|
init([Host, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"proxy.@HOST@">>),
|
MyHosts = gen_mod:get_opt_hosts(Host, Opts),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(MyHost) ->
|
fun(MyHost) ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
|
gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
|
||||||
@ -93,10 +93,10 @@ handle_call(_Request, _From, State) ->
|
|||||||
{reply, ok, State}.
|
{reply, ok, State}.
|
||||||
|
|
||||||
handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
|
handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
|
||||||
NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts, <<"proxy.@HOST@">>),
|
NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts),
|
||||||
OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts, <<"proxy.@HOST@">>),
|
OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts),
|
||||||
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
|
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts),
|
||||||
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
|
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts),
|
||||||
if (NewIQDisc /= OldIQDisc) ->
|
if (NewIQDisc /= OldIQDisc) ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(NewHost) ->
|
fun(NewHost) ->
|
||||||
@ -144,8 +144,7 @@ process_disco_info(#iq{type = set, lang = Lang} = IQ) ->
|
|||||||
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
|
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
|
||||||
process_disco_info(#iq{type = get, to = To, lang = Lang} = IQ) ->
|
process_disco_info(#iq{type = get, to = To, lang = Lang} = IQ) ->
|
||||||
Host = ejabberd_router:host_of_route(To#jid.lserver),
|
Host = ejabberd_router:host_of_route(To#jid.lserver),
|
||||||
Name = gen_mod:get_module_opt(Host, mod_proxy65, name,
|
Name = gen_mod:get_module_opt(Host, mod_proxy65, name),
|
||||||
?T("SOCKS5 Bytestreams")),
|
|
||||||
Info = ejabberd_hooks:run_fold(disco_info, Host,
|
Info = ejabberd_hooks:run_fold(disco_info, Host,
|
||||||
[], [Host, ?MODULE, <<"">>, <<"">>]),
|
[], [Host, ?MODULE, <<"">>, <<"">>]),
|
||||||
xmpp:make_iq_result(
|
xmpp:make_iq_result(
|
||||||
@ -178,7 +177,7 @@ process_vcard(#iq{type = get, lang = Lang} = IQ) ->
|
|||||||
process_bytestreams(#iq{type = get, from = JID, to = To, lang = Lang} = IQ) ->
|
process_bytestreams(#iq{type = get, from = JID, to = To, lang = Lang} = IQ) ->
|
||||||
Host = To#jid.lserver,
|
Host = To#jid.lserver,
|
||||||
ServerHost = ejabberd_router:host_of_route(Host),
|
ServerHost = ejabberd_router:host_of_route(Host),
|
||||||
ACL = gen_mod:get_module_opt(ServerHost, mod_proxy65, access, all),
|
ACL = gen_mod:get_module_opt(ServerHost, mod_proxy65, access),
|
||||||
case acl:match_rule(ServerHost, ACL, JID) of
|
case acl:match_rule(ServerHost, ACL, JID) of
|
||||||
allow ->
|
allow ->
|
||||||
StreamHost = get_streamhost(Host, ServerHost),
|
StreamHost = get_streamhost(Host, ServerHost),
|
||||||
@ -201,7 +200,7 @@ process_bytestreams(#iq{type = set, lang = Lang, from = InitiatorJID, to = To,
|
|||||||
sub_els = [#bytestreams{activate = TargetJID,
|
sub_els = [#bytestreams{activate = TargetJID,
|
||||||
sid = SID}]} = IQ) ->
|
sid = SID}]} = IQ) ->
|
||||||
ServerHost = ejabberd_router:host_of_route(To#jid.lserver),
|
ServerHost = ejabberd_router:host_of_route(To#jid.lserver),
|
||||||
ACL = gen_mod:get_module_opt(ServerHost, mod_proxy65, access, all),
|
ACL = gen_mod:get_module_opt(ServerHost, mod_proxy65, access),
|
||||||
case acl:match_rule(ServerHost, ACL, InitiatorJID) of
|
case acl:match_rule(ServerHost, ACL, InitiatorJID) of
|
||||||
allow ->
|
allow ->
|
||||||
Node = ejabberd_cluster:get_node_by_id(To#jid.lresource),
|
Node = ejabberd_cluster:get_node_by_id(To#jid.lresource),
|
||||||
@ -253,8 +252,10 @@ transform_module_options(Opts) ->
|
|||||||
-spec get_streamhost(binary(), binary()) -> streamhost().
|
-spec get_streamhost(binary(), binary()) -> streamhost().
|
||||||
get_streamhost(Host, ServerHost) ->
|
get_streamhost(Host, ServerHost) ->
|
||||||
{Port, IP} = get_port_ip(ServerHost),
|
{Port, IP} = get_port_ip(ServerHost),
|
||||||
HostName0 = gen_mod:get_module_opt(ServerHost, mod_proxy65, hostname,
|
HostName0 = case gen_mod:get_module_opt(ServerHost, mod_proxy65, hostname) of
|
||||||
misc:ip_to_list(IP)),
|
undefined -> misc:ip_to_list(IP);
|
||||||
|
Val -> Val
|
||||||
|
end,
|
||||||
HostName = misc:expand_keyword(<<"@HOST@">>, HostName0, ServerHost),
|
HostName = misc:expand_keyword(<<"@HOST@">>, HostName0, ServerHost),
|
||||||
Resource = ejabberd_cluster:node_id(),
|
Resource = ejabberd_cluster:node_id(),
|
||||||
#streamhost{jid = jid:make(<<"">>, Host, Resource),
|
#streamhost{jid = jid:make(<<"">>, Host, Resource),
|
||||||
@ -263,8 +264,11 @@ get_streamhost(Host, ServerHost) ->
|
|||||||
|
|
||||||
-spec get_port_ip(binary()) -> {pos_integer(), inet:ip_address()}.
|
-spec get_port_ip(binary()) -> {pos_integer(), inet:ip_address()}.
|
||||||
get_port_ip(Host) ->
|
get_port_ip(Host) ->
|
||||||
Port = gen_mod:get_module_opt(Host, mod_proxy65, port, 7777),
|
Port = gen_mod:get_module_opt(Host, mod_proxy65, port),
|
||||||
IP = gen_mod:get_module_opt(Host, mod_proxy65, ip, get_my_ip()),
|
IP = case gen_mod:get_module_opt(Host, mod_proxy65, ip) of
|
||||||
|
undefined -> get_my_ip();
|
||||||
|
Addr -> Addr
|
||||||
|
end,
|
||||||
{Port, IP}.
|
{Port, IP}.
|
||||||
|
|
||||||
-spec get_my_ip() -> inet:ip_address().
|
-spec get_my_ip() -> inet:ip_address().
|
||||||
@ -276,7 +280,7 @@ get_my_ip() ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
max_connections(ServerHost) ->
|
max_connections(ServerHost) ->
|
||||||
gen_mod:get_module_opt(ServerHost, mod_proxy65, max_connections, infinity).
|
gen_mod:get_module_opt(ServerHost, mod_proxy65, max_connections).
|
||||||
|
|
||||||
register_handlers(Host, IQDisc) ->
|
register_handlers(Host, IQDisc) ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
|
||||||
|
@ -38,7 +38,8 @@
|
|||||||
stream_established/2]).
|
stream_established/2]).
|
||||||
|
|
||||||
-export([start/2, stop/1, start_link/3, activate/2,
|
-export([start/2, stop/1, start_link/3, activate/2,
|
||||||
relay/3, socket_type/0, listen_opt_type/1]).
|
relay/3, socket_type/0, listen_opt_type/1,
|
||||||
|
listen_options/0]).
|
||||||
|
|
||||||
-include("mod_proxy65.hrl").
|
-include("mod_proxy65.hrl").
|
||||||
|
|
||||||
@ -79,10 +80,10 @@ start_link(Socket, Host, Opts) ->
|
|||||||
|
|
||||||
init([Socket, Host, Opts]) ->
|
init([Socket, Host, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
AuthType = gen_mod:get_opt(auth_type, Opts, anonymous),
|
AuthType = gen_mod:get_opt(auth_type, Opts),
|
||||||
Shaper = gen_mod:get_opt(shaper, Opts, none),
|
Shaper = gen_mod:get_opt(shaper, Opts),
|
||||||
RecvBuf = gen_mod:get_opt(recbuf, Opts, 8192),
|
RecvBuf = gen_mod:get_opt(recbuf, Opts),
|
||||||
SendBuf = gen_mod:get_opt(sndbuf, Opts, 8192),
|
SendBuf = gen_mod:get_opt(sndbuf, Opts),
|
||||||
TRef = erlang:send_after(?WAIT_TIMEOUT, self(), stop),
|
TRef = erlang:send_after(?WAIT_TIMEOUT, self(), stop),
|
||||||
inet:setopts(Socket,
|
inet:setopts(Socket,
|
||||||
[{active, true}, {recbuf, RecvBuf}, {sndbuf, SendBuf}]),
|
[{active, true}, {recbuf, RecvBuf}, {sndbuf, SendBuf}]),
|
||||||
@ -293,6 +294,10 @@ listen_opt_type(recbuf) ->
|
|||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
fun (I) when is_integer(I), I > 0 -> I end;
|
||||||
listen_opt_type(shaper) -> fun acl:shaper_rules_validator/1;
|
listen_opt_type(shaper) -> fun acl:shaper_rules_validator/1;
|
||||||
listen_opt_type(sndbuf) ->
|
listen_opt_type(sndbuf) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
fun (I) when is_integer(I), I > 0 -> I end.
|
||||||
listen_opt_type(_) ->
|
|
||||||
[auth_type, recbuf, sndbuf, shaper].
|
listen_options() ->
|
||||||
|
[{auth_type, anonymous},
|
||||||
|
{recbuf, 8192},
|
||||||
|
{sndbuf, 8192},
|
||||||
|
{shaper, none}].
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
%% API and gen_server callbacks
|
%% API and gen_server callbacks
|
||||||
-export([start/2, stop/1, init/1,
|
-export([start/2, stop/1, init/1,
|
||||||
handle_call/3, handle_cast/2, handle_info/2,
|
handle_call/3, handle_cast/2, handle_info/2,
|
||||||
terminate/2, code_change/3, depends/2, mod_opt_type/1]).
|
terminate/2, code_change/3, depends/2, mod_opt_type/1, mod_options/1]).
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
%% API
|
%% API
|
||||||
@ -241,12 +241,12 @@ stop(Host) ->
|
|||||||
init([ServerHost, Opts]) ->
|
init([ServerHost, Opts]) ->
|
||||||
process_flag(trap_exit, true),
|
process_flag(trap_exit, true),
|
||||||
?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]),
|
?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]),
|
||||||
Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"pubsub.@HOST@">>),
|
Hosts = gen_mod:get_opt_hosts(ServerHost, Opts),
|
||||||
Access = gen_mod:get_opt(access_createnode, Opts, all),
|
Access = gen_mod:get_opt(access_createnode, Opts),
|
||||||
PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts, true),
|
PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(ServerHost)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
LastItemCache = gen_mod:get_opt(last_item_cache, Opts, false),
|
LastItemCache = gen_mod:get_opt(last_item_cache, Opts),
|
||||||
MaxItemsNode = gen_mod:get_opt(max_items_node, Opts, ?MAXITEMS),
|
MaxItemsNode = gen_mod:get_opt(max_items_node, Opts),
|
||||||
MaxSubsNode = gen_mod:get_opt(max_subscriptions_node, Opts),
|
MaxSubsNode = gen_mod:get_opt(max_subscriptions_node, Opts),
|
||||||
ejabberd_mnesia:create(?MODULE, pubsub_last_item,
|
ejabberd_mnesia:create(?MODULE, pubsub_last_item,
|
||||||
[{ram_copies, [node()]},
|
[{ram_copies, [node()]},
|
||||||
@ -255,14 +255,14 @@ init([ServerHost, Opts]) ->
|
|||||||
lists:flatmap(
|
lists:flatmap(
|
||||||
fun(Host) ->
|
fun(Host) ->
|
||||||
ejabberd_router:register_route(Host, ServerHost),
|
ejabberd_router:register_route(Host, ServerHost),
|
||||||
case gen_mod:db_type(ServerHost, ?MODULE) of
|
case gen_mod:get_module_opt(ServerHost, ?MODULE, db_type) of
|
||||||
mnesia -> pubsub_index:init(Host, ServerHost, Opts);
|
mnesia -> pubsub_index:init(Host, ServerHost, Opts);
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end,
|
end,
|
||||||
{Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts),
|
{Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts),
|
||||||
DefaultModule = plugin(Host, hd(Plugins)),
|
DefaultModule = plugin(Host, hd(Plugins)),
|
||||||
DefaultNodeCfg = merge_config(
|
DefaultNodeCfg = merge_config(
|
||||||
gen_mod:get_opt(default_node_config, Opts, []),
|
gen_mod:get_opt(default_node_config, Opts),
|
||||||
DefaultModule:options()),
|
DefaultModule:options()),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(H) ->
|
fun(H) ->
|
||||||
@ -339,7 +339,7 @@ init([ServerHost, Opts]) ->
|
|||||||
NodeTree = config(ServerHost, nodetree),
|
NodeTree = config(ServerHost, nodetree),
|
||||||
Plugins = config(ServerHost, plugins),
|
Plugins = config(ServerHost, plugins),
|
||||||
PepMapping = config(ServerHost, pep_mapping),
|
PepMapping = config(ServerHost, pep_mapping),
|
||||||
DBType = gen_mod:db_type(ServerHost, ?MODULE),
|
DBType = gen_mod:get_module_opt(ServerHost, ?MODULE, db_type),
|
||||||
{ok, #state{hosts = Hosts, server_host = ServerHost,
|
{ok, #state{hosts = Hosts, server_host = ServerHost,
|
||||||
access = Access, pep_mapping = PepMapping,
|
access = Access, pep_mapping = PepMapping,
|
||||||
ignore_pep_from_offline = PepOffline,
|
ignore_pep_from_offline = PepOffline,
|
||||||
@ -347,9 +347,10 @@ init([ServerHost, Opts]) ->
|
|||||||
max_items_node = MaxItemsNode, nodetree = NodeTree,
|
max_items_node = MaxItemsNode, nodetree = NodeTree,
|
||||||
plugins = Plugins, db_type = DBType}}.
|
plugins = Plugins, db_type = DBType}}.
|
||||||
|
|
||||||
depends(ServerHost, Opts) ->
|
depends(ServerHost, Opts0) ->
|
||||||
Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>),
|
Opts = Opts0 ++ mod_options(ServerHost),
|
||||||
Plugins = gen_mod:get_opt(plugins, Opts, [?STDNODE]),
|
[Host|_] = gen_mod:get_opt_hosts(ServerHost, Opts),
|
||||||
|
Plugins = gen_mod:get_opt(plugins, Opts),
|
||||||
lists:flatmap(
|
lists:flatmap(
|
||||||
fun(Name) ->
|
fun(Name) ->
|
||||||
Plugin = plugin(ServerHost, Name),
|
Plugin = plugin(ServerHost, Name),
|
||||||
@ -364,11 +365,11 @@ depends(ServerHost, Opts) ->
|
|||||||
%% <em>node_plugin</em>. The 'node_' prefix is mandatory.</p>
|
%% <em>node_plugin</em>. The 'node_' prefix is mandatory.</p>
|
||||||
%% <p>See {@link node_hometree:init/1} for an example implementation.</p>
|
%% <p>See {@link node_hometree:init/1} for an example implementation.</p>
|
||||||
init_plugins(Host, ServerHost, Opts) ->
|
init_plugins(Host, ServerHost, Opts) ->
|
||||||
TreePlugin = tree(Host, gen_mod:get_opt(nodetree, Opts, ?STDTREE)),
|
TreePlugin = tree(Host, gen_mod:get_opt(nodetree, Opts)),
|
||||||
?DEBUG("** tree plugin is ~p", [TreePlugin]),
|
?DEBUG("** tree plugin is ~p", [TreePlugin]),
|
||||||
TreePlugin:init(Host, ServerHost, Opts),
|
TreePlugin:init(Host, ServerHost, Opts),
|
||||||
Plugins = gen_mod:get_opt(plugins, Opts, [?STDNODE]),
|
Plugins = gen_mod:get_opt(plugins, Opts),
|
||||||
PepMapping = gen_mod:get_opt(pep_mapping, Opts, []),
|
PepMapping = gen_mod:get_opt(pep_mapping, Opts),
|
||||||
?DEBUG("** PEP Mapping : ~p~n", [PepMapping]),
|
?DEBUG("** PEP Mapping : ~p~n", [PepMapping]),
|
||||||
PluginsOK = lists:foldl(
|
PluginsOK = lists:foldl(
|
||||||
fun (Name, Acc) ->
|
fun (Name, Acc) ->
|
||||||
@ -980,8 +981,7 @@ iq_disco_info(ServerHost, Host, SNode, From, Lang) ->
|
|||||||
end,
|
end,
|
||||||
case Node of
|
case Node of
|
||||||
<<>> ->
|
<<>> ->
|
||||||
Name = gen_mod:get_module_opt(ServerHost, ?MODULE, name,
|
Name = gen_mod:get_module_opt(ServerHost, ?MODULE, name),
|
||||||
?T("Publish-Subscribe")),
|
|
||||||
{result,
|
{result,
|
||||||
#disco_info{
|
#disco_info{
|
||||||
identities = [#identity{
|
identities = [#identity{
|
||||||
@ -3421,7 +3421,7 @@ subscription_plugin(Host) ->
|
|||||||
|
|
||||||
-spec submodule(host(), binary(), binary()) -> atom().
|
-spec submodule(host(), binary(), binary()) -> atom().
|
||||||
submodule(Host, Type, Name) ->
|
submodule(Host, Type, Name) ->
|
||||||
case gen_mod:db_type(serverhost(Host), ?MODULE) of
|
case gen_mod:get_module_opt(serverhost(Host), ?MODULE, db_type) of
|
||||||
mnesia -> ejabberd:module_name([<<"pubsub">>, Type, Name]);
|
mnesia -> ejabberd:module_name([<<"pubsub">>, Type, Name]);
|
||||||
Db -> ejabberd:module_name([<<"pubsub">>, Type, Name, misc:atom_to_binary(Db)])
|
Db -> ejabberd:module_name([<<"pubsub">>, Type, Name, misc:atom_to_binary(Db)])
|
||||||
end.
|
end.
|
||||||
@ -3524,7 +3524,7 @@ tree_action(Host, Function, Args) ->
|
|||||||
?DEBUG("tree_action ~p ~p ~p", [Host, Function, Args]),
|
?DEBUG("tree_action ~p ~p ~p", [Host, Function, Args]),
|
||||||
ServerHost = serverhost(Host),
|
ServerHost = serverhost(Host),
|
||||||
Fun = fun () -> tree_call(Host, Function, Args) end,
|
Fun = fun () -> tree_call(Host, Function, Args) end,
|
||||||
case gen_mod:db_type(ServerHost, ?MODULE) of
|
case gen_mod:get_module_opt(ServerHost, ?MODULE, db_type) of
|
||||||
mnesia ->
|
mnesia ->
|
||||||
catch mnesia:sync_dirty(Fun);
|
catch mnesia:sync_dirty(Fun);
|
||||||
sql ->
|
sql ->
|
||||||
@ -3592,7 +3592,7 @@ transaction(Host, Node, Action, Trans) ->
|
|||||||
|
|
||||||
transaction(Host, Fun, Trans) ->
|
transaction(Host, Fun, Trans) ->
|
||||||
ServerHost = serverhost(Host),
|
ServerHost = serverhost(Host),
|
||||||
DBType = gen_mod:db_type(ServerHost, ?MODULE),
|
DBType = gen_mod:get_module_opt(ServerHost, ?MODULE, db_type),
|
||||||
Retry = case DBType of
|
Retry = case DBType of
|
||||||
sql -> 2;
|
sql -> 2;
|
||||||
_ -> 1
|
_ -> 1
|
||||||
@ -3867,7 +3867,9 @@ mod_opt_type(last_item_cache) ->
|
|||||||
mod_opt_type(max_items_node) ->
|
mod_opt_type(max_items_node) ->
|
||||||
fun (A) when is_integer(A) andalso A >= 0 -> A end;
|
fun (A) when is_integer(A) andalso A >= 0 -> A end;
|
||||||
mod_opt_type(max_subscriptions_node) ->
|
mod_opt_type(max_subscriptions_node) ->
|
||||||
fun (A) when is_integer(A) andalso A >= 0 -> A end;
|
fun(A) when is_integer(A) andalso A >= 0 -> A;
|
||||||
|
(undefined) -> undefined
|
||||||
|
end;
|
||||||
mod_opt_type(default_node_config) ->
|
mod_opt_type(default_node_config) ->
|
||||||
fun (A) when is_list(A) -> A end;
|
fun (A) when is_list(A) -> A end;
|
||||||
mod_opt_type(nodetree) ->
|
mod_opt_type(nodetree) ->
|
||||||
@ -3875,9 +3877,20 @@ mod_opt_type(nodetree) ->
|
|||||||
mod_opt_type(pep_mapping) ->
|
mod_opt_type(pep_mapping) ->
|
||||||
fun (A) when is_list(A) -> A end;
|
fun (A) when is_list(A) -> A end;
|
||||||
mod_opt_type(plugins) ->
|
mod_opt_type(plugins) ->
|
||||||
fun (A) when is_list(A) -> A end;
|
fun (A) when is_list(A) -> A end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[access_createnode, db_type, host, hosts, name,
|
mod_options(Host) ->
|
||||||
ignore_pep_from_offline, iqdisc, last_item_cache,
|
[{access_createnode, all},
|
||||||
max_items_node, nodetree, pep_mapping, plugins,
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
max_subscriptions_node, default_node_config].
|
{host, <<"pubsub.@HOST@">>},
|
||||||
|
{hosts, []},
|
||||||
|
{name, ?T("Publish-Subscribe")},
|
||||||
|
{ignore_pep_from_offline, true},
|
||||||
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{last_item_cache, false},
|
||||||
|
{max_items_node, ?MAXITEMS},
|
||||||
|
{nodetree, ?STDTREE},
|
||||||
|
{pep_mapping, []},
|
||||||
|
{plugins, [?STDNODE]},
|
||||||
|
{max_subscriptions_node, undefined},
|
||||||
|
{default_node_config, []}].
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
-behavior(gen_mod).
|
-behavior(gen_mod).
|
||||||
|
|
||||||
%% gen_mod callbacks.
|
%% gen_mod callbacks.
|
||||||
-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2]).
|
-export([start/2, stop/1, reload/3, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
%% ejabberd_hooks callbacks.
|
%% ejabberd_hooks callbacks.
|
||||||
-export([disco_sm_features/5, c2s_session_pending/1, c2s_copy_session/2,
|
-export([disco_sm_features/5, c2s_session_pending/1, c2s_copy_session/2,
|
||||||
@ -92,7 +92,7 @@
|
|||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
-spec start(binary(), gen_mod:opts()) -> ok.
|
-spec start(binary(), gen_mod:opts()) -> ok.
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
init_cache(Mod, Host, Opts),
|
init_cache(Mod, Host, Opts),
|
||||||
@ -120,8 +120,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts,
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
gen_iq_handler:iqdisc(Host)) of
|
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
register_iq_handlers(Host, IQDisc);
|
register_iq_handlers(Host, IQDisc);
|
||||||
true ->
|
true ->
|
||||||
@ -142,9 +141,15 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(iqdisc) ->
|
mod_opt_type(iqdisc) ->
|
||||||
fun gen_iq_handler:check_type/1;
|
fun gen_iq_handler:check_type/1.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[db_type, cache_life_time, cache_size, use_cache, cache_missed, iqdisc].
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% ejabberd command callback.
|
%% ejabberd command callback.
|
||||||
@ -165,7 +170,7 @@ delete_old_sessions(Days) ->
|
|||||||
DBTypes = lists:usort(
|
DBTypes = lists:usort(
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(Host) ->
|
fun(Host) ->
|
||||||
case gen_mod:db_type(Host, ?MODULE) of
|
case gen_mod:get_module_opt(Host, ?MODULE, db_type) of
|
||||||
sql -> {sql, Host};
|
sql -> {sql, Host};
|
||||||
Other -> {Other, global}
|
Other -> {Other, global}
|
||||||
end
|
end
|
||||||
@ -579,23 +584,17 @@ drop_online_sessions(LUser, LServer, Clients) ->
|
|||||||
init_cache(Mod, Host, Opts) ->
|
init_cache(Mod, Host, Opts) ->
|
||||||
case use_cache(Mod, Host) of
|
case use_cache(Mod, Host) of
|
||||||
true ->
|
true ->
|
||||||
CacheOpts = cache_opts(Host, Opts),
|
CacheOpts = cache_opts(Opts),
|
||||||
ets_cache:new(?PUSH_CACHE, CacheOpts);
|
ets_cache:new(?PUSH_CACHE, CacheOpts);
|
||||||
false ->
|
false ->
|
||||||
ets_cache:delete(?PUSH_CACHE)
|
ets_cache:delete(?PUSH_CACHE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -605,10 +604,7 @@ cache_opts(Host, Opts) ->
|
|||||||
use_cache(Mod, Host) ->
|
use_cache(Mod, Host) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 1) of
|
case erlang:function_exported(Mod, use_cache, 1) of
|
||||||
true -> Mod:use_cache(Host);
|
true -> Mod:use_cache(Host);
|
||||||
false ->
|
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
-spec cache_nodes(module(), binary()) -> [node()].
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
-behavior(gen_mod).
|
-behavior(gen_mod).
|
||||||
|
|
||||||
%% gen_mod callbacks.
|
%% gen_mod callbacks.
|
||||||
-export([start/2, stop/1, reload/3, mod_opt_type/1, depends/2]).
|
-export([start/2, stop/1, reload/3, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
%% ejabberd_hooks callbacks.
|
%% ejabberd_hooks callbacks.
|
||||||
-export([c2s_session_pending/1, c2s_session_resumed/1, c2s_copy_session/2,
|
-export([c2s_session_pending/1, c2s_session_resumed/1, c2s_copy_session/2,
|
||||||
@ -47,7 +47,7 @@
|
|||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
-spec start(binary(), gen_mod:opts()) -> ok.
|
-spec start(binary(), gen_mod:opts()) -> ok.
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
case gen_mod:get_opt(wake_on_start, Opts, false) of
|
case gen_mod:get_opt(wake_on_start, Opts) of
|
||||||
true ->
|
true ->
|
||||||
wake_all(Host);
|
wake_all(Host);
|
||||||
false ->
|
false ->
|
||||||
@ -61,7 +61,7 @@ stop(Host) ->
|
|||||||
|
|
||||||
-spec reload(binary(), gen_mod:opts(), gen_mod:opts()) -> ok.
|
-spec reload(binary(), gen_mod:opts(), gen_mod:opts()) -> ok.
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(Host, NewOpts, OldOpts) ->
|
||||||
case gen_mod:is_equal_opt(wake_on_start, NewOpts, OldOpts, false) of
|
case gen_mod:is_equal_opt(wake_on_start, NewOpts, OldOpts) of
|
||||||
{false, true, _} ->
|
{false, true, _} ->
|
||||||
wake_all(Host);
|
wake_all(Host);
|
||||||
_ ->
|
_ ->
|
||||||
@ -83,16 +83,12 @@ mod_opt_type(resume_timeout) ->
|
|||||||
mod_opt_type(wake_on_start) ->
|
mod_opt_type(wake_on_start) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(wake_on_timeout) ->
|
mod_opt_type(wake_on_timeout) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|
||||||
fun(I) when is_integer(I), I > 0 -> I;
|
mod_options(_Host) ->
|
||||||
(infinity) -> infinity
|
[{resume_timeout, 86400},
|
||||||
end;
|
{wake_on_start, false},
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
{wake_on_timeout, true}].
|
||||||
fun (B) when is_boolean(B) -> B end;
|
|
||||||
mod_opt_type(_) ->
|
|
||||||
[resume_timeout, wake_on_start, wake_on_timeout, cache_life_time,
|
|
||||||
cache_size, use_cache, cache_missed, iqdisc].
|
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Register/unregister hooks.
|
%% Register/unregister hooks.
|
||||||
@ -168,10 +164,8 @@ c2s_copy_session(State, _) ->
|
|||||||
|
|
||||||
-spec c2s_handle_cast(c2s_state(), any()) -> c2s_state().
|
-spec c2s_handle_cast(c2s_state(), any()) -> c2s_state().
|
||||||
c2s_handle_cast(#{lserver := LServer} = State, push_enable) ->
|
c2s_handle_cast(#{lserver := LServer} = State, push_enable) ->
|
||||||
ResumeTimeout = gen_mod:get_module_opt(LServer, ?MODULE,
|
ResumeTimeout = gen_mod:get_module_opt(LServer, ?MODULE, resume_timeout),
|
||||||
resume_timeout, 86400),
|
WakeOnTimeout = gen_mod:get_module_opt(LServer, ?MODULE, wake_on_timeout),
|
||||||
WakeOnTimeout = gen_mod:get_module_opt(LServer, ?MODULE,
|
|
||||||
wake_on_timeout, true),
|
|
||||||
State#{push_resume_timeout => ResumeTimeout,
|
State#{push_resume_timeout => ResumeTimeout,
|
||||||
push_wake_on_timeout => WakeOnTimeout};
|
push_wake_on_timeout => WakeOnTimeout};
|
||||||
c2s_handle_cast(State, push_disable) ->
|
c2s_handle_cast(State, push_disable) ->
|
||||||
|
@ -37,14 +37,14 @@
|
|||||||
c2s_unauthenticated_packet/2, try_register/5,
|
c2s_unauthenticated_packet/2, try_register/5,
|
||||||
process_iq/1, send_registration_notifications/3,
|
process_iq/1, send_registration_notifications/3,
|
||||||
transform_options/1, transform_module_options/1,
|
transform_options/1, transform_module_options/1,
|
||||||
mod_opt_type/1, opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, opt_type/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
?NS_REGISTER, ?MODULE, process_iq, IQDisc),
|
?NS_REGISTER, ?MODULE, process_iq, IQDisc),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
||||||
@ -69,7 +69,7 @@ stop(Host) ->
|
|||||||
?NS_REGISTER).
|
?NS_REGISTER).
|
||||||
|
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(Host, NewOpts, OldOpts) ->
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_REGISTER,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_REGISTER,
|
||||||
?MODULE, process_iq, IQDisc),
|
?MODULE, process_iq, IQDisc),
|
||||||
@ -83,14 +83,8 @@ depends(_Host, _Opts) ->
|
|||||||
[].
|
[].
|
||||||
|
|
||||||
-spec stream_feature_register([xmpp_element()], binary()) -> [xmpp_element()].
|
-spec stream_feature_register([xmpp_element()], binary()) -> [xmpp_element()].
|
||||||
stream_feature_register(Acc, Host) ->
|
stream_feature_register(Acc, _Host) ->
|
||||||
AF = gen_mod:get_module_opt(Host, ?MODULE, access_from, all),
|
[#feature_register{}|Acc].
|
||||||
case (AF /= none) of
|
|
||||||
true ->
|
|
||||||
[#feature_register{}|Acc];
|
|
||||||
false ->
|
|
||||||
Acc
|
|
||||||
end.
|
|
||||||
|
|
||||||
c2s_unauthenticated_packet(#{ip := IP, server := Server} = State,
|
c2s_unauthenticated_packet(#{ip := IP, server := Server} = State,
|
||||||
#iq{type = T, sub_els = [_]} = IQ)
|
#iq{type = T, sub_els = [_]} = IQ)
|
||||||
@ -119,13 +113,12 @@ process_iq(#iq{from = From} = IQ) ->
|
|||||||
|
|
||||||
process_iq(#iq{from = From, to = To} = IQ, Source) ->
|
process_iq(#iq{from = From, to = To} = IQ, Source) ->
|
||||||
IsCaptchaEnabled =
|
IsCaptchaEnabled =
|
||||||
case gen_mod:get_module_opt(To#jid.lserver, ?MODULE,
|
case gen_mod:get_module_opt(To#jid.lserver, ?MODULE, captcha_protected) of
|
||||||
captcha_protected, false) of
|
|
||||||
true -> true;
|
true -> true;
|
||||||
false -> false
|
false -> false
|
||||||
end,
|
end,
|
||||||
Server = To#jid.lserver,
|
Server = To#jid.lserver,
|
||||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access_remove, all),
|
Access = gen_mod:get_module_opt(Server, ?MODULE, access_remove),
|
||||||
AllowRemove = allow == acl:match_rule(Server, Access, From),
|
AllowRemove = allow == acl:match_rule(Server, Access, From),
|
||||||
process_iq(IQ, Source, IsCaptchaEnabled, AllowRemove).
|
process_iq(IQ, Source, IsCaptchaEnabled, AllowRemove).
|
||||||
|
|
||||||
@ -215,7 +208,7 @@ process_iq(#iq{type = get, from = From, to = To, id = ID, lang = Lang} = IQ,
|
|||||||
Instr = translate:translate(
|
Instr = translate:translate(
|
||||||
Lang, <<"Choose a username and password to register "
|
Lang, <<"Choose a username and password to register "
|
||||||
"with this server">>),
|
"with this server">>),
|
||||||
URL = gen_mod:get_module_opt(Server, ?MODULE, redirect_url, <<"">>),
|
URL = gen_mod:get_module_opt(Server, ?MODULE, redirect_url),
|
||||||
if (URL /= <<"">>) and not IsRegistered ->
|
if (URL /= <<"">>) and not IsRegistered ->
|
||||||
Txt = translate:translate(Lang, <<"To register, visit ~s">>),
|
Txt = translate:translate(Lang, <<"To register, visit ~s">>),
|
||||||
Desc = str:format(Txt, [URL]),
|
Desc = str:format(Txt, [URL]),
|
||||||
@ -322,7 +315,7 @@ try_register(User, Server, Password, SourceRaw, Lang) ->
|
|||||||
false -> {error, xmpp:err_bad_request(<<"Malformed username">>, Lang)};
|
false -> {error, xmpp:err_bad_request(<<"Malformed username">>, Lang)};
|
||||||
_ ->
|
_ ->
|
||||||
JID = jid:make(User, Server),
|
JID = jid:make(User, Server),
|
||||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access, all),
|
Access = gen_mod:get_module_opt(Server, ?MODULE, access),
|
||||||
IPAccess = get_ip_access(Server),
|
IPAccess = get_ip_access(Server),
|
||||||
case {acl:match_rule(Server, Access, JID),
|
case {acl:match_rule(Server, Access, JID),
|
||||||
check_ip_access(SourceRaw, IPAccess)}
|
check_ip_access(SourceRaw, IPAccess)}
|
||||||
@ -390,8 +383,7 @@ try_register(User, Server, Password, SourceRaw, Lang) ->
|
|||||||
|
|
||||||
send_welcome_message(JID) ->
|
send_welcome_message(JID) ->
|
||||||
Host = JID#jid.lserver,
|
Host = JID#jid.lserver,
|
||||||
case gen_mod:get_module_opt(Host, ?MODULE, welcome_message,
|
case gen_mod:get_module_opt(Host, ?MODULE, welcome_message) of
|
||||||
{<<"">>, <<"">>}) of
|
|
||||||
{<<"">>, <<"">>} -> ok;
|
{<<"">>, <<"">>} -> ok;
|
||||||
{Subj, Body} ->
|
{Subj, Body} ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
@ -404,7 +396,7 @@ send_welcome_message(JID) ->
|
|||||||
|
|
||||||
send_registration_notifications(Mod, UJID, Source) ->
|
send_registration_notifications(Mod, UJID, Source) ->
|
||||||
Host = UJID#jid.lserver,
|
Host = UJID#jid.lserver,
|
||||||
case gen_mod:get_module_opt(Host, Mod, registration_watchers, []) of
|
case gen_mod:get_module_opt(Host, Mod, registration_watchers) of
|
||||||
[] -> ok;
|
[] -> ok;
|
||||||
JIDs when is_list(JIDs) ->
|
JIDs when is_list(JIDs) ->
|
||||||
Body =
|
Body =
|
||||||
@ -428,7 +420,7 @@ check_from(#jid{user = <<"">>, server = <<"">>},
|
|||||||
_Server) ->
|
_Server) ->
|
||||||
allow;
|
allow;
|
||||||
check_from(JID, Server) ->
|
check_from(JID, Server) ->
|
||||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access_from, none),
|
Access = gen_mod:get_module_opt(Server, ?MODULE, access_from),
|
||||||
acl:match_rule(Server, Access, JID).
|
acl:match_rule(Server, Access, JID).
|
||||||
|
|
||||||
check_timeout(undefined) -> true;
|
check_timeout(undefined) -> true;
|
||||||
@ -532,7 +524,7 @@ is_strong_password(Server, Password) ->
|
|||||||
|
|
||||||
is_strong_password2(Server, Password) ->
|
is_strong_password2(Server, Password) ->
|
||||||
LServer = jid:nameprep(Server),
|
LServer = jid:nameprep(Server),
|
||||||
case gen_mod:get_module_opt(LServer, ?MODULE, password_strength, 0) of
|
case gen_mod:get_module_opt(LServer, ?MODULE, password_strength) of
|
||||||
0 ->
|
0 ->
|
||||||
true;
|
true;
|
||||||
Entropy ->
|
Entropy ->
|
||||||
@ -596,7 +588,7 @@ may_remove_resource({_, _, _} = From) ->
|
|||||||
may_remove_resource(From) -> From.
|
may_remove_resource(From) -> From.
|
||||||
|
|
||||||
get_ip_access(Host) ->
|
get_ip_access(Host) ->
|
||||||
gen_mod:get_module_opt(Host, ?MODULE, ip_access, all).
|
gen_mod:get_module_opt(Host, ?MODULE, ip_access).
|
||||||
|
|
||||||
check_ip_access({User, Server, Resource}, IPAccess) ->
|
check_ip_access({User, Server, Resource}, IPAccess) ->
|
||||||
case ejabberd_sm:get_user_ip(User, Server, Resource) of
|
case ejabberd_sm:get_user_ip(User, Server, Resource) of
|
||||||
@ -633,11 +625,21 @@ mod_opt_type({welcome_message, subject}) ->
|
|||||||
mod_opt_type({welcome_message, body}) ->
|
mod_opt_type({welcome_message, body}) ->
|
||||||
fun iolist_to_binary/1;
|
fun iolist_to_binary/1;
|
||||||
mod_opt_type(redirect_url) ->
|
mod_opt_type(redirect_url) ->
|
||||||
fun iolist_to_binary/1;
|
fun iolist_to_binary/1.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[access, access_from, access_remove, captcha_protected, ip_access,
|
mod_options(Host) ->
|
||||||
iqdisc, password_strength, registration_watchers, redirect_url,
|
[{access, all},
|
||||||
{welcome_message, subject}, {welcome_message, body}].
|
{access_from, none},
|
||||||
|
{access_remove, all},
|
||||||
|
{captcha_protected, false},
|
||||||
|
{ip_access, all},
|
||||||
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{password_strength, 0},
|
||||||
|
{registration_watchers, []},
|
||||||
|
{redirect_url, <<"">>},
|
||||||
|
{welcome_message,
|
||||||
|
[{subject, <<"">>},
|
||||||
|
{body, <<"">>}]}].
|
||||||
|
|
||||||
-spec opt_type(registration_timeout) -> fun((timeout()) -> timeout());
|
-spec opt_type(registration_timeout) -> fun((timeout()) -> timeout());
|
||||||
(atom()) -> [atom()].
|
(atom()) -> [atom()].
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, process/2, mod_opt_type/1, depends/2]).
|
-export([start/2, stop/1, reload/3, process/2, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -517,7 +517,7 @@ form_del_get(Host, Lang) ->
|
|||||||
%% {error, not_allowed} |
|
%% {error, not_allowed} |
|
||||||
%% {error, invalid_jid}
|
%% {error, invalid_jid}
|
||||||
register_account(Username, Host, Password) ->
|
register_account(Username, Host, Password) ->
|
||||||
Access = gen_mod:get_module_opt(Host, mod_register, access, all),
|
Access = gen_mod:get_module_opt(Host, mod_register, access),
|
||||||
case jid:make(Username, Host) of
|
case jid:make(Username, Host) of
|
||||||
error -> {error, invalid_jid};
|
error -> {error, invalid_jid};
|
||||||
JID ->
|
JID ->
|
||||||
@ -602,4 +602,5 @@ get_error_text({error, passwords_not_identical}) ->
|
|||||||
get_error_text({error, wrong_parameters}) ->
|
get_error_text({error, wrong_parameters}) ->
|
||||||
<<"Wrong parameters in the web formulary">>.
|
<<"Wrong parameters in the web formulary">>.
|
||||||
|
|
||||||
mod_opt_type(_) -> [].
|
mod_options(_) ->
|
||||||
|
[].
|
||||||
|
@ -49,7 +49,8 @@
|
|||||||
get_jid_info/4, encode_item/1, webadmin_page/3,
|
get_jid_info/4, encode_item/1, webadmin_page/3,
|
||||||
webadmin_user/4, get_versioning_feature/2,
|
webadmin_user/4, get_versioning_feature/2,
|
||||||
roster_versioning_enabled/1, roster_version/2,
|
roster_versioning_enabled/1, roster_version/2,
|
||||||
mod_opt_type/1, set_roster/1, del_roster/3, depends/2]).
|
mod_opt_type/1, mod_options/1, set_roster/1, del_roster/3,
|
||||||
|
depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -87,7 +88,7 @@
|
|||||||
-optional_callbacks([use_cache/2, cache_nodes/1]).
|
-optional_callbacks([use_cache/2, cache_nodes/1]).
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
|
||||||
Mod:init(Host, Opts),
|
Mod:init(Host, Opts),
|
||||||
init_cache(Mod, Host, Opts),
|
init_cache(Mod, Host, Opts),
|
||||||
@ -142,7 +143,7 @@ reload(Host, NewOpts, OldOpts) ->
|
|||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
|
||||||
?MODULE, process_iq, IQDisc);
|
?MODULE, process_iq, IQDisc);
|
||||||
@ -181,7 +182,7 @@ process_local_iq(#iq{type = set, from = From, lang = Lang,
|
|||||||
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
|
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
|
||||||
false ->
|
false ->
|
||||||
#jid{server = Server} = From,
|
#jid{server = Server} = From,
|
||||||
Access = gen_mod:get_module_opt(Server, ?MODULE, access, all),
|
Access = gen_mod:get_module_opt(Server, ?MODULE, access),
|
||||||
case acl:match_rule(Server, Access, From) of
|
case acl:match_rule(Server, Access, From) of
|
||||||
deny ->
|
deny ->
|
||||||
Txt = <<"Access denied by service policy">>,
|
Txt = <<"Access denied by service policy">>,
|
||||||
@ -214,10 +215,10 @@ roster_hash(Items) ->
|
|||||||
<- Items]))).
|
<- Items]))).
|
||||||
|
|
||||||
roster_versioning_enabled(Host) ->
|
roster_versioning_enabled(Host) ->
|
||||||
gen_mod:get_module_opt(Host, ?MODULE, versioning, false).
|
gen_mod:get_module_opt(Host, ?MODULE, versioning).
|
||||||
|
|
||||||
roster_version_on_db(Host) ->
|
roster_version_on_db(Host) ->
|
||||||
gen_mod:get_module_opt(Host, ?MODULE, store_current_id, false).
|
gen_mod:get_module_opt(Host, ?MODULE, store_current_id).
|
||||||
|
|
||||||
%% Returns a list that may contain an xmlelement with the XEP-237 feature if it's enabled.
|
%% Returns a list that may contain an xmlelement with the XEP-237 feature if it's enabled.
|
||||||
-spec get_versioning_feature([xmpp_element()], binary()) -> [xmpp_element()].
|
-spec get_versioning_feature([xmpp_element()], binary()) -> [xmpp_element()].
|
||||||
@ -1088,7 +1089,7 @@ has_duplicated_groups(Groups) ->
|
|||||||
|
|
||||||
-spec init_cache(module(), binary(), gen_mod:opts()) -> ok.
|
-spec init_cache(module(), binary(), gen_mod:opts()) -> ok.
|
||||||
init_cache(Mod, Host, Opts) ->
|
init_cache(Mod, Host, Opts) ->
|
||||||
CacheOpts = cache_opts(Host, Opts),
|
CacheOpts = cache_opts(Opts),
|
||||||
case use_cache(Mod, Host, roster_version) of
|
case use_cache(Mod, Host, roster_version) of
|
||||||
true ->
|
true ->
|
||||||
ets_cache:new(?ROSTER_VERSION_CACHE, CacheOpts);
|
ets_cache:new(?ROSTER_VERSION_CACHE, CacheOpts);
|
||||||
@ -1104,17 +1105,11 @@ init_cache(Mod, Host, Opts) ->
|
|||||||
ets_cache:delete(?ROSTER_ITEM_CACHE)
|
ets_cache:delete(?ROSTER_ITEM_CACHE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -1124,10 +1119,7 @@ cache_opts(Host, Opts) ->
|
|||||||
use_cache(Mod, Host, Table) ->
|
use_cache(Mod, Host, Table) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 2) of
|
case erlang:function_exported(Mod, use_cache, 2) of
|
||||||
true -> Mod:use_cache(Host, Table);
|
true -> Mod:use_cache(Host, Table);
|
||||||
false ->
|
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
-spec cache_nodes(module(), binary()) -> [node()].
|
||||||
@ -1213,7 +1205,15 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[access, db_type, iqdisc, store_current_id,
|
mod_options(Host) ->
|
||||||
versioning, cache_life_time, cache_size, use_cache, cache_missed].
|
[{access, all},
|
||||||
|
{store_current_id, false},
|
||||||
|
{versioning, false},
|
||||||
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -53,9 +53,7 @@ init(_Host, _Opts) ->
|
|||||||
use_cache(Host, Table) ->
|
use_cache(Host, Table) ->
|
||||||
case mnesia:table_info(Table, storage_type) of
|
case mnesia:table_info(Table, storage_type) of
|
||||||
disc_only_copies ->
|
disc_only_copies ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(Host, mod_roster, use_cache);
|
||||||
Host, mod_roster, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host));
|
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
-protocol({xep, 185, '1.0'}).
|
-protocol({xep, 185, '1.0'}).
|
||||||
|
|
||||||
%% gen_mod API
|
%% gen_mod API
|
||||||
-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1]).
|
-export([start/2, stop/1, reload/3, depends/2, mod_options/1]).
|
||||||
%% Hooks
|
%% Hooks
|
||||||
-export([s2s_out_auth_result/2, s2s_out_downgraded/2,
|
-export([s2s_out_auth_result/2, s2s_out_downgraded/2,
|
||||||
s2s_in_packet/2, s2s_out_packet/2, s2s_in_recv/3,
|
s2s_in_packet/2, s2s_out_packet/2, s2s_in_recv/3,
|
||||||
@ -97,7 +97,7 @@ reload(Host, NewOpts, _OldOpts) ->
|
|||||||
depends(_Host, _Opts) ->
|
depends(_Host, _Opts) ->
|
||||||
[].
|
[].
|
||||||
|
|
||||||
mod_opt_type(_) ->
|
mod_options(_Host) ->
|
||||||
[].
|
[].
|
||||||
|
|
||||||
s2s_in_features(Acc, _) ->
|
s2s_in_features(Acc, _) ->
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, log_user_send/1,
|
-export([start/2, stop/1, log_user_send/1, mod_options/1,
|
||||||
log_user_receive/1, mod_opt_type/1, depends/2]).
|
log_user_receive/1, mod_opt_type/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
@ -68,7 +68,7 @@ log_user_receive({Packet, C2SState}) ->
|
|||||||
|
|
||||||
-spec log_packet(stanza(), binary()) -> ok.
|
-spec log_packet(stanza(), binary()) -> ok.
|
||||||
log_packet(Packet, Host) ->
|
log_packet(Packet, Host) ->
|
||||||
Loggers = gen_mod:get_module_opt(Host, ?MODULE, loggers, []),
|
Loggers = gen_mod:get_module_opt(Host, ?MODULE, loggers),
|
||||||
ForwardedMsg = #message{from = jid:make(Host),
|
ForwardedMsg = #message{from = jid:make(Host),
|
||||||
id = randoms:get_string(),
|
id = randoms:get_string(),
|
||||||
sub_els = [#forwarded{
|
sub_els = [#forwarded{
|
||||||
@ -86,5 +86,7 @@ mod_opt_type(loggers) ->
|
|||||||
if N /= error -> N end
|
if N /= error -> N end
|
||||||
end,
|
end,
|
||||||
L)
|
L)
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) -> [loggers].
|
|
||||||
|
mod_options(_) ->
|
||||||
|
[{loggers, []}].
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
delete_group/2, get_group_opts/2, set_group_opts/3,
|
delete_group/2, get_group_opts/2, set_group_opts/3,
|
||||||
get_group_users/2, get_group_explicit_users/2,
|
get_group_users/2, get_group_explicit_users/2,
|
||||||
is_user_in_group/3, add_user_to_group/3, opts_to_binary/1,
|
is_user_in_group/3, add_user_to_group/3, opts_to_binary/1,
|
||||||
remove_user_from_group/3, mod_opt_type/1, depends/2]).
|
remove_user_from_group/3, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -1071,5 +1071,7 @@ import(LServer, {sql, _}, DBType, Tab, L) ->
|
|||||||
Mod = gen_mod:db_mod(DBType, ?MODULE),
|
Mod = gen_mod:db_mod(DBType, ?MODULE),
|
||||||
Mod:import(LServer, Tab, L).
|
Mod:import(LServer, Tab, L).
|
||||||
|
|
||||||
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
|
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end.
|
||||||
mod_opt_type(_) -> [db_type].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{db_type, ejabberd_config:default_db(Host, ?MODULE)}].
|
||||||
|
@ -41,8 +41,8 @@
|
|||||||
|
|
||||||
-export([get_user_roster/2,
|
-export([get_user_roster/2,
|
||||||
get_jid_info/4, process_item/2, in_subscription/6,
|
get_jid_info/4, process_item/2, in_subscription/6,
|
||||||
out_subscription/4, mod_opt_type/1, opt_type/1, depends/2,
|
out_subscription/4, mod_opt_type/1, mod_options/1,
|
||||||
transform_module_options/1]).
|
opt_type/1, depends/2, transform_module_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -446,18 +446,21 @@ get_user_part_re(String, Pattern) ->
|
|||||||
parse_options(Host, Opts) ->
|
parse_options(Host, Opts) ->
|
||||||
Eldap_ID = misc:atom_to_binary(gen_mod:get_module_proc(Host, ?MODULE)),
|
Eldap_ID = misc:atom_to_binary(gen_mod:get_module_proc(Host, ?MODULE)),
|
||||||
Cfg = eldap_utils:get_config(Host, Opts),
|
Cfg = eldap_utils:get_config(Host, Opts),
|
||||||
GroupAttr = gen_mod:get_opt(ldap_groupattr, Opts, <<"cn">>),
|
GroupAttr = gen_mod:get_opt(ldap_groupattr, Opts),
|
||||||
GroupDesc = gen_mod:get_opt(ldap_groupdesc, Opts, GroupAttr),
|
GroupDesc = case gen_mod:get_opt(ldap_groupdesc, Opts) of
|
||||||
UserDesc = gen_mod:get_opt(ldap_userdesc, Opts, <<"cn">>),
|
undefined -> GroupAttr;
|
||||||
UserUID = gen_mod:get_opt(ldap_useruid, Opts, <<"cn">>),
|
GD -> GD
|
||||||
UIDAttr = gen_mod:get_opt(ldap_memberattr, Opts, <<"memberUid">>),
|
end,
|
||||||
UIDAttrFormat = gen_mod:get_opt(ldap_memberattr_format, Opts, <<"%u">>),
|
UserDesc = gen_mod:get_opt(ldap_userdesc, Opts),
|
||||||
UIDAttrFormatRe = gen_mod:get_opt(ldap_memberattr_format_re, Opts, <<"">>),
|
UserUID = gen_mod:get_opt(ldap_useruid, Opts),
|
||||||
AuthCheck = gen_mod:get_opt(ldap_auth_check, Opts, true),
|
UIDAttr = gen_mod:get_opt(ldap_memberattr, Opts),
|
||||||
ConfigFilter = gen_mod:get_opt({ldap_filter, Host}, Opts, <<"">>),
|
UIDAttrFormat = gen_mod:get_opt(ldap_memberattr_format, Opts),
|
||||||
ConfigUserFilter = gen_mod:get_opt({ldap_ufilter, Host}, Opts, <<"">>),
|
UIDAttrFormatRe = gen_mod:get_opt(ldap_memberattr_format_re, Opts),
|
||||||
ConfigGroupFilter = gen_mod:get_opt({ldap_gfilter, Host}, Opts, <<"">>),
|
AuthCheck = gen_mod:get_opt(ldap_auth_check, Opts),
|
||||||
RosterFilter = gen_mod:get_opt({ldap_rfilter, Host}, Opts, <<"">>),
|
ConfigFilter = gen_mod:get_opt(ldap_filter, Opts),
|
||||||
|
ConfigUserFilter = gen_mod:get_opt(ldap_ufilter, Opts),
|
||||||
|
ConfigGroupFilter = gen_mod:get_opt(ldap_gfilter, Opts),
|
||||||
|
RosterFilter = gen_mod:get_opt(ldap_rfilter, Opts),
|
||||||
SubFilter = <<"(&(", UIDAttr/binary, "=",
|
SubFilter = <<"(&(", UIDAttr/binary, "=",
|
||||||
UIDAttrFormat/binary, ")(", GroupAttr/binary, "=%g))">>,
|
UIDAttrFormat/binary, ")(", GroupAttr/binary, "=%g))">>,
|
||||||
UserSubFilter = case ConfigUserFilter of
|
UserSubFilter = case ConfigUserFilter of
|
||||||
@ -517,16 +520,13 @@ init_cache(Host, Opts) ->
|
|||||||
end,
|
end,
|
||||||
UseCache.
|
UseCache.
|
||||||
|
|
||||||
use_cache(Host, Opts) ->
|
use_cache(_Host, Opts) ->
|
||||||
gen_mod:get_opt(use_cache, Opts, ejabberd_config:use_cache(Host)).
|
gen_mod:get_opt(use_cache, Opts).
|
||||||
|
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(_Host, Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(cache_size, Opts,
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
CacheMissed = gen_mod:get_opt(cache_missed, Opts,
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -554,51 +554,14 @@ transform_module_options(Opts) ->
|
|||||||
Opt
|
Opt
|
||||||
end, Opts).
|
end, Opts).
|
||||||
|
|
||||||
mod_opt_type(deref_aliases) ->
|
|
||||||
fun (never) -> never;
|
|
||||||
(searching) -> searching;
|
|
||||||
(finding) -> finding;
|
|
||||||
(always) -> always
|
|
||||||
end;
|
|
||||||
mod_opt_type(ldap_backups) ->
|
|
||||||
fun (L) -> [iolist_to_binary(H) || H <- L] end;
|
|
||||||
mod_opt_type(ldap_base) -> fun iolist_to_binary/1;
|
|
||||||
mod_opt_type(ldap_deref_aliases) ->
|
|
||||||
fun (never) -> never;
|
|
||||||
(searching) -> searching;
|
|
||||||
(finding) -> finding;
|
|
||||||
(always) -> always
|
|
||||||
end;
|
|
||||||
mod_opt_type(ldap_encrypt) ->
|
|
||||||
fun (tls) -> tls;
|
|
||||||
(starttls) -> starttls;
|
|
||||||
(none) -> none
|
|
||||||
end;
|
|
||||||
mod_opt_type(ldap_password) -> fun iolist_to_binary/1;
|
|
||||||
mod_opt_type(ldap_port) ->
|
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
|
||||||
mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1;
|
|
||||||
mod_opt_type(ldap_servers) ->
|
|
||||||
fun (L) -> [iolist_to_binary(H) || H <- L] end;
|
|
||||||
mod_opt_type(ldap_tls_cacertfile) ->
|
|
||||||
fun misc:try_read_file/1;
|
|
||||||
mod_opt_type(ldap_tls_certfile) ->
|
|
||||||
fun ejabberd_pkix:try_certfile/1;
|
|
||||||
mod_opt_type(ldap_tls_depth) ->
|
|
||||||
fun (I) when is_integer(I), I >= 0 -> I end;
|
|
||||||
mod_opt_type(ldap_tls_verify) ->
|
|
||||||
fun (hard) -> hard;
|
|
||||||
(soft) -> soft;
|
|
||||||
(false) -> false
|
|
||||||
end;
|
|
||||||
mod_opt_type(ldap_auth_check) ->
|
mod_opt_type(ldap_auth_check) ->
|
||||||
fun (on) -> true;
|
fun (on) -> true;
|
||||||
(off) -> false;
|
(off) -> false;
|
||||||
(false) -> false;
|
(false) -> false;
|
||||||
(true) -> true
|
(true) -> true
|
||||||
end;
|
end;
|
||||||
mod_opt_type(ldap_filter) -> fun eldap_utils:check_filter/1;
|
mod_opt_type(ldap_gfilter) ->
|
||||||
mod_opt_type(ldap_gfilter) -> fun eldap_utils:check_filter/1;
|
opt_type(ldap_gfilter);
|
||||||
mod_opt_type(O) when O == cache_size;
|
mod_opt_type(O) when O == cache_size;
|
||||||
O == cache_life_time ->
|
O == cache_life_time ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I;
|
fun (I) when is_integer(I), I > 0 -> I;
|
||||||
@ -607,7 +570,10 @@ mod_opt_type(O) when O == cache_size;
|
|||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(ldap_groupattr) -> fun iolist_to_binary/1;
|
mod_opt_type(ldap_groupattr) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(ldap_groupdesc) -> fun iolist_to_binary/1;
|
mod_opt_type(ldap_groupdesc) ->
|
||||||
|
fun(undefined) -> undefined;
|
||||||
|
(G) -> iolist_to_binary(G)
|
||||||
|
end;
|
||||||
mod_opt_type(ldap_memberattr) -> fun iolist_to_binary/1;
|
mod_opt_type(ldap_memberattr) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(ldap_memberattr_format) ->
|
mod_opt_type(ldap_memberattr_format) ->
|
||||||
fun iolist_to_binary/1;
|
fun iolist_to_binary/1;
|
||||||
@ -615,23 +581,39 @@ mod_opt_type(ldap_memberattr_format_re) ->
|
|||||||
fun (S) ->
|
fun (S) ->
|
||||||
Re = iolist_to_binary(S), {ok, MP} = re:compile(Re), MP
|
Re = iolist_to_binary(S), {ok, MP} = re:compile(Re), MP
|
||||||
end;
|
end;
|
||||||
mod_opt_type(ldap_rfilter) -> fun eldap_utils:check_filter/1;
|
mod_opt_type(ldap_rfilter) ->
|
||||||
mod_opt_type(ldap_ufilter) -> fun eldap_utils:check_filter/1;
|
opt_type(ldap_rfilter);
|
||||||
|
mod_opt_type(ldap_ufilter) ->
|
||||||
|
opt_type(ldap_ufilter);
|
||||||
mod_opt_type(ldap_userdesc) -> fun iolist_to_binary/1;
|
mod_opt_type(ldap_userdesc) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(ldap_useruid) -> fun iolist_to_binary/1;
|
mod_opt_type(ldap_useruid) -> fun iolist_to_binary/1;
|
||||||
mod_opt_type(_) ->
|
mod_opt_type(Opt) ->
|
||||||
[ldap_auth_check, ldap_filter, ldap_gfilter,
|
eldap_utils:opt_type(Opt).
|
||||||
ldap_groupattr, ldap_groupdesc, ldap_memberattr,
|
|
||||||
ldap_memberattr_format, ldap_memberattr_format_re,
|
|
||||||
ldap_rfilter, ldap_ufilter, ldap_userdesc, ldap_useruid,
|
|
||||||
deref_aliases, ldap_backups, ldap_base,
|
|
||||||
ldap_deref_aliases, ldap_encrypt, ldap_password,
|
|
||||||
ldap_port, ldap_rootdn, ldap_servers,
|
|
||||||
ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth,
|
|
||||||
ldap_tls_verify, use_cache, cache_missed, cache_size, cache_life_time].
|
|
||||||
|
|
||||||
opt_type(ldap_gfilter) -> fun eldap_utils:check_filter/1;
|
mod_options(Host) ->
|
||||||
opt_type(ldap_rfilter) -> fun eldap_utils:check_filter/1;
|
[{ldap_auth_check, true},
|
||||||
opt_type(ldap_ufilter) -> fun eldap_utils:check_filter/1;
|
{ldap_gfilter, ejabberd_config:get_option({ldap_gfilter, Host}, <<"">>)},
|
||||||
|
{ldap_groupattr, <<"cn">>},
|
||||||
|
{ldap_groupdesc, undefined},
|
||||||
|
{ldap_memberattr, <<"memberUid">>},
|
||||||
|
{ldap_memberattr_format, <<"%u">>},
|
||||||
|
{ldap_memberattr_format_re, <<"">>},
|
||||||
|
{ldap_rfilter, ejabberd_config:get_option({ldap_rfilter, Host}, <<"">>)},
|
||||||
|
{ldap_ufilter, ejabberd_config:get_option({ldap_ufilter, Host}, <<"">>)},
|
||||||
|
{ldap_userdesc, <<"cn">>},
|
||||||
|
{ldap_useruid, <<"cn">>},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}
|
||||||
|
| lists:map(
|
||||||
|
fun({Opt, Default}) ->
|
||||||
|
{Opt, ejabberd_config:get_option({Opt, Host}, Default)}
|
||||||
|
end, eldap_utils:options(Host))].
|
||||||
|
|
||||||
|
opt_type(O) when O == ldap_rfilter; O == ldap_gfilter; O == ldap_ufilter ->
|
||||||
|
fun(<<>>) -> <<>>;
|
||||||
|
(F) -> eldap_utils:check_filter(F)
|
||||||
|
end;
|
||||||
opt_type(_) ->
|
opt_type(_) ->
|
||||||
[ldap_gfilter, ldap_rfilter, ldap_ufilter].
|
[ldap_gfilter, ldap_rfilter, ldap_ufilter].
|
||||||
|
@ -32,14 +32,14 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, process_local_iq/1,
|
-export([start/2, stop/1, reload/3, process_local_iq/1,
|
||||||
process_sm_iq/1, mod_opt_type/1, depends/2]).
|
process_sm_iq/1, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_SIC_0,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_SIC_0,
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_SIC_0,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_SIC_0,
|
||||||
@ -56,7 +56,7 @@ stop(Host) ->
|
|||||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_SIC_1).
|
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_SIC_1).
|
||||||
|
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(Host, NewOpts, OldOpts) ->
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_SIC_0,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_SIC_0,
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
@ -107,5 +107,7 @@ get_ip({User, Server, Resource},
|
|||||||
xmpp:make_error(IQ, xmpp:err_item_not_found(Txt, Lang))
|
xmpp:make_error(IQ, xmpp:err_item_not_found(Txt, Lang))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
|
||||||
mod_opt_type(_) -> [iqdisc].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)}].
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
|
||||||
-ifndef(SIP).
|
-ifndef(SIP).
|
||||||
-export([start/2, stop/1, depends/2, mod_opt_type/1]).
|
-export([start/2, stop/1, depends/2, mod_options/1]).
|
||||||
start(_, _) ->
|
start(_, _) ->
|
||||||
?CRITICAL_MSG("ejabberd is not compiled with SIP support", []),
|
?CRITICAL_MSG("ejabberd is not compiled with SIP support", []),
|
||||||
{error, sip_not_compiled}.
|
{error, sip_not_compiled}.
|
||||||
@ -37,7 +37,7 @@ stop(_) ->
|
|||||||
ok.
|
ok.
|
||||||
depends(_, _) ->
|
depends(_, _) ->
|
||||||
[].
|
[].
|
||||||
mod_opt_type(_) ->
|
mod_options(_) ->
|
||||||
[].
|
[].
|
||||||
-else.
|
-else.
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
@ -49,7 +49,7 @@ mod_opt_type(_) ->
|
|||||||
|
|
||||||
-export([data_in/2, data_out/2, message_in/2,
|
-export([data_in/2, data_out/2, message_in/2,
|
||||||
message_out/2, request/2, request/3, response/2,
|
message_out/2, request/2, request/3, response/2,
|
||||||
locate/1, mod_opt_type/1, depends/2]).
|
locate/1, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include_lib("esip/include/esip.hrl").
|
-include_lib("esip/include/esip.hrl").
|
||||||
@ -360,9 +360,15 @@ mod_opt_type(via) ->
|
|||||||
{Type, {Host, Port}}
|
{Type, {Host, Port}}
|
||||||
end,
|
end,
|
||||||
L)
|
L)
|
||||||
end;
|
end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[always_record_route, flow_timeout_tcp,
|
mod_options(Host) ->
|
||||||
flow_timeout_udp, record_route, routes, via].
|
Route = <<"sip:", Host/binary, ";lr">>,
|
||||||
|
[{always_record_route, true},
|
||||||
|
{flow_timeout_tcp, 120},
|
||||||
|
{flow_timeout_udp, 29},
|
||||||
|
{record_route, Route},
|
||||||
|
{routes, [Route]},
|
||||||
|
{via, []}].
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
|
@ -321,7 +321,7 @@ is_request_within_dialog(#sip{hdrs = Hdrs}) ->
|
|||||||
esip:has_param(<<"tag">>, Params).
|
esip:has_param(<<"tag">>, Params).
|
||||||
|
|
||||||
need_record_route(LServer) ->
|
need_record_route(LServer) ->
|
||||||
gen_mod:get_module_opt(LServer, mod_sip, always_record_route, true).
|
gen_mod:get_module_opt(LServer, mod_sip, always_record_route).
|
||||||
|
|
||||||
make_sign(TS, Hdrs) ->
|
make_sign(TS, Hdrs) ->
|
||||||
{_, #uri{user = FUser, host = FServer}, FParams} = esip:get_hdr('from', Hdrs),
|
{_, #uri{user = FUser, host = FServer}, FParams} = esip:get_hdr('from', Hdrs),
|
||||||
@ -348,17 +348,13 @@ is_signed_by_me(TS_Sign, Hdrs) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
get_configured_vias(LServer) ->
|
get_configured_vias(LServer) ->
|
||||||
gen_mod:get_module_opt(LServer, mod_sip, via, []).
|
gen_mod:get_module_opt(LServer, mod_sip, via).
|
||||||
|
|
||||||
get_configured_record_route(LServer) ->
|
get_configured_record_route(LServer) ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(LServer, mod_sip, record_route).
|
||||||
LServer, mod_sip, record_route,
|
|
||||||
#uri{host = LServer, params = [{<<"lr">>, <<"">>}]}).
|
|
||||||
|
|
||||||
get_configured_routes(LServer) ->
|
get_configured_routes(LServer) ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(LServer, mod_sip, routes).
|
||||||
LServer, mod_sip, routes,
|
|
||||||
[#uri{host = LServer, params = [{<<"lr">>, <<"">>}]}]).
|
|
||||||
|
|
||||||
mark_transaction_as_complete(TrID, State) ->
|
mark_transaction_as_complete(TrID, State) ->
|
||||||
NewTrIDs = lists:delete(TrID, State#state.tr_ids),
|
NewTrIDs = lists:delete(TrID, State#state.tr_ids),
|
||||||
|
@ -46,8 +46,6 @@
|
|||||||
|
|
||||||
-define(CALL_TIMEOUT, timer:seconds(30)).
|
-define(CALL_TIMEOUT, timer:seconds(30)).
|
||||||
-define(DEFAULT_EXPIRES, 3600).
|
-define(DEFAULT_EXPIRES, 3600).
|
||||||
-define(FLOW_TIMEOUT_UDP, 29).
|
|
||||||
-define(FLOW_TIMEOUT_TCP, 120).
|
|
||||||
|
|
||||||
-record(sip_session, {us = {<<"">>, <<"">>} :: {binary(), binary()},
|
-record(sip_session, {us = {<<"">>, <<"">>} :: {binary(), binary()},
|
||||||
socket = #sip_socket{} :: #sip_socket{},
|
socket = #sip_socket{} :: #sip_socket{},
|
||||||
@ -497,12 +495,10 @@ get_flow_timeout(LServer, #sip_socket{type = Type}) ->
|
|||||||
case Type of
|
case Type of
|
||||||
udp ->
|
udp ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(
|
||||||
LServer, mod_sip, flow_timeout_udp,
|
LServer, mod_sip, flow_timeout_udp);
|
||||||
?FLOW_TIMEOUT_UDP);
|
|
||||||
_ ->
|
_ ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(
|
||||||
LServer, mod_sip, flow_timeout_tcp,
|
LServer, mod_sip, flow_timeout_tcp)
|
||||||
?FLOW_TIMEOUT_TCP)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
update_table() ->
|
update_table() ->
|
||||||
|
@ -31,14 +31,15 @@
|
|||||||
|
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, process_iq/1, mod_opt_type/1, depends/2]).
|
-export([start/2, stop/1, reload/3, process_iq/1, mod_opt_type/1,
|
||||||
|
mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_STATS,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_STATS,
|
||||||
?MODULE, process_iq, IQDisc).
|
?MODULE, process_iq, IQDisc).
|
||||||
|
|
||||||
@ -233,5 +234,7 @@ search_running_node(SNode, [Node | Nodes]) ->
|
|||||||
_ -> search_running_node(SNode, Nodes)
|
_ -> search_running_node(SNode, Nodes)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
|
||||||
mod_opt_type(_) -> [iqdisc].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)}].
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
-protocol({xep, 198, '1.5.2'}).
|
-protocol({xep, 198, '1.5.2'}).
|
||||||
|
|
||||||
%% gen_mod API
|
%% gen_mod API
|
||||||
-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1]).
|
-export([start/2, stop/1, reload/3, depends/2, mod_opt_type/1, mod_options/1]).
|
||||||
%% hooks
|
%% hooks
|
||||||
-export([c2s_stream_init/2, c2s_stream_started/2, c2s_stream_features/2,
|
-export([c2s_stream_init/2, c2s_stream_started/2, c2s_stream_features/2,
|
||||||
c2s_authenticated_packet/2, c2s_unauthenticated_packet/2,
|
c2s_authenticated_packet/2, c2s_unauthenticated_packet/2,
|
||||||
@ -117,18 +117,17 @@ c2s_stream_init({ok, State}, Opts) ->
|
|||||||
c2s_stream_init(Acc, _Opts) ->
|
c2s_stream_init(Acc, _Opts) ->
|
||||||
Acc.
|
Acc.
|
||||||
|
|
||||||
c2s_stream_started(#{lserver := LServer, mgmt_options := Opts} = State,
|
c2s_stream_started(#{lserver := LServer} = State, _StreamStart) ->
|
||||||
_StreamStart) ->
|
|
||||||
State1 = maps:remove(mgmt_options, State),
|
State1 = maps:remove(mgmt_options, State),
|
||||||
ResumeTimeout = get_resume_timeout(LServer, Opts),
|
ResumeTimeout = get_configured_resume_timeout(LServer),
|
||||||
MaxResumeTimeout = get_max_resume_timeout(LServer, Opts, ResumeTimeout),
|
MaxResumeTimeout = get_max_resume_timeout(LServer, ResumeTimeout),
|
||||||
State1#{mgmt_state => inactive,
|
State1#{mgmt_state => inactive,
|
||||||
mgmt_queue_type => get_queue_type(LServer, Opts),
|
mgmt_queue_type => get_queue_type(LServer),
|
||||||
mgmt_max_queue => get_max_ack_queue(LServer, Opts),
|
mgmt_max_queue => get_max_ack_queue(LServer),
|
||||||
mgmt_timeout => ResumeTimeout,
|
mgmt_timeout => ResumeTimeout,
|
||||||
mgmt_max_timeout => MaxResumeTimeout,
|
mgmt_max_timeout => MaxResumeTimeout,
|
||||||
mgmt_ack_timeout => get_ack_timeout(LServer, Opts),
|
mgmt_ack_timeout => get_ack_timeout(LServer),
|
||||||
mgmt_resend => get_resend_on_timeout(LServer, Opts),
|
mgmt_resend => get_resend_on_timeout(LServer),
|
||||||
mgmt_stanzas_in => 0,
|
mgmt_stanzas_in => 0,
|
||||||
mgmt_stanzas_out => 0,
|
mgmt_stanzas_out => 0,
|
||||||
mgmt_stanzas_req => 0};
|
mgmt_stanzas_req => 0};
|
||||||
@ -711,39 +710,30 @@ bounce_message_queue() ->
|
|||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Configuration processing
|
%%% Configuration processing
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
get_max_ack_queue(Host, Opts) ->
|
get_max_ack_queue(Host) ->
|
||||||
gen_mod:get_module_opt(Host, ?MODULE, max_ack_queue,
|
gen_mod:get_module_opt(Host, ?MODULE, max_ack_queue).
|
||||||
gen_mod:get_opt(max_ack_queue, Opts, 5000)).
|
|
||||||
|
|
||||||
get_resume_timeout(Host, Opts) ->
|
get_configured_resume_timeout(Host) ->
|
||||||
gen_mod:get_module_opt(Host, ?MODULE, resume_timeout,
|
gen_mod:get_module_opt(Host, ?MODULE, resume_timeout).
|
||||||
gen_mod:get_opt(resume_timeout, Opts, 300)).
|
|
||||||
|
|
||||||
get_max_resume_timeout(Host, Opts, ResumeTimeout) ->
|
get_max_resume_timeout(Host, ResumeTimeout) ->
|
||||||
case gen_mod:get_module_opt(Host, ?MODULE, max_resume_timeout,
|
case gen_mod:get_module_opt(Host, ?MODULE, max_resume_timeout) of
|
||||||
gen_mod:get_opt(max_resume_timeout, Opts)) of
|
|
||||||
undefined -> ResumeTimeout;
|
undefined -> ResumeTimeout;
|
||||||
Max when Max >= ResumeTimeout -> Max;
|
Max when Max >= ResumeTimeout -> Max;
|
||||||
_ -> ResumeTimeout
|
_ -> ResumeTimeout
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_ack_timeout(Host, Opts) ->
|
get_ack_timeout(Host) ->
|
||||||
case gen_mod:get_module_opt(Host, ?MODULE, ack_timeout,
|
case gen_mod:get_module_opt(Host, ?MODULE, ack_timeout) of
|
||||||
gen_mod:get_opt(ack_timeout, Opts, 60)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
T -> timer:seconds(T)
|
T -> timer:seconds(T)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_resend_on_timeout(Host, Opts) ->
|
get_resend_on_timeout(Host) ->
|
||||||
gen_mod:get_module_opt(Host, ?MODULE, resend_on_timeout,
|
gen_mod:get_module_opt(Host, ?MODULE, resend_on_timeout).
|
||||||
gen_mod:get_opt(resend_on_timeout, Opts, false)).
|
|
||||||
|
|
||||||
get_queue_type(Host, Opts) ->
|
get_queue_type(Host) ->
|
||||||
case gen_mod:get_module_opt(Host, ?MODULE, queue_type,
|
gen_mod:get_module_opt(Host, ?MODULE, queue_type).
|
||||||
gen_mod:get_opt(queue_type, Opts)) of
|
|
||||||
undefined -> ejabberd_config:default_queue_type(Host);
|
|
||||||
Type -> Type
|
|
||||||
end.
|
|
||||||
|
|
||||||
mod_opt_type(max_ack_queue) ->
|
mod_opt_type(max_ack_queue) ->
|
||||||
fun(I) when is_integer(I), I > 0 -> I;
|
fun(I) when is_integer(I), I > 0 -> I;
|
||||||
@ -752,7 +742,9 @@ mod_opt_type(max_ack_queue) ->
|
|||||||
mod_opt_type(resume_timeout) ->
|
mod_opt_type(resume_timeout) ->
|
||||||
fun(I) when is_integer(I), I >= 0 -> I end;
|
fun(I) when is_integer(I), I >= 0 -> I end;
|
||||||
mod_opt_type(max_resume_timeout) ->
|
mod_opt_type(max_resume_timeout) ->
|
||||||
fun(I) when is_integer(I), I >= 0 -> I end;
|
fun(I) when is_integer(I), I >= 0 -> I;
|
||||||
|
(undefined) -> undefined
|
||||||
|
end;
|
||||||
mod_opt_type(ack_timeout) ->
|
mod_opt_type(ack_timeout) ->
|
||||||
fun(I) when is_integer(I), I > 0 -> I;
|
fun(I) when is_integer(I), I > 0 -> I;
|
||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
@ -762,7 +754,12 @@ mod_opt_type(resend_on_timeout) ->
|
|||||||
(if_offline) -> if_offline
|
(if_offline) -> if_offline
|
||||||
end;
|
end;
|
||||||
mod_opt_type(queue_type) ->
|
mod_opt_type(queue_type) ->
|
||||||
fun(ram) -> ram; (file) -> file end;
|
fun(ram) -> ram; (file) -> file end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[max_ack_queue, resume_timeout, max_resume_timeout, ack_timeout,
|
mod_options(Host) ->
|
||||||
resend_on_timeout, queue_type].
|
[{max_ack_queue, 5000},
|
||||||
|
{resume_timeout, 300},
|
||||||
|
{max_resume_timeout, undefined},
|
||||||
|
{ack_timeout, 60},
|
||||||
|
{resend_on_timeout, false},
|
||||||
|
{queue_type, ejabberd_config:default_queue_type(Host)}].
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, process_local_iq/1,
|
-export([start/2, stop/1, reload/3, process_local_iq/1,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -41,7 +41,7 @@
|
|||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
?NS_TIME, ?MODULE, process_local_iq, IQDisc).
|
?NS_TIME, ?MODULE, process_local_iq, IQDisc).
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ stop(Host) ->
|
|||||||
?NS_TIME).
|
?NS_TIME).
|
||||||
|
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(Host, NewOpts, OldOpts) ->
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_TIME,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_TIME,
|
||||||
?MODULE, process_local_iq, IQDisc);
|
?MODULE, process_local_iq, IQDisc);
|
||||||
@ -74,5 +74,7 @@ process_local_iq(#iq{type = get} = IQ) ->
|
|||||||
depends(_Host, _Opts) ->
|
depends(_Host, _Opts) ->
|
||||||
[].
|
[].
|
||||||
|
|
||||||
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
|
||||||
mod_opt_type(_) -> [iqdisc].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)}].
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, get_sm_features/5,
|
-export([start/2, stop/1, get_sm_features/5, mod_options/1,
|
||||||
process_local_iq/1, process_sm_iq/1, string2lower/1,
|
process_local_iq/1, process_sm_iq/1, string2lower/1,
|
||||||
remove_user/2, export/1, import_info/0, import/5, import_start/2,
|
remove_user/2, export/1, import_info/0, import/5, import_start/2,
|
||||||
depends/2, process_search/1, process_vcard/1, get_vcard/2,
|
depends/2, process_search/1, process_vcard/1, get_vcard/2,
|
||||||
@ -48,7 +48,6 @@
|
|||||||
-include("mod_vcard.hrl").
|
-include("mod_vcard.hrl").
|
||||||
-include("translate.hrl").
|
-include("translate.hrl").
|
||||||
|
|
||||||
-define(JUD_MATCHES, 30).
|
|
||||||
-define(VCARD_CACHE, vcard_cache).
|
-define(VCARD_CACHE, vcard_cache).
|
||||||
|
|
||||||
-callback init(binary(), gen_mod:opts()) -> any().
|
-callback init(binary(), gen_mod:opts()) -> any().
|
||||||
@ -89,7 +88,7 @@ init([Host, Opts]) ->
|
|||||||
init_cache(Mod, Host, Opts),
|
init_cache(Mod, Host, Opts),
|
||||||
ejabberd_hooks:add(remove_user, Host, ?MODULE,
|
ejabberd_hooks:add(remove_user, Host, ?MODULE,
|
||||||
remove_user, 50),
|
remove_user, 50),
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
?NS_VCARD, ?MODULE, process_local_iq, IQDisc),
|
?NS_VCARD, ?MODULE, process_local_iq, IQDisc),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
||||||
@ -97,8 +96,8 @@ init([Host, Opts]) ->
|
|||||||
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE,
|
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE,
|
||||||
get_sm_features, 50),
|
get_sm_features, 50),
|
||||||
ejabberd_hooks:add(vcard_iq_set, Host, ?MODULE, vcard_iq_set, 50),
|
ejabberd_hooks:add(vcard_iq_set, Host, ?MODULE, vcard_iq_set, 50),
|
||||||
MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
|
MyHosts = gen_mod:get_opt_hosts(Host, Opts),
|
||||||
Search = gen_mod:get_opt(search, Opts, false),
|
Search = gen_mod:get_opt(search, Opts),
|
||||||
if Search ->
|
if Search ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(MyHost) ->
|
fun(MyHost) ->
|
||||||
@ -122,7 +121,7 @@ init([Host, Opts]) ->
|
|||||||
false ->
|
false ->
|
||||||
?WARNING_MSG("vcard search functionality is "
|
?WARNING_MSG("vcard search functionality is "
|
||||||
"not implemented for ~s backend",
|
"not implemented for ~s backend",
|
||||||
[gen_mod:db_type(Host, Opts, ?MODULE)]);
|
[gen_mod:get_opt(db_type, Opts)]);
|
||||||
true ->
|
true ->
|
||||||
ejabberd_router:register_route(MyHost, Host)
|
ejabberd_router:register_route(MyHost, Host)
|
||||||
end
|
end
|
||||||
@ -289,7 +288,7 @@ disco_features(Acc, _From, _To, _Node, _Lang) ->
|
|||||||
binary(), binary()) -> [identity()].
|
binary(), binary()) -> [identity()].
|
||||||
disco_identity(Acc, _From, To, <<"">>, Lang) ->
|
disco_identity(Acc, _From, To, <<"">>, Lang) ->
|
||||||
Host = ejabberd_router:host_of_route(To#jid.lserver),
|
Host = ejabberd_router:host_of_route(To#jid.lserver),
|
||||||
Name = gen_mod:get_module_opt(Host, ?MODULE, name, ?T("vCard User Search")),
|
Name = gen_mod:get_module_opt(Host, ?MODULE, name),
|
||||||
[#identity{category = <<"directory">>,
|
[#identity{category = <<"directory">>,
|
||||||
type = <<"user">>,
|
type = <<"user">>,
|
||||||
name = translate:translate(Lang, Name)}|Acc];
|
name = translate:translate(Lang, Name)}|Acc];
|
||||||
@ -467,9 +466,8 @@ item_to_field(Items) ->
|
|||||||
search(LServer, XFields) ->
|
search(LServer, XFields) ->
|
||||||
Data = [{Var, Vals} || #xdata_field{var = Var, values = Vals} <- XFields],
|
Data = [{Var, Vals} || #xdata_field{var = Var, values = Vals} <- XFields],
|
||||||
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
||||||
AllowReturnAll = gen_mod:get_module_opt(LServer, ?MODULE, allow_return_all,
|
AllowReturnAll = gen_mod:get_module_opt(LServer, ?MODULE, allow_return_all),
|
||||||
false),
|
MaxMatch = gen_mod:get_module_opt(LServer, ?MODULE, matches),
|
||||||
MaxMatch = gen_mod:get_module_opt(LServer, ?MODULE, matches, ?JUD_MATCHES),
|
|
||||||
Mod:search(LServer, Data, AllowReturnAll, MaxMatch).
|
Mod:search(LServer, Data, AllowReturnAll, MaxMatch).
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
@ -492,16 +490,10 @@ init_cache(Mod, Host, Opts) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(_Host, Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -511,10 +503,7 @@ cache_opts(Host, Opts) ->
|
|||||||
use_cache(Mod, Host) ->
|
use_cache(Mod, Host) ->
|
||||||
case erlang:function_exported(Mod, use_cache, 1) of
|
case erlang:function_exported(Mod, use_cache, 1) of
|
||||||
true -> Mod:use_cache(Host);
|
true -> Mod:use_cache(Host);
|
||||||
false ->
|
false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
|
||||||
gen_mod:get_module_opt(
|
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host))
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_nodes(module(), binary()) -> [node()].
|
-spec cache_nodes(module(), binary()) -> [node()].
|
||||||
@ -556,15 +545,23 @@ mod_opt_type(matches) ->
|
|||||||
end;
|
end;
|
||||||
mod_opt_type(search) ->
|
mod_opt_type(search) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(search_all_hosts) ->
|
|
||||||
fun (B) when is_boolean(B) -> B end;
|
|
||||||
mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I;
|
fun (I) when is_integer(I), I > 0 -> I;
|
||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[allow_return_all, db_type, host, hosts, iqdisc, matches,
|
mod_options(Host) ->
|
||||||
search, search_all_hosts, cache_life_time, cache_size,
|
[{allow_return_all, false},
|
||||||
use_cache, cache_missed, name].
|
{host, <<"vjud.@HOST@">>},
|
||||||
|
{hosts, []},
|
||||||
|
{matches, 30},
|
||||||
|
{search, false},
|
||||||
|
{name, ?T("vCard User Search")},
|
||||||
|
{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||||
|
{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
-export([start_link/2]).
|
-export([start_link/2]).
|
||||||
-export([init/2, stop/1, get_vcard/2, set_vcard/4, search/4,
|
-export([init/2, stop/1, get_vcard/2, set_vcard/4, search/4,
|
||||||
remove_user/2, import/3, search_fields/1, search_reported/1,
|
remove_user/2, import/3, search_fields/1, search_reported/1,
|
||||||
mod_opt_type/1]).
|
mod_opt_type/1, mod_options/1]).
|
||||||
-export([is_search_supported/1]).
|
-export([is_search_supported/1]).
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
@ -303,26 +303,26 @@ process_pattern(Str, {User, Domain}, AttrValues) ->
|
|||||||
[{<<"%s">>, V, 1} || V <- AttrValues]).
|
[{<<"%s">>, V, 1} || V <- AttrValues]).
|
||||||
|
|
||||||
default_vcard_map() ->
|
default_vcard_map() ->
|
||||||
[{<<"NICKNAME">>, <<"%u">>, []},
|
[{<<"NICKNAME">>, [{<<"%u">>, []}]},
|
||||||
{<<"FN">>, <<"%s">>, [<<"displayName">>]},
|
{<<"FN">>, [{<<"%s">>, [<<"displayName">>]}]},
|
||||||
{<<"FAMILY">>, <<"%s">>, [<<"sn">>]},
|
{<<"FAMILY">>, [{<<"%s">>, [<<"sn">>]}]},
|
||||||
{<<"GIVEN">>, <<"%s">>, [<<"givenName">>]},
|
{<<"GIVEN">>, [{<<"%s">>, [<<"givenName">>]}]},
|
||||||
{<<"MIDDLE">>, <<"%s">>, [<<"initials">>]},
|
{<<"MIDDLE">>, [{<<"%s">>, [<<"initials">>]}]},
|
||||||
{<<"ORGNAME">>, <<"%s">>, [<<"o">>]},
|
{<<"ORGNAME">>, [{<<"%s">>, [<<"o">>]}]},
|
||||||
{<<"ORGUNIT">>, <<"%s">>, [<<"ou">>]},
|
{<<"ORGUNIT">>, [{<<"%s">>, [<<"ou">>]}]},
|
||||||
{<<"CTRY">>, <<"%s">>, [<<"c">>]},
|
{<<"CTRY">>, [{<<"%s">>, [<<"c">>]}]},
|
||||||
{<<"LOCALITY">>, <<"%s">>, [<<"l">>]},
|
{<<"LOCALITY">>, [{<<"%s">>, [<<"l">>]}]},
|
||||||
{<<"STREET">>, <<"%s">>, [<<"street">>]},
|
{<<"STREET">>, [{<<"%s">>, [<<"street">>]}]},
|
||||||
{<<"REGION">>, <<"%s">>, [<<"st">>]},
|
{<<"REGION">>, [{<<"%s">>, [<<"st">>]}]},
|
||||||
{<<"PCODE">>, <<"%s">>, [<<"postalCode">>]},
|
{<<"PCODE">>, [{<<"%s">>, [<<"postalCode">>]}]},
|
||||||
{<<"TITLE">>, <<"%s">>, [<<"title">>]},
|
{<<"TITLE">>, [{<<"%s">>, [<<"title">>]}]},
|
||||||
{<<"URL">>, <<"%s">>, [<<"labeleduri">>]},
|
{<<"URL">>, [{<<"%s">>, [<<"labeleduri">>]}]},
|
||||||
{<<"DESC">>, <<"%s">>, [<<"description">>]},
|
{<<"DESC">>, [{<<"%s">>, [<<"description">>]}]},
|
||||||
{<<"TEL">>, <<"%s">>, [<<"telephoneNumber">>]},
|
{<<"TEL">>, [{<<"%s">>, [<<"telephoneNumber">>]}]},
|
||||||
{<<"EMAIL">>, <<"%s">>, [<<"mail">>]},
|
{<<"EMAIL">>, [{<<"%s">>, [<<"mail">>]}]},
|
||||||
{<<"BDAY">>, <<"%s">>, [<<"birthDay">>]},
|
{<<"BDAY">>, [{<<"%s">>, [<<"birthDay">>]}]},
|
||||||
{<<"ROLE">>, <<"%s">>, [<<"employeeType">>]},
|
{<<"ROLE">>, [{<<"%s">>, [<<"employeeType">>]}]},
|
||||||
{<<"PHOTO">>, <<"%s">>, [<<"jpegPhoto">>]}].
|
{<<"PHOTO">>, [{<<"%s">>, [<<"jpegPhoto">>]}]}].
|
||||||
|
|
||||||
default_search_fields() ->
|
default_search_fields() ->
|
||||||
[{?T("User"), <<"%u">>},
|
[{?T("User"), <<"%u">>},
|
||||||
@ -352,16 +352,15 @@ default_search_reported() ->
|
|||||||
{?T("Organization Unit"), <<"ORGUNIT">>}].
|
{?T("Organization Unit"), <<"ORGUNIT">>}].
|
||||||
|
|
||||||
parse_options(Host, Opts) ->
|
parse_options(Host, Opts) ->
|
||||||
MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
|
MyHosts = gen_mod:get_opt_hosts(Host, Opts),
|
||||||
Search = gen_mod:get_opt(search, Opts, false),
|
Search = gen_mod:get_opt(search, Opts),
|
||||||
Matches = gen_mod:get_opt(matches, Opts, 30),
|
Matches = gen_mod:get_opt(matches, Opts),
|
||||||
Eldap_ID = misc:atom_to_binary(gen_mod:get_module_proc(Host, ?PROCNAME)),
|
Eldap_ID = misc:atom_to_binary(gen_mod:get_module_proc(Host, ?PROCNAME)),
|
||||||
Cfg = eldap_utils:get_config(Host, Opts),
|
Cfg = eldap_utils:get_config(Host, Opts),
|
||||||
UIDsTemp = gen_mod:get_opt({ldap_uids, Host}, Opts,
|
UIDsTemp = gen_mod:get_opt(ldap_uids, Opts),
|
||||||
[{<<"uid">>, <<"%u">>}]),
|
|
||||||
UIDs = eldap_utils:uids_domain_subst(Host, UIDsTemp),
|
UIDs = eldap_utils:uids_domain_subst(Host, UIDsTemp),
|
||||||
SubFilter = eldap_utils:generate_subfilter(UIDs),
|
SubFilter = eldap_utils:generate_subfilter(UIDs),
|
||||||
UserFilter = case gen_mod:get_opt({ldap_filter, Host}, Opts, <<"">>) of
|
UserFilter = case gen_mod:get_opt(ldap_filter, Opts) of
|
||||||
<<"">> ->
|
<<"">> ->
|
||||||
SubFilter;
|
SubFilter;
|
||||||
F ->
|
F ->
|
||||||
@ -370,11 +369,9 @@ parse_options(Host, Opts) ->
|
|||||||
{ok, SearchFilter} =
|
{ok, SearchFilter} =
|
||||||
eldap_filter:parse(eldap_filter:do_sub(UserFilter,
|
eldap_filter:parse(eldap_filter:do_sub(UserFilter,
|
||||||
[{<<"%u">>, <<"*">>}])),
|
[{<<"%u">>, <<"*">>}])),
|
||||||
VCardMap = gen_mod:get_opt(ldap_vcard_map, Opts, default_vcard_map()),
|
VCardMap = gen_mod:get_opt(ldap_vcard_map, Opts),
|
||||||
SearchFields = gen_mod:get_opt(ldap_search_fields, Opts,
|
SearchFields = gen_mod:get_opt(ldap_search_fields, Opts),
|
||||||
default_search_fields()),
|
SearchReported = gen_mod:get_opt(ldap_search_reported, Opts),
|
||||||
SearchReported = gen_mod:get_opt(ldap_search_reported, Opts,
|
|
||||||
default_search_reported()),
|
|
||||||
UIDAttrs = [UAttr || {UAttr, _} <- UIDs],
|
UIDAttrs = [UAttr || {UAttr, _} <- UIDs],
|
||||||
VCardMapAttrs = lists:usort(lists:append([A
|
VCardMapAttrs = lists:usort(lists:append([A
|
||||||
|| {_, _, A} <- VCardMap])
|
|| {_, _, A} <- VCardMap])
|
||||||
@ -412,7 +409,6 @@ parse_options(Host, Opts) ->
|
|||||||
search_reported_attrs = SearchReportedAttrs,
|
search_reported_attrs = SearchReportedAttrs,
|
||||||
matches = Matches}.
|
matches = Matches}.
|
||||||
|
|
||||||
mod_opt_type(ldap_filter) -> fun eldap_utils:check_filter/1;
|
|
||||||
mod_opt_type(ldap_search_fields) ->
|
mod_opt_type(ldap_search_fields) ->
|
||||||
fun (Ls) ->
|
fun (Ls) ->
|
||||||
[{iolist_to_binary(S), iolist_to_binary(P)}
|
[{iolist_to_binary(S), iolist_to_binary(P)}
|
||||||
@ -423,15 +419,6 @@ mod_opt_type(ldap_search_reported) ->
|
|||||||
[{iolist_to_binary(S), iolist_to_binary(P)}
|
[{iolist_to_binary(S), iolist_to_binary(P)}
|
||||||
|| {S, P} <- Ls]
|
|| {S, P} <- Ls]
|
||||||
end;
|
end;
|
||||||
mod_opt_type(ldap_uids) ->
|
|
||||||
fun (Us) ->
|
|
||||||
lists:map(fun ({U, P}) ->
|
|
||||||
{iolist_to_binary(U), iolist_to_binary(P)};
|
|
||||||
({U}) -> {iolist_to_binary(U)};
|
|
||||||
(U) -> {iolist_to_binary(U)}
|
|
||||||
end,
|
|
||||||
lists:flatten(Us))
|
|
||||||
end;
|
|
||||||
mod_opt_type(ldap_vcard_map) ->
|
mod_opt_type(ldap_vcard_map) ->
|
||||||
fun (Ls) ->
|
fun (Ls) ->
|
||||||
lists:map(fun ({S, [{P, L}]}) ->
|
lists:map(fun ({S, [{P, L}]}) ->
|
||||||
@ -440,48 +427,14 @@ mod_opt_type(ldap_vcard_map) ->
|
|||||||
end,
|
end,
|
||||||
Ls)
|
Ls)
|
||||||
end;
|
end;
|
||||||
mod_opt_type(deref_aliases) ->
|
mod_opt_type(Opt) ->
|
||||||
fun (never) -> never;
|
eldap_utils:opt_type(Opt).
|
||||||
(searching) -> searching;
|
|
||||||
(finding) -> finding;
|
mod_options(Host) ->
|
||||||
(always) -> always
|
[{ldap_search_fields, default_search_fields()},
|
||||||
end;
|
{ldap_search_reported, default_search_reported()},
|
||||||
mod_opt_type(ldap_backups) ->
|
{ldap_vcard_map, default_vcard_map()}
|
||||||
fun (L) -> [iolist_to_binary(H) || H <- L] end;
|
| lists:map(
|
||||||
mod_opt_type(ldap_base) -> fun iolist_to_binary/1;
|
fun({Opt, Default}) ->
|
||||||
mod_opt_type(ldap_deref_aliases) ->
|
{Opt, ejabberd_config:get_option({Opt, Host}, Default)}
|
||||||
fun (never) -> never;
|
end, eldap_utils:options(Host))].
|
||||||
(searching) -> searching;
|
|
||||||
(finding) -> finding;
|
|
||||||
(always) -> always
|
|
||||||
end;
|
|
||||||
mod_opt_type(ldap_encrypt) ->
|
|
||||||
fun (tls) -> tls;
|
|
||||||
(starttls) -> starttls;
|
|
||||||
(none) -> none
|
|
||||||
end;
|
|
||||||
mod_opt_type(ldap_password) -> fun iolist_to_binary/1;
|
|
||||||
mod_opt_type(ldap_port) ->
|
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
|
||||||
mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1;
|
|
||||||
mod_opt_type(ldap_servers) ->
|
|
||||||
fun (L) -> [iolist_to_binary(H) || H <- L] end;
|
|
||||||
mod_opt_type(ldap_tls_cacertfile) ->
|
|
||||||
fun misc:try_read_file/1;
|
|
||||||
mod_opt_type(ldap_tls_certfile) ->
|
|
||||||
fun ejabberd_pkix:try_certfile/1;
|
|
||||||
mod_opt_type(ldap_tls_depth) ->
|
|
||||||
fun (I) when is_integer(I), I >= 0 -> I end;
|
|
||||||
mod_opt_type(ldap_tls_verify) ->
|
|
||||||
fun (hard) -> hard;
|
|
||||||
(soft) -> soft;
|
|
||||||
(false) -> false
|
|
||||||
end;
|
|
||||||
mod_opt_type(_) ->
|
|
||||||
[ldap_filter, ldap_search_fields,
|
|
||||||
ldap_search_reported, ldap_uids, ldap_vcard_map,
|
|
||||||
deref_aliases, ldap_backups, ldap_base,
|
|
||||||
ldap_deref_aliases, ldap_encrypt, ldap_password,
|
|
||||||
ldap_port, ldap_rootdn, ldap_servers,
|
|
||||||
ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth,
|
|
||||||
ldap_tls_verify].
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
search_fields/1, search_reported/1, remove_user/2]).
|
search_fields/1, search_reported/1, remove_user/2]).
|
||||||
-export([is_search_supported/1]).
|
-export([is_search_supported/1]).
|
||||||
-export([need_transform/1, transform/1]).
|
-export([need_transform/1, transform/1]).
|
||||||
|
-export([mod_opt_type/1, mod_options/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
@ -193,8 +194,7 @@ filter_fields([{SVar, [Val]} | Ds], Match, LServer)
|
|||||||
NewMatch = case SVar of
|
NewMatch = case SVar of
|
||||||
<<"user">> ->
|
<<"user">> ->
|
||||||
case gen_mod:get_module_opt(LServer, ?MODULE,
|
case gen_mod:get_module_opt(LServer, ?MODULE,
|
||||||
search_all_hosts,
|
search_all_hosts) of
|
||||||
true) of
|
|
||||||
true -> Match#vcard_search{luser = make_val(LVal)};
|
true -> Match#vcard_search{luser = make_val(LVal)};
|
||||||
false ->
|
false ->
|
||||||
Host = find_my_host(LServer),
|
Host = find_my_host(LServer),
|
||||||
@ -265,3 +265,9 @@ record_to_item(R) ->
|
|||||||
{<<"email">>, (R#vcard_search.email)},
|
{<<"email">>, (R#vcard_search.email)},
|
||||||
{<<"orgname">>, (R#vcard_search.orgname)},
|
{<<"orgname">>, (R#vcard_search.orgname)},
|
||||||
{<<"orgunit">>, (R#vcard_search.orgunit)}].
|
{<<"orgunit">>, (R#vcard_search.orgunit)}].
|
||||||
|
|
||||||
|
mod_opt_type(search_all_hosts) ->
|
||||||
|
fun (B) when is_boolean(B) -> B end.
|
||||||
|
|
||||||
|
mod_options(_) ->
|
||||||
|
[{search_all_hosts, true}].
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
-export([start/2, stop/1, reload/3]).
|
-export([start/2, stop/1, reload/3]).
|
||||||
|
|
||||||
-export([update_presence/1, vcard_set/1, remove_user/2,
|
-export([update_presence/1, vcard_set/1, remove_user/2,
|
||||||
user_send_packet/1, mod_opt_type/1, depends/2]).
|
user_send_packet/1, mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -141,23 +141,17 @@ db_get_xupdate(LUser, LServer) ->
|
|||||||
init_cache(Host, Opts) ->
|
init_cache(Host, Opts) ->
|
||||||
case use_cache(Host) of
|
case use_cache(Host) of
|
||||||
true ->
|
true ->
|
||||||
CacheOpts = cache_opts(Host, Opts),
|
CacheOpts = cache_opts(Opts),
|
||||||
ets_cache:new(?VCARD_XUPDATE_CACHE, CacheOpts);
|
ets_cache:new(?VCARD_XUPDATE_CACHE, CacheOpts);
|
||||||
false ->
|
false ->
|
||||||
ets_cache:delete(?VCARD_XUPDATE_CACHE)
|
ets_cache:delete(?VCARD_XUPDATE_CACHE)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
|
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||||
cache_opts(Host, Opts) ->
|
cache_opts(Opts) ->
|
||||||
MaxSize = gen_mod:get_opt(
|
MaxSize = gen_mod:get_opt(cache_size, Opts),
|
||||||
cache_size, Opts,
|
CacheMissed = gen_mod:get_opt(cache_missed, Opts),
|
||||||
ejabberd_config:cache_size(Host)),
|
LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
|
||||||
CacheMissed = gen_mod:get_opt(
|
|
||||||
cache_missed, Opts,
|
|
||||||
ejabberd_config:cache_missed(Host)),
|
|
||||||
LifeTime = case gen_mod:get_opt(
|
|
||||||
cache_life_time, Opts,
|
|
||||||
ejabberd_config:cache_life_time(Host)) of
|
|
||||||
infinity -> infinity;
|
infinity -> infinity;
|
||||||
I -> timer:seconds(I)
|
I -> timer:seconds(I)
|
||||||
end,
|
end,
|
||||||
@ -165,9 +159,7 @@ cache_opts(Host, Opts) ->
|
|||||||
|
|
||||||
-spec use_cache(binary()) -> boolean().
|
-spec use_cache(binary()) -> boolean().
|
||||||
use_cache(Host) ->
|
use_cache(Host) ->
|
||||||
gen_mod:get_module_opt(
|
gen_mod:get_module_opt(Host, ?MODULE, use_cache).
|
||||||
Host, ?MODULE, use_cache,
|
|
||||||
ejabberd_config:use_cache(Host)).
|
|
||||||
|
|
||||||
-spec compute_hash(xmlel()) -> binary() | external.
|
-spec compute_hash(xmlel()) -> binary() | external.
|
||||||
compute_hash(VCard) ->
|
compute_hash(VCard) ->
|
||||||
@ -195,6 +187,10 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
|
|||||||
(infinity) -> infinity
|
(infinity) -> infinity
|
||||||
end;
|
end;
|
||||||
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
mod_opt_type(O) when O == use_cache; O == cache_missed ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) ->
|
|
||||||
[cache_life_time, cache_size, use_cache, cache_missed].
|
mod_options(Host) ->
|
||||||
|
[{use_cache, ejabberd_config:use_cache(Host)},
|
||||||
|
{cache_size, ejabberd_config:cache_size(Host)},
|
||||||
|
{cache_missed, ejabberd_config:cache_missed(Host)},
|
||||||
|
{cache_life_time, ejabberd_config:cache_life_time(Host)}].
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, reload/3, process_local_iq/1,
|
-export([start/2, stop/1, reload/3, process_local_iq/1,
|
||||||
mod_opt_type/1, depends/2]).
|
mod_opt_type/1, mod_options/1, depends/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -40,7 +40,7 @@
|
|||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
start(Host, Opts) ->
|
start(Host, Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
?NS_VERSION, ?MODULE, process_local_iq,
|
?NS_VERSION, ?MODULE, process_local_iq,
|
||||||
IQDisc).
|
IQDisc).
|
||||||
@ -50,7 +50,7 @@ stop(Host) ->
|
|||||||
?NS_VERSION).
|
?NS_VERSION).
|
||||||
|
|
||||||
reload(Host, NewOpts, OldOpts) ->
|
reload(Host, NewOpts, OldOpts) ->
|
||||||
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
|
case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
|
||||||
{false, IQDisc, _} ->
|
{false, IQDisc, _} ->
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VERSION,
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VERSION,
|
||||||
?MODULE, process_local_iq, IQDisc);
|
?MODULE, process_local_iq, IQDisc);
|
||||||
@ -63,7 +63,7 @@ process_local_iq(#iq{type = set, lang = Lang} = IQ) ->
|
|||||||
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
|
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
|
||||||
process_local_iq(#iq{type = get, to = To} = IQ) ->
|
process_local_iq(#iq{type = get, to = To} = IQ) ->
|
||||||
Host = To#jid.lserver,
|
Host = To#jid.lserver,
|
||||||
OS = case gen_mod:get_module_opt(Host, ?MODULE, show_os, true) of
|
OS = case gen_mod:get_module_opt(Host, ?MODULE, show_os) of
|
||||||
true -> get_os();
|
true -> get_os();
|
||||||
false -> undefined
|
false -> undefined
|
||||||
end,
|
end,
|
||||||
@ -87,5 +87,8 @@ depends(_Host, _Opts) ->
|
|||||||
|
|
||||||
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
|
||||||
mod_opt_type(show_os) ->
|
mod_opt_type(show_os) ->
|
||||||
fun (B) when is_boolean(B) -> B end;
|
fun (B) when is_boolean(B) -> B end.
|
||||||
mod_opt_type(_) -> [iqdisc, show_os].
|
|
||||||
|
mod_options(Host) ->
|
||||||
|
[{iqdisc, gen_iq_handler:iqdisc(Host)},
|
||||||
|
{show_os, true}].
|
||||||
|
Loading…
Reference in New Issue
Block a user