diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index e5c8cb97e8..9aadd70927 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -88,6 +88,7 @@ what it is today. * Kitto Flora * KittyLiu * Kurt Taylor (IBM) +* lkalif * lulurun * M.Igarashi * maimedleech diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index c59ea28132..5a23c90185 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -1012,7 +1012,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController throw new Exception(String.Format("Account {0} {1} already exists", firstname, lastname)); account = new UserAccount(scopeID, firstname, lastname, email); - // REFACTORING PROBLEM: no method to set the password! bool success = m_app.SceneManager.CurrentOrFirstScene.UserAccountService.StoreUserAccount(account); @@ -1020,6 +1019,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController throw new Exception(String.Format("failed to create new user {0} {1}", firstname, lastname)); + // Store the password + m_app.SceneManager.CurrentOrFirstScene.AuthenticationService.SetPassword(account.PrincipalID, passwd); + GridRegion home = m_app.SceneManager.CurrentOrFirstScene.GridService.GetRegionByPosition(scopeID, (int)(regX * Constants.RegionSize), (int)(regY * Constants.RegionSize)); if (home == null) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 17bd7959c7..1d6d4c1d03 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -642,6 +642,7 @@ namespace OpenSim.Client.MXP.ClientStack public event Action OnRemoveAvatar; public event ObjectPermissions OnObjectPermissions; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index 4ecbaf917f..43c64e9584 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -288,6 +288,7 @@ namespace OpenSim.Client.Sirikata.ClientStack public event Action OnRemoveAvatar; public event ObjectPermissions OnObjectPermissions; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 1da746ad2b..864b4f16f3 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -291,6 +291,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack public event Action OnRemoveAvatar = delegate { }; public event ObjectPermissions OnObjectPermissions = delegate { }; public event CreateNewInventoryItem OnCreateNewInventoryItem = delegate { }; + public event LinkInventoryItem OnLinkInventoryItem = delegate { }; public event CreateInventoryFolder OnCreateNewInventoryFolder = delegate { }; public event UpdateInventoryFolder OnUpdateInventoryFolder = delegate { }; public event MoveInventoryFolder OnMoveInventoryFolder = delegate { }; diff --git a/OpenSim/Data/IUserAccountData.cs b/OpenSim/Data/IUserAccountData.cs index 6ee5995fd1..906ba6c561 100644 --- a/OpenSim/Data/IUserAccountData.cs +++ b/OpenSim/Data/IUserAccountData.cs @@ -48,6 +48,7 @@ namespace OpenSim.Data { UserAccountData[] Get(string[] fields, string[] values); bool Store(UserAccountData data); + bool Delete(string field, string val); UserAccountData[] GetUsers(UUID scopeID, string query); } } diff --git a/OpenSim/Data/Null/NullInventoryData.cs b/OpenSim/Data/Null/NullInventoryData.cs new file mode 100644 index 0000000000..8f196e2018 --- /dev/null +++ b/OpenSim/Data/Null/NullInventoryData.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; + +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.Null +{ + /// + /// This class is completely null. + /// + public class NullInventoryData : IInventoryDataPlugin + { + public string Version { get { return "1.0.0.0"; } } + + public void Initialise() + { + } + + public void Dispose() + { + // Do nothing. + } + + public string Name + { + get { return "Null Inventory Data Interface"; } + } + + public void Initialise(string connect) + { + } + + + /// + /// Returns all descendent folders of this folder. Does not return the parent folder itself. + /// + /// The folder to get subfolders for + /// A list of inventory folders + public List getFolderHierarchy(UUID parentID) + { + return new List(); + } + + /// + /// Returns a list of inventory items contained within the specified folder + /// + /// The UUID of the target folder + /// A List of InventoryItemBase items + public List getInventoryInFolder(UUID folderID) + { + return new List(); + } + + /// + /// Returns a list of the root folders within a users inventory + /// + /// The user whos inventory is to be searched + /// A list of folder objects + public List getUserRootFolders(UUID user) + { + return new List(); + } + + /// + /// Returns the users inventory root folder. + /// + /// The UUID of the user who is having inventory being returned + /// Root inventory folder, null if no root inventory folder was found + public InventoryFolderBase getUserRootFolder(UUID user) + { + return null; + } + + /// + /// Returns a list of inventory folders contained in the folder 'parentID' + /// + /// The folder to get subfolders for + /// A list of inventory folders + public List getInventoryFolders(UUID parentID) + { + return new List(); + } + + /// + /// Returns an inventory item by its UUID + /// + /// The UUID of the item to be returned + /// A class containing item information + public InventoryItemBase getInventoryItem(UUID item) + { + return null; + } + + /// + /// Returns a specified inventory folder by its UUID + /// + /// The UUID of the folder to be returned + /// A class containing folder information + public InventoryFolderBase getInventoryFolder(UUID folder) + { + return null; + } + + /// + /// Creates a new inventory item based on item + /// + /// The item to be created + public void addInventoryItem(InventoryItemBase item) + { + } + + /// + /// Updates an inventory item with item (updates based on ID) + /// + /// The updated item + public void updateInventoryItem(InventoryItemBase item) + { + } + + /// + /// + /// + /// + public void deleteInventoryItem(UUID item) + { + } + + /// + /// + /// + /// + public InventoryItemBase queryInventoryItem(UUID item) + { + return null; + } + + /// + /// + /// + /// + public InventoryFolderBase queryInventoryFolder(UUID folder) + { + return null; + } + + /// + /// Adds a new folder specified by folder + /// + /// The inventory folder + public void addInventoryFolder(InventoryFolderBase folder) + { + } + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + public void updateInventoryFolder(InventoryFolderBase folder) + { + } + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + public void moveInventoryFolder(InventoryFolderBase folder) + { + } + + /// + /// Deletes a folder. Thie will delete both the folder itself and its contents (items and descendent folders) + /// + /// The id of the folder + public void deleteInventoryFolder(UUID folder) + { + } + + /// + /// Returns all activated gesture-items in the inventory of the specified avatar. + /// + /// + /// The of the avatar + /// + /// + /// The list of gestures (s) + /// + public List fetchActiveGestures(UUID avatarID) + { + return new List(); + } + } +} diff --git a/OpenSim/Data/Null/NullUserAccountData.cs b/OpenSim/Data/Null/NullUserAccountData.cs index fc2c5d5de2..9eb94e643c 100644 --- a/OpenSim/Data/Null/NullUserAccountData.cs +++ b/OpenSim/Data/Null/NullUserAccountData.cs @@ -135,5 +135,26 @@ namespace OpenSim.Data.Null return result; } + public bool Delete(string field, string val) + { + // Only delete by PrincipalID + if (field.Equals("PrincipalID")) + { + UUID uuid = UUID.Zero; + if (UUID.TryParse(val, out uuid) && m_DataByUUID.ContainsKey(uuid)) + { + UserAccountData account = m_DataByUUID[uuid]; + m_DataByUUID.Remove(uuid); + if (m_DataByName.ContainsKey(account.FirstName + " " + account.LastName)) + m_DataByName.Remove(account.FirstName + " " + account.LastName); + if (account.Data.ContainsKey("Email") && account.Data["Email"] != string.Empty && m_DataByEmail.ContainsKey(account.Data["Email"])) + m_DataByEmail.Remove(account.Data["Email"]); + + return true; + } + } + + return false; + } } } diff --git a/OpenSim/Data/SQLite/Resources/001_UserAccount.sql b/OpenSim/Data/SQLite/Resources/001_UserAccount.sql index f9bf24c908..c38d9a762f 100644 --- a/OpenSim/Data/SQLite/Resources/001_UserAccount.sql +++ b/OpenSim/Data/SQLite/Resources/001_UserAccount.sql @@ -2,7 +2,7 @@ -- useraccounts table CREATE TABLE UserAccounts ( - PrincipalID CHAR(36) NOT NULL, + PrincipalID CHAR(36) primary key, ScopeID CHAR(36) NOT NULL, FirstName VARCHAR(64) NOT NULL, LastName VARCHAR(64) NOT NULL, diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs index ace40e5a0c..a032670588 100644 --- a/OpenSim/Data/SQLite/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs @@ -137,7 +137,7 @@ namespace OpenSim.Data.SQLite cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); - + cmd.ExecuteNonQuery(); } } diff --git a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs index 2c28375485..aa10734d50 100644 --- a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs +++ b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs @@ -235,7 +235,7 @@ namespace OpenSim.Data.SQLite if (System.Environment.TickCount - m_LastExpire > 30000) DoExpire(); - SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now, 'localtime', '+" + lifetime.ToString() + + SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"); if (ExecuteNonQuery(cmd, m_Connection) > 0) diff --git a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs index 50e8c238f5..67cf7165b1 100644 --- a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs @@ -66,7 +66,7 @@ namespace OpenSim.Data.SQLite if (words.Length == 1) { - cmd.CommandText = String.Format("select * from {0} where ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", + cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", m_Realm, scopeID.ToString(), words[0]); } else diff --git a/OpenSim/Framework/Communications/Osp/OspResolver.cs b/OpenSim/Framework/Communications/Osp/OspResolver.cs index 2e55f53b25..24ea64d87f 100644 --- a/OpenSim/Framework/Communications/Osp/OspResolver.cs +++ b/OpenSim/Framework/Communications/Osp/OspResolver.cs @@ -139,6 +139,9 @@ namespace OpenSim.Framework.Communications.Osp /// protected static UUID ResolveOspaName(string name, IUserAccountService userService) { + if (userService == null) + return UUID.Zero; + int nameSeparatorIndex = name.IndexOf(OSPA_NAME_VALUE_SEPARATOR); if (nameSeparatorIndex < 0) @@ -149,7 +152,7 @@ namespace OpenSim.Framework.Communications.Osp string firstName = name.Remove(nameSeparatorIndex).TrimEnd(); string lastName = name.Substring(nameSeparatorIndex + 1).TrimStart(); - + UserAccount account = userService.GetUserAccount(UUID.Zero, firstName, lastName); if (account != null) return account.PrincipalID; diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs index be936b6671..a3036d0df6 100644 --- a/OpenSim/Framework/Console/LocalConsole.cs +++ b/OpenSim/Framework/Console/LocalConsole.cs @@ -38,7 +38,7 @@ namespace OpenSim.Framework.Console { /// /// A console that uses cursor control and color - /// + /// public class LocalConsole : CommandConsole { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -100,24 +100,40 @@ namespace OpenSim.Framework.Console private int SetCursorTop(int top) { // From at least mono 2.4.2.3, window resizing can give mono an invalid row and column values. If we try - // to set a cursor row position with a currently invalid column, mono will throw an exception. - // Therefore, we need to make sure that the column position is valid first. + // to set a cursor row position with a currently invalid column, mono will throw an exception. + // Therefore, we need to make sure that the column position is valid first. int left = System.Console.CursorLeft; if (left < 0) + { System.Console.CursorLeft = 0; - else if (left >= System.Console.BufferWidth) - System.Console.CursorLeft = System.Console.BufferWidth - 1; + } + else + { + int bw = System.Console.BufferWidth; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bw > 0 && left >= bw) + System.Console.CursorLeft = bw - 1; + } if (top < 0) + { top = 0; - if (top >= System.Console.BufferHeight) - top = System.Console.BufferHeight - 1; + } + else + { + int bh = System.Console.BufferHeight; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bh > 0 && top >= bh) + top = bh - 1; + } System.Console.CursorTop = top; return top; - } + } /// /// Set the cursor column. @@ -129,23 +145,38 @@ namespace OpenSim.Framework.Console /// /// /// The new cursor column. - /// + /// private int SetCursorLeft(int left) { // From at least mono 2.4.2.3, window resizing can give mono an invalid row and column values. If we try - // to set a cursor column position with a currently invalid row, mono will throw an exception. - // Therefore, we need to make sure that the row position is valid first. + // to set a cursor column position with a currently invalid row, mono will throw an exception. + // Therefore, we need to make sure that the row position is valid first. int top = System.Console.CursorTop; if (top < 0) + { System.Console.CursorTop = 0; - else if (top >= System.Console.BufferHeight) - System.Console.CursorTop = System.Console.BufferHeight - 1; + } + else + { + int bh = System.Console.BufferHeight; + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bh > 0 && top >= bh) + System.Console.CursorTop = bh - 1; + } if (left < 0) + { left = 0; - if (left >= System.Console.BufferWidth) - left = System.Console.BufferWidth - 1; + } + else + { + int bw = System.Console.BufferWidth; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bw > 0 && left >= bw) + left = bw - 1; + } System.Console.CursorLeft = left; @@ -183,7 +214,7 @@ namespace OpenSim.Framework.Console System.Console.Write("{0}", prompt); SetCursorTop(new_y); - SetCursorLeft(new_x); + SetCursorLeft(new_x); } } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 4577758a34..af88c4a632 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -236,6 +236,10 @@ namespace OpenSim.Framework IClientAPI remoteClient, UUID transActionID, UUID folderID, uint callbackID, string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask, int creationDate); + public delegate void LinkInventoryItem( + IClientAPI remoteClient, UUID transActionID, UUID folderID, uint callbackID, string description, string name, + sbyte invType, sbyte type, UUID olditemID); + public delegate void FetchInventoryDescendents( IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); @@ -930,6 +934,7 @@ namespace OpenSim.Framework event ObjectPermissions OnObjectPermissions; event CreateNewInventoryItem OnCreateNewInventoryItem; + event LinkInventoryItem OnLinkInventoryItem; event CreateInventoryFolder OnCreateNewInventoryFolder; event UpdateInventoryFolder OnUpdateInventoryFolder; event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index 9c2a4f9ac1..1208b97300 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs @@ -188,6 +188,10 @@ namespace OpenSim.Framework m_textureEntry = DEFAULT_TEXTURE; } + /// + /// Construct a PrimitiveBaseShape object from a OpenMetaverse.Primitive object + /// + /// public PrimitiveBaseShape(Primitive prim) { PCode = (byte)prim.PrimData.PCode; diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs index f6d6a7cf60..a4898061da 100644 --- a/OpenSim/Framework/SLUtil.cs +++ b/OpenSim/Framework/SLUtil.cs @@ -106,6 +106,39 @@ namespace OpenSim.Framework } } + public static string SLInvTypeToContentType(int invType) + { + switch ((InventoryType)invType) + { + case InventoryType.Animation: + return "application/vnd.ll.animation"; + case InventoryType.CallingCard: + return "application/vnd.ll.callingcard"; + case InventoryType.Folder: + return "application/vnd.ll.folder"; + case InventoryType.Gesture: + return "application/vnd.ll.gesture"; + case InventoryType.Landmark: + return "application/vnd.ll.landmark"; + case InventoryType.LSL: + return "application/vnd.ll.lsltext"; + case InventoryType.Notecard: + return "application/vnd.ll.notecard"; + case InventoryType.Attachment: + case InventoryType.Object: + return "application/vnd.ll.primitive"; + case InventoryType.Sound: + return "application/ogg"; + case InventoryType.Snapshot: + case InventoryType.Texture: + return "image/x-j2c"; + case InventoryType.Wearable: + return "application/vnd.ll.clothing"; + default: + return "application/octet-stream"; + } + } + public static sbyte ContentTypeToSLAssetType(string contentType) { switch (contentType) diff --git a/OpenSim/Framework/Serialization/TarArchiveWriter.cs b/OpenSim/Framework/Serialization/TarArchiveWriter.cs index 20d0f7e90b..0bd639ff3a 100644 --- a/OpenSim/Framework/Serialization/TarArchiveWriter.cs +++ b/OpenSim/Framework/Serialization/TarArchiveWriter.cs @@ -208,7 +208,9 @@ namespace OpenSim.Framework.Serialization m_bw.Write(header); // Write out data - m_bw.Write(data); + // An IOException occurs if we try to write out an empty array in Mono 2.6 + if (data.Length > 0) + m_bw.Write(data); if (data.Length % 512 != 0) { diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 64f6118cfc..802cb37aa0 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1486,4 +1486,4 @@ namespace OpenSim.Framework } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs old mode 100755 new mode 100644 index 38b20843e0..139503074f --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -251,8 +251,9 @@ namespace OpenSim "Save named prim to XML2", SavePrimsXml2); m_console.Commands.AddCommand("region", false, "load oar", - "load oar [--merge] ", - "Load a region's data from OAR archive", LoadOar); + "load oar [--merge] [--skip-assets] ", + "Load a region's data from OAR archive. --merge will merge the oar with the existing scene. --skip-assets will load the oar but ignore the assets it contains", + LoadOar); m_console.Commands.AddCommand("region", false, "save oar", "save oar ", diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 25f6ef0835..d7120a5344 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -182,6 +182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event TeleportLocationRequest OnSetStartLocationRequest; public event UpdateAvatarProperties OnUpdateAvatarProperties; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; @@ -641,7 +642,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (pprocessor.Async) { object obj = new AsyncPacketProcess(this, pprocessor.method, packet); - Util.FireAndForget(ProcessSpecificPacketAsync,obj); + Util.FireAndForget(ProcessSpecificPacketAsync, obj); result = true; } else @@ -669,8 +670,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void ProcessSpecificPacketAsync(object state) { AsyncPacketProcess packetObject = (AsyncPacketProcess)state; - packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); - + + try + { + packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); + } + catch (Exception e) + { + // Make sure that we see any exception caused by the asynchronous operation. + m_log.Error( + string.Format("[LLCLIENTVIEW]: Caught exception while processing {0}", packetObject.Pack), e); + } } #endregion Packet Handling @@ -4740,6 +4750,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder); AddLocalPacketHandler(PacketType.MoveInventoryFolder, HandleMoveInventoryFolder); AddLocalPacketHandler(PacketType.CreateInventoryItem, HandleCreateInventoryItem); + AddLocalPacketHandler(PacketType.LinkInventoryItem, HandleLinkInventoryItem); AddLocalPacketHandler(PacketType.FetchInventory, HandleFetchInventory); AddLocalPacketHandler(PacketType.FetchInventoryDescendents, HandleFetchInventoryDescendents); AddLocalPacketHandler(PacketType.PurgeInventoryDescendents, HandlePurgeInventoryDescendents); @@ -7058,6 +7069,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + /// + /// This is the entry point for the UDP route by which the client can retrieve asset data. If the request + /// is successful then a TransferInfo packet will be sent back, followed by one or more TransferPackets + /// + /// + /// + /// This parameter may be ignored since we appear to return true whatever happens private bool HandleTransferRequest(IClientAPI sender, Packet Pack) { //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); @@ -7068,37 +7086,95 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Has to be done here, because AssetCache can't do it // UUID taskID = UUID.Zero; - if (transfer.TransferInfo.SourceType == 3) + if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) { taskID = new UUID(transfer.TransferInfo.Params, 48); UUID itemID = new UUID(transfer.TransferInfo.Params, 64); UUID requestID = new UUID(transfer.TransferInfo.Params, 80); + +// m_log.DebugFormat( +// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}", +// requestID, itemID, taskID, Name); + if (!(((Scene)m_scene).Permissions.BypassPermissions())) { if (taskID != UUID.Zero) // Prim { SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); + if (part == null) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist", + Name, requestID, itemID, taskID); return true; + } - if (part.OwnerID != AgentId) - return true; - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return true; - - TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); - if (ti == null) - return true; - - if (ti.OwnerID != AgentId) - return true; - - if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) - return true; - - if (ti.AssetID != requestID) + TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); + if (tii == null) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist", + Name, requestID, itemID, taskID); return true; + } + + if (tii.Type == (int)AssetType.LSLText) + { + if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) + return true; + } + else if (tii.Type == (int)AssetType.Notecard) + { + if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId)) + return true; + } + else + { + // TODO: Change this code to allow items other than notecards and scripts to be successfully + // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule + if (part.OwnerID != AgentId) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}", + Name, requestID, itemID, taskID, part.OwnerID); + return true; + } + + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set", + Name, requestID, itemID, taskID); + return true; + } + + if (tii.OwnerID != AgentId) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}", + Name, requestID, itemID, taskID, tii.OwnerID); + return true; + } + + if (( + tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", + Name, requestID, itemID, taskID); + return true; + } + + if (tii.AssetID != requestID) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", + Name, requestID, itemID, taskID, tii.AssetID); + return true; + } + } } else // Agent { @@ -7118,7 +7194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // only to notecards and scripts. All // other asset types are always available // - if (assetRequestItem.AssetType == 10) + if (assetRequestItem.AssetType == (int)AssetType.LSLText) { if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) { @@ -7126,7 +7202,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } } - else if (assetRequestItem.AssetType == 7) + else if (assetRequestItem.AssetType == (int)AssetType.Notecard) { if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) { @@ -7136,7 +7212,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (assetRequestItem.AssetID != requestID) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", + Name, requestID, itemID, assetRequestItem.AssetID); return true; + } } } } @@ -7339,6 +7420,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + private bool HandleLinkInventoryItem(IClientAPI sender, Packet Pack) + { + LinkInventoryItemPacket createLink = (LinkInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (createLink.AgentData.SessionID != SessionId || + createLink.AgentData.AgentID != AgentId) + return true; + } + #endregion + + LinkInventoryItem linkInventoryItem = OnLinkInventoryItem; + + if (linkInventoryItem != null) + { + linkInventoryItem( + this, + createLink.InventoryBlock.TransactionID, + createLink.InventoryBlock.FolderID, + createLink.InventoryBlock.CallbackID, + Util.FieldToString(createLink.InventoryBlock.Description), + Util.FieldToString(createLink.InventoryBlock.Name), + createLink.InventoryBlock.InvType, + createLink.InventoryBlock.Type, + createLink.InventoryBlock.OldItemID); + } + + return true; + } + private bool HandleFetchInventory(IClientAPI sender, Packet Pack) { if (OnFetchInventory != null) @@ -7683,12 +7796,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; + + // Unused? Clicking share with group sets GroupPermissions instead, so perhaps this is something + // different //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; newTaskItem.Type = updatetask.InventoryData.Type; newTaskItem.InvType = updatetask.InventoryData.InvType; newTaskItem.Flags = updatetask.InventoryData.Flags; //newTaskItem.SaleType=updatetask.InventoryData.SaleType; - //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; + //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice; newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; @@ -7696,7 +7812,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP newTaskItem, updatetask.UpdateData.LocalID); } } - } + } return true; } @@ -11088,7 +11204,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (m_debugPacketLevel >= 255) m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); - + if (!ProcessPacketMethod(Pack)) m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); @@ -11290,9 +11406,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_groupPowers.Clear(); - for (int i = 0; i < GroupMembership.Length; i++) + if (GroupMembership != null) { - m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + for (int i = 0; i < GroupMembership.Length; i++) + { + m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + } } } } @@ -11307,17 +11426,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP return String.Empty; } - public void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) + /// + /// Make an asset request to the asset service in response to a client request. + /// + /// + /// + protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) { UUID requestID = UUID.Zero; - if (transferRequest.TransferInfo.SourceType == 2) + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) { - //direct asset request requestID = new UUID(transferRequest.TransferInfo.Params, 0); } - else if (transferRequest.TransferInfo.SourceType == 3) + else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) { - //inventory asset request requestID = new UUID(transferRequest.TransferInfo.Params, 80); //m_log.Debug("[XXX] inventory asset request " + requestID); //if (taskID == UUID.Zero) // Agent @@ -11330,29 +11452,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP // } } - //check to see if asset is in local cache, if not we need to request it from asset server. - //m_log.Debug("asset request " + requestID); +// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); - } + /// + /// When we get a reply back from the asset service in response to a client request, send back the data. + /// + /// + /// + /// protected void AssetReceived(string id, Object sender, AssetBase asset) { TransferRequestPacket transferRequest = (TransferRequestPacket)sender; UUID requestID = UUID.Zero; - byte source = 2; - if ((transferRequest.TransferInfo.SourceType == 2) || (transferRequest.TransferInfo.SourceType == 2222)) + byte source = (byte)SourceType.Asset; + + if ((transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) + || (transferRequest.TransferInfo.SourceType == 2222)) { - //direct asset request requestID = new UUID(transferRequest.TransferInfo.Params, 0); } - else if ((transferRequest.TransferInfo.SourceType == 3) || (transferRequest.TransferInfo.SourceType == 3333)) + else if ((transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) + || (transferRequest.TransferInfo.SourceType == 3333)) { - //inventory asset request requestID = new UUID(transferRequest.TransferInfo.Params, 80); - source = 3; + source = (byte)SourceType.SimInventoryItem; //m_log.Debug("asset request " + requestID); } @@ -11365,9 +11492,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((userAssets != string.Empty) && (userAssets != m_hyperAssets.GetSimAssetServer())) { m_log.DebugFormat("[CLIENT]: asset {0} not found in local asset storage. Trying user's storage.", id); - if (transferRequest.TransferInfo.SourceType == 2) + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) transferRequest.TransferInfo.SourceType = 2222; // marker - else if (transferRequest.TransferInfo.SourceType == 3) + else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) transferRequest.TransferInfo.SourceType = 3333; // marker m_assetService.Get(userAssets + "/" + id, transferRequest, AssetReceived); @@ -11382,7 +11509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } // Scripts cannot be retrieved by direct request - if (transferRequest.TransferInfo.SourceType == 2 && asset.Type == 10) + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == 10) return; // The asset is known to exist and is in our cache, so add it to the AssetRequests list @@ -11615,6 +11742,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public PacketMethod method; public bool Async; } + public class AsyncPacketProcess { public bool result = false; @@ -11692,4 +11820,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(dialog, ThrottleOutPacketType.Task); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 850474d834..41e41e47a7 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -513,6 +513,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte flags = buffer.Data[0]; bool isResend = (flags & Helpers.MSG_RESENT) != 0; bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; + bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0; LLUDPClient udpClient = outgoingPacket.Client; if (!udpClient.IsConnected) @@ -522,23 +523,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP int dataLength = buffer.DataLength; - // Keep appending ACKs until there is no room left in the buffer or there are - // no more ACKs to append - uint ackCount = 0; - uint ack; - while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack)) + // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here + if (!isZerocoded) { - Utils.UIntToBytesBig(ack, buffer.Data, dataLength); - dataLength += 4; - ++ackCount; - } + // Keep appending ACKs until there is no room left in the buffer or there are + // no more ACKs to append + uint ackCount = 0; + uint ack; + while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack)) + { + Utils.UIntToBytesBig(ack, buffer.Data, dataLength); + dataLength += 4; + ++ackCount; + } - if (ackCount > 0) - { - // Set the last byte of the packet equal to the number of appended ACKs - buffer.Data[dataLength++] = (byte)ackCount; - // Set the appended ACKs flag on this packet - buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); + if (ackCount > 0) + { + // Set the last byte of the packet equal to the number of appended ACKs + buffer.Data[dataLength++] = (byte)ackCount; + // Set the appended ACKs flag on this packet + buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); + } } buffer.DataLength = dataLength; diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index 012d58167f..d30e954a10 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -181,7 +181,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction Manager.MyScene.AssetService.Store(asset); if (part.Inventory.UpdateInventoryItem(item)) + { + remoteClient.SendAgentAlertMessage("Notecard saved", false); part.GetProperties(remoteClient); + } } } } diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 37cdaae2bd..9eaa758bd5 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -406,6 +406,11 @@ namespace Flotsam.RegionModules.AssetCache return asset; } + public AssetBase GetCached(string id) + { + return Get(id); + } + public void Expire(string id) { if (m_LogLevel >= 2) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs new file mode 100644 index 0000000000..53d2cefeac --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -0,0 +1,220 @@ +/* + * 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; +using System.Collections.Specialized; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps +{ + #region Stream Handler + + public delegate byte[] StreamHandlerCallback(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse); + + public class StreamHandler : BaseStreamHandler + { + StreamHandlerCallback m_callback; + + public StreamHandler(string httpMethod, string path, StreamHandlerCallback callback) + : base(httpMethod, path) + { + m_callback = callback; + } + + public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return m_callback(path, request, httpRequest, httpResponse); + } + } + + #endregion Stream Handler + + public class GetTextureModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + private IAssetService m_assetService; + + #region IRegionModule Members + + public void Initialise(Scene pScene, IConfigSource pSource) + { + m_scene = pScene; + } + + public void PostInitialise() + { + m_assetService = m_scene.RequestModuleInterface(); + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void Close() { } + + public string Name { get { return "GetTextureModule"; } } + public bool IsSharedModule { get { return false; } } + + public void RegisterCaps(UUID agentID, Caps caps) + { + UUID capID = UUID.Random(); + + m_log.Info("[GETTEXTURE]: /CAPS/" + capID); + caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); + } + + #endregion + + private byte[] ProcessGetTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + // TODO: Change this to a config option + const string REDIRECT_URL = null; + + // Try to parse the texture ID from the request URL + NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); + string textureStr = query.GetOne("texture_id"); + + if (m_assetService == null) + { + m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return null; + } + + UUID textureID; + if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) + { + AssetBase texture; + + if (!String.IsNullOrEmpty(REDIRECT_URL)) + { + // Only try to fetch locally cached textures. Misses are redirected + texture = m_assetService.GetCached(textureID.ToString()); + + if (texture != null) + { + SendTexture(httpRequest, httpResponse, texture); + } + else + { + string textureUrl = REDIRECT_URL + textureID.ToString(); + m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); + httpResponse.RedirectLocation = textureUrl; + } + } + else + { + // Fetch locally or remotely. Misses return a 404 + texture = m_assetService.Get(textureID.ToString()); + + if (texture != null) + { + SendTexture(httpRequest, httpResponse, texture); + } + else + { + m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + } + } + } + else + { + m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); + } + + httpResponse.Send(); + return null; + } + + private void SendTexture(OSHttpRequest request, OSHttpResponse response, AssetBase texture) + { + string range = request.Headers.GetOne("Range"); + if (!String.IsNullOrEmpty(range)) + { + // Range request + int start, end; + if (TryParseRange(range, out start, out end)) + { + end = Utils.Clamp(end, 1, texture.Data.Length); + start = Utils.Clamp(start, 0, end - 1); + + m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); + + if (end - start < texture.Data.Length) + response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; + + response.ContentLength = end - start; + response.ContentType = texture.Metadata.ContentType; + + response.Body.Write(texture.Data, start, end - start); + } + else + { + m_log.Warn("Malformed Range header: " + range); + response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; + } + } + else + { + // Full content request + response.ContentLength = texture.Data.Length; + response.ContentType = texture.Metadata.ContentType; + response.Body.Write(texture.Data, 0, texture.Data.Length); + } + } + + private bool TryParseRange(string header, out int start, out int end) + { + if (header.StartsWith("bytes=")) + { + string[] rangeValues = header.Substring(6).Split('-'); + if (rangeValues.Length == 2) + { + if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end)) + return true; + } + } + + start = end = 0; + return false; + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 23828efea5..f050dcfba3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -30,6 +30,7 @@ using System.Reflection; using log4net; using Nini.Config; using OpenMetaverse; +using OpenMetaverse.Packets; using OpenSim.Framework; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; @@ -169,6 +170,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return true; } + public void RezMultipleAttachmentsFromInventory( + IClientAPI remoteClient, + RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, + RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) + { + foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) + { + RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); + } + } + public UUID RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing single attachment from item {0} for {1}", itemID, remoteClient.Name); @@ -227,6 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Fire after attach, so we don't get messy perms dialogs // 3 == AttachedRez objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3); + objatt.ResumeScripts(); // Do this last so that event listeners have access to all the effects of the attachment m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); @@ -311,6 +324,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } + public void DetachObject(uint objectLocalID, IClientAPI remoteClient) + { + SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); + if (group != null) + { + //group.DetachToGround(); + ShowDetachInUserInventory(group.GetFromItemID(), remoteClient); + } + } + public void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient) { ScenePresence presence; @@ -329,6 +352,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments DetachSingleAttachmentToInv(itemID, remoteClient); } + public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(itemID); + if (part == null || part.ParentGroup == null) + return; + + UUID inventoryID = part.ParentGroup.GetFromItemID(); + + ScenePresence presence; + if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) + { + if (!m_scene.Permissions.CanRezObject( + part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition)) + return; + + presence.Appearance.DetachAttachment(itemID); + + if (m_scene.AvatarFactory != null) + { + m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + } + part.ParentGroup.DetachToGround(); + + List uuids = new List(); + uuids.Add(inventoryID); + m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); + remoteClient.SendRemoveInventoryItem(inventoryID); + } + + m_scene.EventManager.TriggerOnAttach(part.ParentGroup.LocalId, itemID, UUID.Zero); + } + // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? protected void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient) @@ -359,4 +414,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 16e05b7e1c..2352cedef4 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -601,6 +601,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0); + rootPart.ParentGroup.ResumeScripts(); rootPart.ScheduleFullUpdate(); } diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs index e37da9fdee..36dae6ba9f 100644 --- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs @@ -173,11 +173,11 @@ namespace OpenSim.Region.CoreModules.Framework.Library m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName); simpleName = GetInventoryPathFromName(simpleName); + InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName); try { - InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName); List nodes = archread.Execute(); - if (nodes.Count == 0) + if (nodes != null && nodes.Count == 0) { // didn't find the subfolder with the given name; place it on the top m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName); @@ -185,16 +185,33 @@ namespace OpenSim.Region.CoreModules.Framework.Library archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName); archread.Execute(); } - archread.Close(); + foreach (InventoryNodeBase node in nodes) + FixPerms(node); } catch (Exception e) { - m_log.DebugFormat("[LIBRARY MODULE]: Exception when processing archive {0}: {1}", iarFileName, e.Message); + m_log.DebugFormat("[LIBRARY MODULE]: Exception when processing archive {0}: {1}", iarFileName, e.StackTrace); + } + finally + { + archread.Close(); } } } + private void FixPerms(InventoryNodeBase node) + { + if (node is InventoryItemBase) + { + InventoryItemBase item = (InventoryItemBase)node; + item.BasePermissions = 0x7FFFFFFF; + item.EveryOnePermissions = 0x7FFFFFFF; + item.CurrentPermissions = 0x7FFFFFFF; + item.NextPermissions = 0x7FFFFFFF; + } + } + private void DumpLibrary() { InventoryFolderImpl lib = m_Library.LibraryRootFolder; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index af2f3d6558..ebd6bbdcfa 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -229,6 +229,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { AssetBase asset = null; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 50348da728..1b3419d12f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -165,6 +165,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { AssetBase asset = null; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index e97d21fa1b..a2f26d5a2c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -311,10 +311,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory { // m_log.DebugFormat("[LOCAL INVENTORY SERVICES CONNECTOR]: Requesting inventory item {0}", item.ID); + UUID requestedItemId = item.ID; + item = m_InventoryService.GetItem(item); if (null == item) - m_log.ErrorFormat("[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find item with id {0}", item.ID); + m_log.ErrorFormat( + "[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find item with id {0}", requestedItemId); return item; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs index 488dbd5dbe..3321b38232 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs @@ -144,6 +144,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts return account; } + public override bool StoreUserAccount(UserAccount data) + { + // This remote connector refuses to serve this method + return false; + } + #endregion } } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index b1b2336f83..c52f029c39 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -53,25 +53,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); - private static UTF8Encoding m_utf8Encoding = new UTF8Encoding(); - - private Scene m_scene; - private Stream m_loadStream; - private Guid m_requestId; - private string m_errorMessage; + protected Scene m_scene; + protected Stream m_loadStream; + protected Guid m_requestId; + protected string m_errorMessage; /// /// Should the archive being loaded be merged with what is already on the region? /// - private bool m_merge; + protected bool m_merge; + + /// + /// Should we ignore any assets when reloading the archive? + /// + protected bool m_skipAssets; /// /// Used to cache lookups for valid uuids. /// private IDictionary m_validUserUuids = new Dictionary(); - public ArchiveReadRequest(Scene scene, string loadPath, bool merge, Guid requestId) + public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { m_scene = scene; @@ -89,14 +91,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_errorMessage = String.Empty; m_merge = merge; + m_skipAssets = skipAssets; m_requestId = requestId; } - public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, Guid requestId) + public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) { m_scene = scene; m_loadStream = loadStream; m_merge = merge; + m_skipAssets = skipAssets; m_requestId = requestId; } @@ -133,9 +137,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) { - serialisedSceneObjects.Add(m_utf8Encoding.GetString(data)); + serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); } - else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { if (LoadAsset(filePath, data)) successfulAssetRestores++; @@ -155,7 +159,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver } else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { - serialisedParcels.Add(m_utf8Encoding.GetString(data)); + serialisedParcels.Add(Encoding.UTF8.GetString(data)); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { @@ -178,12 +182,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver archive.Close(); } - m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); - - if (failedAssetRestores > 0) + if (!m_skipAssets) { - m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); - m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); + m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); + + if (failedAssetRestores > 0) + { + m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); + m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); + } } if (!m_merge) @@ -277,6 +284,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver { sceneObjectsLoadedCount++; sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); + sceneObject.ResumeScripts(); } } @@ -541,7 +549,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); XmlTextReader xtr - = new XmlTextReader(m_asciiEncoding.GetString(data), XmlNodeType.Document, context); + = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index fc8d4e1d04..82ede01d01 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -94,8 +94,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void HandleLoadOarConsoleCommand(string module, string[] cmdparams) { bool mergeOar = false; + bool skipAssets = false; OptionSet options = new OptionSet().Add("m|merge", delegate (string v) { mergeOar = v != null; }); + options.Add("s|skip-assets", delegate (string v) { skipAssets = v != null; }); + List mainParams = options.Parse(cmdparams); // m_log.DebugFormat("MERGE OAR IS [{0}]", mergeOar); @@ -105,11 +108,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (mainParams.Count > 2) { - DearchiveRegion(mainParams[2], mergeOar, Guid.Empty); + DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); } else { - DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, mergeOar, Guid.Empty); + DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, mergeOar, skipAssets, Guid.Empty); } } @@ -154,25 +157,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void DearchiveRegion(string loadPath) { - DearchiveRegion(loadPath, false, Guid.Empty); + DearchiveRegion(loadPath, false, false, Guid.Empty); } - public void DearchiveRegion(string loadPath, bool merge, Guid requestId) + public void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId) { m_log.InfoFormat( "[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath); - new ArchiveReadRequest(m_scene, loadPath, merge, requestId).DearchiveRegion(); + new ArchiveReadRequest(m_scene, loadPath, merge, skipAssets, requestId).DearchiveRegion(); } public void DearchiveRegion(Stream loadStream) { - DearchiveRegion(loadStream, false, Guid.Empty); + DearchiveRegion(loadStream, false, false, Guid.Empty); } - public void DearchiveRegion(Stream loadStream, bool merge, Guid requestId) + public void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId) { - new ArchiveReadRequest(m_scene, loadStream, merge, requestId).DearchiveRegion(); + new ArchiveReadRequest(m_scene, loadStream, merge, skipAssets, requestId).DearchiveRegion(); } } } diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index de16d89687..624dc22044 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -442,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests byte[] archive = archiveWriteStream.ToArray(); MemoryStream archiveReadStream = new MemoryStream(archive); - m_archiverModule.DearchiveRegion(archiveReadStream, true, Guid.Empty); + m_archiverModule.DearchiveRegion(archiveReadStream, true, false, Guid.Empty); SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name); Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 0f830e12a1..01359f0db9 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -162,7 +162,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions private Dictionary GrantVB = new Dictionary(); private Dictionary GrantJS = new Dictionary(); private Dictionary GrantYP = new Dictionary(); - private IFriendsModule m_friendsModule = null; + private IFriendsModule m_friendsModule; + private IGroupsModule m_groupsModule; #endregion @@ -386,9 +387,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_friendsModule = m_scene.RequestModuleInterface(); if (m_friendsModule == null) - m_log.Error("[PERMISSIONS]: Friends module not found, friend permissions will not work"); - else - m_log.Info("[PERMISSIONS]: Friends module found, friend permissions enabled"); + m_log.Warn("[PERMISSIONS]: Friends module not found, friend permissions will not work"); + + m_groupsModule = m_scene.RequestModuleInterface(); + + if (m_groupsModule == null) + m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work"); } public void Close() @@ -423,14 +427,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions // with the powers requested (powers = 0 for no powers check) protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers) { - ScenePresence sp = m_scene.GetScenePresence(userID); - if (sp != null) - { - IClientAPI client = sp.ControllingClient; + if (null == m_groupsModule) + return false; - return ((groupID == client.ActiveGroupId) && (client.ActiveGroupPowers != 0) && - ((powers == 0) || ((client.ActiveGroupPowers & powers) == powers))); + GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, userID); + + if (gmd != null) + { + if (((gmd.GroupPowers != 0) && powers == 0) || (gmd.GroupPowers & powers) == powers) + return true; } + return false; } @@ -721,8 +728,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions permission = false; } +// m_log.DebugFormat( +// "[PERMISSIONS]: group.GroupID = {0}, part.GroupMask = {1}, isGroupMember = {2} for {3}", +// group.GroupID, +// m_scene.GetSceneObjectPart(objId).GroupMask, +// IsGroupMember(group.GroupID, currentUser, 0), +// currentUser); + // Group members should be able to edit group objects - if ((group.GroupID != UUID.Zero) && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) && IsGroupMember(group.GroupID, currentUser, 0)) + if ((group.GroupID != UUID.Zero) + && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) + && IsGroupMember(group.GroupID, currentUser, 0)) { // Return immediately, so that the administrator can shares group objects return true; @@ -957,7 +973,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); } @@ -1064,7 +1079,9 @@ namespace OpenSim.Region.CoreModules.World.Permissions if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) return false; - } else { + } + else + { if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; } @@ -1080,7 +1097,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; if (!IsGroupMember(ti.GroupID, user, 0)) - return false; + return false; } // Require full perms @@ -1578,14 +1595,16 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (part.OwnerID != user) { if (part.GroupID == UUID.Zero) - return false; + return false; if (!IsGroupMember(part.GroupID, user, 0)) return false; if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) return false; - } else { + } + else + { if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; } @@ -1840,7 +1859,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions return GenericObjectPermission(agentID, prim, false); } - private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) { + private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) + { //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType); switch (scriptType) { case 0: @@ -1874,4 +1894,4 @@ namespace OpenSim.Region.CoreModules.World.Permissions return(false); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs index 6949d7c2c7..9fc002b7b9 100644 --- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs +++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.DataSnapshot if (!m_configLoaded) { m_configLoaded = true; - m_log.Info("[DATASNAPSHOT]: Loading configuration"); + //m_log.Debug("[DATASNAPSHOT]: Loading configuration"); //Read from the config for options lock (m_syncInit) { @@ -123,7 +123,7 @@ namespace OpenSim.Region.DataSnapshot } catch (Exception) { - m_log.Info("[DATASNAPSHOT]: Could not load configuration. DataSnapshot will be disabled."); + m_log.Warn("[DATASNAPSHOT]: Could not load configuration. DataSnapshot will be disabled."); m_enabled = false; return; } @@ -179,7 +179,7 @@ namespace OpenSim.Region.DataSnapshot } else { - m_log.Warn("[DATASNAPSHOT]: Data snapshot disabled, not adding scene to module (or anything else)."); + //m_log.Debug("[DATASNAPSHOT]: Data snapshot disabled, not adding scene to module (or anything else)."); } } diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 8d27f9cf29..09611af887 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -129,6 +129,7 @@ namespace OpenSim.Region.Examples.SimpleModule public event Action OnRemoveAvatar; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 0222b020c7..f8af36756c 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -27,6 +27,7 @@ using System; using OpenMetaverse; +using OpenMetaverse.Packets; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; @@ -81,6 +82,34 @@ namespace OpenSim.Region.Framework.Interfaces UUID RezSingleAttachmentFromInventory( IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus); + /// + /// Rez multiple attachments from a user's inventory + /// + /// + /// + /// + void RezMultipleAttachmentsFromInventory( + IClientAPI remoteClient, + RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, + RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects); + + /// + /// Detach an object from the avatar. + /// + /// + /// This method is called in response to a client's detach request, so we only update the information in + /// inventory + /// + /// + void DetachObject(uint objectLocalID, IClientAPI remoteClient); + + /// + /// Detach the given item to the ground. + /// + /// + /// + void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient); + /// /// Update the user inventory to the attachment of an item /// diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index f58904f8c8..2b90960936 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -74,6 +74,7 @@ namespace OpenSim.Region.Framework.Interfaces void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource); ArrayList GetScriptErrors(UUID itemID); + void ResumeScripts(); /// /// Stop all the scripts in this entity. diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs new file mode 100644 index 0000000000..f15823659b --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs @@ -0,0 +1,73 @@ +/* + * 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 OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + /// + /// Provide mechanisms for messaging groups. + /// + /// + /// TODO: Provide a mechanism for receiving group messages as well as sending them + /// + public interface IGroupsMessagingModule + { + /// + /// Start a group chat session. + /// + /// You must call this before calling SendMessageToGroup(). If a chat session for this group is already taking + /// place then the agent will added to that session. + /// + /// A UUID that represents the agent being added. If you are agentless (e.g. you are + /// a region module), then you can use any random ID. + /// + /// + /// The ID for the group to join. Currently, the session ID used is identical to the + /// group ID. + /// + /// + /// True if the chat session was started successfully, false otherwise. + /// + bool StartGroupChatSession(UUID agentID, UUID groupID); + + /// + /// Send a message to an entire group. + /// + /// + /// The message itself. The fields that must be populated are + /// + /// imSessionID - Populate this with the group ID (session ID and group ID are currently identical) + /// fromAgentName - Populate this with whatever arbitrary name you want to show up in the chat dialog + /// message - The message itself + /// dialog - This must be (byte)InstantMessageDialog.SessionSend + /// + /// + void SendMessageToGroup(GridInstantMessage im, UUID groupID); + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs index 991d60ca11..89e59d0f17 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs @@ -90,8 +90,12 @@ namespace OpenSim.Region.Framework.Interfaces /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region /// settings in the archive will be ignored. /// + /// + /// If true, the archive is loaded without loading any assets contained within it. This is useful if the + /// assets are already known to be present in the grid's asset service. + /// /// If supplied, this request Id is later returned in the saved event - void DearchiveRegion(string loadPath, bool merge, Guid requestId); + void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId); /// /// Dearchive a region from a stream. This replaces the existing scene. @@ -113,7 +117,11 @@ namespace OpenSim.Region.Framework.Interfaces /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region /// settings in the archive will be ignored. /// + /// + /// If true, the archive is loaded without loading any assets contained within it. This is useful if the + /// assets are already known to be present in the grid's asset service. + /// If supplied, this request Id is later returned in the saved event - void DearchiveRegion(Stream loadStream, bool merge, Guid requestId); + void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId); } } diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index e90b3004fe..fecdd1b9b8 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -41,6 +41,14 @@ namespace OpenSim.Region.Framework.Interfaces bool PostScriptEvent(UUID itemID, string name, Object[] args); bool PostObjectEvent(UUID itemID, string name, Object[] args); + // Suspend ALL scripts in a given scene object. The item ID + // is the UUID of a SOG, and the method acts on all contained + // scripts. This is different from the suspend/resume that + // can be issued by a client. + // + void SuspendScript(UUID itemID); + void ResumeScript(UUID itemID); + ArrayList GetScriptErrors(UUID itemID); } } diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 7307662b2a..de4c5fb053 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -419,11 +419,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation if (m_scenePresence.IsChildAgent) return; - m_scenePresence.Scene.ForEachScenePresence( - delegate(ScenePresence SP) - { - SP.Animator.SendAnimPack(); - }); + UUID[] animIDs; + int[] sequenceNums; + UUID[] objectIDs; + + m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); + client.SendAnimations(animIDs, sequenceNums, m_scenePresence.ControllingClient.AgentId, objectIDs); } /// @@ -451,4 +452,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation m_scenePresence = null; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 31c0be1aff..15b523095f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -35,7 +35,6 @@ using OpenMetaverse; using OpenMetaverse.Packets; using log4net; using OpenSim.Framework; - using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes.Serialization; @@ -64,6 +63,7 @@ namespace OpenSim.Region.Framework.Scenes if (group is SceneObjectGroup) { ((SceneObjectGroup) group).CreateScriptInstances(0, false, DefaultScriptEngine, 0); + ((SceneObjectGroup) group).ResumeScripts(); } } } @@ -202,7 +202,9 @@ namespace OpenSim.Region.Framework.Scenes // Update item with new asset item.AssetID = asset.FullID; - group.UpdateInventoryItem(item); + if (group.UpdateInventoryItem(item)) + remoteClient.SendAgentAlertMessage("Notecard saved", false); + part.GetProperties(remoteClient); // Trigger rerunning of script (use TriggerRezScript event, see RezScript) @@ -219,6 +221,7 @@ namespace OpenSim.Region.Framework.Scenes { remoteClient.SendAgentAlertMessage("Script saved", false); } + part.ParentGroup.ResumeScripts(); return errors; } @@ -472,7 +475,6 @@ namespace OpenSim.Region.Framework.Scenes return null; } - if (recipientParentFolderId == UUID.Zero) { InventoryFolderBase recipientRootFolder = InventoryService.GetRootFolder(recipientId); @@ -722,6 +724,37 @@ namespace OpenSim.Region.Framework.Scenes } } + private void HandleLinkInventoryItem(IClientAPI remoteClient, UUID transActionID, UUID folderID, + uint callbackID, string description, string name, + sbyte invType, sbyte type, UUID olditemID) + { + m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item link {0} in folder {1} pointing to {2}", name, folderID, olditemID); + + if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) + return; + + ScenePresence presence; + if (TryGetScenePresence(remoteClient.AgentId, out presence)) + { + byte[] data = null; + + AssetBase asset = new AssetBase(); + asset.FullID = olditemID; + asset.Type = type; + asset.Name = name; + asset.Description = description; + + CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), folderID, name, 0, callbackID, asset, invType, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch()); + + } + else + { + m_log.ErrorFormat( + "ScenePresence for agent uuid {0} unexpectedly not found in HandleLinkInventoryItem", + remoteClient.AgentId); + } + } + /// /// Remove an inventory item for the client's inventory /// @@ -1160,6 +1193,7 @@ namespace OpenSim.Region.Framework.Scenes item = LibraryService.LibraryRootFolder.FindItem(itemID); } + // If we've found the item in the user's inventory or in the library if (item != null) { part.ParentGroup.AddInventoryItem(remoteClient, primLocalID, item, copyID); @@ -1194,7 +1228,10 @@ namespace OpenSim.Region.Framework.Scenes remoteClient, part, transactionID, currentItem); } if (part.Inventory.UpdateInventoryItem(itemInfo)) + { + remoteClient.SendAgentAlertMessage("Notecard saved", false); part.GetProperties(remoteClient); + } } } else @@ -1246,6 +1283,7 @@ namespace OpenSim.Region.Framework.Scenes // "Rezzed script {0} into prim local ID {1} for user {2}", // item.inventoryName, localID, remoteClient.Name); part.GetProperties(remoteClient); + part.ParentGroup.ResumeScripts(); } else { @@ -1315,6 +1353,7 @@ namespace OpenSim.Region.Framework.Scenes part.GetProperties(remoteClient); part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); + part.ParentGroup.ResumeScripts(); } } @@ -1418,6 +1457,8 @@ namespace OpenSim.Region.Framework.Scenes destPart.Inventory.CreateScriptInstance(destTaskItem, start_param, false, DefaultScriptEngine, 0); } + destPart.ParentGroup.ResumeScripts(); + ScenePresence avatar; if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar)) @@ -1838,50 +1879,6 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerStopScript(part.LocalId, itemID); } - internal void SendAttachEvent(uint localID, UUID itemID, UUID avatarID) - { - EventManager.TriggerOnAttach(localID, itemID, avatarID); - } - - public void RezMultipleAttachments(IClientAPI remoteClient, RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, - RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) - { - foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) - { - AttachmentsModule.RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); - } - } - - public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient) - { - SceneObjectPart part = GetSceneObjectPart(itemID); - if (part == null || part.ParentGroup == null) - return; - - UUID inventoryID = part.ParentGroup.GetFromItemID(); - - ScenePresence presence; - if (TryGetScenePresence(remoteClient.AgentId, out presence)) - { - if (!Permissions.CanRezObject(part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition)) - return; - - presence.Appearance.DetachAttachment(itemID); - IAvatarFactory ava = RequestModuleInterface(); - if (ava != null) - { - ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } - part.ParentGroup.DetachToGround(); - - List uuids = new List(); - uuids.Add(inventoryID); - InventoryService.DeleteItems(remoteClient.AgentId, uuids); - remoteClient.SendRemoveInventoryItem(inventoryID); - } - SendAttachEvent(part.ParentGroup.LocalId, itemID, UUID.Zero); - } - public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) { EventManager.TriggerGetScriptRunning(controllingClient, objectID, itemID); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fc915a38b4..57587bedd4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1131,7 +1131,6 @@ namespace OpenSim.Region.Framework.Scenes { if (m_scripts_enabled != !ScriptEngine) { - // Tedd! Here's the method to disable the scripting engine! if (ScriptEngine) { m_log.Info("Stopping all Scripts in Scene"); @@ -1153,6 +1152,7 @@ namespace OpenSim.Region.Framework.Scenes if (ent is SceneObjectGroup) { ((SceneObjectGroup)ent).CreateScriptInstances(0, false, DefaultScriptEngine, 0); + ((SceneObjectGroup)ent).ResumeScripts(); } } } @@ -2749,6 +2749,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientInventoryEvents(IClientAPI client) { client.OnCreateNewInventoryItem += CreateNewInventoryItem; + client.OnLinkInventoryItem += HandleLinkInventoryItem; client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! @@ -2768,14 +2769,13 @@ namespace OpenSim.Region.Framework.Scenes } public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) - { - client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; - client.OnObjectDetach += m_sceneGraph.DetachObject; - + { if (AttachmentsModule != null) { client.OnRezSingleAttachmentFromInv += AttachmentsModule.RezSingleAttachmentFromInventory; + client.OnRezMultipleAttachmentsFromInv += AttachmentsModule.RezMultipleAttachmentsFromInventory; client.OnObjectAttach += AttachmentsModule.AttachObject; + client.OnObjectDetach += AttachmentsModule.DetachObject; client.OnDetachAttachmentIntoInv += AttachmentsModule.ShowDetachInUserInventory; } } @@ -2924,14 +2924,13 @@ namespace OpenSim.Region.Framework.Scenes } public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) - { - client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; - client.OnObjectDetach -= m_sceneGraph.DetachObject; - + { if (AttachmentsModule != null) { - client.OnRezSingleAttachmentFromInv -= AttachmentsModule.RezSingleAttachmentFromInventory; + client.OnRezSingleAttachmentFromInv -= AttachmentsModule.RezSingleAttachmentFromInventory; + client.OnRezMultipleAttachmentsFromInv -= AttachmentsModule.RezMultipleAttachmentsFromInventory; client.OnObjectAttach -= AttachmentsModule.AttachObject; + client.OnObjectDetach -= AttachmentsModule.DetachObject; client.OnDetachAttachmentIntoInv -= AttachmentsModule.ShowDetachInUserInventory; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 23a4ee9274..1421d0e974 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -443,9 +443,7 @@ namespace OpenSim.Region.Framework.Scenes { SceneObjectGroup group = GetGroupByPrim(objectLocalID); if (group != null) - { - m_parentScene.DetachSingleAttachmentToGround(group.UUID, remoteClient); - } + m_parentScene.AttachmentsModule.DetachSingleAttachmentToGround(group.UUID, remoteClient); } protected internal void DetachObject(uint objectLocalID, IClientAPI remoteClient) @@ -1757,6 +1755,7 @@ namespace OpenSim.Region.Framework.Scenes copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 0); copy.HasGroupChanged = true; copy.ScheduleGroupForFullUpdate(); + copy.ResumeScripts(); // required for physics to update it's position copy.AbsolutePosition = copy.AbsolutePosition; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 71354b4eac..f7e46afa6b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -173,7 +173,9 @@ namespace OpenSim.Region.Framework.Scenes item.NextPermissions; taskItem.NextPermissions = item.NextPermissions; taskItem.CurrentPermissions |= 8; - } else { + } + else + { taskItem.BasePermissions = item.BasePermissions; taskItem.CurrentPermissions = item.CurrentPermissions; taskItem.CurrentPermissions |= 8; @@ -414,5 +416,13 @@ namespace OpenSim.Region.Framework.Scenes scriptModule.SetXMLState(itemID, n.OuterXml); } } + + public void ResumeScripts() + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.Inventory.ResumeScripts(); + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 77bf6fe616..3b1b567557 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -282,36 +282,32 @@ namespace OpenSim.Region.Framework.Scenes return; } - m_part.ParentGroup.Scene.AssetService.Get( - item.AssetID.ToString(), this, delegate(string id, object sender, AssetBase asset) - { - if (null == asset) - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", - item.Name, item.ItemID, m_part.AbsolutePosition, - m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); - } - else - { - if (m_part.ParentGroup.m_savedScriptState != null) - RestoreSavedScriptState(item.OldItemID, item.ItemID); + AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); + if (null == asset) + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", + item.Name, item.ItemID, m_part.AbsolutePosition, + m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); + } + else + { + if (m_part.ParentGroup.m_savedScriptState != null) + RestoreSavedScriptState(item.OldItemID, item.ItemID); - lock (m_items) - { - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; - } - - string script = Utils.BytesToString(asset.Data); - m_part.ParentGroup.Scene.EventManager.TriggerRezScript( - m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); - m_part.ParentGroup.AddActiveScriptCount(1); - m_part.ScheduleFullUpdate(); - } + lock (m_items) + { + m_items[item.ItemID].PermsMask = 0; + m_items[item.ItemID].PermsGranter = UUID.Zero; } - ); + + string script = Utils.BytesToString(asset.Data); + m_part.ParentGroup.Scene.EventManager.TriggerRezScript( + m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); + m_part.ParentGroup.AddActiveScriptCount(1); + m_part.ScheduleFullUpdate(); + } } } @@ -527,6 +523,7 @@ namespace OpenSim.Region.Framework.Scenes item.ParentID = m_part.UUID; item.ParentPartID = m_part.UUID; item.Name = name; + item.GroupID = m_part.GroupID; lock (m_items) { @@ -619,20 +616,16 @@ namespace OpenSim.Region.Framework.Scenes item.ParentID = m_part.UUID; item.ParentPartID = m_part.UUID; item.Flags = m_items[item.ItemID].Flags; + + // If group permissions have been set on, check that the groupID is up to date in case it has + // changed since permissions were last set. + if (item.GroupPermissions != (uint)PermissionMask.None) + item.GroupID = m_part.GroupID; + if (item.AssetID == UUID.Zero) { item.AssetID = m_items[item.ItemID].AssetID; } - else if ((InventoryType)item.Type == InventoryType.Notecard) - { - ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); - - if (presence != null) - { - presence.ControllingClient.SendAgentAlertMessage( - "Notecard saved", false); - } - } m_items[item.ItemID] = item; m_inventorySerial++; @@ -770,6 +763,7 @@ namespace OpenSim.Region.Framework.Scenes uint everyoneMask = 0; uint baseMask = item.BasePermissions; uint ownerMask = item.CurrentPermissions; + uint groupMask = item.GroupPermissions; invString.AddItemStart(); invString.AddNameValueLine("item_id", item.ItemID.ToString()); @@ -779,7 +773,7 @@ namespace OpenSim.Region.Framework.Scenes invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); @@ -1034,5 +1028,28 @@ namespace OpenSim.Region.Framework.Scenes return ret; } + + public void ResumeScripts() + { + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + if (engines == null) + return; + + + lock (m_items) + { + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.InvType == (int)InventoryType.LSL) + { + foreach (IScriptModule engine in engines) + { + if (engine != null) + engine.ResumeScript(item.ItemID); + } + } + } + } + } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b5f621721a..3efb45fa87 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -912,6 +912,7 @@ namespace OpenSim.Region.Framework.Scenes m_isChildAgent = false; + // send the animations of the other presences to me m_scene.ForEachScenePresence(delegate(ScenePresence presence) { if (presence != this) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs index cf0f3451d2..b6677f092e 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs @@ -182,6 +182,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization foreach (SceneObjectGroup sceneObject in sceneObjects) { sceneObject.CreateScriptInstances(0, true, scene.DefaultScriptEngine, 0); + sceneObject.ResumeScripts(); } } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index f5b148f69d..69e78b36ca 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -724,6 +724,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event Action OnRemoveAvatar; public event ObjectPermissions OnObjectPermissions; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs index e664b445f5..d49a4899ca 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs @@ -109,7 +109,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat } else { - m_log.WarnFormat("[IRC-Bridge] Not enabled. Connect for region {0} ignored", scene.RegionInfo.RegionName); + //m_log.DebugFormat("[IRC-Bridge] Not enabled. Connect for region {0} ignored", scene.RegionInfo.RegionName); } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 00fe5df046..185d44de80 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -28,41 +28,30 @@ using System; using System.Collections.Generic; using System.Reflection; - - using log4net; using Mono.Addins; using Nini.Config; - using OpenMetaverse; using OpenMetaverse.StructuredData; - using OpenSim.Framework; using OpenSim.Region.CoreModules.Framework.EventQueue; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; - using Caps = OpenSim.Framework.Capabilities.Caps; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class GroupsMessagingModule : ISharedRegionModule + public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_sceneList = new List(); private IMessageTransferModule m_msgTransferModule = null; - private IGroupsModule m_groupsModule = null; - - // TODO: Move this off to the Groups Server - public Dictionary> m_agentsInGroupSession = new Dictionary>(); - public Dictionary> m_agentsDroppedSession = new Dictionary>(); - + private IGroupsServicesConnector m_groupData = null; // Config Options private bool m_groupMessagingEnabled = false; @@ -108,8 +97,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(Scene scene) { - // NoOp + if (!m_groupMessagingEnabled) + return; + + scene.RegisterModuleInterface(this); } + public void RegionLoaded(Scene scene) { if (!m_groupMessagingEnabled) @@ -117,12 +110,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupsModule = scene.RequestModuleInterface(); + m_groupData = scene.RequestModuleInterface(); // No groups module, no groups messaging - if (m_groupsModule == null) + if (m_groupData == null) { - m_log.Error("[GROUPS-MESSAGING]: Could not get IGroupsModule, GroupsMessagingModule is now disabled."); + m_log.Error("[GROUPS-MESSAGING]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled."); Close(); m_groupMessagingEnabled = false; return; @@ -144,7 +137,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - + scene.EventManager.OnClientLogin += OnClientLogin; } public void RemoveRegion(Scene scene) @@ -172,7 +165,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_sceneList.Clear(); - m_groupsModule = null; + m_groupData = null; m_msgTransferModule = null; } @@ -197,8 +190,84 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion + /// + /// Not really needed, but does confirm that the group exists. + /// + public bool StartGroupChatSession(UUID agentID, UUID groupID) + { + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID, groupID, null); + + if (groupInfo != null) + { + return true; + } + else + { + return false; + } + } + + public void SendMessageToGroup(GridInstantMessage im, UUID groupID) + { + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + + foreach (GroupMembersData member in m_groupData.GetGroupMembers(UUID.Zero, groupID)) + { + if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) + { + // Don't deliver messages to people who have dropped this session + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); + continue; + } + + // Copy Message + GridInstantMessage msg = new GridInstantMessage(); + msg.imSessionID = groupID.Guid; + msg.fromAgentName = im.fromAgentName; + msg.message = im.message; + msg.dialog = im.dialog; + msg.offline = im.offline; + msg.ParentEstateID = im.ParentEstateID; + msg.Position = im.Position; + msg.RegionID = im.RegionID; + msg.binaryBucket = im.binaryBucket; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + + msg.fromAgentID = im.fromAgentID; + msg.fromGroup = true; + + msg.toAgentID = member.AgentID.Guid; + + IClientAPI client = GetActiveClient(member.AgentID); + if (client == null) + { + // If they're not local, forward across the grid + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); + m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); + } + else + { + // Deliver locally, directly + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); + ProcessMessageFromGroupSession(msg); + } + } + } + #region SimGridEventHandlers + void OnClientLogin(IClientAPI client) + { + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); + + + } + private void OnNewClient(IClientAPI client) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); @@ -236,42 +305,46 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); + UUID AgentID = new UUID(msg.fromAgentID); + UUID GroupID = new UUID(msg.imSessionID); + switch (msg.dialog) { case (byte)InstantMessageDialog.SessionAdd: - AddAgentToGroupSession(msg.fromAgentID, msg.imSessionID); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); break; case (byte)InstantMessageDialog.SessionDrop: - RemoveAgentFromGroupSession(msg.fromAgentID, msg.imSessionID); + m_groupData.AgentDroppedFromGroupChatSession(AgentID, GroupID); break; case (byte)InstantMessageDialog.SessionSend: - if (!m_agentsInGroupSession.ContainsKey(msg.toAgentID) - && !m_agentsDroppedSession.ContainsKey(msg.toAgentID)) + if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID) + && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID, GroupID) + ) { // Agent not in session and hasn't dropped from session // Add them to the session for now, and Invite them - AddAgentToGroupSession(msg.toAgentID, msg.imSessionID); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); UUID toAgentID = new UUID(msg.toAgentID); IClientAPI activeClient = GetActiveClient(toAgentID); if (activeClient != null) { - UUID groupID = new UUID(msg.fromAgentID); - - GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); if (groupInfo != null) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); // Force? open the group session dialog??? + // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); IEventQueue eq = activeClient.Scene.RequestModuleInterface(); eq.ChatterboxInvitation( - groupID + GroupID , groupInfo.GroupName , new UUID(msg.fromAgentID) - , msg.message, new UUID(msg.toAgentID) + , msg.message + , new UUID(msg.toAgentID) , msg.fromAgentName , msg.dialog , msg.timestamp @@ -285,7 +358,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ); eq.ChatterBoxSessionAgentListUpdates( - new UUID(groupID) + new UUID(GroupID) , new UUID(msg.fromAgentID) , new UUID(msg.toAgentID) , false //canVoiceChat @@ -295,7 +368,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } } - else if (!m_agentsDroppedSession.ContainsKey(msg.toAgentID)) + else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) { // User hasn't dropped, so they're in the session, // maybe we should deliver it. @@ -321,56 +394,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion + #region ClientEvents - - private void RemoveAgentFromGroupSession(Guid agentID, Guid sessionID) - { - if (m_agentsInGroupSession.ContainsKey(sessionID)) - { - // If in session remove - if (m_agentsInGroupSession[sessionID].Contains(agentID)) - { - m_agentsInGroupSession[sessionID].Remove(agentID); - } - - // If not in dropped list, add - if (!m_agentsDroppedSession[sessionID].Contains(agentID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Dropped {1} from session {0}", sessionID, agentID); - m_agentsDroppedSession[sessionID].Add(agentID); - } - } - } - - private void AddAgentToGroupSession(Guid agentID, Guid sessionID) - { - // Add Session Status if it doesn't exist for this session - CreateGroupSessionTracking(sessionID); - - // If nessesary, remove from dropped list - if (m_agentsDroppedSession[sessionID].Contains(agentID)) - { - m_agentsDroppedSession[sessionID].Remove(agentID); - } - - // If nessesary, add to in session list - if (!m_agentsInGroupSession[sessionID].Contains(agentID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Added {1} to session {0}", sessionID, agentID); - m_agentsInGroupSession[sessionID].Add(agentID); - } - } - - private void CreateGroupSessionTracking(Guid sessionID) - { - if (!m_agentsInGroupSession.ContainsKey(sessionID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Creating session tracking for : {0}", sessionID); - m_agentsInGroupSession.Add(sessionID, new List()); - m_agentsDroppedSession.Add(sessionID, new List()); - } - } - private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { if (m_debugEnabled) @@ -383,21 +408,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Start group IM session if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) { - UUID groupID = new UUID(im.toAgentID); + if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID); - GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); + if (groupInfo != null) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Start Group Session for {0}", groupInfo.GroupName); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); - AddAgentToGroupSession(im.fromAgentID, im.imSessionID); - - ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, groupID); + ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); queue.ChatterBoxSessionAgentListUpdates( - new UUID(groupID) - , new UUID(im.fromAgentID) + GroupID + , AgentID , new UUID(im.toAgentID) , false //canVoiceChat , false //isModerator @@ -409,64 +436,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Send a message from locally connected client to a group if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) { - UUID groupID = new UUID(im.toAgentID); + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", groupID, im.imSessionID.ToString()); + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); - SendMessageToGroup(im, groupID); + //If this agent is sending a message, then they want to be in the session + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); + + SendMessageToGroup(im, GroupID); } } #endregion - private void SendMessageToGroup(GridInstantMessage im, UUID groupID) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - foreach (GroupMembersData member in m_groupsModule.GroupMembersRequest(null, groupID)) - { - if (!m_agentsDroppedSession.ContainsKey(im.imSessionID) || m_agentsDroppedSession[im.imSessionID].Contains(member.AgentID.Guid)) - { - // Don't deliver messages to people who have dropped this session - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); - continue; - } - - // Copy Message - GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = im.imSessionID; - msg.fromAgentName = im.fromAgentName; - msg.message = im.message; - msg.dialog = im.dialog; - msg.offline = im.offline; - msg.ParentEstateID = im.ParentEstateID; - msg.Position = im.Position; - msg.RegionID = im.RegionID; - msg.binaryBucket = im.binaryBucket; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - - // Updat Pertinate fields to make it a "group message" - msg.fromAgentID = groupID.Guid; - msg.fromGroup = true; - - msg.toAgentID = member.AgentID.Guid; - - IClientAPI client = GetActiveClient(member.AgentID); - if (client == null) - { - // If they're not local, forward across the grid - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); - m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); - } - else - { - // Deliver locally, directly - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); - ProcessMessageFromGroupSession(msg); - } - } - } - void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -518,6 +502,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private IClientAPI GetActiveClient(UUID agentID) { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); + IClientAPI child = null; // Try root avatar first @@ -529,16 +515,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ScenePresence user = (ScenePresence)scene.Entities[agentID]; if (!user.IsChildAgent) { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", user.ControllingClient.Name); return user.ControllingClient; } else { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", user.ControllingClient.Name); child = user.ControllingClient; } } } // If we didn't find a root, then just return whichever child we found, or null if none + if (child == null) + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); + } + else + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); + } return child; } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 61c51e077d..56c0d985f1 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -89,16 +89,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private IGroupsServicesConnector m_groupData = null; - class GroupRequestIDInfo - { - public GroupRequestID RequestID = new GroupRequestID(); - public DateTime LastUsedTMStamp = DateTime.MinValue; - } - private Dictionary m_clientRequestIDInfo = new Dictionary(); - private const int m_clientRequestIDFlushTimeOut = 300000; // Every 5 minutes - private Timer m_clientRequestIDFlushTimer; - - // Configuration settings private bool m_groupsEnabled = false; private bool m_groupNoticesEnabled = true; @@ -135,30 +125,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupNoticesEnabled = groupsConfig.GetBoolean("NoticesEnabled", true); m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); - m_clientRequestIDFlushTimer = new Timer(); - m_clientRequestIDFlushTimer.Interval = m_clientRequestIDFlushTimeOut; - m_clientRequestIDFlushTimer.Elapsed += FlushClientRequestIDInfoCache; - m_clientRequestIDFlushTimer.AutoReset = true; - m_clientRequestIDFlushTimer.Start(); - } - } - - void FlushClientRequestIDInfoCache(object sender, ElapsedEventArgs e) - { - lock (m_clientRequestIDInfo) - { - TimeSpan cacheTimeout = new TimeSpan(0,0, m_clientRequestIDFlushTimeOut / 1000); - UUID[] CurrentKeys = new UUID[m_clientRequestIDInfo.Count]; - foreach (UUID key in CurrentKeys) - { - if (m_clientRequestIDInfo.ContainsKey(key)) - { - if (DateTime.Now - m_clientRequestIDInfo[key].LastUsedTMStamp > cacheTimeout) - { - m_clientRequestIDInfo.Remove(key); - } - } - } } } @@ -210,7 +176,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - // The InstantMessageModule itself doesn't do this, // so lets see if things explode if we don't do it // scene.EventManager.OnClientClosed += OnClientClosed; @@ -236,8 +201,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; if (m_debugEnabled) m_log.Debug("[GROUPS]: Shutting down Groups module."); - - m_clientRequestIDFlushTimer.Stop(); } public Type ReplaceableInterface @@ -274,14 +237,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Used for Notices and Group Invites/Accept/Reject client.OnInstantMessage += OnInstantMessage; - lock (m_clientRequestIDInfo) - { - if (m_clientRequestIDInfo.ContainsKey(client.AgentId)) - { - // flush any old RequestID information - m_clientRequestIDInfo.Remove(client.AgentId); - } - } + // Send client thier groups information. SendAgentGroupDataUpdate(client, client.AgentId); } @@ -289,7 +245,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetClientGroupRequestID(remoteClient), avatarID).ToArray(); + //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray(); GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); } @@ -338,9 +294,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); // TODO: This currently ignores pretty much all the query flags including Mature and sort order - remoteClient.SendDirGroupsReply( - queryID, m_groupData.FindGroups(GetClientGroupRequestID(remoteClient), queryText).ToArray()); - } + remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray()); + } + } private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) @@ -352,7 +308,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups string activeGroupName = string.Empty; ulong activeGroupPowers = (ulong)GroupPowers.None; - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetClientGroupRequestID(remoteClient), dataForAgentID); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient), dataForAgentID); if (membership != null) { activeGroupID = membership.GroupID; @@ -371,7 +327,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups string GroupName; - GroupRecord group = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null); + GroupRecord group = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null); if (group != null) { GroupName = group.GroupName; @@ -392,7 +348,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) { UUID inviteID = new UUID(im.imSessionID); - GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); if (inviteInfo == null) { @@ -411,7 +367,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received an accept invite notice."); // and the sessionid is the role - m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); + m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; @@ -435,14 +391,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // TODO: If the inviter is still online, they need an agent dataupdate // and maybe group membership updates for the invitee - m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } // Reject if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice."); - m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } } } @@ -456,7 +412,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } UUID GroupID = new UUID(im.toAgentID); - if (m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null) != null) + if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null) != null) { UUID NoticeID = UUID.Random(); string Subject = im.message.Substring(0, im.message.IndexOf('|')); @@ -500,14 +456,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - m_groupData.AddGroupNotice(GetClientGroupRequestID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); + m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); if (OnNewGroupNotice != null) { OnNewGroupNotice(GroupID, NoticeID); } // Send notice out to everyone that wants notices - foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), GroupID)) + foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID)) { if (m_debugEnabled) { @@ -553,7 +509,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups IClientAPI ejectee = GetActiveClient(ejecteeID); if (ejectee != null) { - UUID groupID = new UUID(im.fromAgentID); + UUID groupID = new UUID(im.imSessionID); ejectee.SendAgentDropGroup(groupID); } } @@ -592,25 +548,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public GroupRecord GetGroupRecord(UUID GroupID) { - return m_groupData.GetGroupRecord(null, GroupID, null); + return m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); } public GroupRecord GetGroupRecord(string name) { - return m_groupData.GetGroupRecord(null, UUID.Zero, name); + return m_groupData.GetGroupRecord(UUID.Zero, UUID.Zero, name); } public void ActivateGroup(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID); + m_groupData.SetAgentActiveGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); // Changing active group changes title, active powers, all kinds of things // anyone who is in any region that can see this client, should probably be // updated with new group info. At a minimum, they should get ScenePresence // updated with new title. - UpdateAllClientsWithGroupInfo(remoteClient.AgentId); + UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); } /// @@ -620,10 +576,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - List agentRoles = m_groupData.GetAgentGroupRoles(grID, remoteClient.AgentId, groupID); - GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(grID, remoteClient.AgentId, groupID); + List agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); + GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); List titles = new List(); foreach (GroupRolesData role in agentRoles) @@ -645,8 +600,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public List GroupMembersRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + List data = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID); - List data = m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), groupID); + if (m_debugEnabled) + { + foreach (GroupMembersData member in data) + { + m_log.DebugFormat("[GROUPS]: Member({0}) - IsOwner({1})", member.AgentID, member.IsOwner); + } + } return data; @@ -656,7 +618,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupRoles(GetClientGroupRequestID(remoteClient), groupID); + List data = m_groupData.GetGroupRoles(GetRequestingAgentID(remoteClient), groupID); return data; } @@ -665,8 +627,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupRoleMembers(GetClientGroupRequestID(remoteClient), groupID); + List data = m_groupData.GetGroupRoleMembers(GetRequestingAgentID(remoteClient), groupID); + if (m_debugEnabled) + { + foreach (GroupRoleMembersData member in data) + { + m_log.DebugFormat("[GROUPS]: Member({0}) - Role({1})", member.MemberID, member.RoleID); + } + } return data; } @@ -676,17 +645,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupProfileData profile = new GroupProfileData(); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - GroupRecord groupInfo = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), groupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); if (groupInfo != null) { profile.AllowPublish = groupInfo.AllowPublish; profile.Charter = groupInfo.Charter; profile.FounderID = groupInfo.FounderID; profile.GroupID = groupID; - profile.GroupMembershipCount = m_groupData.GetGroupMembers(grID, groupID).Count; - profile.GroupRolesCount = m_groupData.GetGroupRoles(grID, groupID).Count; + profile.GroupMembershipCount = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID).Count; + profile.GroupRolesCount = m_groupData.GetGroupRoles(GetRequestingAgentID(remoteClient), groupID).Count; profile.InsigniaID = groupInfo.GroupPicture; profile.MaturePublish = groupInfo.MaturePublish; profile.MembershipFee = groupInfo.MembershipFee; @@ -697,7 +665,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups profile.ShowInList = groupInfo.ShowInList; } - GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(grID, remoteClient.AgentId, groupID); + GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); if (memberInfo != null) { profile.MemberTitle = memberInfo.GroupTitle; @@ -711,7 +679,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - return m_groupData.GetAgentGroupMemberships(null, agentID).ToArray(); + return m_groupData.GetAgentGroupMemberships(UUID.Zero, agentID).ToArray(); } public GroupMembershipData GetMembershipData(UUID groupID, UUID agentID) @@ -721,33 +689,30 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups "[GROUPS]: {0} called with groupID={1}, agentID={2}", System.Reflection.MethodBase.GetCurrentMethod().Name, groupID, agentID); - return m_groupData.GetAgentGroupMembership(null, agentID, groupID); + return m_groupData.GetAgentGroupMembership(UUID.Zero, agentID, groupID); } public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - // TODO: Security Check? - - m_groupData.UpdateGroup(GetClientGroupRequestID(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); + // Note: Permissions checking for modification rights is handled by the Groups Server/Service + m_groupData.UpdateGroup(GetRequestingAgentID(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); } public void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile) { - // TODO: Security Check? + // Note: Permissions checking for modification rights is handled by the Groups Server/Service if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentGroupInfo(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, acceptNotices, listInProfile); + m_groupData.SetAgentGroupInfo(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, acceptNotices, listInProfile); } public UUID CreateGroup(IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - - if (m_groupData.GetGroupRecord(grID, UUID.Zero, name) != null) + if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), UUID.Zero, name) != null) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists."); return UUID.Zero; @@ -761,14 +726,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got issuficient funds to create a group."); return UUID.Zero; } - money.ApplyGroupCreationCharge(remoteClient.AgentId); + money.ApplyGroupCreationCharge(GetRequestingAgentID(remoteClient)); } - UUID groupID = m_groupData.CreateGroup(grID, name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, remoteClient.AgentId); + UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); return groupID; } @@ -779,7 +744,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // ToDo: check if agent is a member of group and is allowed to see notices? - return m_groupData.GetGroupNotices(GetClientGroupRequestID(remoteClient), groupID).ToArray(); + return m_groupData.GetGroupNotices(GetRequestingAgentID(remoteClient), groupID).ToArray(); } /// @@ -789,7 +754,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(null, avatarID); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(UUID.Zero, avatarID); if (membership != null) { return membership.GroupTitle; @@ -804,13 +769,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroupRole(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, titleRoleID); + m_groupData.SetAgentActiveGroupRole(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, titleRoleID); // TODO: Not sure what all is needed here, but if the active group role change is for the group // the client currently has set active, then we need to do a scene presence update too - // if (m_groupData.GetAgentActiveMembership(remoteClient.AgentId).GroupID == GroupID) + // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) - UpdateAllClientsWithGroupInfo(remoteClient.AgentId); + UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); } @@ -820,16 +785,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Security Checks are handled in the Groups Service. - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - switch ((OpenMetaverse.GroupRoleUpdate)updateType) { case OpenMetaverse.GroupRoleUpdate.Create: - m_groupData.AddGroupRole(grID, groupID, UUID.Random(), name, description, title, powers); + m_groupData.AddGroupRole(GetRequestingAgentID(remoteClient), groupID, UUID.Random(), name, description, title, powers); break; case OpenMetaverse.GroupRoleUpdate.Delete: - m_groupData.RemoveGroupRole(grID, groupID, roleID); + m_groupData.RemoveGroupRole(GetRequestingAgentID(remoteClient), groupID, roleID); break; case OpenMetaverse.GroupRoleUpdate.UpdateAll: @@ -840,7 +803,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupPowers gp = (GroupPowers)powers; m_log.DebugFormat("[GROUPS]: Role ({0}) updated with Powers ({1}) ({2})", name, powers.ToString(), gp.ToString()); } - m_groupData.UpdateGroupRole(grID, groupID, roleID, name, description, title, powers); + m_groupData.UpdateGroupRole(GetRequestingAgentID(remoteClient), groupID, roleID, name, description, title, powers); break; case OpenMetaverse.GroupRoleUpdate.NoUpdate: @@ -851,7 +814,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) @@ -859,18 +822,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Todo: Security check - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - switch (changes) { case 0: // Add - m_groupData.AddAgentToGroupRole(grID, memberID, groupID, roleID); + m_groupData.AddAgentToGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); break; case 1: // Remove - m_groupData.RemoveAgentFromGroupRole(grID, memberID, groupID, roleID); + m_groupData.RemoveAgentFromGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); break; default: @@ -879,25 +840,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - - GroupNoticeInfo data = m_groupData.GetGroupNotice(grID, groupNoticeID); + GroupNoticeInfo data = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), groupNoticeID); if (data != null) { - GroupRecord groupInfo = m_groupData.GetGroupRecord(grID, data.GroupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; msg.fromAgentID = data.GroupID.Guid; - msg.toAgentID = remoteClient.AgentId.Guid; + msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName; msg.message = data.noticeData.Subject + "|" + data.Message; @@ -909,7 +868,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.RegionID = UUID.Zero.Guid; msg.binaryBucket = data.BinaryBucket; - OutgoingInstantMessage(msg, remoteClient.AgentId); + OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); } } @@ -929,7 +888,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.Position = Vector3.Zero; msg.RegionID = UUID.Zero.Guid; - GroupNoticeInfo info = m_groupData.GetGroupNotice(null, groupNoticeID); + GroupNoticeInfo info = m_groupData.GetGroupNotice(agentID, groupNoticeID); if (info != null) { msg.fromAgentID = info.GroupID.Guid; @@ -956,7 +915,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Send agent information about his groups - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) @@ -964,19 +923,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Should check to see if OpenEnrollment, or if there's an outstanding invitation - m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, UUID.Zero); + m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, UUID.Zero); remoteClient.SendJoinGroupReply(groupID, true); // Should this send updates to everyone in the group? - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.RemoveAgentFromGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID); + m_groupData.RemoveAgentFromGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); remoteClient.SendLeaveGroupReply(groupID, true); @@ -984,33 +943,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // SL sends out notifcations to the group messaging session that the person has left // Should this also update everyone who is in the group? - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); // Todo: Security check? - m_groupData.RemoveAgentFromGroup(grID, ejecteeID, groupID); + m_groupData.RemoveAgentFromGroup(GetRequestingAgentID(remoteClient), ejecteeID, groupID); - remoteClient.SendEjectGroupMemberReply(remoteClient.AgentId, groupID, true); + remoteClient.SendEjectGroupMemberReply(GetRequestingAgentID(remoteClient), groupID, true); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); - GroupRecord groupInfo = m_groupData.GetGroupRecord(grID, groupID, null); UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, ejecteeID); if ((groupInfo == null) || (account == null)) { return; - } - + } // Send Message to Ejectee GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = remoteClient.AgentId.Guid; + msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; // msg.fromAgentID = info.GroupID; msg.toAgentID = ejecteeID.Guid; //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); @@ -1036,8 +994,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = remoteClient.AgentId.Guid; - msg.toAgentID = remoteClient.AgentId.Guid; + msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; + msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; msg.timestamp = 0; msg.fromAgentName = remoteClient.Name; if (account != null) @@ -1055,7 +1013,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.Position = Vector3.Zero; msg.RegionID = remoteClient.Scene.RegionInfo.RegionID.Guid; msg.binaryBucket = new byte[0]; - OutgoingInstantMessage(msg, remoteClient.AgentId); + OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); // SL sends out messages to everyone in the group @@ -1069,13 +1027,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Todo: Security check, probably also want to send some kind of notification UUID InviteID = UUID.Random(); - GroupRequestID grid = GetClientGroupRequestID(remoteClient); - m_groupData.AddAgentToGroupInvite(grid, InviteID, groupID, roleID, invitedAgentID); + m_groupData.AddAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID, groupID, roleID, invitedAgentID); // Check to see if the invite went through, if it did not then it's possible // the remoteClient did not validate or did not have permission to invite. - GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(grid, InviteID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID); if (inviteInfo != null) { @@ -1087,7 +1044,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.imSessionID = inviteUUID; - // msg.fromAgentID = remoteClient.AgentId.Guid; + // msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; msg.fromAgentID = groupID.Guid; msg.toAgentID = invitedAgentID.Guid; //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); @@ -1140,57 +1097,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return child; } - private GroupRequestID GetClientGroupRequestID(IClientAPI client) - { - if (client == null) - { - return new GroupRequestID(); - } - - lock (m_clientRequestIDInfo) - { - if (!m_clientRequestIDInfo.ContainsKey(client.AgentId)) - { - GroupRequestIDInfo info = new GroupRequestIDInfo(); - info.RequestID.AgentID = client.AgentId; - info.RequestID.SessionID = client.SessionId; - - //UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(client.AgentId); - UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId); - if (account == null) - { - // This should be impossible. If I've been passed a reference to a client - // that client should be registered with the UserService. So something - // is horribly wrong somewhere. - - m_log.WarnFormat("[GROUPS]: Could not find a user profile for {0} / {1}", client.Name, client.AgentId); - - // Default to local user service and hope for the best? - // REFACTORING PROBLEM - //info.RequestID.UserServiceURL = m_sceneList[0].CommsManager.NetworkServersInfo.UserURL; - - } - else - { - string domain = string.Empty; //m_sceneList[0].CommsManager.NetworkServersInfo.UserURL; - object homeUriObj; - if (account.ServiceURLs.TryGetValue("HomeURI", out homeUriObj) && homeUriObj != null) - domain = homeUriObj.ToString(); - // They're a local user, use this: - info.RequestID.UserServiceURL = domain; - } - - m_clientRequestIDInfo.Add(client.AgentId, info); - } - - m_clientRequestIDInfo[client.AgentId].LastUsedTMStamp = DateTime.Now; - - return m_clientRequestIDInfo[client.AgentId].RequestID; - } -// Unreachable code! -// return new GroupRequestID(); - } - /// /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'. /// @@ -1209,7 +1115,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups foreach (GroupMembershipData membership in data) { - if (remoteClient.AgentId != dataForAgentID) + if (GetRequestingAgentID(remoteClient) != dataForAgentID) { if (!membership.ListInProfile) { @@ -1239,11 +1145,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups llDataStruct.Add("GroupData", GroupData); llDataStruct.Add("NewGroupData", NewGroupData); + if (m_debugEnabled) + { + m_log.InfoFormat("[GROUPS]: {0}", OSDParser.SerializeJsonString(llDataStruct)); + } + IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); if (queue != null) { - queue.Enqueue(EventQueueHelper.buildEvent("AgentGroupDataUpdate", llDataStruct), remoteClient.AgentId); + queue.Enqueue(EventQueueHelper.buildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient)); } } @@ -1316,7 +1227,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private GroupMembershipData[] GetProfileListedGroupMemberships(IClientAPI requestingClient, UUID dataForAgentID) { - List membershipData = m_groupData.GetAgentGroupMemberships(GetClientGroupRequestID(requestingClient), dataForAgentID); + List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; if (requestingClient.AgentId != dataForAgentID) @@ -1338,7 +1249,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); foreach (GroupMembershipData membership in membershipArray) { - m_log.InfoFormat("[GROUPS]: {0} :: {1} - {2}", dataForAgentID, membership.GroupName, membership.GroupTitle); + m_log.InfoFormat("[GROUPS]: {0} :: {1} - {2} - {3}", dataForAgentID, membership.GroupName, membership.GroupTitle, membership.GroupPowers); } } @@ -1397,6 +1308,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } #endregion + + private UUID GetRequestingAgentID(IClientAPI client) + { + UUID requestingAgentID = UUID.Zero; + if (client != null) + { + requestingAgentID = client.AgentId; + } + return requestingAgentID; + } } + public class GroupNoticeInfo + { + public GroupNoticeData noticeData = new GroupNoticeData(); + public UUID GroupID = UUID.Zero; + public string Message = string.Empty; + public byte[] BinaryBucket = new byte[0]; + } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs index 621ab28565..a046e094cd 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs @@ -36,41 +36,47 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { interface IGroupsServicesConnector { - UUID CreateGroup(GroupRequestID requestID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); - void UpdateGroup(GroupRequestID requestID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); - GroupRecord GetGroupRecord(GroupRequestID requestID, UUID GroupID, string GroupName); - List FindGroups(GroupRequestID requestID, string search); - List GetGroupMembers(GroupRequestID requestID, UUID GroupID); + UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); + void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); + GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); + List FindGroups(UUID RequestingAgentID, string search); + List GetGroupMembers(UUID RequestingAgentID, UUID GroupID); - void AddGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); - void UpdateGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); - void RemoveGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID); - List GetGroupRoles(GroupRequestID requestID, UUID GroupID); - List GetGroupRoleMembers(GroupRequestID requestID, UUID GroupID); + void AddGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void UpdateGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void RemoveGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID); + List GetGroupRoles(UUID RequestingAgentID, UUID GroupID); + List GetGroupRoleMembers(UUID RequestingAgentID, UUID GroupID); - void AddAgentToGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void RemoveAgentFromGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID); + void AddAgentToGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - void AddAgentToGroupInvite(GroupRequestID requestID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID); - GroupInviteInfo GetAgentToGroupInvite(GroupRequestID requestID, UUID inviteID); - void RemoveAgentToGroupInvite(GroupRequestID requestID, UUID inviteID); + void AddAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID); + GroupInviteInfo GetAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID); + void RemoveAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID); - void AddAgentToGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void RemoveAgentFromGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - List GetAgentGroupRoles(GroupRequestID requestID, UUID AgentID, UUID GroupID); + void AddAgentToGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + List GetAgentGroupRoles(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - void SetAgentActiveGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID); - GroupMembershipData GetAgentActiveMembership(GroupRequestID requestID, UUID AgentID); + void SetAgentActiveGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID); + GroupMembershipData GetAgentActiveMembership(UUID RequestingAgentID, UUID AgentID); - void SetAgentActiveGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void SetAgentGroupInfo(GroupRequestID requestID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); + void SetAgentActiveGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void SetAgentGroupInfo(UUID RequestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); - GroupMembershipData GetAgentGroupMembership(GroupRequestID requestID, UUID AgentID, UUID GroupID); - List GetAgentGroupMemberships(GroupRequestID requestID, UUID AgentID); + GroupMembershipData GetAgentGroupMembership(UUID RequestingAgentID, UUID AgentID, UUID GroupID); + List GetAgentGroupMemberships(UUID RequestingAgentID, UUID AgentID); - void AddGroupNotice(GroupRequestID requestID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); - GroupNoticeInfo GetGroupNotice(GroupRequestID requestID, UUID noticeID); - List GetGroupNotices(GroupRequestID requestID, UUID GroupID); + void AddGroupNotice(UUID RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); + GroupNoticeInfo GetGroupNotice(UUID RequestingAgentID, UUID noticeID); + List GetGroupNotices(UUID RequestingAgentID, UUID GroupID); + + void ResetAgentGroupChatSessions(UUID agentID); + bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID); + bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID); + void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID); + void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID); } public class GroupInviteInfo @@ -80,11 +86,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public UUID AgentID = UUID.Zero; public UUID InviteID = UUID.Zero; } - - public class GroupRequestID - { - public UUID AgentID = UUID.Zero; - public string UserServiceURL = string.Empty; - public UUID SessionID = UUID.Zero; - } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs new file mode 100644 index 0000000000..9363205263 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -0,0 +1,1390 @@ +/* + * 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; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Reflection; + +using Nwc.XmlRpc; + +using log4net; +using Mono.Addins; +using Nini.Config; + +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; + +/*************************************************************************** + * Simian Data Map + * =============== + * + * OwnerID -> Type -> Key + * ----------------------- + * + * UserID -> Group -> ActiveGroup + * + GroupID + * + * UserID -> GroupSessionDropped -> GroupID + * UserID -> GroupSessionInvited -> GroupID + * + * UserID -> GroupMember -> GroupID + * + SelectedRoleID [UUID] + * + AcceptNotices [bool] + * + ListInProfile [bool] + * + Contribution [int] + * + * UserID -> GroupRole[GroupID] -> RoleID + * + * + * GroupID -> Group -> GroupName + * + Charter + * + ShowInList + * + InsigniaID + * + MembershipFee + * + OpenEnrollment + * + AllowPublish + * + MaturePublish + * + FounderID + * + EveryonePowers + * + OwnerRoleID + * + OwnersPowers + * + * GroupID -> GroupRole -> RoleID + * + Name + * + Description + * + Title + * + Powers + * + * GroupID -> GroupMemberInvite -> InviteID + * + AgentID + * + RoleID + * + * GroupID -> GroupNotice -> NoticeID + * + TimeStamp [uint] + * + FromName [string] + * + Subject [string] + * + Message [string] + * + BinaryBucket [byte[]] + * + * */ + +namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | + GroupPowers.Accountable | + GroupPowers.JoinChat | + GroupPowers.AllowVoiceChat | + GroupPowers.ReceiveNotices | + GroupPowers.StartProposal | + GroupPowers.VoteOnProposal; + + // Would this be cleaner as (GroupPowers)ulong.MaxValue; + public const GroupPowers m_DefaultOwnerPowers = GroupPowers.Accountable + | GroupPowers.AllowEditLand + | GroupPowers.AllowFly + | GroupPowers.AllowLandmark + | GroupPowers.AllowRez + | GroupPowers.AllowSetHome + | GroupPowers.AllowVoiceChat + | GroupPowers.AssignMember + | GroupPowers.AssignMemberLimited + | GroupPowers.ChangeActions + | GroupPowers.ChangeIdentity + | GroupPowers.ChangeMedia + | GroupPowers.ChangeOptions + | GroupPowers.CreateRole + | GroupPowers.DeedObject + | GroupPowers.DeleteRole + | GroupPowers.Eject + | GroupPowers.FindPlaces + | GroupPowers.Invite + | GroupPowers.JoinChat + | GroupPowers.LandChangeIdentity + | GroupPowers.LandDeed + | GroupPowers.LandDivideJoin + | GroupPowers.LandEdit + | GroupPowers.LandEjectAndFreeze + | GroupPowers.LandGardening + | GroupPowers.LandManageAllowed + | GroupPowers.LandManageBanned + | GroupPowers.LandManagePasses + | GroupPowers.LandOptions + | GroupPowers.LandRelease + | GroupPowers.LandSetSale + | GroupPowers.ModerateChat + | GroupPowers.ObjectManipulate + | GroupPowers.ObjectSetForSale + | GroupPowers.ReceiveNotices + | GroupPowers.RemoveMember + | GroupPowers.ReturnGroupOwned + | GroupPowers.ReturnGroupSet + | GroupPowers.ReturnNonGroup + | GroupPowers.RoleProperties + | GroupPowers.SendNotices + | GroupPowers.SetLandingPoint + | GroupPowers.StartProposal + | GroupPowers.VoteOnProposal; + + private bool m_connectorEnabled = false; + + private string m_groupsServerURI = string.Empty; + + private bool m_debugEnabled = false; + + private ExpiringCache m_memoryCache; + private int m_cacheTimeout = 30; + + // private IUserAccountService m_accountService = null; + + + #region IRegionModuleBase Members + + public string Name + { + get { return "SimianGroupsServicesConnector"; } + } + + // this module is not intended to be replaced, but there should only be 1 of them. + public Type ReplaceableInterface + { + get { return null; } + } + + public void Initialise(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + + if (groupsConfig == null) + { + // Do not run this module by default. + return; + } + else + { + // if groups aren't enabled, we're not needed. + // if we're not specified as the connector to use, then we're not wanted + if ((groupsConfig.GetBoolean("Enabled", false) == false) + || (groupsConfig.GetString("ServicesConnectorModule", "Default") != Name)) + { + m_connectorEnabled = false; + return; + } + + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name); + + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); + if ((m_groupsServerURI == null) || + (m_groupsServerURI == string.Empty)) + { + m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); + m_connectorEnabled = false; + return; + } + + + m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30); + if (m_cacheTimeout == 0) + { + m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Disabled."); + } + else + { + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Timeout set to {0}.", m_cacheTimeout); + } + + + + m_memoryCache = new ExpiringCache(); + + + // If we got all the config options we need, lets start'er'up + m_connectorEnabled = true; + + m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); + + } + } + + public void Close() + { + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Closing {0}", this.Name); + } + + public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) + { + if (m_connectorEnabled) + { + scene.RegisterModuleInterface(this); + } + } + + public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) + { + if (scene.RequestModuleInterface() == this) + { + scene.UnregisterModuleInterface(this); + } + } + + public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) + { + // TODO: May want to consider listenning for Agent Connections so we can pre-cache group info + // scene.EventManager.OnNewClient += OnNewClient; + } + + #endregion + + #region ISharedRegionModule Members + + public void PostInitialise() + { + // NoOp + } + + #endregion + + + + + #region IGroupsServicesConnector Members + + /// + /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. + /// + public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, + int membershipFee, bool openEnrollment, bool allowPublish, + bool maturePublish, UUID founderID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + UUID GroupID = UUID.Random(); + UUID OwnerRoleID = UUID.Random(); + + OSDMap GroupInfoMap = new OSDMap(); + GroupInfoMap["Charter"] = OSD.FromString(charter); + GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); + GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); + GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); + GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); + GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); + GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); + GroupInfoMap["FounderID"] = OSD.FromUUID(founderID); + GroupInfoMap["EveryonePowers"] = OSD.FromULong((ulong)m_DefaultEveryonePowers); + GroupInfoMap["OwnerRoleID"] = OSD.FromUUID(OwnerRoleID); + GroupInfoMap["OwnersPowers"] = OSD.FromULong((ulong)m_DefaultOwnerPowers); + + if(SimianAddGeneric(GroupID, "Group", name, GroupInfoMap)) + { + AddGroupRole(requestingAgentID, GroupID, UUID.Zero, "Everyone", "Members of " + name, "Member of " + name, (ulong)m_DefaultEveryonePowers); + AddGroupRole(requestingAgentID, GroupID, OwnerRoleID, "Owners", "Owners of " + name, "Owner of " + name, (ulong)m_DefaultOwnerPowers); + + AddAgentToGroup(requestingAgentID, requestingAgentID, GroupID, OwnerRoleID); + + return GroupID; + } + else + { + return UUID.Zero; + } + } + + + public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, + UUID insigniaID, int membershipFee, bool openEnrollment, + bool allowPublish, bool maturePublish) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + // TODO: Check to make sure requestingAgentID has permission to update group + + string GroupName; + OSDMap GroupInfoMap; + if( SimianGetFirstGenericEntry(groupID, "GroupInfo", out GroupName, out GroupInfoMap) ) + { + GroupInfoMap["Charter"] = OSD.FromString(charter); + GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); + GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); + GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); + GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); + GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); + GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); + + SimianAddGeneric(groupID, "Group", GroupName, GroupInfoMap); + } + + } + + + public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + string title, ulong powers) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupRoleInfo = new OSDMap(); + GroupRoleInfo["Name"] = OSD.FromString(name); + GroupRoleInfo["Description"] = OSD.FromString(description); + GroupRoleInfo["Title"] = OSD.FromString(title); + GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); + + // TODO: Add security, make sure that requestingAgentID has permision to add roles + SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); + } + + public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: Add security + + // Can't delete the Everyone Role + if (roleID != UUID.Zero) + { + // Remove all GroupRole Members from Role + Dictionary GroupRoleMembers; + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + if (SimianGetGenericEntries(GroupRoleMemberType, roleID.ToString(), out GroupRoleMembers)) + { + foreach(UUID UserID in GroupRoleMembers.Keys) + { + EnsureRoleNotSelectedByMember(groupID, roleID, UserID); + + SimianRemoveGenericEntry(UserID, GroupRoleMemberType, roleID.ToString()); + } + } + + // Remove role + SimianRemoveGenericEntry(groupID, "GroupRole", roleID.ToString()); + } + } + + + public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + string title, ulong powers) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: Security, check that requestingAgentID is allowed to update group roles + + OSDMap GroupRoleInfo; + if (SimianGetGenericEntry(groupID, "GroupRole", roleID.ToString(), out GroupRoleInfo)) + { + if (name != null) + { + GroupRoleInfo["Name"] = OSD.FromString(name); + } + if (description != null) + { + GroupRoleInfo["Description"] = OSD.FromString(description); + } + if (title != null) + { + GroupRoleInfo["Title"] = OSD.FromString(title); + } + GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); + + } + + + SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); + } + + public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupInfoMap = null; + if (groupID != UUID.Zero) + { + if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out GroupInfoMap)) + { + return null; + } + } + else if ((groupName != null) && (groupName != string.Empty)) + { + if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) + { + return null; + } + } + + GroupRecord GroupInfo = new GroupRecord(); + + GroupInfo.GroupID = groupID; + GroupInfo.GroupName = groupName; + GroupInfo.Charter = GroupInfoMap["Charter"].AsString(); + GroupInfo.ShowInList = GroupInfoMap["ShowInList"].AsBoolean(); + GroupInfo.GroupPicture = GroupInfoMap["InsigniaID"].AsUUID(); + GroupInfo.MembershipFee = GroupInfoMap["MembershipFee"].AsInteger(); + GroupInfo.OpenEnrollment = GroupInfoMap["OpenEnrollment"].AsBoolean(); + GroupInfo.AllowPublish = GroupInfoMap["AllowPublish"].AsBoolean(); + GroupInfo.MaturePublish = GroupInfoMap["MaturePublish"].AsBoolean(); + GroupInfo.FounderID = GroupInfoMap["FounderID"].AsUUID(); + GroupInfo.OwnerRoleID = GroupInfoMap["OwnerRoleID"].AsUUID(); + + return GroupInfo; + + } + + public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID groupID, UUID memberID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap groupProfile; + string groupName; + if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out groupProfile)) + { + // GroupProfileData is not nullable + return new GroupProfileData(); + } + + GroupProfileData MemberGroupProfile = new GroupProfileData(); + MemberGroupProfile.GroupID = groupID; + MemberGroupProfile.Name = groupName; + + if (groupProfile["Charter"] != null) + { + MemberGroupProfile.Charter = groupProfile["Charter"].AsString(); + } + + MemberGroupProfile.ShowInList = groupProfile["ShowInList"].AsString() == "1"; + MemberGroupProfile.InsigniaID = groupProfile["InsigniaID"].AsUUID(); + MemberGroupProfile.MembershipFee = groupProfile["MembershipFee"].AsInteger(); + MemberGroupProfile.OpenEnrollment = groupProfile["OpenEnrollment"].AsBoolean(); + MemberGroupProfile.AllowPublish = groupProfile["AllowPublish"].AsBoolean(); + MemberGroupProfile.MaturePublish = groupProfile["MaturePublish"].AsBoolean(); + MemberGroupProfile.FounderID = groupProfile["FounderID"].AsUUID();; + MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID(); + + Dictionary Members; + if (SimianGetGenericEntries("GroupMember",groupID.ToString(), out Members)) + { + MemberGroupProfile.GroupMembershipCount = Members.Count; + } + + Dictionary Roles; + if (SimianGetGenericEntries(groupID, "GroupRole", out Roles)) + { + MemberGroupProfile.GroupRolesCount = Roles.Count; + } + + // TODO: Get Group Money balance from somewhere + // group.Money = 0; + + GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, memberID, groupID); + + MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; + MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; + + return MemberGroupProfile; + } + + public void SetAgentActiveGroup(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap ActiveGroup = new OSDMap(); + ActiveGroup.Add("GroupID", OSD.FromUUID(groupID)); + SimianAddGeneric(agentID, "Group", "ActiveGroup", ActiveGroup); + } + + public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInfo; + if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) + { + GroupMemberInfo = new OSDMap(); + } + + GroupMemberInfo["SelectedRoleID"] = OSD.FromUUID(roleID); + SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); + } + + public void SetAgentGroupInfo(UUID requestingAgentID, UUID agentID, UUID groupID, bool acceptNotices, bool listInProfile) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInfo; + if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) + { + GroupMemberInfo = new OSDMap(); + } + + GroupMemberInfo["AcceptNotices"] = OSD.FromBoolean(acceptNotices); + GroupMemberInfo["ListInProfile"] = OSD.FromBoolean(listInProfile); + GroupMemberInfo["Contribution"] = OSD.FromInteger(0); + GroupMemberInfo["SelectedRole"] = OSD.FromUUID(UUID.Zero); + SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); + } + + public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap Invite = new OSDMap(); + Invite["AgentID"] = OSD.FromUUID(agentID); + Invite["RoleID"] = OSD.FromUUID(roleID); + + SimianAddGeneric(groupID, "GroupMemberInvite", inviteID.ToString(), Invite); + } + + public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInvite; + UUID GroupID; + if (!SimianGetFirstGenericEntry("GroupMemberInvite", inviteID.ToString(), out GroupID, out GroupMemberInvite)) + { + return null; + } + + GroupInviteInfo inviteInfo = new GroupInviteInfo(); + inviteInfo.InviteID = inviteID; + inviteInfo.GroupID = GroupID; + inviteInfo.AgentID = GroupMemberInvite["AgentID"].AsUUID(); + inviteInfo.RoleID = GroupMemberInvite["RoleID"].AsUUID(); + + return inviteInfo; + } + + public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupInviteInfo invite = GetAgentToGroupInvite(requestingAgentID, inviteID); + SimianRemoveGenericEntry(invite.GroupID, "GroupMemberInvite", inviteID.ToString()); + } + + public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Setup Agent/Group information + SetAgentGroupInfo(requestingAgentID, AgentID, GroupID, true, true); + + // Add agent to Everyone Group + AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, UUID.Zero); + + // Add agent to Specified Role + AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, RoleID); + + // Set selected role in this group to specified role + SetAgentActiveGroupRole(requestingAgentID, AgentID, GroupID, RoleID); + } + + public void RemoveAgentFromGroup(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // If current active group is the group the agent is being removed from, change their group to UUID.Zero + GroupMembershipData memberActiveMembership = GetAgentActiveMembership(requestingAgentID, agentID); + if (memberActiveMembership.GroupID == groupID) + { + SetAgentActiveGroup(agentID, agentID, UUID.Zero); + } + + // Remove Group Member information for this group + SimianRemoveGenericEntry(agentID, "GroupMember", groupID.ToString()); + + // By using a Simian Generics Type consisting of a prefix and a groupID, + // combined with RoleID as key allows us to get a list of roles a particular member + // of a group is assigned to. + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + + // Take Agent out of all other group roles + Dictionary GroupRoles; + if (SimianGetGenericEntries(agentID, GroupRoleMemberType, out GroupRoles)) + { + foreach (string roleID in GroupRoles.Keys) + { + SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID); + } + } + } + + public void AddAgentToGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + SimianAddGeneric(agentID, "GroupRole" + groupID.ToString(), roleID.ToString(), new OSDMap()); + } + + public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Cannot remove members from the Everyone Role + if (roleID != UUID.Zero) + { + EnsureRoleNotSelectedByMember(groupID, roleID, agentID); + + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID.ToString()); + } + } + + public List FindGroups(UUID requestingAgentID, string search) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List findings = new List(); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", "Group" }, + { "Key", search }, + { "Fuzzy", "1" } + }; + + + OSDMap response = CachedPostRequest(requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + DirGroupsReplyData data = new DirGroupsReplyData(); + data.groupID = entryMap["OwnerID"].AsUUID(); + data.groupName = entryMap["Key"].AsString(); + + // TODO: is there a better way to do this? + Dictionary Members; + if (SimianGetGenericEntries("GroupMember", data.groupID.ToString(), out Members)) + { + data.members = Members.Count; + } + else + { + data.members = 0; + } + + // TODO: sort results? + // data.searchOrder = order; + + findings.Add(data); + } + } + + + return findings; + } + + public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupMembershipData data = new GroupMembershipData(); + + /////////////////////////////// + // Agent Specific Information: + // + OSDMap UserActiveGroup; + if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) + { + data.Active = UserActiveGroup["GroupID"].AsUUID().Equals(groupID); + } + + OSDMap UserGroupMemberInfo; + if( SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out UserGroupMemberInfo) ) + { + data.AcceptNotices = UserGroupMemberInfo["AcceptNotices"].AsBoolean(); + data.Contribution = UserGroupMemberInfo["Contribution"].AsInteger(); + data.ListInProfile = UserGroupMemberInfo["ListInProfile"].AsBoolean(); + data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID(); + + /////////////////////////////// + // Role Specific Information: + // + + OSDMap GroupRoleInfo; + if( SimianGetGenericEntry(groupID, "GroupRole", data.ActiveRole.ToString(), out GroupRoleInfo) ) + { + data.GroupTitle = GroupRoleInfo["Title"].AsString(); + data.GroupPowers = GroupRoleInfo["Powers"].AsULong(); + } + } + + /////////////////////////////// + // Group Specific Information: + // + OSDMap GroupInfo; + string GroupName; + if( SimianGetFirstGenericEntry(groupID, "Group", out GroupName, out GroupInfo) ) + { + data.GroupID = groupID; + data.AllowPublish = GroupInfo["AllowPublish"].AsBoolean(); + data.Charter = GroupInfo["Charter"].AsString(); + data.FounderID = GroupInfo["FounderID"].AsUUID(); + data.GroupName = GroupName; + data.GroupPicture = GroupInfo["InsigniaID"].AsUUID(); + data.MaturePublish = GroupInfo["MaturePublish"].AsBoolean(); + data.MembershipFee = GroupInfo["MembershipFee"].AsInteger(); + data.OpenEnrollment = GroupInfo["OpenEnrollment"].AsBoolean(); + data.ShowInList = GroupInfo["ShowInList"].AsBoolean(); + } + + return data; + } + + public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + UUID GroupID = UUID.Zero; + OSDMap UserActiveGroup; + if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) + { + GroupID = UserActiveGroup["GroupID"].AsUUID(); + } + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Active GroupID : {0}", GroupID.ToString()); + return GetAgentGroupMembership(requestingAgentID, agentID, GroupID); + } + + public List GetAgentGroupMemberships(UUID requestingAgentID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List memberships = new List(); + + Dictionary GroupMemberShips; + if (SimianGetGenericEntries(agentID, "GroupMember", out GroupMemberShips)) + { + foreach (string key in GroupMemberShips.Keys) + { + memberships.Add(GetAgentGroupMembership(requestingAgentID, agentID, UUID.Parse(key))); + } + } + + return memberships; + } + + public List GetAgentGroupRoles(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List Roles = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + Dictionary MemberRoles; + if (SimianGetGenericEntries(agentID, "GroupRole" + groupID.ToString(), out MemberRoles)) + { + foreach (KeyValuePair kvp in MemberRoles) + { + GroupRolesData data = new GroupRolesData(); + data.RoleID = UUID.Parse(kvp.Key); + data.Name = GroupRoles[kvp.Key]["Name"].AsString(); + data.Description = GroupRoles[kvp.Key]["Description"].AsString(); + data.Title = GroupRoles[kvp.Key]["Title"].AsString(); + data.Powers = GroupRoles[kvp.Key]["Powers"].AsULong(); + + Roles.Add(data); + } + } + } + return Roles; + } + + public List GetGroupRoles(UUID requestingAgentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List Roles = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + foreach (KeyValuePair role in GroupRoles) + { + GroupRolesData data = new GroupRolesData(); + + data.RoleID = UUID.Parse(role.Key); + + data.Name = role.Value["Name"].AsString(); + data.Description = role.Value["Description"].AsString(); + data.Title = role.Value["Title"].AsString(); + data.Powers = role.Value["Powers"].AsULong(); + + Dictionary GroupRoleMembers; + if (SimianGetGenericEntries("GroupRole" + groupID.ToString(), role.Key, out GroupRoleMembers)) + { + data.Members = GroupRoleMembers.Count; + } + else + { + data.Members = 0; + } + + Roles.Add(data); + } + } + + return Roles; + + } + + + + public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List members = new List(); + + OSDMap GroupInfo; + string GroupName; + UUID GroupOwnerRoleID = UUID.Zero; + if (!SimianGetFirstGenericEntry(GroupID, "Group", out GroupName, out GroupInfo)) + { + return members; + } + GroupOwnerRoleID = GroupInfo["OwnerRoleID"].AsUUID(); + + // Locally cache group roles, since we'll be needing this data for each member + Dictionary GroupRoles; + SimianGetGenericEntries(GroupID, "GroupRole", out GroupRoles); + + // Locally cache list of group owners + Dictionary GroupOwners; + SimianGetGenericEntries("GroupRole" + GroupID.ToString(), GroupOwnerRoleID.ToString(), out GroupOwners); + + + Dictionary GroupMembers; + if (SimianGetGenericEntries("GroupMember", GroupID.ToString(), out GroupMembers)) + { + foreach (KeyValuePair member in GroupMembers) + { + GroupMembersData data = new GroupMembersData(); + + data.AgentID = member.Key; + + UUID SelectedRoleID = member.Value["SelectedRoleID"].AsUUID(); + + data.AcceptNotices = member.Value["AcceptNotices"].AsBoolean(); + data.ListInProfile = member.Value["ListInProfile"].AsBoolean(); + data.Contribution = member.Value["Contribution"].AsInteger(); + + data.IsOwner = GroupOwners.ContainsKey(member.Key); + + OSDMap GroupRoleInfo = GroupRoles[SelectedRoleID.ToString()]; + data.Title = GroupRoleInfo["Title"].AsString(); + data.AgentPowers = GroupRoleInfo["Powers"].AsULong(); + + members.Add(data); + } + } + + return members; + + } + + public List GetGroupRoleMembers(UUID requestingAgentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List members = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + foreach( KeyValuePair Role in GroupRoles ) + { + Dictionary GroupRoleMembers; + if( SimianGetGenericEntries("GroupRole"+groupID.ToString(), Role.Key, out GroupRoleMembers) ) + { + foreach( KeyValuePair GroupRoleMember in GroupRoleMembers ) + { + GroupRoleMembersData data = new GroupRoleMembersData(); + + data.MemberID = GroupRoleMember.Key; + data.RoleID = UUID.Parse(Role.Key); + + members.Add(data); + } + } + } + } + + return members; + } + + public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List values = new List(); + + Dictionary Notices; + if (SimianGetGenericEntries(GroupID, "GroupNotice", out Notices)) + { + foreach (KeyValuePair Notice in Notices) + { + GroupNoticeData data = new GroupNoticeData(); + data.NoticeID = UUID.Parse(Notice.Key); + data.Timestamp = Notice.Value["TimeStamp"].AsUInteger(); + data.FromName = Notice.Value["FromName"].AsString(); + data.Subject = Notice.Value["Subject"].AsString(); + data.HasAttachment = Notice.Value["BinaryBucket"].AsBinary().Length > 0; + + //TODO: Figure out how to get this + data.AssetType = 0; + + values.Add(data); + } + } + + return values; + + } + public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupNotice; + UUID GroupID; + if (SimianGetFirstGenericEntry("GroupNotice", noticeID.ToString(), out GroupID, out GroupNotice)) + { + GroupNoticeInfo data = new GroupNoticeInfo(); + data.GroupID = GroupID; + data.Message = GroupNotice["Message"].AsString(); + data.BinaryBucket = GroupNotice["BinaryBucket"].AsBinary(); + data.noticeData.NoticeID = noticeID; + data.noticeData.Timestamp = GroupNotice["TimeStamp"].AsUInteger(); + data.noticeData.FromName = GroupNotice["FromName"].AsString(); + data.noticeData.Subject = GroupNotice["Subject"].AsString(); + data.noticeData.HasAttachment = data.BinaryBucket.Length > 0; + data.noticeData.AssetType = 0; + + if (data.Message == null) + { + data.Message = string.Empty; + } + + return data; + } + return null; + } + public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap Notice = new OSDMap(); + Notice["TimeStamp"] = OSD.FromUInteger((uint)Util.UnixTimeSinceEpoch()); + Notice["FromName"] = OSD.FromString(fromName); + Notice["Subject"] = OSD.FromString(subject); + Notice["Message"] = OSD.FromString(message); + Notice["BinaryBucket"] = OSD.FromBinary(binaryBucket); + + SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice); + + } + #endregion + + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(UUID agentID) + { + Dictionary agentSessions; + + if (SimianGetGenericEntries(agentID, "GroupSessionDropped", out agentSessions)) + { + foreach (string GroupID in agentSessions.Keys) + { + SimianRemoveGenericEntry(agentID, "GroupSessionDropped", GroupID); + } + } + + if (SimianGetGenericEntries(agentID, "GroupSessionInvited", out agentSessions)) + { + foreach (string GroupID in agentSessions.Keys) + { + SimianRemoveGenericEntry(agentID, "GroupSessionInvited", GroupID); + } + } + } + + public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) + { + OSDMap session; + return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); + } + + public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) + { + SimianAddGeneric(agentID, "GroupSessionDropped", groupID.ToString(), new OSDMap()); + } + + public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + SimianAddGeneric(agentID, "GroupSessionInvited", groupID.ToString(), new OSDMap()); + } + + public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + OSDMap session; + return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); + } + + #endregion + + private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // If member's SelectedRole is roleID, change their selected role to Everyone + // before removing them from the role + OSDMap UserGroupInfo; + if (SimianGetGenericEntry(userID, "GroupMember", groupID.ToString(), out UserGroupInfo)) + { + if (UserGroupInfo["SelectedRoleID"].AsUUID() == roleID) + { + UserGroupInfo["SelectedRoleID"] = OSD.FromUUID(UUID.Zero); + } + SimianAddGeneric(userID, "GroupMember", groupID.ToString(), UserGroupInfo); + } + } + + + #region Simian Util Methods + private bool SimianAddGeneric(UUID ownerID, string type, string key, OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + string value = OSDParser.SerializeJsonString(map); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] value: {0}", value); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "AddGeneric" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key }, + { "Value", value} + }; + + + OSDMap Response = CachedPostRequest(RequestArgs); + if (Response["Success"].AsBoolean()) + { + return true; + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, Response["Message"]); + return false; + } + } + + /// + /// Returns the first of possibly many entries for Owner/Type pair + /// + private bool SimianGetFirstGenericEntry(UUID ownerID, string type, out string key, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type } + }; + + + OSDMap Response = CachedPostRequest(RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count >= 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + key = entryMap["Key"].AsString(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + key = null; + map = null; + return false; + } + private bool SimianGetFirstGenericEntry(string type, string key, out UUID ownerID, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); + + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", type }, + { "Key", key} + }; + + + OSDMap Response = CachedPostRequest(RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count >= 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + ownerID = entryMap["OwnerID"].AsUUID(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + ownerID = UUID.Zero; + map = null; + return false; + } + + private bool SimianGetGenericEntry(UUID ownerID, string type, string key, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key} + }; + + + OSDMap Response = CachedPostRequest(RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count == 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + key = entryMap["Key"].AsString(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + map = null; + return false; + } + + private bool SimianGetGenericEntries(UUID ownerID, string type, out Dictionary maps) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name,ownerID, type); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type } + }; + + + + OSDMap response = CachedPostRequest(requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + maps = new Dictionary(); + + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + maps.Add(entryMap["Key"].AsString(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); + } + if(maps.Count == 0) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + + return true; + } + else + { + maps = null; + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", response["Message"]); + } + return false; + } + private bool SimianGetGenericEntries(string type, string key, out Dictionary maps) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", type }, + { "Key", key } + }; + + + + OSDMap response = CachedPostRequest(requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + maps = new Dictionary(); + + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + maps.Add(entryMap["OwnerID"].AsUUID(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); + } + if (maps.Count == 0) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + return true; + } + else + { + maps = null; + m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR]: Error retrieving group info ({0})", response["Message"]); + } + return false; + } + + private bool SimianRemoveGenericEntry(UUID ownerID, string type, string key) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "RemoveGeneric" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key } + }; + + + OSDMap response = CachedPostRequest(requestArgs); + if (response["Success"].AsBoolean()) + { + return true; + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, response["Message"]); + return false; + } + } + #endregion + + #region CheesyCache + OSDMap CachedPostRequest(NameValueCollection requestArgs) + { + // Immediately forward the request if the cache is disabled. + if (m_cacheTimeout == 0) + { + return WebUtil.PostToService(m_groupsServerURI, requestArgs); + } + + // Check if this is an update or a request + if ( requestArgs["RequestMethod"] == "RemoveGeneric" + || requestArgs["RequestMethod"] == "AddGeneric" + ) + + { + // Any and all updates cause the cache to clear + m_memoryCache.Clear(); + + // Send update to server, return the response without caching it + return WebUtil.PostToService(m_groupsServerURI, requestArgs); + + } + + // If we're not doing an update, we must be requesting data + + // Create the cache key for the request and see if we have it cached + string CacheKey = WebUtil.BuildQueryString(requestArgs); + OSDMap response = null; + if (!m_memoryCache.TryGetValue(CacheKey, out response)) + { + // if it wasn't in the cache, pass the request to the Simian Grid Services + response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + + // and cache the response + m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout)); + } + + // return cached response + return response; + } + #endregion + + } + +} + diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 24ae4f7975..79b9a167d0 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -29,6 +29,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Text; using Nwc.XmlRpc; @@ -40,7 +41,9 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; +using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { @@ -59,13 +62,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_connectorEnabled = false; - private string m_serviceURL = string.Empty; + private string m_groupsServerURI = string.Empty; private bool m_disableKeepAlive = false; private string m_groupReadKey = string.Empty; private string m_groupWriteKey = string.Empty; + private IUserAccountService m_accountService = null; + + private ExpiringCache m_memoryCache; + private int m_cacheTimeout = 30; + + // Used to track which agents are have dropped from a group chat session + // Should be reset per agent, on logon + // TODO: move this to Flotsam XmlRpc Service + // SessionID, List + private Dictionary> m_groupsAgentsDroppedFromChatSession = new Dictionary>(); + private Dictionary> m_groupsAgentsInvitedToChatSession = new Dictionary>(); + #region IRegionModuleBase Members @@ -100,13 +115,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name); - m_serviceURL = groupsConfig.GetString("XmlRpcServiceURL", string.Empty); - if ((m_serviceURL == null) || - (m_serviceURL == string.Empty)) + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); + if ((m_groupsServerURI == null) || + (m_groupsServerURI == string.Empty)) { - m_log.ErrorFormat("Please specify a valid URL for XmlRpcServiceURL in OpenSim.ini, [Groups]"); + m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]"); m_connectorEnabled = false; return; } @@ -116,26 +131,49 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); + + m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30); + if (m_cacheTimeout == 0) + { + m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Disabled."); + } + else + { + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Timeout set to {0}.", m_cacheTimeout); + } + // If we got all the config options we need, lets start'er'up + m_memoryCache = new ExpiringCache(); m_connectorEnabled = true; } } public void Close() { - m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Closing {0}", this.Name); } public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) { if (m_connectorEnabled) + { + + if (m_accountService == null) + { + m_accountService = scene.UserAccountService; + } + + scene.RegisterModuleInterface(this); + } } public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) { if (scene.RequestModuleInterface() == this) + { scene.UnregisterModuleInterface(this); + } } public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) @@ -155,14 +193,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion - - #region IGroupsServicesConnector Members /// /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. /// - public UUID CreateGroup(GroupRequestID requestID, string name, string charter, bool showInList, UUID insigniaID, + public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID) { @@ -234,7 +270,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - Hashtable respData = XmlRpcCall(requestID, "groups.createGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param); if (respData.Contains("error")) { @@ -246,7 +282,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return UUID.Parse((string)respData["GroupID"]); } - public void UpdateGroup(GroupRequestID requestID, UUID groupID, string charter, bool showInList, + public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { @@ -260,10 +296,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AllowPublish"] = allowPublish == true ? 1 : 0; param["MaturePublish"] = maturePublish == true ? 1 : 0; - XmlRpcCall(requestID, "groups.updateGroup", param); + XmlRpcCall(requestingAgentID, "groups.updateGroup", param); } - public void AddGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, + public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -274,19 +310,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Title"] = title; param["Powers"] = powers.ToString(); - XmlRpcCall(requestID, "groups.addRoleToGroup", param); + XmlRpcCall(requestingAgentID, "groups.addRoleToGroup", param); } - public void RemoveGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID) + public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) { Hashtable param = new Hashtable(); param["GroupID"] = groupID.ToString(); param["RoleID"] = roleID.ToString(); - XmlRpcCall(requestID, "groups.removeRoleFromGroup", param); + XmlRpcCall(requestingAgentID, "groups.removeRoleFromGroup", param); } - public void UpdateGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, + public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -306,10 +342,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } param["Powers"] = powers.ToString(); - XmlRpcCall(requestID, "groups.updateGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.updateGroupRole", param); } - public GroupRecord GetGroupRecord(GroupRequestID requestID, UUID GroupID, string GroupName) + public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName) { Hashtable param = new Hashtable(); if (GroupID != UUID.Zero) @@ -321,7 +357,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Name"] = GroupName.ToString(); } - Hashtable respData = XmlRpcCall(requestID, "groups.getGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param); if (respData.Contains("error")) { @@ -332,12 +368,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public GroupProfileData GetMemberGroupProfile(GroupRequestID requestID, UUID GroupID, UUID AgentID) + public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param); if (respData.Contains("error")) { @@ -345,7 +381,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return new GroupProfileData(); } - GroupMembershipData MemberInfo = GetAgentGroupMembership(requestID, AgentID, GroupID); + GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, AgentID, GroupID); GroupProfileData MemberGroupProfile = GroupProfileHashtableToGroupProfileData(respData); MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; @@ -354,26 +390,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return MemberGroupProfile; } - public void SetAgentActiveGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public void SetAgentActiveGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - XmlRpcCall(requestID, "groups.setAgentActiveGroup", param); + XmlRpcCall(requestingAgentID, "groups.setAgentActiveGroup", param); } - public void SetAgentActiveGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["SelectedRoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.setAgentGroupInfo", param); + XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param); } - public void SetAgentGroupInfo(GroupRequestID requestID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + public void SetAgentGroupInfo(UUID requestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); @@ -381,11 +417,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AcceptNotices"] = AcceptNotices ? "1" : "0"; param["ListInProfile"] = ListInProfile ? "1" : "0"; - XmlRpcCall(requestID, "groups.setAgentGroupInfo", param); + XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param); } - public void AddAgentToGroupInvite(GroupRequestID requestID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) + public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); @@ -393,16 +429,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["RoleID"] = roleID.ToString(); param["GroupID"] = groupID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroupInvite", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroupInvite", param); } - public GroupInviteInfo GetAgentToGroupInvite(GroupRequestID requestID, UUID inviteID) + public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentToGroupInvite", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentToGroupInvite", param); if (respData.Contains("error")) { @@ -418,59 +454,59 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return inviteInfo; } - public void RemoveAgentToGroupInvite(GroupRequestID requestID, UUID inviteID) + public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentToGroupInvite", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentToGroupInvite", param); } - public void AddAgentToGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroup", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroup", param); } - public void RemoveAgentFromGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public void RemoveAgentFromGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentFromGroup", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroup", param); } - public void AddAgentToGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void AddAgentToGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroupRole", param); } - public void RemoveAgentFromGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentFromGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroupRole", param); } - public List FindGroups(GroupRequestID requestID, string search) + public List FindGroups(UUID requestingAgentID, string search) { Hashtable param = new Hashtable(); param["Search"] = search; - Hashtable respData = XmlRpcCall(requestID, "groups.findGroups", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.findGroups", param); List findings = new List(); @@ -492,13 +528,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return findings; } - public GroupMembershipData GetAgentGroupMembership(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentGroupMembership", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMembership", param); if (respData.Contains("error")) { @@ -510,12 +546,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } - public GroupMembershipData GetAgentActiveMembership(GroupRequestID requestID, UUID AgentID) + public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID AgentID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentActiveMembership", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentActiveMembership", param); if (respData.Contains("error")) { @@ -525,12 +561,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return HashTableToGroupMembershipData(respData); } - public List GetAgentGroupMemberships(GroupRequestID requestID, UUID AgentID) + public List GetAgentGroupMemberships(UUID requestingAgentID, UUID AgentID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentGroupMemberships", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMemberships", param); List memberships = new List(); @@ -545,13 +581,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return memberships; } - public List GetAgentGroupRoles(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public List GetAgentGroupRoles(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentRoles", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentRoles", param); List Roles = new List(); @@ -577,12 +613,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public List GetGroupRoles(GroupRequestID requestID, UUID GroupID) + public List GetGroupRoles(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupRoles", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoles", param); List Roles = new List(); @@ -610,12 +646,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - public List GetGroupMembers(GroupRequestID requestID, UUID GroupID) + public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupMembers", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupMembers", param); List members = new List(); @@ -643,12 +679,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public List GetGroupRoleMembers(GroupRequestID requestID, UUID GroupID) + public List GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupRoleMembers", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoleMembers", param); List members = new List(); @@ -667,12 +703,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return members; } - public List GetGroupNotices(GroupRequestID requestID, UUID GroupID) + public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupNotices", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotices", param); List values = new List(); @@ -694,12 +730,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return values; } - public GroupNoticeInfo GetGroupNotice(GroupRequestID requestID, UUID noticeID) + public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) { Hashtable param = new Hashtable(); param["NoticeID"] = noticeID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupNotice", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param); if (respData.Contains("error")) @@ -725,7 +761,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } - public void AddGroupNotice(GroupRequestID requestID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) + public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) { string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, ""); @@ -738,7 +774,70 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["BinaryBucket"] = binBucket; param["TimeStamp"] = ((uint)Util.UnixTimeSinceEpoch()).ToString(); - XmlRpcCall(requestID, "groups.addGroupNotice", param); + XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); + } + + + + #endregion + + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(UUID agentID) + { + foreach (List agentList in m_groupsAgentsDroppedFromChatSession.Values) + { + agentList.Remove(agentID); + } + } + + public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + // If we're tracking this group, and we can find them in the tracking, then they've been invited + return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID) + && m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID); + } + + public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) + { + // If we're tracking drops for this group, + // and we find them, well... then they've dropped + return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID) + && m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID); + } + + public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) + { + if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + // If not in dropped list, add + if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID); + } + } + } + + public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + // Add Session Status if it doesn't exist for this session + CreateGroupChatSessionTracking(groupID); + + // If nessesary, remove from dropped list + if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID); + } + } + + private void CreateGroupChatSessionTracking(UUID groupID) + { + if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + m_groupsAgentsDroppedFromChatSession.Add(groupID, new List()); + m_groupsAgentsInvitedToChatSession.Add(groupID, new List()); + } + } #endregion @@ -831,53 +930,86 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Encapsulate the XmlRpc call to standardize security and error handling. /// - private Hashtable XmlRpcCall(GroupRequestID requestID, string function, Hashtable param) + private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) { - if (requestID == null) - { - requestID = new GroupRequestID(); - } - param.Add("RequestingAgentID", requestID.AgentID.ToString()); - param.Add("RequestingAgentUserService", requestID.UserServiceURL); - param.Add("RequestingSessionID", requestID.SessionID.ToString()); - - - param.Add("ReadKey", m_groupReadKey); - param.Add("WriteKey", m_groupWriteKey); - - - IList parameters = new ArrayList(); - parameters.Add(param); - - ConfigurableKeepAliveXmlRpcRequest req; - req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); - XmlRpcResponse resp = null; + string CacheKey = null; - try + // Only bother with the cache if it isn't disabled. + if (m_cacheTimeout > 0) { - resp = req.Send(m_serviceURL, 10000); + if (!function.StartsWith("groups.get")) + { + // Any and all updates cause the cache to clear + m_memoryCache.Clear(); + } + else + { + StringBuilder sb = new StringBuilder(requestingAgentID + function); + foreach (object key in param.Keys) + { + if (param[key] != null) + { + sb.AppendFormat(",{0}:{1}", key.ToString(), param[key].ToString()); + } + } + + CacheKey = sb.ToString(); + m_memoryCache.TryGetValue(CacheKey, out resp); + } + } - catch (Exception e) + + if( resp == null ) { - + string UserService; + UUID SessionID; + GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); + param.Add("requestingAgentID", requestingAgentID.ToString()); + param.Add("RequestingAgentUserService", UserService); + param.Add("RequestingSessionID", SessionID.ToString()); - m_log.ErrorFormat("[XMLRPCGROUPDATA]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", e.ToString()); - foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine },StringSplitOptions.None)) + param.Add("ReadKey", m_groupReadKey); + param.Add("WriteKey", m_groupWriteKey); + + + IList parameters = new ArrayList(); + parameters.Add(param); + + ConfigurableKeepAliveXmlRpcRequest req; + req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); + + + try { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", ResponseLine); - } + resp = req.Send(m_groupsServerURI, 10000); - foreach (string key in param.Keys) + if ((m_cacheTimeout > 0) && (CacheKey != null)) + { + m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout)); + } + + } + catch (Exception e) { - m_log.WarnFormat("[XMLRPCGROUPDATA]: {0} :: {1}", key, param[key].ToString()); - } + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", e.ToString()); - Hashtable respData = new Hashtable(); - respData.Add("error", e.ToString()); - return respData; + foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) + { + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", ResponseLine); + } + + foreach (string key in param.Keys) + { + m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", key, param[key].ToString()); + } + + Hashtable respData = new Hashtable(); + respData.Add("error", e.ToString()); + return respData; + } } if (resp.Value is Hashtable) @@ -891,21 +1023,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return respData; } - m_log.ErrorFormat("[XMLRPCGROUPDATA]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString()); if (resp.Value is ArrayList) { ArrayList al = (ArrayList)resp.Value; - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Contains {0} elements", al.Count); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Contains {0} elements", al.Count); foreach (object o in al) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} :: {1}", o.GetType().ToString(), o.ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", o.GetType().ToString(), o.ToString()); } } else { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Function returned: {0}", resp.Value.ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Function returned: {0}", resp.Value.ToString()); } Hashtable error = new Hashtable(); @@ -915,30 +1047,64 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void LogRespDataToConsoleError(Hashtable respData) { - m_log.Error("[XMLRPCGROUPDATA]: Error:"); + m_log.Error("[XMLRPC-GROUPS-CONNECTOR]: Error:"); foreach (string key in respData.Keys) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Key: {0}", key); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Key: {0}", key); string[] lines = respData[key].ToString().Split(new char[] { '\n' }); foreach (string line in lines) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0}", line); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", line); } } } + + /// + /// Group Request Tokens are an attempt to allow the groups service to authenticate + /// requests. + /// TODO: This broke after the big grid refactor, either find a better way, or discard this + /// + /// + /// + private void GetClientGroupRequestID(UUID AgentID, out string UserServiceURL, out UUID SessionID) + { + UserServiceURL = ""; + SessionID = UUID.Zero; - } - public class GroupNoticeInfo - { - public GroupNoticeData noticeData = new GroupNoticeData(); - public UUID GroupID = UUID.Zero; - public string Message = string.Empty; - public byte[] BinaryBucket = new byte[0]; + // Need to rework this based on changes to User Services + /* + UserAccount userAccount = m_accountService.GetUserAccount(UUID.Zero,AgentID); + if (userAccount == null) + { + // This should be impossible. If I've been passed a reference to a client + // that client should be registered with the UserService. So something + // is horribly wrong somewhere. + + m_log.WarnFormat("[GROUPS]: Could not find a UserServiceURL for {0}", AgentID); + + } + else if (userProfile is ForeignUserProfileData) + { + // They aren't from around here + ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile; + UserServiceURL = fupd.UserServerURI; + SessionID = fupd.CurrentAgent.SessionID; + + } + else + { + // They're a local user, use this: + UserServiceURL = m_commManager.NetworkServersInfo.UserURL; + SessionID = userProfile.CurrentAgent.SessionID; + } + */ + } + } } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 338c04b271..6360c9918d 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -235,6 +235,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event Action OnRemoveAvatar; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs index ae148a9c5a..9f6ea35e31 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs @@ -81,6 +81,9 @@ namespace OpenSim.Region.ScriptEngine.Interfaces void PostEvent(EventParams data); + void Suspend(); + void Resume(); + /// /// Process the next event queued for this script /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index d30d2dcacc..3dd381dd43 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -95,6 +95,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance private bool m_startedFromSavedState; private UUID m_CurrentStateHash; private UUID m_RegionID; + private bool m_Suspended = false; private Dictionary, KeyValuePair> m_LineMap; @@ -638,6 +639,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance /// public object EventProcessor() { + if (m_Suspended) + return 0; + lock (m_Script) { EventParams data = null; @@ -1011,5 +1015,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { get { return m_RegionID; } } + + public void Suspend() + { + m_Suspended = true; + } + + public void Resume() + { + m_Suspended = false; + } } } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 98e77c0b92..54074ed4fd 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1488,5 +1488,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine return new ArrayList(); } } + + public void SuspendScript(UUID itemID) + { + IScriptInstance instance = GetInstance(itemID); + if (instance == null) + return; + + instance.Suspend(); + } + + public void ResumeScript(UUID itemID) + { + IScriptInstance instance = GetInstance(itemID); + if (instance == null) + return; + + instance.Resume(); + } } } diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs index 6a82165134..a1d487128d 100644 --- a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs +++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs @@ -176,18 +176,7 @@ namespace OpenSim.Server.Handlers.UserAccounts byte[] StoreAccount(Dictionary request) { - //if (!request.ContainsKey("account")) - // return FailureResult(); - //if (request["account"] == null) - // return FailureResult(); - //if (!(request["account"] is Dictionary)) - // return FailureResult(); - - UserAccount account = new UserAccount(request); - - if (m_UserAccountService.StoreUserAccount(account)) - return SuccessResult(); - + // No can do. No changing user accounts from remote sims return FailureResult(); } diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs index 10cd9c5b89..d3e65a4bdd 100644 --- a/OpenSim/Server/ServerMain.cs +++ b/OpenSim/Server/ServerMain.cs @@ -47,7 +47,7 @@ namespace OpenSim.Server protected static List m_ServiceConnectors = new List(); - static int Main(string[] args) + public static int Main(string[] args) { m_Server = new HttpServerBase("R.O.B.U.S.T.", args); diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index b9723a84b3..ed87f3f6fc 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -93,6 +93,11 @@ namespace OpenSim.Services.AssetService return m_Database.GetAsset(assetID); } + public AssetBase GetCached(string id) + { + return Get(id); + } + public AssetMetadata GetMetadata(string id) { UUID assetID; diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index a5c157d7f2..65b3537041 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -111,6 +111,14 @@ namespace OpenSim.Services.Connectors return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { if (m_Cache != null) diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs index 677169d76a..34df54a90b 100644 --- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs @@ -116,6 +116,20 @@ namespace OpenSim.Services.Connectors return null; } + public AssetBase GetCached(string id) + { + string url = string.Empty; + string assetID = string.Empty; + + if (StringToUrlAndAssetID(id, out url, out assetID)) + { + IAssetService connector = GetConnector(url); + return connector.GetCached(assetID); + } + + return null; + } + public AssetMetadata GetMetadata(string id) { string url = string.Empty; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 27434ad0de..79e49a11b9 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -112,59 +112,23 @@ namespace OpenSim.Services.Connectors.SimianGrid public AssetBase Get(string id) { - AssetBase asset = null; - // Cache fetch if (m_cache != null) { - asset = m_cache.Get(id); + AssetBase asset = m_cache.Get(id); if (asset != null) return asset; } - Uri url; + return GetRemote(id); + } - // Determine if id is an absolute URL or a grid-relative UUID - if (!Uri.TryCreate(id, UriKind.Absolute, out url)) - url = new Uri(m_serverUrl + id); + public AssetBase GetCached(string id) + { + if (m_cache != null) + return m_cache.Get(id); - try - { - HttpWebRequest request = UntrustedHttpWebRequest.Create(url); - - using (WebResponse response = request.GetResponse()) - { - using (Stream responseStream = response.GetResponseStream()) - { - string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty; - - // Create the asset object - asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID); - - UUID assetID; - if (UUID.TryParse(id, out assetID)) - asset.FullID = assetID; - - // Grab the asset data from the response stream - using (MemoryStream stream = new MemoryStream()) - { - responseStream.CopyTo(stream, Int32.MaxValue); - asset.Data = stream.ToArray(); - } - } - } - - // Cache store - if (m_cache != null && asset != null) - m_cache.Cache(asset); - - return asset; - } - catch (Exception ex) - { - m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); - return null; - } + return null; } /// @@ -245,10 +209,21 @@ namespace OpenSim.Services.Connectors.SimianGrid /// True if the id was parseable, false otherwise public bool Get(string id, Object sender, AssetRetrieved handler) { + // Cache fetch + if (m_cache != null) + { + AssetBase asset = m_cache.Get(id); + if (asset != null) + { + handler(id, sender, asset); + return true; + } + } + Util.FireAndForget( delegate(object o) { - AssetBase asset = Get(id); + AssetBase asset = GetRemote(id); handler(id, sender, asset); } ); @@ -406,5 +381,53 @@ namespace OpenSim.Services.Connectors.SimianGrid } #endregion IAssetService + + private AssetBase GetRemote(string id) + { + AssetBase asset = null; + Uri url; + + // Determine if id is an absolute URL or a grid-relative UUID + if (!Uri.TryCreate(id, UriKind.Absolute, out url)) + url = new Uri(m_serverUrl + id); + + try + { + HttpWebRequest request = UntrustedHttpWebRequest.Create(url); + + using (WebResponse response = request.GetResponse()) + { + using (Stream responseStream = response.GetResponseStream()) + { + string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty; + + // Create the asset object + asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID); + + UUID assetID; + if (UUID.TryParse(id, out assetID)) + asset.FullID = assetID; + + // Grab the asset data from the response stream + using (MemoryStream stream = new MemoryStream()) + { + responseStream.CopyTo(stream, Int32.MaxValue); + asset.Data = stream.ToArray(); + } + } + } + + // Cache store + if (m_cache != null && asset != null) + m_cache.Cache(asset); + + return asset; + } + catch (Exception ex) + { + m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); + return null; + } + } } } diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs index e78429d29b..b19135e0c5 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -104,6 +104,8 @@ namespace OpenSim.Services.Connectors.SimianGrid OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Identities"] is OSDArray) { + bool md5hashFound = false; + OSDArray identities = (OSDArray)response["Identities"]; for (int i = 0; i < identities.Count; i++) { @@ -114,13 +116,19 @@ namespace OpenSim.Services.Connectors.SimianGrid { string credential = identity["Credential"].AsString(); - if (password == credential || "$1$" + Utils.MD5String(password) == credential) + if (password == credential || "$1$" + Utils.MD5String(password) == credential || Utils.MD5String(password) == credential) return Authorize(principalID); + + md5hashFound = true; + break; } } } - m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + principalID); + if (md5hashFound) + m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + principalID + " using md5hash $1$" + Utils.MD5String(password)); + else + m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + principalID + ", no md5hash identity found"); } else { diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index 56e74755bb..dc68259d93 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -583,6 +583,14 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Permissions", permissions } }; + // Add different asset type only if it differs from inventory type + // (needed for links) + string invContentType = SLUtil.SLInvTypeToContentType(item.InvType); + string assetContentType = SLUtil.SLAssetTypeToContentType(item.AssetType); + + if (invContentType != assetContentType) + extraData["LinkedItemType"] = OSD.FromString(assetContentType); + NameValueCollection requestArgs = new NameValueCollection { { "RequestMethod", "AddInventoryItem" }, @@ -593,6 +601,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Name", item.Name }, { "Description", item.Description }, { "CreatorID", item.CreatorId }, + { "ContentType", invContentType }, { "ExtraData", OSDParser.SerializeJsonString(extraData) } }; @@ -781,6 +790,9 @@ namespace OpenSim.Services.Connectors.SimianGrid invItem.GroupPermissions = perms["GroupMask"].AsUInteger(); invItem.NextPermissions = perms["NextOwnerMask"].AsUInteger(); } + + if (extraData.ContainsKey("LinkedItemType")) + invItem.AssetType = SLUtil.ContentTypeToSLAssetType(extraData["LinkedItemType"].AsString()); } if (invItem.BasePermissions == 0) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index 696be94ce9..c324272093 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -395,7 +395,7 @@ namespace OpenSim.Services.Connectors.SimianGrid } else { - m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve sessions for " + userID + ": " + response["Message"].AsString()); + m_log.Debug("[SIMIAN PRESENCE CONNECTOR]: No session returned for " + userID + ": " + response["Message"].AsString()); } } diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs index 2f9b520de9..1527db20df 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs @@ -187,7 +187,7 @@ namespace OpenSim.Services.Connectors return accounts; } - public bool StoreUserAccount(UserAccount data) + public virtual bool StoreUserAccount(UserAccount data) { Dictionary sendData = new Dictionary(); //sendData["SCOPEID"] = scopeID.ToString(); diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index 6dfe78d724..3be6815728 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs @@ -51,7 +51,15 @@ namespace OpenSim.Services.Interfaces byte[] GetData(string id); /// - /// Get an asset asynchronously + /// Synchronously fetches an asset from the local cache only + /// + /// Asset ID + /// The fetched asset, or null if it did not exist in the local cache + AssetBase GetCached(string id); + + /// + /// Get an asset synchronously or asynchronously (depending on whether + /// it is locally cached) and fire a callback with the fetched asset /// /// The asset id /// Represents the requester. Passed back via the handler diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 38caf745fe..7b38aa69f9 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -134,6 +134,10 @@ namespace OpenSim.Services.UserAccountService u.UserTitle = d.Data["UserTitle"].ToString(); else u.UserTitle = string.Empty; + if (d.Data.ContainsKey("UserLevel") && d.Data["UserLevel"] != null) + Int32.TryParse(d.Data["UserLevel"], out u.UserLevel); + if (d.Data.ContainsKey("UserFlags") && d.Data["UserFlags"] != null) + Int32.TryParse(d.Data["UserFlags"], out u.UserFlags); if (d.Data.ContainsKey("ServiceURLs") && d.Data["ServiceURLs"] != null) { @@ -218,6 +222,10 @@ namespace OpenSim.Services.UserAccountService d.Data = new Dictionary(); d.Data["Email"] = data.Email; d.Data["Created"] = data.Created.ToString(); + d.Data["UserLevel"] = data.UserLevel.ToString(); + d.Data["UserFlags"] = data.UserFlags.ToString(); + if (data.UserTitle != null) + d.Data["UserTitle"] = data.UserTitle.ToString(); List parts = new List(); diff --git a/OpenSim/Tests/Common/Mock/MockAssetService.cs b/OpenSim/Tests/Common/Mock/MockAssetService.cs index cb380431d4..4118308bed 100644 --- a/OpenSim/Tests/Common/Mock/MockAssetService.cs +++ b/OpenSim/Tests/Common/Mock/MockAssetService.cs @@ -65,6 +65,11 @@ namespace OpenSim.Tests.Common.Mock return asset; } + public AssetBase GetCached(string id) + { + return Get(id); + } + public AssetMetadata GetMetadata(string id) { throw new System.NotImplementedException(); diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index f015db2c84..b07a0727a3 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -141,6 +141,7 @@ namespace OpenSim.Tests.Common.Mock public event Action OnRemoveAvatar; public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event LinkInventoryItem OnLinkInventoryItem; public event CreateInventoryFolder OnCreateNewInventoryFolder; public event UpdateInventoryFolder OnUpdateInventoryFolder; public event MoveInventoryFolder OnMoveInventoryFolder; diff --git a/OpenSim/Tools/Robust.32BitLaunch/Program.cs b/OpenSim/Tools/Robust.32BitLaunch/Program.cs new file mode 100644 index 0000000000..490414c456 --- /dev/null +++ b/OpenSim/Tools/Robust.32BitLaunch/Program.cs @@ -0,0 +1,60 @@ +/* + * 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 log4net; + +namespace Robust._32BitLaunch +{ + class Program + { + static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + System.Console.WriteLine("32-bit OpenSim executor"); + System.Console.WriteLine("-----------------------"); + System.Console.WriteLine(""); + System.Console.WriteLine("This application is compiled for 32-bit CPU and will run under WOW32 or similar."); + System.Console.WriteLine("All 64-bit incompatibilities should be gone."); + System.Console.WriteLine(""); + System.Threading.Thread.Sleep(300); + try + { + global::OpenSim.Server.OpenSimServer.Main(args); + } + catch (Exception ex) + { + System.Console.WriteLine("OpenSim threw an exception:"); + System.Console.WriteLine(ex.ToString()); + System.Console.WriteLine(""); + System.Console.WriteLine("Application will now terminate!"); + System.Console.WriteLine(""); + } + } + } +} diff --git a/OpenSim/Tools/Robust.32BitLaunch/Properties/AssemblyInfo.cs b/OpenSim/Tools/Robust.32BitLaunch/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..cf80f472ef --- /dev/null +++ b/OpenSim/Tools/Robust.32BitLaunch/Properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +/* + * 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Robust.32BitLaunch")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("http://opensimulator.org")] +[assembly: AssemblyProduct("Robust.32BitLaunch")] +[assembly: AssemblyCopyright("Copyright (c) 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5072e919-46ab-47e6-8a63-08108324ccdf")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("0.6.3.*")] +[assembly: AssemblyVersion("0.6.3.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj new file mode 100644 index 0000000000..f19e082c28 --- /dev/null +++ b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj @@ -0,0 +1,62 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {595D67F3-B413-4A43-8568-5B5930E3B31D} + Exe + Properties + Robust._32BitLaunch + Robust.32BitLaunch + v3.5 + 512 + + + true + full + false + ..\..\..\bin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\..\bin\log4net.dll + + + False + ..\..\..\bin\OpenSim.Server.exe + + + + 3.5 + + + + + + + + + + + \ No newline at end of file diff --git a/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln new file mode 100644 index 0000000000..c7c97b1d93 --- /dev/null +++ b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C# Express 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robust.32BitLaunch", "Robust.32BitLaunch.csproj", "{595D67F3-B413-4A43-8568-5B5930E3B31D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/README.txt b/README.txt index ed59bf56b7..f1a71beadf 100644 --- a/README.txt +++ b/README.txt @@ -59,7 +59,8 @@ Once you are presented with a prompt that looks like: You have successfully started OpenSim. -Before you can log in you will need to create a user account. You can do +Before you can log in you will need to create a user account if you didn't already create +your user as the "Master Avatar" during the region configuration stage. You can do this by running the "create user" command on the OpenSim console. This will ask you a series of questions such as first name, last name and password. diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 24573185d1..06306885db 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -1176,10 +1176,18 @@ ;MessagingModule = GroupsMessagingModule ;MessagingEnabled = true - ; Service connector to Groups Service [Select One] - ; XmlRpc Service Connector to the Flotsam XmlRpc Groups Service Implementation + ; Service connector to Groups Service [Select One] ServicesConnectorModule + + + ; Simian Grid Service for Groups + ;ServicesConnectorModule = SimianGroupsServicesConnector + ;GroupsServerURI = http://mygridserver.com:82/Grid/ + + ; XmlRpc Service Connector to the Flotsam XmlRpc Groups Service settings ;ServicesConnectorModule = XmlRpcGroupsServicesConnector - ;XmlRpcServiceURL = http://yourxmlrpcserver.com/xmlrpc.php + ;GroupsServerURI = http://yourxmlrpcserver.com/xmlrpc.php + + ; XmlRpc Service Settings ;XmlRpcServiceReadKey = 1234 ;XmlRpcServiceWriteKey = 1234 diff --git a/bin/Robust.32BitLaunch.exe b/bin/Robust.32BitLaunch.exe new file mode 100644 index 0000000000..14a6db3f1f Binary files /dev/null and b/bin/Robust.32BitLaunch.exe differ diff --git a/bin/Robust.32BitLaunch.exe.config b/bin/Robust.32BitLaunch.exe.config new file mode 100644 index 0000000000..dae45ffaaa --- /dev/null +++ b/bin/Robust.32BitLaunch.exe.config @@ -0,0 +1,32 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 47175613c0..6e27694cd6 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -52,6 +52,12 @@ ; FriendsServerURI = "http://mygridserver.com:8003" +[Groups] + ; + ; change this to your grid-wide groups server + ; + GroupsServerURI = "http://mygridserver.com:82/Grid/" + [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. diff --git a/bin/config-include/SimianGrid.ini b/bin/config-include/SimianGrid.ini index 064f36ec89..41deb92db2 100644 --- a/bin/config-include/SimianGrid.ini +++ b/bin/config-include/SimianGrid.ini @@ -15,6 +15,7 @@ ; UserAccountServerURI = "http://www.mygrid.com/Grid/" ; AuthenticationServerURI = "http://www.mygrid.com/Grid/" ; FriendsServerURI = "http://www.mygrid.com/Grid/" +; GroupsServerURI = "http://www.mygrid.com/Grid/" [Includes] Include-Common = "config-include/GridCommon.ini" @@ -55,3 +56,12 @@ [AssetService] DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" AssetLoaderArgs = "assets/AssetSets.xml" + +[Groups] + Enabled = true + Module = GroupsModule + DebugEnabled = false + NoticesEnabled = true + MessagingModule = GroupsMessagingModule + MessagingEnabled = true + ServicesConnectorModule = SimianGroupsServicesConnector