diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Inventory/Archiver')
4 files changed, 199 insertions, 136 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 4c02214..ee8b1bf 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,6 +129,11 @@ 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 | { |
@@ -168,43 +143,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
168 | rootDestinationFolder, foldersCreated, nodesLoaded); | 143 | rootDestinationFolder, foldersCreated, nodesLoaded); |
169 | 144 | ||
170 | if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) | 145 | if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) |
171 | { | 146 | { |
172 | // Escape back characters | 147 | InventoryItemBase item = LoadItem(data, foundFolder); |
173 | filePath = filePath.Replace("/", "/"); | ||
174 | filePath = filePath.Replace("&", "&"); | ||
175 | |||
176 | InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data); | ||
177 | |||
178 | // Don't use the item ID that's in the file | ||
179 | item.ID = UUID.Random(); | ||
180 | |||
181 | UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.CommsManager); | ||
182 | if (UUID.Zero != ospResolvedId) | ||
183 | item.CreatorIdAsUuid = ospResolvedId; | ||
184 | else | ||
185 | item.CreatorIdAsUuid = m_userInfo.UserProfile.ID; | ||
186 | |||
187 | item.Owner = m_userInfo.UserProfile.ID; | ||
188 | |||
189 | // Reset folder ID to the one in which we want to load it | ||
190 | item.Folder = foundFolder.ID; | ||
191 | |||
192 | //m_userInfo.AddItem(item); | ||
193 | m_scene.InventoryService.AddItem(item); | ||
194 | successfulItemRestores++; | ||
195 | 148 | ||
196 | // If we're loading an item directly into the given destination folder then we need to record | 149 | if (item != null) |
197 | // it separately from any loaded root folders | 150 | { |
198 | if (rootDestinationFolder == foundFolder) | 151 | successfulItemRestores++; |
199 | nodesLoaded.Add(item); | 152 | |
153 | // If we're loading an item directly into the given destination folder then we need to record | ||
154 | // it separately from any loaded root folders | ||
155 | if (rootDestinationFolder == foundFolder) | ||
156 | nodesLoaded.Add(item); | ||
157 | } | ||
200 | } | 158 | } |
201 | } | 159 | } |
202 | } | 160 | } |
203 | 161 | ||
204 | archive.Close(); | 162 | archive.Close(); |
205 | 163 | ||
206 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Restored {0} assets", successfulAssetRestores); | 164 | m_log.DebugFormat( |
207 | 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); | ||
208 | 168 | ||
209 | return nodesLoaded; | 169 | return nodesLoaded; |
210 | } | 170 | } |
@@ -239,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
239 | string originalArchivePath = archivePath; | 199 | string originalArchivePath = archivePath; |
240 | 200 | ||
241 | m_log.DebugFormat( | 201 | m_log.DebugFormat( |
242 | "[INVENTORY ARCHIVER]: Loading to folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); | 202 | "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); |
243 | 203 | ||
244 | InventoryFolderBase destFolder = null; | 204 | InventoryFolderBase destFolder = null; |
245 | 205 | ||
@@ -250,8 +210,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
250 | { | 210 | { |
251 | if (foldersCreated.ContainsKey(archivePath)) | 211 | if (foldersCreated.ContainsKey(archivePath)) |
252 | { | 212 | { |
253 | m_log.DebugFormat( | 213 | // m_log.DebugFormat( |
254 | "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); | 214 | // "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); |
255 | destFolder = foldersCreated[archivePath]; | 215 | destFolder = foldersCreated[archivePath]; |
256 | } | 216 | } |
257 | else | 217 | else |
@@ -294,10 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
294 | 254 | ||
295 | string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex); | 255 | string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex); |
296 | 256 | ||
297 | // Escape back characters | 257 | newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName); |
298 | newFolderName = newFolderName.Replace("/", "/"); | ||
299 | newFolderName = newFolderName.Replace("&", "&"); | ||
300 | |||
301 | UUID newFolderId = UUID.Random(); | 258 | UUID newFolderId = UUID.Random(); |
302 | 259 | ||
303 | // 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 |
@@ -370,6 +327,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
370 | } | 327 | } |
371 | 328 | ||
372 | /// <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> | ||
373 | /// Load an asset | 361 | /// Load an asset |
374 | /// </summary> | 362 | /// </summary> |
375 | /// <param name="assetFilename"></param> | 363 | /// <param name="assetFilename"></param> |
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 af0b72f..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. |
@@ -394,13 +362,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
394 | /// <returns></returns> | 362 | /// <returns></returns> |
395 | public static string CreateArchiveFolderName(string name, UUID id) | 363 | public static string CreateArchiveFolderName(string name, UUID id) |
396 | { | 364 | { |
397 | // Only encode ampersands (for escaping anything) and / (since this is used as general dir separator). | ||
398 | name = name.Replace("&", "&"); | ||
399 | name = name.Replace("/", "/"); | ||
400 | |||
401 | return string.Format( | 365 | return string.Format( |
402 | "{0}{1}{2}/", | 366 | "{0}{1}{2}/", |
403 | name, | 367 | InventoryArchiveUtils.EscapeArchivePath(name), |
404 | ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, | 368 | ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, |
405 | id); | 369 | id); |
406 | } | 370 | } |
@@ -413,12 +377,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
413 | /// <returns></returns> | 377 | /// <returns></returns> |
414 | public static string CreateArchiveItemName(string name, UUID id) | 378 | public static string CreateArchiveItemName(string name, UUID id) |
415 | { | 379 | { |
416 | name = name.Replace("&", "&"); | ||
417 | name = name.Replace("/", "/"); | ||
418 | |||
419 | return string.Format( | 380 | return string.Format( |
420 | "{0}{1}{2}.xml", | 381 | "{0}{1}{2}.xml", |
421 | name, | 382 | InventoryArchiveUtils.EscapeArchivePath(name), |
422 | ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, | 383 | ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, |
423 | id); | 384 | id); |
424 | } | 385 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index e300eb1..99d02c4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs | |||
@@ -295,7 +295,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
295 | TestHelper.InMethod(); | 295 | TestHelper.InMethod(); |
296 | log4net.Config.XmlConfigurator.Configure(); | 296 | log4net.Config.XmlConfigurator.Configure(); |
297 | 297 | ||
298 | string itemName = "You & you are a mean man"; | 298 | string itemName = "You & you are a mean/man/"; |
299 | string humanEscapedItemName = @"You & you are a mean\/man\/"; | ||
299 | string userPassword = "meowfood"; | 300 | string userPassword = "meowfood"; |
300 | 301 | ||
301 | InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); | 302 | InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); |
@@ -360,7 +361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
360 | Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); | 361 | Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); |
361 | mre.WaitOne(60000, false); | 362 | mre.WaitOne(60000, false); |
362 | 363 | ||
363 | /// LOAD ITEM | 364 | // LOAD ITEM |
364 | MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); | 365 | MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); |
365 | 366 | ||
366 | archiverModule.DearchiveInventory(userFirstName, userLastName, "Scripts", userPassword, archiveReadStream); | 367 | archiverModule.DearchiveInventory(userFirstName, userLastName, "Scripts", userPassword, archiveReadStream); |
@@ -369,7 +370,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
369 | = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); | 370 | = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); |
370 | 371 | ||
371 | InventoryItemBase foundItem1 | 372 | InventoryItemBase foundItem1 |
372 | = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userId, "Scripts/Objects/" + itemName); | 373 | = InventoryArchiveUtils.FindItemByPath( |
374 | scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName); | ||
373 | 375 | ||
374 | Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); | 376 | Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); |
375 | // Assert.That( | 377 | // Assert.That( |