diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 8c17e577f..139047d9c 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -770,22 +770,32 @@ add_option(Opt, Val) -> -spec prepare_opt_val(any(), any(), check_fun(), any()) -> any(). prepare_opt_val(Opt, Val, F, Default) -> - Res = case F of - {Mod, Fun} -> - catch Mod:Fun(Val); - _ -> - catch F(Val) - end, - case Res of - {'EXIT', _} -> + Call = case F of + {Mod, Fun} -> + fun() -> Mod:Fun(Val) end; + _ -> + fun() -> F(Val) end + end, + try Call() of + Res -> + Res + catch {replace_with, NewRes} -> + NewRes; + {invalid_syntax, Error} -> + ?WARNING_MSG("incorrect value '~s' of option '~s', " + "using '~s' as fallback: ~s", + [format_term(Val), + format_term(Opt), + format_term(Default), + Error]), + Default; + _:_ -> ?WARNING_MSG("incorrect value '~s' of option '~s', " "using '~s' as fallback", [format_term(Val), format_term(Opt), format_term(Default)]), - Default; - _ -> - Res + Default end. -type check_fun() :: fun((any()) -> any()) | {module(), atom()}. @@ -908,19 +918,26 @@ get_modules_with_options() -> validate_opts(#state{opts = Opts} = State) -> ModOpts = get_modules_with_options(), - NewOpts = lists:filter( - fun(#local_config{key = {Opt, _Host}, value = Val}) -> + NewOpts = lists:filtermap( + fun(#local_config{key = {Opt, _Host}, value = Val} = In) -> case dict:find(Opt, ModOpts) of {ok, [Mod|_]} -> VFun = Mod:opt_type(Opt), - case catch VFun(Val) of - {'EXIT', _} -> + try VFun(Val) of + _ -> + true + catch {replace_with, NewVal} -> + {true, In#local_config{value = NewVal}}; + {invalid_syntax, Error} -> + ?ERROR_MSG("ignoring option '~s' with " + "invalid value: ~p: ~s", + [Opt, Val, Error]), + false; + _:_ -> ?ERROR_MSG("ignoring option '~s' with " "invalid value: ~p", [Opt, Val]), - false; - _ -> - true + false end; _ -> ?ERROR_MSG("unknown option '~s' will be likely" diff --git a/src/gen_mod.erl b/src/gen_mod.erl index f96397192..1cc65ac21 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -266,18 +266,25 @@ get_opt_host(Host, Opts, Default) -> ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host). validate_opts(Module, Opts) -> - lists:filter( + lists:filtermap( fun({Opt, Val}) -> case catch Module:mod_opt_type(Opt) of VFun when is_function(VFun) -> - case catch VFun(Val) of - {'EXIT', _} -> + try VFun(Val) of + _ -> + true + catch {replace_with, NewVal} -> + {true, {Opt, NewVal}}; + {invalid_syntax, Error} -> + ?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 " "option '~s' of module '~s'", [Val, Opt, Module]), - false; - _ -> - true + false end; L when is_list(L) -> SOpts = str:join([[$', atom_to_list(A), $'] || A <- L], <<", ">>),