* for iars, allow item names/folders including "/" to be escaped using "\/"

* also, "\" has to be escaped as "\\"
* add item name unit test for escaped characters
0.6.8-post-fixes
Justin Clark-Casey (justincc) 2009-11-09 15:49:09 +00:00
parent f8f1e94cf8
commit 668850b974
3 changed files with 87 additions and 5 deletions

View File

@ -27,6 +27,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Text;
using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
@ -38,6 +41,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
/// </summary> /// </summary>
public static class InventoryArchiveUtils public static class InventoryArchiveUtils
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static readonly string PATH_DELIMITER = "/"; public static readonly string PATH_DELIMITER = "/";
/// <summary> /// <summary>
@ -181,10 +186,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
public static InventoryItemBase FindItemByPath( public static InventoryItemBase FindItemByPath(
IInventoryService inventoryService, InventoryFolderBase startFolder, string path) IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
{ {
string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); string[] components = SplitEscapedPath(path);
components[0] = UnescapePath(components[0]);
//string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
if (components.Length == 1) if (components.Length == 1)
{ {
// m_log.DebugFormat("FOUND SINGLE COMPONENT [{0}]", components[0]);
List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID);
foreach (InventoryItemBase item in items) foreach (InventoryItemBase item in items)
{ {
@ -194,6 +204,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
} }
else else
{ {
// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]);
InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
foreach (InventoryFolderBase folder in contents.Folders) foreach (InventoryFolderBase folder in contents.Folders)
@ -206,5 +218,74 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// We didn't find an item or intermediate folder with the given name // We didn't find an item or intermediate folder with the given name
return null; return null;
} }
/// <summary>
/// Split a human escaped path into two components if it contains an unescaped path delimiter, or one component
/// if no delimiter is present
/// </summary>
/// <param name="path"></param>
/// <returns>
/// The split path. We leave the components in their originally unescaped state (though we remove the delimiter
/// which originally split them if applicable).
/// </returns>
public static string[] SplitEscapedPath(string path)
{
// m_log.DebugFormat("SPLITTING PATH {0}", path);
bool singleEscapeChar = false;
for (int i = 0; i < path.Length; i++)
{
if (path[i] == '\\' && !singleEscapeChar)
{
singleEscapeChar = true;
}
else
{
if (PATH_DELIMITER == path[i].ToString() && !singleEscapeChar)
return new string[2] { path.Remove(i), path.Substring(i + 1) };
else
singleEscapeChar = false;
}
}
// We didn't find a delimiter
return new string[1] { path };
}
/// <summary>
/// Unescapes a human escaped path. This means that "\\" goes to "\", and "\/" goes to "/"
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string UnescapePath(string path)
{
// m_log.DebugFormat("ESCAPING PATH {0}", path);
StringBuilder sb = new StringBuilder();
bool singleEscapeChar = false;
for (int i = 0; i < path.Length; i++)
{
if (path[i] == '\\' && !singleEscapeChar)
singleEscapeChar = true;
else
singleEscapeChar = false;
if (singleEscapeChar)
{
if (PATH_DELIMITER == path[i].ToString())
sb.Append(PATH_DELIMITER);
}
else
{
sb.Append(path[i]);
}
}
// m_log.DebugFormat("ESCAPED PATH TO {0}", sb);
return sb.ToString();
}
} }
} }

View File

@ -296,7 +296,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
TestHelper.InMethod(); TestHelper.InMethod();
log4net.Config.XmlConfigurator.Configure(); log4net.Config.XmlConfigurator.Configure();
string itemName = "You & you are a mean man"; string itemName = "You & you are a mean/man/";
string humanEscapedItemName = @"You & you are a mean\/man\/";
string userPassword = "meowfood"; string userPassword = "meowfood";
InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); InventoryArchiverModule archiverModule = new InventoryArchiverModule(true);
@ -362,7 +363,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream);
mre.WaitOne(60000, false); mre.WaitOne(60000, false);
/// LOAD ITEM // LOAD ITEM
MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
archiverModule.DearchiveInventory(userFirstName, userLastName, "Scripts", userPassword, archiveReadStream); archiverModule.DearchiveInventory(userFirstName, userLastName, "Scripts", userPassword, archiveReadStream);
@ -371,7 +372,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
= scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName);
InventoryItemBase foundItem1 InventoryItemBase foundItem1
= InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userId, "Scripts/Objects/" + itemName); = InventoryArchiveUtils.FindItemByPath(
scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName);
Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
// Assert.That( // Assert.That(

View File

@ -93,7 +93,6 @@ namespace OpenSim.Region.Framework.Scenes
public void AddInventoryItem(UUID AgentID, InventoryItemBase item) public void AddInventoryItem(UUID AgentID, InventoryItemBase item)
{ {
if (InventoryService.AddItem(item)) if (InventoryService.AddItem(item))
{ {
int userlevel = 0; int userlevel = 0;