-export([start/2, stop/1, reload/3, process_iq/1, export/1,
import_info/0, process_local_iq/1, get_user_roster/2,
- import/5, get_roster/2,
+ import/5, get_roster/2, push_item/3,
import_start/2, import_stop/2,
c2s_self_presence/1, in_subscription/2,
out_subscription/1, set_items/3, remove_user/2,
process_iq_set(#iq{from = _From, to = To,
sub_els = [#roster_query{items = [QueryItem]}]} = IQ) ->
- #jid{user = User, luser = LUser, lserver = LServer} = To,
+ #jid{luser = LUser, lserver = LServer} = To,
LJID = jid:tolower(QueryItem#roster_item.jid),
F = fun () ->
Item = get_roster_item(LUser, LServer, LJID),
end,
case transaction(LUser, LServer, [LJID], F) of
{atomic, {OldItem, Item}} ->
- push_item(User, LServer, To, OldItem, Item),
+ push_item(To, OldItem, Item),
case Item#roster.subscription of
remove ->
send_unsubscribing_presence(To, OldItem);
xmpp:make_error(IQ, xmpp:err_internal_server_error())
end.
-push_item(User, Server, From, OldItem, NewItem) ->
- case roster_versioning_enabled(Server) of
- true ->
- push_item_version(Server, User, From, OldItem, NewItem,
- roster_version(Server, User));
- false ->
- lists:foreach(
- fun(Resource) ->
- push_item(User, Server, Resource, From, OldItem, NewItem)
- end, ejabberd_sm:get_user_resources(User, Server))
- end.
-
-push_item(User, Server, Resource, From, OldItem, NewItem) ->
- push_item(User, Server, Resource, From, OldItem, NewItem, undefined).
-
-push_item(User, Server, Resource, From, OldItem, NewItem, Ver) ->
- To = jid:make(User, Server, Resource),
- route_presence_change(To, OldItem, NewItem),
- ResIQ = #iq{type = set, from = From, to = To,
- id = <<"push", (randoms:get_string())/binary>>,
- sub_els = [#roster_query{ver = Ver,
- items = [encode_item(NewItem)]}]},
- ejabberd_router:route(ResIQ).
-
-push_item_version(Server, User, From, OldItem, NewItem, RosterVersion) ->
+push_item(To, OldItem, NewItem) ->
+ #jid{luser = LUser, lserver = LServer} = To,
+ Ver = case roster_versioning_enabled(LServer) of
+ true -> roster_version(LServer, LUser);
+ false -> undefined
+ end,
lists:foreach(
fun(Resource) ->
- push_item(User, Server, Resource, From,
- OldItem, NewItem, RosterVersion)
- end, ejabberd_sm:get_user_resources(User, Server)).
+ To1 = jid:replace_resource(To, Resource),
+ push_item(To1, OldItem, NewItem, Ver)
+ end, ejabberd_sm:get_user_resources(LUser, LServer)).
+
+push_item(To, OldItem, NewItem, Ver) ->
+ route_presence_change(To, OldItem, NewItem),
+ IQ = #iq{type = set, to = To,
+ from = jid:remove_resource(To),
+ id = <<"push", (randoms:get_string())/binary>>,
+ sub_els = [#roster_query{ver = Ver,
+ items = [encode_item(NewItem)]}]},
+ ejabberd_router:route(IQ).
-spec route_presence_change(jid(), #roster{}, #roster{}) -> ok.
route_presence_change(From, OldItem, NewItem) ->
NewItem#roster.ask == in ->
ok;
true ->
- push_item(User, Server,
- jid:make(User, Server), OldItem, NewItem)
+ push_item(jid:make(User, Server), OldItem, NewItem)
end,
true;
none ->
DisplayedGroups = get_displayed_groups(Group, LServer),
push_user_to_displayed(LUser, LServer, Group, Host, both, DisplayedToGroups),
push_displayed_to_user(LUser, LServer, Host, both, DisplayedGroups),
- broadcast_user_to_displayed(LUser, LServer, Host, both, DisplayedToGroups),
- broadcast_displayed_to_user(LUser, LServer, Host, both, DisplayedGroups),
Mod = gen_mod:db_mod(Host, ?MODULE),
Mod:add_user_to_group(Host, US, Group)
end.
GroupOpts = proplists:get_value(Group, GroupsOpts, []),
proplists:get_value(displayed_groups, GroupOpts, []).
-broadcast_displayed_to_user(LUser, LServer, Host, Subscription, DisplayedGroups) ->
- [broadcast_members_to_user(LUser, LServer, DGroup, Host,
- Subscription)
- || DGroup <- DisplayedGroups].
-
push_displayed_to_user(LUser, LServer, Host, Subscription, DisplayedGroups) ->
[push_members_to_user(LUser, LServer, DGroup, Host,
Subscription)
end,
Members).
-broadcast_members_to_user(LUser, LServer, Group, Host, Subscription) ->
- Members = get_group_users(Host, Group),
- lists:foreach(
- fun({U, S}) ->
- 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}),
GroupName, Subscription)
|| GroupD <- DisplayedToGroupsOpts].
-broadcast_user_to_displayed(LUser, LServer, Host, Subscription, DisplayedToGroupsOpts) ->
- [broadcast_user_to_group(LUser, LServer, GroupD, Host, Subscription)
- || GroupD <- DisplayedToGroupsOpts].
-
push_user_to_group(LUser, LServer, Group, Host,
GroupName, Subscription) ->
lists:foreach(fun ({U, S})
end,
get_group_users(Host, Group)).
-broadcast_user_to_group(LUser, LServer, Group, Host, Subscription) ->
- lists:foreach(
- fun({U, S}) when (U == LUser) and (S == LServer) -> ok;
- ({U, S}) ->
- broadcast_subscription(LUser, LServer, {U, S, <<"">>}, Subscription)
- end, get_group_users(Host, Group)).
-
%% Get list of groups to which this group is displayed
displayed_to_groups(GroupName, LServer) ->
GroupsOpts = groups_with_opts(LServer),
[Name || {Name, _} <- Gs].
push_item(User, Server, Item) ->
- Stanza = #iq{type = set, id = <<"push", (randoms:get_string())/binary>>,
- sub_els = [#roster_query{
- items = [mod_roster:encode_item(Item)]}]},
- lists:foreach(fun (Resource) ->
- JID = jid:make(User, Server, Resource),
- ejabberd_router:route(
- xmpp:set_from_to(Stanza, jid:remove_resource(JID), JID))
- end,
- ejabberd_sm:get_user_resources(User, Server)).
+ mod_roster:push_item(jid:make(User, Server),
+ Item#roster{subscription = none},
+ Item).
push_roster_item(User, Server, ContactU, ContactS,
GroupName, Subscription) ->
-spec c2s_self_presence({presence(), ejabberd_c2s:state()})
-> {presence(), ejabberd_c2s:state()}.
-c2s_self_presence({_, #{pres_last := _}} = Acc) ->
- %% This is just a presence update, nothing to do
- Acc;
-c2s_self_presence({#presence{type = available}, #{jid := New}} = Acc) ->
- LUser = New#jid.luser,
- LServer = New#jid.lserver,
- Resources = ejabberd_sm:get_user_resources(LUser, LServer),
- ?DEBUG("user_available for ~p @ ~p (~p resources)",
- [LUser, LServer, length(Resources)]),
- case length(Resources) of
- %% first session for this user
- 1 ->
- UserGroups = get_user_groups({LUser, LServer}),
- lists:foreach(fun (OG) ->
- ?DEBUG("user_available: pushing ~p @ ~p grp ~p",
- [LUser, LServer, OG]),
- DisplayedToGroups = displayed_to_groups(OG, LServer),
- DisplayedGroups = get_displayed_groups(OG, LServer),
- broadcast_displayed_to_user(LUser, LServer, LServer, both, DisplayedGroups),
- broadcast_user_to_displayed(LUser, LServer, LServer, both, DisplayedToGroups)
- end,
- UserGroups);
- _ -> ok
- end,
- Acc;
c2s_self_presence(Acc) ->
Acc.
[_] -> {Host, Group}
end.
-broadcast_subscription(User, Server, ContactJid, Subscription) ->
- ejabberd_sm:route(jid:make(User, Server),
- {item, ContactJid, Subscription}).
-
displayed_groups_update(Members, DisplayedGroups, Subscription) ->
- lists:foreach(fun({U, S}) ->
- push_displayed_to_user(U, S, S, Subscription, DisplayedGroups),
- case Subscription of
- both ->
- broadcast_displayed_to_user(U, S, S, to, DisplayedGroups),
- broadcast_displayed_to_user(U, S, S, from, DisplayedGroups);
- Subscr ->
- broadcast_displayed_to_user(U, S, S, Subscr, DisplayedGroups)
- end
- end, Members).
+ lists:foreach(
+ fun({U, S}) ->
+ push_displayed_to_user(U, S, S, Subscription, DisplayedGroups)
+ end, Members).
opts_to_binary(Opts) ->
lists:map(