mirror of
https://github.com/processone/ejabberd.git
synced 2024-06-16 22:05:29 +02:00
Make it possible to validate second-level options
This commit is contained in:
parent
e790e66f47
commit
fb17c1b99f
139
src/gen_mod.erl
139
src/gen_mod.erl
|
@ -191,7 +191,7 @@ start_module(Host, Module, Opts) ->
|
||||||
start_module(Host, Module, Opts0, NeedValidation) ->
|
start_module(Host, Module, Opts0, NeedValidation) ->
|
||||||
?DEBUG("loading ~s at ~s", [Module, Host]),
|
?DEBUG("loading ~s at ~s", [Module, Host]),
|
||||||
Opts = if NeedValidation ->
|
Opts = if NeedValidation ->
|
||||||
validate_opts(Module, Opts0);
|
validate_opts(Host, Module, Opts0);
|
||||||
true ->
|
true ->
|
||||||
Opts0
|
Opts0
|
||||||
end,
|
end,
|
||||||
|
@ -244,7 +244,7 @@ reload_modules(Host) ->
|
||||||
fun({Mod, OldOpts}) ->
|
fun({Mod, OldOpts}) ->
|
||||||
case lists:keyfind(Mod, 1, NewMods) of
|
case lists:keyfind(Mod, 1, NewMods) of
|
||||||
{_, NewOpts0} ->
|
{_, NewOpts0} ->
|
||||||
case validate_opts(Mod, NewOpts0) of
|
case validate_opts(Host, Mod, NewOpts0) of
|
||||||
OldOpts ->
|
OldOpts ->
|
||||||
ok;
|
ok;
|
||||||
NewOpts ->
|
NewOpts ->
|
||||||
|
@ -441,74 +441,95 @@ get_opt_host(Host, Opts, Default) ->
|
||||||
Val = get_opt(host, Opts, Default),
|
Val = get_opt(host, Opts, Default),
|
||||||
ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host).
|
ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host).
|
||||||
|
|
||||||
|
-spec get_validators(binary(), module(), opts()) -> {ok, [{atom(), check_fun()}]} | undef.
|
||||||
get_module_mod_opt_type_fun(Module) ->
|
get_validators(Host, Module, Opts) ->
|
||||||
DBSubMods = ejabberd_config:v_dbs_mods(Module),
|
try Module:mod_opt_type('') of
|
||||||
fun(Opt) ->
|
L ->
|
||||||
Res = lists:foldl(fun(Mod, {Funs, ArgsList, _} = Acc) ->
|
SubMods1 = case lists:member(db_type, L) of
|
||||||
case catch Mod:mod_opt_type(Opt) of
|
true -> [db_mod(Host, Opts, Module)];
|
||||||
Fun when is_function(Fun) ->
|
false -> []
|
||||||
{[Fun | Funs], ArgsList, true};
|
end,
|
||||||
L when is_list(L) ->
|
SubMods2 = case lists:member(ram_db_type, L) of
|
||||||
{Funs, L ++ ArgsList, true};
|
true -> [ram_db_mod(Host, Opts, Module)];
|
||||||
_ ->
|
false -> []
|
||||||
Acc
|
end,
|
||||||
end
|
{ok, dict:to_list(
|
||||||
end, {[], [], false}, [Module | DBSubMods]),
|
lists:foldl(
|
||||||
case Res of
|
fun(Mod, D) ->
|
||||||
{[], [], false} ->
|
try Mod:mod_opt_type('') of
|
||||||
throw({'EXIT', {undef, mod_opt_type}});
|
Os ->
|
||||||
{[], Args, _} -> Args;
|
lists:foldl(
|
||||||
{Funs, _, _} ->
|
fun({Opt, SubOpt} = O, Acc) ->
|
||||||
fun(Val) -> try_mod_opt_type(Funs, Val) end
|
F = Mod:mod_opt_type(O),
|
||||||
end
|
dict:append(Opt, {SubOpt, F}, 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
|
||||||
end.
|
end.
|
||||||
|
|
||||||
try_mod_opt_type([Fun|Funs], Val) ->
|
-spec validate_opts(binary(), module(), opts()) -> opts().
|
||||||
try Fun(Val) of
|
validate_opts(Host, Module, Opts) ->
|
||||||
NewVal -> NewVal
|
case get_validators(Host, Module, Opts) of
|
||||||
catch {invalid_syntax, _Error} = E2 ->
|
{ok, Validators} ->
|
||||||
throw(E2);
|
validate_opts(Host, Module, Opts, Validators);
|
||||||
_:_ ->
|
undef ->
|
||||||
try_mod_opt_type(Funs, Val)
|
Opts
|
||||||
end.
|
end.
|
||||||
|
|
||||||
validate_opts(Module, Opts) ->
|
validate_opts(Host, Module, Opts, Validators) when is_list(Opts) ->
|
||||||
ModOptFun = get_module_mod_opt_type_fun(Module),
|
lists:flatmap(
|
||||||
lists:filtermap(
|
fun({Opt, Val}) when is_atom(Opt) ->
|
||||||
fun({Opt, Val}) ->
|
case lists:keyfind(Opt, 1, Validators) of
|
||||||
case catch ModOptFun(Opt) of
|
{_, VFun} when is_function(VFun) ->
|
||||||
VFun when is_function(VFun) ->
|
validate_opt(Module, Opt, Val, VFun);
|
||||||
try VFun(Val) of
|
{_, SubValidators} ->
|
||||||
NewVal ->
|
try validate_opts(Host, Module, Val, SubValidators) of
|
||||||
{true, {Opt, NewVal}}
|
SubOpts -> [{Opt, SubOpts}]
|
||||||
catch {invalid_syntax, Error} ->
|
catch _:bad_option ->
|
||||||
?ERROR_MSG("ignoring invalid value '~p' for "
|
|
||||||
"option '~s' of module '~s': ~s",
|
|
||||||
[Val, Opt, Module, Error]),
|
|
||||||
false;
|
|
||||||
_:_ ->
|
|
||||||
?ERROR_MSG("ignoring invalid value '~p' for "
|
?ERROR_MSG("ignoring invalid value '~p' for "
|
||||||
"option '~s' of module '~s'",
|
"option '~s' of module '~s'",
|
||||||
[Val, Opt, Module]),
|
[Val, Opt, Module]),
|
||||||
false
|
[]
|
||||||
end;
|
end;
|
||||||
L when is_list(L) ->
|
false ->
|
||||||
SOpts = str:join([[$', atom_to_list(A), $'] || A <- L], <<", ">>),
|
|
||||||
?ERROR_MSG("unknown option '~s' for module '~s' will be"
|
?ERROR_MSG("unknown option '~s' for module '~s' will be"
|
||||||
" likely ignored, available options are: ~s",
|
" likely ignored, available options are: ~s",
|
||||||
[Opt, Module, SOpts]),
|
[Opt, Module,
|
||||||
true;
|
misc:join_atoms([K || {K, _} <- Validators],
|
||||||
{'EXIT', {undef, _}} ->
|
<<", ">>)]),
|
||||||
?WARNING_MSG("module '~s' doesn't export mod_opt_type/1",
|
[{Opt, Val}]
|
||||||
[Module]),
|
|
||||||
true
|
|
||||||
end;
|
end;
|
||||||
(Junk) ->
|
(_) ->
|
||||||
?ERROR_MSG("failed to understand option ~p for module '~s'",
|
erlang:error(bad_option)
|
||||||
[Junk, Module]),
|
end, Opts);
|
||||||
false
|
validate_opts(_, _, _, _) ->
|
||||||
end, Opts).
|
erlang:error(bad_option).
|
||||||
|
|
||||||
|
-spec validate_opt(module(), atom(), any(),
|
||||||
|
[{atom(), check_fun(), any()}]) -> [{atom(), any()}].
|
||||||
|
validate_opt(Module, Opt, Val, VFun) ->
|
||||||
|
try VFun(Val) of
|
||||||
|
NewVal -> [{Opt, NewVal}]
|
||||||
|
catch {invalid_syntax, Error} ->
|
||||||
|
?ERROR_MSG("ignoring invalid value '~p' for "
|
||||||
|
"option '~s' of module '~s': ~s",
|
||||||
|
[Val, Opt, Module, Error]),
|
||||||
|
[];
|
||||||
|
_:_ ->
|
||||||
|
?ERROR_MSG("ignoring invalid value '~p' for "
|
||||||
|
"option '~s' of module '~s'",
|
||||||
|
[Val, Opt, Module]),
|
||||||
|
[]
|
||||||
|
end.
|
||||||
|
|
||||||
-spec db_type(binary() | global, module()) -> db_type();
|
-spec db_type(binary() | global, module()) -> db_type();
|
||||||
(opts(), module()) -> db_type().
|
(opts(), module()) -> db_type().
|
||||||
|
|
Loading…
Reference in New Issue
Block a user