Index: ejabberd-trunk-quilt/src/mod_shared_roster.erl
===================================================================
--- ejabberd-trunk-quilt.orig/src/mod_shared_roster.erl
+++ ejabberd-trunk-quilt/src/mod_shared_roster.erl
@@ -28,7 +28,7 @@
 	 delete_group/2,
 	 get_group_opts/2,
 	 set_group_opts/3,
-	 get_group_users/2,
+	 get_group_users/3,
 	 get_group_explicit_users/2,
 	 add_user_to_group/3,
 	 remove_user_from_group/3]).
@@ -117,7 +117,7 @@ get_user_roster(Items, US) ->
 						   get_group_name(S, Group),
 						   Acc2)
 			    end
-		    end, Acc1, get_group_users(S, Group))
+		    end, Acc1, get_group_users(U, S, Group))
 	  end, dict:new(), DisplayedGroups),
 
     %% If partially subscribed users are also in shared roster, show them as
@@ -178,7 +178,7 @@ get_subscription_lists({F, T}, User, Ser
 	lists:usort(
 	  lists:flatmap(
 	    fun(Group) ->
-		    get_group_users(LServer, Group)
+		    get_group_users(LUser, LServer, Group)
 	    end, DisplayedGroups)),
     SRJIDs = [{U1, S1, ""} || {U1, S1} <- SRUsers],
     {lists:usort(SRJIDs ++ F), lists:usort(SRJIDs ++ T)}.
@@ -197,7 +197,7 @@ get_jid_info({Subscription, Groups}, Use
 		    fun(User1, Acc2) ->
 			    dict:append(
 			      User1, get_group_name(LServer, Group), Acc2)
-		    end, Acc1, get_group_users(LServer, Group))
+		    end, Acc1, get_group_users(LUser, LServer, Group))
 	  end, dict:new(), DisplayedGroups),
     case dict:find(US1, SRUsers) of
 	{ok, GroupNames} ->
@@ -227,7 +227,7 @@ process_subscription(Direction, User, Se
 	lists:usort(
 	  lists:flatmap(
 	    fun(Group) ->
-		    get_group_users(LServer, Group)
+		    get_group_users(LUser, LServer, Group)
 	    end, DisplayedGroups)),
     case lists:member(US1, SRUsers) of
 	true ->
@@ -363,7 +363,22 @@ get_recent_users(Host, Days) ->
 get_online_users(Host) ->
     lists:usort([{U, S} || {U, S, _} <- ejabberd_sm:get_vh_session_list(Host)]).
 
-get_group_users(Host, Group) ->
+get_nearby_users(User, Host) ->
+    Resources = ejabberd_sm:get_user_resources(User, Host),
+    Sessions = ejabberd_sm:get_vh_session_list(Host),
+    Nearby = lists:foldl(
+      fun(Resource, Acc1) ->
+        lists:foldl(
+          fun({U, S, R} = Session, Acc2) ->
+            if
+              R == Resource -> {U, S} ++ Acc2;
+              true -> Acc2
+            end
+          end, [], Sessions) ++ Acc1
+      end, [], Resources),
+    lists:usort(Nearby).
+
+get_group_users(User, Host, Group) ->
     case get_group_opt(Host, Group, all_users, false) of
 	true ->
 	    ejabberd_auth:get_vh_registered_users(Host);
@@ -382,6 +397,12 @@ get_group_users(Host, Group) ->
 	false ->
 	    []
     end ++
+    case get_group_opt(Host, Group, nearby_users, false) of
+	true ->
+	    get_nearby_users(User, Host);
+	false ->
+	    []
+    end ++
     get_group_explicit_users(Host, Group).
 
 get_group_explicit_users(Host, Group) ->
@@ -401,7 +422,8 @@ get_special_users_groups(Host) ->
       fun(Group) ->
 	get_group_opt(Host, Group, all_users, false) orelse
 	get_group_opt(Host, Group, recent_users_days, 0) > 0 orelse
-	get_group_opt(Host, Group, online_users, false) end,
+	get_group_opt(Host, Group, online_users, false) orelse
+	get_group_opt(Host, Group, nearby_users, false) end,
       list_groups(Host)).
 
 get_user_displayed_groups(US) ->
@@ -448,7 +470,7 @@ user_registered(User, Server) ->
     DisplayedGroups = get_user_displayed_groups(US),
     lists:foreach(
       fun(Group) ->
-	      USs = get_group_users(LServer, Group),
+	      USs = get_group_users(LUser, LServer, Group),
 	      lists:foreach(
 		fun({U, S} = US1) ->
 			Item = #roster{usj = {U, S, {LUser, LServer, ""}},
@@ -499,7 +521,8 @@ user_available(New) ->
 	    DisplayedGroups = get_user_displayed_groups(OnlineUS),
 	    OnlineGroups = lists:filter(
 		fun(Group) ->
-		  get_group_opt(LServer, Group, online_users, false)
+		  get_group_opt(LServer, Group, online_users, false) orelse
+		  get_group_opt(LServer, Group, nearby_users, false)
 		end, DisplayedGroups),
 	    case OnlineGroups of
 	      [] ->
@@ -533,7 +556,8 @@ unset_presence(LUser, LServer, Resource,
 	    DisplayedGroups = get_user_displayed_groups(OnlineUS),
 	    OnlineGroups = lists:filter(
 	      fun(Group) ->
-		get_group_opt(LServer, Group, online_users, false)
+		get_group_opt(LServer, Group, online_users, false) orelse
+		get_group_opt(LServer, Group, nearby_users, false)
 	      end, DisplayedGroups),
 	    case OnlineGroups of
 	      [] ->
@@ -725,6 +749,7 @@ shared_roster_group(Host, Group, Query, 
     AllUsers = get_opt(GroupOpts, all_users, false),
     RecentUsersDays = get_opt(GroupOpts, recent_users_days, 0),
     OnlineUsers = get_opt(GroupOpts, online_users, false),
+    NearbyUsers = get_opt(GroupOpts, nearby_users, false),
     %%Disabled = false,
     DisplayedGroups = get_opt(GroupOpts, displayed_groups, []),
     Members = mod_shared_roster:get_group_explicit_users(Host, Group),
@@ -747,6 +772,12 @@ shared_roster_group(Host, Group, Query, 
 	    true ->
 		[]
 	end ++
+	if
+	    NearbyUsers ->
+		"@nearby@\n";
+	    true ->
+		[]
+	end ++
 	[[us_to_list(Member), $\n] || Member <- Members],
     FDisplayedGroups = [[DG, $\n] || DG <- DisplayedGroups],
     FGroup =
@@ -834,6 +865,8 @@ shared_roster_group_parse_query(Host, Gr
 				  USs;
 			      "@online@" ->
 				  USs;
+			      "@nearby@" ->
+				  USs;
 			      _ ->
 				  case jlib:string_to_jid(SJID) of
 				      JID when is_record(JID, jid) ->
@@ -859,11 +892,16 @@ shared_roster_group_parse_query(Host, Gr
 		    true -> [{online_users, true}];
 		    false -> []
 		end,
+	    NearbyUsersOpt =
+		case lists:member("@nearby@", SJIDs) of
+		    true -> [{nearby_users, true}];
+		    false -> []
+		end,
 
 	    mod_shared_roster:set_group_opts(
 	      Host, Group,
 	      NameOpt ++ DispGroupsOpt ++ DescriptionOpt ++ AllUsersOpt
-		++ RecentUsersOpt ++ OnlineUsersOpt),
+		++ RecentUsersOpt ++ OnlineUsersOpt ++ NearbyUsersOpt),
 
 	    if
 		NewMembers == error -> error;
