diff --git a/ChangeLog b/ChangeLog index e39bdb54b..592f90926 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2006-07-06 Mickael Remond + + * src/mod_shared_roster.erl: Shared roster entries can now be moved or + rename from a client without breaking current presence status. + * src/mod_roster.erl: Likewise. + * src/mod_roster_odbc.erl: Likewise. + 2006-07-05 Mickael Remond * src/web/ejabberd_web_admin.erl: More flexible parsing the shared diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 896b0e9f9..04d539cbf 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -205,7 +205,11 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) -> _ -> mnesia:write(Item2) end, - {Item, Item2} + %% If the item exist in shared roster, take the + %% subscription information from there: + Item3 = ejabberd_hooks:run_fold(roster_process_item, + LServer, Item2, [LServer]), + {Item, Item3} end, case mnesia:transaction(F) of {atomic, {OldItem, Item}} -> diff --git a/src/mod_roster_odbc.erl b/src/mod_roster_odbc.erl index 626698cc7..dfea38480 100644 --- a/src/mod_roster_odbc.erl +++ b/src/mod_roster_odbc.erl @@ -273,7 +273,11 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) -> end, ItemGroups) end, - {Item, Item2} + %% If the item exist in shared roster, take the + %% subscription information from there: + Item3 = ejabberd_hooks:run_fold(roster_process_item, + LServer, Item2, [LServer]), + {Item, Item3} end, case ejabberd_odbc:sql_transaction(LServer, F) of {atomic, {OldItem, Item}} -> diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 7477d31c9..6a438e673 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -15,6 +15,7 @@ get_user_roster/2, get_subscription_lists/3, get_jid_info/4, + process_item/2, in_subscription/6, out_subscription/4, list_groups/1, @@ -53,7 +54,9 @@ start(Host, _Opts) -> ejabberd_hooks:add(roster_get_subscription_lists, Host, ?MODULE, get_subscription_lists, 70), ejabberd_hooks:add(roster_get_jid_info, Host, - ?MODULE, get_jid_info, 70). + ?MODULE, get_jid_info, 70), + ejabberd_hooks:add(roster_process_item, Host, + ?MODULE, process_item, 50). %ejabberd_hooks:add(remove_user, Host, % ?MODULE, remove_user, 50), @@ -67,7 +70,9 @@ stop(Host) -> ejabberd_hooks:delete(roster_get_subscription_lists, Host, ?MODULE, get_subscription_lists, 70), ejabberd_hooks:delete(roster_get_jid_info, Host, - ?MODULE, get_jid_info, 70). + ?MODULE, get_jid_info, 70), + ejabberd_hooks:delete(roster_process_item, Host, + ?MODULE, process_item, 50). %ejabberd_hooks:delete(remove_user, Host, % ?MODULE, remove_user, 50), @@ -116,6 +121,28 @@ get_user_roster(Items, US) -> {{U1, S1}, GroupNames} <- dict:to_list(SRUsersRest)], SRItems ++ NewItems1. +%% This function in use to rewrite the roster entries when moving or renaming +%% them in the user contact list. +process_item(RosterItem, Host) -> + USFrom = RosterItem#roster.us, + {User,Server,_Resource} = RosterItem#roster.jid, + USTo = {User,Server}, + DisplayedGroups = get_user_displayed_groups(USFrom), + CommonGroups = lists:filter(fun(Group) -> + is_user_in_group(USTo, Group, Host) + end, DisplayedGroups), + case CommonGroups of + [] -> RosterItem; + %% Roster item cannot be removed: We simply reset the original groups: + _ when RosterItem#roster.subscription == remove -> + GroupNames = lists:map(fun(Group) -> + get_group_name(Host, Group) + end, CommonGroups), + RosterItem#roster{subscription = both, ask = none, + groups=[GroupNames]}; + _ -> RosterItem#roster{subscription = both, ask = none} + end. + get_subscription_lists({F, T}, User, Server) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), @@ -234,8 +261,6 @@ set_group_opts(Host, Group, Opts) -> end, mnesia:transaction(F). - - get_user_groups(US) -> Host = element(2, US), case catch mnesia:dirty_read(sr_user, US) of @@ -306,6 +331,12 @@ get_user_displayed_groups(US) -> end, get_user_groups(US))), [Group || Group <- DisplayedGroups1, is_group_enabled(Host, Group)]. +is_user_in_group(US, Group, Host) -> + case mnesia:match_object(#sr_user{us=US, group_host={Group, Host}}) of + [] -> false; + _ -> true + end. + add_user_to_group(Host, US, Group) -> R = #sr_user{us = US, group_host = {Group, Host}}, F = fun() ->