aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_config.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejabberd_config.erl')
-rw-r--r--src/ejabberd_config.erl235
1 files changed, 225 insertions, 10 deletions
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl
index e2a8633ee..0a4208b7f 100644
--- a/src/ejabberd_config.erl
+++ b/src/ejabberd_config.erl
@@ -29,9 +29,13 @@
-export([start/0, load_file/1,
add_global_option/2, add_local_option/2,
- get_global_option/1, get_local_option/1]).
+ get_global_option/2, get_local_option/2,
+ get_global_option/3, get_local_option/3]).
-export([get_vh_by_auth_method/1]).
-export([is_file_readable/1]).
+-export([get_version/0, get_myhosts/0, get_mylang/0]).
+-export([prepare_opt_val/4]).
+-export([convert_table_to_binary/5]).
-include("ejabberd.hrl").
-include("ejabberd_config.hrl").
@@ -96,11 +100,15 @@ load_file(File) ->
%% in which the options 'include_config_file' were parsed
%% and the terms in those files were included.
%% @spec(string()) -> [term()]
+%% @spec(iolist()) -> [term()]
+get_plain_terms_file(File) when is_binary(File) ->
+ get_plain_terms_file(binary_to_list(File));
get_plain_terms_file(File1) ->
File = get_absolute_path(File1),
case file:consult(File) of
{ok, Terms} ->
- include_config_files(Terms);
+ BinTerms = strings_to_binary(Terms),
+ include_config_files(BinTerms);
{error, {LineNumber, erl_parse, _ParseMessage} = Reason} ->
ExitText = describe_config_problem(File, Reason, LineNumber),
?ERROR_MSG(ExitText, []),
@@ -159,7 +167,7 @@ normalize_hosts(Hosts) ->
normalize_hosts([], PrepHosts) ->
lists:reverse(PrepHosts);
normalize_hosts([Host|Hosts], PrepHosts) ->
- case jlib:nodeprep(Host) of
+ case jlib:nodeprep(iolist_to_binary(Host)) of
error ->
?ERROR_MSG("Can't load config file: "
"invalid host name [~p]", [Host]),
@@ -564,7 +572,6 @@ set_opts(State) ->
exit("Error reading Mnesia database")
end.
-
add_global_option(Opt, Val) ->
mnesia:transaction(fun() ->
mnesia:write(#config{key = Opt,
@@ -577,23 +584,63 @@ add_local_option(Opt, Val) ->
value = Val})
end).
+-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', _} ->
+ ?INFO_MSG("Configuration problem:~n"
+ "** Option: ~s~n"
+ "** Invalid value: ~s~n"
+ "** Using as fallback: ~s",
+ [format_term(Opt),
+ format_term(Val),
+ format_term(Default)]),
+ Default;
+ _ ->
+ Res
+ end.
+
+-type check_fun() :: fun((any()) -> any()) | {module(), atom()}.
+
+-spec get_global_option(any(), check_fun()) -> any().
+
+get_global_option(Opt, F) ->
+ get_global_option(Opt, F, undefined).
+
+-spec get_global_option(any(), check_fun(), any()) -> any().
-get_global_option(Opt) ->
+get_global_option(Opt, F, Default) ->
case ets:lookup(config, Opt) of
[#config{value = Val}] ->
- Val;
+ prepare_opt_val(Opt, Val, F, Default);
_ ->
- undefined
+ Default
end.
-get_local_option(Opt) ->
+-spec get_local_option(any(), check_fun()) -> any().
+
+get_local_option(Opt, F) ->
+ get_local_option(Opt, F, undefined).
+
+-spec get_local_option(any(), check_fun(), any()) -> any().
+
+get_local_option(Opt, F, Default) ->
case ets:lookup(local_config, Opt) of
[#local_config{value = Val}] ->
- Val;
+ prepare_opt_val(Opt, Val, F, Default);
_ ->
- undefined
+ Default
end.
+-spec get_vh_by_auth_method(atom()) -> [binary()].
+
%% Return the list of hosts handled by a given module
get_vh_by_auth_method(AuthMethod) ->
mnesia:dirty_select(local_config,
@@ -613,8 +660,25 @@ is_file_readable(Path) ->
false
end.
+get_version() ->
+ list_to_binary(element(2, application:get_key(ejabberd, vsn))).
+
+-spec get_myhosts() -> [binary()].
+
+get_myhosts() ->
+ ejabberd_config:get_global_option(hosts, fun(V) -> V end).
+
+-spec get_mylang() -> binary().
+
+get_mylang() ->
+ ejabberd_config:get_global_option(
+ language,
+ fun iolist_to_binary/1,
+ <<"en">>).
+
replace_module(mod_announce_odbc) -> {mod_announce, odbc};
replace_module(mod_blocking_odbc) -> {mod_blocking, odbc};
+replace_module(mod_caps_odbc) -> {mod_caps, odbc};
replace_module(mod_irc_odbc) -> {mod_irc, odbc};
replace_module(mod_last_odbc) -> {mod_last, odbc};
replace_module(mod_muc_odbc) -> {mod_muc, odbc};
@@ -632,10 +696,161 @@ replace_modules(Modules) ->
fun({Module, Opts}) ->
case replace_module(Module) of
{NewModule, DBType} ->
+ emit_deprecation_warning(Module, NewModule, DBType),
NewOpts = [{db_type, DBType} |
lists:keydelete(db_type, 1, Opts)],
{NewModule, NewOpts};
NewModule ->
+ if Module /= NewModule ->
+ emit_deprecation_warning(Module, NewModule);
+ true ->
+ ok
+ end,
{NewModule, Opts}
end
end, Modules).
+
+strings_to_binary([]) ->
+ [];
+strings_to_binary(L) when is_list(L) ->
+ case is_string(L) of
+ true ->
+ list_to_binary(L);
+ false ->
+ strings_to_binary1(L)
+ end;
+strings_to_binary(T) when is_tuple(T) ->
+ list_to_tuple(strings_to_binary(tuple_to_list(T)));
+strings_to_binary(X) ->
+ X.
+
+strings_to_binary1([El|L]) ->
+ [strings_to_binary(El)|strings_to_binary1(L)];
+strings_to_binary1([]) ->
+ [];
+strings_to_binary1(T) ->
+ T.
+
+is_string([C|T]) when (C >= 0) and (C =< 255) ->
+ is_string(T);
+is_string([]) ->
+ true;
+is_string(_) ->
+ false.
+
+binary_to_strings(B) when is_binary(B) ->
+ binary_to_list(B);
+binary_to_strings([H|T]) ->
+ [binary_to_strings(H)|binary_to_strings(T)];
+binary_to_strings(T) when is_tuple(T) ->
+ list_to_tuple(binary_to_strings(tuple_to_list(T)));
+binary_to_strings(T) ->
+ T.
+
+format_term(Bin) when is_binary(Bin) ->
+ io_lib:format("\"~s\"", [Bin]);
+format_term(S) when is_list(S), S /= [] ->
+ case lists:all(fun(C) -> (C>=0) and (C=<255) end, S) of
+ true ->
+ io_lib:format("\"~s\"", [S]);
+ false ->
+ io_lib:format("~p", [binary_to_strings(S)])
+ end;
+format_term(T) ->
+ io_lib:format("~p", [binary_to_strings(T)]).
+
+-spec convert_table_to_binary(atom(), [atom()], atom(),
+ fun(), fun()) -> ok.
+
+convert_table_to_binary(Tab, Fields, Type, DetectFun, ConvertFun) ->
+ case is_table_still_list(Tab, DetectFun) of
+ true ->
+ ?INFO_MSG("Converting '~s' table from strings to binaries.", [Tab]),
+ TmpTab = list_to_atom(atom_to_list(Tab) ++ "_tmp_table"),
+ catch mnesia:delete_table(TmpTab),
+ case mnesia:create_table(TmpTab,
+ [{disc_only_copies, [node()]},
+ {type, Type},
+ {local_content, true},
+ {record_name, Tab},
+ {attributes, Fields}]) of
+ {atomic, ok} ->
+ mnesia:transform_table(Tab, ignore, Fields),
+ case mnesia:transaction(
+ fun() ->
+ mnesia:write_lock_table(TmpTab),
+ mnesia:foldl(
+ fun(R, _) ->
+ NewR = ConvertFun(R),
+ mnesia:dirty_write(TmpTab, NewR)
+ end, ok, Tab)
+ end) of
+ {atomic, ok} ->
+ mnesia:clear_table(Tab),
+ case mnesia:transaction(
+ fun() ->
+ mnesia:write_lock_table(Tab),
+ mnesia:foldl(
+ fun(R, _) ->
+ mnesia:dirty_write(R)
+ end, ok, TmpTab)
+ end) of
+ {atomic, ok} ->
+ mnesia:delete_table(TmpTab);
+ Err ->
+ report_and_stop(Tab, Err)
+ end;
+ Err ->
+ report_and_stop(Tab, Err)
+ end;
+ Err ->
+ report_and_stop(Tab, Err)
+ end;
+ false ->
+ ok
+ end.
+
+is_table_still_list(Tab, DetectFun) ->
+ is_table_still_list(Tab, DetectFun, mnesia:dirty_first(Tab)).
+
+is_table_still_list(_Tab, _DetectFun, '$end_of_table') ->
+ false;
+is_table_still_list(Tab, DetectFun, Key) ->
+ Rs = mnesia:dirty_read(Tab, Key),
+ Res = lists:foldl(fun(_, true) ->
+ true;
+ (_, false) ->
+ false;
+ (R, _) ->
+ case DetectFun(R) of
+ '$next' ->
+ '$next';
+ El ->
+ is_list(El)
+ end
+ end, '$next', Rs),
+ case Res of
+ true ->
+ true;
+ false ->
+ false;
+ '$next' ->
+ is_table_still_list(Tab, DetectFun, mnesia:dirty_next(Tab, Key))
+ end.
+
+report_and_stop(Tab, Err) ->
+ ErrTxt = lists:flatten(
+ io_lib:format(
+ "Failed to convert '~s' table to binary: ~p",
+ [Tab, Err])),
+ ?CRITICAL_MSG(ErrTxt, []),
+ timer:sleep(1000),
+ halt(string:substr(ErrTxt, 1, 199)).
+
+emit_deprecation_warning(Module, NewModule, DBType) ->
+ ?WARNING_MSG("Module ~s is deprecated, use {~s, [{db_type, ~s}, ...]}"
+ " instead", [Module, NewModule, DBType]).
+
+emit_deprecation_warning(Module, NewModule) ->
+ ?WARNING_MSG("Module ~s is deprecated, use ~s instead",
+ [Module, NewModule]).