diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs
index d90788a111..0a4b2426a8 100644
--- a/OpenSim/Data/Null/NullFriendsData.cs
+++ b/OpenSim/Data/Null/NullFriendsData.cs
@@ -56,13 +56,21 @@ namespace OpenSim.Data.Null
///
public FriendsData[] GetFriends(string userID)
{
- List lst = m_Data.FindAll(delegate (FriendsData fdata)
+ List lst = m_Data.FindAll(fdata =>
{
return fdata.PrincipalID == userID.ToString();
});
if (lst != null)
+ {
+ lst.ForEach(f =>
+ {
+ FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID);
+ if (f2 != null) { f.Data["TheirFlags"] = f2.Data["Flags"]; }
+ });
+
return lst.ToArray();
+ }
return new FriendsData[0];
}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 2e76acb5ca..8fdbe7b50d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -11197,6 +11197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText));
return true;
}
+
private bool HandleGrantUserRights(IClientAPI sender, Packet Pack)
{
GrantUserRightsPacket GrantUserRights =
@@ -11217,6 +11218,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
GrantUserRights.Rights[0].RelatedRights);
return true;
}
+
private bool HandlePlacesQuery(IClientAPI sender, Packet Pack)
{
PlacesQueryPacket placesQueryPacket =
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index eed7cd590a..b557ffe5f2 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -46,7 +46,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
// Fields
private bool m_dumpAssetsToFile;
private Scene m_Scene;
- private UUID UserID;
private Dictionary XferUploaders = new Dictionary();
// Methods
@@ -54,7 +53,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
bool dumpAssetsToFile)
{
m_Scene = scene;
- UserID = agentID;
m_dumpAssetsToFile = dumpAssetsToFile;
}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index a5131ecad0..74f32e7fc9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -165,7 +165,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// Instantiate the request handler
IHttpServer server = MainServer.GetHttpServer((uint)mPort);
- server.AddStreamHandler(new FriendsRequestHandler(this));
+
+ if (server != null)
+ server.AddStreamHandler(new FriendsRequestHandler(this));
}
if (m_FriendsService == null)
@@ -352,20 +354,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
continue;
}
- PresenceInfo presence = null;
- PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid });
- if (presences != null && presences.Length > 0)
- presence = presences[0];
- if (presence != null)
- im.offline = 0;
-
+ im.offline = 0;
im.fromAgentID = fromAgentID.Guid;
im.fromAgentName = firstname + " " + lastname;
im.offline = (byte)((presence == null) ? 1 : 0);
im.imSessionID = im.fromAgentID;
im.message = FriendshipMessage(fid);
- // Finally
LocalFriendshipOffered(agentID, im);
}
@@ -576,9 +571,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders)
{
- m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID);
+ m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID);
- StoreFriendships(agentID, friendID);
+ AddFriend(client, friendID);
+ }
+
+ public void AddFriend(IClientAPI client, UUID friendID)
+ {
+ StoreFriendships(client.AgentId, friendID);
ICallingCardModule ccm = client.Scene.RequestModuleInterface();
if (ccm != null)
@@ -594,7 +594,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
//
// Try Local
- if (LocalFriendshipApproved(agentID, client.Name, friendID))
+ if (LocalFriendshipApproved(client.AgentId, client.Name, friendID))
{
client.SendAgentOnline(new UUID[] { friendID });
return;
@@ -608,7 +608,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (friendSession != null)
{
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
- m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID);
+ m_FriendsSimConnector.FriendshipApproved(region, client.AgentId, client.Name, friendID);
client.SendAgentOnline(new UUID[] { friendID });
}
}
@@ -882,7 +882,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
///
- /// Update loca cache only
+ /// Update local cache only
///
///
///
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index dda67f9c2b..02b417f946 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -141,7 +141,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
List fList = new List();
foreach (string s in friendList)
- fList.Add(s.Substring(0, 36));
+ {
+ if (s.Length < 36)
+ m_log.WarnFormat(
+ "[HGFRIENDS MODULE]: Ignoring friend {0} ({1} chars) for {2} since identifier too short",
+ s, s.Length, userID);
+ else
+ fList.Add(s.Substring(0, 36));
+ }
PresenceInfo[] presence = PresenceService.GetAgents(fList.ToArray());
foreach (PresenceInfo pi in presence)
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
new file mode 100644
index 0000000000..942091c4c1
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using Nini.Config;
+using NUnit.Framework;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Region.CoreModules.Avatar.Friends;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Tests.Common;
+using OpenSim.Tests.Common.Mock;
+
+namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
+{
+ [TestFixture]
+ public class FriendsModuleTests
+ {
+ private FriendsModule m_fm;
+ private TestScene m_scene;
+
+ [SetUp]
+ public void Init()
+ {
+ IConfigSource config = new IniConfigSource();
+ config.AddConfig("Modules");
+ // Not strictly necessary since FriendsModule assumes it is the default (!)
+ config.Configs["Modules"].Set("FriendsModule", "FriendsModule");
+ config.AddConfig("Friends");
+ config.Configs["Friends"].Set("Connector", "OpenSim.Services.FriendsService.dll");
+ config.AddConfig("FriendsService");
+ config.Configs["FriendsService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
+
+ m_scene = SceneHelpers.SetupScene();
+ m_fm = new FriendsModule();
+ SceneHelpers.SetupSceneModules(m_scene, config, m_fm);
+ }
+
+ [Test]
+ public void TestNoFriends()
+ {
+ TestHelpers.InMethod();
+// log4net.Config.XmlConfigurator.Configure();
+
+ UUID userId = TestHelpers.ParseTail(0x1);
+
+ ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
+
+ Assert.That(((TestClient)sp.ControllingClient).OfflineNotificationsReceived.Count, Is.EqualTo(0));
+ Assert.That(((TestClient)sp.ControllingClient).OnlineNotificationsReceived.Count, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void TestAddFriendWhileOnline()
+ {
+ TestHelpers.InMethod();
+// log4net.Config.XmlConfigurator.Configure();
+
+ UUID userId = TestHelpers.ParseTail(0x1);
+ UUID user2Id = TestHelpers.ParseTail(0x2);
+
+ ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
+ SceneHelpers.AddScenePresence(m_scene, user2Id);
+
+ // This friendship is currently only one-way, which might be pathalogical in Second Life.
+ m_fm.AddFriend(sp.ControllingClient, user2Id);
+
+ Assert.That(((TestClient)sp.ControllingClient).OfflineNotificationsReceived.Count, Is.EqualTo(0));
+ Assert.That(((TestClient)sp.ControllingClient).OnlineNotificationsReceived.Count, Is.EqualTo(1));
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
index 321a70522b..560d9136ca 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -225,12 +225,13 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
foreach (Scene scene in m_Scenes)
{
ScenePresence sp = scene.GetScenePresence(toAgentID);
- if(!sp.IsChildAgent)
+ if(sp != null && !sp.IsChildAgent)
{
scene.EventManager.TriggerIncomingInstantMessage(gim);
successful = true;
}
}
+
if (!successful)
{
// If the message can't be delivered to an agent, it
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 73ab4e31cc..10ab6d0e6b 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -50,8 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
///
public Scene Scene { get; set; }
- private bool m_Enabled = false;
- private Scene m_Scene;
+ private bool m_Enabled;
private XInventoryServicesConnector m_RemoteConnector;
private IUserManagement m_UserManager;
diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
index d4a6857188..8143164283 100644
--- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
@@ -33,6 +33,20 @@ namespace OpenSim.Region.Framework.Interfaces
{
public interface IFriendsModule
{
+ ///
+ /// Add a friend for the given user.
+ ///
+ ///
+ /// This is a one-way friendship. To make a two way friendship you will need to call this again with the
+ /// client and friend reversed.
+ ///
+ /// Ultimately, it would be more useful to take in a user account here rather than having to have a user
+ /// present in the scene.
+ ///
+ ///
+ ///
+ void AddFriend(IClientAPI client, UUID friendID);
+
uint GetFriendPerms(UUID PrincipalID, UUID FriendID);
bool SendFriendsOnlineIfNeeded(IClientAPI client);
}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 087697f480..8906c6ff74 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2862,6 +2862,8 @@ namespace OpenSim.Region.Framework.Scenes
Velocity = Vector3.Zero;
AbsolutePosition = pos;
+// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
+
AddToPhysicalScene(isFlying);
}
}
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 60a23f518f..5fe1985d55 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -56,6 +56,10 @@ namespace OpenSim.Tests.Common.Mock
private IScene m_scene;
+ // Properties so that we can get at received data for test purposes
+ public List OfflineNotificationsReceived { get; private set; }
+ public List OnlineNotificationsReceived { get; private set; }
+
// disable warning: public events, part of the public API
#pragma warning disable 67
@@ -440,6 +444,9 @@ namespace OpenSim.Tests.Common.Mock
m_circuitCode = agentData.circuitcode;
m_scene = scene;
CapsSeedUrl = agentData.CapsPath;
+
+ OfflineNotificationsReceived = new List();
+ OnlineNotificationsReceived = new List();
}
///
@@ -827,12 +834,12 @@ namespace OpenSim.Tests.Common.Mock
public void SendAgentOffline(UUID[] agentIDs)
{
-
+ OfflineNotificationsReceived.AddRange(agentIDs);
}
public void SendAgentOnline(UUID[] agentIDs)
{
-
+ OnlineNotificationsReceived.AddRange(agentIDs);
}
public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
diff --git a/prebuild.xml b/prebuild.xml
index ecc60fb04e..d1a1cf826a 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -2947,6 +2947,7 @@
+