diff --git a/ChangeLog b/ChangeLog index 04eef9ce3..3747dc12b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2009-03-03 Badlop + * src/mod_roster.erl: When account is deleted, cancel presence + subscription for all roster items (EJAB-790) + * src/mod_roster_odbc.erl: Likewise + * src/mod_shared_roster.erl: Fix bug: a pending subscription request, and later the requester added to the roster due to a shared roster group, that request could neither be accepted or diff --git a/src/mod_roster.erl b/src/mod_roster.erl index cb1b195e7..be4afd098 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -271,7 +271,8 @@ process_item_set(From, To, #xmlel{} = El) -> Item2 = process_item_els(Item1, El#xmlel.children), case Item2#roster.subscription of remove -> - mnesia:delete({roster, {LUser, LServer, LJID}}); + send_unsubscribing_presence(From, Item), + ok; _ -> mnesia:write(Item2) end, @@ -688,6 +689,7 @@ remove_user(User, Server) LUser = exmpp_stringprep:nodeprep(User), LServer = exmpp_stringprep:nameprep(Server), US = {LUser, LServer}, + send_unsubscription_to_rosteritems(LUser, LServer), F = fun() -> lists:foreach(fun(R) -> mnesia:delete_object(R) @@ -700,6 +702,51 @@ remove_user(User, Server) ok end. +%% For each contact with Subscription: +%% Both or From, send a "unsubscribed" presence stanza; +%% Both or To, send a "unsubscribe" presence stanza. +send_unsubscription_to_rosteritems(LUser, LServer) -> + RosterItems = get_user_roster([], {LUser, LServer}), + From = jlib:make_jid({LUser, LServer, ""}), + lists:foreach(fun(RosterItem) -> + send_unsubscribing_presence(From, RosterItem) + end, + RosterItems). + +%% @spec (From::jid(), Item::roster()) -> ok +send_unsubscribing_presence(From, Item) -> + IsTo = case Item#roster.subscription of + both -> true; + to -> true; + _ -> false + end, + IsFrom = case Item#roster.subscription of + both -> true; + from -> true; + _ -> false + end, + if IsTo -> + send_presence_type( + jlib:jid_remove_resource(From), + jlib:make_jid(Item#roster.jid), "unsubscribe"); + true -> ok + end, + if IsFrom -> + send_presence_type( + jlib:jid_remove_resource(From), + jlib:make_jid(Item#roster.jid), "unsubscribed"); + true -> ok + end, + ok. + +send_presence_type(From, To, Type) -> + ejabberd_router:route( + From, To, + {xmlelement, "presence", + [{"type", Type}], + []}). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% @spec (User, Server, El) -> term() diff --git a/src/mod_roster_odbc.erl b/src/mod_roster_odbc.erl index b408f7664..8f5a8405b 100644 --- a/src/mod_roster_odbc.erl +++ b/src/mod_roster_odbc.erl @@ -253,7 +253,8 @@ process_item_set(From, To, #xmlel{} = El) -> Item2 = process_item_els(Item1, El#xmlel.children), case Item2#roster.subscription of remove -> - odbc_queries:del_roster(LServer, Username, SJID); + send_unsubscribing_presence(From, Item), + ok; _ -> ItemVals = record_to_string(Item2), ItemGroups = groups_to_string(Item2), @@ -629,6 +630,7 @@ remove_user(User, Server) when is_binary(User), is_binary(Server) -> LUser = exmpp_stringprep:nodeprep(User), LServer = binary_to_list(exmpp_stringprep:nameprep(Server)), Username = ejabberd_odbc:escape(LUser), + send_unsubscription_to_rosteritems(LUser, LServer), odbc_queries:del_user_roster_t(LServer, Username), ok catch @@ -636,6 +638,51 @@ remove_user(User, Server) when is_binary(User), is_binary(Server) -> ok end. +%% For each contact with Subscription: +%% Both or From, send a "unsubscribed" presence stanza; +%% Both or To, send a "unsubscribe" presence stanza. +send_unsubscription_to_rosteritems(LUser, LServer) -> + RosterItems = get_user_roster([], {LUser, LServer}), + From = jlib:make_jid({LUser, LServer, ""}), + lists:foreach(fun(RosterItem) -> + send_unsubscribing_presence(From, RosterItem) + end, + RosterItems). + +%% @spec (From::jid(), Item::roster()) -> ok +send_unsubscribing_presence(From, Item) -> + IsTo = case Item#roster.subscription of + both -> true; + to -> true; + _ -> false + end, + IsFrom = case Item#roster.subscription of + both -> true; + from -> true; + _ -> false + end, + if IsTo -> + send_presence_type( + jlib:jid_remove_resource(From), + jlib:make_jid(Item#roster.jid), "unsubscribe"); + true -> ok + end, + if IsFrom -> + send_presence_type( + jlib:jid_remove_resource(From), + jlib:make_jid(Item#roster.jid), "unsubscribed"); + true -> ok + end, + ok. + +send_presence_type(From, To, Type) -> + ejabberd_router:route( + From, To, + {xmlelement, "presence", + [{"type", Type}], + []}). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_items(User, Server, #xmlel{children = Els}) when is_binary(User), is_binary(Server) ->