/// <summary> /// Try do delete files that have been decrypted temporarily, if the conditions are met for such a deletion, /// i.e. it is apparently not locked or in use etc. /// </summary> /// <param name="fileSystemState">The instance of FileSystemState where active files are recorded.</param> /// <param name="progress">The context where progress may be reported.</param> public static void PurgeActiveFiles(this FileSystemState fileSystemState, ProgressContext progress) { progress.NotifyLevelStart(); fileSystemState.ForEach(ChangedEventMode.RaiseOnlyOnModified, (ActiveFile activeFile) => { if (FileLock.IsLocked(activeFile.DecryptedFileInfo)) { if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("Not deleting '{0}' because it is marked as locked.".InvariantFormat(activeFile.DecryptedFileInfo.FullName)); } return(activeFile); } if (activeFile.IsModified) { if (activeFile.Status.HasMask(ActiveFileStatus.NotShareable)) { activeFile = new ActiveFile(activeFile, activeFile.Status & ~ActiveFileStatus.NotShareable); } activeFile = CheckIfTimeToUpdate(activeFile, progress); } if (activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted)) { activeFile = TryDelete(activeFile, progress); } return(activeFile); }); progress.NotifyLevelFinished(); }
/// <summary> /// Enumerate all files listed as active, checking for status changes and take appropriate actions such as updating status /// in the FileSystemState, re-encrypting or deleting temporary plaintext copies. /// </summary> /// <param name="fileSystemState">The FileSystemState to enumerate and possibly update.</param> /// <param name="mode">Under what circumstances is the FileSystemState.Changed event raised.</param> /// <param name="progress">The ProgressContext to provide visual progress feedback via.</param> public static void CheckActiveFiles(this FileSystemState fileSystemState, ChangedEventMode mode, ProgressContext progress) { progress.NotifyLevelStart(); progress.AddTotal(fileSystemState.ActiveFileCount); fileSystemState.ForEach(mode, (ActiveFile activeFile) => { try { if (FileLock.IsLocked(activeFile.DecryptedFileInfo, activeFile.EncryptedFileInfo)) { return(activeFile); } if (OS.Current.UtcNow - activeFile.LastActivityTimeUtc <= new TimeSpan(0, 0, 5)) { return(activeFile); } activeFile = fileSystemState.CheckActiveFileActions(activeFile, progress); return(activeFile); } finally { progress.AddCount(1); } }); progress.NotifyLevelFinished(); }
/// <summary> /// For each active file, check if provided key matches the thumbprint of an active file that does not yet have /// a known key. If so, update the active file with the now known key. /// </summary> /// <param name="fileSystemState">The FileSystemState that contains the list of active files.</param> /// <param name="key">The newly added key to check the files for a match with.</param> /// <returns>True if any file was updated with the new key, False otherwise.</returns> public static bool UpdateActiveFileWithKeyIfKeyMatchesThumbprint(this FileSystemState fileSystemState, AesKey key) { bool keyMatch = false; fileSystemState.ForEach(ChangedEventMode.RaiseOnlyOnModified, (ActiveFile activeFile) => { if (activeFile.Key != null) { return(activeFile); } if (!activeFile.ThumbprintMatch(key)) { return(activeFile); } keyMatch = true; activeFile = new ActiveFile(activeFile, key); return(activeFile); }); return(keyMatch); }
public static void TestArgumentNull() { using (FileSystemState state = new FileSystemState()) { ActiveFile nullActiveFile = null; string nullPath = null; Func<ActiveFile, ActiveFile> nullAction = null; IRuntimeFileInfo nullFileInfo = null; Assert.Throws<ArgumentNullException>(() => { state.Remove(nullActiveFile); }); Assert.Throws<ArgumentNullException>(() => { state.Add(nullActiveFile); }); Assert.Throws<ArgumentNullException>(() => { state.FindEncryptedPath(nullPath); }); Assert.Throws<ArgumentNullException>(() => { state.FindDecryptedPath(nullPath); }); Assert.Throws<ArgumentNullException>(() => { state.ForEach(ChangedEventMode.RaiseAlways, nullAction); }); Assert.Throws<ArgumentNullException>(() => { state.Load(nullFileInfo); }); } }
public static void TestForEach() { bool changedEventWasRaised = false; using (FileSystemState state = new FileSystemState()) { state.Load(OS.Current.FileInfo(_mystateXmlPath)); state.Changed += ((object sender, ActiveFileChangedEventArgs e) => { changedEventWasRaised = true; }); ActiveFile activeFile; activeFile = new ActiveFile(OS.Current.FileInfo(_encrypted1AxxPath), OS.Current.FileInfo(_decrypted1TxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, null); state.Add(activeFile); activeFile = new ActiveFile(OS.Current.FileInfo(_encrypted2AxxPath), OS.Current.FileInfo(_decrypted2TxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, null); state.Add(activeFile); activeFile = new ActiveFile(OS.Current.FileInfo(_encrypted3AxxPath), OS.Current.FileInfo(_decrypted3TxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, null); state.Add(activeFile); Assert.That(changedEventWasRaised, Is.True, "The change event should have been raised by the adding of active files."); changedEventWasRaised = false; Assert.That(state.ActiveFiles.Count(), Is.EqualTo(3), "There should be three."); int i = 0; state.ForEach(ChangedEventMode.RaiseOnlyOnModified, (ActiveFile activeFileArgument) => { ++i; return activeFileArgument; }); Assert.That(i, Is.EqualTo(3), "The iteration should have visited three active files."); Assert.That(changedEventWasRaised, Is.False, "No change event should have been raised."); i = 0; state.ForEach(ChangedEventMode.RaiseAlways, (ActiveFile activeFileArgument) => { ++i; return activeFileArgument; }); Assert.That(i, Is.EqualTo(3), "The iteration should have visited three active files."); Assert.That(changedEventWasRaised, Is.True, "The change event should have been raised."); changedEventWasRaised = false; i = 0; state.ForEach(ChangedEventMode.RaiseAlways, (ActiveFile activeFileArgument) => { ++i; return new ActiveFile(activeFileArgument, activeFile.Status | ActiveFileStatus.Error); }); Assert.That(i, Is.EqualTo(3), "The iteration should have visited three active files."); Assert.That(changedEventWasRaised, Is.True, "The change event should have been raised."); } }