From 722864666d32edab031fbe161e178173e3b48a8e Mon Sep 17 00:00:00 2001 From: Evgeny Khramtsov Date: Wed, 10 Jul 2019 10:31:51 +0300 Subject: [PATCH] Add/improve type specs --- src/ejabberd_captcha.erl | 10 +++-- src/mod_avatar.erl | 1 + src/mod_block_strangers.erl | 9 +++++ src/mod_blocking.erl | 1 + src/mod_caps.erl | 17 +++++---- src/mod_configure.erl | 74 ++++++++++++++++++++++++++----------- src/mod_delegation.erl | 25 ++++++------- src/mod_fail2ban.erl | 3 ++ src/mod_last.erl | 3 ++ src/mod_time.erl | 1 + src/mod_vcard.erl | 4 +- 11 files changed, 101 insertions(+), 47 deletions(-) diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index cd07709ab..02cf2659a 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -52,6 +52,7 @@ -type image_error() :: efbig | enodata | limit | malformed_image | timeout. -type priority() :: neg_integer(). +-type callback() :: fun((captcha_succeed | captcha_failed) -> any()). -record(state, {limits = treap:empty() :: treap:treap(), enabled = false :: boolean()}). @@ -84,8 +85,9 @@ mk_field(Type, Var, Value) -> #xdata_field{type = Type, var = Var, values = [Value]}. -spec create_captcha(binary(), jid(), jid(), - binary(), any(), any()) -> {error, image_error()} | - {ok, binary(), [text()], [xmpp_element()]}. + binary(), any(), + callback() | term()) -> {error, image_error()} | + {ok, binary(), [text()], [xmpp_element()]}. create_captcha(SID, From, To, Lang, Limiter, Args) -> case create_image(Limiter) of {ok, Type, Key, Image} -> @@ -607,7 +609,9 @@ clean_treap(Treap, CleanPriority) -> end end. --spec callback(captcha_succeed | captcha_failed, pid(), term()) -> any(). +-spec callback(captcha_succeed | captcha_failed, + pid() | undefined, + callback() | term()) -> any(). callback(Result, _Pid, F) when is_function(F) -> F(Result); callback(Result, Pid, Args) when is_pid(Pid) -> diff --git a/src/mod_avatar.erl b/src/mod_avatar.erl index 73b89af62..8edcf3237 100644 --- a/src/mod_avatar.erl +++ b/src/mod_avatar.erl @@ -68,6 +68,7 @@ depends(_Host, _Opts) -> %%%=================================================================== %%% Hooks %%%=================================================================== +-spec pubsub_publish_item(binary(), binary(), jid(), jid(), binary(), [xmlel()]) -> ok. pubsub_publish_item(LServer, ?NS_AVATAR_METADATA, #jid{luser = LUser, lserver = LServer} = From, #jid{luser = LUser, lserver = LServer} = Host, diff --git a/src/mod_block_strangers.erl b/src/mod_block_strangers.erl index 5f59978a3..0fc83eab6 100644 --- a/src/mod_block_strangers.erl +++ b/src/mod_block_strangers.erl @@ -40,6 +40,8 @@ -define(SETS, gb_sets). +-type c2s_state() :: ejabberd_c2s:state(). + %%%=================================================================== %%% Callbacks and hooks %%%=================================================================== @@ -62,6 +64,8 @@ stop(Host) -> reload(_Host, _NewOpts, _OldOpts) -> ok. +-spec filter_packet({stanza(), c2s_state()}) -> {stanza(), c2s_state()} | + {stop, {drop, c2s_state()}}. filter_packet({#message{from = From} = Msg, State} = Acc) -> LFrom = jid:tolower(From), LBFrom = jid:remove_resource(LFrom), @@ -80,12 +84,14 @@ filter_packet({#message{from = From} = Msg, State} = Acc) -> filter_packet(Acc) -> Acc. +-spec filter_offline_msg({_, message()}) -> {_, message()} | {stop, {drop, message()}}. filter_offline_msg({_Action, #message{} = Msg} = Acc) -> case check_message(Msg) of allow -> Acc; deny -> {stop, {drop, Msg}} end. +-spec filter_subscription(boolean(), presence()) -> boolean() | {stop, false}. filter_subscription(Acc, #presence{meta = #{captcha := passed}}) -> Acc; filter_subscription(Acc, #presence{from = From, to = To, lang = Lang, @@ -136,6 +142,7 @@ filter_subscription(Acc, #presence{from = From, to = To, lang = Lang, filter_subscription(Acc, _) -> Acc. +-spec handle_captcha_result(captcha_succeed | captcha_failed, presence()) -> ok. handle_captcha_result(captcha_succeed, Pres) -> Pres1 = xmpp:put_meta(Pres, captcha, passed), ejabberd_router:route(Pres1); @@ -146,6 +153,7 @@ handle_captcha_result(captcha_failed, #presence{lang = Lang} = Pres) -> %%%=================================================================== %%% Internal functions %%%=================================================================== +-spec check_message(message()) -> allow | deny. check_message(#message{from = From, to = To, lang = Lang} = Msg) -> LServer = To#jid.lserver, case need_check(Msg) of @@ -222,6 +230,7 @@ check_subscription(From, To) -> true end. +-spec sets_bare_member(ljid(), ?SETS:set()) -> boolean(). sets_bare_member({U, S, <<"">>} = LBJID, Set) -> case ?SETS:next(?SETS:iterator_from(LBJID, Set)) of {{U, S, _}, _} -> true; diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 233ce95ae..64687bb3a 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -258,6 +258,7 @@ process_get(#iq{from = #jid{luser = LUser, lserver = LServer}} = IQ) -> err_db_failure(IQ) end. +-spec err_db_failure(iq()) -> iq(). err_db_failure(#iq{lang = Lang} = IQ) -> Txt = ?T("Database failure"), xmpp:make_error(IQ, xmpp:err_internal_server_error(Txt, Lang)). diff --git a/src/mod_caps.erl b/src/mod_caps.erl index f1fc0e8f6..ca1269194 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -60,6 +60,8 @@ -record(state, {host = <<"">> :: binary()}). +-type digest_type() :: md5 | sha | sha224 | sha256 | sha384 | sha512. + -callback init(binary(), gen_mod:opts()) -> any(). -callback import(binary(), {binary(), binary()}, [binary() | pos_integer()]) -> ok. -callback caps_read(binary(), {binary(), binary()}) -> @@ -416,19 +418,18 @@ make_my_disco_hash(Host) -> _Err -> <<"">> end. --type digest_type() :: md5 | sha | sha224 | sha256 | sha384 | sha512. -spec compute_disco_hash(disco_info(), digest_type()) -> binary(). compute_disco_hash(DiscoInfo, Algo) -> Concat = list_to_binary([concat_identities(DiscoInfo), concat_features(DiscoInfo), concat_info(DiscoInfo)]), base64:encode(case Algo of - md5 -> erlang:md5(Concat); - sha -> crypto:hash(sha, Concat); - sha224 -> crypto:hash(sha224, Concat); - sha256 -> crypto:hash(sha256, Concat); - sha384 -> crypto:hash(sha384, Concat); - sha512 -> crypto:hash(sha512, Concat) - end). + md5 -> erlang:md5(Concat); + sha -> crypto:hash(sha, Concat); + sha224 -> crypto:hash(sha224, Concat); + sha256 -> crypto:hash(sha256, Concat); + sha384 -> crypto:hash(sha384, Concat); + sha512 -> crypto:hash(sha512, Concat) + end). -spec check_hash(caps(), disco_info()) -> boolean(). check_hash(Caps, DiscoInfo) -> diff --git a/src/mod_configure.erl b/src/mod_configure.erl index ebdfadeeb..3c3381d7b 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -119,8 +119,10 @@ depends(_Host, _Opts) -> [<<"http:">>, <<"jabber.org">>, <<"protocol">>, <<"admin">>, Sub]). +-spec tokenize(binary()) -> [binary()]. tokenize(Node) -> str:tokens(Node, <<"/#">>). +-spec get_sm_identity([identity()], jid(), jid(), binary(), binary()) -> [identity()]. get_sm_identity(Acc, _From, _To, Node, Lang) -> case Node of <<"config">> -> @@ -128,6 +130,7 @@ get_sm_identity(Acc, _From, _To, Node, Lang) -> _ -> Acc end. +-spec get_local_identity([identity()], jid(), jid(), binary(), binary()) -> [identity()]. get_local_identity(Acc, _From, _To, Node, Lang) -> LNode = tokenize(Node), case LNode of @@ -190,6 +193,8 @@ get_local_identity(Acc, _From, _To, Node, Lang) -> allow -> {result, Feats} end). +-spec get_sm_features(mod_disco:features_acc(), jid(), jid(), + binary(), binary()) -> mod_disco:features_acc(). get_sm_features(Acc, From, #jid{lserver = LServer} = _To, Node, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of @@ -202,6 +207,8 @@ get_sm_features(Acc, From, end end. +-spec get_local_features(mod_disco:features_acc(), jid(), jid(), + binary(), binary()) -> mod_disco:features_acc(). get_local_features(Acc, From, #jid{lserver = LServer} = _To, Node, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of @@ -264,10 +271,8 @@ get_local_features(Acc, From, end. %%%----------------------------------------------------------------------- --spec adhoc_sm_items(empty | {error, stanza_error()} | {result, [disco_item()]}, - jid(), jid(), binary()) -> {error, stanza_error()} | - {result, [disco_item()]} | - empty. +-spec adhoc_sm_items(mod_disco:items_acc(), + jid(), jid(), binary()) -> mod_disco:items_acc(). adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To, Lang) -> case acl:match_rule(LServer, configure, From) of @@ -283,7 +288,8 @@ adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To, end. %%%----------------------------------------------------------------------- - +-spec get_sm_items(mod_disco:items_acc(), jid(), jid(), + binary(), binary()) -> mod_disco:items_acc(). get_sm_items(Acc, From, #jid{user = User, server = Server, lserver = LServer} = To, @@ -309,6 +315,7 @@ get_sm_items(Acc, From, end end. +-spec get_user_resources(binary(), binary()) -> [disco_item()]. get_user_resources(User, Server) -> Rs = ejabberd_sm:get_user_resources(User, Server), lists:map(fun (R) -> @@ -319,10 +326,8 @@ get_user_resources(User, Server) -> %%%----------------------------------------------------------------------- --spec adhoc_local_items(empty | {error, stanza_error()} | {result, [disco_item()]}, - jid(), jid(), binary()) -> {error, stanza_error()} | - {result, [disco_item()]} | - empty. +-spec adhoc_local_items(mod_disco:items_acc(), + jid(), jid(), binary()) -> mod_disco:items_acc(). adhoc_local_items(Acc, From, #jid{lserver = LServer, server = Server} = To, Lang) -> case acl:match_rule(LServer, configure, From) of @@ -336,7 +341,7 @@ adhoc_local_items(Acc, From, <<"">>, Server, Lang), Nodes1 = lists:filter( fun (#disco_item{node = Nd}) -> - F = get_local_features([], From, To, Nd, Lang), + F = get_local_features(empty, From, To, Nd, Lang), case F of {result, [?NS_COMMANDS]} -> true; _ -> false @@ -347,6 +352,8 @@ adhoc_local_items(Acc, From, _ -> Acc end. +-spec recursively_get_local_items(global | vhost, binary(), binary(), + binary(), binary()) -> [disco_item()]. recursively_get_local_items(_PermLev, _LServer, <<"online users">>, _Server, _Lang) -> []; @@ -376,6 +383,7 @@ recursively_get_local_items(PermLev, LServer, Node, end, Items)). +-spec get_permission_level(jid()) -> global | vhost. get_permission_level(JID) -> case acl:match_rule(global, configure, JID) of allow -> global; @@ -397,6 +405,8 @@ get_permission_level(JID) -> end end). +-spec get_local_items(mod_disco:items_acc(), jid(), jid(), + binary(), binary()) -> mod_disco:items_acc(). get_local_items(Acc, From, #jid{lserver = LServer} = To, <<"">>, Lang) -> case gen_mod:is_loaded(LServer, mod_adhoc) of @@ -489,10 +499,8 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To, end. %%%----------------------------------------------------------------------- - -%% @spec ({PermissionLevel, Host}, [string()], Server::string(), Lang) -%% -> {result, [xmlelement()]} -%% PermissionLevel = global | vhost +-spec get_local_items({global | vhost, binary()}, [binary()], + binary(), binary()) -> {result, [disco_item()]} | {error, stanza_error()}. get_local_items(_Host, [], Server, Lang) -> {result, [?NODE(?T("Configuration"), <<"config">>), @@ -550,7 +558,7 @@ get_local_items({_, Host}, name = <>} end, Sub)} catch _:_ -> - xmpp:err_not_acceptable() + {error, xmpp:err_not_acceptable()} end; get_local_items({_, Host}, [<<"outgoing s2s">>], _Server, Lang) -> @@ -638,6 +646,7 @@ get_local_items(_Host, get_local_items(_Host, _, _Server, _Lang) -> {error, xmpp:err_item_not_found()}. +-spec get_online_vh_users(binary()) -> [disco_item()]. get_online_vh_users(Host) -> case catch ejabberd_sm:get_vh_session_list(Host) of {'EXIT', _Reason} -> []; @@ -650,6 +659,7 @@ get_online_vh_users(Host) -> end, SURs) end. +-spec get_all_vh_users(binary()) -> [disco_item()]. get_all_vh_users(Host) -> case catch ejabberd_auth:get_users(Host) of @@ -686,6 +696,7 @@ get_all_vh_users(Host) -> end end. +-spec get_outgoing_s2s(binary(), binary()) -> [disco_item()]. get_outgoing_s2s(Host, Lang) -> case catch ejabberd_s2s:dirty_get_connections() of {'EXIT', _Reason} -> []; @@ -703,6 +714,7 @@ get_outgoing_s2s(Host, Lang) -> end, lists:usort(TConns)) end. +-spec get_outgoing_s2s(binary(), binary(), binary()) -> [disco_item()]. get_outgoing_s2s(Host, Lang, To) -> case catch ejabberd_s2s:dirty_get_connections() of {'EXIT', _Reason} -> []; @@ -719,6 +731,7 @@ get_outgoing_s2s(Host, Lang, To) -> Connections))) end. +-spec get_running_nodes(binary(), binary()) -> [disco_item()]. get_running_nodes(Server, _Lang) -> case catch mnesia:system_info(running_db_nodes) of {'EXIT', _Reason} -> []; @@ -733,6 +746,7 @@ get_running_nodes(Server, _Lang) -> lists:sort(DBNodes)) end. +-spec get_stopped_nodes(binary()) -> [disco_item()]. get_stopped_nodes(_Lang) -> case catch lists:usort(mnesia:system_info(db_nodes) ++ mnesia:system_info(extra_db_nodes)) @@ -785,6 +799,7 @@ adhoc_local_commands(Acc, From, _ -> Acc end. +-spec adhoc_local_commands(jid(), jid(), adhoc_command()) -> adhoc_command() | {error, stanza_error()}. adhoc_local_commands(From, #jid{lserver = LServer} = _To, #adhoc_command{lang = Lang, node = Node, @@ -852,6 +867,9 @@ adhoc_local_commands(From, #xdata_option{label = tr(Lang, ?T("Remote copy")), value = <<"unknown">>}]}). +-spec get_form(binary(), [binary()], binary()) -> {result, xdata()} | + {result, completed, xdata()} | + {error, stanza_error()}. get_form(_Host, [<<"running nodes">>, ENode, <<"DB">>], Lang) -> case search_running_node(ENode) of @@ -1169,6 +1187,8 @@ get_form(Host, ?NS_ADMINL(<<"get-online-users-num">>), get_form(_Host, _, _Lang) -> {error, xmpp:err_service_unavailable()}. +-spec set_form(jid(), binary(), [binary()], binary(), xdata()) -> {result, xdata() | undefined} | + {error, stanza_error()}. set_form(_From, _Host, [<<"running nodes">>, ENode, <<"DB">>], Lang, XData) -> case search_running_node(ENode) of @@ -1543,22 +1563,28 @@ set_form(From, Host, ?NS_ADMINL(<<"user-stats">>), Lang, set_form(_From, _Host, _, _Lang, _XData) -> {error, xmpp:err_service_unavailable()}. -get_value(Field, XData) -> hd(get_values(Field, XData)). +-spec get_value(binary(), xdata()) -> binary(). +get_value(Field, XData) -> + hd(get_values(Field, XData)). +-spec get_values(binary(), xdata()) -> [binary()]. get_values(Field, XData) -> xmpp_util:get_xdata_values(Field, XData). +-spec search_running_node(binary()) -> false | node(). search_running_node(SNode) -> search_running_node(SNode, mnesia:system_info(running_db_nodes)). +-spec search_running_node(binary(), [node()]) -> false | node(). search_running_node(_, []) -> false; search_running_node(SNode, [Node | Nodes]) -> - case iolist_to_binary(atom_to_list(Node)) of - SNode -> Node; - _ -> search_running_node(SNode, Nodes) + case atom_to_binary(Node, utf8) of + SNode -> Node; + _ -> search_running_node(SNode, Nodes) end. +-spec stop_node(jid(), binary(), binary(), restart | stop, xdata()) -> {result, undefined}. stop_node(From, Host, ENode, Action, XData) -> Delay = binary_to_integer(get_value(<<"delay">>, XData)), Subject = case get_value(<<"subject">>, XData) of @@ -1586,9 +1612,10 @@ stop_node(From, Host, ENode, Action, XData) -> end, Time = timer:seconds(Delay), Node = misc:binary_to_atom(ENode), - {ok, _} = timer:apply_after(Time, rpc, call, [Node, init, Action, []]), + {ok, _} = timer:apply_after(Time, ejabberd_cluster, call, [Node, init, Action, []]), {result, undefined}. +-spec get_last_info(binary(), binary()) -> {ok, non_neg_integer(), binary()} | not_found. get_last_info(User, Server) -> case gen_mod:is_loaded(Server, mod_last) of true -> mod_last:get_last_info(User, Server); @@ -1596,7 +1623,8 @@ get_last_info(User, Server) -> end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec adhoc_sm_commands(adhoc_command(), jid(), jid(), adhoc_command()) -> adhoc_command(). +-spec adhoc_sm_commands(adhoc_command(), jid(), jid(), adhoc_command()) -> adhoc_command() | + {error, stanza_error()}. adhoc_sm_commands(_Acc, From, #jid{user = User, server = Server, lserver = LServer}, #adhoc_command{lang = Lang, node = <<"config">>, @@ -1627,6 +1655,8 @@ adhoc_sm_commands(_Acc, From, end; adhoc_sm_commands(Acc, _From, _To, _Request) -> Acc. +-spec get_sm_form(binary(), binary(), binary(), binary()) -> {result, xdata()} | + {error, stanza_error()}. get_sm_form(User, Server, <<"config">>, Lang) -> {result, #xdata{type = form, @@ -1650,6 +1680,8 @@ get_sm_form(User, Server, <<"config">>, Lang) -> get_sm_form(_User, _Server, _Node, _Lang) -> {error, xmpp:err_service_unavailable()}. +-spec set_sm_form(binary(), binary(), binary(), adhoc_command()) -> adhoc_command() | + {error, stanza_error()}. set_sm_form(User, Server, <<"config">>, #adhoc_command{lang = Lang, node = Node, sid = SessionID, xdata = XData}) -> diff --git a/src/mod_delegation.erl b/src/mod_delegation.erl index c49f973ac..8dbc903ee 100644 --- a/src/mod_delegation.erl +++ b/src/mod_delegation.erl @@ -44,7 +44,6 @@ -include("xmpp.hrl"). -include("translate.hrl"). --type disco_acc() :: {error, stanza_error()} | {result, [binary()]} | empty. -type route_type() :: ejabberd_sm | ejabberd_local. -type delegations() :: #{{binary(), route_type()} => {binary(), disco_info()}}. -record(state, {server_host = <<"">> :: binary()}). @@ -115,19 +114,21 @@ ejabberd_local(IQ) -> ejabberd_sm(IQ) -> process_iq(IQ, ejabberd_sm). --spec disco_local_features(disco_acc(), jid(), jid(), binary(), binary()) -> disco_acc(). +-spec disco_local_features(mod_disco:features_acc(), jid(), jid(), + binary(), binary()) -> mod_disco:features_acc(). disco_local_features(Acc, From, To, Node, Lang) -> disco_features(Acc, From, To, Node, Lang, ejabberd_local). --spec disco_sm_features(disco_acc(), jid(), jid(), binary(), binary()) -> disco_acc(). +-spec disco_sm_features(mod_disco:features_acc(), jid(), jid(), + binary(), binary()) -> mod_disco:features_acc(). disco_sm_features(Acc, From, To, Node, Lang) -> disco_features(Acc, From, To, Node, Lang, ejabberd_sm). --spec disco_local_identity(disco_acc(), jid(), jid(), binary(), binary()) -> disco_acc(). +-spec disco_local_identity([identity()], jid(), jid(), binary(), binary()) -> [identity()]. disco_local_identity(Acc, From, To, Node, Lang) -> disco_identity(Acc, From, To, Node, Lang, ejabberd_local). --spec disco_sm_identity(disco_acc(), jid(), jid(), binary(), binary()) -> disco_acc(). +-spec disco_sm_identity([identity()], jid(), jid(), binary(), binary()) -> [identity()]. disco_sm_identity(Acc, From, To, Node, Lang) -> disco_identity(Acc, From, To, Node, Lang, ejabberd_sm). @@ -335,8 +336,8 @@ send_disco_queries(LServer, Host, NS) -> end, [{ejabberd_local, <<(?NS_DELEGATION)/binary, "::", NS/binary>>}, {ejabberd_sm, <<(?NS_DELEGATION)/binary, ":bare:", NS/binary>>}]). --spec disco_features(disco_acc(), jid(), jid(), binary(), binary(), - route_type()) -> disco_acc(). +-spec disco_features(mod_disco:features_acc(), jid(), jid(), binary(), binary(), + route_type()) -> mod_disco:features_acc(). disco_features(Acc, _From, To, <<"">>, _Lang, Type) -> Delegations = get_delegations(To#jid.lserver), Features = my_features(Type) ++ @@ -354,8 +355,8 @@ disco_features(Acc, _From, To, <<"">>, _Lang, Type) -> disco_features(Acc, _, _, _, _, _) -> Acc. --spec disco_identity(disco_acc(), jid(), jid(), binary(), binary(), - route_type()) -> disco_acc(). +-spec disco_identity([identity()], jid(), jid(), binary(), binary(), + route_type()) -> [identity()]. disco_identity(Acc, _From, To, <<"">>, _Lang, Type) -> Delegations = get_delegations(To#jid.lserver), Identities = lists:flatmap( @@ -364,11 +365,7 @@ disco_identity(Acc, _From, To, <<"">>, _Lang, Type) -> (_) -> [] end, maps:to_list(Delegations)), - case Acc of - empty when Identities /= [] -> {result, Identities}; - {result, Ids} -> {result, Ids ++ Identities}; - Acc -> Acc - end; + Acc ++ Identities; disco_identity(Acc, _From, _To, _Node, _Lang, _Type) -> Acc. diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index eeb9186a6..770393914 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -225,13 +225,16 @@ log_and_disconnect(#{ip := {Addr, _}, lang := Lang} = State, Attempts, UnbanTS) Err = xmpp:serr_policy_violation({Format, Args}, Lang), {stop, ejabberd_c2s:send(State, Err)}. +-spec is_whitelisted(binary(), inet:ip_address()) -> boolean(). is_whitelisted(Host, Addr) -> Access = mod_fail2ban_opt:access(Host), acl:match_rule(Host, Access, Addr) == allow. +-spec seconds_to_now(non_neg_integer()) -> erlang:timestamp(). seconds_to_now(Secs) -> {Secs div 1000000, Secs rem 1000000, 0}. +-spec format_date(calendar:datetime()) -> iolist(). format_date({{Year, Month, Day}, {Hour, Minute, Second}}) -> io_lib:format("~2..0w:~2..0w:~2..0w ~2..0w.~2..0w.~4..0w", [Hour, Minute, Second, Day, Month, Year]). diff --git a/src/mod_last.erl b/src/mod_last.erl index ec08a6449..28b66be08 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -45,6 +45,8 @@ -define(LAST_CACHE, last_activity_cache). +-type c2s_state() :: ejabberd_c2s:state(). + -callback init(binary(), gen_mod:opts()) -> any(). -callback import(binary(), #last_activity{}) -> ok | pass. -callback get_last(binary(), binary()) -> @@ -144,6 +146,7 @@ process_sm_iq(#iq{from = From, to = To, lang = Lang} = IQ) -> xmpp:make_error(IQ, xmpp:err_subscription_required(Txt, Lang)) end. +-spec privacy_check_packet(allow | deny, c2s_state(), stanza(), in | out) -> allow | deny | {stop, deny}. privacy_check_packet(allow, C2SState, #iq{from = From, to = To, type = T} = IQ, in) when T == get; T == set -> diff --git a/src/mod_time.erl b/src/mod_time.erl index 1355ba46c..53f2e5432 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -50,6 +50,7 @@ stop(Host) -> reload(_Host, _NewOpts, _OldOpts) -> ok. +-spec process_local_iq(iq()) -> iq(). process_local_iq(#iq{type = set, lang = Lang} = IQ) -> Txt = ?T("Value 'set' of 'type' attribute is not allowed"), xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)); diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index b7be42a13..41f04940a 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -132,7 +132,8 @@ 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) -> @@ -443,6 +444,7 @@ mk_search_form(JID, ServerHost, Lang) -> 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,