diff options
Diffstat (limited to '')
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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | ||
31 | using System.Text; | ||
32 | using log4net; | ||
30 | using OpenMetaverse; | 33 | using OpenMetaverse; |
31 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
32 | using OpenSim.Services.Interfaces; | 35 | using 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("&", "&").Replace("/", "/"); | ||
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("/", "/").Replace("&", "&"); | ||
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; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.IO; | 30 | using System.IO; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Text; | ||
33 | using System.Threading; | 32 | using System.Threading; |
34 | using NUnit.Framework; | 33 | using NUnit.Framework; |
35 | using NUnit.Framework.SyntaxHelpers; | 34 | using 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"; |