-define(NS_HTTP_BIND,
<<"http://jabber.org/protocol/httpbind">>).
--define(DEFAULT_MAXPAUSE, 120).
-
-define(DEFAULT_WAIT, 300).
-define(DEFAULT_HOLD, 1).
-define(DEFAULT_POLLING, 2).
--define(DEFAULT_INACTIVITY, 30).
-
-define(MAX_SHAPED_REQUESTS_QUEUE_LEN, 1000).
-define(SEND_TIMEOUT, 15000).
inactivity_timer :: reference() | undefined,
wait_timer :: reference() | undefined,
wait_timeout = ?DEFAULT_WAIT :: timeout(),
- inactivity_timeout = ?DEFAULT_INACTIVITY :: timeout(),
+ inactivity_timeout :: timeout(),
prev_rid = 0 :: non_neg_integer(),
prev_key = <<"">> :: binary(),
prev_poll :: erlang:timestamp() | undefined,
XMPPVer = get_attr('xmpp:version', Attrs),
XMPPDomain = get_attr(to, Attrs),
{InBuf, Opts} = case gen_mod:get_module_opt(
- XMPPDomain, mod_bosh, prebind, false) of
+ XMPPDomain, mod_bosh, prebind) of
true ->
JID = make_random_jid(XMPPDomain),
{buf_new(XMPPDomain), [{jid, JID} | Opts2]};
xmpp_socket:start(ejabberd_c2s, ?MODULE, Socket,
[{receiver, self()}|Opts]),
Inactivity = gen_mod:get_module_opt(XMPPDomain,
- mod_bosh, max_inactivity,
- ?DEFAULT_INACTIVITY),
- MaxConcat = gen_mod:get_module_opt(XMPPDomain, mod_bosh, max_concat,
- unlimited),
+ mod_bosh, max_inactivity),
+ MaxConcat = gen_mod:get_module_opt(XMPPDomain, mod_bosh, max_concat),
ShapedReceivers = buf_new(XMPPDomain, ?MAX_SHAPED_REQUESTS_QUEUE_LEN),
State = #state{host = XMPPDomain, sid = SID, ip = IP,
xmpp_ver = XMPPVer, el_ibuf = InBuf,
true -> {undefined, []}
end,
MaxPause = gen_mod:get_module_opt(State#state.host,
- mod_bosh, max_pause,
- ?DEFAULT_MAXPAUSE),
+ mod_bosh, max_pause),
Resp = #body{attrs =
[{sid, State#state.sid}, {wait, Wait},
{ver, ?BOSH_VERSION}, {polling, ?DEFAULT_POLLING},
buf_new(Host, Limit) ->
QueueType = gen_mod:get_module_opt(
- Host, mod_bosh, queue_type,
- ejabberd_config:default_queue_type(Host)),
+ Host, mod_bosh, queue_type),
p1_queue:new(QueueType, Limit).
buf_in(Xs, Buf) ->
#presence{from = From, to = To, type = Type} = Pres) ->
if Type == subscribe; Type == subscribed;
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),
case acl:match_rule(LServer, Access, MyBareJID) of
deny ->
end;
listen_opt_type(max_fsm_queue) ->
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) ->
- ?WARNING_MSG("listening option 'stream_management' is deprecated: "
- "use mod_stream_mgmt module", []),
+ ?ERROR_MSG("listening option 'stream_management' is ignored: "
+ "use mod_stream_mgmt module", []),
fun(B) when is_boolean(B) -> B end;
listen_opt_type(O) ->
- case mod_stream_mgmt:mod_opt_type(O) of
- L when is_list(L) ->
+ StreamOpts = mod_stream_mgmt:mod_options(?MYNAME),
+ case lists:keyfind(O, 1, StreamOpts) of
+ false ->
[access, shaper, certfile, ciphers, dhfile, cafile,
protocol_options, tls, tls_compression, starttls,
starttls_required, tls_verify, zlib, max_fsm_queue];
- VFun ->
- ?WARNING_MSG("listening option '~s' is deprecated: use '~s' "
- "option from mod_stream_mgmt module", [O, O]),
- VFun
+ _ ->
+ ?ERROR_MSG("Listening option '~s' is ignored: use '~s' "
+ "option from mod_stream_mgmt module", [O, O]),
+ mod_stream_mgmt:mod_opt_type(O)
end.
-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_vh_by_auth_method/1,
get_version/0, get_myhosts/0, get_mylang/0, get_lang/1,
get_ejabberd_config_path/0, is_using_elixir_config/0,
prepare_opt_val/4, transform_options/1, collect_options/1,
start() ->
ConfigFile = get_ejabberd_config_path(),
?INFO_MSG("Loading configuration from ~s", [ConfigFile]),
- p1_options:start_link(ejabberd_options),
- p1_options:start_link(ejabberd_db_modules),
+ catch ets:new(ejabberd_options,
+ [named_table, public, {read_concurrency, true}]),
+ catch ets:new(ejabberd_db_modules,
+ [named_table, public, {read_concurrency, true}]),
State1 = load_file(ConfigFile),
UnixTime = p1_time_compat:system_time(seconds),
SharedKey = case erlang:get_cookie() of
%% At the moment, these functions are mainly used to setup unit tests.
-spec start(Hosts :: [binary()], Opts :: [acl:acl() | local_config()]) -> ok.
start(Hosts, Opts) ->
- p1_options:start_link(ejabberd_options),
- p1_options:start_link(ejabberd_db_modules),
+ catch ets:new(ejabberd_options,
+ [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})),
ok.
set_opts(State) ->
Opts = State#state.opts,
- ets:select_delete(ejabberd_options,
- ets:fun2ms(
- fun({{node_start, _}, _}) -> false;
- ({{shared_key, _}, _}) -> false;
- (_) -> true
- end)),
- 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),
+ ets:insert(
+ ejabberd_options,
+ lists:map(
+ fun(#local_config{key = Key, value = Val}) ->
+ {Key, Val}
+ end, Opts)),
set_log_level().
set_log_level() ->
add_option(Opt, Val) when is_atom(Opt) ->
add_option({Opt, global}, Val);
add_option({Opt, Host}, Val) ->
- p1_options:insert(ejabberd_options, Opt, Host, Val),
- p1_options:compile(ejabberd_options).
+ ets:insert(ejabberd_options, {{Opt, Host}, Val}).
-spec prepare_opt_val(any(), any(), check_fun(), any()) -> any().
"format. This is likely a bug", [Opt]),
{undefined, global}
end,
- case ejabberd_options:is_known(Key) of
- true ->
- case ejabberd_options:Key(Host) of
- {ok, Val} -> Val;
- undefined -> Default
+ try ets:lookup_element(ejabberd_options, {Key, Host}, 2)
+ catch _:badarg when Host /= global ->
+ try ets:lookup_element(ejabberd_options, {Key, global}, 2)
+ catch _:badarg -> Default
end;
- false ->
+ _:badarg ->
Default
end.
init_module_db_table(Modules) ->
%% Dirty hack for mod_pubsub
- p1_options: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, mnesia}, true}),
+ ets:insert(ejabberd_db_modules, {{mod_pubsub, sql}, true}),
lists:foreach(
fun(M) ->
case re:split(atom_to_list(M), "_", [{return, list}]) of
BareMod = list_to_atom(string:join(lists:reverse(T), "_")),
case is_behaviour(BareMod, M) of
true ->
- p1_options:insert(ejabberd_db_modules,
- BareMod, Suffix, true);
+ ets:insert(ejabberd_db_modules,
+ {{BareMod, Suffix}, true});
false ->
ok
end
end
- end, Modules),
- p1_options:compile(ejabberd_db_modules).
+ end, Modules).
is_behaviour(Behav, Mod) ->
try Mod:module_info(attributes) of
v_db(Mod, internal) -> v_db(Mod, mnesia);
v_db(Mod, odbc) -> v_db(Mod, sql);
v_db(Mod, Type) ->
- case ejabberd_db_modules:is_known(Mod) of
- true ->
- case ejabberd_db_modules:Mod(Type) of
- {ok, _} -> Type;
- _ -> erlang:error(badarg)
- end;
- false ->
- erlang:error(badarg)
+ case ets:member(ejabberd_db_modules, {Mod, Type}) of
+ true -> Type;
+ false -> erlang:error(badarg)
end.
-spec v_dbs(module()) -> [atom()].
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()].
end, Opts),
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
is_file_readable(Path) ->
case file:read_file_info(Path) of
+++ /dev/null
-%%%-------------------------------------------------------------------
-%%% @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
-%%%===================================================================
transform_options(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()}].
validate_module_options(Module, Opts) ->
- try Module:listen_opt_type('') of
+ try known_listen_options(Module) of
_ ->
maybe_start_zlib(Opts),
lists:filtermap(
+++ /dev/null
-%%%-------------------------------------------------------------------
-%%% @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
-%%%===================================================================
%% The pages of a vhost are only accesible if the user is admin of that vhost:
get_acl_rule([<<"server">>, VHost | _RPath], Method)
when Method =:= 'GET' orelse Method =:= 'HEAD' ->
- AC = gen_mod:get_module_opt(VHost, ejabberd_web_admin,
- access, configure),
- ACR = gen_mod:get_module_opt(VHost, ejabberd_web_admin,
- access_readonly, webadmin_view),
+ AC = ejabberd_config:get_option({access, VHost}, configure),
+ ACR = ejabberd_config:get_option({access_readonly, VHost}, webadmin_view),
{VHost, [AC, ACR]};
get_acl_rule([<<"server">>, VHost | _RPath], 'POST') ->
- AC = gen_mod:get_module_opt(VHost, ejabberd_web_admin,
- access, configure),
+ AC = ejabberd_config:get_option({access, VHost}, configure),
{VHost, [AC]};
%% Default rule: only global admins can access any other random page
get_acl_rule(_RPath, Method)
when Method =:= 'GET' orelse Method =:= 'HEAD' ->
- AC = gen_mod:get_module_opt(global, ejabberd_web_admin,
- access, configure),
- ACR = gen_mod:get_module_opt(global, ejabberd_web_admin,
- access_readonly, webadmin_view),
+ AC = ejabberd_config:get_option(access, configure),
+ ACR = ejabberd_config:get_option(access_readonly, webadmin_view),
{global, [AC, ACR]};
get_acl_rule(_RPath, 'POST') ->
- AC = gen_mod:get_module_opt(global, ejabberd_web_admin,
- access, configure),
+ AC = ejabberd_config:get_option(access, configure),
{global, [AC]}.
%%%==================================
end.
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">>}];
_ -> []
end.
%%-----------------------------------------------------------------------
connect_bind(S) ->
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 ->
[{packet, asn1}, {active, true}, {keepalive, true},
binary
[{packet, asn1}, {active, true}, {keepalive, true},
{send_timeout, ?SEND_TIMEOUT}, binary]
end,
+ ?DEBUG("Connecting to LDAP server at ~s:~p with options ~p",
+ [Host, S#eldap.port, Opts]),
HostS = binary_to_list(Host),
SocketData = case S#eldap.tls of
tls ->
{ok, connecting, NewS#eldap{host = Host}}
end;
{error, Reason} ->
- ?ERROR_MSG("LDAP connection failed:~n** Server: "
- "~s:~p~n** Reason: ~p~n** Socket options: ~p",
- [Host, S#eldap.port, Reason, Opts]),
+ ?ERROR_MSG("LDAP connection to ~s:~b failed: ~s",
+ [Host, S#eldap.port, format_error(SockMod, Reason)]),
NewS = close_and_retry(S),
{ok, connecting, NewS#eldap{host = Host}}
end.
when Id > (?MAX_TRANSACTION_ID) ->
?MIN_TRANSACTION_ID;
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.
-export([generate_subfilter/1, find_ldap_attrs/2, check_filter/1,
get_ldap_attr/2, get_user_part/2, make_filter/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("logger.hrl").
TLSCertFile = get_opt(ldap_tls_certfile, Host, Opts),
TLSCAFile = get_opt(ldap_tls_cacertfile, 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
tls -> ?LDAPS_PORT;
starttls -> ?LDAP_PORT;
_ -> ?LDAP_PORT
- end),
+ end;
+ P ->
+ P
+ end,
RootDN = get_opt(ldap_rootdn, Host, Opts, <<"">>),
Password = get_opt(ldap_password, Host, Opts, <<"">>),
Base = get_opt(ldap_base, Host, Opts, <<"">>),
(ldap_uids) -> fun((uids()) -> uids());
(atom()) -> [atom()].
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) ->
fun (L) -> [iolist_to_binary(H) || H <- L] end;
opt_type(ldap_base) -> fun iolist_to_binary/1;
end;
opt_type(ldap_password) -> fun iolist_to_binary/1;
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_servers) ->
fun (L) -> [iolist_to_binary(H) || H <- L] end;
opt_type(ldap_tls_certfile) ->
- fun(S) ->
- binary_to_list(ejabberd_pkix:try_certfile(S))
+ fun(undefined) -> undefined;
+ (S) -> binary_to_list(ejabberd_pkix:try_certfile(S))
end;
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) ->
- 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) ->
fun (hard) -> hard;
(soft) -> soft;
(false) -> false
end;
opt_type(ldap_filter) ->
- fun check_filter/1;
+ fun(<<"">>) -> <<"">>;
+ (F) -> check_filter(F)
+ end;
opt_type(ldap_uids) ->
fun (Us) ->
lists:map(fun ({U, P}) ->
ldap_port, ldap_rootdn, ldap_servers, ldap_filter,
ldap_tls_certfile, ldap_tls_cacertfile, ldap_tls_depth,
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}].
stop_child/1, stop_child/2, config_reloaded/0]).
-export([start_module/2, start_module/3,
stop_module/2, stop_module_keep_config/2,
- get_opt/2, get_opt/3, get_opt_host/3,
- get_opt_hosts/3, opt_type/1, is_equal_opt/4,
- get_module_opt/3, get_module_opt/4, get_module_opt_host/3,
+ get_opt/2, get_opt_hosts/2, opt_type/1, is_equal_opt/3,
+ get_module_opt/3, get_module_opt_host/3,
loaded_modules/1, loaded_modules_with_opts/1,
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,
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
--export([get_opt/4, get_module_opt/5]).
--deprecated([{get_opt, 4}, {get_module_opt, 5}]).
+-export([get_opt/3, get_opt/4, get_module_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("logger.hrl").
-callback stop(binary()) -> any().
-callback reload(binary(), opts(), opts()) -> ok | {ok, pid()}.
-callback mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()].
+-callback mod_options(binary()) -> opts().
-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([db_type/0]).
end, ?MYHOSTS).
get_modules_options(Host) ->
- ejabberd_config:get_option({modules, Host}, []).
+ sort_modules(Host, ejabberd_config:get_option({modules, Host})).
sort_modules(Host, ModOpts) ->
G = digraph:new([acyclic]),
case lists:keyfind(DepMod, 1, ModOpts) of
false when Type == hard ->
ErrTxt = io_lib:format(
- "failed to load module '~s' "
+ "Failed to load module '~s' "
"because it depends on module '~s' "
"which is not found in the config",
[Mod, DepMod]),
digraph:del_vertex(G, Mod),
maybe_halt_ejabberd(ErrTxt);
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 "
"the config",
[DepMod, Mod]);
digraph:add_vertex(G, DepMod, DepOpts),
case digraph:add_edge(G, DepMod, Mod) of
{error, {bad_edge, Path}} ->
- ?WARNING_MSG("cyclic dependency detected "
+ ?WARNING_MSG("Cyclic dependency detected "
"between modules: ~p",
[Path]);
_ ->
-spec start_modules(binary()) -> ok.
start_modules(Host) ->
- Modules = sort_modules(Host, get_modules_options(Host)),
+ Modules = get_modules_options(Host),
lists:foreach(
fun({Module, Opts}) ->
start_module(Host, Module, Opts)
-spec start_module(binary(), atom(), opts(), boolean()) -> ok | {ok, pid()}.
start_module(Host, Module, Opts0, NeedValidation) ->
- ?DEBUG("loading ~s at ~s", [Module, Host]),
- Opts = if NeedValidation ->
- validate_opts(Host, Module, Opts0);
- true ->
- Opts0
- end,
- store_options(Host, Module, Opts),
- try case Module:start(Host, Opts) of
- ok -> ok;
- {ok, Pid} when is_pid(Pid) -> {ok, Pid};
- Err -> erlang:error(Err)
- end
- catch Class:Reason ->
- ets:delete(ejabberd_modules, {Module, Host}),
- ErrorText =
- io_lib:format("Problem starting the module ~s for host "
- "~s ~n options: ~p~n ~p: ~p~n~p",
- [Module, Host, Opts, Class, Reason,
- erlang:get_stacktrace()]),
- ?CRITICAL_MSG(ErrorText, []),
- maybe_halt_ejabberd(ErrorText),
- erlang:raise(Class, Reason, erlang:get_stacktrace())
+ ?DEBUG("Loading ~s at ~s", [Module, Host]),
+ Res = if NeedValidation ->
+ validate_opts(Host, Module, Opts0);
+ true ->
+ {ok, Opts0}
+ end,
+ case Res of
+ {ok, Opts} ->
+ store_options(Host, Module, Opts),
+ try case Module:start(Host, Opts) of
+ ok -> ok;
+ {ok, Pid} when is_pid(Pid) -> {ok, Pid};
+ Err -> erlang:error(Err)
+ end
+ catch Class:Reason ->
+ ets:delete(ejabberd_modules, {Module, Host}),
+ ErrorText =
+ io_lib:format("Problem starting the module ~s for host "
+ "~s ~n options: ~p~n ~p: ~p~n~p",
+ [Module, Host, Opts, Class, Reason,
+ erlang:get_stacktrace()]),
+ ?CRITICAL_MSG(ErrorText, []),
+ maybe_halt_ejabberd(ErrorText),
+ erlang:raise(Class, Reason, erlang:get_stacktrace())
+ end;
+ {error, ErrorText} ->
+ maybe_halt_ejabberd(ErrorText)
end.
-spec reload_modules(binary()) -> ok.
reload_modules(Host) ->
- NewMods = ejabberd_config:get_option({modules, Host}, []),
+ NewMods = ejabberd_config:get_option({modules, Host}),
OldMods = ets:select(
ejabberd_modules,
ets:fun2ms(
case lists:keyfind(Mod, 1, NewMods) of
{_, NewOpts0} ->
case validate_opts(Host, Mod, NewOpts0) of
- OldOpts ->
+ {ok, OldOpts} ->
ok;
- NewOpts ->
- reload_module(Host, Mod, NewOpts, OldOpts)
+ {ok, NewOpts} ->
+ reload_module(Host, Mod, NewOpts, OldOpts);
+ {error, _} ->
+ ok
end;
_ ->
ok
reload_module(Host, Module, NewOpts, OldOpts) ->
case erlang:function_exported(Module, reload, 3) of
true ->
- ?DEBUG("reloading ~s at ~s", [Module, Host]),
+ ?DEBUG("Reloading ~s at ~s", [Module, Host]),
store_options(Host, Module, NewOpts),
try case Module:reload(Host, NewOpts, OldOpts) of
ok -> ok;
end
catch Class:Reason ->
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",
[Module, Host,
{Class, {Reason, StackTrace}}]),
erlang:raise(Class, Reason, StackTrace)
end;
false ->
- ?WARNING_MSG("module ~s doesn't support reloading "
+ ?WARNING_MSG("Module ~s doesn't support reloading "
"and will be restarted", [Module]),
stop_module(Host, Module),
start_module(Host, Module, NewOpts, false)
-spec stop_modules(binary()) -> ok.
stop_modules(Host) ->
- Modules = get_modules_options(Host),
+ Modules = lists:reverse(get_modules_options(Host)),
lists:foreach(
fun({Module, _Args}) ->
stop_module_keep_config(Host, Module)
-spec stop_module(binary(), atom()) -> error | {aborted, any()} | {atomic, any()}.
stop_module(Host, Module) ->
- ?DEBUG("stopping ~s at ~s", [Module, Host]),
case stop_module_keep_config(Host, Module) of
error -> error;
ok -> ok
-spec stop_module_keep_config(binary(), atom()) -> error | ok.
stop_module_keep_config(Host, Module) ->
+ ?DEBUG("Stopping ~s at ~s", [Module, Host]),
case catch Module:stop(Host) of
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), error;
{wait, ProcList} when is_list(ProcList) ->
-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, 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, 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) ->
case lists:keyfind(Opt, 1, Opts) of
false ->
Val = get_opt(host, Opts, Default),
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) ->
- Vals = case get_opt(host, Opts, undefined) of
- undefined ->
- case get_opt(hosts, Opts, []) of
- [] -> [Default];
- L -> L
- end;
- Val ->
- [Val]
+ Vals = case get_opt(hosts, Opts) of
+ L when L == [] orelse L == undefined ->
+ case get_opt(host, Opts) of
+ undefined -> [Default];
+ H -> [H]
+ end;
+ L ->
+ L
end,
[ejabberd_regexp:greplace(V, <<"@HOST@">>, Host) || V <- Vals].
--spec get_validators(binary(), module(), opts()) -> dict:dict() | undef.
-get_validators(Host, Module, Opts) ->
- try Module:mod_opt_type('') of
- L ->
- 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(
- fun(Mod, D) ->
- try Mod:mod_opt_type('') of
- Os ->
- lists:foldl(
- fun({Opt, SubOpt} = O, Acc) ->
- SubF = Mod:mod_opt_type(O),
- F = case Mod:mod_opt_type(Opt) of
- F1 when is_function(F1) ->
- F1;
- _ ->
- fun(X) -> X end
- end,
- dict:append_list(
- Opt, [F, {SubOpt, [SubF]}], Acc);
- (O, Acc) ->
- F = Mod:mod_opt_type(O),
- dict:store(O, [F], Acc)
- end, D, Os)
- catch _:undef ->
- D
- end
- end, dict:new(), [Module|SubMods1 ++ SubMods2])
- catch _:undef ->
- ?WARNING_MSG("module '~s' doesn't export mod_opt_type/1",
- [Module]),
- undef
+-spec get_validators(binary(), {module(), [module()]}) -> list() | undef.
+get_validators(Host, {Module, SubMods}) ->
+ Validators =
+ dict:to_list(
+ lists:foldl(
+ fun(Mod, D) ->
+ try list_known_opts(Host, Mod) of
+ Os ->
+ lists:foldl(
+ fun({Opt, SubOpt} = O, Acc) ->
+ SubF = Mod:mod_opt_type(O),
+ F = try Mod:mod_opt_type(Opt)
+ catch _:_ -> fun(X) -> X end
+ end,
+ dict:append_list(
+ Opt, [F, {SubOpt, [SubF]}], Acc);
+ (O, Acc) ->
+ F = Mod:mod_opt_type(O),
+ dict:store(O, [F], Acc)
+ end, D, Os)
+ catch _:undef ->
+ D
+ end
+ end, dict:new(), [Module|SubMods])),
+ case Validators of
+ [] ->
+ case have_validators(Module) of
+ false ->
+ ?WARNING_MSG("Third-party module '~s' doesn't export "
+ "options validator; consider to upgrade "
+ "the module", [Module]),
+ undef;
+ true ->
+ []
+ end;
+ _ ->
+ Validators
end.
--spec validate_opts(binary(), module(), opts()) -> opts().
-validate_opts(Host, Module, Opts) ->
- case get_validators(Host, Module, Opts) of
- undef ->
- Opts;
- Validators ->
- validate_opts(Host, Module, Opts, dict:to_list(Validators))
+-spec have_validators(module()) -> boolean().
+have_validators(Module) ->
+ 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 ->
+ Opts;
+ 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.
-validate_opts(Host, Module, Opts, Validators) when is_list(Opts) ->
+validate_opts(Host, Module, Opts, Required, Validators) when is_list(Opts) ->
lists:flatmap(
fun({Opt, Val}) when is_atom(Opt) ->
case lists:keyfind(Opt, 1, Validators) of
{_, L} ->
case lists:partition(fun is_function/1, L) of
{[VFun|_], []} ->
- validate_opt(Module, Opt, Val, VFun);
+ validate_opt(Module, Opt, Val, Required, VFun);
{[VFun|_], SubValidators} ->
- try validate_opts(Host, Module, Val, SubValidators) of
+ try validate_opts(Host, Module, Val, Required, SubValidators) of
SubOpts ->
- validate_opt(Module, Opt, SubOpts, VFun)
+ validate_opt(Module, Opt, SubOpts, Required, VFun)
catch _:bad_option ->
- ?ERROR_MSG("ignoring invalid value '~p' for "
+ ?ERROR_MSG("Ignoring invalid value '~p' for "
"option '~s' of module '~s'",
[Val, Opt, Module]),
+ fail_if_option_is_required(Opt, Required),
[]
end
end;
false ->
case Validators of
[] ->
- ?ERROR_MSG("unknown option '~s' for module '~s' "
- "will be likely ignored because the "
- "module doesn't have any options",
+ ?ERROR_MSG("Ignoring unknown option '~s' of '~s':"
+ " the module doesn't have any options",
[Opt, Module]);
_ ->
- ?ERROR_MSG("unknown option '~s' for module '~s' will be"
- " likely ignored, available options are: ~s",
+ ?ERROR_MSG("Ignoring unknown option '~s' of '~s',"
+ " available options are: ~s",
[Opt, Module,
- misc:join_atoms([K || {K, _} <- Validators],
- <<", ">>)])
+ misc:join_atoms(
+ [K || {K, _} <- Validators],
+ <<", ">>)])
end,
- [{Opt, Val}]
+ []
end;
(_) ->
erlang:error(bad_option)
end, Opts);
-validate_opts(_, _, _, _) ->
+validate_opts(_, _, _, _, _) ->
erlang:error(bad_option).
--spec validate_opt(module(), atom(), any(),
+-spec validate_opt(module(), atom(), any(), [atom()],
[{atom(), check_fun(), any()}]) -> [{atom(), any()}].
-validate_opt(Module, Opt, Val, VFun) ->
+validate_opt(Module, Opt, Val, Required, VFun) ->
try VFun(Val) of
NewVal -> [{Opt, NewVal}]
catch {invalid_syntax, Error} ->
- ?ERROR_MSG("ignoring invalid value '~p' for "
+ ?ERROR_MSG("Ignoring invalid value '~p' for "
"option '~s' of module '~s': ~s",
[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'",
[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.
ram_db_mod(Host, Opts, Module) when is_list(Opts) ->
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()].
loaded_modules(Host) ->
reload_modules(Host)
end, ?MYHOSTS).
--spec is_equal_opt(atom(), opts(), opts(), any()) ->
+-spec is_equal_opt(atom(), opts(), opts()) ->
true | {false, any(), any()}.
-is_equal_opt(Opt, NewOpts, OldOpts, Default) ->
- NewVal = get_opt(Opt, NewOpts, Default),
- OldVal = get_opt(Opt, OldOpts, Default),
+is_equal_opt(Opt, NewOpts, OldOpts) ->
+ NewVal = get_opt(Opt, NewOpts),
+ OldVal = get_opt(Opt, OldOpts),
if NewVal /= OldVal ->
{false, NewVal, OldVal};
true ->
process_sm_iq/1, get_local_commands/5,
get_local_identity/5, get_local_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("logger.hrl").
-include("xmpp.hrl").
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_COMMANDS, ?MODULE, process_local_iq,
IQDisc),
?NS_COMMANDS).
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_COMMANDS,
?MODULE, process_local_iq, IQDisc),
#jid{server = Server, lserver = LServer} = _To, <<"">>,
Lang) ->
Display = gen_mod:get_module_opt(LServer, ?MODULE,
- report_commands_node,
- false),
+ report_commands_node),
case Display of
false -> Acc;
_ ->
get_sm_commands(Acc, _From,
#jid{lserver = LServer} = To, <<"">>, Lang) ->
Display = gen_mod:get_module_opt(LServer, ?MODULE,
- report_commands_node,
- false),
+ report_commands_node),
case Display of
false -> Acc;
_ ->
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(report_commands_node) ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) -> [iqdisc, report_commands_node].
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)},
+ {report_commands_node, false}].
-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]).
% Commands API
|| X <- binary_to_list(crypto:hash(sha, AccountPass))]).
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).
%% Code based on ejabberd/src/web/ejabberd_web_admin.erl
is_glob_match(String, Glob) ->
is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
-mod_opt_type(_) -> [].
+mod_options(_) -> [].
-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]).
% Commands API
ok
end.
-mod_opt_type(_) -> [].
+mod_options(_) -> [].
import_start/2, import/5, announce/1, send_motd/1, disco_identity/5,
disco_features/5, disco_items/5, depends/2,
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,
handle_info/2, terminate/2, code_change/3]).
-export([announce_all/1,
-spec get_access(global | binary()) -> atom().
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().
add_store_hint(El) ->
init_cache(Mod, Host, Opts) ->
case use_cache(Mod, Host) of
true ->
- CacheOpts = cache_opts(Host, Opts),
+ CacheOpts = cache_opts(Opts),
ets_cache:new(?MOTD_CACHE, CacheOpts);
false ->
ets_cache:delete(?MOTD_CACHE)
end.
--spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
use_cache(Mod, Host) ->
case erlang:function_exported(Mod, use_cache, 1) of
true -> Mod:use_cache(Host);
- false ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
end.
-spec cache_nodes(module(), binary()) -> [node()].
(infinity) -> infinity
end;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) ->
- [access, db_type, cache_life_time, cache_size,
- use_cache, cache_missed].
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(Host) ->
+ [{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)}].
-behaviour(gen_mod).
%% 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
-export([pubsub_publish_item/6, vcard_iq_convert/1, vcard_iq_publish/1]).
-spec get_converting_rules(binary()) -> convert_rules().
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.
get_type(Data) ->
false ->
fail(From);
true ->
- case eimp:is_supported(To) of
+ case eimp:is_supported(To) orelse To == undefined of
false -> fail(To);
true -> To
end
end
- end;
-mod_opt_type(_) ->
- [{convert, T} || T <- [default|eimp:supported_formats()]].
+ end.
+
+mod_options(_) ->
+ [{convert,
+ [{T, undefined} || T <- [default|eimp:supported_formats()]]}].
%% API
-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]).
check_message(#message{from = From, to = To, lang = Lang} = Msg) ->
LServer = To#jid.lserver,
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
Msg#message.subject == [])
orelse ((AllowLocalUsers orelse From#jid.luser == <<"">>) andalso
false ->
case check_subscription(From, To) of
none ->
- Drop = gen_mod:get_module_opt(LServer, ?MODULE, drop, true),
- Log = gen_mod:get_module_opt(LServer, ?MODULE, log, false),
+ Drop = gen_mod:get_module_opt(LServer, ?MODULE, drop),
+ Log = gen_mod:get_module_opt(LServer, ?MODULE, log),
if
Log ->
?INFO_MSG("~s message from stranger ~s to ~s",
none;
{none, _} ->
case gen_mod:get_module_opt(LocalServer, ?MODULE,
- allow_transports, true) of
+ allow_transports) of
true ->
%% Check if the contact's server is in the roster
case ejabberd_hooks:run_fold(
mod_opt_type(allow_local_users) ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(allow_transports) ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) -> [drop, log, allow_local_users, allow_transports].
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(_) ->
+ [{drop, true},
+ {log, false},
+ {allow_local_users, true},
+ {allow_transports, true}].
-protocol({xep, 191, '1.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("logger.hrl").
-include("mod_privacy.hrl").
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),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
?NS_BLOCKING, ?MODULE, process_iq, IQDisc).
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING).
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING,
?MODULE, process_iq, IQDisc);
Txt = <<"Database failure">>,
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].
+mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)}].
-export([start/2, stop/1, reload/3, process/2, open_session/2,
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("logger.hrl").
%%% Internal functions
%%%===================================================================
start_jiffy(Opts) ->
- case gen_mod:get_opt(json, Opts, false) of
+ case gen_mod:get_opt(json, Opts) of
false ->
ok;
true ->
fun(I) when is_integer(I), I>0 -> I;
(unlimited) -> infinity;
(infinity) -> infinity
- end;
-mod_opt_type(_) ->
- [json, max_concat, max_inactivity, max_pause, prebind, ram_db_type,
- queue_type, use_cache, cache_size, cache_missed, cache_life_time].
+ end.
+
+mod_options(Host) ->
+ [{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
use_cache(Mod) ->
case erlang:function_exported(Mod, use_cache, 0) of
true -> Mod:use_cache();
- false ->
- gen_mod:get_module_opt(
- global, ?MODULE, use_cache,
- ejabberd_config:use_cache(global))
+ false -> gen_mod:get_module_opt(global, ?MODULE, use_cache)
end.
-spec cache_nodes(module()) -> [node()].
-spec cache_opts() -> [proplists:property()].
cache_opts() ->
- MaxSize = gen_mod:get_module_opt(
- global, ?MODULE, cache_size,
- ejabberd_config:cache_size(global)),
- 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
+ MaxSize = gen_mod:get_module_opt(global, ?MODULE, cache_size),
+ CacheMissed = gen_mod:get_module_opt(global, ?MODULE, cache_missed),
+ LifeTime = case gen_mod:get_module_opt(global, ?MODULE, cache_life_time) of
infinity -> infinity;
I -> timer:seconds(I)
end,
handle_cast/2, terminate/2, code_change/3]).
-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("logger.hrl").
true ->
ok
end,
- case gen_mod:is_equal_opt(cache_size, NewOpts, OldOpts,
- ejabberd_config:cache_size(Host)) of
+ case gen_mod:is_equal_opt(cache_size, NewOpts, OldOpts) of
{false, MaxSize, _} ->
ets_cache:setopts(caps_features_cache, [{max_size, MaxSize}]),
ets_cache:setopts(caps_requests_cache, [{max_size, MaxSize}]);
true ->
ok
end,
- case gen_mod:is_equal_opt(cache_life_time, NewOpts, OldOpts,
- ejabberd_config:cache_life_time(Host)) of
+ case gen_mod:is_equal_opt(cache_life_time, NewOpts, OldOpts) of
{false, Time, _} ->
LifeTime = case Time of
infinity -> infinity;
init([Host, Opts]) ->
process_flag(trap_exit, true),
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
- init_cache(Host, Opts),
+ init_cache(Opts),
Mod:init(Host, Opts),
ejabberd_hooks:add(c2s_presence_in, Host, ?MODULE,
c2s_presence_in, 75),
false
end.
-init_cache(Host, Opts) ->
- CacheOpts = cache_opts(Host, Opts),
- case use_cache(Host, Opts) of
+init_cache(Opts) ->
+ CacheOpts = cache_opts(Opts),
+ case use_cache(Opts) of
true ->
ets_cache:new(caps_features_cache, CacheOpts);
false ->
[{max_size, CacheSize},
{life_time, timer:seconds(?BAD_HASH_LIFETIME)}]).
-use_cache(Host, Opts) ->
- gen_mod:get_opt(use_cache, Opts, ejabberd_config:use_cache(Host)).
+use_cache(Opts) ->
+ gen_mod:get_opt(use_cache, Opts).
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
end;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
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(_) ->
- [cache_life_time, cache_size, use_cache, cache_missed, db_type].
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end.
+
+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)}].
-export([user_send_packet/1, user_receive_packet/1,
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("logger.hrl").
false.
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),
Mod = gen_mod:ram_db_mod(Host, ?MODULE),
init_cache(Mod, Host, Opts),
end,
case use_cache(NewMod, Host) of
true ->
- ets_cache:new(?CARBONCOPY_CACHE, cache_opts(Host, NewOpts));
+ ets_cache:new(?CARBONCOPY_CACHE, cache_opts(NewOpts));
false ->
ok
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2,
?MODULE, iq_handler, IQDisc);
init_cache(Mod, Host, Opts) ->
case use_cache(Mod, Host) of
true ->
- ets_cache:new(?CARBONCOPY_CACHE, cache_opts(Host, Opts));
+ ets_cache:new(?CARBONCOPY_CACHE, cache_opts(Opts));
false ->
ets_cache:delete(?CARBONCOPY_CACHE)
end.
--spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
use_cache(Mod, Host) ->
case erlang:function_exported(Mod, use_cache, 1) of
true -> Mod:use_cache(Host);
- false ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
end.
-spec cache_nodes(module(), binary()) -> [node()].
fun(I) when is_integer(I), I>0 -> I;
(unlimited) -> infinity;
(infinity) -> infinity
- end;
-mod_opt_type(_) ->
- [ram_db_type, iqdisc, use_cache, cache_size, cache_missed, cache_life_time].
+ end.
+
+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)}].
-behavior(gen_mod).
%% 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.
-export([filter_presence/1, filter_chat_states/1,
%%--------------------------------------------------------------------
-spec start(binary(), gen_mod:opts()) -> ok.
start(Host, Opts) ->
- QueuePresence = gen_mod:get_opt(queue_presence, Opts, true),
- QueueChatStates = gen_mod:get_opt(queue_chat_states, Opts, true),
- QueuePEP = gen_mod:get_opt(queue_pep, Opts, true),
+ QueuePresence = gen_mod:get_opt(queue_presence, Opts),
+ QueueChatStates = gen_mod:get_opt(queue_chat_states, Opts),
+ QueuePEP = gen_mod:get_opt(queue_pep, Opts),
if QueuePresence; QueueChatStates; QueuePEP ->
register_hooks(Host),
if QueuePresence ->
-spec stop(binary()) -> ok.
stop(Host) ->
- QueuePresence = gen_mod:get_module_opt(Host, ?MODULE, queue_presence, true),
- QueueChatStates = gen_mod:get_module_opt(Host, ?MODULE, queue_chat_states, true),
- QueuePEP = gen_mod:get_module_opt(Host, ?MODULE, queue_pep, true),
+ QueuePresence = gen_mod:get_module_opt(Host, ?MODULE, queue_presence),
+ QueueChatStates = gen_mod:get_module_opt(Host, ?MODULE, queue_chat_states),
+ QueuePEP = gen_mod:get_module_opt(Host, ?MODULE, queue_pep),
if QueuePresence; QueueChatStates; QueuePEP ->
unregister_hooks(Host),
if QueuePresence ->
-spec reload(binary(), gen_mod:opts(), gen_mod:opts()) -> ok.
reload(Host, NewOpts, _OldOpts) ->
- QueuePresence = gen_mod:get_opt(queue_presence, NewOpts, true),
- QueueChatStates = gen_mod:get_opt(queue_chat_states, NewOpts, true),
- QueuePEP = gen_mod:get_opt(queue_pep, NewOpts, true),
+ QueuePresence = gen_mod:get_opt(queue_presence, NewOpts),
+ QueueChatStates = gen_mod:get_opt(queue_chat_states, NewOpts),
+ QueuePEP = gen_mod:get_opt(queue_pep, NewOpts),
if QueuePresence; QueueChatStates; QueuePEP ->
register_hooks(Host);
true ->
mod_opt_type(queue_chat_states) ->
fun(B) when is_boolean(B) -> B end;
mod_opt_type(queue_pep) ->
- fun(B) when is_boolean(B) -> B end;
-mod_opt_type(_) -> [queue_presence, queue_chat_states, queue_pep].
+ fun(B) when is_boolean(B) -> B end.
+
+mod_options(_) ->
+ [{queue_presence, true},
+ {queue_chat_states, true},
+ {queue_pep, true}].
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
depends(_Host, _Opts) ->
get_local_features/5, get_local_items/5,
adhoc_local_items/4, adhoc_local_commands/4,
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
- adhoc_sm_items/4, adhoc_sm_commands/4, mod_opt_type/1,
+ adhoc_sm_items/4, adhoc_sm_commands/4, mod_options/1,
depends/2]).
-include("ejabberd.hrl").
set_sm_form(_User, _Server, _Node, _Request) ->
{error, xmpp:err_service_unavailable()}.
-mod_opt_type(_) -> [].
+mod_options(_) -> [].
-behaviour(gen_mod).
%% 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
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
Access = proplists:get_value(access, Opts, none),
{NS, Attrs, Access}
end, L)
- end;
-mod_opt_type(_) ->
- [namespaces, iqdisc].
+ end.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)},
+ {namespaces, []}].
depends(_, _) ->
[].
ServerHost = State#state.server_host,
To = jid:make(Host),
NSAttrsAccessList = gen_mod:get_module_opt(
- ServerHost, ?MODULE, namespaces, []),
+ ServerHost, ?MODULE, namespaces),
lists:foreach(
fun({NS, _Attrs, Access}) ->
case acl:match_rule(ServerHost, Access, To) of
get_local_features/5, get_local_services/5,
process_sm_iq_items/1, process_sm_iq_info/1,
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("logger.hrl").
-type items_acc() :: {error, stanza_error()} | {result, [disco_item()]} | empty.
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_DISCO_ITEMS, ?MODULE,
process_local_iq_items, IQDisc),
catch ets:new(disco_extra_domains,
[named_table, ordered_set, public,
{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) ->
register_extra_domain(Host, Domain)
end,
ok.
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} ->
lists:foreach(
fun(Domain) ->
true ->
ok
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
?NS_DISCO_ITEMS, ?MODULE,
binary(), binary()) -> [identity()].
get_local_identity(Acc, _From, To, <<"">>, _Lang) ->
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">>,
type = <<"im">>,
name = Name}];
-spec get_fields(binary(), module()) -> [xdata_field()].
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, _, _}) ->
case Modules of
all -> true;
{Mods, Name, URLs}
end,
L)
- end;
-mod_opt_type(_) -> [extra_domains, iqdisc, server_info, name].
+ end.
+
+mod_options(Host) ->
+ [{extra_domains, []},
+ {iqdisc, gen_iq_handler:iqdisc(Host)},
+ {server_info, []},
+ {name, ?T("ejabberd")}].
-export([init/1, handle_call/3, handle_cast/2,
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("logger.hrl").
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(_) -> [host, hosts].
+ fun(L) -> lists:map(fun iolist_to_binary/1, L) end.
+
+mod_options(_Host) ->
+ [{host, <<"echo.@HOST@">>}, {hosts, []}].
%%====================================================================
%% gen_server callbacks
%%--------------------------------------------------------------------
init([Host, Opts]) ->
process_flag(trap_exit, true),
- Hosts = gen_mod:get_opt_hosts(Host, Opts,
- <<"echo.@HOST@">>),
+ Hosts = gen_mod:get_opt_hosts(Host, Opts),
lists:foreach(
fun(H) ->
ejabberd_router:register_route(H, Host)
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast({reload, Host, NewOpts, OldOpts}, State) ->
- NewMyHosts = gen_mod:get_opt_hosts(Host, NewOpts,
- <<"echo.@HOST@">>),
- OldMyHosts = gen_mod:get_opt_hosts(Host, OldOpts,
- <<"echo.@HOST@">>),
+ NewMyHosts = gen_mod:get_opt_hosts(Host, NewOpts),
+ OldMyHosts = gen_mod:get_opt_hosts(Host, OldOpts),
lists:foreach(
fun(H) ->
ejabberd_router:unregister_route(H)
-export([init/1, handle_call/3, handle_cast/2,
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("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
--define(C2S_AUTH_BAN_LIFETIME, 3600). %% 1 hour
--define(C2S_MAX_AUTH_FAILURES, 20).
-define(CLEAN_INTERVAL, timer:minutes(10)).
-record(state, {host = <<"">> :: binary()}).
State;
false ->
BanLifetime = gen_mod:get_module_opt(
- LServer, ?MODULE, c2s_auth_ban_lifetime,
- ?C2S_AUTH_BAN_LIFETIME),
+ LServer, ?MODULE, c2s_auth_ban_lifetime),
MaxFailures = gen_mod:get_module_opt(
- LServer, ?MODULE, c2s_max_auth_failures,
- ?C2S_MAX_AUTH_FAILURES),
+ LServer, ?MODULE, c2s_max_auth_failures),
UnbanTS = p1_time_compat:system_time(seconds) + BanLifetime,
Attempts = case ets:lookup(failed_auth, Addr) of
[{Addr, N, _, _}] ->
{stop, ejabberd_c2s:send(State, Err)}.
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.
seconds_to_now(Secs) ->
mod_opt_type(c2s_auth_ban_lifetime) ->
fun (T) when is_integer(T), T > 0 -> T end;
mod_opt_type(c2s_max_auth_failures) ->
- fun (I) when is_integer(I), I > 0 -> I end;
-mod_opt_type(_) ->
- [access, c2s_auth_ban_lifetime, c2s_max_auth_failures].
+ fun (I) when is_integer(I), I > 0 -> I end.
+
+mod_options(_Host) ->
+ [{access, none},
+ {c2s_auth_ban_lifetime, 3600}, %% one hour
+ {c2s_max_auth_failures, 20}].
-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("xmpp.hrl").
NonListArgs.
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),
R = case Rules of
all ->
end, {1, []}, R),
Res.
-mod_opt_type(admin_ip_access) -> fun acl:access_rules_validator/1;
-mod_opt_type(_) -> [admin_ip_access].
+mod_opt_type(admin_ip_access) -> fun acl:access_rules_validator/1.
+mod_options(_) -> [{admin_ip_access, none}].
%% utility for other http modules
-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("logger.hrl").
-define(HTTP_ERR_HOST_UNKNOWN,
{-1, 410, [], <<"Host unknown">>}).
--define(DEFAULT_CONTENT_TYPE,
- <<"application/octet-stream">>).
-
-define(DEFAULT_CONTENT_TYPES,
[{<<".css">>, <<"text/css">>},
{<<".gif">>, <<"image/gif">>},
initialize(Host, 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),
AccessLogFD = try_open_log(AccessLog, Host),
- DirectoryIndices = gen_mod:get_opt(directory_indices, Opts, []),
- CustomHeaders = gen_mod:get_opt(custom_headers, Opts, []),
- DefaultContentType = gen_mod:get_opt(default_content_type, Opts,
- ?DEFAULT_CONTENT_TYPE),
- UserAccess0 = gen_mod:get_opt(must_authenticate_with, Opts, []),
+ DirectoryIndices = gen_mod:get_opt(directory_indices, Opts),
+ CustomHeaders = gen_mod:get_opt(custom_headers, Opts),
+ DefaultContentType = gen_mod:get_opt(default_content_type, Opts),
+ UserAccess0 = gen_mod:get_opt(must_authenticate_with, Opts),
UserAccess = case UserAccess0 of
[] -> none;
_ ->
dict:from_list(UserAccess0)
end,
ContentTypes = build_list_content_types(
- gen_mod:get_opt(content_types, Opts, []),
+ gen_mod:get_opt(content_types, Opts),
?DEFAULT_CONTENT_TYPES),
?DEBUG("known content types: ~s",
[str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes],
|| {Extension, Value} <- CTsUnfiltered,
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) ->
undefined;
try_open_log(FN, _Host) ->
Parts = lists:map(fun (Int) -> io_lib:format("~.16B", [Int]) end, tuple_to_list(Address)),
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) ->
fun(L) when is_list(L) ->
lists:map(
fun iolist_to_binary/1;
mod_opt_type(directory_indices) ->
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) ->
fun (L) when is_list(L) ->
lists:map(fun(UP) when is_binary(UP) ->
[K, V] = binary:split(UP, <<":">>),
{K, V}
end, L)
- end;
-mod_opt_type(_) ->
- [accesslog, content_types, custom_headers,
- default_content_type, directory_indices, docroot,
- must_authenticate_with].
+ end.
+
+mod_options(_) ->
+ [{accesslog, undefined},
+ {content_types, []},
+ {default_content_type, <<"application/octet-stream">>},
+ {custom_headers, []},
+ {directory_indices, []},
+ {must_authenticate_with, []},
+ %% Required option
+ docroot].
-export([start/2,
stop/1,
depends/2,
- mod_opt_type/1]).
+ mod_opt_type/1,
+ mod_options/1]).
%% gen_server callbacks.
-export([init/1,
-spec start(binary(), gen_mod:opts()) -> {ok, pid()}.
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 ->
ejabberd_hooks:add(remove_user, ServerHost, ?MODULE,
remove_user, 50);
-spec stop(binary()) -> ok | {error, any()}.
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 ->
ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE,
remove_user, 50);
(node) -> node
end;
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) ->
- fun(Mode) -> ?STR_TO_INT(Mode, 8) end;
+ fun(undefined) -> undefined;
+ (Mode) -> ?STR_TO_INT(Mode, 8)
+ end;
mod_opt_type(docroot) ->
fun iolist_to_binary/1;
mod_opt_type(put_url) ->
end;
mod_opt_type(get_url) ->
fun(<<"http://", _/binary>> = URL) -> URL;
- (<<"https://", _/binary>> = URL) -> URL
+ (<<"https://", _/binary>> = URL) -> URL;
+ (undefined) -> undefined
end;
mod_opt_type(service_url) ->
fun(<<"http://", _/binary>> = URL) -> URL;
- (<<"https://", _/binary>> = URL) -> URL
+ (<<"https://", _/binary>> = URL) -> URL;
+ (undefined) -> undefined
end;
mod_opt_type(custom_headers) ->
fun(Headers) ->
end;
(false) ->
false
- end;
-mod_opt_type(_) ->
- [host, hosts, name, access, max_size, secret_length, jid_in_url, file_mode,
- dir_mode, docroot, put_url, get_url, service_url, custom_headers,
- rm_on_unregister, thumbnail].
+ end.
+
+mod_options(_Host) ->
+ [{host, <<"upload.@HOST@">>},
+ {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}].
init([ServerHost, Opts]) ->
process_flag(trap_exit, true),
- Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"upload.@HOST@">>),
- Name = gen_mod:get_opt(name, Opts, ?T("HTTP File Upload")),
- Access = gen_mod:get_opt(access, Opts, local),
- MaxSize = gen_mod:get_opt(max_size, Opts, 104857600),
- SecretLength = gen_mod:get_opt(secret_length, Opts, 40),
- JIDinURL = gen_mod:get_opt(jid_in_url, Opts, sha1),
- DocRoot = gen_mod:get_opt(docroot, Opts, <<"@HOME@/upload">>),
+ Hosts = gen_mod:get_opt_hosts(ServerHost, Opts),
+ Name = gen_mod:get_opt(name, Opts),
+ Access = gen_mod:get_opt(access, Opts),
+ MaxSize = gen_mod:get_opt(max_size, Opts),
+ SecretLength = gen_mod:get_opt(secret_length, Opts),
+ JIDinURL = gen_mod:get_opt(jid_in_url, Opts),
+ DocRoot = gen_mod:get_opt(docroot, Opts),
FileMode = gen_mod:get_opt(file_mode, Opts),
DirMode = gen_mod:get_opt(dir_mode, Opts),
- PutURL = gen_mod:get_opt(put_url, Opts, <<"http://@HOST@:5444">>),
- GetURL = gen_mod:get_opt(get_url, Opts, PutURL),
+ PutURL = gen_mod:get_opt(put_url, Opts),
+ GetURL = case gen_mod:get_opt(get_url, Opts) of
+ undefined -> PutURL;
+ URL -> URL
+ end,
ServiceURL = gen_mod:get_opt(service_url, Opts),
- Thumbnail = gen_mod:get_opt(thumbnail, Opts, true),
- CustomHeaders = gen_mod:get_opt(custom_headers, Opts, []),
+ Thumbnail = gen_mod:get_opt(thumbnail, Opts),
+ CustomHeaders = gen_mod:get_opt(custom_headers, Opts),
DocRoot1 = expand_home(str:strip(DocRoot, right, $/)),
DocRoot2 = expand_host(DocRoot1, ServerHost),
case DirMode of
-spec get_proc_name(binary(), atom()) -> atom().
get_proc_name(ServerHost, ModuleName) ->
- PutURL = gen_mod:get_module_opt(ServerHost, ?MODULE, put_url,
- <<"http://@HOST@">>),
+ PutURL = gen_mod:get_module_opt(ServerHost, ?MODULE, put_url),
{ok, {_Scheme, _UserInfo, Host, _Port, Path, _Query}} =
http_uri:parse(binary_to_list(expand_host(PutURL, ServerHost))),
ProcPrefix = list_to_binary(string:strip(Host ++ Path, right, $/)),
-spec iq_disco_info(binary(), binary(), binary(), [xdata()]) -> disco_info().
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 ->
AddInfo;
MaxSize ->
remove_user(User, Server) ->
ServerHost = jid:nameprep(Server),
- DocRoot = gen_mod:get_module_opt(ServerHost, ?MODULE, docroot,
- <<"@HOME@/upload">>),
- JIDinURL = gen_mod:get_module_opt(ServerHost, ?MODULE, jid_in_url, sha1),
+ DocRoot = gen_mod:get_module_opt(ServerHost, ?MODULE, docroot),
+ JIDinURL = gen_mod:get_module_opt(ServerHost, ?MODULE, jid_in_url),
DocRoot1 = expand_host(expand_home(DocRoot), ServerHost),
UserStr = make_user_string(jid:make(User, Server), JIDinURL),
UserDir = str:join([DocRoot1, UserStr], <<$/>>),
-export([start/2,
stop/1,
depends/2,
- mod_opt_type/1]).
+ mod_opt_type/1,
+ mod_options/1]).
%% gen_server callbacks.
-export([init/1,
mod_opt_type(max_days) ->
fun(I) when is_integer(I), I > 0 -> I;
(infinity) -> infinity
- end;
-mod_opt_type(_) ->
- [access_soft_quota, access_hard_quota, max_days].
+ end.
+
+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}].
init([ServerHost, Opts]) ->
process_flag(trap_exit, true),
- AccessSoftQuota = gen_mod:get_opt(access_soft_quota, Opts,
- soft_upload_quota),
- AccessHardQuota = gen_mod:get_opt(access_hard_quota, Opts,
- hard_upload_quota),
- MaxDays = gen_mod:get_opt(max_days, Opts, infinity),
- DocRoot1 = gen_mod:get_module_opt(ServerHost, mod_http_upload, docroot,
- <<"@HOME@/upload">>),
+ AccessSoftQuota = gen_mod:get_opt(access_soft_quota, Opts),
+ AccessHardQuota = gen_mod:get_opt(access_hard_quota, Opts),
+ MaxDays = gen_mod:get_opt(max_days, Opts),
+ DocRoot1 = gen_mod:get_module_opt(ServerHost, mod_http_upload, docroot),
DocRoot2 = mod_http_upload:expand_home(str:strip(DocRoot1, right, $/)),
DocRoot3 = mod_http_upload:expand_host(DocRoot2, ServerHost),
Timers = if MaxDays == infinity -> [];
-export([init/1, handle_call/3, handle_cast/2,
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("logger.hrl").
-include("mod_irc.hrl").
-include("translate.hrl").
--define(DEFAULT_IRC_ENCODING, <<"iso8859-15">>).
-
-define(DEFAULT_IRC_PORT, 6667).
--define(DEFAULT_REALNAME, <<"WebIRC-User">>).
-
--define(DEFAULT_WEBIRC_PASSWORD, <<"">>).
-
-define(POSSIBLE_ENCODINGS,
[<<"koi8-r">>, <<"iso8859-15">>, <<"iso8859-1">>, <<"iso8859-2">>,
<<"utf-8">>, <<"utf-8+latin-1">>]).
init([Host, Opts]) ->
process_flag(trap_exit, true),
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:init(Host, Opts),
- Access = gen_mod:get_opt(access, Opts, all),
+ Access = gen_mod:get_opt(access, Opts),
catch ets:new(irc_connection,
[named_table, public,
{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(
fun(MyHost) ->
register_hooks(MyHost, IQDisc),
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
- NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts, <<"irc.@HOST@">>),
- OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts, <<"irc.@HOST@">>),
- NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
- OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
+ NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts),
+ OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts),
+ NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts),
+ OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts),
NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?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 ->
NewMod:init(ServerHost, NewOpts);
true ->
ejabberd_router:unregister_route(OldHost),
unregister_hooks(OldHost)
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}};
handle_cast(Msg, State) ->
?WARNING_MSG("unexpected cast: ~p", [Msg]),
ets:delete(irc_connection, {From, Server, Host}).
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{
identities = [#identity{category = <<"conference">>,
type = <<"irc">>,
IRCServer).
get_default_encoding(ServerHost) ->
- Result = gen_mod:get_module_opt(ServerHost, ?MODULE, default_encoding,
- ?DEFAULT_IRC_ENCODING),
+ Result = gen_mod:get_module_opt(ServerHost, ?MODULE, default_encoding),
?INFO_MSG("The default_encoding configured for "
"host ~p is: ~p~n",
[ServerHost, Result]),
Result.
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) ->
- 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,
IRCServer) ->
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(_) ->
- [access, db_type, default_encoding, host, hosts, name].
+mod_opt_type(realname) ->
+ 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().
extract_ident(Packet) ->
-export([start/2, stop/1, reload/3, process_local_iq/1, export/1,
process_sm_iq/1, on_presence_update/4, import_info/0,
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]).
-include("ejabberd.hrl").
-optional_callbacks([use_cache/1, cache_nodes/1]).
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:init(Host, Opts),
init_cache(Mod, Host, Opts),
ok
end,
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_LAST,
?MODULE, process_local_iq, IQDisc),
init_cache(Mod, Host, Opts) ->
case use_cache(Mod, Host) of
true ->
- CacheOpts = cache_opts(Host, Opts),
+ CacheOpts = cache_opts(Opts),
ets_cache:new(?LAST_CACHE, CacheOpts);
false ->
ets_cache:delete(?LAST_CACHE)
end.
--spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
use_cache(Mod, Host) ->
case erlang:function_exported(Mod, use_cache, 1) of
true -> Mod:use_cache(Host);
- false ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
end.
-spec cache_nodes(module(), binary()) -> [node()].
(infinity) -> infinity
end;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) ->
- [db_type, iqdisc, cache_life_time, cache_size, use_cache, cache_missed].
+ fun (B) when is_boolean(B) -> B end.
+
+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)}].
use_cache(Host) ->
case mnesia:table_info(last_activity, storage_type) of
disc_only_copies ->
- gen_mod:get_module_opt(
- Host, mod_last, use_cache,
- ejabberd_config:use_cache(Host));
+ gen_mod:get_module_opt(Host, mod_last, use_cache);
_ ->
false
end.
-protocol({xep, 78, '2.5'}).
%% 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
-export([c2s_unauthenticated_packet/2, c2s_stream_features/2]).
depends(_Host, _Opts) ->
[].
-mod_opt_type(_) ->
+mod_options(_) ->
[].
-spec c2s_unauthenticated_packet(c2s_state(), iq()) ->
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,
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("logger.hrl").
%%% API
%%%===================================================================
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:init(Host, Opts),
init_cache(Host, Opts),
get_room_config, 50),
ejabberd_hooks:add(set_room_option, Host, ?MODULE,
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 ->
ejabberd_hooks:add(message_is_archived, Host, ?MODULE,
message_is_archived, 50);
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
case erlang:function_exported(Mod, use_cache, 2) of
true -> Mod:use_cache(Host, Opts);
- false ->
- gen_mod:get_opt(use_cache, Opts,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_opt(use_cache, Opts)
end.
init_cache(Host, Opts) ->
case use_cache(Host, Opts) of
true ->
- ets_cache:new(archive_prefs_cache, cache_opts(Host, Opts));
+ ets_cache:new(archive_prefs_cache, cache_opts(Opts));
false ->
ok
end.
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
get_room_config, 50),
ejabberd_hooks:delete(set_room_option, Host, ?MODULE,
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 ->
ejabberd_hooks:delete(message_is_archived, Host, ?MODULE,
message_is_archived, 50);
true ->
ok
end,
- ets_cache:setopts(archive_prefs_cache, cache_opts(Host, NewOpts)),
- case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts, gen_iq_handler:iqdisc(Host)) of
+ ets_cache:setopts(archive_prefs_cache, cache_opts(NewOpts)),
+ case gen_mod:is_equal_opt(iqdisc, NewOpts, OldOpts) of
{false, IQDisc, _} ->
register_iq_handlers(Host, IQDisc);
true ->
ok
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, _} ->
ejabberd_hooks:add(message_is_archived, Host, ?MODULE,
message_is_archived, 50);
message_is_archived(true, _C2SState, _Pkt) ->
true;
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 ->
is_archived(Pkt, LServer);
false ->
DBTypes = lists:usort(
lists:map(
fun(Host) ->
- case gen_mod:db_type(Host, ?MODULE) of
+ case gen_mod:get_module_opt(Host, ?MODULE, db_type) of
sql -> {sql, Host};
Other -> {Other, global}
end
error ->
ActivateOpt = gen_mod:get_module_opt(
LServer, ?MODULE,
- request_activates_archiving, false),
+ request_activates_archiving),
case ActivateOpt of
true ->
#archive_prefs{us = {LUser, LServer}, default = never};
false ->
Default = gen_mod:get_module_opt(
- LServer, ?MODULE, default, never),
+ LServer, ?MODULE, default),
#archive_prefs{us = {LUser, LServer}, default = Default}
end
end.
maybe_activate_mam(LUser, LServer) ->
ActivateOpt = gen_mod:get_module_opt(
- LServer, ?MODULE, request_activates_archiving, false),
+ LServer, ?MODULE, request_activates_archiving),
case ActivateOpt of
true ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
ok;
error ->
Default = gen_mod:get_module_opt(
- LServer, ?MODULE, default, never),
+ LServer, ?MODULE, default),
write_prefs(LUser, LServer, LServer, Default, [], [])
end;
false ->
end;
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(request_activates_archiving) ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) ->
- [assume_mam_usage, cache_life_time, cache_size, use_cache, cache_missed,
- db_type, default, iqdisc, request_activates_archiving].
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(Host) ->
+ [{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)}].
-include("logger.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,
sm_register_connection_hook/3, sm_remove_connection_hook/3,
%%====================================================================
push(Host, Probe) ->
- IP = gen_mod:get_module_opt(Host, ?MODULE, ip, {127,0,0,1}),
- Port = gen_mod:get_module_opt(Host, ?MODULE, port, 11111),
+ IP = gen_mod:get_module_opt(Host, ?MODULE, ip),
+ Port = gen_mod:get_module_opt(Host, ?MODULE, port),
send_metrics(Host, Probe, IP, Port).
send_metrics(Host, Probe, Peer, Port) ->
IP
end;
mod_opt_type(port) ->
- fun(I) when is_integer(I), I>0, I<65536 -> I end;
-mod_opt_type(_) ->
- [ip, port].
+ fun(I) when is_integer(I), I>0, I<65536 -> I end.
+
+mod_options(_) ->
+ [{ip, <<"127.0.0.1">>}, {port, 11111}].
%% API
-export([start/2, stop/1, process_iq/1,
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
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
%%%===================================================================
init([ServerHost, Opts]) ->
process_flag(trap_exit, true),
- Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"mix.@HOST@">>),
- IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(ServerHost)),
+ Hosts = gen_mod:get_opt_hosts(ServerHost, Opts),
+ IQDisc = gen_mod:get_opt(iqdisc, Opts),
lists:foreach(
fun(Host) ->
ConfigTab = gen_mod:get_module_proc(Host, config),
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/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(_) -> [host, hosts, iqdisc].
+ fun (L) -> lists:map(fun iolist_to_binary/1, L) end.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)},
+ {host, <<"mix.@HOST@">>},
+ {hosts, []}].
-export([init/1, handle_call/3, handle_cast/2,
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("logger.hrl").
init([Host, Opts]) ->
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,
history_size = HistorySize, queue_type = QueueType,
room_shaper = RoomShaper} = State = init_state(Host, Opts),
{reply, ok, State}.
handle_cast({reload, ServerHost, NewOpts, OldOpts}, #state{hosts = OldHosts}) ->
- NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
- OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
+ NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts),
+ OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts),
NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
NewRMod = gen_mod:ram_db_mod(ServerHost, NewOpts, ?MODULE),
OldMod = gen_mod:db_mod(ServerHost, OldOpts, ?MODULE),
%%% Internal functions
%%--------------------------------------------------------------------
init_state(Host, Opts) ->
- MyHosts = gen_mod:get_opt_hosts(Host, Opts,
- <<"conference.@HOST@">>),
- Access = gen_mod:get_opt(access, Opts, all),
- AccessCreate = gen_mod:get_opt(access_create, Opts, all),
- AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
- AccessPersistent = gen_mod:get_opt(access_persistent, Opts, all),
- HistorySize = gen_mod:get_opt(history_size, Opts, 20),
- MaxRoomsDiscoItems = gen_mod:get_opt(max_rooms_discoitems, Opts, 100),
- DefRoomOpts = gen_mod:get_opt(default_room_options, Opts, []),
- QueueType = gen_mod:get_opt(queue_type, Opts,
- ejabberd_config:default_queue_type(Host)),
- RoomShaper = gen_mod:get_opt(room_shaper, Opts, none),
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts),
+ Access = gen_mod:get_opt(access, Opts),
+ AccessCreate = gen_mod:get_opt(access_create, Opts),
+ AccessAdmin = gen_mod:get_opt(access_admin, Opts),
+ AccessPersistent = gen_mod:get_opt(access_persistent, Opts),
+ HistorySize = gen_mod:get_opt(history_size, Opts),
+ MaxRoomsDiscoItems = gen_mod:get_opt(max_rooms_discoitems, Opts),
+ DefRoomOpts = gen_mod:get_opt(default_room_options, Opts),
+ QueueType = gen_mod:get_opt(queue_type, Opts),
+ RoomShaper = gen_mod:get_opt(room_shaper, Opts),
#state{hosts = MyHosts,
server_host = Host,
access = {Access, AccessCreate, AccessAdmin, AccessPersistent},
Features = [?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
?NS_REGISTER, ?NS_MUC, ?NS_VCARD, ?NS_MUCSUB, ?NS_MUC_UNIQUE
| 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">>,
type = <<"text">>,
name = translate:translate(Lang, Name)},
Host = To#jid.lserver,
ServerHost = ejabberd_router:host_of_route(Host),
MaxRoomsDiscoItems = gen_mod:get_module_opt(
- ServerHost, ?MODULE, max_rooms_discoitems,
- 100),
+ ServerHost, ?MODULE, max_rooms_discoitems),
case iq_disco_items(ServerHost, Host, From, Lang,
MaxRoomsDiscoItems, Node, RSM) of
{error, Err} ->
end.
check_create_roomid(ServerHost, RoomID) ->
- Max = gen_mod:get_module_opt(ServerHost, ?MODULE, max_room_id, infinity),
- Regexp = gen_mod:get_module_opt(ServerHost, ?MODULE, regexp_room_id, ""),
+ Max = gen_mod:get_module_opt(ServerHost, ?MODULE, max_room_id),
+ Regexp = gen_mod:get_module_opt(ServerHost, ?MODULE, regexp_room_id),
(byte_size(RoomID) =< Max) and
(re:run(RoomID, Regexp, [unicode, {capture, none}]) == match).
(visitor) -> visitor
end, L)
end;
-mod_opt_type(_) ->
- [access, access_admin, access_create, access_persistent,
- db_type, ram_db_type, history_size, host, hosts, name,
- max_room_desc, max_room_id, max_room_name,
- max_rooms_discoitems, max_user_conferences, max_users,
- max_users_admin_threshold, max_users_presence,
- min_message_interval, min_presence_interval, queue_type,
- regexp_room_id, room_shaper, user_message_shaper, user_presence_shaper,
- {default_room_options, allow_change_subj},
- {default_room_options, allow_private_messages},
- {default_room_options, allow_query_users},
- {default_room_options, allow_user_invites},
- {default_room_options, allow_visitor_nickchange},
- {default_room_options, allow_visitor_status},
- {default_room_options, anonymous},
- {default_room_options, captcha_protected},
- {default_room_options, logging},
- {default_room_options, members_by_default},
- {default_room_options, members_only},
- {default_room_options, moderated},
- {default_room_options, password_protected},
- {default_room_options, persistent},
- {default_room_options, public},
- {default_room_options, public_list},
- {default_room_options, mam},
- {default_room_options, allow_subscription},
- {default_room_options, password},
- {default_room_options, title},
- {default_room_options, allow_private_messages_from_visitors},
- {default_room_options, max_users},
- {default_room_options, presence_broadcast}].
+mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
+
+mod_options(Host) ->
+ [{access, all},
+ {access_admin, none},
+ {access_create, all},
+ {access_persistent, all},
+ {db_type, ejabberd_config:default_db(Host, ?MODULE)},
+ {ram_db_type, ejabberd_config:default_ram_db(Host, ?MODULE)},
+ {iqdisc, gen_iq_handler:iqdisc(Host)},
+ {history_size, 20},
+ {host, <<"conference.@HOST@">>},
+ {hosts, []},
+ {name, ?T("Chatrooms")},
+ {max_room_desc, infinity},
+ {max_room_id, infinity},
+ {max_room_name, infinity},
+ {max_rooms_discoitems, 100},
+ {max_user_conferences, 10},
+ {max_users, 200},
+ {max_users_admin_threshold, 5},
+ {max_users_presence, 1000},
+ {min_message_interval, 0},
+ {min_presence_interval, 0},
+ {queue_type, ejabberd_config:default_queue_type(Host)},
+ {regexp_room_id, <<"">>},
+ {room_shaper, none},
+ {user_message_shaper, none},
+ {user_presence_shaper, none},
+ {default_room_options,
+ [{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]}]}].
set_room_affiliation/4, get_room_affiliations/2,
web_menu_main/2, web_page_main/2, web_menu_host/3,
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("logger.hrl").
%% Get the default room options from the muc configuration
DefRoomOpts = gen_mod:get_module_opt(ServerHost, mod_muc,
- default_room_options, []),
+ default_room_options),
%% Change default room options as required
FormattedRoomOpts = [format_room_option(Opt, Val) || {Opt, Val}<-CustomRoomOpts],
RoomOpts = lists:ukeymerge(1,
mod_muc:store_room(ServerHost, Host, Name, RoomOpts),
%% Get all remaining mod_muc parameters that might be utilized
- Access = gen_mod:get_module_opt(ServerHost, mod_muc, access, all),
- AcCreate = gen_mod:get_module_opt(ServerHost, mod_muc, access_create, all),
- AcAdmin = gen_mod:get_module_opt(ServerHost, mod_muc, access_admin, none),
- AcPer = gen_mod:get_module_opt(ServerHost, mod_muc, access_persistent, all),
- HistorySize = gen_mod:get_module_opt(ServerHost, mod_muc, history_size, 20),
- RoomShaper = gen_mod:get_module_opt(ServerHost, mod_muc, room_shaper, none),
- QueueType = gen_mod:get_module_opt(ServerHost, mod_muc, queue_type,
- ejabberd_config:default_queue_type(ServerHost)),
+ Access = gen_mod:get_module_opt(ServerHost, mod_muc, access),
+ AcCreate = gen_mod:get_module_opt(ServerHost, mod_muc, access_create),
+ AcAdmin = gen_mod:get_module_opt(ServerHost, mod_muc, access_admin),
+ AcPer = gen_mod:get_module_opt(ServerHost, mod_muc, access_persistent),
+ HistorySize = gen_mod:get_module_opt(ServerHost, mod_muc, history_size),
+ RoomShaper = gen_mod:get_module_opt(ServerHost, mod_muc, room_shaper),
+ QueueType = gen_mod:get_module_opt(ServerHost, mod_muc, queue_type),
%% If the room does not exist yet in the muc_online_room
case mod_muc:find_online_room(Name, Host) of
file:close(F),
%% Read the default room options defined for the first virtual host
DefRoomOpts = gen_mod:get_module_opt(?MYNAME, mod_muc,
- default_room_options, []),
+ default_room_options),
[muc_create_room(?MYNAME, A, DefRoomOpts) || A <- Rooms],
ok.
[]
end.
-mod_opt_type(_) -> [].
+mod_options(_) -> [].
-export([init/1, handle_call/3, handle_cast/2,
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("logger.hrl").
%%% Internal functions
%%--------------------------------------------------------------------
init_state(Host, Opts) ->
- OutDir = gen_mod:get_opt(outdir, Opts, <<"www/muc">>),
- DirType = gen_mod:get_opt(dirtype, Opts, subdirs),
- DirName = gen_mod:get_opt(dirname, Opts, room_jid),
- FileFormat = gen_mod:get_opt(file_format, Opts, html),
- FilePermissions = gen_mod:get_opt(file_permissions, Opts, {644, 33}),
- CSSFile = gen_mod:get_opt(cssfile, Opts, false),
- AccessLog = gen_mod:get_opt(access_log, Opts, muc_admin),
- Timezone = gen_mod:get_opt(timezone, Opts, local),
- Top_link = gen_mod:get_opt(top_link, Opts, {<<"/">>, <<"Home">>}),
- NoFollow = gen_mod:get_opt(spam_prevention, Opts, true),
+ OutDir = gen_mod:get_opt(outdir, Opts),
+ DirType = gen_mod:get_opt(dirtype, Opts),
+ DirName = gen_mod:get_opt(dirname, Opts),
+ FileFormat = gen_mod:get_opt(file_format, Opts),
+ FilePermissions = gen_mod:get_opt(file_permissions, Opts),
+ CSSFile = gen_mod:get_opt(cssfile, Opts),
+ AccessLog = gen_mod:get_opt(access_log, Opts),
+ Timezone = gen_mod:get_opt(timezone, Opts),
+ Top_link = gen_mod:get_opt(top_link, Opts),
+ NoFollow = gen_mod:get_opt(spam_prevention, Opts),
Lang = ejabberd_config:get_lang(Host),
#logstate{host = Host, out_dir = OutDir,
dir_type = DirType, dir_name = DirName,
mod_opt_type(access_log) ->
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) ->
fun (room_jid) -> room_jid;
(room_name) -> room_name
mod_opt_type(top_link) ->
fun ([{S1, S2}]) ->
{iolist_to_binary(S1), iolist_to_binary(S2)}
- end;
-mod_opt_type(_) ->
- [access_log, cssfile, dirname, dirtype, file_format,
- {file_permissions, mode}, {file_permissions, group},
- outdir, spam_prevention, timezone, top_link].
+ end.
+
+mod_options(_) ->
+ [{access_log, muc_admin},
+ {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">>}]}].
Now = p1_time_compat:system_time(micro_seconds),
MinMessageInterval = trunc(gen_mod:get_module_opt(
StateData#state.server_host,
- mod_muc, min_message_interval,
- 0) * 1000000),
+ mod_muc, min_message_interval)
+ * 1000000),
Size = element_size(Packet),
{MessageShaper, MessageShaperInterval} =
shaper:update(Activity#activity.message_shaper, Size),
Now = p1_time_compat:system_time(micro_seconds),
MinPresenceInterval =
trunc(gen_mod:get_module_opt(StateData#state.server_host,
- mod_muc, min_presence_interval,
- 0) * 1000000),
+ mod_muc, min_presence_interval)
+ * 1000000),
if (Now >= Activity#activity.presence_time + MinPresenceInterval)
and (Activity#activity.presence == undefined) ->
NewActivity = Activity#activity{presence_time = Now},
-spec get_service_max_users(state()) -> pos_integer().
get_service_max_users(StateData) ->
gen_mod:get_module_opt(StateData#state.server_host,
- mod_muc, max_users,
- ?MAX_USERS_DEFAULT).
+ mod_muc, max_users).
-spec get_max_users_admin_threshold(state()) -> pos_integer().
get_max_users_admin_threshold(StateData) ->
gen_mod:get_module_opt(StateData#state.server_host,
- mod_muc, max_users_admin_threshold,
- 5).
+ mod_muc, max_users_admin_threshold).
-spec room_queue_new(binary(), shaper:shaper(), _) -> p1_queue:queue().
room_queue_new(ServerHost, Shaper, QueueType) ->
HaveRoomShaper = Shaper /= none,
HaveMessageShaper = gen_mod:get_module_opt(
- ServerHost, mod_muc, user_message_shaper,
- none) /= none,
+ ServerHost, mod_muc,
+ user_message_shaper) /= none,
HavePresenceShaper = gen_mod:get_module_opt(
- ServerHost, mod_muc, user_presence_shaper,
- none) /= none,
+ ServerHost, mod_muc,
+ user_presence_shaper) /= none,
HaveMinMessageInterval = gen_mod:get_module_opt(
- ServerHost, mod_muc, min_message_interval,
- 0) /= 0,
+ ServerHost, mod_muc,
+ min_message_interval) /= 0,
HaveMinPresenceInterval = gen_mod:get_module_opt(
- ServerHost, mod_muc, min_presence_interval,
- 0) /= 0,
+ ServerHost, mod_muc,
+ min_presence_interval) /= 0,
if HaveRoomShaper or HaveMessageShaper or HavePresenceShaper
or HaveMinMessageInterval or HaveMinPresenceInterval ->
p1_queue:new(QueueType);
error ->
MessageShaper =
shaper:new(gen_mod:get_module_opt(StateData#state.server_host,
- mod_muc, user_message_shaper,
- none)),
+ mod_muc, user_message_shaper)),
PresenceShaper =
shaper:new(gen_mod:get_module_opt(StateData#state.server_host,
- mod_muc, user_presence_shaper,
- none)),
+ mod_muc, user_presence_shaper)),
#activity{message_shaper = MessageShaper,
presence_shaper = PresenceShaper}
end.
store_user_activity(JID, UserActivity, StateData) ->
MinMessageInterval =
trunc(gen_mod:get_module_opt(StateData#state.server_host,
- mod_muc, min_message_interval,
- 0) * 1000),
+ mod_muc, min_message_interval)
+ * 1000),
MinPresenceInterval =
trunc(gen_mod:get_module_opt(StateData#state.server_host,
- mod_muc, min_presence_interval,
- 0) * 1000),
+ mod_muc, min_presence_interval)
+ * 1000),
Key = jid:tolower(JID),
Now = p1_time_compat:system_time(micro_seconds),
Activity1 = clean_treap(StateData#state.activity,
NConferences = tab_count_user(From, StateData),
MaxConferences =
gen_mod:get_module_opt(StateData#state.server_host,
- mod_muc, max_user_conferences,
- 10),
+ mod_muc, max_user_conferences),
Collision = nick_collision(From, Nick, StateData),
IsSubscribeRequest = not is_record(Packet, presence),
case {(ServiceAffiliation == owner orelse
is_room_overcrowded(StateData) ->
MaxUsersPresence = gen_mod:get_module_opt(
StateData#state.server_host,
- mod_muc, max_users_presence,
- ?DEFAULT_MAX_USERS_PRESENCE),
+ mod_muc, max_users_presence),
(?DICT):size(StateData#state.users) > MaxUsersPresence.
-spec presence_broadcast_allowed(jid(), state()) -> boolean().
RoomDesc = proplists:get_value(roomdesc, Options, <<"">>),
MaxRoomName = gen_mod:get_module_opt(
StateData#state.server_host,
- mod_muc, max_room_name,
- infinity),
+ mod_muc, max_room_name),
MaxRoomDesc = gen_mod:get_module_opt(
StateData#state.server_host,
- mod_muc, max_room_desc,
- infinity),
+ mod_muc, max_room_desc),
(byte_size(RoomName) =< MaxRoomName)
andalso (byte_size(RoomDesc) =< MaxRoomDesc).
get_default_room_maxusers(RoomState) ->
DefRoomOpts =
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#state.config)#config.max_users.
-export([init/1, handle_info/2, handle_call/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("logger.hrl").
init([LServerS, Opts]) ->
process_flag(trap_exit, true),
- LServiceS = gen_mod:get_opt_host(LServerS, Opts,
- <<"multicast.@HOST@">>),
- Access = gen_mod:get_opt(access, Opts, all),
- SLimits = build_service_limit_record(gen_mod:get_opt(limits, Opts, [])),
+ [LServiceS|_] = gen_mod:get_opt_hosts(LServerS, Opts),
+ Access = gen_mod:get_opt(access, Opts),
+ SLimits = build_service_limit_record(gen_mod:get_opt(limits, Opts)),
create_cache(),
try_start_loop(),
create_pool(),
handle_cast({reload, NewOpts, NewOpts},
#state{lserver = LServerS, lservice = OldLServiceS} = State) ->
- Access = gen_mod:get_opt(access, NewOpts, all),
- SLimits = build_service_limit_record(gen_mod:get_opt(limits, NewOpts, [])),
- NewLServiceS = gen_mod:get_opt_host(LServerS, NewOpts,
- <<"multicast.@HOST@">>),
+ Access = gen_mod:get_opt(access, NewOpts),
+ SLimits = build_service_limit_record(gen_mod:get_opt(limits, NewOpts)),
+ [NewLServiceS|_] = gen_mod:get_opt_hosts(LServerS, NewOpts),
if NewLServiceS /= OldLServiceS ->
ejabberd_router:register_route(NewLServiceS, LServerS),
ejabberd_router:unregister_route(OldLServiceS);
-define(FEATURE(Feat), Feat).
iq_disco_info(From, Lang, State) ->
- Name = gen_mod:get_module_opt(State#state.lserver, ?MODULE,
- name, ?T("Multicast")),
+ Name = gen_mod:get_module_opt(State#state.lserver, ?MODULE, name),
#disco_info{
identities = [#identity{category = <<"service">>,
type = <<"multicast">>,
mod_opt_type(access) ->
fun acl:access_rules_validator/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({limits, Type}) when (Type == local) or (Type == remote) ->
fun(L) ->
({message, I} = O) when is_integer(I) -> O;
({presence, I} = O) when is_integer(I) -> O
end, L)
- end;
-mod_opt_type(_) -> [access, host, {limits, local}, {limits, remote}, name].
+ end.
+
+mod_options(_Host) ->
+ [{access, all},
+ {host, <<"multicast.@HOST@">>},
+ {hosts, []},
+ {limits, [{local, []}, {remote, []}]},
+ {name, ?T("Multicast")}].
webadmin_user/4,
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}).
start(Host, Opts) ->
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
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,
store_packet, 50),
ejabberd_hooks:add(c2s_self_presence, Host, ?MODULE, c2s_self_presence, 50),
true ->
ok
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_FLEX_OFFLINE,
?MODULE, handle_offline_query, IQDisc);
end.
get_max_user_messages(User, Server) ->
- Access = gen_mod:get_module_opt(Server, ?MODULE, access_max_user_messages,
- max_user_offline_messages),
+ Access = gen_mod:get_module_opt(Server, ?MODULE, access_max_user_messages),
case acl:match_rule(Server, Access, jid:make(User, Server)) of
Max when is_integer(Max) -> Max;
infinity -> infinity;
false;
none ->
case gen_mod:get_module_opt(
- LServer, ?MODULE, store_empty_body,
- unless_chat_state) of
+ LServer, ?MODULE, store_empty_body) of
true ->
true;
false ->
fun (V) when is_boolean(V) -> V;
(unless_chat_state) -> unless_chat_state
end;
-mod_opt_type(_) ->
- [access_max_user_messages, db_type, store_empty_body].
+mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
+
+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}].
-include("xmpp.hrl").
--define(DEFAULT_SEND_PINGS, false).
-
--define(DEFAULT_PING_INTERVAL, 60).
-
%% API
-export([start_ping/2, stop_ping/2]).
handle_cast/2, handle_info/2, code_change/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,
- {host = <<"">>,
- send_pings = ?DEFAULT_SEND_PINGS :: boolean(),
- ping_interval = ?DEFAULT_PING_INTERVAL :: non_neg_integer(),
- ping_ack_timeout = undefined :: non_neg_integer(),
- timeout_action = none :: none | kill,
+ {host = <<"">> :: binary(),
+ send_pings :: boolean(),
+ ping_interval :: non_neg_integer(),
+ ping_ack_timeout :: undefined | non_neg_integer(),
+ timeout_action ::none | kill,
timers = maps:new() :: map()}).
%%====================================================================
init([Host, Opts]) ->
process_flag(trap_exit, true),
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),
case State#state.send_pings of
true -> register_hooks(Host);
handle_cast({reload, Host, NewOpts, OldOpts},
#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);
true -> ok
end,
%% Internal functions
%%====================================================================
init_state(Host, Opts) ->
- SendPings = gen_mod:get_opt(send_pings, Opts, ?DEFAULT_SEND_PINGS),
- PingInterval = gen_mod:get_opt(ping_interval, Opts, ?DEFAULT_PING_INTERVAL),
+ SendPings = gen_mod:get_opt(send_pings, Opts),
+ PingInterval = gen_mod:get_opt(ping_interval, 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,
send_pings = SendPings,
ping_interval = PingInterval,
mod_opt_type(ping_interval) ->
fun (I) when is_integer(I), I > 0 -> I end;
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) ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(timeout_action) ->
fun (none) -> none;
(kill) -> kill
- end;
-mod_opt_type(_) ->
- [iqdisc, ping_interval, ping_ack_timeout, send_pings, timeout_action].
+ end.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)},
+ {ping_interval, 60},
+ {ping_ack_timeout, undefined},
+ {send_pings, false},
+ {timeout_action, none}].
-behavior(gen_mod).
-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("logger.hrl").
Acc.
update(Server, JID, Dir) ->
- StormCount = gen_mod:get_module_opt(Server, ?MODULE, count, 5),
- TimeInterval = gen_mod:get_module_opt(Server, ?MODULE, interval, 60),
+ StormCount = gen_mod:get_module_opt(Server, ?MODULE, count),
+ TimeInterval = gen_mod:get_module_opt(Server, ?MODULE, interval),
TimeStamp = p1_time_compat:system_time(seconds),
case read(Dir) of
undefined ->
mod_opt_type(count) ->
fun (I) when is_integer(I), I > 0 -> I end;
mod_opt_type(interval) ->
- fun (I) when is_integer(I), I > 0 -> I end;
-mod_opt_type(_) -> [count, interval].
+ fun (I) when is_integer(I), I > 0 -> I end.
+
+mod_options(_) ->
+ [{count, 5}, {interval, 60}].
set_list/1, set_list/4, set_default_list/3,
user_send_packet/1, user_receive_packet/1,
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("logger.hrl").
-optional_callbacks([use_cache/1, cache_nodes/1]).
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:init(Host, Opts),
init_cache(Mod, Host, Opts),
ok
end,
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVACY,
?MODULE, process_iq, IQDisc);
init_cache(Mod, Host, Opts) ->
case use_cache(Mod, Host) of
true ->
- CacheOpts = cache_opts(Host, Opts),
+ CacheOpts = cache_opts(Opts),
ets_cache:new(?PRIVACY_CACHE, CacheOpts),
ets_cache:new(?PRIVACY_LIST_CACHE, CacheOpts);
false ->
ets_cache:delete(?PRIVACY_LIST_CACHE)
end.
--spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
use_cache(Mod, Host) ->
case erlang:function_exported(Mod, use_cache, 1) of
true -> Mod:use_cache(Host);
- false ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
end.
-spec cache_nodes(module(), binary()) -> [node()].
(infinity) -> infinity
end;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) ->
- [db_type, iqdisc, cache_life_time, cache_size,
- use_cache, cache_missed].
+ fun (B) when is_boolean(B) -> B end.
+
+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)}].
use_cache(Host) ->
case mnesia:table_info(privacy, storage_type) of
disc_only_copies ->
- gen_mod:get_module_opt(
- Host, mod_privacy, use_cache,
- ejabberd_config:use_cache(Host));
+ gen_mod:get_module_opt(Host, mod_privacy, use_cache);
_ ->
false
end.
-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,
- 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("logger.hrl").
-optional_callbacks([use_cache/1, cache_nodes/1]).
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:init(Host, Opts),
init_cache(Mod, Host, Opts),
ok
end,
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE,
?MODULE, process_sm_iq, IQDisc);
init_cache(Mod, Host, Opts) ->
case use_cache(Mod, Host) of
true ->
- CacheOpts = cache_opts(Host, Opts),
+ CacheOpts = cache_opts(Opts),
ets_cache:new(?PRIVATE_CACHE, CacheOpts);
false ->
ets_cache:delete(?PRIVATE_CACHE)
end.
--spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
use_cache(Mod, Host) ->
case erlang:function_exported(Mod, use_cache, 1) of
true -> Mod:use_cache(Host);
- false ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
end.
-spec cache_nodes(module(), binary()) -> [node()].
(infinity) -> infinity
end;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) ->
- [db_type, iqdisc, cache_life_time, cache_size, use_cache, cache_missed].
+ fun (B) when is_boolean(B) -> B end.
+
+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)}].
use_cache(Host) ->
case mnesia:table_info(private_storage, storage_type) of
disc_only_copies ->
- gen_mod:get_module_opt(
- Host, mod_private, use_cache,
- ejabberd_config:use_cache(Host));
+ gen_mod:get_module_opt(Host, mod_private, use_cache);
_ ->
false
end.
-behaviour(gen_mod).
%% 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
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
mod_opt_type({roster, _}) -> 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(_) ->
- [{roster, both}, {roster, get}, {roster, set},
- {message, outgoing}, {presence, managed_entity}, {presence, roster}].
+mod_opt_type({presence, _}) -> fun acl:access_rules_validator/1.
+
+mod_options(_) ->
+ [{roster, [{both, none}, {get, none}, {set, none}]},
+ {presence, [{managed_entity, none}, {roster, none}]},
+ {message, [{outgoing,none}]}].
depends(_, _) ->
[].
end.
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
allow ->
both;
end.
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
allow -> outgoing;
deny -> none
end.
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
allow ->
roster;
%% supervisor callbacks.
-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).
+-include("translate.hrl").
+
-callback init() -> any().
-callback register_stream(binary(), pid()) -> ok | {error, any()}.
-callback unregister_stream(binary()) -> ok | {error, any()}.
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(hostname) -> fun iolist_to_binary/1;
+mod_opt_type(hostname) ->
+ fun(undefined) -> undefined;
+ (H) -> iolist_to_binary(H)
+ end;
mod_opt_type(ip) ->
- fun (S) ->
+ fun(undefined) ->
+ undefined;
+ (S) ->
{ok, Addr} =
inet_parse:address(binary_to_list(iolist_to_binary(S))),
Addr
end;
mod_opt_type(ram_db_type) ->
fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
+mod_opt_type(iqdisc) ->
+ fun gen_iq_handler:check_type/1;
mod_opt_type(Opt) ->
- case mod_proxy65_stream:listen_opt_type(Opt) of
- Opts when is_list(Opts) ->
- [access, host, hosts, hostname, ip, name, port,
- max_connections, ram_db_type] ++ Opts;
- Fun ->
- Fun
- end.
+ mod_proxy65_stream:listen_opt_type(Opt).
+
+mod_options(Host) ->
+ [{ram_db_type, ejabberd_config:default_ram_db(Host, ?MODULE)},
+ {iqdisc, gen_iq_handler:iqdisc(Host)},
+ {access, all},
+ {host, <<"proxy.@HOST@">>},
+ {hosts, []},
+ {hostname, undefined},
+ {ip, undefined},
+ {port, 7777},
+ {name, ?T("SOCKS5 Bytestreams")},
+ {max_connections, infinity}] ++
+ mod_proxy65_stream:listen_options().
init([Host, Opts]) ->
process_flag(trap_exit, true),
- IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
- MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"proxy.@HOST@">>),
+ IQDisc = gen_mod:get_opt(iqdisc, Opts),
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts),
lists:foreach(
fun(MyHost) ->
gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
{reply, ok, State}.
handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
- NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts, <<"proxy.@HOST@">>),
- OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts, <<"proxy.@HOST@">>),
- NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
- OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
+ NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts),
+ OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts),
+ NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts),
+ OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts),
if (NewIQDisc /= OldIQDisc) ->
lists:foreach(
fun(NewHost) ->
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
process_disco_info(#iq{type = get, to = To, lang = Lang} = IQ) ->
Host = ejabberd_router:host_of_route(To#jid.lserver),
- Name = gen_mod:get_module_opt(Host, mod_proxy65, name,
- ?T("SOCKS5 Bytestreams")),
+ Name = gen_mod:get_module_opt(Host, mod_proxy65, name),
Info = ejabberd_hooks:run_fold(disco_info, Host,
[], [Host, ?MODULE, <<"">>, <<"">>]),
xmpp:make_iq_result(
process_bytestreams(#iq{type = get, from = JID, to = To, lang = Lang} = IQ) ->
Host = To#jid.lserver,
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
allow ->
StreamHost = get_streamhost(Host, ServerHost),
sub_els = [#bytestreams{activate = TargetJID,
sid = SID}]} = IQ) ->
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
allow ->
Node = ejabberd_cluster:get_node_by_id(To#jid.lresource),
-spec get_streamhost(binary(), binary()) -> streamhost().
get_streamhost(Host, ServerHost) ->
{Port, IP} = get_port_ip(ServerHost),
- HostName0 = gen_mod:get_module_opt(ServerHost, mod_proxy65, hostname,
- misc:ip_to_list(IP)),
+ HostName0 = case gen_mod:get_module_opt(ServerHost, mod_proxy65, hostname) of
+ undefined -> misc:ip_to_list(IP);
+ Val -> Val
+ end,
HostName = misc:expand_keyword(<<"@HOST@">>, HostName0, ServerHost),
Resource = ejabberd_cluster:node_id(),
#streamhost{jid = jid:make(<<"">>, Host, Resource),
-spec get_port_ip(binary()) -> {pos_integer(), inet:ip_address()}.
get_port_ip(Host) ->
- Port = gen_mod:get_module_opt(Host, mod_proxy65, port, 7777),
- IP = gen_mod:get_module_opt(Host, mod_proxy65, ip, get_my_ip()),
+ Port = gen_mod:get_module_opt(Host, mod_proxy65, port),
+ IP = case gen_mod:get_module_opt(Host, mod_proxy65, ip) of
+ undefined -> get_my_ip();
+ Addr -> Addr
+ end,
{Port, IP}.
-spec get_my_ip() -> inet:ip_address().
end.
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) ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
stream_established/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").
init([Socket, Host, Opts]) ->
process_flag(trap_exit, true),
- AuthType = gen_mod:get_opt(auth_type, Opts, anonymous),
- Shaper = gen_mod:get_opt(shaper, Opts, none),
- RecvBuf = gen_mod:get_opt(recbuf, Opts, 8192),
- SendBuf = gen_mod:get_opt(sndbuf, Opts, 8192),
+ AuthType = gen_mod:get_opt(auth_type, Opts),
+ Shaper = gen_mod:get_opt(shaper, Opts),
+ RecvBuf = gen_mod:get_opt(recbuf, Opts),
+ SendBuf = gen_mod:get_opt(sndbuf, Opts),
TRef = erlang:send_after(?WAIT_TIMEOUT, self(), stop),
inet:setopts(Socket,
[{active, true}, {recbuf, RecvBuf}, {sndbuf, SendBuf}]),
fun (I) when is_integer(I), I > 0 -> I end;
listen_opt_type(shaper) -> fun acl:shaper_rules_validator/1;
listen_opt_type(sndbuf) ->
- fun (I) when is_integer(I), I > 0 -> I end;
-listen_opt_type(_) ->
- [auth_type, recbuf, sndbuf, shaper].
+ fun (I) when is_integer(I), I > 0 -> I end.
+
+listen_options() ->
+ [{auth_type, anonymous},
+ {recbuf, 8192},
+ {sndbuf, 8192},
+ {shaper, none}].
%% API and gen_server callbacks
-export([start/2, stop/1, init/1,
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
init([ServerHost, Opts]) ->
process_flag(trap_exit, true),
?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]),
- Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"pubsub.@HOST@">>),
- Access = gen_mod:get_opt(access_createnode, Opts, all),
- PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts, true),
- IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(ServerHost)),
- LastItemCache = gen_mod:get_opt(last_item_cache, Opts, false),
- MaxItemsNode = gen_mod:get_opt(max_items_node, Opts, ?MAXITEMS),
+ Hosts = gen_mod:get_opt_hosts(ServerHost, Opts),
+ Access = gen_mod:get_opt(access_createnode, Opts),
+ PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts),
+ IQDisc = gen_mod:get_opt(iqdisc, Opts),
+ LastItemCache = gen_mod:get_opt(last_item_cache, Opts),
+ MaxItemsNode = gen_mod:get_opt(max_items_node, Opts),
MaxSubsNode = gen_mod:get_opt(max_subscriptions_node, Opts),
ejabberd_mnesia:create(?MODULE, pubsub_last_item,
[{ram_copies, [node()]},
lists:flatmap(
fun(Host) ->
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);
_ -> ok
end,
{Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts),
DefaultModule = plugin(Host, hd(Plugins)),
DefaultNodeCfg = merge_config(
- gen_mod:get_opt(default_node_config, Opts, []),
+ gen_mod:get_opt(default_node_config, Opts),
DefaultModule:options()),
lists:foreach(
fun(H) ->
NodeTree = config(ServerHost, nodetree),
Plugins = config(ServerHost, plugins),
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,
access = Access, pep_mapping = PepMapping,
ignore_pep_from_offline = PepOffline,
max_items_node = MaxItemsNode, nodetree = NodeTree,
plugins = Plugins, db_type = DBType}}.
-depends(ServerHost, Opts) ->
- Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>),
- Plugins = gen_mod:get_opt(plugins, Opts, [?STDNODE]),
+depends(ServerHost, Opts0) ->
+ Opts = Opts0 ++ mod_options(ServerHost),
+ [Host|_] = gen_mod:get_opt_hosts(ServerHost, Opts),
+ Plugins = gen_mod:get_opt(plugins, Opts),
lists:flatmap(
fun(Name) ->
Plugin = plugin(ServerHost, Name),
%% <em>node_plugin</em>. The 'node_' prefix is mandatory.</p>
%% <p>See {@link node_hometree:init/1} for an example implementation.</p>
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]),
TreePlugin:init(Host, ServerHost, Opts),
- Plugins = gen_mod:get_opt(plugins, Opts, [?STDNODE]),
- PepMapping = gen_mod:get_opt(pep_mapping, Opts, []),
+ Plugins = gen_mod:get_opt(plugins, Opts),
+ PepMapping = gen_mod:get_opt(pep_mapping, Opts),
?DEBUG("** PEP Mapping : ~p~n", [PepMapping]),
PluginsOK = lists:foldl(
fun (Name, Acc) ->
end,
case Node of
<<>> ->
- Name = gen_mod:get_module_opt(ServerHost, ?MODULE, name,
- ?T("Publish-Subscribe")),
+ Name = gen_mod:get_module_opt(ServerHost, ?MODULE, name),
{result,
#disco_info{
identities = [#identity{
-spec submodule(host(), binary(), binary()) -> atom().
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]);
Db -> ejabberd:module_name([<<"pubsub">>, Type, Name, misc:atom_to_binary(Db)])
end.
?DEBUG("tree_action ~p ~p ~p", [Host, Function, Args]),
ServerHost = serverhost(Host),
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 ->
catch mnesia:sync_dirty(Fun);
sql ->
transaction(Host, Fun, Trans) ->
ServerHost = serverhost(Host),
- DBType = gen_mod:db_type(ServerHost, ?MODULE),
+ DBType = gen_mod:get_module_opt(ServerHost, ?MODULE, db_type),
Retry = case DBType of
sql -> 2;
_ -> 1
mod_opt_type(max_items_node) ->
fun (A) when is_integer(A) andalso A >= 0 -> A end;
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) ->
fun (A) when is_list(A) -> A end;
mod_opt_type(nodetree) ->
mod_opt_type(pep_mapping) ->
fun (A) when is_list(A) -> A end;
mod_opt_type(plugins) ->
- fun (A) when is_list(A) -> A end;
-mod_opt_type(_) ->
- [access_createnode, db_type, host, hosts, name,
- ignore_pep_from_offline, iqdisc, last_item_cache,
- max_items_node, nodetree, pep_mapping, plugins,
- max_subscriptions_node, default_node_config].
+ fun (A) when is_list(A) -> A end.
+
+mod_options(Host) ->
+ [{access_createnode, all},
+ {db_type, ejabberd_config:default_db(Host, ?MODULE)},
+ {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, []}].
-behavior(gen_mod).
%% 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.
-export([disco_sm_features/5, c2s_session_pending/1, c2s_copy_session/2,
%%--------------------------------------------------------------------
-spec start(binary(), gen_mod:opts()) -> ok.
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:init(Host, Opts),
init_cache(Mod, Host, Opts),
true ->
ok
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, _} ->
register_iq_handlers(Host, IQDisc);
true ->
mod_opt_type(O) when O == use_cache; O == cache_missed ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(iqdisc) ->
- fun gen_iq_handler:check_type/1;
-mod_opt_type(_) ->
- [db_type, cache_life_time, cache_size, use_cache, cache_missed, iqdisc].
+ fun gen_iq_handler:check_type/1.
+
+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.
DBTypes = lists:usort(
lists:map(
fun(Host) ->
- case gen_mod:db_type(Host, ?MODULE) of
+ case gen_mod:get_module_opt(Host, ?MODULE, db_type) of
sql -> {sql, Host};
Other -> {Other, global}
end
init_cache(Mod, Host, Opts) ->
case use_cache(Mod, Host) of
true ->
- CacheOpts = cache_opts(Host, Opts),
+ CacheOpts = cache_opts(Opts),
ets_cache:new(?PUSH_CACHE, CacheOpts);
false ->
ets_cache:delete(?PUSH_CACHE)
end.
--spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
use_cache(Mod, Host) ->
case erlang:function_exported(Mod, use_cache, 1) of
true -> Mod:use_cache(Host);
- false ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
end.
-spec cache_nodes(module(), binary()) -> [node()].
-behavior(gen_mod).
%% 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.
-export([c2s_session_pending/1, c2s_session_resumed/1, c2s_copy_session/2,
%%--------------------------------------------------------------------
-spec start(binary(), gen_mod:opts()) -> ok.
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 ->
wake_all(Host);
false ->
-spec reload(binary(), gen_mod:opts(), gen_mod:opts()) -> ok.
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, _} ->
wake_all(Host);
_ ->
mod_opt_type(wake_on_start) ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(wake_on_timeout) ->
- 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;
- (infinity) -> infinity
- end;
-mod_opt_type(O) when O == use_cache; O == cache_missed ->
- 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].
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(_Host) ->
+ [{resume_timeout, 86400},
+ {wake_on_start, false},
+ {wake_on_timeout, true}].
%%--------------------------------------------------------------------
%% Register/unregister hooks.
-spec c2s_handle_cast(c2s_state(), any()) -> c2s_state().
c2s_handle_cast(#{lserver := LServer} = State, push_enable) ->
- ResumeTimeout = gen_mod:get_module_opt(LServer, ?MODULE,
- resume_timeout, 86400),
- WakeOnTimeout = gen_mod:get_module_opt(LServer, ?MODULE,
- wake_on_timeout, true),
+ ResumeTimeout = gen_mod:get_module_opt(LServer, ?MODULE, resume_timeout),
+ WakeOnTimeout = gen_mod:get_module_opt(LServer, ?MODULE, wake_on_timeout),
State#{push_resume_timeout => ResumeTimeout,
push_wake_on_timeout => WakeOnTimeout};
c2s_handle_cast(State, push_disable) ->
c2s_unauthenticated_packet/2, try_register/5,
process_iq/1, send_registration_notifications/3,
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("logger.hrl").
-include("xmpp.hrl").
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_REGISTER, ?MODULE, process_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
?NS_REGISTER).
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_REGISTER,
?MODULE, process_iq, IQDisc),
[].
-spec stream_feature_register([xmpp_element()], binary()) -> [xmpp_element()].
-stream_feature_register(Acc, Host) ->
- AF = gen_mod:get_module_opt(Host, ?MODULE, access_from, all),
- case (AF /= none) of
- true ->
- [#feature_register{}|Acc];
- false ->
- Acc
- end.
+stream_feature_register(Acc, _Host) ->
+ [#feature_register{}|Acc].
c2s_unauthenticated_packet(#{ip := IP, server := Server} = State,
#iq{type = T, sub_els = [_]} = IQ)
process_iq(#iq{from = From, to = To} = IQ, Source) ->
IsCaptchaEnabled =
- case gen_mod:get_module_opt(To#jid.lserver, ?MODULE,
- captcha_protected, false) of
+ case gen_mod:get_module_opt(To#jid.lserver, ?MODULE, captcha_protected) of
true -> true;
false -> false
end,
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),
process_iq(IQ, Source, IsCaptchaEnabled, AllowRemove).
Instr = translate:translate(
Lang, <<"Choose a username and password to register "
"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 ->
Txt = translate:translate(Lang, <<"To register, visit ~s">>),
Desc = str:format(Txt, [URL]),
false -> {error, xmpp:err_bad_request(<<"Malformed username">>, Lang)};
_ ->
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),
case {acl:match_rule(Server, Access, JID),
check_ip_access(SourceRaw, IPAccess)}
send_welcome_message(JID) ->
Host = JID#jid.lserver,
- case gen_mod:get_module_opt(Host, ?MODULE, welcome_message,
- {<<"">>, <<"">>}) of
+ case gen_mod:get_module_opt(Host, ?MODULE, welcome_message) of
{<<"">>, <<"">>} -> ok;
{Subj, Body} ->
ejabberd_router:route(
send_registration_notifications(Mod, UJID, Source) ->
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;
JIDs when is_list(JIDs) ->
Body =
_Server) ->
allow;
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).
check_timeout(undefined) -> true;
is_strong_password2(Server, Password) ->
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 ->
true;
Entropy ->
may_remove_resource(From) -> From.
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) ->
case ejabberd_sm:get_user_ip(User, Server, Resource) of
mod_opt_type({welcome_message, body}) ->
fun iolist_to_binary/1;
mod_opt_type(redirect_url) ->
- fun iolist_to_binary/1;
-mod_opt_type(_) ->
- [access, access_from, access_remove, captcha_protected, ip_access,
- iqdisc, password_strength, registration_watchers, redirect_url,
- {welcome_message, subject}, {welcome_message, body}].
+ fun iolist_to_binary/1.
+
+mod_options(Host) ->
+ [{access, all},
+ {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());
(atom()) -> [atom()].
-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("logger.hrl").
%% {error, not_allowed} |
%% {error, invalid_jid}
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
error -> {error, invalid_jid};
JID ->
get_error_text({error, wrong_parameters}) ->
<<"Wrong parameters in the web formulary">>.
-mod_opt_type(_) -> [].
+mod_options(_) ->
+ [].
get_jid_info/4, encode_item/1, webadmin_page/3,
webadmin_user/4, get_versioning_feature/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("logger.hrl").
-optional_callbacks([use_cache/2, cache_nodes/1]).
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:init(Host, Opts),
init_cache(Mod, Host, Opts),
true ->
ok
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
?MODULE, process_iq, IQDisc);
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
false ->
#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
deny ->
Txt = <<"Access denied by service policy">>,
<- Items]))).
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) ->
- 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.
-spec get_versioning_feature([xmpp_element()], binary()) -> [xmpp_element()].
-spec init_cache(module(), binary(), gen_mod:opts()) -> ok.
init_cache(Mod, Host, Opts) ->
- CacheOpts = cache_opts(Host, Opts),
+ CacheOpts = cache_opts(Opts),
case use_cache(Mod, Host, roster_version) of
true ->
ets_cache:new(?ROSTER_VERSION_CACHE, CacheOpts);
ets_cache:delete(?ROSTER_ITEM_CACHE)
end.
--spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
use_cache(Mod, Host, Table) ->
case erlang:function_exported(Mod, use_cache, 2) of
true -> Mod:use_cache(Host, Table);
- false ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
end.
-spec cache_nodes(module(), binary()) -> [node()].
(infinity) -> infinity
end;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) ->
- [access, db_type, iqdisc, store_current_id,
- versioning, cache_life_time, cache_size, use_cache, cache_missed].
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(Host) ->
+ [{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)}].
use_cache(Host, Table) ->
case mnesia:table_info(Table, storage_type) of
disc_only_copies ->
- gen_mod:get_module_opt(
- Host, mod_roster, use_cache,
- ejabberd_config:use_cache(Host));
+ gen_mod:get_module_opt(Host, mod_roster, use_cache);
_ ->
false
end.
-protocol({xep, 185, '1.0'}).
%% 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
-export([s2s_out_auth_result/2, s2s_out_downgraded/2,
s2s_in_packet/2, s2s_out_packet/2, s2s_in_recv/3,
depends(_Host, _Opts) ->
[].
-mod_opt_type(_) ->
+mod_options(_Host) ->
[].
s2s_in_features(Acc, _) ->
-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]).
-include("ejabberd.hrl").
-spec log_packet(stanza(), binary()) -> ok.
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),
id = randoms:get_string(),
sub_els = [#forwarded{
if N /= error -> N end
end,
L)
- end;
-mod_opt_type(_) -> [loggers].
+ end.
+
+mod_options(_) ->
+ [{loggers, []}].
delete_group/2, get_group_opts/2, set_group_opts/3,
get_group_users/2, get_group_explicit_users/2,
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("logger.hrl").
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Tab, L).
-mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
-mod_opt_type(_) -> [db_type].
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end.
+
+mod_options(Host) ->
+ [{db_type, ejabberd_config:default_db(Host, ?MODULE)}].
-export([get_user_roster/2,
get_jid_info/4, process_item/2, in_subscription/6,
- out_subscription/4, mod_opt_type/1, opt_type/1, depends/2,
- transform_module_options/1]).
+ out_subscription/4, mod_opt_type/1, mod_options/1,
+ opt_type/1, depends/2, transform_module_options/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
parse_options(Host, Opts) ->
Eldap_ID = misc:atom_to_binary(gen_mod:get_module_proc(Host, ?MODULE)),
Cfg = eldap_utils:get_config(Host, Opts),
- GroupAttr = gen_mod:get_opt(ldap_groupattr, Opts, <<"cn">>),
- GroupDesc = gen_mod:get_opt(ldap_groupdesc, Opts, GroupAttr),
- UserDesc = gen_mod:get_opt(ldap_userdesc, Opts, <<"cn">>),
- UserUID = gen_mod:get_opt(ldap_useruid, Opts, <<"cn">>),
- UIDAttr = gen_mod:get_opt(ldap_memberattr, Opts, <<"memberUid">>),
- UIDAttrFormat = gen_mod:get_opt(ldap_memberattr_format, Opts, <<"%u">>),
- UIDAttrFormatRe = gen_mod:get_opt(ldap_memberattr_format_re, Opts, <<"">>),
- AuthCheck = gen_mod:get_opt(ldap_auth_check, Opts, true),
- ConfigFilter = gen_mod:get_opt({ldap_filter, Host}, Opts, <<"">>),
- ConfigUserFilter = gen_mod:get_opt({ldap_ufilter, Host}, Opts, <<"">>),
- ConfigGroupFilter = gen_mod:get_opt({ldap_gfilter, Host}, Opts, <<"">>),
- RosterFilter = gen_mod:get_opt({ldap_rfilter, Host}, Opts, <<"">>),
+ GroupAttr = gen_mod:get_opt(ldap_groupattr, Opts),
+ GroupDesc = case gen_mod:get_opt(ldap_groupdesc, Opts) of
+ undefined -> GroupAttr;
+ GD -> GD
+ end,
+ UserDesc = gen_mod:get_opt(ldap_userdesc, Opts),
+ UserUID = gen_mod:get_opt(ldap_useruid, Opts),
+ UIDAttr = gen_mod:get_opt(ldap_memberattr, Opts),
+ UIDAttrFormat = gen_mod:get_opt(ldap_memberattr_format, Opts),
+ UIDAttrFormatRe = gen_mod:get_opt(ldap_memberattr_format_re, Opts),
+ AuthCheck = gen_mod:get_opt(ldap_auth_check, 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, "=",
UIDAttrFormat/binary, ")(", GroupAttr/binary, "=%g))">>,
UserSubFilter = case ConfigUserFilter of
end,
UseCache.
-use_cache(Host, Opts) ->
- gen_mod:get_opt(use_cache, Opts, ejabberd_config:use_cache(Host)).
+use_cache(_Host, Opts) ->
+ gen_mod:get_opt(use_cache, Opts).
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+cache_opts(_Host, Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
Opt
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) ->
fun (on) -> true;
(off) -> false;
(false) -> false;
(true) -> true
end;
-mod_opt_type(ldap_filter) -> fun eldap_utils:check_filter/1;
-mod_opt_type(ldap_gfilter) -> fun eldap_utils:check_filter/1;
+mod_opt_type(ldap_gfilter) ->
+ opt_type(ldap_gfilter);
mod_opt_type(O) when O == cache_size;
O == cache_life_time ->
fun (I) when is_integer(I), I > 0 -> I;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
fun (B) when is_boolean(B) -> B end;
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_format) ->
fun iolist_to_binary/1;
fun (S) ->
Re = iolist_to_binary(S), {ok, MP} = re:compile(Re), MP
end;
-mod_opt_type(ldap_rfilter) -> fun eldap_utils:check_filter/1;
-mod_opt_type(ldap_ufilter) -> fun eldap_utils:check_filter/1;
+mod_opt_type(ldap_rfilter) ->
+ 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_useruid) -> fun iolist_to_binary/1;
-mod_opt_type(_) ->
- [ldap_auth_check, ldap_filter, ldap_gfilter,
- 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;
-opt_type(ldap_rfilter) -> fun eldap_utils:check_filter/1;
-opt_type(ldap_ufilter) -> fun eldap_utils:check_filter/1;
+mod_opt_type(Opt) ->
+ eldap_utils:opt_type(Opt).
+
+mod_options(Host) ->
+ [{ldap_auth_check, true},
+ {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(_) ->
[ldap_gfilter, ldap_rfilter, ldap_ufilter].
-behaviour(gen_mod).
-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("logger.hrl").
-include("xmpp.hrl").
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,
?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_SIC_0,
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_SIC_1).
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_SIC_0,
?MODULE, process_local_iq, IQDisc),
xmpp:make_error(IQ, xmpp:err_item_not_found(Txt, Lang))
end.
-mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
-mod_opt_type(_) -> [iqdisc].
+mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)}].
-include("logger.hrl").
-ifndef(SIP).
--export([start/2, stop/1, depends/2, mod_opt_type/1]).
+-export([start/2, stop/1, depends/2, mod_options/1]).
start(_, _) ->
?CRITICAL_MSG("ejabberd is not compiled with SIP support", []),
{error, sip_not_compiled}.
ok.
depends(_, _) ->
[].
-mod_opt_type(_) ->
+mod_options(_) ->
[].
-else.
-behaviour(gen_mod).
-export([data_in/2, data_out/2, message_in/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_lib("esip/include/esip.hrl").
{Type, {Host, Port}}
end,
L)
- end;
-mod_opt_type(_) ->
- [always_record_route, flow_timeout_tcp,
- flow_timeout_udp, record_route, routes, via].
+ end.
+
+mod_options(Host) ->
+ Route = <<"sip:", Host/binary, ";lr">>,
+ [{always_record_route, true},
+ {flow_timeout_tcp, 120},
+ {flow_timeout_udp, 29},
+ {record_route, Route},
+ {routes, [Route]},
+ {via, []}].
-endif.
esip:has_param(<<"tag">>, Params).
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) ->
{_, #uri{user = FUser, host = FServer}, FParams} = esip:get_hdr('from', Hdrs),
end.
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) ->
- gen_mod:get_module_opt(
- LServer, mod_sip, record_route,
- #uri{host = LServer, params = [{<<"lr">>, <<"">>}]}).
+ gen_mod:get_module_opt(LServer, mod_sip, record_route).
get_configured_routes(LServer) ->
- gen_mod:get_module_opt(
- LServer, mod_sip, routes,
- [#uri{host = LServer, params = [{<<"lr">>, <<"">>}]}]).
+ gen_mod:get_module_opt(LServer, mod_sip, routes).
mark_transaction_as_complete(TrID, State) ->
NewTrIDs = lists:delete(TrID, State#state.tr_ids),
-define(CALL_TIMEOUT, timer:seconds(30)).
-define(DEFAULT_EXPIRES, 3600).
--define(FLOW_TIMEOUT_UDP, 29).
--define(FLOW_TIMEOUT_TCP, 120).
-record(sip_session, {us = {<<"">>, <<"">>} :: {binary(), binary()},
socket = #sip_socket{} :: #sip_socket{},
case Type of
udp ->
gen_mod:get_module_opt(
- LServer, mod_sip, flow_timeout_udp,
- ?FLOW_TIMEOUT_UDP);
+ LServer, mod_sip, flow_timeout_udp);
_ ->
gen_mod:get_module_opt(
- LServer, mod_sip, flow_timeout_tcp,
- ?FLOW_TIMEOUT_TCP)
+ LServer, mod_sip, flow_timeout_tcp)
end.
update_table() ->
-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("logger.hrl").
-include("xmpp.hrl").
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,
?MODULE, process_iq, IQDisc).
_ -> search_running_node(SNode, Nodes)
end.
-mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
-mod_opt_type(_) -> [iqdisc].
+mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)}].
-protocol({xep, 198, '1.5.2'}).
%% 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
-export([c2s_stream_init/2, c2s_stream_started/2, c2s_stream_features/2,
c2s_authenticated_packet/2, c2s_unauthenticated_packet/2,
c2s_stream_init(Acc, _Opts) ->
Acc.
-c2s_stream_started(#{lserver := LServer, mgmt_options := Opts} = State,
- _StreamStart) ->
+c2s_stream_started(#{lserver := LServer} = State, _StreamStart) ->
State1 = maps:remove(mgmt_options, State),
- ResumeTimeout = get_resume_timeout(LServer, Opts),
- MaxResumeTimeout = get_max_resume_timeout(LServer, Opts, ResumeTimeout),
+ ResumeTimeout = get_configured_resume_timeout(LServer),
+ MaxResumeTimeout = get_max_resume_timeout(LServer, ResumeTimeout),
State1#{mgmt_state => inactive,
- mgmt_queue_type => get_queue_type(LServer, Opts),
- mgmt_max_queue => get_max_ack_queue(LServer, Opts),
+ mgmt_queue_type => get_queue_type(LServer),
+ mgmt_max_queue => get_max_ack_queue(LServer),
mgmt_timeout => ResumeTimeout,
mgmt_max_timeout => MaxResumeTimeout,
- mgmt_ack_timeout => get_ack_timeout(LServer, Opts),
- mgmt_resend => get_resend_on_timeout(LServer, Opts),
+ mgmt_ack_timeout => get_ack_timeout(LServer),
+ mgmt_resend => get_resend_on_timeout(LServer),
mgmt_stanzas_in => 0,
mgmt_stanzas_out => 0,
mgmt_stanzas_req => 0};
%%%===================================================================
%%% Configuration processing
%%%===================================================================
-get_max_ack_queue(Host, Opts) ->
- gen_mod:get_module_opt(Host, ?MODULE, max_ack_queue,
- gen_mod:get_opt(max_ack_queue, Opts, 5000)).
+get_max_ack_queue(Host) ->
+ gen_mod:get_module_opt(Host, ?MODULE, max_ack_queue).
-get_resume_timeout(Host, Opts) ->
- gen_mod:get_module_opt(Host, ?MODULE, resume_timeout,
- gen_mod:get_opt(resume_timeout, Opts, 300)).
+get_configured_resume_timeout(Host) ->
+ gen_mod:get_module_opt(Host, ?MODULE, resume_timeout).
-get_max_resume_timeout(Host, Opts, ResumeTimeout) ->
- case gen_mod:get_module_opt(Host, ?MODULE, max_resume_timeout,
- gen_mod:get_opt(max_resume_timeout, Opts)) of
+get_max_resume_timeout(Host, ResumeTimeout) ->
+ case gen_mod:get_module_opt(Host, ?MODULE, max_resume_timeout) of
undefined -> ResumeTimeout;
Max when Max >= ResumeTimeout -> Max;
_ -> ResumeTimeout
end.
-get_ack_timeout(Host, Opts) ->
- case gen_mod:get_module_opt(Host, ?MODULE, ack_timeout,
- gen_mod:get_opt(ack_timeout, Opts, 60)) of
+get_ack_timeout(Host) ->
+ case gen_mod:get_module_opt(Host, ?MODULE, ack_timeout) of
infinity -> infinity;
T -> timer:seconds(T)
end.
-get_resend_on_timeout(Host, Opts) ->
- gen_mod:get_module_opt(Host, ?MODULE, resend_on_timeout,
- gen_mod:get_opt(resend_on_timeout, Opts, false)).
+get_resend_on_timeout(Host) ->
+ gen_mod:get_module_opt(Host, ?MODULE, resend_on_timeout).
-get_queue_type(Host, Opts) ->
- case 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.
+get_queue_type(Host) ->
+ gen_mod:get_module_opt(Host, ?MODULE, queue_type).
mod_opt_type(max_ack_queue) ->
fun(I) when is_integer(I), I > 0 -> I;
mod_opt_type(resume_timeout) ->
fun(I) when is_integer(I), I >= 0 -> I end;
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) ->
fun(I) when is_integer(I), I > 0 -> I;
(infinity) -> infinity
(if_offline) -> if_offline
end;
mod_opt_type(queue_type) ->
- fun(ram) -> ram; (file) -> file end;
-mod_opt_type(_) ->
- [max_ack_queue, resume_timeout, max_resume_timeout, ack_timeout,
- resend_on_timeout, queue_type].
+ fun(ram) -> ram; (file) -> file end.
+
+mod_options(Host) ->
+ [{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)}].
-behaviour(gen_mod).
-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("logger.hrl").
-include("xmpp.hrl").
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_TIME, ?MODULE, process_local_iq, IQDisc).
?NS_TIME).
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_TIME,
?MODULE, process_local_iq, IQDisc);
depends(_Host, _Opts) ->
[].
-mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
-mod_opt_type(_) -> [iqdisc].
+mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)}].
-behaviour(gen_server).
-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,
remove_user/2, export/1, import_info/0, import/5, import_start/2,
depends/2, process_search/1, process_vcard/1, get_vcard/2,
-include("mod_vcard.hrl").
-include("translate.hrl").
--define(JUD_MATCHES, 30).
-define(VCARD_CACHE, vcard_cache).
-callback init(binary(), gen_mod:opts()) -> any().
init_cache(Mod, Host, Opts),
ejabberd_hooks:add(remove_user, Host, ?MODULE,
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,
?NS_VCARD, ?MODULE, process_local_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE,
get_sm_features, 50),
ejabberd_hooks:add(vcard_iq_set, Host, ?MODULE, vcard_iq_set, 50),
- MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
- Search = gen_mod:get_opt(search, Opts, false),
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts),
+ Search = gen_mod:get_opt(search, Opts),
if Search ->
lists:foreach(
fun(MyHost) ->
false ->
?WARNING_MSG("vcard search functionality is "
"not implemented for ~s backend",
- [gen_mod:db_type(Host, Opts, ?MODULE)]);
+ [gen_mod:get_opt(db_type, Opts)]);
true ->
ejabberd_router:register_route(MyHost, Host)
end
binary(), binary()) -> [identity()].
disco_identity(Acc, _From, To, <<"">>, Lang) ->
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">>,
type = <<"user">>,
name = translate:translate(Lang, Name)}|Acc];
search(LServer, XFields) ->
Data = [{Var, Vals} || #xdata_field{var = Var, values = Vals} <- XFields],
Mod = gen_mod:db_mod(LServer, ?MODULE),
- AllowReturnAll = gen_mod:get_module_opt(LServer, ?MODULE, allow_return_all,
- false),
- MaxMatch = gen_mod:get_module_opt(LServer, ?MODULE, matches, ?JUD_MATCHES),
+ AllowReturnAll = gen_mod:get_module_opt(LServer, ?MODULE, allow_return_all),
+ MaxMatch = gen_mod:get_module_opt(LServer, ?MODULE, matches),
Mod:search(LServer, Data, AllowReturnAll, MaxMatch).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end.
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+cache_opts(_Host, Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
use_cache(Mod, Host) ->
case erlang:function_exported(Mod, use_cache, 1) of
true -> Mod:use_cache(Host);
- false ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host))
+ false -> gen_mod:get_module_opt(Host, ?MODULE, use_cache)
end.
-spec cache_nodes(module(), binary()) -> [node()].
end;
mod_opt_type(search) ->
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 ->
fun (I) when is_integer(I), I > 0 -> I;
(infinity) -> infinity
end;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) ->
- [allow_return_all, db_type, host, hosts, iqdisc, matches,
- search, search_all_hosts, cache_life_time, cache_size,
- use_cache, cache_missed, name].
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(Host) ->
+ [{allow_return_all, false},
+ {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)}].
-export([start_link/2]).
-export([init/2, stop/1, get_vcard/2, set_vcard/4, search/4,
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]).
%% gen_server callbacks
[{<<"%s">>, V, 1} || V <- AttrValues]).
default_vcard_map() ->
- [{<<"NICKNAME">>, <<"%u">>, []},
- {<<"FN">>, <<"%s">>, [<<"displayName">>]},
- {<<"FAMILY">>, <<"%s">>, [<<"sn">>]},
- {<<"GIVEN">>, <<"%s">>, [<<"givenName">>]},
- {<<"MIDDLE">>, <<"%s">>, [<<"initials">>]},
- {<<"ORGNAME">>, <<"%s">>, [<<"o">>]},
- {<<"ORGUNIT">>, <<"%s">>, [<<"ou">>]},
- {<<"CTRY">>, <<"%s">>, [<<"c">>]},
- {<<"LOCALITY">>, <<"%s">>, [<<"l">>]},
- {<<"STREET">>, <<"%s">>, [<<"street">>]},
- {<<"REGION">>, <<"%s">>, [<<"st">>]},
- {<<"PCODE">>, <<"%s">>, [<<"postalCode">>]},
- {<<"TITLE">>, <<"%s">>, [<<"title">>]},
- {<<"URL">>, <<"%s">>, [<<"labeleduri">>]},
- {<<"DESC">>, <<"%s">>, [<<"description">>]},
- {<<"TEL">>, <<"%s">>, [<<"telephoneNumber">>]},
- {<<"EMAIL">>, <<"%s">>, [<<"mail">>]},
- {<<"BDAY">>, <<"%s">>, [<<"birthDay">>]},
- {<<"ROLE">>, <<"%s">>, [<<"employeeType">>]},
- {<<"PHOTO">>, <<"%s">>, [<<"jpegPhoto">>]}].
+ [{<<"NICKNAME">>, [{<<"%u">>, []}]},
+ {<<"FN">>, [{<<"%s">>, [<<"displayName">>]}]},
+ {<<"FAMILY">>, [{<<"%s">>, [<<"sn">>]}]},
+ {<<"GIVEN">>, [{<<"%s">>, [<<"givenName">>]}]},
+ {<<"MIDDLE">>, [{<<"%s">>, [<<"initials">>]}]},
+ {<<"ORGNAME">>, [{<<"%s">>, [<<"o">>]}]},
+ {<<"ORGUNIT">>, [{<<"%s">>, [<<"ou">>]}]},
+ {<<"CTRY">>, [{<<"%s">>, [<<"c">>]}]},
+ {<<"LOCALITY">>, [{<<"%s">>, [<<"l">>]}]},
+ {<<"STREET">>, [{<<"%s">>, [<<"street">>]}]},
+ {<<"REGION">>, [{<<"%s">>, [<<"st">>]}]},
+ {<<"PCODE">>, [{<<"%s">>, [<<"postalCode">>]}]},
+ {<<"TITLE">>, [{<<"%s">>, [<<"title">>]}]},
+ {<<"URL">>, [{<<"%s">>, [<<"labeleduri">>]}]},
+ {<<"DESC">>, [{<<"%s">>, [<<"description">>]}]},
+ {<<"TEL">>, [{<<"%s">>, [<<"telephoneNumber">>]}]},
+ {<<"EMAIL">>, [{<<"%s">>, [<<"mail">>]}]},
+ {<<"BDAY">>, [{<<"%s">>, [<<"birthDay">>]}]},
+ {<<"ROLE">>, [{<<"%s">>, [<<"employeeType">>]}]},
+ {<<"PHOTO">>, [{<<"%s">>, [<<"jpegPhoto">>]}]}].
default_search_fields() ->
[{?T("User"), <<"%u">>},
{?T("Organization Unit"), <<"ORGUNIT">>}].
parse_options(Host, Opts) ->
- MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
- Search = gen_mod:get_opt(search, Opts, false),
- Matches = gen_mod:get_opt(matches, Opts, 30),
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts),
+ Search = gen_mod:get_opt(search, Opts),
+ Matches = gen_mod:get_opt(matches, Opts),
Eldap_ID = misc:atom_to_binary(gen_mod:get_module_proc(Host, ?PROCNAME)),
Cfg = eldap_utils:get_config(Host, Opts),
- UIDsTemp = gen_mod:get_opt({ldap_uids, Host}, Opts,
- [{<<"uid">>, <<"%u">>}]),
+ UIDsTemp = gen_mod:get_opt(ldap_uids, Opts),
UIDs = eldap_utils:uids_domain_subst(Host, UIDsTemp),
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;
F ->
{ok, SearchFilter} =
eldap_filter:parse(eldap_filter:do_sub(UserFilter,
[{<<"%u">>, <<"*">>}])),
- VCardMap = gen_mod:get_opt(ldap_vcard_map, Opts, default_vcard_map()),
- SearchFields = gen_mod:get_opt(ldap_search_fields, Opts,
- default_search_fields()),
- SearchReported = gen_mod:get_opt(ldap_search_reported, Opts,
- default_search_reported()),
+ VCardMap = gen_mod:get_opt(ldap_vcard_map, Opts),
+ SearchFields = gen_mod:get_opt(ldap_search_fields, Opts),
+ SearchReported = gen_mod:get_opt(ldap_search_reported, Opts),
UIDAttrs = [UAttr || {UAttr, _} <- UIDs],
VCardMapAttrs = lists:usort(lists:append([A
|| {_, _, A} <- VCardMap])
search_reported_attrs = SearchReportedAttrs,
matches = Matches}.
-mod_opt_type(ldap_filter) -> fun eldap_utils:check_filter/1;
mod_opt_type(ldap_search_fields) ->
fun (Ls) ->
[{iolist_to_binary(S), iolist_to_binary(P)}
[{iolist_to_binary(S), iolist_to_binary(P)}
|| {S, P} <- Ls]
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) ->
fun (Ls) ->
lists:map(fun ({S, [{P, L}]}) ->
end,
Ls)
end;
-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_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].
+mod_opt_type(Opt) ->
+ eldap_utils:opt_type(Opt).
+
+mod_options(Host) ->
+ [{ldap_search_fields, default_search_fields()},
+ {ldap_search_reported, default_search_reported()},
+ {ldap_vcard_map, default_vcard_map()}
+ | lists:map(
+ fun({Opt, Default}) ->
+ {Opt, ejabberd_config:get_option({Opt, Host}, Default)}
+ end, eldap_utils:options(Host))].
search_fields/1, search_reported/1, remove_user/2]).
-export([is_search_supported/1]).
-export([need_transform/1, transform/1]).
+-export([mod_opt_type/1, mod_options/1]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
NewMatch = case SVar of
<<"user">> ->
case gen_mod:get_module_opt(LServer, ?MODULE,
- search_all_hosts,
- true) of
+ search_all_hosts) of
true -> Match#vcard_search{luser = make_val(LVal)};
false ->
Host = find_my_host(LServer),
{<<"email">>, (R#vcard_search.email)},
{<<"orgname">>, (R#vcard_search.orgname)},
{<<"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}].
-export([start/2, stop/1, reload/3]).
-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("logger.hrl").
init_cache(Host, Opts) ->
case use_cache(Host) of
true ->
- CacheOpts = cache_opts(Host, Opts),
+ CacheOpts = cache_opts(Opts),
ets_cache:new(?VCARD_XUPDATE_CACHE, CacheOpts);
false ->
ets_cache:delete(?VCARD_XUPDATE_CACHE)
end.
--spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
-cache_opts(Host, Opts) ->
- MaxSize = gen_mod:get_opt(
- cache_size, Opts,
- ejabberd_config:cache_size(Host)),
- 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
+-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
+cache_opts(Opts) ->
+ MaxSize = gen_mod:get_opt(cache_size, Opts),
+ CacheMissed = gen_mod:get_opt(cache_missed, Opts),
+ LifeTime = case gen_mod:get_opt(cache_life_time, Opts) of
infinity -> infinity;
I -> timer:seconds(I)
end,
-spec use_cache(binary()) -> boolean().
use_cache(Host) ->
- gen_mod:get_module_opt(
- Host, ?MODULE, use_cache,
- ejabberd_config:use_cache(Host)).
+ gen_mod:get_module_opt(Host, ?MODULE, use_cache).
-spec compute_hash(xmlel()) -> binary() | external.
compute_hash(VCard) ->
(infinity) -> infinity
end;
mod_opt_type(O) when O == use_cache; O == cache_missed ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) ->
- [cache_life_time, cache_size, use_cache, cache_missed].
+ fun (B) when is_boolean(B) -> B end.
+
+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)}].
-behaviour(gen_mod).
-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("logger.hrl").
-include("xmpp.hrl").
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_VERSION, ?MODULE, process_local_iq,
IQDisc).
?NS_VERSION).
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, _} ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VERSION,
?MODULE, process_local_iq, IQDisc);
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
process_local_iq(#iq{type = get, to = To} = IQ) ->
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();
false -> undefined
end,
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(show_os) ->
- fun (B) when is_boolean(B) -> B end;
-mod_opt_type(_) -> [iqdisc, show_os].
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(Host) ->
+ [{iqdisc, gen_iq_handler:iqdisc(Host)},
+ {show_os, true}].