diff --git a/.gitignore b/.gitignore index af7e18beae..dc4087e488 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,10 @@ bin/*.db-journal bin/addin-db-* bin/*.dll bin/OpenSim.vshost.exe.config +bin/OpenSim.32BitLaunch.vshost.exe.config +bin/OpenSim.32BitLaunch.log +UpgradeLog.XML +_UpgradeReport_Files/ bin/ScriptEngines/*-*-*-*-* bin/ScriptEngines/*.dll bin/ScriptEngines/*/*.dll diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs index 85a5c08d37..e64a82820d 100644 --- a/OpenSim/Data/IXInventoryData.cs +++ b/OpenSim/Data/IXInventoryData.cs @@ -40,6 +40,11 @@ namespace OpenSim.Data public UUID folderID; public UUID agentID; public UUID parentFolderID; + + public XInventoryFolder Clone() + { + return (XInventoryFolder)MemberwiseClone(); + } } public class XInventoryItem @@ -64,6 +69,11 @@ namespace OpenSim.Data public UUID avatarID; public UUID parentFolderID; public int inventoryGroupPermissions; + + public XInventoryItem Clone() + { + return (XInventoryItem)MemberwiseClone(); + } } public interface IXInventoryData diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs index a12183c535..b3457a65b9 100644 --- a/OpenSim/Framework/InventoryFolderBase.cs +++ b/OpenSim/Framework/InventoryFolderBase.cs @@ -73,33 +73,27 @@ namespace OpenSim.Framework { } - public InventoryFolderBase(UUID id) + public InventoryFolderBase(UUID id) : this() { ID = id; } - public InventoryFolderBase(UUID id, UUID owner) + public InventoryFolderBase(UUID id, UUID owner) : this(id) { - ID = id; Owner = owner; } - public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) + public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner) { - ID = id; Name = name; - Owner = owner; ParentID = parent; } - public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version) + public InventoryFolderBase( + UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent) { - ID = id; - Name = name; - Owner = owner; Type = type; - ParentID = parent; Version = version; } } -} +} \ No newline at end of file diff --git a/OpenSim/Framework/Serialization/External/OspResolver.cs b/OpenSim/Framework/Serialization/External/OspResolver.cs index d31d27c4a6..fa7160f874 100644 --- a/OpenSim/Framework/Serialization/External/OspResolver.cs +++ b/OpenSim/Framework/Serialization/External/OspResolver.cs @@ -65,9 +65,14 @@ namespace OpenSim.Framework.Serialization UserAccount account = userService.GetUserAccount(UUID.Zero, userId); if (account != null) + { return MakeOspa(account.FirstName, account.LastName); + } // else +// { // m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); +// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId); +// } return null; } @@ -79,10 +84,13 @@ namespace OpenSim.Framework.Serialization /// public static string MakeOspa(string firstName, string lastName) { -// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName); + string ospa + = OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName; + +// m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName); +// System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName); - return - OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName; + return ospa; } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index b112b6db52..12a05b3df5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); } - /// - /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where - /// an account exists with the same name as the creator, though not the same id. - /// - [Test] - public void TestLoadIarV0_1SameNameCreator() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); - - m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); - - Assert.That( - foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), - "Loaded item non-uuid creator doesn't match original"); - Assert.That( - foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), - "Loaded item uuid creator doesn't match original"); - Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), - "Loaded item owner doesn't match inventory reciever"); - - AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); - string xmlData = Utils.BytesToString(asset1.Data); - SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - - Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); - } +// /// +// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where +// /// an account exists with the same name as the creator, though not the same id. +// /// +// [Test] +// public void TestLoadIarV0_1SameNameCreator() +// { +// TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); +// +// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); +// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); +// +// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); +// InventoryItemBase foundItem1 +// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); +// +// Assert.That( +// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), +// "Loaded item non-uuid creator doesn't match original"); +// Assert.That( +// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), +// "Loaded item uuid creator doesn't match original"); +// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), +// "Loaded item owner doesn't match inventory reciever"); +// +// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); +// string xmlData = Utils.BytesToString(asset1.Data); +// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); +// +// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); +// } /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 18bd0186b8..13b74983b1 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -49,6 +49,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public const int DISP_EXPIRE = 1; public const int DISP_TEMP = 2; + /// + /// If true then where possible dynamic textures are reused. + /// + public bool ReuseTextures { get; set; } + private Dictionary RegisteredScenes = new Dictionary(); private Dictionary RenderPlugins = @@ -56,6 +61,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture private Dictionary Updaters = new Dictionary(); + /// + /// Record dynamic textures that we can reuse for a given data and parameter combination rather than + /// regenerate. + /// + /// + /// Key is string.Format("{0}{1}", data + /// + private Cache m_reuseableDynamicTextures; + #region IDynamicTextureManager Members public void RegisterRender(string handleType, IDynamicTextureRender render) @@ -71,7 +85,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture /// /// /// - public void ReturnData(UUID id, byte[] data) + /// True if the data generated can be reused for subsequent identical requests + public void ReturnData(UUID id, byte[] data, bool isReuseable) { DynamicTextureUpdater updater = null; @@ -88,7 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture if (RegisteredScenes.ContainsKey(updater.SimUUID)) { Scene scene = RegisteredScenes[updater.SimUUID]; - updater.DataReceived(data, scene); + UUID newTextureID = updater.DataReceived(data, scene); + + if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture) + m_reuseableDynamicTextures.Store( + GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID); } } @@ -169,6 +188,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { if (RenderPlugins.ContainsKey(contentType)) { + // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire + // them. + if (ReuseTextures) + disp = disp & ~DISP_EXPIRE; + DynamicTextureUpdater updater = new DynamicTextureUpdater(); updater.SimUUID = simID; updater.PrimID = primID; @@ -183,21 +207,49 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture updater.Url = "Local image"; updater.Disp = disp; - lock (Updaters) + object reusableTextureUUID = null; + + if (ReuseTextures) + reusableTextureUUID + = m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams)); + + // We cannot reuse a dynamic texture if the data is going to be blended with something already there. + if (reusableTextureUUID == null || updater.BlendWithOldTexture) { - if (!Updaters.ContainsKey(updater.UpdaterID)) + lock (Updaters) { - Updaters.Add(updater.UpdaterID, updater); + if (!Updaters.ContainsKey(updater.UpdaterID)) + { + Updaters.Add(updater.UpdaterID, updater); + } + } + + RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); + } + else + { + // No need to add to updaters as the texture is always the same. Not that this functionality + // apppears to be implemented anyway. + if (RegisteredScenes.ContainsKey(updater.SimUUID)) + { + SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID); + + if (part != null) + updater.UpdatePart(part, (UUID)reusableTextureUUID); } } - RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); return updater.UpdaterID; } return UUID.Zero; } + private string GenerateReusableTextureKey(string data, string extraParams) + { + return string.Format("{0}{1}", data, extraParams); + } + public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, out double xSize, out double ySize) { @@ -224,6 +276,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public void PostInitialise() { +// ReuseTextures = true; + if (ReuseTextures) + { + m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative); + m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0); + } } public void Close() @@ -268,10 +326,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture BodyData = null; } + /// + /// Update the given part with the new texture. + /// + /// + /// The old texture UUID. + /// + public UUID UpdatePart(SceneObjectPart part, UUID textureID) + { + UUID oldID; + + lock (part) + { + // mostly keep the values from before + Primitive.TextureEntry tmptex = part.Shape.Textures; + + // FIXME: Need to return the appropriate ID if only a single face is replaced. + oldID = tmptex.DefaultTexture.TextureID; + + if (Face == ALL_SIDES) + { + oldID = tmptex.DefaultTexture.TextureID; + tmptex.DefaultTexture.TextureID = textureID; + } + else + { + try + { + Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); + texface.TextureID = textureID; + tmptex.FaceTextures[Face] = texface; + } + catch (Exception) + { + tmptex.DefaultTexture.TextureID = textureID; + } + } + + // I'm pretty sure we always want to force this to true + // I'm pretty sure noone whats to set fullbright true if it wasn't true before. + // tmptex.DefaultTexture.Fullbright = true; + + part.UpdateTextureEntry(tmptex.GetBytes()); + } + + return oldID; + } + /// /// Called once new texture data has been received for this updater. /// - public void DataReceived(byte[] data, Scene scene) + /// + /// + /// True if the data given is reuseable. + /// The asset UUID given to the incoming data. + public UUID DataReceived(byte[] data, Scene scene) { SceneObjectPart part = scene.GetSceneObjectPart(PrimID); @@ -281,7 +390,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); - return; + + return UUID.Zero; } byte[] assetData = null; @@ -323,52 +433,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture cacheLayerDecode = null; } - UUID oldID = UUID.Zero; - - lock (part) - { - // mostly keep the values from before - Primitive.TextureEntry tmptex = part.Shape.Textures; - - // remove the old asset from the cache - oldID = tmptex.DefaultTexture.TextureID; - - if (Face == ALL_SIDES) - { - tmptex.DefaultTexture.TextureID = asset.FullID; - } - else - { - try - { - Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); - texface.TextureID = asset.FullID; - tmptex.FaceTextures[Face] = texface; - } - catch (Exception) - { - tmptex.DefaultTexture.TextureID = asset.FullID; - } - } - - // I'm pretty sure we always want to force this to true - // I'm pretty sure noone whats to set fullbright true if it wasn't true before. - // tmptex.DefaultTexture.Fullbright = true; - - part.UpdateTextureEntry(tmptex.GetBytes()); - } + UUID oldID = UpdatePart(part, asset.FullID); if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) { - if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); + if (oldAsset == null) + oldAsset = scene.AssetService.Get(oldID.ToString()); + if (oldAsset != null) { - if (oldAsset.Temporary == true) + if (oldAsset.Temporary) { scene.AssetService.Delete(oldID.ToString()); } } } + + return asset.FullID; } private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 6f839485ec..2b3a0f29ff 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -67,12 +67,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL return true; } +// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) +// { +// // We don't support conversion of body data. +// return false; +// } + public byte[] ConvertUrl(string url, string extraParams) { return null; } - public byte[] ConvertStream(Stream data, string extraParams) + public byte[] ConvertData(string bodyData, string extraParams) { return null; } @@ -236,9 +242,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL stream.Close(); } } + m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", imageJ2000.Length, state.RequestID); - m_textureManager.ReturnData(state.RequestID, imageJ2000); + + m_textureManager.ReturnData(state.RequestID, imageJ2000, false); } #region Nested type: RequestState diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 9787c8c173..b50c0bd7cd 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -45,31 +45,250 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests { [TestFixture] - public class VectorRenderModuleTests + public class VectorRenderModuleTests : OpenSimTestCase { + Scene m_scene; + DynamicTextureModule m_dtm; + VectorRenderModule m_vrm; + + private void SetupScene(bool reuseTextures) + { + m_scene = new SceneHelpers().SetupScene(); + + m_dtm = new DynamicTextureModule(); + m_dtm.ReuseTextures = reuseTextures; + + m_vrm = new VectorRenderModule(); + + SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm); + } + [Test] public void TestDraw() { TestHelpers.InMethod(); - Scene scene = new SceneHelpers().SetupScene(); - DynamicTextureModule dtm = new DynamicTextureModule(); - VectorRenderModule vrm = new VectorRenderModule(); - SceneHelpers.SetupSceneModules(scene, dtm, vrm); - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); + SetupScene(false); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - dtm.AddDynamicTextureData( - scene.RegionInfo.RegionID, + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, so.UUID, - vrm.GetContentType(), + m_vrm.GetContentType(), "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", "", 0); + Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDraw() + { + TestHelpers.InMethod(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SetupScene(false); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDrawDifferentExtraParams() + { + TestHelpers.InMethod(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SetupScene(false); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "alpha:250", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDrawContainingImage() + { + TestHelpers.InMethod(); + + string dtText + = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; + + SetupScene(false); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestDrawReusingTexture() + { + TestHelpers.InMethod(); + + SetupScene(true); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", + "", + 0); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } + + [Test] + public void TestRepeatSameDrawReusingTexture() + { + TestHelpers.InMethod(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SetupScene(true); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() + { + TestHelpers.InMethod(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SetupScene(true); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "alpha:250", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDrawContainingImageReusingTexture() + { + TestHelpers.InMethod(); + + string dtText + = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; + + SetupScene(true); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 05eaaeceb0..f687646e76 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -30,6 +30,7 @@ using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; +using System.Linq; using System.Net; using Nini.Config; using OpenMetaverse; @@ -47,7 +48,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private string m_name = "VectorRenderModule"; private Scene m_scene; private IDynamicTextureManager m_textureManager; private Graphics m_graph; @@ -61,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public string GetContentType() { - return ("vector"); + return "vector"; } public string GetName() { - return m_name; + return Name; } public bool SupportsAsynchronous() @@ -74,14 +74,26 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender return true; } +// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) +// { +// string[] lines = GetLines(bodyData); +// return lines.Any((str, r) => str.StartsWith("Image")); +// } + public byte[] ConvertUrl(string url, string extraParams) { return null; } - public byte[] ConvertStream(Stream data, string extraParams) + public byte[] ConvertData(string bodyData, string extraParams) { - return null; + bool reuseable; + return Draw(bodyData, extraParams, out reuseable); + } + + private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable) + { + return Draw(bodyData, extraParams, out reuseable); } public bool AsyncConvertUrl(UUID id, string url, string extraParams) @@ -91,7 +103,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public bool AsyncConvertData(UUID id, string bodyData, string extraParams) { - Draw(bodyData, id, extraParams); + // XXX: This isn't actually being done asynchronously! + bool reuseable; + byte[] data = ConvertData(bodyData, extraParams, out reuseable); + + m_textureManager.ReturnData(id, data, reuseable); + return true; } @@ -152,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public string Name { - get { return m_name; } + get { return "VectorRenderModule"; } } public bool IsSharedModule @@ -162,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender #endregion - private void Draw(string data, UUID id, string extraParams) + private byte[] Draw(string data, string extraParams, out bool reuseable) { // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 @@ -343,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } } - GDIDraw(data, graph, altDataDelim); + GDIDraw(data, graph, altDataDelim, out reuseable); } byte[] imageJ2000 = new byte[0]; @@ -359,7 +376,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender e.Message, e.StackTrace); } - m_textureManager.ReturnData(id, imageJ2000); + return imageJ2000; } finally { @@ -434,8 +451,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } */ - private void GDIDraw(string data, Graphics graph, char dataDelim) + /// + /// Split input data into discrete command lines. + /// + /// + /// + /// + private string[] GetLines(string data, char dataDelim) { + char[] lineDelimiter = { dataDelim }; + return data.Split(lineDelimiter); + } + + private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable) + { + reuseable = true; Point startPoint = new Point(0, 0); Point endPoint = new Point(0, 0); Pen drawPen = null; @@ -450,11 +480,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender myFont = new Font(fontName, fontSize); myBrush = new SolidBrush(Color.Black); - char[] lineDelimiter = {dataDelim}; char[] partsDelimiter = {','}; - string[] lines = data.Split(lineDelimiter); - foreach (string line in lines) + foreach (string line in GetLines(data, dataDelim)) { string nextLine = line.Trim(); //replace with switch, or even better, do some proper parsing @@ -485,6 +513,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } else if (nextLine.StartsWith("Image")) { + // We cannot reuse any generated texture involving fetching an image via HTTP since that image + // can change. + reuseable = false; + float x = 0; float y = 0; GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 402b9fb0fe..d99567cd4b 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -414,6 +414,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void LoadPlugins() { m_plugineffects = new Dictionary(); + LoadPlugins(Assembly.GetCallingAssembly()); string plugineffectsPath = "Terrain"; // Load the files in the Terrain/ dir @@ -427,32 +428,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain try { Assembly library = Assembly.LoadFrom(file); - foreach (Type pluginType in library.GetTypes()) - { - try - { - if (pluginType.IsAbstract || pluginType.IsNotPublic) - continue; - - string typeName = pluginType.Name; - - if (pluginType.GetInterface("ITerrainEffect", false) != null) - { - ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); - - InstallPlugin(typeName, terEffect); - } - else if (pluginType.GetInterface("ITerrainLoader", false) != null) - { - ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); - m_loaders[terLoader.FileExtension] = terLoader; - m_log.Info("L ... " + typeName); - } - } - catch (AmbiguousMatchException) - { - } - } + LoadPlugins(library); } catch (BadImageFormatException) { @@ -460,6 +436,36 @@ namespace OpenSim.Region.CoreModules.World.Terrain } } + private void LoadPlugins(Assembly library) + { + foreach (Type pluginType in library.GetTypes()) + { + try + { + if (pluginType.IsAbstract || pluginType.IsNotPublic) + continue; + + string typeName = pluginType.Name; + + if (pluginType.GetInterface("ITerrainEffect", false) != null) + { + ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString())); + + InstallPlugin(typeName, terEffect); + } + else if (pluginType.GetInterface("ITerrainLoader", false) != null) + { + ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); + m_loaders[terLoader.FileExtension] = terLoader; + m_log.Info("L ... " + typeName); + } + } + catch (AmbiguousMatchException) + { + } + } + } + public void InstallPlugin(string pluginName, ITerrainEffect effect) { lock (m_plugineffects) @@ -1178,7 +1184,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceRunPluginEffect(Object[] args) { - if ((string) args[0] == "list") + string firstArg = (string)args[0]; + if (firstArg == "list") { m_log.Info("List of loaded plugins"); foreach (KeyValuePair kvp in m_plugineffects) @@ -1187,14 +1194,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain } return; } - if ((string) args[0] == "reload") + if (firstArg == "reload") { LoadPlugins(); return; } - if (m_plugineffects.ContainsKey((string) args[0])) + if (m_plugineffects.ContainsKey(firstArg)) { - m_plugineffects[(string) args[0]].RunEffect(m_channel); + m_plugineffects[firstArg].RunEffect(m_channel); CheckForTerrainUpdates(); } else diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 8954513c06..1a3bcbbc71 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs @@ -33,7 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IDynamicTextureManager { void RegisterRender(string handleType, IDynamicTextureRender render); - void ReturnData(UUID id, byte[] data); + void ReturnData(UUID id, byte[] data, bool isReuseable); UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, int updateTimer); @@ -113,8 +113,20 @@ namespace OpenSim.Region.Framework.Interfaces string GetName(); string GetContentType(); bool SupportsAsynchronous(); + +// /// +// /// Return true if converting the input body and extra params data will always result in the same byte[] array +// /// +// /// +// /// This method allows the caller to use a previously generated asset if it has one. +// /// +// /// +// /// +// /// +// bool AlwaysIdenticalConversion(string bodyData, string extraParams); + byte[] ConvertUrl(string url, string extraParams); - byte[] ConvertStream(Stream data, string extraParams); + byte[] ConvertData(string bodyData, string extraParams); bool AsyncConvertUrl(UUID id, string url, string extraParams); bool AsyncConvertData(UUID id, string bodyData, string extraParams); void GetDrawStringSize(string text, string fontName, int fontSize, diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index 44d2d452d5..9457ebb374 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -50,8 +50,40 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.Framework.Tests { [TestFixture] - public class UserInventoryTests + public class UserInventoryTests : OpenSimTestCase { + [Test] + public void TestCreateInventoryFolders() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + // For this test both folders will have the same name which is legal in SL user inventories. + string foldersName = "f1"; + + Scene scene = new SceneHelpers().SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); + + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); + + List oneFolder + = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); + + Assert.That(oneFolder.Count, Is.EqualTo(1)); + InventoryFolderBase firstRetrievedFolder = oneFolder[0]; + Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName)); + + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); + + List twoFolders + = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); + + Assert.That(twoFolders.Count, Is.EqualTo(2)); + Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName)); + Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName)); + Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID)); + } + [Test] public void TestGiveInventoryItem() { @@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests public void TestGiveInventoryFolder() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); Scene scene = new SceneHelpers().SetupScene(); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5316d085a5..61e8a28f65 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7701,7 +7701,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); + setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); ScriptSleep(200); } @@ -7710,10 +7710,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(linknumber, rules); + setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); + + ScriptSleep(200); } - private void setLinkPrimParams(int linknumber, LSL_List rules) + private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) { List parts = new List(); List prims = GetLinkParts(linknumber); @@ -7724,15 +7726,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parts.Add(p); LSL_List remaining = null; + uint rulesParsed = 0; if (parts.Count > 0) { foreach (object part in parts) { if (part is SceneObjectPart) - remaining = SetPrimParams((SceneObjectPart)part, rules); + remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); else - remaining = SetPrimParams((ScenePresence)part, rules); + remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); } while ((object)remaining != null && remaining.Length > 2) @@ -7750,9 +7753,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (object part in parts) { if (part is SceneObjectPart) - remaining = SetPrimParams((SceneObjectPart)part, rules); + remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); else - remaining = SetPrimParams((ScenePresence)part, rules); + remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); } } } @@ -7790,6 +7793,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) { + setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); llSetLinkPrimitiveParamsFast(linknumber, rules); ScriptSleep(200); } @@ -7817,12 +7821,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new Vector3((float)x, (float)y, (float)z); } - protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules) + protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) { if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return null; int idx = 0; + int idxStart = 0; SceneObjectGroup parentgrp = part.ParentGroup; @@ -7833,9 +7838,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { while (idx < rules.Length) { + ++rulesParsed; int code = rules.GetLSLIntegerItem(idx++); int remain = rules.Length - idx; + idxStart = idx; int face; LSL_Vector v; @@ -8243,7 +8250,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } catch (InvalidCastException e) { - ShoutError(e.Message); + ShoutError(string.Format( + "{0} error running rule #{1}: arg #{2} ", + originFunc, rulesParsed, idx - idxStart) + e.Message); } finally { @@ -11660,7 +11669,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return tid.ToString(); } - public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); if (obj == null) @@ -11669,14 +11678,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.OwnerID != m_host.OwnerID) return; - LSL_List remaining = SetPrimParams(obj, rules); + uint rulesParsed = 0; + LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed); while ((object)remaining != null && remaining.Length > 2) { LSL_Integer newLink = remaining.GetLSLIntegerItem(0); LSL_List newrules = remaining.GetSublist(1, -1); foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ - remaining = SetPrimParams(part, newrules); + remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed); } } } @@ -12640,11 +12650,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) + protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed) { //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. int idx = 0; + int idxStart = 0; bool positionChanged = false; Vector3 finalPos = Vector3.Zero; @@ -12653,9 +12664,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { while (idx < rules.Length) { + ++rulesParsed; int code = rules.GetLSLIntegerItem(idx++); int remain = rules.Length - idx; + idxStart = idx; switch (code) { @@ -12809,7 +12822,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - + catch (InvalidCastException e) + { + ShoutError(string.Format( + "{0} error running rule #{1}: arg #{2} ", + originFunc, rulesParsed, idx - idxStart) + e.Message); + } finally { if (positionChanged) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 5bc78d68c2..ceff88913c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3036,7 +3036,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); InitLSL(); - m_LSL_Api.SetPrimitiveParamsEx(prim, rules); + m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); } /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index e08328f66e..05c20f9978 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -429,7 +429,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); - void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc); void llSetKeyframedMotion(LSL_List frames, LSL_List options); LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 8101da5d37..d0e041cf7d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -40,16 +40,75 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { + /// + /// To permit region owners to enable the extended scripting functionality + /// of OSSL, without allowing malicious scripts to access potentially + /// troublesome functions, each OSSL function is assigned a threat level, + /// and access to the functions is granted or denied based on a default + /// threshold set in OpenSim.ini (which can be overridden for individual + /// functions on a case-by-case basis) + /// public enum ThreatLevel { + // Not documented, presumably means permanently disabled ? NoAccess = -1, + + /// + /// Function is no threat at all. It doesn't constitute a threat to + /// either users or the system and has no known side effects. + /// None = 0, + + /// + /// Abuse of this command can cause a nuisance to the region operator, + /// such as log message spew. + /// Nuisance = 1, + + /// + /// Extreme levels of abuse of this function can cause impaired + /// functioning of the region, or very gullible users can be tricked + /// into experiencing harmless effects. + /// VeryLow = 2, + + /// + /// Intentional abuse can cause crashes or malfunction under certain + /// circumstances, which can be easily rectified; or certain users can + /// be tricked into certain situations in an avoidable manner. + /// Low = 3, + + /// + /// Intentional abuse can cause denial of service and crashes with + /// potential of data or state loss; or trusting users can be tricked + /// into embarrassing or uncomfortable situations. + /// Moderate = 4, + + /// + /// Casual abuse can cause impaired functionality or temporary denial + /// of service conditions. Intentional abuse can easily cause crashes + /// with potential data loss, or can be used to trick experienced and + /// cautious users into unwanted situations, or changes global data + /// permanently and without undo ability. + /// High = 5, + + /// + /// Even normal use may, depending on the number of instances, or + /// frequency of use, result in severe service impairment or crash + /// with loss of data, or can be used to cause unwanted or harmful + /// effects on users without giving the user a means to avoid it. + /// VeryHigh = 6, + + /// + /// Even casual use is a danger to region stability, or function allows + /// console or OS command execution, or function allows taking money + /// without consent, or allows deletion or modification of user data, + /// or allows the compromise of sensitive data by design. + /// Severe = 7 }; diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index deacd5a4b4..309dab4501 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -94,6 +94,7 @@ namespace OpenSim.Services.InventoryService m_Database = LoadPlugin(dllName, new Object[] {connString, String.Empty}); + if (m_Database == null) throw new Exception("Could not find a storage interface in the given module"); } @@ -326,7 +327,7 @@ namespace OpenSim.Services.InventoryService if (check != null) return false; - if (folder.Type != (short)AssetType.Folder || folder.Type != (short)AssetType.Unknown) + if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown) { InventoryFolderBase rootFolder = GetRootFolder(folder.Owner); diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 7598cc360e..fc49169c97 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -245,7 +245,7 @@ namespace OpenSim.Tests.Common config.AddConfig("Modules"); config.AddConfig("InventoryService"); config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); - config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService"); + config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService"); config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index b3a7c9eec3..87d9410f22 100644 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -199,7 +199,9 @@ namespace OpenSim.Tests.Common string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); InventoryFolderBase newFolder - = new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID); + = new InventoryFolderBase( + UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0); + inventoryService.AddFolder(newFolder); if (components.Length > 1) diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs new file mode 100644 index 0000000000..bca5979e50 --- /dev/null +++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs @@ -0,0 +1,131 @@ +/* + * 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.Tests.Common.Mock +{ + public class TestXInventoryDataPlugin : IXInventoryData + { + private Dictionary m_allFolders = new Dictionary(); + private Dictionary m_allItems = new Dictionary(); + + public TestXInventoryDataPlugin(string conn, string realm) {} + + public XInventoryItem[] GetItems(string[] fields, string[] vals) + { + List origItems = Get(fields, vals, m_allItems.Values.ToList()); + + return origItems.Select(i => i.Clone()).ToArray(); + } + + public XInventoryFolder[] GetFolders(string[] fields, string[] vals) + { + List origFolders + = Get(fields, vals, m_allFolders.Values.ToList()); + + 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(); + +// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID); + + return true; + } + + public bool StoreItem(XInventoryItem item) + { + m_allItems[item.inventoryID] = item.Clone(); + +// Console.WriteLine("Added item {0} {1}, creator {2}, owner {3}", item.inventoryName, item.inventoryID, item.creatorID, item.avatarID); + + return true; + } + + public bool DeleteFolders(string field, string val) + { + return DeleteFolders(new string[] { field }, new string[] { val }); + } + + public bool DeleteFolders(string[] fields, string[] vals) + { + XInventoryFolder[] foldersToDelete = GetFolders(fields, vals); + Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID)); + + return true; + } + + public bool DeleteItems(string field, string val) + { + return DeleteItems(new string[] { field }, new string[] { val }); + } + + public bool DeleteItems(string[] fields, string[] vals) + { + XInventoryItem[] itemsToDelete = GetItems(fields, vals); + Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID)); + + return true; + } + + public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); } + public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); } + public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/TestHelpers.cs b/OpenSim/Tests/Common/TestHelpers.cs index 30121fef6a..57da802e6b 100644 --- a/OpenSim/Tests/Common/TestHelpers.cs +++ b/OpenSim/Tests/Common/TestHelpers.cs @@ -95,6 +95,7 @@ namespace OpenSim.Tests.Common public static void EnableLogging() { log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream); + EnableLoggingConfigStream.Position = 0; } ///