diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | 120 |
1 files changed, 103 insertions, 17 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d0e88f6..f002ad7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | |||
@@ -34,6 +34,7 @@ using System.Xml; | |||
34 | using log4net; | 34 | using log4net; |
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenSim.Framework; | 36 | using OpenSim.Framework; |
37 | using OpenSim.Framework.Monitoring; | ||
37 | using OpenSim.Framework.Serialization; | 38 | using OpenSim.Framework.Serialization; |
38 | using OpenSim.Framework.Serialization.External; | 39 | using OpenSim.Framework.Serialization.External; |
39 | using OpenSim.Region.CoreModules.World.Archiver; | 40 | using OpenSim.Region.CoreModules.World.Archiver; |
@@ -42,6 +43,8 @@ using OpenSim.Services.Interfaces; | |||
42 | using Ionic.Zlib; | 43 | using Ionic.Zlib; |
43 | using GZipStream = Ionic.Zlib.GZipStream; | 44 | using GZipStream = Ionic.Zlib.GZipStream; |
44 | using CompressionMode = Ionic.Zlib.CompressionMode; | 45 | using CompressionMode = Ionic.Zlib.CompressionMode; |
46 | using CompressionLevel = Ionic.Zlib.CompressionLevel; | ||
47 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
45 | 48 | ||
46 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | 49 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver |
47 | { | 50 | { |
@@ -54,6 +57,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
54 | /// </summary> | 57 | /// </summary> |
55 | public bool SaveAssets { get; set; } | 58 | public bool SaveAssets { get; set; } |
56 | 59 | ||
60 | /// <summary> | ||
61 | /// Determines which items will be included in the archive, according to their permissions. | ||
62 | /// Default is null, meaning no permission checks. | ||
63 | /// </summary> | ||
64 | public string FilterContent { get; set; } | ||
65 | |||
66 | /// <summary> | ||
67 | /// Counter for inventory items saved to archive for passing to compltion event | ||
68 | /// </summary> | ||
69 | public int CountItems { get; set; } | ||
70 | |||
71 | /// <summary> | ||
72 | /// Counter for inventory items skipped due to permission filter option for passing to compltion event | ||
73 | /// </summary> | ||
74 | public int CountFiltered { get; set; } | ||
75 | |||
57 | /// <value> | 76 | /// <value> |
58 | /// Used to select all inventory nodes in a folder but not the folder itself | 77 | /// Used to select all inventory nodes in a folder but not the folder itself |
59 | /// </value> | 78 | /// </value> |
@@ -73,12 +92,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
73 | /// <value> | 92 | /// <value> |
74 | /// ID of this request | 93 | /// ID of this request |
75 | /// </value> | 94 | /// </value> |
76 | protected Guid m_id; | 95 | protected UUID m_id; |
77 | |||
78 | /// <value> | ||
79 | /// Used to collect the uuids of the assets that we need to save into the archive | ||
80 | /// </value> | ||
81 | protected Dictionary<UUID, AssetType> m_assetUuids = new Dictionary<UUID, AssetType>(); | ||
82 | 96 | ||
83 | /// <value> | 97 | /// <value> |
84 | /// Used to collect the uuids of the users that we need to save into the archive | 98 | /// Used to collect the uuids of the users that we need to save into the archive |
@@ -94,7 +108,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
94 | /// Constructor | 108 | /// Constructor |
95 | /// </summary> | 109 | /// </summary> |
96 | public InventoryArchiveWriteRequest( | 110 | public InventoryArchiveWriteRequest( |
97 | Guid id, InventoryArchiverModule module, Scene scene, | 111 | UUID id, InventoryArchiverModule module, Scene scene, |
98 | UserAccount userInfo, string invPath, string savePath) | 112 | UserAccount userInfo, string invPath, string savePath) |
99 | : this( | 113 | : this( |
100 | id, | 114 | id, |
@@ -110,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
110 | /// Constructor | 124 | /// Constructor |
111 | /// </summary> | 125 | /// </summary> |
112 | public InventoryArchiveWriteRequest( | 126 | public InventoryArchiveWriteRequest( |
113 | Guid id, InventoryArchiverModule module, Scene scene, | 127 | UUID id, InventoryArchiverModule module, Scene scene, |
114 | UserAccount userInfo, string invPath, Stream saveStream) | 128 | UserAccount userInfo, string invPath, Stream saveStream) |
115 | { | 129 | { |
116 | m_id = id; | 130 | m_id = id; |
@@ -122,9 +136,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
122 | m_assetGatherer = new UuidGatherer(m_scene.AssetService); | 136 | m_assetGatherer = new UuidGatherer(m_scene.AssetService); |
123 | 137 | ||
124 | SaveAssets = true; | 138 | SaveAssets = true; |
139 | FilterContent = null; | ||
125 | } | 140 | } |
126 | 141 | ||
127 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) | 142 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut) |
128 | { | 143 | { |
129 | Exception reportedException = null; | 144 | Exception reportedException = null; |
130 | bool succeeded = true; | 145 | bool succeeded = true; |
@@ -143,8 +158,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
143 | m_saveStream.Close(); | 158 | m_saveStream.Close(); |
144 | } | 159 | } |
145 | 160 | ||
161 | if (timedOut) | ||
162 | { | ||
163 | succeeded = false; | ||
164 | reportedException = new Exception("Loading assets timed out"); | ||
165 | } | ||
166 | |||
146 | m_module.TriggerInventoryArchiveSaved( | 167 | m_module.TriggerInventoryArchiveSaved( |
147 | m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); | 168 | m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException, CountItems, CountFiltered); |
148 | } | 169 | } |
149 | 170 | ||
150 | protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService) | 171 | protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService) |
@@ -160,10 +181,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
160 | "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}", | 181 | "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}", |
161 | inventoryItem.Name, inventoryItem.ID, path); | 182 | inventoryItem.Name, inventoryItem.ID, path); |
162 | } | 183 | } |
184 | |||
185 | CountFiltered++; | ||
186 | |||
163 | return; | 187 | return; |
164 | } | 188 | } |
165 | } | 189 | } |
166 | 190 | ||
191 | // Check For Permissions Filter Flags | ||
192 | if (!CanUserArchiveObject(m_userInfo.PrincipalID, inventoryItem)) | ||
193 | { | ||
194 | m_log.InfoFormat( | ||
195 | "[INVENTORY ARCHIVER]: Insufficient permissions, skipping inventory item {0} {1} at {2}", | ||
196 | inventoryItem.Name, inventoryItem.ID, path); | ||
197 | |||
198 | // Count Items Excluded | ||
199 | CountFiltered++; | ||
200 | |||
201 | return; | ||
202 | } | ||
203 | |||
167 | if (options.ContainsKey("verbose")) | 204 | if (options.ContainsKey("verbose")) |
168 | m_log.InfoFormat( | 205 | m_log.InfoFormat( |
169 | "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", | 206 | "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", |
@@ -179,9 +216,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
179 | 216 | ||
180 | AssetType itemAssetType = (AssetType)inventoryItem.AssetType; | 217 | AssetType itemAssetType = (AssetType)inventoryItem.AssetType; |
181 | 218 | ||
219 | // Count inventory items (different to asset count) | ||
220 | CountItems++; | ||
221 | |||
182 | // Don't chase down link asset items as they actually point to their target item IDs rather than an asset | 222 | // Don't chase down link asset items as they actually point to their target item IDs rather than an asset |
183 | if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) | 223 | if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) |
184 | m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); | 224 | m_assetGatherer.AddForInspection(inventoryItem.AssetID); |
185 | } | 225 | } |
186 | 226 | ||
187 | /// <summary> | 227 | /// <summary> |
@@ -237,6 +277,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
237 | } | 277 | } |
238 | 278 | ||
239 | /// <summary> | 279 | /// <summary> |
280 | /// Checks whether the user has permission to export an inventory item to an IAR. | ||
281 | /// </summary> | ||
282 | /// <param name="UserID">The user</param> | ||
283 | /// <param name="InvItem">The inventory item</param> | ||
284 | /// <returns>Whether the user is allowed to export the object to an IAR</returns> | ||
285 | private bool CanUserArchiveObject(UUID UserID, InventoryItemBase InvItem) | ||
286 | { | ||
287 | if (FilterContent == null) | ||
288 | return true;// Default To Allow Export | ||
289 | |||
290 | bool permitted = true; | ||
291 | |||
292 | bool canCopy = (InvItem.CurrentPermissions & (uint)PermissionMask.Copy) != 0; | ||
293 | bool canTransfer = (InvItem.CurrentPermissions & (uint)PermissionMask.Transfer) != 0; | ||
294 | bool canMod = (InvItem.CurrentPermissions & (uint)PermissionMask.Modify) != 0; | ||
295 | |||
296 | if (FilterContent.Contains("C") && !canCopy) | ||
297 | permitted = false; | ||
298 | |||
299 | if (FilterContent.Contains("T") && !canTransfer) | ||
300 | permitted = false; | ||
301 | |||
302 | if (FilterContent.Contains("M") && !canMod) | ||
303 | permitted = false; | ||
304 | |||
305 | return permitted; | ||
306 | } | ||
307 | |||
308 | /// <summary> | ||
240 | /// Execute the inventory write request | 309 | /// Execute the inventory write request |
241 | /// </summary> | 310 | /// </summary> |
242 | public void Execute(Dictionary<string, object> options, IUserAccountService userAccountService) | 311 | public void Execute(Dictionary<string, object> options, IUserAccountService userAccountService) |
@@ -244,6 +313,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
244 | if (options.ContainsKey("noassets") && (bool)options["noassets"]) | 313 | if (options.ContainsKey("noassets") && (bool)options["noassets"]) |
245 | SaveAssets = false; | 314 | SaveAssets = false; |
246 | 315 | ||
316 | // Set Permission filter if flag is set | ||
317 | if (options.ContainsKey("checkPermissions")) | ||
318 | { | ||
319 | Object temp; | ||
320 | if (options.TryGetValue("checkPermissions", out temp)) | ||
321 | FilterContent = temp.ToString().ToUpper(); | ||
322 | } | ||
323 | |||
247 | try | 324 | try |
248 | { | 325 | { |
249 | InventoryFolderBase inventoryFolder = null; | 326 | InventoryFolderBase inventoryFolder = null; |
@@ -266,6 +343,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
266 | saveFolderContentsOnly = true; | 343 | saveFolderContentsOnly = true; |
267 | maxComponentIndex--; | 344 | maxComponentIndex--; |
268 | } | 345 | } |
346 | else if (maxComponentIndex == -1) | ||
347 | { | ||
348 | // If the user has just specified "/", then don't save the root "My Inventory" folder. This is | ||
349 | // more intuitive then requiring the user to specify "/*" for this. | ||
350 | saveFolderContentsOnly = true; | ||
351 | } | ||
269 | 352 | ||
270 | m_invPath = String.Empty; | 353 | m_invPath = String.Empty; |
271 | for (int i = 0; i <= maxComponentIndex; i++) | 354 | for (int i = 0; i <= maxComponentIndex; i++) |
@@ -283,7 +366,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
283 | { | 366 | { |
284 | m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); | 367 | m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); |
285 | List<InventoryFolderBase> candidateFolders | 368 | List<InventoryFolderBase> candidateFolders |
286 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); | 369 | = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, rootFolder, m_invPath); |
287 | if (candidateFolders.Count > 0) | 370 | if (candidateFolders.Count > 0) |
288 | inventoryFolder = candidateFolders[0]; | 371 | inventoryFolder = candidateFolders[0]; |
289 | } | 372 | } |
@@ -297,7 +380,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
297 | // We couldn't find the path indicated | 380 | // We couldn't find the path indicated |
298 | string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); | 381 | string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); |
299 | Exception e = new InventoryArchiverException(errorMessage); | 382 | Exception e = new InventoryArchiverException(errorMessage); |
300 | m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); | 383 | m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0); |
301 | throw e; | 384 | throw e; |
302 | } | 385 | } |
303 | 386 | ||
@@ -335,22 +418,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
335 | 418 | ||
336 | if (SaveAssets) | 419 | if (SaveAssets) |
337 | { | 420 | { |
338 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); | 421 | m_assetGatherer.GatherAll(); |
422 | |||
423 | m_log.DebugFormat( | ||
424 | "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count); | ||
339 | 425 | ||
340 | AssetsRequest ar | 426 | AssetsRequest ar |
341 | = new AssetsRequest( | 427 | = new AssetsRequest( |
342 | new AssetsArchiver(m_archiveWriter), | 428 | new AssetsArchiver(m_archiveWriter), |
343 | m_assetUuids, m_scene.AssetService, | 429 | m_assetGatherer.GatheredUuids, m_scene.AssetService, |
344 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, | 430 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, |
345 | options, ReceivedAllAssets); | 431 | options, ReceivedAllAssets); |
346 | 432 | ||
347 | Util.FireAndForget(o => ar.Execute()); | 433 | WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name)); |
348 | } | 434 | } |
349 | else | 435 | else |
350 | { | 436 | { |
351 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); | 437 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); |
352 | 438 | ||
353 | ReceivedAllAssets(new List<UUID>(), new List<UUID>()); | 439 | ReceivedAllAssets(new List<UUID>(), new List<UUID>(), false); |
354 | } | 440 | } |
355 | } | 441 | } |
356 | catch (Exception) | 442 | catch (Exception) |