aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/Inventory
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs124
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs120
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs78
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs112
4 files changed, 299 insertions, 135 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index f761bf0..aafcfa2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -99,36 +99,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
99 int failedAssetRestores = 0; 99 int failedAssetRestores = 0;
100 int successfulItemRestores = 0; 100 int successfulItemRestores = 0;
101 List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>(); 101 List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>();
102
103 /*
104 if (!m_userInfo.HasReceivedInventory)
105 {
106 // If the region server has access to the user admin service (by which users are created),
107 // then we'll assume that it's okay to fiddle with the user's inventory even if they are not on the
108 // server.
109 //
110 // FIXME: FetchInventory should probably be assumed to by async anyway, since even standalones might
111 // use a remote inventory service, though this is vanishingly rare at the moment.
112 if (null == m_scene.CommsManager.UserAdminService)
113 {
114 m_log.ErrorFormat(
115 "[INVENTORY ARCHIVER]: Have not yet received inventory info for user {0} {1}",
116 m_userInfo.UserProfile.Name, m_userInfo.UserProfile.ID);
117
118 return nodesLoaded;
119 }
120 else
121 {
122 m_userInfo.FetchInventory();
123 for (int i = 0 ; i < 50 ; i++)
124 {
125 if (m_userInfo.HasReceivedInventory == true)
126 break;
127 Thread.Sleep(200);
128 }
129 }
130 }
131 */
132 102
133 //InventoryFolderImpl rootDestinationFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath); 103 //InventoryFolderImpl rootDestinationFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath);
134 InventoryFolderBase rootDestinationFolder 104 InventoryFolderBase rootDestinationFolder
@@ -159,9 +129,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
159 successfulAssetRestores++; 129 successfulAssetRestores++;
160 else 130 else
161 failedAssetRestores++; 131 failedAssetRestores++;
132
133 if ((successfulAssetRestores) % 50 == 0)
134 m_log.DebugFormat(
135 "[INVENTORY ARCHIVER]: Loaded {0} assets...",
136 successfulAssetRestores);
162 } 137 }
163 else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) 138 else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
164 { 139 {
165 InventoryFolderBase foundFolder 140 InventoryFolderBase foundFolder
166 = ReplicateArchivePathToUserInventory( 141 = ReplicateArchivePathToUserInventory(
167 filePath, TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType, 142 filePath, TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType,
@@ -169,38 +144,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
169 144
170 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) 145 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
171 { 146 {
172 InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data); 147 InventoryItemBase item = LoadItem(data, foundFolder);
173
174 // Don't use the item ID that's in the file
175 item.ID = UUID.Random();
176
177 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.CommsManager);
178 if (UUID.Zero != ospResolvedId)
179 item.CreatorIdAsUuid = ospResolvedId;
180 else
181 item.CreatorIdAsUuid = m_userInfo.UserProfile.ID;
182
183 item.Owner = m_userInfo.UserProfile.ID;
184
185 // Reset folder ID to the one in which we want to load it
186 item.Folder = foundFolder.ID;
187 148
188 //m_userInfo.AddItem(item); 149 if (item != null)
189 m_scene.InventoryService.AddItem(item); 150 {
190 successfulItemRestores++; 151 successfulItemRestores++;
191 152
192 // If we're loading an item directly into the given destination folder then we need to record 153 // If we're loading an item directly into the given destination folder then we need to record
193 // it separately from any loaded root folders 154 // it separately from any loaded root folders
194 if (rootDestinationFolder == foundFolder) 155 if (rootDestinationFolder == foundFolder)
195 nodesLoaded.Add(item); 156 nodesLoaded.Add(item);
157 }
196 } 158 }
197 } 159 }
198 } 160 }
199 161
200 archive.Close(); 162 archive.Close();
201 163
202 m_log.DebugFormat("[INVENTORY ARCHIVER]: Restored {0} assets", successfulAssetRestores); 164 m_log.DebugFormat(
203 m_log.InfoFormat("[INVENTORY ARCHIVER]: Restored {0} items", successfulItemRestores); 165 "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures",
166 successfulAssetRestores, failedAssetRestores);
167 m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores);
204 168
205 return nodesLoaded; 169 return nodesLoaded;
206 } 170 }
@@ -234,8 +198,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
234 198
235 string originalArchivePath = archivePath; 199 string originalArchivePath = archivePath;
236 200
237 m_log.DebugFormat( 201// m_log.DebugFormat(
238 "[INVENTORY ARCHIVER]: Loading to folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); 202// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
239 203
240 InventoryFolderBase destFolder = null; 204 InventoryFolderBase destFolder = null;
241 205
@@ -246,8 +210,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
246 { 210 {
247 if (foldersCreated.ContainsKey(archivePath)) 211 if (foldersCreated.ContainsKey(archivePath))
248 { 212 {
249 m_log.DebugFormat( 213// m_log.DebugFormat(
250 "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); 214// "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
251 destFolder = foldersCreated[archivePath]; 215 destFolder = foldersCreated[archivePath];
252 } 216 }
253 else 217 else
@@ -289,6 +253,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
289 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR); 253 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
290 254
291 string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex); 255 string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);
256
257 newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
292 UUID newFolderId = UUID.Random(); 258 UUID newFolderId = UUID.Random();
293 259
294 // Asset type has to be Unknown here rather than Folder, otherwise the created folder can't be 260 // Asset type has to be Unknown here rather than Folder, otherwise the created folder can't be
@@ -361,6 +327,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
361 } 327 }
362 328
363 /// <summary> 329 /// <summary>
330 /// Load an item from the archive
331 /// </summary>
332 /// <param name="filePath">The archive path for the item</param>
333 /// <param name="data">The raw item data</param>
334 /// <param name="rootDestinationFolder">The root destination folder for loaded items</param>
335 /// <param name="nodesLoaded">All the inventory nodes (items and folders) loaded so far</param>
336 protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder)
337 {
338 InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data);
339
340 // Don't use the item ID that's in the file
341 item.ID = UUID.Random();
342
343 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.CommsManager);
344 if (UUID.Zero != ospResolvedId)
345 item.CreatorIdAsUuid = ospResolvedId;
346 else
347 item.CreatorIdAsUuid = m_userInfo.UserProfile.ID;
348
349 item.Owner = m_userInfo.UserProfile.ID;
350
351 // Reset folder ID to the one in which we want to load it
352 item.Folder = loadFolder.ID;
353
354 //m_userInfo.AddItem(item);
355 m_scene.InventoryService.AddItem(item);
356
357 return item;
358 }
359
360 /// <summary>
364 /// Load an asset 361 /// Load an asset
365 /// </summary> 362 /// </summary>
366 /// <param name="assetFilename"></param> 363 /// <param name="assetFilename"></param>
@@ -389,11 +386,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
389 { 386 {
390 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; 387 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
391 388
392 //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); 389 if (assetType == (sbyte)AssetType.Unknown)
390 m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid);
393 391
394 AssetBase asset = new AssetBase(new UUID(uuid), "RandomName"); 392 //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
395 393
396 asset.Type = assetType; 394 AssetBase asset = new AssetBase(new UUID(uuid), "RandomName", assetType);
397 asset.Data = data; 395 asset.Data = data;
398 396
399 m_scene.AssetService.Store(asset); 397 m_scene.AssetService.Store(asset);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
index a822d10..247cee4 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
@@ -27,6 +27,9 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using log4net;
30using OpenMetaverse; 33using OpenMetaverse;
31using OpenSim.Framework; 34using OpenSim.Framework;
32using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
@@ -38,7 +41,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
38 /// </summary> 41 /// </summary>
39 public static class InventoryArchiveUtils 42 public static class InventoryArchiveUtils
40 { 43 {
41 public static readonly string PATH_DELIMITER = "/"; 44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 // Character used for escaping the path delimter ("\/") and itself ("\\") in human escaped strings
47 public static readonly char ESCAPE_CHARACTER = '\\';
48
49 // The character used to separate inventory path components (different folders and items)
50 public static readonly char PATH_DELIMITER = '/';
42 51
43 /// <summary> 52 /// <summary>
44 /// Find a folder given a PATH_DELIMITER delimited path starting from a user's root folder 53 /// Find a folder given a PATH_DELIMITER delimited path starting from a user's root folder
@@ -103,10 +112,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
103 112
104 path = path.Trim(); 113 path = path.Trim();
105 114
106 if (path == PATH_DELIMITER) 115 if (path == PATH_DELIMITER.ToString())
107 return startFolder; 116 return startFolder;
108 117
109 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); 118 string[] components = SplitEscapedPath(path);
119 components[0] = UnescapePath(components[0]);
120
121 //string[] components = path.Split(new string[] { PATH_DELIMITER.ToString() }, 2, StringSplitOptions.None);
122
110 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 123 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
111 124
112 foreach (InventoryFolderBase folder in contents.Folders) 125 foreach (InventoryFolderBase folder in contents.Folders)
@@ -181,10 +194,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
181 public static InventoryItemBase FindItemByPath( 194 public static InventoryItemBase FindItemByPath(
182 IInventoryService inventoryService, InventoryFolderBase startFolder, string path) 195 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
183 { 196 {
184 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); 197 string[] components = SplitEscapedPath(path);
198 components[0] = UnescapePath(components[0]);
199
200 //string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
185 201
186 if (components.Length == 1) 202 if (components.Length == 1)
187 { 203 {
204// m_log.DebugFormat("FOUND SINGLE COMPONENT [{0}]", components[0]);
205
188 List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); 206 List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID);
189 foreach (InventoryItemBase item in items) 207 foreach (InventoryItemBase item in items)
190 { 208 {
@@ -194,6 +212,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
194 } 212 }
195 else 213 else
196 { 214 {
215// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]);
216
197 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 217 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
198 218
199 foreach (InventoryFolderBase folder in contents.Folders) 219 foreach (InventoryFolderBase folder in contents.Folders)
@@ -206,5 +226,97 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
206 // We didn't find an item or intermediate folder with the given name 226 // We didn't find an item or intermediate folder with the given name
207 return null; 227 return null;
208 } 228 }
229
230 /// <summary>
231 /// Split a human escaped path into two components if it contains an unescaped path delimiter, or one component
232 /// if no delimiter is present
233 /// </summary>
234 /// <param name="path"></param>
235 /// <returns>
236 /// The split path. We leave the components in their originally unescaped state (though we remove the delimiter
237 /// which originally split them if applicable).
238 /// </returns>
239 public static string[] SplitEscapedPath(string path)
240 {
241// m_log.DebugFormat("SPLITTING PATH {0}", path);
242
243 bool singleEscapeChar = false;
244
245 for (int i = 0; i < path.Length; i++)
246 {
247 if (path[i] == ESCAPE_CHARACTER && !singleEscapeChar)
248 {
249 singleEscapeChar = true;
250 }
251 else
252 {
253 if (PATH_DELIMITER == path[i] && !singleEscapeChar)
254 return new string[2] { path.Remove(i), path.Substring(i + 1) };
255 else
256 singleEscapeChar = false;
257 }
258 }
259
260 // We didn't find a delimiter
261 return new string[1] { path };
262 }
263
264 /// <summary>
265 /// Unescapes a human escaped path. This means that "\\" goes to "\", and "\/" goes to "/"
266 /// </summary>
267 /// <param name="path"></param>
268 /// <returns></returns>
269 public static string UnescapePath(string path)
270 {
271// m_log.DebugFormat("ESCAPING PATH {0}", path);
272
273 StringBuilder sb = new StringBuilder();
274
275 bool singleEscapeChar = false;
276 for (int i = 0; i < path.Length; i++)
277 {
278 if (path[i] == ESCAPE_CHARACTER && !singleEscapeChar)
279 singleEscapeChar = true;
280 else
281 singleEscapeChar = false;
282
283 if (singleEscapeChar)
284 {
285 if (PATH_DELIMITER == path[i])
286 sb.Append(PATH_DELIMITER);
287 }
288 else
289 {
290 sb.Append(path[i]);
291 }
292 }
293
294// m_log.DebugFormat("ESCAPED PATH TO {0}", sb);
295
296 return sb.ToString();
297 }
298
299 /// <summary>
300 /// Escape an archive path.
301 /// </summary>
302 /// This has to be done differently from human paths because we can't leave in any "/" characters (due to
303 /// problems if the archive is built from or extracted to a filesystem
304 /// <param name="path"></param>
305 /// <returns></returns>
306 public static string EscapeArchivePath(string path)
307 {
308 // Only encode ampersands (for escaping anything) and / (since this is used as general dir separator).
309 return path.Replace("&", "&amp;").Replace("/", "&#47;");
310 }
311
312 /// <summary>
313 /// Unescape an archive path.
314 /// </summary>
315 /// <param name="path"></param>
316 /// <returns></returns>
317 public static string UnescapeArchivePath(string path)
318 {
319 return path.Replace("&#47;", "/").Replace("&amp;", "&");
320 }
209 } 321 }
210} \ No newline at end of file 322} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 499c552..bbb49f6 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -217,37 +217,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
217 InventoryItemBase inventoryItem = null; 217 InventoryItemBase inventoryItem = null;
218 InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.UserProfile.ID); 218 InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.UserProfile.ID);
219 219
220 // XXX: Very temporarily, drop and refetch inventory to make sure we have any newly created items in cache
221 // This will disappear very soon once we stop using the old cached inventory.
222 /*
223 m_userInfo.DropInventory();
224 m_userInfo.FetchInventory();
225 */
226
227 /*
228 if (!m_userInfo.HasReceivedInventory)
229 {
230 // If the region server has access to the user admin service (by which users are created),
231 // then we'll assume that it's okay to fiddle with the user's inventory even if they are not on the
232 // server.
233 //
234 // FIXME: FetchInventory should probably be assumed to by async anyway, since even standalones might
235 // use a remote inventory service, though this is vanishingly rare at the moment.
236 if (null == m_scene.CommsManager.UserAdminService)
237 {
238 m_log.ErrorFormat(
239 "[INVENTORY ARCHIVER]: Have not yet received inventory info for user {0} {1}",
240 m_userInfo.UserProfile.Name, m_userInfo.UserProfile.ID);
241
242 return;
243 }
244 else
245 {
246 m_userInfo.FetchInventory();
247 }
248 }
249 */
250
251 bool foundStar = false; 220 bool foundStar = false;
252 221
253 // Eliminate double slashes and any leading / on the path. 222 // Eliminate double slashes and any leading / on the path.
@@ -294,34 +263,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
294 263
295 m_archiveWriter = new TarArchiveWriter(m_saveStream); 264 m_archiveWriter = new TarArchiveWriter(m_saveStream);
296 265
297 if (null == inventoryFolder) 266 if (inventoryFolder != null)
298 {
299 if (null == inventoryItem)
300 {
301 // We couldn't find the path indicated
302 m_saveStream.Close();
303 m_module.TriggerInventoryArchiveSaved(
304 m_id, false, m_userInfo, m_invPath, m_saveStream,
305 new Exception(string.Format("Could not find inventory entry at path {0}", m_invPath)));
306 return;
307 }
308 else
309 {
310 m_log.DebugFormat(
311 "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
312 inventoryItem.Name, inventoryItem.ID, m_invPath);
313
314 SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH);
315 }
316 }
317 else
318 { 267 {
319 m_log.DebugFormat( 268 m_log.DebugFormat(
320 "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}", 269 "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}",
321 inventoryFolder.Name, inventoryFolder.ID, m_invPath); 270 inventoryFolder.Name, inventoryFolder.ID, m_invPath);
322 271
323 //recurse through all dirs getting dirs and files 272 //recurse through all dirs getting dirs and files
324 SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !foundStar); 273 SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !foundStar);
274 }
275 else if (inventoryItem != null)
276 {
277 m_log.DebugFormat(
278 "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
279 inventoryItem.Name, inventoryItem.ID, m_invPath);
280
281 SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH);
282 }
283 else
284 {
285 // We couldn't find the path indicated
286 m_saveStream.Close();
287 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath);
288 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", errorMessage);
289 m_module.TriggerInventoryArchiveSaved(
290 m_id, false, m_userInfo, m_invPath, m_saveStream,
291 new Exception(errorMessage));
292 return;
325 } 293 }
326 294
327 // Don't put all this profile information into the archive right now. 295 // Don't put all this profile information into the archive right now.
@@ -396,7 +364,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
396 { 364 {
397 return string.Format( 365 return string.Format(
398 "{0}{1}{2}/", 366 "{0}{1}{2}/",
399 name, 367 InventoryArchiveUtils.EscapeArchivePath(name),
400 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, 368 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
401 id); 369 id);
402 } 370 }
@@ -411,7 +379,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
411 { 379 {
412 return string.Format( 380 return string.Format(
413 "{0}{1}{2}.xml", 381 "{0}{1}{2}.xml",
414 name, 382 InventoryArchiveUtils.EscapeArchivePath(name),
415 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, 383 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
416 id); 384 id);
417 } 385 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index b0fdcd6..f8a010c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -29,7 +29,6 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Reflection; 31using System.Reflection;
32using System.Text;
33using System.Threading; 32using System.Threading;
34using NUnit.Framework; 33using NUnit.Framework;
35using NUnit.Framework.SyntaxHelpers; 34using NUnit.Framework.SyntaxHelpers;
@@ -122,9 +121,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
122 } 121 }
123 122
124 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 123 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
125 AssetBase asset1 = new AssetBase(); 124 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
126 asset1.FullID = asset1Id;
127 asset1.Data = Encoding.ASCII.GetBytes(SceneObjectSerializer.ToXml2Format(object1));
128 scene.AssetService.Store(asset1); 125 scene.AssetService.Store(asset1);
129 126
130 // Create item 127 // Create item
@@ -136,7 +133,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
136 InventoryFolderBase objsFolder 133 InventoryFolderBase objsFolder
137 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects"); 134 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects");
138 item1.Folder = objsFolder.ID; 135 item1.Folder = objsFolder.ID;
139 scene.AddInventoryItem(userId, item1); 136 scene.AddInventoryItem(userId, item1);
140 137
141 MemoryStream archiveWriteStream = new MemoryStream(); 138 MemoryStream archiveWriteStream = new MemoryStream();
142 archiverModule.OnInventoryArchiveSaved += SaveCompleted; 139 archiverModule.OnInventoryArchiveSaved += SaveCompleted;
@@ -218,14 +215,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
218 string userItemCreatorLastName = "Lucan"; 215 string userItemCreatorLastName = "Lucan";
219 UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 216 UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
220 217
221 string itemName = "b.lsl"; 218 string item1Name = "b.lsl";
222 string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); 219 string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1Name, UUID.Random());
223 220
224 MemoryStream archiveWriteStream = new MemoryStream(); 221 MemoryStream archiveWriteStream = new MemoryStream();
225 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); 222 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
226 223
227 InventoryItemBase item1 = new InventoryItemBase(); 224 InventoryItemBase item1 = new InventoryItemBase();
228 item1.Name = itemName; 225 item1.Name = item1Name;
229 item1.AssetID = UUID.Random(); 226 item1.AssetID = UUID.Random();
230 item1.GroupID = UUID.Random(); 227 item1.GroupID = UUID.Random();
231 item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName); 228 item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName);
@@ -259,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
259 = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); 256 = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName);
260 257
261 InventoryItemBase foundItem1 258 InventoryItemBase foundItem1
262 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, itemName); 259 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, item1Name);
263 260
264 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); 261 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
265 Assert.That( 262 Assert.That(
@@ -277,7 +274,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
277 archiverModule.DearchiveInventory(userFirstName, userLastName, "xA", "meowfood", archiveReadStream); 274 archiverModule.DearchiveInventory(userFirstName, userLastName, "xA", "meowfood", archiveReadStream);
278 275
279 InventoryItemBase foundItem2 276 InventoryItemBase foundItem2
280 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, "xA/" + itemName); 277 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, "xA/" + item1Name);
281 Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); 278 Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2");
282 279
283 // Now try loading to a more deeply nested folder 280 // Now try loading to a more deeply nested folder
@@ -286,10 +283,99 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
286 archiverModule.DearchiveInventory(userFirstName, userLastName, "xB/xC", "meowfood", archiveReadStream); 283 archiverModule.DearchiveInventory(userFirstName, userLastName, "xB/xC", "meowfood", archiveReadStream);
287 284
288 InventoryItemBase foundItem3 285 InventoryItemBase foundItem3
289 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, "xB/xC/" + itemName); 286 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, "xB/xC/" + item1Name);
290 Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); 287 Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3");
291 } 288 }
292 289
290 [Test]
291 public void TestIarV0_1WithEscapedChars()
292 {
293 TestHelper.InMethod();
294// log4net.Config.XmlConfigurator.Configure();
295
296 string itemName = "You & you are a mean/man/";
297 string humanEscapedItemName = @"You & you are a mean\/man\/";
298 string userPassword = "meowfood";
299
300 InventoryArchiverModule archiverModule = new InventoryArchiverModule(true);
301
302 Scene scene = SceneSetupHelpers.SetupScene("Inventory");
303 SceneSetupHelpers.SetupSceneModules(scene, archiverModule);
304 CommunicationsManager cm = scene.CommsManager;
305
306 // Create user
307 string userFirstName = "Jock";
308 string userLastName = "Stirrup";
309 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
310
311 lock (this)
312 {
313 UserProfileTestUtils.CreateUserWithInventory(
314 cm, userFirstName, userLastName, userPassword, userId, InventoryReceived);
315 Monitor.Wait(this, 60000);
316 }
317
318 // Create asset
319 SceneObjectGroup object1;
320 SceneObjectPart part1;
321 {
322 string partName = "part name";
323 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
324 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
325 Vector3 groupPosition = new Vector3(10, 20, 30);
326 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
327 Vector3 offsetPosition = new Vector3(5, 10, 15);
328
329 part1
330 = new SceneObjectPart(
331 ownerId, shape, groupPosition, rotationOffset, offsetPosition);
332 part1.Name = partName;
333
334 object1 = new SceneObjectGroup(part1);
335 scene.AddNewSceneObject(object1, false);
336 }
337
338 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
339 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
340 scene.AssetService.Store(asset1);
341
342 // Create item
343 UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080");
344 InventoryItemBase item1 = new InventoryItemBase();
345 item1.Name = itemName;
346 item1.AssetID = asset1.FullID;
347 item1.ID = item1Id;
348 InventoryFolderBase objsFolder
349 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects");
350 item1.Folder = objsFolder.ID;
351 scene.AddInventoryItem(userId, item1);
352
353 MemoryStream archiveWriteStream = new MemoryStream();
354 archiverModule.OnInventoryArchiveSaved += SaveCompleted;
355
356 mre.Reset();
357 archiverModule.ArchiveInventory(
358 Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream);
359 mre.WaitOne(60000, false);
360
361 // LOAD ITEM
362 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
363
364 archiverModule.DearchiveInventory(userFirstName, userLastName, "Scripts", userPassword, archiveReadStream);
365
366 InventoryItemBase foundItem1
367 = InventoryArchiveUtils.FindItemByPath(
368 scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName);
369
370 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
371// Assert.That(
372// foundItem1.CreatorId, Is.EqualTo(userUuid),
373// "Loaded item non-uuid creator doesn't match that of the loading user");
374 Assert.That(
375 foundItem1.Name, Is.EqualTo(itemName),
376 "Loaded item name doesn't match saved name");
377 }
378
293 /// <summary> 379 /// <summary>
294 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 380 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
295 /// embedded creators do not exist in the system 381 /// embedded creators do not exist in the system
@@ -302,7 +388,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
302 { 388 {
303 TestHelper.InMethod(); 389 TestHelper.InMethod();
304 390
305 log4net.Config.XmlConfigurator.Configure(); 391 //log4net.Config.XmlConfigurator.Configure();
306 392
307 string userFirstName = "Charlie"; 393 string userFirstName = "Charlie";
308 string userLastName = "Chan"; 394 string userLastName = "Chan";
@@ -370,7 +456,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
370 { 456 {
371 TestHelper.InMethod(); 457 TestHelper.InMethod();
372 458
373 log4net.Config.XmlConfigurator.Configure(); 459 //log4net.Config.XmlConfigurator.Configure();
374 460
375 string userFirstName = "Dennis"; 461 string userFirstName = "Dennis";
376 string userLastName = "Menace"; 462 string userLastName = "Menace";