aboutsummaryrefslogtreecommitdiff
path: root/src/mod_vcard.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_vcard.erl')
-rw-r--r--src/mod_vcard.erl128
1 files changed, 69 insertions, 59 deletions
diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl
index 6b6f5f7d5..41f04940a 100644
--- a/src/mod_vcard.erl
+++ b/src/mod_vcard.erl
@@ -41,11 +41,13 @@
vcard_iq_set/1, mod_opt_type/1, set_vcard/3, make_vcard_search/4]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
+-export([route/1]).
-include("logger.hrl").
-include("xmpp.hrl").
-include("mod_vcard.hrl").
-include("translate.hrl").
+-include("ejabberd_stacktrace.hrl").
-define(VCARD_CACHE, vcard_cache).
@@ -82,7 +84,7 @@ stop(Host) ->
%%====================================================================
init([Host, Opts]) ->
process_flag(trap_exit, true),
- Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
+ Mod = gen_mod:db_mod(Opts, ?MODULE),
Mod:init(Host, Opts),
init_cache(Mod, Host, Opts),
ejabberd_hooks:add(remove_user, Host, ?MODULE,
@@ -94,8 +96,8 @@ init([Host, Opts]) ->
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),
- Search = gen_mod:get_opt(search, Opts),
+ MyHosts = gen_mod:get_opt_hosts(Opts),
+ Search = mod_vcard_opt:search(Opts),
if Search ->
lists:foreach(
fun(MyHost) ->
@@ -117,11 +119,12 @@ init([Host, Opts]) ->
process_local_iq_info),
case Mod:is_search_supported(Host) of
false ->
- ?WARNING_MSG("vcard search functionality is "
+ ?WARNING_MSG("vCard search functionality is "
"not implemented for ~s backend",
- [gen_mod:get_opt(db_type, Opts)]);
+ [mod_vcard_opt:db_type(Opts)]);
true ->
- ejabberd_router:register_route(MyHost, Host)
+ ejabberd_router:register_route(
+ MyHost, Host, {apply, ?MODULE, route})
end
end, MyHosts);
true ->
@@ -129,21 +132,25 @@ init([Host, Opts]) ->
end,
{ok, #state{hosts = MyHosts, server_host = Host}}.
-handle_call(_Call, _From, State) ->
+handle_call(Call, From, State) ->
+ ?WARNING_MSG("Unexpected call from ~p: ~p", [From, Call]),
{noreply, State}.
handle_cast(Cast, State) ->
- ?WARNING_MSG("unexpected cast: ~p", [Cast]),
+ ?WARNING_MSG("Unexpected cast: ~p", [Cast]),
{noreply, State}.
handle_info({route, Packet}, State) ->
- case catch do_route(Packet) of
- {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
- _ -> ok
+ try route(Packet)
+ catch ?EX_RULE(Class, Reason, St) ->
+ StackTrace = ?EX_STACK(St),
+ ?ERROR_MSG("Failed to route packet:~n~s~n** ~s",
+ [xmpp:pp(Packet),
+ misc:format_exception(2, Class, Reason, StackTrace)])
end,
{noreply, State};
handle_info(Info, State) ->
- ?WARNING_MSG("unexpected info: ~p", [Info]),
+ ?WARNING_MSG("Unexpected info: ~p", [Info]),
{noreply, State}.
terminate(_Reason, #state{hosts = MyHosts, server_host = Host}) ->
@@ -169,9 +176,10 @@ terminate(_Reason, #state{hosts = MyHosts, server_host = Host}) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
-do_route(#iq{} = IQ) ->
+-spec route(stanza()) -> ok.
+route(#iq{} = IQ) ->
ejabberd_router:process_iq(IQ);
-do_route(_) ->
+route(_) ->
ok.
-spec get_sm_features({error, stanza_error()} | empty | {result, [binary()]},
@@ -193,7 +201,7 @@ get_sm_features(Acc, _From, _To, Node, _Lang) ->
-spec process_local_iq(iq()) -> iq().
process_local_iq(#iq{type = set, lang = Lang} = IQ) ->
- Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+ Txt = ?T("Value 'set' of 'type' attribute is not allowed"),
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
process_local_iq(#iq{type = get, lang = Lang} = IQ) ->
xmpp:make_iq_result(
@@ -205,7 +213,7 @@ process_local_iq(#iq{type = get, lang = Lang} = IQ) ->
-spec process_sm_iq(iq()) -> iq().
process_sm_iq(#iq{type = set, lang = Lang, from = From} = IQ) ->
#jid{lserver = LServer} = From,
- case lists:member(LServer, ejabberd_config:get_myhosts()) of
+ case lists:member(LServer, ejabberd_option:hosts()) of
true ->
case ejabberd_hooks:run_fold(vcard_iq_set, LServer, IQ, []) of
drop -> ignore;
@@ -213,14 +221,14 @@ process_sm_iq(#iq{type = set, lang = Lang, from = From} = IQ) ->
_ -> xmpp:make_iq_result(IQ)
end;
false ->
- Txt = <<"The query is only allowed from local users">>,
+ Txt = ?T("The query is only allowed from local users"),
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang))
end;
process_sm_iq(#iq{type = get, from = From, to = To, lang = Lang} = IQ) ->
#jid{luser = LUser, lserver = LServer} = To,
case get_vcard(LUser, LServer) of
error ->
- Txt = <<"Database failure">>,
+ Txt = ?T("Database failure"),
xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang));
[] ->
xmpp:make_iq_result(IQ, #vcard_temp{});
@@ -230,7 +238,7 @@ process_sm_iq(#iq{type = get, from = From, to = To, lang = Lang} = IQ) ->
-spec process_vcard(iq()) -> iq().
process_vcard(#iq{type = set, lang = Lang} = IQ) ->
- Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+ Txt = ?T("Value 'set' of 'type' attribute is not allowed"),
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
process_vcard(#iq{type = get, lang = Lang} = IQ) ->
xmpp:make_iq_result(
@@ -249,7 +257,7 @@ process_search(#iq{type = set, to = To, lang = Lang,
ResultXData = search_result(Lang, To, ServerHost, Fs),
xmpp:make_iq_result(IQ, #search{xdata = ResultXData});
process_search(#iq{type = set, lang = Lang} = IQ) ->
- Txt = <<"Incorrect data form">>,
+ Txt = ?T("Incorrect data form"),
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang)).
-spec disco_items({error, stanza_error()} | {result, [disco_item()]} | empty,
@@ -258,7 +266,7 @@ process_search(#iq{type = set, lang = Lang} = IQ) ->
disco_items(empty, _From, _To, <<"">>, _Lang) ->
{result, []};
disco_items(empty, _From, _To, _Node, Lang) ->
- {error, xmpp:err_item_not_found(<<"No services available">>, Lang)};
+ {error, xmpp:err_item_not_found(?T("No services available"), Lang)};
disco_items(Acc, _From, _To, _Node, _Lang) ->
Acc.
@@ -275,7 +283,7 @@ disco_features(Acc, _From, _To, <<"">>, _Lang) ->
{result, [?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
?NS_VCARD, ?NS_SEARCH | Features]};
disco_features(empty, _From, _To, _Node, Lang) ->
- Txt = <<"No features available">>,
+ Txt = ?T("No features available"),
{error, xmpp:err_item_not_found(Txt, Lang)};
disco_features(Acc, _From, _To, _Node, _Lang) ->
Acc.
@@ -284,7 +292,7 @@ disco_features(Acc, _From, _To, _Node, _Lang) ->
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),
+ Name = mod_vcard_opt:name(Host),
[#identity{category = <<"directory">>,
type = <<"user">>,
name = translate:translate(Lang, Name)}|Acc];
@@ -380,7 +388,7 @@ vcard_iq_set(#iq{from = From, lang = Lang, sub_els = [VCard]} = IQ) ->
case set_vcard(User, LServer, VCard) of
{error, badarg} ->
%% Should not be here?
- Txt = <<"Nodeprep has failed">>,
+ Txt = ?T("Nodeprep has failed"),
{stop, xmpp:err_internal_server_error(Txt, Lang)};
ok ->
IQ
@@ -422,7 +430,7 @@ mk_field(Var, Val) ->
-spec mk_search_form(jid(), binary(), binary()) -> search().
mk_search_form(JID, ServerHost, Lang) ->
- Title = <<(translate:translate(Lang, <<"Search users in ">>))/binary,
+ Title = <<(translate:translate(Lang, ?T("Search users in ")))/binary,
(jid:encode(JID))/binary>>,
Mod = gen_mod:db_mod(ServerHost, ?MODULE),
SearchFields = Mod:search_fields(ServerHost),
@@ -433,17 +441,18 @@ mk_search_form(JID, ServerHost, Lang) ->
fields = Fs},
#search{instructions =
translate:translate(
- Lang, <<"You need an x:data capable client to search">>),
+ Lang, ?T("You need an x:data capable client to search")),
xdata = X}.
+-spec make_instructions(module(), binary()) -> binary().
make_instructions(Mod, Lang) ->
Fill = translate:translate(
Lang,
- <<"Fill in the form to search for any matching "
- "Jabber User">>),
+ ?T("Fill in the form to search for any matching "
+ "Jabber User")),
Add = translate:translate(
Lang,
- <<" (Add * to the end of field to match substring)">>),
+ ?T(" (Add * to the end of field to match substring)")),
case Mod of
mod_vcard_mnesia -> Fill;
_ -> str:concat(Fill, Add)
@@ -456,7 +465,7 @@ search_result(Lang, JID, ServerHost, XFields) ->
{Label, Var} <- Mod:search_reported(ServerHost)],
#xdata{type = result,
title = <<(translate:translate(Lang,
- <<"Search Results for ">>))/binary,
+ ?T("Search Results for ")))/binary,
(jid:encode(JID))/binary>>,
reported = Reported,
items = lists:map(fun (Item) -> item_to_field(Item) end,
@@ -470,8 +479,8 @@ item_to_field(Items) ->
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),
- MaxMatch = gen_mod:get_module_opt(LServer, ?MODULE, matches),
+ AllowReturnAll = mod_vcard_opt:allow_return_all(LServer),
+ MaxMatch = mod_vcard_opt:matches(LServer),
Mod:search(LServer, Data, AllowReturnAll, MaxMatch).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -495,19 +504,16 @@ init_cache(Mod, Host, Opts) ->
-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()].
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,
+ MaxSize = mod_vcard_opt:cache_size(Opts),
+ CacheMissed = mod_vcard_opt:cache_missed(Opts),
+ LifeTime = mod_vcard_opt:cache_life_time(Opts),
[{max_size, MaxSize}, {cache_missed, CacheMissed}, {life_time, LifeTime}].
-spec use_cache(module(), binary()) -> boolean().
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)
+ false -> mod_vcard_opt:use_cache(Host)
end.
-spec cache_nodes(module(), binary()) -> [node()].
@@ -536,33 +542,37 @@ depends(_Host, _Opts) ->
[].
mod_opt_type(allow_return_all) ->
- 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(name) -> fun iolist_to_binary/1;
-mod_opt_type(host) -> fun ejabberd_config:v_host/1;
-mod_opt_type(hosts) -> fun ejabberd_config:v_hosts/1;
+ econf:bool();
+mod_opt_type(name) ->
+ econf:binary();
mod_opt_type(matches) ->
- fun (infinity) -> infinity;
- (I) when is_integer(I), I > 0 -> I
- end;
+ econf:pos_int(infinity);
mod_opt_type(search) ->
- 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.
+ econf:bool();
+mod_opt_type(host) ->
+ econf:host();
+mod_opt_type(hosts) ->
+ econf:hosts();
+mod_opt_type(db_type) ->
+ econf:db_type(?MODULE);
+mod_opt_type(use_cache) ->
+ econf:bool();
+mod_opt_type(cache_size) ->
+ econf:pos_int(infinity);
+mod_opt_type(cache_missed) ->
+ econf:bool();
+mod_opt_type(cache_life_time) ->
+ econf:timeout(second, infinity).
mod_options(Host) ->
[{allow_return_all, false},
- {host, <<"vjud.@HOST@">>},
+ {host, <<"vjud.", Host/binary>>},
{hosts, []},
{matches, 30},
{search, false},
{name, ?T("vCard User Search")},
{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, ejabberd_option:use_cache(Host)},
+ {cache_size, ejabberd_option:cache_size(Host)},
+ {cache_missed, ejabberd_option:cache_missed(Host)},
+ {cache_life_time, ejabberd_option:cache_life_time(Host)}].