diff --git a/OpenSim/Data/IXGroupData.cs b/OpenSim/Data/IXGroupData.cs new file mode 100644 index 0000000000..2965e8cc3d --- /dev/null +++ b/OpenSim/Data/IXGroupData.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data +{ + public class XGroup + { + public UUID groupID; + public UUID ownerRoleID; + public string name; + public string charter; + public bool showInList; + public UUID insigniaID; + public int membershipFee; + public bool openEnrollment; + public bool allowPublish; + public bool maturePublish; + public UUID founderID; + public ulong everyonePowers; + public ulong ownersPowers; + + public XGroup Clone() + { + return (XGroup)MemberwiseClone(); + } + } + + /// + /// Early stub interface for groups data, not final. + /// + /// + /// Currently in-use only for regression test purposes. Needs to be filled out over time. + /// + public interface IXGroupData + { + bool StoreGroup(XGroup group); + XGroup[] GetGroups(string field, string val); + XGroup[] GetGroups(string[] fields, string[] vals); + bool DeleteGroups(string field, string val); + bool DeleteGroups(string[] fields, string[] vals); + } +} \ No newline at end of file diff --git a/OpenSim/Data/Null/NullGenericDataHandler.cs b/OpenSim/Data/Null/NullGenericDataHandler.cs new file mode 100644 index 0000000000..dd9d190910 --- /dev/null +++ b/OpenSim/Data/Null/NullGenericDataHandler.cs @@ -0,0 +1,67 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Data; + +namespace OpenSim.Data.Null +{ + /// + /// Not a proper generic data handler yet - probably needs to actually store the data as well instead of relying + /// on descendent classes + /// + public class NullGenericDataHandler + { + protected List Get(string[] fields, string[] vals, List inputEntities) + { + List entities = inputEntities; + + for (int i = 0; i < fields.Length; i++) + { + entities + = entities.Where( + e => + { + FieldInfo fi = typeof(T).GetField(fields[i]); + if (fi == null) + throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i])); + + return fi.GetValue(e).ToString() == vals[i]; + } + ).ToList(); + } + + return entities; + } + } +} \ No newline at end of file diff --git a/OpenSim/Data/Null/NullXGroupData.cs b/OpenSim/Data/Null/NullXGroupData.cs new file mode 100644 index 0000000000..7a86b9f230 --- /dev/null +++ b/OpenSim/Data/Null/NullXGroupData.cs @@ -0,0 +1,90 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Threading; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Data; + +namespace OpenSim.Data.Null +{ + public class NullXGroupData : NullGenericDataHandler, IXGroupData + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary m_groups = new Dictionary(); + + public NullXGroupData(string connectionString, string realm) {} + + public bool StoreGroup(XGroup group) + { + lock (m_groups) + { + m_groups[group.groupID] = group.Clone(); + } + + return true; + } + + public XGroup[] GetGroups(string field, string val) + { + return GetGroups(new string[] { field }, new string[] { val }); + } + + public XGroup[] GetGroups(string[] fields, string[] vals) + { + lock (m_groups) + { + List origGroups = Get(fields, vals, m_groups.Values.ToList()); + + return origGroups.Select(g => g.Clone()).ToArray(); + } + } + + public bool DeleteGroups(string field, string val) + { + return DeleteGroups(new string[] { field }, new string[] { val }); + } + + public bool DeleteGroups(string[] fields, string[] vals) + { + lock (m_groups) + { + XGroup[] groupsToDelete = GetGroups(fields, vals); + Array.ForEach(groupsToDelete, g => m_groups.Remove(g.groupID)); + } + + return true; + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs index 48f1c4f94f..0c12787882 100644 --- a/OpenSim/Framework/Serialization/ArchiveConstants.cs +++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs @@ -154,6 +154,11 @@ namespace OpenSim.Framework.Serialization EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; } + public static string CreateOarLandDataPath(LandData ld) + { + return string.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, ld.GlobalID); + } + /// /// Create the filename used to store an object in an OpenSim Archive. /// diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 60bbf9b2aa..c8102424e8 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -552,19 +552,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Validate User and Group UUID's - if (!ResolveUserUuid(scene, parcel.OwnerID)) - parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; - - if (!ResolveGroupUuid(parcel.GroupID)) + if (parcel.IsGroupOwned) { -// m_log.DebugFormat("[ARCHIVE READ REQUEST]: Could not find group {0}", parcel.GroupID); - parcel.GroupID = UUID.Zero; - parcel.IsGroupOwned = false; + if (!ResolveGroupUuid(parcel.GroupID)) + { + parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; + parcel.GroupID = UUID.Zero; + parcel.IsGroupOwned = false; + } + } + else + { + if (!ResolveUserUuid(scene, parcel.OwnerID)) + parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; + + if (!ResolveGroupUuid(parcel.GroupID)) + parcel.GroupID = UUID.Zero; } -// else -// { -// m_log.DebugFormat("[ARCHIVE READ REQUEST]: Found group {0}", parcel.GroupID); -// } List accessList = new List(); foreach (LandAccessEntry entry in parcel.ParcelAccessList) @@ -576,8 +580,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver parcel.ParcelAccessList = accessList; // m_log.DebugFormat( -// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", -// parcel.Name, parcel.LocalID, parcel.Area); +// "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}", +// parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area); landData.Add(parcel); } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs index d751b1c990..7bdd65c60b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs @@ -167,7 +167,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver } scenesGroup.CalcSceneLocations(); - m_archiveWriter = new TarArchiveWriter(m_saveStream); try @@ -216,7 +215,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary assetUuids) { m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); @@ -540,7 +538,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); } - protected void Save(Scene scene, List sceneObjects, string regionDir) { if (regionDir != string.Empty) @@ -560,8 +557,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (ILandObject lo in landObjects) { LandData landData = lo.LandData; - string landDataPath = String.Format("{0}{1}{2}.xml", - regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); + string landDataPath + = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData)); m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); } @@ -604,7 +601,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver CloseArchive(String.Empty); } - /// /// Closes the archive and notifies that we're done. @@ -629,6 +625,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); } - } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 82f49b0dfa..7cc3519870 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -31,16 +31,19 @@ using System.IO; using System.Reflection; using System.Threading; using log4net.Config; +using Nini.Config; using NUnit.Framework; using OpenMetaverse; using OpenMetaverse.Assets; using OpenSim.Framework; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; +using OpenSim.Region.CoreModules.World.Land; using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.World.Terrain; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; @@ -127,6 +130,53 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; } + + private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) + { + SceneObjectPart part1 = CreateSceneObjectPart1(); + sog1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(sog1, false); + + AssetNotecard nc = new AssetNotecard(); + nc.BodyText = "Hello World!"; + nc.Encode(); + ncAssetUuid = UUID.Random(); + UUID ncItemUuid = UUID.Random(); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + m_scene.AssetService.Store(ncAsset); + + TaskInventoryItem ncItem + = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; + SceneObjectPart part2 = CreateSceneObjectPart2(); + sog2 = new SceneObjectGroup(part2); + part2.Inventory.AddInventoryItem(ncItem, true); + + scene.AddNewSceneObject(sog2, false); + } + + private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) + { + using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) + { + using (BinaryReader br = new BinaryReader(resource)) + { + // FIXME: Use the inspector instead + soundData = br.ReadBytes(99999999); + soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); + string soundAssetFileName + = ArchiveConstants.ASSETS_PATH + soundUuid + + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; + tar.WriteFile(soundAssetFileName, soundData); + + /* + AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); + scene.AssetService.Store(soundAsset); + asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; + */ + } + } + } /// /// Test saving an OpenSim Region Archive. @@ -204,30 +254,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // TODO: Test presence of more files and contents of files. } - private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) - { - SceneObjectPart part1 = CreateSceneObjectPart1(); - sog1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(sog1, false); - - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - ncAssetUuid = UUID.Random(); - UUID ncItemUuid = UUID.Random(); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - m_scene.AssetService.Store(ncAsset); - - TaskInventoryItem ncItem - = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; - SceneObjectPart part2 = CreateSceneObjectPart2(); - sog2 = new SceneObjectGroup(part2); - part2.Inventory.AddInventoryItem(ncItem, true); - - scene.AddNewSceneObject(sog2, false); - } - /// /// Test saving an OpenSim Region Archive with the no assets option /// @@ -308,59 +334,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // TODO: Test presence of more files and contents of files. } - /// - /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g. - /// 2 can come after 3). - /// - [Test] - public void TestLoadOarUnorderedParts() - { - TestHelpers.InMethod(); - - UUID ownerId = TestHelpers.ParseTail(0xaaaa); - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - tar.WriteFile( - ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); - - SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); - SceneObjectPart sop2 - = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId); - SceneObjectPart sop3 - = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId); - - // Add the parts so they will be written out in reverse order to the oar - sog1.AddPart(sop3); - sop3.LinkNum = 3; - sog1.AddPart(sop2); - sop2.LinkNum = 2; - - tar.WriteFile( - ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition), - SceneObjectSerializer.ToXml2Format(sog1)); - - tar.Close(); - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - lock (this) - { - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - m_archiverModule.DearchiveRegion(archiveReadStream); - } - - Assert.That(m_lastErrorMessage, Is.Null); - - SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2"); - Assert.That(part2.LinkNum, Is.EqualTo(2)); - - SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3"); - Assert.That(part3.LinkNum, Is.EqualTo(3)); - } - /// /// Test loading an OpenSim Region Archive. /// @@ -435,50 +408,57 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests TestLoadedRegion(part1, soundItemName, soundData); } - private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) + /// + /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g. + /// 2 can come after 3). + /// + [Test] + public void TestLoadOarUnorderedParts() { - using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) + TestHelpers.InMethod(); + + UUID ownerId = TestHelpers.ParseTail(0xaaaa); + + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, + new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + + SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); + SceneObjectPart sop2 + = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId); + SceneObjectPart sop3 + = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId); + + // Add the parts so they will be written out in reverse order to the oar + sog1.AddPart(sop3); + sop3.LinkNum = 3; + sog1.AddPart(sop2); + sop2.LinkNum = 2; + + tar.WriteFile( + ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition), + SceneObjectSerializer.ToXml2Format(sog1)); + + tar.Close(); + + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + + lock (this) { - using (BinaryReader br = new BinaryReader(resource)) - { - // FIXME: Use the inspector instead - soundData = br.ReadBytes(99999999); - soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); - string soundAssetFileName - = ArchiveConstants.ASSETS_PATH + soundUuid - + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; - tar.WriteFile(soundAssetFileName, soundData); - - /* - AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); - scene.AssetService.Store(soundAsset); - asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; - */ - } + m_scene.EventManager.OnOarFileLoaded += LoadCompleted; + m_archiverModule.DearchiveRegion(archiveReadStream); } - } - private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) - { - SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); + Assert.That(m_lastErrorMessage, Is.Null); - Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); - Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); - Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); - Assert.That( - object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); - Assert.That( - object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); - Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); - Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition)); + SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2"); + Assert.That(part2.LinkNum, Is.EqualTo(2)); - TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; - Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); - AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString()); - Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); - Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); - - Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); + SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3"); + Assert.That(part3.LinkNum, Is.EqualTo(3)); } /// @@ -562,6 +542,81 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests } } + /// + /// Test OAR loading where the land parcel is group deeded. + /// + /// + /// In this situation, the owner ID is set to the group ID. + /// + [Test] + public void TestLoadOarDeededLand() + { + TestHelpers.InMethod(); + TestHelpers.EnableLogging(); + + UUID landID = TestHelpers.ParseTail(0x10); + + MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector(); + + IConfigSource configSource = new IniConfigSource(); + IConfig config = configSource.AddConfig("Groups"); + config.Set("Enabled", true); + config.Set("Module", "GroupsModule"); + config.Set("DebugEnabled", true); + SceneHelpers.SetupSceneModules( + m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() }); + + // Create group in scene for loading + // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests. + UUID groupID + = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero); + + // Construct OAR + MemoryStream oarStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(oarStream); + + tar.WriteDir(ArchiveConstants.LANDDATA_PATH); + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, + new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + + LandObject lo = new LandObject(groupID, true, null); + + // FIXME: We set directly rather than call SetLandBitmap in order not to do an AABB value update, which + // requests the terrain heightmap from an active scene. This is confusing and not a long-term solution. + //lo.LandBitmap = lo.BasicFullRegionLandBitmap(); + lo.SetLandBitmap(lo.BasicFullRegionLandBitmap()); + + // FIXME: We have to make a separate call to update the LandData's copy of the land bitmap, even though this is + // identical to the LandObject copy. This should be changed so there's only one copy of the data if at all + // possible + //lo.UpdateLandBitmapByteArray(); + + LandData ld = lo.LandData; + ld.GlobalID = landID; + + string ldPath = ArchiveConstants.CreateOarLandDataPath(ld); + tar.WriteFile(ldPath, LandDataSerializer.Serialize(ld, null)); + tar.Close(); + + oarStream = new MemoryStream(oarStream.ToArray()); + + // Load OAR + lock (this) + { + m_scene.EventManager.OnOarFileLoaded += LoadCompleted; + m_archiverModule.DearchiveRegion(oarStream); + } + + ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16); + LandData rLd = rLo.LandData; + + Assert.That(rLd.GlobalID, Is.EqualTo(landID)); + Assert.That(rLd.OwnerID, Is.EqualTo(groupID)); + Assert.That(rLd.GroupID, Is.EqualTo(groupID)); + Assert.That(rLd.IsGroupOwned, Is.EqualTo(true)); + } + /// /// Test loading the region settings of an OpenSim Region Archive. /// @@ -781,9 +836,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests } } - // Save OAR - MemoryStream archiveWriteStream = new MemoryStream(); m_scene.EventManager.OnOarFileSaved += SaveCompleted; @@ -800,7 +853,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // Check that the OAR contains the expected data - Assert.That(m_lastRequestId, Is.EqualTo(requestId)); byte[] archive = archiveWriteStream.ToArray(); @@ -976,5 +1028,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests TestLoadedRegion(part1, soundItemName, soundData); } + private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) + { + SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); + + Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); + Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); + Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); + Assert.That( + object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); + Assert.That( + object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); + Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); + Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition)); + + TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; + Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); + AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString()); + Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); + Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); + + Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); + } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 8682798d93..7149aad55d 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -1378,10 +1378,11 @@ namespace OpenSim.Region.CoreModules.World.Land public void EventManagerOnIncomingLandDataFromStorage(List data) { +// m_log.DebugFormat( +// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name); + for (int i = 0; i < data.Count; i++) - { IncomingLandObjectFromStorage(data[i]); - } } public void IncomingLandObjectFromStorage(LandData data) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 8829f27a97..5969d45426 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -727,9 +727,10 @@ namespace OpenSim.Region.CoreModules.World.Land int ty = min_y * 4; if (ty > ((int)Constants.RegionSize - 1)) ty = ((int)Constants.RegionSize - 1); + LandData.AABBMin = - new Vector3((float) (min_x * 4), (float) (min_y * 4), - (float) m_scene.Heightmap[tx, ty]); + new Vector3( + (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); tx = max_x * 4; if (tx > ((int)Constants.RegionSize - 1)) @@ -737,9 +738,11 @@ namespace OpenSim.Region.CoreModules.World.Land ty = max_y * 4; if (ty > ((int)Constants.RegionSize - 1)) ty = ((int)Constants.RegionSize - 1); - LandData.AABBMax = - new Vector3((float) (max_x * 4), (float) (max_y * 4), - (float) m_scene.Heightmap[tx, ty]); + + LandData.AABBMax + = new Vector3( + (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); + LandData.Area = tempArea; } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs index 6d2607541e..6b5b40a507 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs @@ -36,7 +36,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { 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); + + /// + /// Get the group record. + /// + /// + /// The UUID of the user making the request. + /// + /// The ID of the record to retrieve. + /// GroupName may be specified instead, in which case this parameter will be UUID.Zero + /// + /// + /// The name of the group to retrieve. + /// GroupID may be specified instead, in which case this parmeter will be null. + /// GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); + List FindGroups(UUID RequestingAgentID, string search); List GetGroupMembers(UUID RequestingAgentID, UUID GroupID); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index d0c3ea5910..1101851900 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -54,13 +54,62 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_debugEnabled = false; - public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | - GroupPowers.Accountable | - GroupPowers.JoinChat | - GroupPowers.AllowVoiceChat | - GroupPowers.ReceiveNotices | - GroupPowers.StartProposal | - GroupPowers.VoteOnProposal; + public const GroupPowers 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 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; @@ -219,59 +268,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AllowPublish"] = allowPublish == true ? 1 : 0; param["MaturePublish"] = maturePublish == true ? 1 : 0; param["FounderID"] = founderID.ToString(); - param["EveryonePowers"] = ((ulong)m_DefaultEveryonePowers).ToString(); + param["EveryonePowers"] = ((ulong)DefaultEveryonePowers).ToString(); param["OwnerRoleID"] = OwnerRoleID.ToString(); - - // Would this be cleaner as (GroupPowers)ulong.MaxValue; - GroupPowers OwnerPowers = 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; - param["OwnersPowers"] = ((ulong)OwnerPowers).ToString(); - - - + param["OwnersPowers"] = ((ulong)DefaultOwnerPowers).ToString(); Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param); @@ -612,8 +611,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } return Roles; - - } public List GetGroupRoles(UUID requestingAgentID, UUID GroupID) @@ -676,7 +673,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } return members; - } public List GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) @@ -727,9 +723,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups values.Add(data); } } - return values; + return values; } + public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) { Hashtable param = new Hashtable(); @@ -737,7 +734,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param); - if (respData.Contains("error")) { return null; @@ -761,6 +757,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } + public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) { string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, ""); @@ -777,8 +774,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); } - - #endregion #region GroupSessionTracking diff --git a/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs b/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs index 6fb9df1313..3035cea888 100644 --- a/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs +++ b/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs @@ -26,12 +26,15 @@ */ using System; +using System.Collections; using System.Collections.Generic; using System.Reflection; using log4net; using Mono.Addins; using Nini.Config; using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Data.Null; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -44,6 +47,8 @@ namespace OpenSim.Tests.Common.Mock { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + IXGroupData m_data = new NullXGroupData(null, null); + public string Name { get { return "MockGroupsServicesConnector"; } @@ -84,7 +89,33 @@ namespace OpenSim.Tests.Common.Mock int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID) { - return UUID.Zero; + XGroup group = new XGroup() + { + groupID = UUID.Random(), + ownerRoleID = UUID.Random(), + name = name, + charter = charter, + showInList = showInList, + insigniaID = insigniaID, + membershipFee = membershipFee, + openEnrollment = openEnrollment, + allowPublish = allowPublish, + maturePublish = maturePublish, + founderID = founderID, + everyonePowers = (ulong)XmlRpcGroupsServicesConnectorModule.DefaultEveryonePowers, + ownersPowers = (ulong)XmlRpcGroupsServicesConnectorModule.DefaultOwnerPowers + }; + + if (m_data.StoreGroup(group)) + { + m_log.DebugFormat("[MOCK GROUPS SERVICES CONNECTOR]: Created group {0} {1}", group.name, group.groupID); + return group.groupID; + } + else + { + m_log.ErrorFormat("[MOCK GROUPS SERVICES CONNECTOR]: Failed to create group {0}", name); + return UUID.Zero; + } } public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, @@ -107,9 +138,49 @@ namespace OpenSim.Tests.Common.Mock { } - public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName) + public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName) { - return null; + m_log.DebugFormat( + "[MOCK GROUPS SERVICES CONNECTOR]: Processing GetGroupRecord() for groupID {0}, name {1}", + groupID, groupName); + + XGroup[] groups; + string field, val; + + if (groupID != UUID.Zero) + { + field = "groupID"; + val = groupID.ToString(); + } + else + { + field = "name"; + val = groupName; + } + + groups = m_data.GetGroups(field, val); + + if (groups.Length == 0) + return null; + + XGroup xg = groups[0]; + + GroupRecord gr = new GroupRecord() + { + GroupID = xg.groupID, + GroupName = xg.name, + AllowPublish = xg.allowPublish, + MaturePublish = xg.maturePublish, + Charter = xg.charter, + FounderID = xg.founderID, + // FIXME: group picture storage location unknown + MembershipFee = xg.membershipFee, + OpenEnrollment = xg.openEnrollment, + OwnerRoleID = xg.ownerRoleID, + ShowInList = xg.showInList + }; + + return gr; } public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID) diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs index f9bf768da3..ccbdf81115 100644 --- a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs @@ -33,10 +33,11 @@ using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; +using OpenSim.Data.Null; namespace OpenSim.Tests.Common.Mock { - public class TestXInventoryDataPlugin : IXInventoryData + public class TestXInventoryDataPlugin : NullGenericDataHandler, IXInventoryData { private Dictionary m_allFolders = new Dictionary(); private Dictionary m_allItems = new Dictionary(); @@ -58,28 +59,6 @@ namespace OpenSim.Tests.Common.Mock return origFolders.Select(f => f.Clone()).ToArray(); } - private List Get(string[] fields, string[] vals, List inputEntities) - { - List entities = inputEntities; - - for (int i = 0; i < fields.Length; i++) - { - entities - = entities.Where( - e => - { - FieldInfo fi = typeof(T).GetField(fields[i]); - if (fi == null) - throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i])); - - return fi.GetValue(e).ToString() == vals[i]; - } - ).ToList(); - } - - return entities; - } - public bool StoreFolder(XInventoryFolder folder) { m_allFolders[folder.folderID] = folder.Clone(); diff --git a/prebuild.xml b/prebuild.xml index 101d48fafa..a7201c53f7 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1676,6 +1676,7 @@ ../../../bin/ + @@ -2683,12 +2684,13 @@ + + - @@ -2980,6 +2982,7 @@ +