diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 523832566d..3bda6b42a1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -91,7 +91,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// Constructor /// public InventoryArchiveWriteRequest( - Guid id, InventoryArchiverModule module, Scene scene, + Guid id, InventoryArchiverModule module, Scene scene, UserAccount userInfo, string invPath, string savePath) : this( id, @@ -107,7 +107,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// Constructor /// public InventoryArchiveWriteRequest( - Guid id, InventoryArchiverModule module, Scene scene, + Guid id, InventoryArchiverModule module, Scene scene, UserAccount userInfo, string invPath, Stream saveStream) { m_id = id; @@ -125,7 +125,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { Exception reportedException = null; bool succeeded = true; - + try { m_archiveWriter.Close(); @@ -146,6 +146,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary options, IUserAccountService userAccountService) { + if (options.ContainsKey("exclude")) + { + if (((List)options["exclude"]).Contains(inventoryItem.Name) || + ((List)options["exclude"]).Contains(inventoryItem.ID.ToString())) + { + if (options.ContainsKey("verbose")) + { + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}", + inventoryItem.Name, inventoryItem.ID, path); + } + return; + } + } + if (options.ContainsKey("verbose")) m_log.InfoFormat( "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", @@ -175,12 +190,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// protected void SaveInvFolder( - InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself, + InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself, Dictionary options, IUserAccountService userAccountService) { + if (options.ContainsKey("excludefolders")) + { + if (((List)options["excludefolders"]).Contains(inventoryFolder.Name) || + ((List)options["excludefolders"]).Contains(inventoryFolder.ID.ToString())) + { + if (options.ContainsKey("verbose")) + { + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Skipping folder {0} at {1}", + inventoryFolder.Name, path); + } + return; + } + } + if (options.ContainsKey("verbose")) m_log.InfoFormat("[INVENTORY ARCHIVER]: Saving folder {0}", inventoryFolder.Name); - + if (saveThisFolderItself) { path += CreateArchiveFolderName(inventoryFolder); @@ -189,7 +219,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_archiveWriter.WriteDir(path); } - InventoryCollection contents + InventoryCollection contents = m_scene.InventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID); foreach (InventoryFolderBase childFolder in contents.Folders) @@ -216,16 +246,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver InventoryFolderBase inventoryFolder = null; InventoryItemBase inventoryItem = null; InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); - + bool saveFolderContentsOnly = false; - + // Eliminate double slashes and any leading / on the path. string[] components = m_invPath.Split( new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); - + int maxComponentIndex = components.Length - 1; - + // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the // folder itself. This may get more sophisicated later on if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) @@ -233,13 +263,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver saveFolderContentsOnly = true; maxComponentIndex--; } - + m_invPath = String.Empty; for (int i = 0; i <= maxComponentIndex; i++) { m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; } - + // Annoyingly Split actually returns the original string if the input string consists only of delimiters // Therefore if we still start with a / after the split, then we need the root folder if (m_invPath.Length == 0) @@ -249,25 +279,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver else { m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); - List candidateFolders + List candidateFolders = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); if (candidateFolders.Count > 0) inventoryFolder = candidateFolders[0]; } - + // The path may point to an item instead if (inventoryFolder == null) inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); - + if (null == inventoryFolder && null == inventoryItem) { - // We couldn't find the path indicated + // We couldn't find the path indicated string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); Exception e = new InventoryArchiverException(errorMessage); m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); throw e; } - + m_archiveWriter = new TarArchiveWriter(m_saveStream); // Write out control file. This has to be done first so that subsequent loaders will see this file first @@ -275,15 +305,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // not sure how to fix this though, short of going with a completely different file format. m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); m_log.InfoFormat("[INVENTORY ARCHIVER]: Added control file to archive."); - + if (inventoryFolder != null) { m_log.DebugFormat( "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}", - inventoryFolder.Name, - inventoryFolder.ID, + inventoryFolder.Name, + inventoryFolder.ID, m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath); - + //recurse through all dirs getting dirs and files SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService); } @@ -292,10 +322,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.DebugFormat( "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, m_invPath); - + SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService); } - + // Don't put all this profile information into the archive right now. //SaveUsers(); @@ -354,7 +384,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// These names are prepended with an inventory folder's UUID so that more than one folder can have the /// same name - /// + /// /// /// public static string CreateArchiveFolderName(InventoryFolderBase folder) @@ -368,7 +398,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// These names are prepended with an inventory item's UUID so that more than one item can have the /// same name - /// + /// /// /// public static string CreateArchiveItemName(InventoryItemBase item) @@ -414,7 +444,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver public string CreateControlFile(Dictionary options) { int majorVersion, minorVersion; - + if (options.ContainsKey("home")) { majorVersion = 1; @@ -424,10 +454,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { majorVersion = 0; minorVersion = 3; - } - + } + m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); - + StringWriter sw = new StringWriter(); XmlTextWriter xtw = new XmlTextWriter(sw); xtw.Formatting = Formatting.Indented; @@ -449,4 +479,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return s; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index a81f36c996..1cec52428b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -47,18 +47,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + public string Name { get { return "Inventory Archiver Module"; } } - + public bool IsSharedModule { get { return true; } } /// - /// Enable or disable checking whether the iar user is actually logged in + /// Enable or disable checking whether the iar user is actually logged in /// // public bool DisablePresenceChecks { get; set; } - + public event InventoryArchiveSaved OnInventoryArchiveSaved; - + /// /// The file to load and save inventory if no filename has been specified /// @@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// Pending save completions initiated from the console /// protected List m_pendingConsoleSaves = new List(); - + /// /// All scenes that this module knows about /// @@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { scene.RegisterModuleInterface(this); OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted; - + scene.AddCommand( this, "load iar", "load iar [-m|--merge] []", @@ -119,16 +119,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver + " is the filesystem path or URI from which to load the IAR." + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), HandleLoadInvConsoleCommand); - + scene.AddCommand( this, "save iar", - "save iar [-h|--home=] [--noassets] [] [-c|--creators] [-v|--verbose]", - "Save user inventory archive (IAR).", + "save iar [-h|--home=] [--noassets] [] [-c|--creators] [-e|--exclude=] [-f|--excludefolder=] [-v|--verbose]", + "Save user inventory archive (IAR).", " is the user's first name." + Environment.NewLine + " is the user's last name." + Environment.NewLine + " is the path inside the user's inventory for the folder/item to be saved." + Environment.NewLine + "-h|--home= adds the url of the profile service to the saved user information." + Environment.NewLine + "-c|--creators preserves information about foreign creators." + Environment.NewLine + + "-e|--exclude= don't save the inventory item in archive" + Environment.NewLine + + "-f|--excludefolder= don't save contents of the folder in archive" + Environment.NewLine + "-v|--verbose extra debug messages." + Environment.NewLine + "--noassets stops assets being saved to the IAR." + " is the filesystem path at which to save the IAR." @@ -137,26 +139,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_aScene = scene; } - + m_scenes[scene.RegionInfo.RegionID] = scene; } public void PostInitialise() {} public void Close() {} - + /// /// Trigger the inventory archive saved event. /// protected internal void TriggerInventoryArchiveSaved( - Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, + Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, Exception reportedException) { InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved; if (handlerInventoryArchiveSaved != null) handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException); } - + public bool ArchiveInventory( Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) { @@ -164,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } public bool ArchiveInventory( - Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, + Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, Dictionary options) { if (m_scenes.Count > 0) @@ -188,7 +190,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - + return true; // } // else @@ -202,15 +204,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - + public bool ArchiveInventory( - Guid id, string firstName, string lastName, string invPath, string pass, string savePath, + Guid id, string firstName, string lastName, string invPath, string pass, string savePath, Dictionary options) { if (m_scenes.Count > 0) { UserAccount userInfo = GetUserInfo(firstName, lastName, pass); - + if (userInfo != null) { // if (CheckPresence(userInfo.PrincipalID)) @@ -228,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - + return true; // } // else @@ -239,7 +241,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // } } } - + return false; } @@ -247,9 +249,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary()); } - + public bool DearchiveInventory( - string firstName, string lastName, string invPath, string pass, Stream loadStream, + string firstName, string lastName, string invPath, string pass, Stream loadStream, Dictionary options) { if (m_scenes.Count > 0) @@ -295,22 +297,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - + public bool DearchiveInventory( - string firstName, string lastName, string invPath, string pass, string loadPath, + string firstName, string lastName, string invPath, string pass, string loadPath, Dictionary options) { if (m_scenes.Count > 0) { UserAccount userInfo = GetUserInfo(firstName, lastName, pass); - + if (userInfo != null) { // if (CheckPresence(userInfo.PrincipalID)) // { InventoryArchiveReadRequest request; bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); - + try { request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge); @@ -324,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - + UpdateClientWithLoadedNodes(userInfo, request.Execute()); return true; @@ -340,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - + /// /// Load inventory from an inventory file archive /// @@ -350,29 +352,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver try { m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); - + Dictionary options = new Dictionary(); OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); - + List mainParams = optionSet.Parse(cmdparams); - + if (mainParams.Count < 6) { m_log.Error( - "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] []"); + "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] []"); return; } - + string firstName = mainParams[2]; string lastName = mainParams[3]; string invPath = mainParams[4]; string pass = mainParams[5]; string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); - + m_log.InfoFormat( "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", loadPath, invPath, firstName, lastName); - + if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) m_log.InfoFormat( "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", @@ -383,7 +385,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); } } - + /// /// Save inventory to a file archive /// @@ -400,6 +402,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); + ops.Add("e|exclude=", delegate(string v) + { + if (!options.ContainsKey("exclude")) + options["exclude"] = new List(); + ((List)options["exclude"]).Add(v); + }); + ops.Add("f|excludefolder=", delegate(string v) + { + if (!options.ContainsKey("excludefolders")) + options["excludefolders"] = new List(); + ((List)options["excludefolders"]).Add(v); + }); List mainParams = ops.Parse(cmdparams); @@ -408,10 +422,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (mainParams.Count < 6) { m_log.Error( - "[INVENTORY ARCHIVER]: usage is save iar [-h|--home=] [--noassets] [] [-c|--creators] [-v|--verbose]"); + "[INVENTORY ARCHIVER]: save iar [-h|--home=] [--noassets] [] [-c|--creators] [-e|--exclude=] [-f|--excludefolder=] [-v|--verbose]"); return; } - + m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); if (options.ContainsKey("home")) m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -home option if you want to produce a compatible IAR"); @@ -421,7 +435,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string invPath = mainParams[4]; string pass = mainParams[5]; string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); - + m_log.InfoFormat( "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", savePath, invPath, firstName, lastName); @@ -436,9 +450,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); } } - + private void SaveInvConsoleCommandCompleted( - Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, + Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, Exception reportedException) { lock (m_pendingConsoleSaves) @@ -448,7 +462,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver else return; } - + if (succeeded) { m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive for {0} {1}", userInfo.FirstName, userInfo.LastName); @@ -456,11 +470,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver else { m_log.ErrorFormat( - "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}", + "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}", userInfo.FirstName, userInfo.LastName, reportedException.Message); } } - + /// /// Get user information for the given name. /// @@ -470,13 +484,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// protected UserAccount GetUserInfo(string firstName, string lastName, string pass) { - UserAccount account + UserAccount account = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName); - + if (null == account) { m_log.ErrorFormat( - "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}", + "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}", firstName, lastName); return null; } @@ -491,7 +505,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver else { m_log.ErrorFormat( - "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.", + "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.", firstName, lastName); return null; } @@ -502,7 +516,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return null; } } - + /// /// Notify the client of loaded nodes if they are logged in /// @@ -511,22 +525,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { if (loadedNodes.Count == 0) return; - + foreach (Scene scene in m_scenes.Values) { ScenePresence user = scene.GetScenePresence(userInfo.PrincipalID); - + if (user != null && !user.IsChildAgent) { foreach (InventoryNodeBase node in loadedNodes) { // m_log.DebugFormat( -// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}", +// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}", // user.Name, node.Name); - + user.ControllingClient.SendBulkUpdateInventory(node); } - + break; } } @@ -541,7 +555,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // { // if (DisablePresenceChecks) // return true; -// +// // foreach (Scene scene in m_scenes.Values) // { // ScenePresence p;