/// <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(); }
public static void TestAddCountAfterFinished() { ProgressContext progress = new ProgressContext(); progress.NotifyLevelStart(); progress.NotifyLevelFinished(); Assert.Throws<InvalidOperationException>(() => { progress.AddCount(1); }); }
private bool DecryptFileOperation() { _progress.NotifyLevelStart(); try { AxCryptFile.Decrypt(_eventArgs.AxCryptDocument, OS.Current.FileInfo(_eventArgs.SaveFileFullName), AxCryptOptions.SetFileTimes, _progress); } finally { _eventArgs.AxCryptDocument.Dispose(); _eventArgs.AxCryptDocument = null; } AxCryptFile.Wipe(OS.Current.FileInfo(_eventArgs.OpenFileFullName), _progress); _progress.NotifyLevelFinished(); _eventArgs.Status = FileOperationStatus.Success; return(true); }
public static void TestTooManyNotifyFinished() { ProgressContext progress = new ProgressContext(); Assert.Throws<InvalidOperationException>(() => { progress.NotifyLevelFinished(); }); }
public static void TestProgressWithSynchronizationContext() { SynchronizationContext synchronizationContext = new SynchronizationContext(); StateForSynchronizationContext s = new StateForSynchronizationContext(); s.WaitEvent = new ManualResetEvent(false); s.SynchronizationContext = synchronizationContext; synchronizationContext.Post( (object state) => { StateForSynchronizationContext ss = (StateForSynchronizationContext)state; SynchronizationContext.SetSynchronizationContext(ss.SynchronizationContext); ss.SynchronizationContext = SynchronizationContext.Current; ProgressContext progress = new ProgressContext(); progress.NotifyLevelStart(); progress.Progressing += (object sender, ProgressEventArgs e) => { ss.DidProgress = true; }; progress.NotifyLevelFinished(); ss.WaitEvent.Set(); }, s); bool waitOk = s.WaitEvent.WaitOne(TimeSpan.FromSeconds(10), false); Assert.That(waitOk, "The wait should not time-out"); Assert.That(s.SynchronizationContext, Is.EqualTo(synchronizationContext), "The SynchronizationContext should be current in the code executed."); Assert.That(s.DidProgress, "There should always be one Progressing event after NotifyFinished()."); }
public static void TestProgressWithoutSynchronizationContext() { bool didProgress = false; SynchronizationContext currentContext = new SynchronizationContext(); Thread thread = new Thread( (object state) => { currentContext = SynchronizationContext.Current; ProgressContext progress = new ProgressContext(); progress.NotifyLevelStart(); progress.Progressing += (object sender, ProgressEventArgs e) => { didProgress = true; }; progress.NotifyLevelFinished(); } ); thread.Start(); thread.Join(); Assert.That(didProgress, "There should always be one Progressing event after NotifyFinished()."); Assert.That(currentContext, Is.Null, "There should be no SynchronizationContext here."); }
public static void TestProgressTo100AndAboveShouldOnlyReturn99BeforeFinishedPercent() { FakeRuntimeEnvironment fakeEnvironment = (FakeRuntimeEnvironment)OS.Current; fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(1000); ProgressContext progress = new ProgressContext(TimeSpan.FromMilliseconds(1000)); progress.NotifyLevelStart(); int percent = 0; progress.Progressing += (object sender, ProgressEventArgs e) => { percent = e.Percent; }; progress.AddTotal(2); Assert.That(percent, Is.EqualTo(0), "No progress yet - should be zero."); progress.AddCount(1); Assert.That(percent, Is.EqualTo(50), "Halfway should be 50 percent."); fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(2000); progress.AddCount(1); Assert.That(percent, Is.EqualTo(99), "Even at 100 should report 99 percent."); fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(3000); progress.AddCount(1000); Assert.That(percent, Is.EqualTo(99), "Even at very much above 100 should report 99 percent."); progress.NotifyLevelFinished(); Assert.That(percent, Is.EqualTo(100), "Only when NotifyFinished() is called should 100 percent be reported."); }
public static void TestDoubleNotifyFinished() { ProgressContext progress = new ProgressContext(); progress.NotifyLevelStart(); progress.NotifyLevelStart(); progress.NotifyLevelFinished(); Assert.DoesNotThrow(() => { progress.NotifyLevelFinished(); }); }
public static void TestCurrentAndMax() { ProgressContext progress = new ProgressContext(); progress.NotifyLevelStart(); int percent = -1; progress.Progressing += (object sender, ProgressEventArgs e) => { percent = e.Percent; }; progress.AddTotal(99); progress.NotifyLevelFinished(); Assert.That(percent, Is.EqualTo(100), "After Finished(), Percent should always be 100."); }
public static void Wipe(IRuntimeFileInfo fileInfo, ProgressContext progress) { if (fileInfo == null) { throw new ArgumentNullException("fileInfo"); } if (!fileInfo.Exists) { return; } if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("Wiping '{0}'.".InvariantFormat(fileInfo.Name)); } bool cancelPending = false; progress.NotifyLevelStart(); using (Stream stream = fileInfo.OpenWrite()) { long length = stream.Length + OS.Current.StreamBufferSize - stream.Length % OS.Current.StreamBufferSize; progress.AddTotal(length); for (long position = 0; position < length; position += OS.Current.StreamBufferSize) { byte[] random = OS.Current.GetRandomBytes(OS.Current.StreamBufferSize); stream.Write(random, 0, random.Length); stream.Flush(); try { progress.AddCount(random.Length); } catch (OperationCanceledException) { cancelPending = true; progress.Cancel = false; progress.AddCount(random.Length); } } } string randomName; do { randomName = GenerateRandomFileName(fileInfo.FullName); } while (OS.Current.FileInfo(randomName).Exists); IRuntimeFileInfo moveToFileInfo = OS.Current.FileInfo(fileInfo.FullName); moveToFileInfo.MoveTo(randomName); moveToFileInfo.Delete(); progress.NotifyLevelFinished(); if (cancelPending) { progress.Cancel = true; throw new OperationCanceledException("Delayed cancel during wipe."); } }
private static long CopyToWithCount(Stream inputStream, Stream outputStream, Stream realInputStream, ProgressContext progress) { progress.NotifyLevelStart(); if (realInputStream.CanSeek) { progress.AddTotal(realInputStream.Length - realInputStream.Position); } long totalCount = 0; byte[] buffer = new byte[OS.Current.StreamBufferSize]; int offset = 0; int length = buffer.Length; while (true) { int count = inputStream.Read(buffer, offset, length); offset += count; length -= count; if (length > 0 && count > 0) { continue; } if (offset == 0) { break; } outputStream.Write(buffer, 0, offset); outputStream.Flush(); progress.AddCount(offset); totalCount += offset; offset = 0; length = buffer.Length; } progress.NotifyLevelFinished(); return totalCount; }
public static void CheckWatchedFolders(this FileSystemState fileSystemState, ProgressContext progress) { if (fileSystemState == null) { throw new ArgumentNullException("fileSystemState"); } AesKey encryptionKey = fileSystemState.KnownKeys.DefaultEncryptionKey; if (encryptionKey == null) { return; } IEnumerable<IRuntimeFileInfo> files = fileSystemState.DecryptedFilesInWatchedFolders(); progress.NotifyLevelStart(); try { progress.AddTotal(files.Count()); foreach (IRuntimeFileInfo fileInfo in files) { IRuntimeFileInfo destinationFileInfo = fileInfo.CreateEncryptedName(); AxCryptFile.EncryptFileWithBackupAndWipe(fileInfo, destinationFileInfo, encryptionKey, progress); progress.AddCount(1); } } finally { progress.NotifyLevelFinished(); } }
public static void RemoveRecentFiles(this FileSystemState fileSystemState, IEnumerable<string> encryptedPaths, ProgressContext progress) { progress.NotifyLevelStart(); progress.AddTotal(encryptedPaths.Count()); foreach (string encryptedPath in encryptedPaths) { ActiveFile activeFile = fileSystemState.FindEncryptedPath(encryptedPath); if (activeFile != null) { fileSystemState.Remove(activeFile); } progress.AddCount(1); } fileSystemState.Save(); progress.NotifyLevelFinished(); }
/// <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(); }
public static void TestWipeWithConfirmAll() { ProgressContext progress = new ProgressContext(); FileOperationsController controller = new FileOperationsController(_fileSystemState, progress); int confirmationCount = 0; controller.WipeQueryConfirmation += (object sender, FileOperationEventArgs e) => { if (confirmationCount++ > 0) { throw new InvalidOperationException("The event should not be raised a second time."); } e.ConfirmAll = true; }; progress.NotifyLevelStart(); FileOperationStatus status = controller.WipeFile(_helloWorldAxxPath); Assert.That(status, Is.EqualTo(FileOperationStatus.Success), "The wipe should indicate success."); IRuntimeFileInfo fileInfo = OS.Current.FileInfo(_helloWorldAxxPath); Assert.That(!fileInfo.Exists, "The file should not exist after wiping."); Assert.DoesNotThrow(() => { status = controller.WipeFile(_davidCopperfieldTxtPath); }); Assert.That(status, Is.EqualTo(FileOperationStatus.Success), "The wipe should indicate success."); progress.NotifyLevelFinished(); fileInfo = OS.Current.FileInfo(_davidCopperfieldTxtPath); Assert.That(!fileInfo.Exists, "The file should not exist after wiping."); }
public static void TestCancel() { ProgressContext progress = new ProgressContext(); progress.NotifyLevelStart(); progress.AddTotal(100); progress.AddCount(10); progress.Cancel = true; Assert.Throws<OperationCanceledException>(() => { progress.NotifyLevelStart(); }); Assert.Throws<OperationCanceledException>(() => { progress.NotifyLevelFinished(); }); Assert.Throws<OperationCanceledException>(() => { progress.AddTotal(50); }); Assert.Throws<OperationCanceledException>(() => { progress.AddCount(10); }); }
public static void EncryptFileWithBackupAndWipe(IRuntimeFileInfo sourceFileInfo, IRuntimeFileInfo destinationFileInfo, AesKey key, ProgressContext progress) { if (sourceFileInfo == null) { throw new ArgumentNullException("sourceFileInfo"); } if (destinationFileInfo == null) { throw new ArgumentNullException("destinationFileInfo"); } if (key == null) { throw new ArgumentNullException("key"); } if (progress == null) { throw new ArgumentNullException("progress"); } progress.NotifyLevelStart(); using (Stream activeFileStream = sourceFileInfo.OpenRead()) { WriteToFileWithBackup(destinationFileInfo, (Stream destination) => { Encrypt(sourceFileInfo, destination, key, AxCryptOptions.EncryptWithCompression, progress); }, progress); } Wipe(sourceFileInfo, progress); progress.NotifyLevelFinished(); }