From 522a186a3822a3fdb04a423b2238aab2fcfb4b1c Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 9 Aug 2016 10:56:32 +0300 Subject: [PATCH] Improve some type specs --- include/ejabberd.hrl | 2 +- include/xmpp_codec.hrl | 10 +-- src/ejabberd_auth_anonymous.erl | 2 + src/ejabberd_c2s.erl | 98 ++++++++++++++++------ src/ejabberd_config.erl | 2 +- src/ejabberd_local.erl | 5 +- src/ejabberd_router_multicast.erl | 2 +- src/ejabberd_s2s_in.erl | 31 +++---- src/ejabberd_s2s_out.erl | 8 +- src/ejabberd_service.erl | 2 +- src/ejabberd_sm.erl | 8 +- src/ejabberd_socket.erl | 2 +- src/ejabberd_system_monitor.erl | 3 +- src/ejabberd_web_admin.erl | 35 ++++---- src/gen_iq_handler.erl | 1 + src/gen_mod.erl | 2 +- src/mod_adhoc.erl | 24 ++++-- src/mod_announce.erl | 43 +++++----- src/mod_blocking.erl | 7 +- src/mod_caps.erl | 28 +++++-- src/mod_carboncopy.erl | 2 +- src/mod_client_state.erl | 26 +++--- src/mod_configure.erl | 16 +++- src/mod_disco.erl | 5 +- src/mod_fail2ban.erl | 8 +- src/mod_http_upload.erl | 9 +- src/mod_ip_blacklist.erl | 4 + src/mod_irc.erl | 6 +- src/mod_irc_connection.erl | 18 ++-- src/mod_mam.erl | 12 +-- src/mod_metrics.erl | 41 +++++++--- src/mod_mix.erl | 4 + src/mod_muc_room.erl | 132 ++++++++++++++++-------------- src/mod_offline.erl | 7 +- src/mod_ping.erl | 4 +- src/mod_privacy.erl | 1 + src/mod_private.erl | 1 + src/mod_pubsub.erl | 16 +++- src/mod_register.erl | 4 + src/mod_roster.erl | 7 +- src/mod_shared_roster.erl | 10 ++- src/mod_shared_roster_ldap.erl | 3 + src/mod_vcard_xupdate.erl | 3 +- src/node_online.erl | 1 + src/xmpp.erl | 2 +- src/xmpp_codec.erl | 22 +++-- tools/xmpp_codec.spec | 19 +++-- 47 files changed, 437 insertions(+), 261 deletions(-) diff --git a/include/ejabberd.hrl b/include/ejabberd.hrl index a97474d2b..7a6df5644 100644 --- a/include/ejabberd.hrl +++ b/include/ejabberd.hrl @@ -64,7 +64,7 @@ -define(TDICT, dict:dict()). -define(TGB_TREE, gb_trees:tree()). --define(TGB_SET, gb_set:set()). +-define(TGB_SET, gb_sets:set()). -define(TQUEUE, queue:queue()). -endif. diff --git a/include/xmpp_codec.hrl b/include/xmpp_codec.hrl index 935607de9..3424ec3b9 100644 --- a/include/xmpp_codec.hrl +++ b/include/xmpp_codec.hrl @@ -178,8 +178,8 @@ -record(private, {xml_els = [] :: [fxml:xmlel()]}). -type private() :: #private{}. --record(db_verify, {from :: jid:jid(), - to :: jid:jid(), +-record(db_verify, {from = <<>> :: binary(), + to = <<>> :: binary(), id = <<>> :: binary(), type :: 'error' | 'invalid' | 'valid', key = <<>> :: binary(), @@ -361,7 +361,7 @@ -record(caps, {node = <<>> :: binary(), version = <<>> :: binary(), hash = <<>> :: binary(), - exts = [] :: binary() | []}). + exts = [] :: [binary()]}). -type caps() :: #caps{}. -record(muc, {history :: #muc_history{}, @@ -428,8 +428,8 @@ userid :: binary()}). -type vcard_email() :: #vcard_email{}. --record(db_result, {from :: jid:jid(), - to :: jid:jid(), +-record(db_result, {from = <<>> :: binary(), + to = <<>> :: binary(), type :: 'error' | 'invalid' | 'valid', key = <<>> :: binary(), sub_els = [] :: [xmpp_element() | fxml:xmlel()]}). diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index c0ad1fb21..c84321ad9 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -139,6 +139,7 @@ remove_connection(SID, LUser, LServer) -> mnesia:transaction(F). %% Register connection +-spec register_connection(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> ok. register_connection(SID, #jid{luser = LUser, lserver = LServer}, Info) -> AuthModule = proplists:get_value(auth_module, Info, undefined), @@ -155,6 +156,7 @@ register_connection(SID, end. %% Remove an anonymous user from the anonymous users table +-spec unregister_connection(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> any(). unregister_connection(SID, #jid{luser = LUser, lserver = LServer}, _) -> purge_hook(anonymous_user_exist(LUser, LServer), LUser, diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index b13e7fe00..9c1d99091 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -125,6 +125,7 @@ -type state() :: #state{}. -type fsm_stop() :: {stop, normal, state()}. -type fsm_next() :: {next_state, state_name(), state(), non_neg_integer()}. +-type fsm_reply() :: {reply, any(), state_name(), state(), non_neg_integer()}. -type fsm_transition() :: fsm_stop() | fsm_next(). -export_type([state/0]). @@ -184,9 +185,9 @@ get_presence(FsmRef) -> -spec get_aux_field(any(), state()) -> {ok, any()} | error. get_aux_field(Key, #state{aux_fields = Opts}) -> - case lists:keysearch(Key, 1, Opts) of - {value, {_, Val}} -> {ok, Val}; - _ -> error + case lists:keyfind(Key, 1, Opts) of + {_, Val} -> {ok, Val}; + false -> error end. -spec set_aux_field(any(), any(), state()) -> state(). @@ -525,7 +526,7 @@ wait_for_auth(#iq{type = get, Auth = #legacy_auth{username = Username, password = <<>>, resource = <<>>}, Res = case ejabberd_auth:plain_password_required(StateData#state.server) of false -> - xmpp:make_iq_result(IQ, Auth#legacy_auth{digest = none}); + xmpp:make_iq_result(IQ, Auth#legacy_auth{digest = <<>>}); true -> xmpp:make_iq_result(IQ, Auth) end, @@ -1067,7 +1068,6 @@ session_established2(Pkt, StateData) -> J -> J end, Lang = case xmpp:get_lang(Pkt) of - undefined -> StateData#state.lang; <<"">> -> StateData#state.lang; L -> L end, @@ -1252,7 +1252,7 @@ handle_info({route, From, To, Packet}, StateName, StateData) when ?is_stanza(Pac process_presence_probe(From, To, NewStateData), {false, NewStateData}; error -> - NewA = remove_element(jid:tolower(From), State#state.pres_a), + NewA = ?SETS:del_element(jid:tolower(From), State#state.pres_a), {true, State#state{pres_a = NewA}}; subscribe -> SRes = is_privacy_allow(State, From, To, Packet, in), @@ -1666,6 +1666,7 @@ get_conn_type(StateData) -> websocket -> websocket end. +-spec process_presence_probe(jid(), jid(), state()) -> ok. process_presence_probe(From, To, StateData) -> LFrom = jid:tolower(From), LBFrom = setelement(3, LFrom, <<"">>), @@ -1702,6 +1703,7 @@ process_presence_probe(From, To, StateData) -> end. %% User updates his presence (non-directed presence packet) +-spec presence_update(jid(), presence(), state()) -> state(). presence_update(From, Packet, StateData) -> #presence{type = Type} = Packet, case Type of @@ -1761,6 +1763,7 @@ presence_update(From, Packet, StateData) -> end. %% User sends a directed presence packet +-spec presence_track(jid(), jid(), presence(), state()) -> state(). presence_track(From, To, Packet, StateData) -> #presence{type = Type} = Packet, LTo = jid:tolower(To), @@ -1768,7 +1771,7 @@ presence_track(From, To, Packet, StateData) -> Server = StateData#state.server, case Type of unavailable -> - A = remove_element(LTo, StateData#state.pres_a), + A = ?SETS:del_element(LTo, StateData#state.pres_a), check_privacy_route(From, StateData#state{pres_a = A}, From, To, Packet); subscribe -> try_roster_subscribe(subscribe, User, Server, From, To, Packet, StateData); @@ -1793,6 +1796,7 @@ presence_track(From, To, Packet, StateData) -> check_privacy_route(From, StateData#state{pres_a = A}, From, To, Packet) end. +-spec check_privacy_route(jid(), state(), jid(), jid(), stanza()) -> state(). check_privacy_route(From, StateData, FromRoute, To, Packet) -> case privacy_check_packet(StateData, From, To, Packet, @@ -1812,6 +1816,7 @@ check_privacy_route(From, StateData, FromRoute, To, end. %% Check if privacy rules allow this delivery +-spec privacy_check_packet(state(), jid(), jid(), stanza(), in | out) -> allow | deny. privacy_check_packet(StateData, From, To, Packet, Dir) -> ejabberd_hooks:run_fold(privacy_check_packet, @@ -1820,11 +1825,14 @@ privacy_check_packet(StateData, From, To, Packet, StateData#state.privacy_list, {From, To, Packet}, Dir]). +-spec is_privacy_allow(state(), jid(), jid(), stanza(), in | out) -> boolean(). is_privacy_allow(StateData, From, To, Packet, Dir) -> allow == privacy_check_packet(StateData, From, To, Packet, Dir). %%% Check ACL before allowing to send a subscription stanza +-spec try_roster_subscribe(subscribe | unsubscribe, binary(), binary(), + jid(), jid(), presence(), state()) -> state(). try_roster_subscribe(Type, User, Server, From, To, Packet, StateData) -> JID1 = jid:make(User, Server, <<"">>), Access = gen_mod:get_module_opt(Server, mod_roster, access, fun(A) when is_atom(A) -> A end, all), @@ -1841,21 +1849,24 @@ try_roster_subscribe(Type, User, Server, From, To, Packet, StateData) -> end. %% Send presence when disconnecting +-spec presence_broadcast(state(), jid(), ?SETS:set(), presence()) -> ok. presence_broadcast(StateData, From, JIDSet, Packet) -> JIDs = ?SETS:to_list(JIDSet), JIDs2 = format_and_check_privacy(From, StateData, Packet, JIDs, out), Server = StateData#state.server, send_multiple(From, Server, JIDs2, Packet). +-spec presence_broadcast_to_trusted( + state(), jid(), ?SETS:set(), ?SETS:set(), presence()) -> ok. %% Send presence when updating presence presence_broadcast_to_trusted(StateData, From, Trusted, JIDSet, Packet) -> - JIDs = ?SETS:to_list(JIDSet), - JIDs_trusted = [JID || JID <- JIDs, ?SETS:is_element(JID, Trusted)], - JIDs2 = format_and_check_privacy(From, StateData, Packet, JIDs_trusted, out), + JIDs = ?SETS:to_list(?SETS:intersection(Trusted, JIDSet)), + JIDs2 = format_and_check_privacy(From, StateData, Packet, JIDs, out), Server = StateData#state.server, send_multiple(From, Server, JIDs2, Packet). %% Send presence when connecting +-spec presence_broadcast_first(jid(), state(), presence()) -> state(). presence_broadcast_first(From, StateData, Packet) -> JIDsProbe = ?SETS:fold( @@ -1877,6 +1888,8 @@ presence_broadcast_first(From, StateData, Packet) -> send_multiple(From, Server, JIDs2, Packet), StateData#state{pres_a = As}. +-spec format_and_check_privacy( + jid(), state(), stanza(), [ljid()], in | out) -> [jid()]. format_and_check_privacy(From, StateData, Packet, JIDs, Dir) -> FJIDs = [jid:make(JID) || JID <- JIDs], lists:filter( @@ -1895,15 +1908,11 @@ format_and_check_privacy(From, StateData, Packet, JIDs, Dir) -> end, FJIDs). +-spec send_multiple(jid(), binary(), [jid()], stanza()) -> ok. send_multiple(From, Server, JIDs, Packet) -> ejabberd_router_multicast:route_multicast(From, Server, JIDs, Packet). -remove_element(E, Set) -> - case (?SETS):is_element(E, Set) of - true -> (?SETS):del_element(E, Set); - _ -> Set - end. - +-spec roster_change(jid(), both | from | none | remove | to, state()) -> state(). roster_change(IJID, ISubscription, StateData) -> LIJID = jid:tolower(IJID), IsFrom = (ISubscription == both) or (ISubscription == from), @@ -1911,11 +1920,11 @@ roster_change(IJID, ISubscription, StateData) -> OldIsFrom = (?SETS):is_element(LIJID, StateData#state.pres_f), FSet = if IsFrom -> (?SETS):add_element(LIJID, StateData#state.pres_f); - true -> remove_element(LIJID, StateData#state.pres_f) + true -> ?SETS:del_element(LIJID, StateData#state.pres_f) end, TSet = if IsTo -> (?SETS):add_element(LIJID, StateData#state.pres_t); - true -> remove_element(LIJID, StateData#state.pres_t) + true -> ?SETS:del_element(LIJID, StateData#state.pres_t) end, case StateData#state.pres_last of undefined -> @@ -1946,13 +1955,14 @@ roster_change(IJID, ISubscription, StateData) -> deny -> ok; allow -> ejabberd_router:route(From, To, PU) end, - A = remove_element(LIJID, StateData#state.pres_a), + A = ?SETS:del_element(LIJID, StateData#state.pres_a), StateData#state{pres_a = A, pres_f = FSet, pres_t = TSet}; true -> StateData#state{pres_f = FSet, pres_t = TSet} end end. +-spec update_priority(integer(), presence(), state()) -> ok. update_priority(Priority, Packet, StateData) -> Info = [{ip, StateData#state.ip}, {conn, StateData#state.conn}, {auth_module, StateData#state.auth_module}], @@ -1960,12 +1970,14 @@ update_priority(Priority, Packet, StateData) -> StateData#state.user, StateData#state.server, StateData#state.resource, Priority, Packet, Info). +-spec get_priority_from_presence(presence()) -> integer(). get_priority_from_presence(#presence{priority = Prio}) -> case Prio of undefined -> 0; _ -> Prio end. +-spec process_privacy_iq(iq(), state()) -> state(). process_privacy_iq(#iq{from = From, to = To, type = Type, lang = Lang} = IQ, StateData) -> Txt = <<"No module is handling this query">>, @@ -2001,6 +2013,7 @@ process_privacy_iq(#iq{from = From, to = To, ejabberd_router:route(To, From, IQRes), NewStateData. +-spec resend_offline_messages(state()) -> ok. resend_offline_messages(#state{ask_offline = true} = StateData) -> case ejabberd_hooks:run_fold(resend_offline_messages_hook, StateData#state.server, [], @@ -2025,6 +2038,7 @@ resend_offline_messages(#state{ask_offline = true} = StateData) -> resend_offline_messages(_StateData) -> ok. +-spec resend_subscription_requests(state()) -> state(). resend_subscription_requests(#state{user = User, server = Server} = StateData) -> PendingSubscriptions = @@ -2036,13 +2050,16 @@ resend_subscription_requests(#state{user = User, StateData, PendingSubscriptions). +-spec get_showtag(undefined | presence()) -> binary(). get_showtag(undefined) -> <<"unavailable">>; get_showtag(#presence{show = undefined}) -> <<"available">>; get_showtag(#presence{show = Show}) -> atom_to_binary(Show, utf8). -get_statustag(#presence{status = [#text{data = Status}|_]}) -> Status; -get_statustag(_) -> <<"">>. +-spec get_statustag(undefined | presence()) -> binary(). +get_statustag(#presence{status = Status}) -> xmpp:get_text(Status); +get_statustag(undefined) -> <<"">>. +-spec process_unauthenticated_stanza(state(), iq()) -> ok | {error, any()}. process_unauthenticated_stanza(StateData, #iq{type = T, lang = L} = IQ) when T == set; T == get -> Lang = if L == undefined; L == <<"">> -> StateData#state.lang; @@ -2067,6 +2084,9 @@ process_unauthenticated_stanza(_StateData, _) -> %% Drop any stanza, which isn't IQ stanza ok. +-spec peerip(ejabberd_socket:sockmod(), + ejabberd_socket:socket()) -> + {inet:ip_address(), non_neg_integer()} | undefined. peerip(SockMod, Socket) -> IP = case SockMod of gen_tcp -> inet:peername(Socket); @@ -2124,6 +2144,7 @@ fsm_next_state(StateName, StateData) -> %% fsm_reply: Generate the reply FSM tuple with different timeout, %% depending on the future state +-spec fsm_reply(_, state_name(), state()) -> fsm_reply(). fsm_reply(Reply, session_established, StateData) -> {reply, Reply, session_established, StateData, ?C2S_HIBERNATE_TIMEOUT}; @@ -2135,6 +2156,8 @@ fsm_reply(Reply, StateName, StateData) -> {reply, Reply, StateName, StateData, ?C2S_OPEN_TIMEOUT}. %% Used by c2s blacklist plugins +-spec is_ip_blacklisted(undefined | {inet:ip_address(), non_neg_integer()}, + binary()) -> false | {true, binary(), binary()}. is_ip_blacklisted(undefined, _Lang) -> false; is_ip_blacklisted({IP, _Port}, Lang) -> ejabberd_hooks:run_fold(check_bl_c2s, false, [IP, Lang]). @@ -2174,6 +2197,7 @@ fsm_limit_opts(Opts) -> end end. +-spec bounce_messages() -> ok. bounce_messages() -> receive {route, From, To, El} -> @@ -2181,6 +2205,7 @@ bounce_messages() -> after 0 -> ok end. +-spec process_compression_request(compress(), state_name(), state()) -> fsm_next(). process_compression_request(#compress{methods = []}, StateName, StateData) -> send_element(StateData, #compress_failure{reason = 'setup-failed'}), fsm_next_state(StateName, StateData); @@ -2203,6 +2228,8 @@ process_compression_request(#compress{methods = Ms}, StateName, StateData) -> %%% XEP-0191 %%%---------------------------------------------------------------------- +-spec route_blocking( + {block, [jid()]} | {unblock, [jid()]} | unblock_all, state()) -> state(). route_blocking(What, StateData) -> SubEl = case What of {block, JIDs} -> @@ -2223,12 +2250,13 @@ route_blocking(What, StateData) -> %%%---------------------------------------------------------------------- %%% XEP-0198 %%%---------------------------------------------------------------------- - +-spec stream_mgmt_enabled(state()) -> boolean(). stream_mgmt_enabled(#state{mgmt_state = disabled}) -> false; stream_mgmt_enabled(_StateData) -> true. +-spec dispatch_stream_mgmt(xmpp_element(), state()) -> state(). dispatch_stream_mgmt(El, #state{mgmt_state = MgmtState} = StateData) when MgmtState == active; MgmtState == pending -> @@ -2236,6 +2264,7 @@ dispatch_stream_mgmt(El, #state{mgmt_state = MgmtState} = StateData) dispatch_stream_mgmt(El, StateData) -> negotiate_stream_mgmt(El, StateData). +-spec negotiate_stream_mgmt(xmpp_element(), state()) -> state(). negotiate_stream_mgmt(_El, #state{resource = <<"">>} = StateData) -> %% XEP-0198 says: "For client-to-server connections, the client MUST NOT %% attempt to enable stream management until after it has completed Resource @@ -2272,6 +2301,7 @@ negotiate_stream_mgmt(Pkt, StateData) -> StateData end. +-spec perform_stream_mgmt(xmpp_element(), state()) -> state(). perform_stream_mgmt(Pkt, StateData) -> case xmpp:get_ns(Pkt) of Xmlns when Xmlns == StateData#state.mgmt_xmlns -> @@ -2298,6 +2328,7 @@ perform_stream_mgmt(Pkt, StateData) -> xmlns = StateData#state.mgmt_xmlns}) end. +-spec handle_enable(state(), sm_enable()) -> state(). handle_enable(#state{mgmt_timeout = DefaultTimeout, mgmt_max_timeout = MaxTimeout} = StateData, #sm_enable{resume = Resume, max = Max}) -> @@ -2325,15 +2356,18 @@ handle_enable(#state{mgmt_timeout = DefaultTimeout, mgmt_queue = queue:new(), mgmt_timeout = Timeout * 1000}. +-spec handle_r(state()) -> state(). handle_r(StateData) -> Res = #sm_a{xmlns = StateData#state.mgmt_xmlns, h = StateData#state.mgmt_stanzas_in}, send_element(StateData, Res), StateData. +-spec handle_a(state(), sm_a()) -> state(). handle_a(StateData, #sm_a{h = H}) -> check_h_attribute(StateData, H). +-spec handle_resume(state(), sm_resume()) -> {ok, state()} | error. handle_resume(StateData, #sm_resume{h = H, previd = PrevID, xmlns = Xmlns}) -> R = case stream_mgmt_enabled(StateData) of true -> @@ -2379,6 +2413,7 @@ handle_resume(StateData, #sm_resume{h = H, previd = PrevID, xmlns = Xmlns}) -> error end. +-spec check_h_attribute(state(), non_neg_integer()) -> state(). check_h_attribute(#state{mgmt_stanzas_out = NumStanzasOut} = StateData, H) when H > NumStanzasOut -> ?DEBUG("~s acknowledged ~B stanzas, but only ~B were sent", @@ -2389,6 +2424,7 @@ check_h_attribute(#state{mgmt_stanzas_out = NumStanzasOut} = StateData, H) -> [jid:to_string(StateData#state.jid), H, NumStanzasOut]), mgmt_queue_drop(StateData, H). +-spec update_num_stanzas_in(state(), xmpp_element()) -> state(). update_num_stanzas_in(#state{mgmt_state = MgmtState} = StateData, El) when MgmtState == active; MgmtState == pending -> @@ -2404,6 +2440,7 @@ update_num_stanzas_in(#state{mgmt_state = MgmtState} = StateData, El) update_num_stanzas_in(StateData, _El) -> StateData. +-spec send_stanza_and_ack_req(state(), stanza()) -> state(). send_stanza_and_ack_req(StateData, Stanza) -> AckReq = #sm_r{xmlns = StateData#state.mgmt_xmlns}, case send_element(StateData, Stanza) == ok andalso @@ -2414,6 +2451,7 @@ send_stanza_and_ack_req(StateData, Stanza) -> StateData#state{mgmt_state = pending} end. +-spec mgmt_queue_add(state(), xmpp_element()) -> state(). mgmt_queue_add(StateData, El) -> NewNum = case StateData#state.mgmt_stanzas_out of 4294967295 -> @@ -2426,11 +2464,13 @@ mgmt_queue_add(StateData, El) -> mgmt_stanzas_out = NewNum}, check_queue_length(NewState). +-spec mgmt_queue_drop(state(), non_neg_integer()) -> state(). mgmt_queue_drop(StateData, NumHandled) -> NewQueue = jlib:queue_drop_while(fun({N, _T, _E}) -> N =< NumHandled end, StateData#state.mgmt_queue), StateData#state{mgmt_queue = NewQueue}. +-spec check_queue_length(state()) -> state(). check_queue_length(#state{mgmt_max_queue = Limit} = StateData) when Limit == infinity; Limit == exceeded -> @@ -2444,6 +2484,7 @@ check_queue_length(#state{mgmt_queue = Queue, StateData end. +-spec handle_unacked_stanzas(state(), fun((_, _, _, _) -> _)) -> ok. handle_unacked_stanzas(#state{mgmt_state = MgmtState} = StateData, F) when MgmtState == active; MgmtState == pending; @@ -2465,6 +2506,7 @@ handle_unacked_stanzas(#state{mgmt_state = MgmtState} = StateData, F) handle_unacked_stanzas(_StateData, _F) -> ok. +-spec handle_unacked_stanzas(state()) -> ok. handle_unacked_stanzas(#state{mgmt_state = MgmtState} = StateData) when MgmtState == active; MgmtState == pending; @@ -2537,6 +2579,7 @@ handle_unacked_stanzas(#state{mgmt_state = MgmtState} = StateData) handle_unacked_stanzas(_StateData) -> ok. +-spec is_encapsulated_forward(stanza()) -> boolean(). is_encapsulated_forward(#message{} = Msg) -> xmpp:has_subtag(Msg, #forwarded{}) orelse xmpp:has_subtag(Msg, #carbons_sent{}) orelse @@ -2544,6 +2587,9 @@ is_encapsulated_forward(#message{} = Msg) -> is_encapsulated_forward(_El) -> false. +-spec inherit_session_state(state(), binary()) -> {ok, state()} | + {error, binary()} | + {error, binary(), non_neg_integer()}. inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) -> case jlib:base64_to_term(ResumeID) of {term, {R, Time}} -> @@ -2604,13 +2650,16 @@ inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) -> {error, <<"Invalid 'previd' value">>} end. +-spec resume_session({integer(), pid()}) -> any(). resume_session({Time, PID}) -> (?GEN_FSM):sync_send_all_state_event(PID, {resume_session, Time}, 5000). +-spec make_resume_id(state()) -> binary(). make_resume_id(StateData) -> {Time, _} = StateData#state.sid, jlib:term_to_base64({StateData#state.resource, Time}). +-spec add_resent_delay_info(state(), stanza(), erlang:timestamp()) -> stanza(). add_resent_delay_info(_State, #iq{} = El, _Time) -> El; add_resent_delay_info(#state{server = From}, El, Time) -> @@ -2619,7 +2668,7 @@ add_resent_delay_info(#state{server = From}, El, Time) -> %%%---------------------------------------------------------------------- %%% XEP-0352 %%%---------------------------------------------------------------------- - +-spec csi_filter_stanza(state(), stanza()) -> state(). csi_filter_stanza(#state{csi_state = CsiState, server = Server} = StateData, Stanza) -> {StateData1, Stanzas} = ejabberd_hooks:run_fold(csi_filter_stanza, Server, @@ -2631,6 +2680,7 @@ csi_filter_stanza(#state{csi_state = CsiState, server = Server} = StateData, Stanzas), StateData2#state{csi_state = CsiState}. +-spec csi_flush_queue(state()) -> state(). csi_flush_queue(#state{csi_state = CsiState, server = Server} = StateData) -> {StateData1, Stanzas} = ejabberd_hooks:run_fold(csi_flush_queue, Server, {StateData, []}, [Server]), @@ -2646,6 +2696,7 @@ csi_flush_queue(#state{csi_state = CsiState, server = Server} = StateData) -> %% Try to reduce the heap footprint of the four presence sets %% by ensuring that we re-use strings and Jids wherever possible. +-spec pack(state()) -> state(). pack(S = #state{pres_a = A, pres_f = F, pres_t = T}) -> {NewA, Pack2} = pack_jid_set(A, gb_trees:empty()), @@ -2682,6 +2733,7 @@ pack_string(String, Pack) -> transform_listen_option(Opt, Opts) -> [Opt|Opts]. +-spec identity([{atom(), binary()}]) -> binary(). identity(Props) -> case proplists:get_value(authzid, Props, <<>>) of <<>> -> proplists:get_value(username, Props, <<>>); diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 5a39df043..d82e32b9a 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -877,7 +877,7 @@ v_db(Mod, Type) -> [] -> erlang:error(badarg) end. --spec default_db(binary(), module()) -> atom(). +-spec default_db(global | binary(), module()) -> atom(). default_db(Host, Module) -> case ejabberd_config:get_option( diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index dca456427..c2bf453a5 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -183,14 +183,13 @@ unregister_iq_handler(Host, XMLNS) -> refresh_iq_handlers() -> ejabberd_local ! refresh_iq_handlers. --spec bounce_resource_packet(jid(), jid(), stanza()) -> stop. +-spec bounce_resource_packet(jid(), jid(), stanza()) -> ok. bounce_resource_packet(From, To, Packet) -> Lang = xmpp:get_lang(Packet), Txt = <<"No available resource found">>, Err = xmpp:make_error(Packet, xmpp:err_item_not_found(Txt, Lang)), - ejabberd_router:route(To, From, Err), - stop. + ejabberd_router:route(To, From, Err). %%==================================================================== %% gen_server callbacks diff --git a/src/ejabberd_router_multicast.erl b/src/ejabberd_router_multicast.erl index 967699007..283bcac25 100644 --- a/src/ejabberd_router_multicast.erl +++ b/src/ejabberd_router_multicast.erl @@ -45,7 +45,7 @@ -include("logger.hrl"). -include("xmpp.hrl"). --record(route_multicast, {domain = <<"">> :: binary(), +-record(route_multicast, {domain = <<"">> :: binary() | '_', pid = self() :: pid()}). -record(state, {}). diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 04b961b3d..7be4906fb 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -62,7 +62,7 @@ connections = (?DICT):new() :: ?TDICT, timer = make_ref() :: reference()}). --type state_name() :: wait_for_stream | wait_for_features | stream_established. +-type state_name() :: wait_for_stream | wait_for_feature_request | stream_established. -type state() :: #state{}. -type fsm_next() :: {next_state, state_name(), state()}. -type fsm_stop() :: {stop, normal, state()}. @@ -287,7 +287,8 @@ wait_for_feature_request(#starttls{}, end, TLSSocket = (StateData#state.sockmod):starttls( Socket, TLSOpts, - fxml:element_to_binary(#starttls_proceed{})), + fxml:element_to_binary( + xmpp:encode(#starttls_proceed{}))), {next_state, wait_for_stream, StateData#state{socket = TLSSocket, streamid = new_id(), tls_enabled = true, tls_options = TLSOpts}}; @@ -342,19 +343,17 @@ stream_established({xmlstreamelement, El}, StateData) -> stream_established(#db_result{to = To, from = From, key = Key}, StateData) -> ?DEBUG("GET KEY: ~p", [{To, From, Key}]), - LTo = To#jid.lserver, - LFrom = From#jid.lserver, - case {ejabberd_s2s:allow_host(LTo, LFrom), - lists:member(LTo, ejabberd_router:dirty_get_all_domains())} of + case {ejabberd_s2s:allow_host(To, From), + lists:member(To, ejabberd_router:dirty_get_all_domains())} of {true, true} -> - ejabberd_s2s_out:terminate_if_waiting_delay(LTo, LFrom), - ejabberd_s2s_out:start(LTo, LFrom, + ejabberd_s2s_out:terminate_if_waiting_delay(To, From), + ejabberd_s2s_out:start(To, From, {verify, self(), Key, StateData#state.streamid}), - Conns = (?DICT):store({LFrom, LTo}, + Conns = (?DICT):store({From, To}, wait_for_verification, StateData#state.connections), - change_shaper(StateData, LTo, jid:make(LFrom)), + change_shaper(StateData, To, jid:make(From)), {next_state, stream_established, StateData#state{connections = Conns}}; {_, false} -> @@ -367,9 +366,7 @@ stream_established(#db_result{to = To, from = From, key = Key}, stream_established(#db_verify{to = To, from = From, id = Id, key = Key}, StateData) -> ?DEBUG("VERIFY KEY: ~p", [{To, From, Id, Key}]), - LTo = jid:nameprep(To), - LFrom = jid:nameprep(From), - Type = case ejabberd_s2s:make_key({LTo, LFrom}, Id) of + Type = case ejabberd_s2s:make_key({To, From}, Id) of Key -> valid; _ -> invalid end, @@ -412,19 +409,15 @@ stream_established({valid, From, To}, StateData) -> #db_result{from = To, to = From, type = valid}), ?INFO_MSG("Accepted s2s dialback authentication for ~s (TLS=~p)", [From, StateData#state.tls_enabled]), - LFrom = jid:nameprep(From), - LTo = jid:nameprep(To), NSD = StateData#state{connections = - (?DICT):store({LFrom, LTo}, established, + (?DICT):store({From, To}, established, StateData#state.connections)}, {next_state, stream_established, NSD}; stream_established({invalid, From, To}, StateData) -> send_element(StateData, #db_result{from = To, to = From, type = invalid}), - LFrom = jid:nameprep(From), - LTo = jid:nameprep(To), NSD = StateData#state{connections = - (?DICT):erase({LFrom, LTo}, + (?DICT):erase({From, To}, StateData#state.connections)}, {next_state, stream_established, NSD}; stream_established({xmlstreamend, _Name}, StateData) -> diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 024e51e7a..4284f7f7b 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -832,15 +832,15 @@ send_db_request(StateData) -> {StateData#state.myname, Server}, StateData#state.remote_streamid), send_element(StateData, - #db_result{from = jid:make(StateData#state.myname), - to = jid:make(Server), + #db_result{from = StateData#state.myname, + to = Server, key = Key1}) end, case StateData#state.verify of false -> ok; {_Pid, Key2, SID} -> send_element(StateData, - #db_verify{from = jid:make(StateData#state.myname), + #db_verify{from = StateData#state.myname, to = StateData#state.server, id = SID, key = Key2}) @@ -1067,7 +1067,7 @@ get_max_retry_delay() -> end. %% Terminate s2s_out connections that are in state wait_before_retry --spec terminate_if_waiting_delay(ljid(), ljid()) -> ok. +-spec terminate_if_waiting_delay(binary(), binary()) -> ok. terminate_if_waiting_delay(From, To) -> FromTo = {From, To}, Pids = ejabberd_s2s:get_connections_pids(FromTo), diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 432253e09..3df39438a 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -127,7 +127,7 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) -> try xmpp:decode(#xmlel{name = Name, attrs = Attrs}) of #stream_start{xmlns = ?NS_COMPONENT, to = To} when is_record(To, jid) -> Host = To#jid.lserver, - send_header(StateData, To), + send_header(StateData, Host), HostOpts = case dict:is_key(Host, StateData#state.host_opts) of true -> StateData#state.host_opts; diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index bc550ef44..3ff9f2908 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -110,7 +110,7 @@ %%==================================================================== %% API %%==================================================================== --export_type([sid/0]). +-export_type([sid/0, info/0]). start() -> ChildSpec = {?MODULE, {?MODULE, start_link, []}, @@ -168,7 +168,7 @@ check_in_subscription(Acc, User, Server, _JID, _Type, _Reason) -> false -> {stop, false} end. --spec bounce_offline_message(jid(), jid(), xmlel()) -> stop. +-spec bounce_offline_message(jid(), jid(), message()) -> stop. bounce_offline_message(From, To, Packet) -> Lang = xmpp:get_lang(Packet), @@ -234,7 +234,7 @@ get_user_info(User, Server, Resource) -> end. -spec set_presence(sid(), binary(), binary(), binary(), - prio(), xmlel(), info()) -> ok. + prio(), presence(), info()) -> ok. set_presence(SID, User, Server, Resource, Priority, Presence, Info) -> @@ -750,7 +750,7 @@ process_iq(From, To, #iq{type = T} = Packet) when T == get; T == set -> process_iq(_From, _To, #iq{}) -> ok. --spec force_update_presence({binary(), binary()}) -> any(). +-spec force_update_presence({binary(), binary()}) -> ok. force_update_presence({LUser, LServer}) -> Mod = get_sm_backend(LServer), diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl index 7160025e7..f8dc84630 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -65,7 +65,7 @@ -type socket_state() :: #socket_state{}. --export_type([socket_state/0, sockmod/0]). +-export_type([socket/0, socket_state/0, sockmod/0]). %%==================================================================== diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index ae7cb2d88..7f815a57e 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -61,6 +61,7 @@ start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, Opts, []). +-spec process_command(jid(), jid(), stanza()) -> ok. process_command(From, To, Packet) -> case To of #jid{luser = <<"">>, lresource = <<"watchdog">>} -> @@ -75,7 +76,7 @@ process_command(From, To, Packet) -> process_flag(priority, high), process_command1(From, To, BodyText) end), - stop; + ok; false -> ok end; _ -> ok diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index e62b4d257..2740e2879 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -1045,17 +1045,21 @@ process_admin(Host, process_admin(Host, #request{lang = Lang, auth = {_, _Auth, AJID}} = Request) -> - {Hook, Opts} = case Host of - global -> {webadmin_page_main, [Request]}; - Host -> {webadmin_page_host, [Host, Request]} - end, - case ejabberd_hooks:run_fold(Hook, Host, [], Opts) of + Res = case Host of + global -> + ejabberd_hooks:run_fold( + webadmin_page_main, Host, [], [Request]); + _ -> + ejabberd_hooks:run_fold( + webadmin_page_host, Host, [], [Host, Request]) + end, + case Res of [] -> setelement(1, make_xhtml([?XC(<<"h1">>, <<"Not Found">>)], Host, Lang, AJID), 404); - Res -> make_xhtml(Res, Host, Lang, AJID) + _ -> make_xhtml(Res, Host, Lang, AJID) end. %%%================================== @@ -2269,16 +2273,17 @@ get_node(global, Node, [<<"update">>], Query, Lang) -> ?BR, ?INPUTT(<<"submit">>, <<"update">>, <<"Update">>)])]; get_node(Host, Node, NPath, Query, Lang) -> - {Hook, Opts} = case Host of - global -> - {webadmin_page_node, [Node, NPath, Query, Lang]}; - Host -> - {webadmin_page_hostnode, - [Host, Node, NPath, Query, Lang]} - end, - case ejabberd_hooks:run_fold(Hook, Host, [], Opts) of + Res = case Host of + global -> + ejabberd_hooks:run_fold(webadmin_page_node, Host, [], + [Node, NPath, Query, Lang]); + _ -> + ejabberd_hooks:run_fold(webadmin_page_hostnode, Host, [], + [Host, Node, NPath, Query, Lang]) + end, + case Res of [] -> [?XC(<<"h1">>, <<"Not Found">>)]; - Res -> Res + _ -> Res end. %%%================================== diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl index f78ba7e40..fcfe9f3a7 100644 --- a/src/gen_iq_handler.erl +++ b/src/gen_iq_handler.erl @@ -47,6 +47,7 @@ -type component() :: ejabberd_sm | ejabberd_local. -type type() :: no_queue | one_queue | pos_integer() | parallel. -type opts() :: no_queue | {one_queue, pid()} | {queues, [pid()]} | parallel. +-export_type([opts/0]). %%==================================================================== %% API diff --git a/src/gen_mod.erl b/src/gen_mod.erl index e5b504897..476e19e9d 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -378,7 +378,7 @@ db_type(Host, Module) when is_atom(Module) -> undefined end. --spec db_type(binary(), opts(), module()) -> db_type(). +-spec db_type(global | binary(), opts(), module()) -> db_type(). db_type(Host, Opts, Module) -> case catch Module:mod_opt_type(db_type) of diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index 22bde2586..e6d94e40a 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -173,7 +173,9 @@ get_sm_identity(Acc, _From, _To, ?NS_COMMANDS, Lang) -> get_sm_identity(Acc, _From, _To, _Node, _Lang) -> Acc. %------------------------------------------------------------------------- - +-spec get_local_features({error, error()} | {result, [binary()]} | empty, + jid(), jid(), binary(), binary()) -> + {error, error()} | {result, [binary()]} | empty. get_local_features(Acc, _From, _To, <<"">>, _Lang) -> Feats = case Acc of {result, I} -> I; @@ -205,16 +207,24 @@ get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. %------------------------------------------------------------------------- process_local_iq(IQ) -> - process_adhoc_request(IQ, adhoc_local_commands). + process_adhoc_request(IQ, local). process_sm_iq(IQ) -> - process_adhoc_request(IQ, adhoc_sm_commands). + process_adhoc_request(IQ, sm). process_adhoc_request(#iq{from = From, to = To, type = set, lang = Lang, - sub_els = [#adhoc_command{} = SubEl]} = IQ, Hook) -> + sub_els = [#adhoc_command{} = SubEl]} = IQ, Type) -> Host = To#jid.lserver, - case ejabberd_hooks:run_fold(Hook, Host, empty, [From, To, SubEl]) of + Res = case Type of + local -> + ejabberd_hooks:run_fold(adhoc_local_commands, Host, empty, + [From, To, SubEl]); + sm -> + ejabberd_hooks:run_fold(adhoc_sm_commands, Host, empty, + [From, To, SubEl]) + end, + case Res of ignore -> ignore; empty -> @@ -228,6 +238,8 @@ process_adhoc_request(#iq{from = From, to = To, process_adhoc_request(#iq{} = IQ, _Hooks) -> xmpp:make_error(IQ, xmpp:err_bad_request()). +-spec ping_item(empty | {error, error()} | {result, [disco_item()]}, + jid(), jid(), binary()) -> {result, [disco_item()]}. ping_item(Acc, _From, #jid{server = Server} = _To, Lang) -> Items = case Acc of @@ -239,6 +251,8 @@ ping_item(Acc, _From, #jid{server = Server} = _To, name = translate:translate(Lang, <<"Ping">>)}], {result, Items ++ Nodes}. +-spec ping_command(adhoc_command(), jid(), jid(), adhoc_command()) -> + adhoc_command() | {error, error()}. ping_command(_Acc, _From, _To, #adhoc_command{lang = Lang, node = <<"ping">>, action = Action} = Request) -> diff --git a/src/mod_announce.erl b/src/mod_announce.erl index 1a42a460b..eb201fc88 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -130,42 +130,34 @@ stop(Host) -> {wait, Proc}. %% Announcing via messages to a custom resource +-spec announce(jid(), jid(), stanza()) -> ok. announce(From, #jid{luser = <<>>} = To, #message{} = Packet) -> Proc = gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME), case To#jid.lresource of <<"announce/all">> -> - Proc ! {announce_all, From, To, Packet}, - stop; + Proc ! {announce_all, From, To, Packet}; <<"announce/all-hosts/all">> -> - Proc ! {announce_all_hosts_all, From, To, Packet}, - stop; + Proc ! {announce_all_hosts_all, From, To, Packet}; <<"announce/online">> -> - Proc ! {announce_online, From, To, Packet}, - stop; + Proc ! {announce_online, From, To, Packet}; <<"announce/all-hosts/online">> -> - Proc ! {announce_all_hosts_online, From, To, Packet}, - stop; + Proc ! {announce_all_hosts_online, From, To, Packet}; <<"announce/motd">> -> - Proc ! {announce_motd, From, To, Packet}, - stop; + Proc ! {announce_motd, From, To, Packet}; <<"announce/all-hosts/motd">> -> - Proc ! {announce_all_hosts_motd, From, To, Packet}, - stop; + Proc ! {announce_all_hosts_motd, From, To, Packet}; <<"announce/motd/update">> -> - Proc ! {announce_motd_update, From, To, Packet}, - stop; + Proc ! {announce_motd_update, From, To, Packet}; <<"announce/all-hosts/motd/update">> -> - Proc ! {announce_all_hosts_motd_update, From, To, Packet}, - stop; + Proc ! {announce_all_hosts_motd_update, From, To, Packet}; <<"announce/motd/delete">> -> - Proc ! {announce_motd_delete, From, To, Packet}, - stop; + Proc ! {announce_motd_delete, From, To, Packet}; <<"announce/all-hosts/motd/delete">> -> - Proc ! {announce_all_hosts_motd_delete, From, To, Packet}, - stop; + Proc ! {announce_all_hosts_motd_delete, From, To, Packet}; _ -> ok - end; + end, + ok; announce(_From, _To, _Packet) -> ok. @@ -344,7 +336,10 @@ disco_items(Acc, From, #jid{lserver = LServer} = _To, Node, Lang) -> end. %%------------------------------------------------------------------------- - +-spec announce_items(empty | {error, error()} | {result, [disco_item()]}, + jid(), jid(), binary()) -> {error, error()} | + {result, [disco_item()]} | + empty. announce_items(Acc, From, #jid{lserver = LServer, server = Server} = _To, Lang) -> Access1 = get_access(LServer), Nodes1 = case acl:match_rule(LServer, Access1, From) of @@ -390,7 +385,8 @@ commands_result(Allow, From, To, Request) -> announce_commands(From, To, Request) end. - +-spec announce_commands(adhoc_command(), jid(), jid(), adhoc_command()) -> + adhoc_command() | {error, error()}. announce_commands(Acc, From, #jid{lserver = LServer} = To, #adhoc_command{node = Node} = Request) -> LNode = tokenize(Node), @@ -764,6 +760,7 @@ announce_motd_delete(LServer) -> Mod = gen_mod:db_mod(LServer, ?MODULE), Mod:delete_motd(LServer). +-spec send_motd(jid()) -> ok | {atomic, any()}. send_motd(#jid{luser = LUser, lserver = LServer} = JID) when LUser /= <<>> -> Mod = gen_mod:db_mod(LServer, ?MODULE), case Mod:get_motd(LServer) of diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index bc3080871..98fb1e441 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -227,16 +227,13 @@ make_userlist(Name, List) -> NeedDb = mod_privacy:is_list_needdb(List), #userlist{name = Name, list = List, needdb = NeedDb}. --spec broadcast_list_update(binary(), binary(), binary(), userlist()) -> - {broadcast, - {privacy_list, userlist(), binary() | none}}. +-spec broadcast_list_update(binary(), binary(), binary(), userlist()) -> ok. broadcast_list_update(LUser, LServer, Name, UserList) -> ejabberd_sm:route(jid:make(LUser, LServer, <<"">>), jid:make(LUser, LServer, <<"">>), {broadcast, {privacy_list, UserList, Name}}). --spec broadcast_blocklist_event(binary(), binary(), block_event()) -> - {broadcast, {blocking, block_event()}}. +-spec broadcast_blocklist_event(binary(), binary(), block_event()) -> ok. broadcast_blocklist_event(LUser, LServer, Event) -> JID = jid:make(LUser, LServer, <<"">>), ejabberd_sm:route(JID, JID, diff --git a/src/mod_caps.erl b/src/mod_caps.erl index d5033ffd8..e57bc7928 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -161,7 +161,7 @@ caps_stream_features(Acc, MyHost) -> -spec disco_features({error, error()} | {result, [binary()]} | empty, jid(), jid(), binary(), binary()) -> - {error, error()} | {result, [binary()]}. + {error, error()} | {result, [binary()]} | empty. disco_features(Acc, From, To, Node, Lang) -> case is_valid_node(Node) of true -> @@ -185,16 +185,18 @@ disco_identity(Acc, From, To, Node, Lang) -> Acc end. --spec disco_info([xdata()], binary(), module(), - binary(), binary()) -> [xdata()]. -disco_info(Acc, Host, Module, Node, Lang) -> +-spec disco_info([xdata()], binary(), module(), binary(), binary()) -> [xdata()]; + ([xdata()], jid(), jid(), binary(), binary()) -> [xdata()]. +disco_info(Acc, Host, Module, Node, Lang) when is_atom(Module) -> case is_valid_node(Node) of true -> ejabberd_hooks:run_fold(disco_info, Host, [], [Host, Module, <<"">>, Lang]); false -> Acc - end. + end; +disco_info(Acc, _, _, _Node, _Lang) -> + Acc. -spec c2s_presence_in(ejabberd_c2s:state(), {jid(), jid(), presence()}) -> ejabberd_c2s:state(). @@ -277,6 +279,7 @@ c2s_broadcast_recipients(InAcc, Host, C2SState, end; c2s_broadcast_recipients(Acc, _, _, _, _, _) -> Acc. +-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}]. depends(_Host, _Opts) -> []. @@ -403,13 +406,13 @@ feature_response(_IQResult, Host, From, Caps, [_SubNode | SubNodes]) -> feature_request(Host, From, Caps, SubNodes). --spec caps_read_fun(binary(), binary()) -> function(). +-spec caps_read_fun(binary(), {binary(), binary()}) -> function(). caps_read_fun(Host, Node) -> LServer = jid:nameprep(Host), Mod = gen_mod:db_mod(LServer, ?MODULE), fun() -> Mod:caps_read(LServer, Node) end. --spec caps_write_fun(binary(), binary(), [binary()]) -> function(). +-spec caps_write_fun(binary(), {binary(), binary()}, [binary()]) -> function(). caps_write_fun(Host, Node, Features) -> LServer = jid:nameprep(Host), Mod = gen_mod:db_mod(LServer, ?MODULE), @@ -437,8 +440,8 @@ make_my_disco_hash(Host) -> _Err -> <<"">> end. --spec make_disco_hash(disco_info(), crypto:digest_type()) -> binary(). - +-type digest_type() :: md5 | sha | sha224 | sha256 | sha384 | sha512. +-spec make_disco_hash(disco_info(), digest_type()) -> binary(). make_disco_hash(DiscoInfo, Algo) -> Concat = list_to_binary([concat_identities(DiscoInfo), concat_features(DiscoInfo), concat_info(DiscoInfo)]), @@ -469,19 +472,23 @@ check_hash(Caps, DiscoInfo) -> _ -> true end. +-spec concat_features(disco_info()) -> iolist(). concat_features(#disco_info{features = Features}) -> lists:usort([[Feat, $<] || Feat <- Features]). +-spec concat_identities(disco_info()) -> iolist(). concat_identities(#disco_info{identities = Identities}) -> lists:sort( [[Cat, $/, T, $/, Lang, $/, Name, $<] || #identity{category = Cat, type = T, lang = Lang, name = Name} <- Identities]). +-spec concat_info(disco_info()) -> iolist(). concat_info(#disco_info{xdata = Xs}) -> lists:sort( [concat_xdata_fields(Fs) || #xdata{type = result, fields = Fs} <- Xs]). +-spec concat_xdata_fields([xdata_field()]) -> iolist(). concat_xdata_fields(Fields) -> Form = case lists:keyfind(<<"FORM_TYPE">>, #xdata_field.var, Fields) of #xdata_field{values = Values} -> Values; @@ -492,10 +499,12 @@ concat_xdata_fields(Fields) -> is_binary(Var), Var /= <<"FORM_TYPE">>], [Form, $<, lists:sort(Res)]. +-spec gb_trees_fold(fun((_, _, T) -> T), T, gb_trees:tree()) -> T. gb_trees_fold(F, Acc, Tree) -> Iter = gb_trees:iterator(Tree), gb_trees_fold_iter(F, Acc, Iter). +-spec gb_trees_fold_iter(fun((_, _, T) -> T), T, gb_trees:iter()) -> T. gb_trees_fold_iter(F, Acc, Iter) -> case gb_trees:next(Iter) of {Key, Val, NewIter} -> @@ -504,6 +513,7 @@ gb_trees_fold_iter(F, Acc, Iter) -> _ -> Acc end. +-spec now_ts() -> integer(). now_ts() -> p1_time_compat:system_time(seconds). diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index b70ccbc2a..e35caa1c7 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -197,7 +197,7 @@ send_copies(JID, To, Packet, Direction)-> -spec build_forward_packet(jid(), message(), jid(), jid(), direction()) -> message(). build_forward_packet(JID, #message{type = T} = Msg, Sender, Dest, Direction) -> - Forwarded = #forwarded{sub_els = complete_packet(JID, Msg, Direction)}, + Forwarded = #forwarded{sub_els = [complete_packet(JID, Msg, Direction)]}, Carbon = case Direction of sent -> #carbons_sent{forwarded = Forwarded}; received -> #carbons_received{forwarded = Forwarded} diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index a6a6ddc20..042c59702 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -151,12 +151,13 @@ depends(_Host, _Opts) -> %% ejabberd_hooks callbacks. %%-------------------------------------------------------------------- --spec filter_presence({term(), [stanza()]}, binary(), stanza()) - -> {term(), [stanza()]} | {stop, {term(), [stanza()]}}. +-spec filter_presence({ejabberd_c2s:state(), [stanza()]}, binary(), stanza()) + -> {ejabberd_c2s:state(), [stanza()]} | + {stop, {ejabberd_c2s:state(), [stanza()]}}. filter_presence({C2SState, _OutStanzas} = Acc, Host, #presence{type = Type} = Stanza) -> - if Type == available, Type == unavailable -> + if Type == available; Type == unavailable -> ?DEBUG("Got availability presence stanza", []), queue_add(presence, Stanza, Host, C2SState); true -> @@ -164,8 +165,9 @@ filter_presence({C2SState, _OutStanzas} = Acc, Host, end; filter_presence(Acc, _Host, _Stanza) -> Acc. --spec filter_chat_states({term(), [stanza()]}, binary(), stanza()) - -> {term(), [stanza()]} | {stop, {term(), [stanza()]}}. +-spec filter_chat_states({ejabberd_c2s:state(), [stanza()]}, binary(), stanza()) + -> {ejabberd_c2s:state(), [stanza()]} | + {stop, {ejabberd_c2s:state(), [stanza()]}}. filter_chat_states({C2SState, _OutStanzas} = Acc, Host, #message{from = From, to = To} = Stanza) -> @@ -186,8 +188,9 @@ filter_chat_states({C2SState, _OutStanzas} = Acc, Host, end; filter_chat_states(Acc, _Host, _Stanza) -> Acc. --spec filter_pep({term(), [stanza()]}, binary(), stanza()) - -> {term(), [stanza()]} | {stop, {term(), [stanza()]}}. +-spec filter_pep({ejabberd_c2s:state(), [stanza()]}, binary(), stanza()) + -> {ejabberd_c2s:state(), [stanza()]} | + {stop, {ejabberd_c2s:state(), [stanza()]}}. filter_pep({C2SState, _OutStanzas} = Acc, Host, #message{} = Stanza) -> case get_pep_node(Stanza) of @@ -199,14 +202,15 @@ filter_pep({C2SState, _OutStanzas} = Acc, Host, #message{} = Stanza) -> end; filter_pep(Acc, _Host, _Stanza) -> Acc. --spec filter_other({term(), [stanza()]}, binary(), stanza()) - -> {stop, {term(), [stanza()]}}. +-spec filter_other({ejabberd_c2s:state(), [stanza()]}, binary(), stanza()) + -> {stop, {ejabberd_c2s:state(), [stanza()]}}. filter_other({C2SState, _OutStanzas}, Host, Stanza) -> ?DEBUG("Won't add stanza to CSI queue", []), queue_take(Stanza, Host, C2SState). --spec flush_queue({term(), [stanza()]}, binary()) -> {term(), [stanza()]}. +-spec flush_queue({ejabberd_c2s:state(), [stanza()]}, binary()) + -> {ejabberd_c2s:state(), [stanza()]}. flush_queue({C2SState, _OutStanzas}, Host) -> ?DEBUG("Going to flush CSI queue", []), @@ -284,7 +288,7 @@ get_pep_node(#message{from = #jid{luser = <<>>}}) -> undefined; get_pep_node(#message{} = Msg) -> case xmpp:get_subtag(Msg, #pubsub_event{}) of - #pubsub_event{items = [#pubsub_event_item{node = Node}]} -> + #pubsub_event{items = [#pubsub_event_items{node = Node}]} -> Node; _ -> undefined diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 07a1c7333..a798d010f 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -270,7 +270,10 @@ get_local_features(Acc, From, end. %%%----------------------------------------------------------------------- - +-spec adhoc_sm_items(empty | {error, error()} | {result, [disco_item()]}, + jid(), jid(), binary()) -> {error, error()} | + {result, [disco_item()]} | + empty. adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To, Lang) -> case acl:match_rule(LServer, configure, From) of @@ -322,6 +325,10 @@ get_user_resources(User, Server) -> %%%----------------------------------------------------------------------- +-spec adhoc_local_items(empty | {error, error()} | {result, [disco_item()]}, + jid(), jid(), binary()) -> {error, error()} | + {result, [disco_item()]} | + empty. adhoc_local_items(Acc, From, #jid{lserver = LServer, server = Server} = To, Lang) -> case acl:match_rule(LServer, configure, From) of @@ -765,6 +772,8 @@ get_stopped_nodes(_Lang) -> allow -> adhoc_local_commands(From, To, Request) end). +-spec adhoc_local_commands(adhoc_command(), jid(), jid(), adhoc_command()) -> + adhoc_command() | {error, error()}. adhoc_local_commands(Acc, From, #jid{lserver = LServer} = To, #adhoc_command{node = Node, lang = Lang} = Request) -> @@ -1672,8 +1681,7 @@ set_form(_From, _Host, _, _Lang, _XData) -> get_value(Field, XData) -> hd(get_values(Field, XData)). get_values(Field, XData) -> - [_|_] = Values = xmpp_util:get_xdata_values(Field, XData), - Values. + xmpp_util:get_xdata_values(Field, XData). search_running_node(SNode) -> search_running_node(SNode, @@ -1723,7 +1731,7 @@ get_last_info(User, Server) -> end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - +-spec adhoc_sm_commands(adhoc_command(), jid(), jid(), adhoc_command()) -> adhoc_command(). adhoc_sm_commands(_Acc, From, #jid{user = User, server = Server, lserver = LServer}, #adhoc_command{lang = Lang, node = <<"config">>, diff --git a/src/mod_disco.erl b/src/mod_disco.erl index e78b8f72f..e33241928 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -424,8 +424,9 @@ transform_module_options(Opts) -> %%% Support for: XEP-0157 Contact Addresses for XMPP Services --spec get_info([xdata()], binary(), module(), binary(), binary()) -> [xdata()]. -get_info(_A, Host, Mod, Node, _Lang) when Node == <<"">> -> +-spec get_info([xdata()], binary(), module(), binary(), binary()) -> [xdata()]; + ([xdata()], jid(), jid(), binary(), binary()) -> [xdata()]. +get_info(_A, Host, Mod, Node, _Lang) when is_atom(Mod), Node == <<"">> -> Module = case Mod of undefined -> ?MODULE; _ -> Mod diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index c57ac21b0..cc3b4bf7f 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -52,6 +52,8 @@ start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). +-spec c2s_auth_result(boolean(), binary(), binary(), + {inet:ip_address(), non_neg_integer()}) -> ok. c2s_auth_result(false, _User, LServer, {Addr, _Port}) -> case is_whitelisted(LServer, Addr) of true -> @@ -71,11 +73,15 @@ c2s_auth_result(false, _User, LServer, {Addr, _Port}) -> ets:insert(failed_auth, {Addr, N+1, UnbanTS, MaxFailures}); [] -> ets:insert(failed_auth, {Addr, 1, UnbanTS, MaxFailures}) - end + end, + ok end; c2s_auth_result(true, _User, _Server, _AddrPort) -> ok. +-spec check_bl_c2s({true, binary(), binary()} | false, + {inet:ip_address(), non_neg_integer()}, + binary()) -> {stop, {true, binary(), binary()}} | false. check_bl_c2s(_Acc, Addr, Lang) -> case ets:lookup(failed_auth, Addr) of [{Addr, N, TS, MaxFailures}] when N >= MaxFailures -> diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 63dc2dfe2..babdbb7b6 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -553,8 +553,8 @@ process_iq(From, #iq{type = get, lang = Lang, {slot_timed_out, Slot}), NewState = add_slot(Slot, Size, Timer, State), - Slot = mk_slot(Slot, State, XMLNS), - {xmpp:make_iq_result(IQ, Slot), NewState}; + NewSlot = mk_slot(Slot, State, XMLNS), + {xmpp:make_iq_result(IQ, NewSlot), NewState}; {ok, PutURL, GetURL} -> Slot = mk_slot(PutURL, GetURL, XMLNS), xmpp:make_iq_result(IQ, Slot); @@ -668,11 +668,14 @@ del_slot(Slot, #state{slots = Slots} = State) -> NewSlots = maps:remove(Slot, Slots), State#state{slots = NewSlots}. --spec mk_slot(slot() | binary(), state() | binary(), binary()) -> xmlel(). +-spec mk_slot(slot(), state(), binary()) -> upload_slot(); + (binary(), binary(), binary()) -> upload_slot(). mk_slot(Slot, #state{put_url = PutPrefix, get_url = GetPrefix}, XMLNS) -> PutURL = str:join([PutPrefix | Slot], <<$/>>), GetURL = str:join([GetPrefix | Slot], <<$/>>), + mk_slot(PutURL, GetURL, XMLNS); +mk_slot(PutURL, GetURL, XMLNS) -> #upload_slot{get = GetURL, put = PutURL, xmlns = XMLNS}. -spec make_user_string(jid(), sha1 | node) -> binary(). diff --git a/src/mod_ip_blacklist.erl b/src/mod_ip_blacklist.erl index 4f54ecd79..897810927 100644 --- a/src/mod_ip_blacklist.erl +++ b/src/mod_ip_blacklist.erl @@ -109,6 +109,10 @@ update_bl_c2s() -> %% Return: false: IP not blacklisted %% true: IP is blacklisted %% IPV4 IP tuple: +-spec is_ip_in_c2s_blacklist( + {true, binary(), binary()} | false, + {inet:ip_address(), non_neg_integer()}, + binary()) -> {stop, {true, binary(), binary()}} | false. is_ip_in_c2s_blacklist(_Val, IP, Lang) when is_tuple(IP) -> BinaryIP = jlib:ip_to_list(IP), case ets:lookup(bl_c2s, BinaryIP) of diff --git a/src/mod_irc.erl b/src/mod_irc.erl index 3c094ef9c..a833287c8 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -66,10 +66,8 @@ -callback init(binary(), gen_mod:opts()) -> any(). -callback import(binary(), #irc_custom{}) -> ok | pass. --callback get_data(binary(), binary(), {binary(), binary()}) -> - error | empty | irc_data(). --callback set_data(binary(), binary(), {binary(), binary()}, irc_data()) -> - {atomic, any()}. +-callback get_data(binary(), binary(), jid()) -> error | empty | irc_data(). +-callback set_data(binary(), binary(), jid(), irc_data()) -> {atomic, any()}. %%==================================================================== %% API diff --git a/src/mod_irc_connection.erl b/src/mod_irc_connection.erl index 694accf45..c9b460ad0 100644 --- a/src/mod_irc_connection.erl +++ b/src/mod_irc_connection.erl @@ -584,12 +584,12 @@ handle_info({ircstring, <<$:, String/binary>>}, [From, <<"MODE">>, <<$#, Chan/binary>>, <<"+o">>, Nick | _] -> process_mode_o(StateData, Chan, From, Nick, - <<"admin">>, <<"moderator">>), + admin, moderator), StateData; [From, <<"MODE">>, <<$#, Chan/binary>>, <<"-o">>, Nick | _] -> process_mode_o(StateData, Chan, From, Nick, - <<"member">>, <<"participant">>), + member, participant), StateData; [From, <<"KICK">>, <<$#, Chan/binary>>, Nick | _] -> process_kick(StateData, Chan, From, Nick, String), @@ -756,16 +756,16 @@ process_channel_list_user(StateData, Chan, User) -> end, {User2, Affiliation, Role} = case User1 of <<$@, U2/binary>> -> - {U2, <<"admin">>, <<"moderator">>}; + {U2, admin, moderator}; <<$+, U2/binary>> -> - {U2, <<"member">>, <<"participant">>}; + {U2, member, participant}; <<$%, U2/binary>> -> - {U2, <<"admin">>, <<"moderator">>}; + {U2, admin, moderator}; <<$&, U2/binary>> -> - {U2, <<"admin">>, <<"moderator">>}; + {U2, admin, moderator}; <<$~, U2/binary>> -> - {U2, <<"admin">>, <<"moderator">>}; - _ -> {User1, <<"member">>, <<"participant">>} + {U2, admin, moderator}; + _ -> {User1, member, participant} end, ejabberd_router:route( jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), @@ -1157,8 +1157,6 @@ remove_element(E, Set) -> iq_admin(StateData, Channel, From, To, #iq{type = Type, sub_els = [SubEl]} = IQ) -> try process_iq_admin(StateData, Channel, Type, SubEl) of - ignore -> - ignore; {result, Result} -> ejabberd_router:route(To, From, xmpp:make_iq_result(IQ, Result)); {error, Error} -> diff --git a/src/mod_mam.erl b/src/mod_mam.erl index b83c423c7..7e93a3166 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -175,17 +175,21 @@ stop(Host) -> depends(_Host, _Opts) -> []. +-spec remove_user(binary(), binary()) -> ok. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:remove_user(LUser, LServer). + Mod:remove_user(LUser, LServer), + ok. +-spec remove_room(binary(), binary(), binary()) -> ok. remove_room(LServer, Name, Host) -> LName = jid:nodeprep(Name), LHost = jid:nameprep(Host), Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:remove_room(LServer, LName, LHost). + Mod:remove_room(LServer, LName, LHost), + ok. get_room_config(X, RoomState, _From, Lang) -> Config = RoomState#state.config, @@ -621,9 +625,7 @@ should_archive_muc(#message{type = groupchat, end; _ -> true - end; - _ -> - false + end end; should_archive_muc(_) -> false. diff --git a/src/mod_metrics.erl b/src/mod_metrics.erl index cb7946a28..605fe3d6b 100644 --- a/src/mod_metrics.erl +++ b/src/mod_metrics.erl @@ -31,13 +31,7 @@ -include("ejabberd.hrl"). -include("logger.hrl"). --include("jid.hrl"). - --define(HOOKS, [offline_message_hook, - sm_register_connection_hook, sm_remove_connection_hook, - user_send_packet, user_receive_packet, - s2s_send_packet, s2s_receive_packet, - remove_user, register_user]). +-include("xmpp.hrl"). -export([start/2, stop/1, send_metrics/4, opt_type/1, mod_opt_type/1, depends/2]). @@ -53,12 +47,26 @@ %%==================================================================== start(Host, _Opts) -> - [ejabberd_hooks:add(Hook, Host, ?MODULE, Hook, 20) - || Hook <- ?HOOKS]. + ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, offline_message_hook, 20), + ejabberd_hooks:add(sm_register_connection_hook, Host, ?MODULE, sm_register_connection_hook, 20), + ejabberd_hooks:add(sm_remove_connection_hook, Host, ?MODULE, sm_remove_connection_hook, 20), + ejabberd_hooks:add(user_send_packet, Host, ?MODULE, user_send_packet, 20), + ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, user_receive_packet, 20), + ejabberd_hooks:add(s2s_send_packet, Host, ?MODULE, s2s_send_packet, 20), + ejabberd_hooks:add(s2s_receive_packet, Host, ?MODULE, s2s_receive_packet, 20), + ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 20), + ejabberd_hooks:add(register_user, Host, ?MODULE, register_user, 20). stop(Host) -> - [ejabberd_hooks:delete(Hook, Host, ?MODULE, Hook, 20) - || Hook <- ?HOOKS]. + ejabberd_hooks:delete(offline_message_hook, Host, ?MODULE, offline_message_hook, 20), + ejabberd_hooks:delete(sm_register_connection_hook, Host, ?MODULE, sm_register_connection_hook, 20), + ejabberd_hooks:delete(sm_remove_connection_hook, Host, ?MODULE, sm_remove_connection_hook, 20), + ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, user_send_packet, 20), + ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, user_receive_packet, 20), + ejabberd_hooks:delete(s2s_send_packet, Host, ?MODULE, s2s_send_packet, 20), + ejabberd_hooks:delete(s2s_receive_packet, Host, ?MODULE, s2s_receive_packet, 20), + ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 20), + ejabberd_hooks:delete(register_user, Host, ?MODULE, register_user, 20). depends(_Host, _Opts) -> []. @@ -66,12 +74,15 @@ depends(_Host, _Opts) -> %%==================================================================== %% Hooks handlers %%==================================================================== - +-spec offline_message_hook(jid(), jid(), message()) -> any(). offline_message_hook(_From, #jid{lserver=LServer}, _Packet) -> push(LServer, offline_message). +-spec sm_register_connection_hook(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> any(). sm_register_connection_hook(_SID, #jid{lserver=LServer}, _Info) -> push(LServer, sm_register_connection). + +-spec sm_remove_connection_hook(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> any(). sm_remove_connection_hook(_SID, #jid{lserver=LServer}, _Info) -> push(LServer, sm_remove_connection). @@ -82,13 +93,19 @@ user_receive_packet(Packet, _C2SState, _JID, _From, #jid{lserver=LServer}) -> push(LServer, user_receive_packet), Packet. +-spec s2s_send_packet(jid(), jid(), stanza()) -> any(). s2s_send_packet(#jid{lserver=LServer}, _To, _Packet) -> push(LServer, s2s_send_packet). + +-spec s2s_receive_packet(jid(), jid(), stanza()) -> any(). s2s_receive_packet(_From, #jid{lserver=LServer}, _Packet) -> push(LServer, s2s_receive_packet). +-spec remove_user(binary(), binary()) -> any(). remove_user(_User, Server) -> push(jid:nameprep(Server), remove_user). + +-spec register_user(binary(), binary()) -> any(). register_user(_User, Server) -> push(jid:nameprep(Server), register_user). diff --git a/src/mod_mix.erl b/src/mod_mix.erl index 3ba173b9f..52a3c8ed8 100644 --- a/src/mod_mix.erl +++ b/src/mod_mix.erl @@ -52,6 +52,8 @@ stop(Host) -> supervisor:delete_child(ejabberd_sup, Proc), ok. +-spec disco_features({error, error()} | {result, [binary()]} | empty, + jid(), jid(), binary(), binary()) -> {result, [binary()]}. disco_features(_Acc, _From, _To, _Node, _Lang) -> {result, [?NS_MIX_0]}. @@ -69,6 +71,8 @@ disco_identity(Acc, _From, _To, _Node, _Lang) -> Acc ++ [#identity{category = <<"conference">>, type = <<"mix">>}]. +-spec disco_info([xdata()], binary(), module(), binary(), binary()) -> [xdata()]; + ([xdata()], jid(), jid(), binary(), binary()) -> [xdata()]. disco_info(_Acc, _From, To, _Node, _Lang) when is_atom(To) -> [#xdata{type = result, fields = [#xdata_field{var = <<"FORM_TYPE">>, diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 5814ca832..b470c093e 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -3317,28 +3317,34 @@ set_config(#xdata{fields = Fields}, StateData, Lang) -> Err -> Err end. +get_config_opt_name(Pos) -> + Fs = [config|record_info(fields, config)], + lists:nth(Pos, Fs). + -define(SET_BOOL_XOPT(Opt, Val), case Val of <<"0">> -> - set_xoption(Opts, Config#config{Opt = false}, ServerHost, Lang); + set_xoption(Opts, setelement(Opt, Config, false), ServerHost, Lang); <<"false">> -> - set_xoption(Opts, Config#config{Opt = false}, ServerHost, Lang); - <<"1">> -> set_xoption(Opts, Config#config{Opt = true}, ServerHost, Lang); + set_xoption(Opts, setelement(Opt, Config, false), ServerHost, Lang); + <<"1">> -> set_xoption(Opts, setelement(Opt, Config, true), ServerHost, Lang); <<"true">> -> - set_xoption(Opts, Config#config{Opt = true}, ServerHost, Lang); + set_xoption(Opts, setelement(Opt, Config, true), ServerHost, Lang); _ -> Txt = <<"Value of '~s' should be boolean">>, - ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + OptName = get_config_opt_name(Opt), + ErrTxt = iolist_to_binary(io_lib:format(Txt, [OptName])), {error, xmpp:err_bad_request(ErrTxt, Lang)} end). -define(SET_NAT_XOPT(Opt, Val), case catch binary_to_integer(Val) of I when is_integer(I), I > 0 -> - set_xoption(Opts, Config#config{Opt = I}, ServerHost, Lang); + set_xoption(Opts, setelement(Opt, Config, I), ServerHost, Lang); _ -> Txt = <<"Value of '~s' should be integer">>, - ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + OptName = get_config_opt_name(Opt), + ErrTxt = iolist_to_binary(io_lib:format(Txt, [OptName])), {error, xmpp:err_bad_request(ErrTxt, Lang)} end). @@ -3349,10 +3355,11 @@ set_config(#xdata{fields = Fields}, StateData, Lang) -> [Val] -> Val; _ when is_atom(Vals) -> Vals end, - set_xoption(Opts, Config#config{Opt = V}, ServerHost, Lang) + set_xoption(Opts, setelement(Opt, Config, V), ServerHost, Lang) catch _:_ -> Txt = <<"Incorrect value of option '~s'">>, - ErrTxt = iolist_to_binary(io_lib:format(Txt, [Opt])), + OptName = get_config_opt_name(Opt), + ErrTxt = iolist_to_binary(io_lib:format(Txt, [OptName])), {error, xmpp:err_bad_request(ErrTxt, Lang)} end). @@ -3366,7 +3373,7 @@ set_config(#xdata{fields = Fields}, StateData, Lang) -> (_, Set1) -> Set1 end, (?SETS):empty(), Vals), - set_xoption(Opts, Config#config{Opt = Set}, ServerHost, Lang) + set_xoption(Opts, setelement(Opt, Config, Set), ServerHost, Lang) end). -spec set_xoption([{binary(), [binary()]}], #config{}, @@ -3375,35 +3382,35 @@ set_xoption([], Config, _ServerHost, _Lang) -> Config; set_xoption([{<<"muc#roomconfig_roomname">>, Vals} | Opts], Config, ServerHost, Lang) -> - ?SET_STRING_XOPT(title, Vals); + ?SET_STRING_XOPT(#config.title, Vals); set_xoption([{<<"muc#roomconfig_roomdesc">>, Vals} | Opts], Config, ServerHost, Lang) -> - ?SET_STRING_XOPT(description, Vals); + ?SET_STRING_XOPT(#config.description, Vals); set_xoption([{<<"muc#roomconfig_changesubject">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(allow_change_subj, Val); + ?SET_BOOL_XOPT(#config.allow_change_subj, Val); set_xoption([{<<"allow_query_users">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(allow_query_users, Val); + ?SET_BOOL_XOPT(#config.allow_query_users, Val); set_xoption([{<<"allow_private_messages">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(allow_private_messages, Val); + ?SET_BOOL_XOPT(#config.allow_private_messages, Val); set_xoption([{<<"allow_private_messages_from_visitors">>, [Val]} | Opts], Config, ServerHost, Lang) -> case Val of <<"anyone">> -> - ?SET_STRING_XOPT(allow_private_messages_from_visitors, + ?SET_STRING_XOPT(#config.allow_private_messages_from_visitors, anyone); <<"moderators">> -> - ?SET_STRING_XOPT(allow_private_messages_from_visitors, + ?SET_STRING_XOPT(#config.allow_private_messages_from_visitors, moderators); <<"nobody">> -> - ?SET_STRING_XOPT(allow_private_messages_from_visitors, + ?SET_STRING_XOPT(#config.allow_private_messages_from_visitors, nobody); _ -> Txt = <<"Value of 'allow_private_messages_from_visitors' " @@ -3414,58 +3421,58 @@ set_xoption([{<<"muc#roomconfig_allowvisitorstatus">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(allow_visitor_status, Val); + ?SET_BOOL_XOPT(#config.allow_visitor_status, Val); set_xoption([{<<"muc#roomconfig_allowvisitornickchange">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(allow_visitor_nickchange, Val); + ?SET_BOOL_XOPT(#config.allow_visitor_nickchange, Val); set_xoption([{<<"muc#roomconfig_publicroom">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(public, Val); + ?SET_BOOL_XOPT(#config.public, Val); set_xoption([{<<"public_list">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(public_list, Val); + ?SET_BOOL_XOPT(#config.public_list, Val); set_xoption([{<<"muc#roomconfig_persistentroom">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(persistent, Val); + ?SET_BOOL_XOPT(#config.persistent, Val); set_xoption([{<<"muc#roomconfig_moderatedroom">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(moderated, Val); + ?SET_BOOL_XOPT(#config.moderated, Val); set_xoption([{<<"members_by_default">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(members_by_default, Val); + ?SET_BOOL_XOPT(#config.members_by_default, Val); set_xoption([{<<"muc#roomconfig_membersonly">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(members_only, Val); + ?SET_BOOL_XOPT(#config.members_only, Val); set_xoption([{<<"captcha_protected">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(captcha_protected, Val); + ?SET_BOOL_XOPT(#config.captcha_protected, Val); set_xoption([{<<"muc#roomconfig_allowinvites">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(allow_user_invites, Val); + ?SET_BOOL_XOPT(#config.allow_user_invites, Val); set_xoption([{<<"muc#roomconfig_allow_subscription">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(allow_subscription, Val); + ?SET_BOOL_XOPT(#config.allow_subscription, Val); set_xoption([{<<"muc#roomconfig_passwordprotectedroom">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(password_protected, Val); + ?SET_BOOL_XOPT(#config.password_protected, Val); set_xoption([{<<"muc#roomconfig_roomsecret">>, Vals} | Opts], Config, ServerHost, Lang) -> - ?SET_STRING_XOPT(password, Vals); + ?SET_STRING_XOPT(#config.password, Vals); set_xoption([{<<"anonymous">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(anonymous, Val); + ?SET_BOOL_XOPT(#config.anonymous, Val); set_xoption([{<<"muc#roomconfig_presencebroadcast">>, Vals} | Opts], Config, ServerHost, Lang) -> Roles = @@ -3496,21 +3503,21 @@ set_xoption([{<<"muc#roomconfig_allowvoicerequests">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(allow_voice_requests, Val); + ?SET_BOOL_XOPT(#config.allow_voice_requests, Val); set_xoption([{<<"muc#roomconfig_voicerequestmininterval">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_NAT_XOPT(voice_request_min_interval, Val); + ?SET_NAT_XOPT(#config.voice_request_min_interval, Val); set_xoption([{<<"muc#roomconfig_whois">>, [Val]} | Opts], Config, ServerHost, Lang) -> case Val of <<"moderators">> -> - ?SET_BOOL_XOPT(anonymous, + ?SET_BOOL_XOPT(#config.anonymous, (iolist_to_binary(integer_to_list(1)))); <<"anyone">> -> - ?SET_BOOL_XOPT(anonymous, + ?SET_BOOL_XOPT(#config.anonymous, (iolist_to_binary(integer_to_list(0)))); _ -> Txt = <<"Value of 'muc#roomconfig_whois' should be " @@ -3521,19 +3528,19 @@ set_xoption([{<<"muc#roomconfig_maxusers">>, [Val]} | Opts], Config, ServerHost, Lang) -> case Val of - <<"none">> -> ?SET_STRING_XOPT(max_users, none); - _ -> ?SET_NAT_XOPT(max_users, Val) + <<"none">> -> ?SET_STRING_XOPT(#config.max_users, none); + _ -> ?SET_NAT_XOPT(#config.max_users, Val) end; set_xoption([{<<"muc#roomconfig_enablelogging">>, [Val]} | Opts], Config, ServerHost, Lang) -> - ?SET_BOOL_XOPT(logging, Val); + ?SET_BOOL_XOPT(#config.logging, Val); set_xoption([{<<"muc#roomconfig_captcha_whitelist">>, Vals} | Opts], Config, ServerHost, Lang) -> JIDs = [jid:from_string(Val) || Val <- Vals], - ?SET_JIDMULTI_XOPT(captcha_whitelist, JIDs); + ?SET_JIDMULTI_XOPT(#config.captcha_whitelist, JIDs); set_xoption([{<<"FORM_TYPE">>, _} | Opts], Config, ServerHost, Lang) -> set_xoption(Opts, Config, ServerHost, Lang); set_xoption([{Opt, Vals} | Opts], Config, ServerHost, Lang) -> @@ -3752,7 +3759,8 @@ set_opts([{Opt, Val} | Opts], StateData) -> end, set_opts(Opts, NSD). --define(MAKE_CONFIG_OPT(Opt), {Opt, Config#config.Opt}). +-define(MAKE_CONFIG_OPT(Opt), + {get_config_opt_name(Opt), element(Opt, Config)}). -spec make_opts(state()) -> [{atom(), any()}]. make_opts(StateData) -> @@ -3764,27 +3772,27 @@ make_opts(StateData) -> (_, _, Acc) -> Acc end, [], StateData#state.users), - [?MAKE_CONFIG_OPT(title), ?MAKE_CONFIG_OPT(description), - ?MAKE_CONFIG_OPT(allow_change_subj), - ?MAKE_CONFIG_OPT(allow_query_users), - ?MAKE_CONFIG_OPT(allow_private_messages), - ?MAKE_CONFIG_OPT(allow_private_messages_from_visitors), - ?MAKE_CONFIG_OPT(allow_visitor_status), - ?MAKE_CONFIG_OPT(allow_visitor_nickchange), - ?MAKE_CONFIG_OPT(public), ?MAKE_CONFIG_OPT(public_list), - ?MAKE_CONFIG_OPT(persistent), - ?MAKE_CONFIG_OPT(moderated), - ?MAKE_CONFIG_OPT(members_by_default), - ?MAKE_CONFIG_OPT(members_only), - ?MAKE_CONFIG_OPT(allow_user_invites), - ?MAKE_CONFIG_OPT(password_protected), - ?MAKE_CONFIG_OPT(captcha_protected), - ?MAKE_CONFIG_OPT(password), ?MAKE_CONFIG_OPT(anonymous), - ?MAKE_CONFIG_OPT(logging), ?MAKE_CONFIG_OPT(max_users), - ?MAKE_CONFIG_OPT(allow_voice_requests), - ?MAKE_CONFIG_OPT(mam), - ?MAKE_CONFIG_OPT(voice_request_min_interval), - ?MAKE_CONFIG_OPT(vcard), + [?MAKE_CONFIG_OPT(#config.title), ?MAKE_CONFIG_OPT(#config.description), + ?MAKE_CONFIG_OPT(#config.allow_change_subj), + ?MAKE_CONFIG_OPT(#config.allow_query_users), + ?MAKE_CONFIG_OPT(#config.allow_private_messages), + ?MAKE_CONFIG_OPT(#config.allow_private_messages_from_visitors), + ?MAKE_CONFIG_OPT(#config.allow_visitor_status), + ?MAKE_CONFIG_OPT(#config.allow_visitor_nickchange), + ?MAKE_CONFIG_OPT(#config.public), ?MAKE_CONFIG_OPT(#config.public_list), + ?MAKE_CONFIG_OPT(#config.persistent), + ?MAKE_CONFIG_OPT(#config.moderated), + ?MAKE_CONFIG_OPT(#config.members_by_default), + ?MAKE_CONFIG_OPT(#config.members_only), + ?MAKE_CONFIG_OPT(#config.allow_user_invites), + ?MAKE_CONFIG_OPT(#config.password_protected), + ?MAKE_CONFIG_OPT(#config.captcha_protected), + ?MAKE_CONFIG_OPT(#config.password), ?MAKE_CONFIG_OPT(#config.anonymous), + ?MAKE_CONFIG_OPT(#config.logging), ?MAKE_CONFIG_OPT(#config.max_users), + ?MAKE_CONFIG_OPT(#config.allow_voice_requests), + ?MAKE_CONFIG_OPT(#config.mam), + ?MAKE_CONFIG_OPT(#config.voice_request_min_interval), + ?MAKE_CONFIG_OPT(#config.vcard), {captcha_whitelist, (?SETS):to_list((StateData#state.config)#config.captcha_whitelist)}, {affiliations, diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 4d597a52c..03eb3c59a 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -297,7 +297,8 @@ get_sm_items(_Acc, #jid{luser = U, lserver = S, lresource = R} = JID, get_sm_items(Acc, _From, _To, _Node, _Lang) -> Acc. --spec get_info([xdata()], jid(), jid(), binary(), binary()) -> [xdata()]. +-spec get_info([xdata()], binary(), module(), binary(), binary()) -> [xdata()]; + ([xdata()], jid(), jid(), binary(), binary()) -> [xdata()]. get_info(_Acc, #jid{luser = U, lserver = S, lresource = R}, #jid{luser = U, lserver = S}, ?NS_FLEX_OFFLINE, _Lang) -> N = jlib:integer_to_binary(count_offline_messages(U, S)), @@ -570,11 +571,13 @@ remove_old_messages(Days, Server) -> Mod = gen_mod:db_mod(LServer, ?MODULE), Mod:remove_old_messages(Days, LServer). +-spec remove_user(binary(), binary()) -> ok. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:remove_user(LUser, LServer). + Mod:remove_user(LUser, LServer), + ok. %% Helper functions: diff --git a/src/mod_ping.erl b/src/mod_ping.erl index b09ca9ab2..5e861b7f7 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -207,11 +207,11 @@ iq_ping(#iq{lang = Lang} = IQ) -> Txt = <<"Ping query is incorrect">>, xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang)). --spec user_online(ejabberd_sm:sid(), jid(), any()) -> ok. +-spec user_online(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> ok. user_online(_SID, JID, _Info) -> start_ping(JID#jid.lserver, JID). --spec user_offline(ejabberd_sm:sid(), jid(), any()) -> ok. +-spec user_offline(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> ok. user_offline(_SID, JID, _Info) -> stop_ping(JID#jid.lserver, JID). diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 1da040d43..f94c422b3 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -515,6 +515,7 @@ is_type_match(Type, Value, JID, Subscription, Groups) -> group -> lists:member(Value, Groups) end. +-spec remove_user(binary(), binary()) -> any(). remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), diff --git a/src/mod_private.erl b/src/mod_private.erl index 6236b1012..565500d4a 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -117,6 +117,7 @@ get_data(LUser, LServer) -> Mod = gen_mod:db_mod(LServer, ?MODULE), Mod:get_all_data(LUser, LServer). +-spec remove_user(binary(), binary()) -> any(). remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 81afc9a06..0796a20bb 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -660,6 +660,7 @@ disco_items(Host, Node, From) -> %% presence hooks handling functions %% +-spec caps_add(jid(), jid(), [binary()]) -> ok. caps_add(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) when Host =/= S -> %% When a remote contact goes online while the local user is offline, the @@ -675,9 +676,11 @@ caps_add(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID caps_add(_From, _To, _Feature) -> ok. +-spec caps_update(jid(), jid(), [binary()]) -> ok. caps_update(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) -> presence(Host, {presence, U, S, [R], JID}). +-spec presence_probe(jid(), jid(), pid()) -> ok. presence_probe(#jid{luser = U, lserver = S, lresource = R} = JID, JID, Pid) -> presence(S, {presence, JID, Pid}), presence(S, {presence, U, S, [R], JID}); @@ -697,12 +700,16 @@ presence(ServerHost, Presence) -> undefined -> init_send_loop(ServerHost); Pid -> {Pid, undefined} end, - SendLoop ! Presence. + SendLoop ! Presence, + ok. %% ------- %% subscription hooks handling functions %% +-spec out_subscription( + binary(), binary(), jid(), + subscribed | unsubscribed | subscribe | unsubscribe) -> boolean(). out_subscription(User, Server, JID, subscribed) -> Owner = jid:make(User, Server, <<>>), {PUser, PServer, PResource} = jid:tolower(JID), @@ -763,6 +770,7 @@ unsubscribe_user(Host, Entity, Owner) -> %% user remove hook handling function %% +-spec remove_user(binary(), binary()) -> ok. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), @@ -802,7 +810,8 @@ remove_user(User, Server) -> Affs) end, plugins(Host)) - end). + end), + ok. handle_call(server_host, _From, State) -> {reply, State#state.server_host, State}; @@ -4224,11 +4233,12 @@ extended_headers(Jids) -> attrs = [{<<"type">>, <<"replyto">>}, {<<"jid">>, Jid}]} || Jid <- Jids]. +-spec on_user_offline(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> ok. on_user_offline(_, JID, _) -> {User, Server, Resource} = jid:tolower(JID), case user_resources(User, Server) of [] -> purge_offline({User, Server, Resource}); - _ -> true + _ -> ok end. purge_offline(LJID) -> diff --git a/src/mod_register.erl b/src/mod_register.erl index 1ed266d47..334af4514 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -74,6 +74,7 @@ stop(Host) -> depends(_Host, _Opts) -> []. +-spec stream_feature_register([xmpp_element()], binary()) -> [xmpp_element()]. stream_feature_register(Acc, Host) -> AF = gen_mod:get_module_opt(Host, ?MODULE, access_from, fun(A) -> A end, @@ -85,6 +86,9 @@ stream_feature_register(Acc, Host) -> Acc end. +-spec unauthenticated_iq_register(empty | iq(), binary(), iq(), + {inet:ip_address(), non_neg_integer()}) -> + empty | iq(). unauthenticated_iq_register(_Acc, Server, #iq{sub_els = [#register{}]} = IQ, IP) -> Address = case IP of diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 51fe08ba5..c118a61ff 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -452,6 +452,9 @@ in_subscription(_, User, Server, JID, Type, Reason) -> process_subscription(in, User, Server, JID, Type, Reason). +-spec out_subscription( + binary(), binary(), jid(), + subscribed | unsubscribed | subscribe | unsubscribe) -> boolean(). out_subscription(User, Server, JID, Type) -> process_subscription(out, User, Server, JID, Type, <<"">>). @@ -643,12 +646,14 @@ in_auto_reply(from, out, unsubscribe) -> unsubscribed; in_auto_reply(both, none, unsubscribe) -> unsubscribed; in_auto_reply(_, _, _) -> none. +-spec remove_user(binary(), binary()) -> ok. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), send_unsubscription_to_rosteritems(LUser, LServer), Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:remove_user(LUser, LServer). + Mod:remove_user(LUser, LServer), + ok. %% For each contact with Subscription: %% Both or From, send a "unsubscribed" presence stanza; diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 079a2f44c..ac3717bd3 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -336,6 +336,9 @@ in_subscription(Acc, User, Server, JID, Type, _Reason) -> process_subscription(in, User, Server, JID, Type, Acc). +-spec out_subscription( + binary(), binary(), jid(), + subscribed | unsubscribed | subscribe | unsubscribe) -> boolean(). out_subscription(UserFrom, ServerFrom, JIDTo, unsubscribed) -> #jid{luser = UserTo, lserver = ServerTo} = JIDTo, @@ -629,12 +632,15 @@ broadcast_members_to_user(LUser, LServer, Group, Host, Subscription) -> broadcast_subscription(U, S, {LUser, LServer, <<"">>}, Subscription) end, Members). +-spec register_user(binary(), binary()) -> ok. register_user(User, Server) -> Groups = get_user_groups({User, Server}), [push_user_to_displayed(User, Server, Group, Server, both, displayed_to_groups(Group, Server)) - || Group <- Groups]. + || Group <- Groups], + ok. +-spec remove_user(binary(), binary()) -> ok. remove_user(User, Server) -> push_user_to_members(User, Server, remove). @@ -724,6 +730,7 @@ push_roster_item(User, Server, ContactU, ContactS, groups = [GroupName]}, push_item(User, Server, Item). +-spec user_available(jid()) -> ok. user_available(New) -> LUser = New#jid.luser, LServer = New#jid.lserver, @@ -747,6 +754,7 @@ user_available(New) -> _ -> ok end. +-spec unset_presence(binary(), binary(), binary(), binary()) -> ok. unset_presence(LUser, LServer, Resource, Status) -> Resources = ejabberd_sm:get_user_resources(LUser, LServer), diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index 06dd0e3a9..809887237 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -191,6 +191,9 @@ in_subscription(Acc, User, Server, JID, Type, _Reason) -> process_subscription(in, User, Server, JID, Type, Acc). +-spec out_subscription( + binary(), binary(), jid(), + subscribed | unsubscribed | subscribe | unsubscribe) -> boolean(). out_subscription(User, Server, JID, Type) -> process_subscription(out, User, Server, JID, Type, false). diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index 27ea8461a..5cc87056e 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -51,11 +51,12 @@ depends(_Host, _Opts) -> %%==================================================================== %% Hooks %%==================================================================== - +-spec update_presence(presence(), binary(), binary()) -> presence(). update_presence(#presence{type = undefined} = Packet, User, Host) -> presence_with_xupdate(Packet, User, Host); update_presence(Packet, _User, _Host) -> Packet. +-spec vcard_set(binary(), binary(), xmlel()) -> ok. vcard_set(LUser, LServer, VCARD) -> US = {LUser, LServer}, case fxml:get_path_s(VCARD, diff --git a/src/node_online.erl b/src/node_online.erl index 4b01d2a2c..2620e6a49 100644 --- a/src/node_online.erl +++ b/src/node_online.erl @@ -57,6 +57,7 @@ terminate(Host, ServerHost) -> ?MODULE, user_offline, 75), ok. +-spec user_offline(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> _. user_offline(_SID, #jid{luser=LUser,lserver=LServer}, _Info) -> mod_pubsub:remove_user(LUser, LServer). diff --git a/src/xmpp.erl b/src/xmpp.erl index c81474f10..8dbc49532 100644 --- a/src/xmpp.erl +++ b/src/xmpp.erl @@ -134,7 +134,7 @@ get_type(#message{type = T}) -> T; get_type(#presence{type = T}) -> T; get_type(#xmlel{attrs = Attrs}) -> fxml:get_attr_s(<<"type">>, Attrs). --spec get_lang(iq() | message() | presence()) -> binary(). +-spec get_lang(iq() | message() | presence() | xmlel()) -> binary(). get_lang(#iq{lang = L}) -> L; get_lang(#message{lang = L}) -> L; get_lang(#presence{lang = L}) -> L; diff --git a/src/xmpp_codec.erl b/src/xmpp_codec.erl index 905e48f3c..afe6ff1ad 100644 --- a/src/xmpp_codec.erl +++ b/src/xmpp_codec.erl @@ -3483,6 +3483,12 @@ dec_bool(<<"0">>) -> false; dec_bool(<<"true">>) -> true; dec_bool(<<"1">>) -> true. +nameprep(S) -> + case jid:nameprep(S) of + error -> erlang:error(badarg); + S1 -> S1 + end. + resourceprep(R) -> case jid:resourceprep(R) of error -> erlang:error(badarg); @@ -4887,7 +4893,7 @@ decode_db_verify_attr_from(__TopXMLNS, undefined) -> {missing_attr, <<"from">>, <<"db:verify">>, __TopXMLNS}}); decode_db_verify_attr_from(__TopXMLNS, _val) -> - case catch dec_jid(_val) of + case catch nameprep(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"from">>, <<"db:verify">>, @@ -4896,13 +4902,13 @@ decode_db_verify_attr_from(__TopXMLNS, _val) -> end. encode_db_verify_attr_from(_val, _acc) -> - [{<<"from">>, enc_jid(_val)} | _acc]. + [{<<"from">>, nameprep(_val)} | _acc]. decode_db_verify_attr_to(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"to">>, <<"db:verify">>, __TopXMLNS}}); decode_db_verify_attr_to(__TopXMLNS, _val) -> - case catch dec_jid(_val) of + case catch nameprep(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"to">>, <<"db:verify">>, @@ -4911,7 +4917,7 @@ decode_db_verify_attr_to(__TopXMLNS, _val) -> end. encode_db_verify_attr_to(_val, _acc) -> - [{<<"to">>, enc_jid(_val)} | _acc]. + [{<<"to">>, nameprep(_val)} | _acc]. decode_db_verify_attr_id(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, @@ -5014,7 +5020,7 @@ decode_db_result_attr_from(__TopXMLNS, undefined) -> {missing_attr, <<"from">>, <<"db:result">>, __TopXMLNS}}); decode_db_result_attr_from(__TopXMLNS, _val) -> - case catch dec_jid(_val) of + case catch nameprep(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"from">>, <<"db:result">>, @@ -5023,13 +5029,13 @@ decode_db_result_attr_from(__TopXMLNS, _val) -> end. encode_db_result_attr_from(_val, _acc) -> - [{<<"from">>, enc_jid(_val)} | _acc]. + [{<<"from">>, nameprep(_val)} | _acc]. decode_db_result_attr_to(__TopXMLNS, undefined) -> erlang:error({xmpp_codec, {missing_attr, <<"to">>, <<"db:result">>, __TopXMLNS}}); decode_db_result_attr_to(__TopXMLNS, _val) -> - case catch dec_jid(_val) of + case catch nameprep(_val) of {'EXIT', _} -> erlang:error({xmpp_codec, {bad_attr_value, <<"to">>, <<"db:result">>, @@ -5038,7 +5044,7 @@ decode_db_result_attr_to(__TopXMLNS, _val) -> end. encode_db_result_attr_to(_val, _acc) -> - [{<<"to">>, enc_jid(_val)} | _acc]. + [{<<"to">>, nameprep(_val)} | _acc]. decode_db_result_attr_type(__TopXMLNS, undefined) -> undefined; diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 0b8f3b668..d410a7613 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -2860,9 +2860,9 @@ result = {db_result, '$from', '$to', '$type', '$key', '$_els'}, cdata = #cdata{default = <<"">>, label = '$key'}, attrs = [#attr{name = <<"from">>, required = true, - dec = {dec_jid, []}, enc = {enc_jid, []}}, + dec = {nameprep, []}, enc = {nameprep, []}}, #attr{name = <<"to">>, required = true, - dec = {dec_jid, []}, enc = {enc_jid, []}}, + dec = {nameprep, []}, enc = {nameprep, []}}, #attr{name = <<"type">>, dec = {dec_enum, [[valid, invalid, error]]}, enc = {enc_enum, []}}]}). @@ -2873,9 +2873,9 @@ result = {db_verify, '$from', '$to', '$id', '$type', '$key', '$_els'}, cdata = #cdata{default = <<"">>, label = '$key'}, attrs = [#attr{name = <<"from">>, required = true, - dec = {dec_jid, []}, enc = {enc_jid, []}}, + dec = {nameprep, []}, enc = {nameprep, []}}, #attr{name = <<"to">>, required = true, - dec = {dec_jid, []}, enc = {enc_jid, []}}, + dec = {nameprep, []}, enc = {nameprep, []}}, #attr{name = <<"id">>, required = true}, #attr{name = <<"type">>, dec = {dec_enum, [[valid, invalid, error]]}, @@ -3113,6 +3113,15 @@ resourceprep(R) -> R1 end. +-spec nameprep(_) -> binary(). +nameprep(S) -> + case jid:nameprep(S) of + error -> + erlang:error(badarg); + S1 -> + S1 + end. + -spec dec_bool(_) -> boolean(). dec_bool(<<"false">>) -> false; dec_bool(<<"0">>) -> false; @@ -3137,7 +3146,7 @@ enc_ip({0,0,0,0,0,16#ffff,A,B}) -> enc_ip(Addr) -> list_to_binary(inet_parse:ntoa(Addr)). --spec re:split(_, _) -> binary(). +-spec re:split(_, _) -> [binary()]. -spec base64:decode(_) -> binary(). -spec dec_host_port(_) -> binary() | inet:ip_address() | -- 2.40.0