From 1e55e018e534aa82541c5f460063a237192b768c Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 9 Jan 2017 17:02:17 +0300 Subject: Adopt remaining code to support new hooks --- src/mod_roster.erl | 169 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 96 insertions(+), 73 deletions(-) (limited to 'src/mod_roster.erl') diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 5c207f3a4..085f50225 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -43,9 +43,9 @@ -export([start/2, stop/1, process_iq/1, export/1, import_info/0, process_local_iq/1, get_user_roster/2, - import/5, get_subscription_lists/3, get_roster/2, - import_start/2, import_stop/2, c2s_handle_info/2, - get_in_pending_subscriptions/3, in_subscription/6, + import/5, c2s_session_opened/1, get_roster/2, + import_start/2, import_stop/2, user_receive_packet/1, + c2s_self_presence/1, in_subscription/6, out_subscription/4, set_items/3, remove_user/2, get_jid_info/4, encode_item/1, webadmin_page/3, webadmin_user/4, get_versioning_feature/2, @@ -94,24 +94,24 @@ start(Host, Opts) -> ?MODULE, in_subscription, 50), ejabberd_hooks:add(roster_out_subscription, Host, ?MODULE, out_subscription, 50), - ejabberd_hooks:add(roster_get_subscription_lists, Host, - ?MODULE, get_subscription_lists, 50), + ejabberd_hooks:add(c2s_session_opened, Host, ?MODULE, + c2s_session_opened, 50), ejabberd_hooks:add(roster_get_jid_info, Host, ?MODULE, get_jid_info, 50), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), - ejabberd_hooks:add(resend_subscription_requests_hook, - Host, ?MODULE, get_in_pending_subscriptions, 50), + ejabberd_hooks:add(c2s_self_presence, Host, ?MODULE, + c2s_self_presence, 50), ejabberd_hooks:add(c2s_post_auth_features, Host, ?MODULE, get_versioning_feature, 50), ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, webadmin_page, 50), ejabberd_hooks:add(webadmin_user, Host, ?MODULE, webadmin_user, 50), - ejabberd_hooks:add(c2s_handle_info, Host, ?MODULE, - c2s_handle_info, 50), + ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, + user_receive_packet, 50), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER, ?MODULE, process_iq, IQDisc). @@ -122,24 +122,24 @@ stop(Host) -> ?MODULE, in_subscription, 50), ejabberd_hooks:delete(roster_out_subscription, Host, ?MODULE, out_subscription, 50), - ejabberd_hooks:delete(roster_get_subscription_lists, - Host, ?MODULE, get_subscription_lists, 50), + ejabberd_hooks:delete(c2s_session_opened, Host, ?MODULE, + c2s_session_opened, 50), ejabberd_hooks:delete(roster_get_jid_info, Host, ?MODULE, get_jid_info, 50), ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), - ejabberd_hooks:delete(resend_subscription_requests_hook, - Host, ?MODULE, get_in_pending_subscriptions, 50), + ejabberd_hooks:delete(c2s_self_presence, Host, ?MODULE, + c2s_self_presence, 50), ejabberd_hooks:delete(c2s_post_auth_features, Host, ?MODULE, get_versioning_feature, 50), ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, webadmin_page, 50), ejabberd_hooks:delete(webadmin_user, Host, ?MODULE, webadmin_user, 50), - ejabberd_hooks:delete(c2s_handle_info, Host, ?MODULE, - c2s_handle_info, 50), + ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, + user_receive_packet, 50), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER). @@ -220,10 +220,16 @@ roster_version_on_db(Host) -> %% Returns a list that may contain an xmlelement with the XEP-237 feature if it's enabled. -spec get_versioning_feature([xmpp_element()], binary()) -> [xmpp_element()]. get_versioning_feature(Acc, Host) -> - case roster_versioning_enabled(Host) of - true -> - [#rosterver_feature{}|Acc]; - false -> [] + case gen_mod:is_loaded(Host, ?MODULE) of + true -> + case roster_versioning_enabled(Host) of + true -> + [#rosterver_feature{}|Acc]; + false -> + Acc + end; + false -> + Acc end. roster_version(LServer, LUser) -> @@ -423,8 +429,6 @@ process_iq_set(#iq{from = From, to = To, end. push_item(User, Server, From, Item) -> - ejabberd_sm:route(jid:make(User, Server, <<"">>), - {item, Item#roster.jid, Item#roster.subscription}), case roster_versioning_enabled(Server) of true -> push_item_version(Server, User, From, Item, @@ -446,15 +450,12 @@ push_item(User, Server, Resource, From, Item, not_found -> undefined; _ -> RosterVersion end, - ResIQ = #iq{type = set, -%% @doc Roster push, calculate and include the version attribute. -%% TODO: don't push to those who didn't load roster + To = jid:make(User, Server, Resource), + ResIQ = #iq{type = set, from = From, to = To, id = <<"push", (randoms:get_string())/binary>>, sub_els = [#roster_query{ver = Ver, items = [encode_item(Item)]}]}, - ejabberd_router:route(From, - jid:make(User, Server, Resource), - ResIQ). + ejabberd_router:route(From, To, xmpp:put_meta(ResIQ, roster_item, Item)). push_item_version(Server, User, From, Item, RosterVersion) -> @@ -464,19 +465,19 @@ push_item_version(Server, User, From, Item, end, ejabberd_sm:get_user_resources(User, Server)). -c2s_handle_info(State, {item, JID, Sub}) -> - {stop, roster_change(State, JID, Sub)}; -c2s_handle_info(State, _) -> - State. +-spec user_receive_packet({stanza(), ejabberd_c2s:state()}) -> {stanza(), ejabberd_c2s:state()}. +user_receive_packet({#iq{type = set, meta = #{roster_item := Item}} = IQ, State}) -> + {IQ, roster_change(State, Item)}; +user_receive_packet(Acc) -> + Acc. --spec roster_change(ejabberd_c2s:state(), jid(), subscription()) -> ejabberd_c2s:state(). -roster_change(#{user := U, server := S, resource := R} = State, - IJID, ISubscription) -> +-spec roster_change(ejabberd_c2s:state(), #roster{}) -> ejabberd_c2s:state(). +roster_change(#{user := U, server := S, resource := R, + pres_a := PresA, pres_f := PresF, pres_t := PresT} = State, + #roster{jid = IJID, subscription = ISubscription}) -> LIJID = jid:tolower(IJID), IsFrom = (ISubscription == both) or (ISubscription == from), IsTo = (ISubscription == both) or (ISubscription == to), - PresF = maps:get(pres_f, State, ?SETS:new()), - PresT = maps:get(pres_t, State, ?SETS:new()), OldIsFrom = ?SETS:is_element(LIJID, PresF), FSet = if IsFrom -> ?SETS:add_element(LIJID, PresF); true -> ?SETS:del_element(LIJID, PresF) @@ -490,7 +491,6 @@ roster_change(#{user := U, server := S, resource := R} = State, State1; LastPres -> From = jid:make(U, S, R), - PresA = maps:get(pres_a, State1, ?SETS:new()), To = jid:make(IJID), Cond1 = IsFrom andalso not OldIsFrom, Cond2 = not IsFrom andalso OldIsFrom andalso @@ -507,7 +507,7 @@ roster_change(#{user := U, server := S, resource := R} = State, end, A = ?SETS:add_element(LIJID, PresA), State1#{pres_a => A}; - Cond2 -> + Cond2 -> PU = #presence{from = From, to = To, type = unavailable}, case ejabberd_hooks:run_fold( privacy_check_packet, allow, @@ -524,26 +524,29 @@ roster_change(#{user := U, server := S, resource := R} = State, end end. --spec get_subscription_lists({[ljid()], [ljid()]}, binary(), binary()) - -> {[ljid()], [ljid()]}. -get_subscription_lists(_Acc, User, Server) -> - LUser = jid:nodeprep(User), - LServer = jid:nameprep(Server), +-spec c2s_session_opened(ejabberd_c2s:state()) -> ejabberd_c2s:state(). +c2s_session_opened(#{jid := #jid{luser = LUser, lserver = LServer} = JID, + pres_f := PresF, pres_t := PresT} = State) -> Mod = gen_mod:db_mod(LServer, ?MODULE), Items = Mod:get_only_items(LUser, LServer), - fill_subscription_lists(LServer, Items, [], []). + {F, T} = fill_subscription_lists(Items, PresF, PresT), + LJID = jid:tolower(jid:remove_resource(JID)), + State#{pres_f => ?SETS:add(LJID, F), pres_t => ?SETS:add(LJID, T)}. -fill_subscription_lists(LServer, [I | Is], F, T) -> +fill_subscription_lists([I | Is], F, T) -> J = element(3, I#roster.usj), - case I#roster.subscription of - both -> - fill_subscription_lists(LServer, Is, [J | F], [J | T]); - from -> - fill_subscription_lists(LServer, Is, [J | F], T); - to -> fill_subscription_lists(LServer, Is, F, [J | T]); - _ -> fill_subscription_lists(LServer, Is, F, T) - end; -fill_subscription_lists(_LServer, [], F, T) -> + {F1, T1} = case I#roster.subscription of + both -> + {?SETS:add_element(J, F), ?SETS:add_element(J, T)}; + from -> + {?SETS:add_element(J, F), T}; + to -> + {F, ?SETS:add_element(J, T)}; + _ -> + {F, T} + end, + fill_subscription_lists(Is, F1, T1); +fill_subscription_lists([], F, T) -> {F, T}. ask_to_pending(subscribe) -> out; @@ -836,27 +839,47 @@ process_item_set_t(LUser, LServer, #roster_item{jid = JID1} = QueryItem) -> end; process_item_set_t(_LUser, _LServer, _) -> ok. --spec get_in_pending_subscriptions([presence()], binary(), binary()) -> [presence()]. -get_in_pending_subscriptions(Ls, User, Server) -> - LServer = jid:nameprep(Server), - Mod = gen_mod:db_mod(LServer, ?MODULE), - get_in_pending_subscriptions(Ls, User, Server, Mod). +-spec c2s_self_presence({presence(), ejabberd_c2s:state()}) + -> {presence(), ejabberd_c2s:state()}. +c2s_self_presence({_, #{pres_last := _}} = Acc) -> + Acc; +c2s_self_presence({#presence{type = available} = Pkt, + #{lserver := LServer} = State}) -> + Prio = get_priority_from_presence(Pkt), + if Prio >= 0 -> + Mod = gen_mod:db_mod(LServer, ?MODULE), + State1 = resend_pending_subscriptions(State, Mod), + {Pkt, State1}; + true -> + {Pkt, State} + end; +c2s_self_presence(Acc) -> + Acc. -get_in_pending_subscriptions(Ls, User, Server, Mod) -> - JID = jid:make(User, Server, <<"">>), +-spec resend_pending_subscriptions(ejabberd_c2s:state(), module()) -> ejabberd_c2s:state(). +resend_pending_subscriptions(#{jid := JID} = State, Mod) -> + BareJID = jid:remove_resource(JID), Result = Mod:get_only_items(JID#jid.luser, JID#jid.lserver), - Ls ++ lists:flatmap( - fun(#roster{ask = Ask} = R) when Ask == in; Ask == both -> - Message = R#roster.askmessage, - Status = if is_binary(Message) -> (Message); - true -> <<"">> - end, - [#presence{from = R#roster.jid, to = JID, - type = subscribe, - status = xmpp:mk_text(Status)}]; - (_) -> - [] - end, Result). + lists:foldl( + fun(#roster{ask = Ask} = R, AccState) when Ask == in; Ask == both -> + Message = R#roster.askmessage, + Status = if is_binary(Message) -> (Message); + true -> <<"">> + end, + Sub = #presence{from = R#roster.jid, to = BareJID, + type = subscribe, + status = xmpp:mk_text(Status)}, + ejabberd_c2s:send(AccState, Sub); + (_, AccState) -> + AccState + end, State, Result). + +-spec get_priority_from_presence(presence()) -> integer(). +get_priority_from_presence(#presence{priority = Prio}) -> + case Prio of + undefined -> 0; + _ -> Prio + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3