aboutsummaryrefslogtreecommitdiff
path: root/src/mod_roster.erl
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-01-09 17:02:17 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-01-09 17:02:17 +0300
commit1e55e018e534aa82541c5f460063a237192b768c (patch)
tree9584ed46fe2b18770343399254b0ba15ff591e51 /src/mod_roster.erl
parentGet rid of "jlib.hrl" header in some files (diff)
Adopt remaining code to support new hooks
Diffstat (limited to 'src/mod_roster.erl')
-rw-r--r--src/mod_roster.erl169
1 files changed, 96 insertions, 73 deletions
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.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%