/// <summary> /// Iterate over all active files in the state. /// </summary> /// <param name="mode">RaiseAlways to raise Changed event for each active file, RaiseOnlyOnModified to only raise for modified active files.</param> /// <param name="action">A delegate with an action to take for each active file, returning the same or updated active file as need be.</param> public void ForEach(ChangedEventMode mode, Func <ActiveFile, ActiveFile> action) { if (action == null) { throw new ArgumentNullException("action"); } bool isModified = false; List <ActiveFile> activeFiles = new List <ActiveFile>(); foreach (ActiveFile activeFile in ActiveFiles) { ActiveFile updatedActiveFile = action(activeFile); activeFiles.Add(updatedActiveFile); if (updatedActiveFile != activeFile) { isModified = true; OnChanged(new ActiveFileChangedEventArgs(updatedActiveFile)); activeFile.Dispose(); } } if (isModified) { lock (_lock) { SetRangeInternal(activeFiles, ActiveFileStatus.None); } Save(); } if (!isModified && mode == ChangedEventMode.RaiseAlways) { RaiseChangedForAll(activeFiles); } }
/// <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 virtual async Task <ActiveFile> CheckActiveFile(ActiveFile activeFile, IProgressContext progress) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } try { if (activeFile.Status.HasMask(ActiveFileStatus.Exception)) { return(activeFile); } if (New <FileLocker>().IsLocked(activeFile.DecryptedFileInfo, activeFile.EncryptedFileInfo)) { return(activeFile); } using (FileLock decryptedFileLock = New <FileLocker>().Acquire(activeFile.DecryptedFileInfo)) { using (FileLock encryptedFileLock = New <FileLocker>().Acquire(activeFile.EncryptedFileInfo)) { activeFile = await CheckActiveFileActions(activeFile, encryptedFileLock, decryptedFileLock, progress).Free(); return(activeFile); } } } catch (Exception ex) when(!(ex is AxCryptException)) { throw new FileOperationException("Unexpected exception checking active files.", $"{activeFile.EncryptedFileInfo.FullName} : {activeFile.DecryptedFileInfo.FullName}", ErrorStatus.Exception, ex); } }
public virtual async Task RemoveRecentFiles(IEnumerable <IDataStore> encryptedPaths, IProgressContext progress) { if (encryptedPaths == null) { throw new ArgumentNullException("encryptedPaths"); } if (progress == null) { throw new ArgumentNullException("progress"); } progress.NotifyLevelStart(); try { progress.AddTotal(encryptedPaths.Count()); foreach (IDataStore encryptedPath in encryptedPaths) { ActiveFile activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(encryptedPath.FullName); if (activeFile != null) { Resolve.FileSystemState.RemoveActiveFile(activeFile); } progress.AddCount(1); } await Resolve.FileSystemState.Save().Free(); } finally { progress.NotifyLevelFinished(); } }
private static async Task <ActiveFile> CheckIfTimeToDelete(ActiveFile activeFile, FileLock decryptedFileLock, IProgressContext progress) { switch (OS.Current.Platform) { case Platform.WindowsDesktop: case Platform.Linux: case Platform.MacOsx: break; default: return(activeFile); } if (!activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted)) { return(activeFile); } if (activeFile.Status.HasMask(ActiveFileStatus.NotShareable)) { return(activeFile); } if (activeFile.Status.HasMask(ActiveFileStatus.NoProcessKnown)) { return(activeFile); } if (Resolve.ProcessState.HasActiveProcess(activeFile)) { return(activeFile); } activeFile = await TryDelete(activeFile, decryptedFileLock, progress).Free(); return(activeFile); }
/// <summary> /// Add a file to the volatile file system state. To persist, call Save(). /// </summary> /// <param name="activeFile">The active file to save</param> public void Add(ActiveFile activeFile) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } AddInternal(activeFile); }
private void AddInternal(ActiveFile activeFile) { lock (_activeFilesByEncryptedPath) { _activeFilesByEncryptedPath[activeFile.EncryptedFileInfo.FullName] = activeFile; } New <ActiveFileWatcher>().Add(activeFile.EncryptedFileInfo); }
private void Initialize(ActiveFile other) { Initialize(other.EncryptedFileInfo, other.DecryptedFileInfo, other.LastEncryptionWriteTimeUtc, other.Key, other.Thumbprint, other.Status, other.Process); if (other.Process != null) { other.Process = null; } }
public ActiveFile(ActiveFile activeFile, ActiveFileStatus status) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile); Status = status; }
public ActiveFile(ActiveFile activeFile) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile); Properties = new ActiveFileProperties(activeFile.Properties.LastActivityTimeUtc, Properties.LastEncryptionWriteTimeUtc, activeFile.Properties.CryptoId); Identity = LogOnIdentity.Empty; }
public ActiveFile(ActiveFile activeFile, Guid cryptoId, LogOnIdentity identity) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile, identity); Properties = new ActiveFileProperties(activeFile.Properties.LastActivityTimeUtc, activeFile.Properties.LastEncryptionWriteTimeUtc, cryptoId); }
public ActiveFile(ActiveFile activeFile, ActiveFileStatus status, ILauncher process) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile); Status = status; Process = process; }
public ActiveFile(ActiveFile activeFile, DateTime lastEncryptionWriteTimeUtc, ActiveFileStatus status) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile); Properties = new ActiveFileProperties(activeFile.Properties.LastActivityTimeUtc, lastEncryptionWriteTimeUtc, activeFile.Properties.CryptoId); Status = status; }
public ActiveFile(ActiveFile activeFile, ActiveFileStatus status, ILauncher process) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile); Status = status; Process = process; }
public ActiveFile(ActiveFile activeFile, DateTime lastEncryptionWriteTimeUtc, ActiveFileStatus status) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile); LastEncryptionWriteTimeUtc = lastEncryptionWriteTimeUtc; Status = status; }
private async Task RemoveDeletedActiveFile(IDataItem dataItem) { ActiveFile removedActiveFile = FindActiveFileFromEncryptedPath(dataItem.FullName); if (removedActiveFile != null) { RemoveActiveFile(removedActiveFile); await Save(); } }
public virtual async Task ClearExceptionState() { await Resolve.FileSystemState.ForEach(async (ActiveFile activeFile) => { if (activeFile.Status.HasFlag(ActiveFileStatus.Exception)) { activeFile = new ActiveFile(activeFile, activeFile.Status & ~ActiveFileStatus.Exception); } return(activeFile); }).Free(); }
private static async Task <ActiveFile> CheckActiveFileActions(ActiveFile activeFile, FileLock encryptedFileLock, FileLock decryptedFileLock, IProgressContext progress) { activeFile = CheckIfKeyIsKnown(activeFile); activeFile = CheckIfCreated(activeFile); activeFile = CheckIfProcessExited(activeFile); activeFile = await CheckIfTimeToUpdate(activeFile, encryptedFileLock, decryptedFileLock, progress).Free(); activeFile = await CheckIfTimeToDelete(activeFile, decryptedFileLock, progress).Free(); return(activeFile); }
private static LogOnIdentity FindKnownKeyOrEmpty(ActiveFile activeFile) { foreach (LogOnIdentity key in Resolve.KnownIdentities.Identities) { if (activeFile.ThumbprintMatch(key.Passphrase)) { return(key); } } return(LogOnIdentity.Empty); }
private List <ILauncher> ActiveProcesses(ActiveFile activeFile) { lock (_lock) { List <ILauncher> processes; if (!_processState.TryGetValue(activeFile.EncryptedFileInfo.FullName, out processes)) { return(null); } return(processes); } }
/// <summary> /// Add a file to the volatile file system state. To persist, call Save(). /// </summary> /// <param name="activeFile">The active file to save</param> public void Add(ActiveFile activeFile) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } lock (_lock) { AddInternal(activeFile); } OnChanged(new ActiveFileChangedEventArgs(activeFile)); }
private static ActiveFile CheckIfProcessExited(ActiveFile activeFile) { if (activeFile.Process == null || !activeFile.Process.HasExited) { return(activeFile); } if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("Process exit for '{0}'".InvariantFormat(activeFile.DecryptedFileInfo.FullName)); } activeFile = new ActiveFile(activeFile, activeFile.Status & ~ActiveFileStatus.NotShareable, null); return(activeFile); }
public override int Compare(ActiveFile x, ActiveFile y) { if (x == null) { throw new ArgumentNullException("x"); } if (y == null) { throw new ArgumentNullException("y"); } return((ReverseSort ? -1 : 1) * String.Compare(x.EncryptedFileInfo.FullName, y.EncryptedFileInfo.FullName, StringComparison.OrdinalIgnoreCase)); }
public override int Compare(ActiveFile x, ActiveFile y) { if (x == null) { throw new ArgumentNullException("x"); } if (y == null) { throw new ArgumentNullException("y"); } return((ReverseSort ? -1 : 1) * String.Compare(Resolve.CryptoFactory.Create(x.Properties.CryptoId).Name, Resolve.CryptoFactory.Create(y.Properties.CryptoId).Name, StringComparison.OrdinalIgnoreCase)); }
public override int Compare(ActiveFile x, ActiveFile y) { if (x == null) { throw new ArgumentNullException("x"); } if (y == null) { throw new ArgumentNullException("y"); } return((ReverseSort ? -1 : 1) * String.Compare(Resolve.Portable.Path().GetFileName(x.DecryptedFileInfo.FullName), Resolve.Portable.Path().GetFileName(y.DecryptedFileInfo.FullName), StringComparison.OrdinalIgnoreCase)); }
public override int Compare(ActiveFile x, ActiveFile y) { if (x == null) { throw new ArgumentNullException("x"); } if (y == null) { throw new ArgumentNullException("y"); } return((ReverseSort ? -1 : 1) * x.Properties.LastActivityTimeUtc.CompareTo(y.Properties.LastActivityTimeUtc)); }
private static async Task <ActiveFile> CheckIfTimeToUpdate(ActiveFile activeFile, FileLock encryptedFileLock, FileLock decryptedFileLock, IProgressContext progress) { if (!activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted) || activeFile.Status.HasMask(ActiveFileStatus.NotShareable)) { return(activeFile); } if (New <KnownIdentities>().DefaultEncryptionIdentity == LogOnIdentity.Empty && activeFile.Identity == LogOnIdentity.Empty) { return(activeFile); } return(await activeFile.CheckUpdateDecrypted(encryptedFileLock, decryptedFileLock, progress).Free()); }
private static ActiveFile CheckIfTimeToDelete(ActiveFile activeFile, ProgressContext progress) { if (OS.Current.Platform != Platform.WindowsDesktop) { return(activeFile); } if (!activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted) || activeFile.Status.HasMask(ActiveFileStatus.NotShareable)) { return(activeFile); } activeFile = TryDelete(activeFile, progress); return(activeFile); }
/// <summary> /// Remove a file from the volatile file system state. To persist, call Save(). /// </summary> /// <param name="activeFile">An active file to remove</param> public void Remove(ActiveFile activeFile) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } lock (_lock) { _activeFilesByDecryptedPath.Remove(activeFile.DecryptedFileInfo.FullName); _activeFilesByEncryptedPath.Remove(activeFile.EncryptedFileInfo.FullName); } activeFile = new ActiveFile(activeFile, activeFile.Status | ActiveFileStatus.NoLongerActive); OnChanged(new ActiveFileChangedEventArgs(activeFile)); }
private void SetRangeInternal(IEnumerable <ActiveFile> activeFiles, ActiveFileStatus mask) { _activeFilesByDecryptedPath = new Dictionary <string, ActiveFile>(); _activeFilesByEncryptedPath = new Dictionary <string, ActiveFile>(); foreach (ActiveFile activeFile in activeFiles) { ActiveFile thisActiveFile = activeFile; if ((activeFile.Status & mask) != 0) { thisActiveFile = new ActiveFile(activeFile, activeFile.Status & ~mask, null); } AddInternal(thisActiveFile); } }
public ActiveFile(ActiveFile activeFile, AesKey key) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } if (key == null) { throw new ArgumentNullException("key"); } Initialize(activeFile); LastActivityTimeUtc = activeFile.LastActivityTimeUtc; Key = key; }
public ActiveFile(ActiveFile activeFile, AesKey key) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } if (key == null) { throw new ArgumentNullException("key"); } Initialize(activeFile); LastActivityTimeUtc = activeFile.LastActivityTimeUtc; Key = key; }
public static void TestActiveFileCollectionEnumerationConstructor() { IRuntimeFileInfo decryptedFileInfo1 = OS.Current.FileInfo(Path.Combine(_rootPath, "test1.txt")); IRuntimeFileInfo encryptedFileInfo1 = OS.Current.FileInfo(Path.Combine(_rootPath, "test1-txt.axx")); IRuntimeFileInfo decryptedFileInfo2 = OS.Current.FileInfo(Path.Combine(_rootPath, "test2.txt")); IRuntimeFileInfo encryptedFileInfo2 = OS.Current.FileInfo(Path.Combine(_rootPath, "test2-text.axx")); ActiveFile activeFile1 = new ActiveFile(encryptedFileInfo1, decryptedFileInfo1, new AesKey(), ActiveFileStatus.None, null); ActiveFile activeFile2 = new ActiveFile(encryptedFileInfo2, decryptedFileInfo2, new AesKey(), ActiveFileStatus.None, null); ActiveFileCollection collection = new ActiveFileCollection(new ActiveFile[] { activeFile1, activeFile2 }); Assert.That(collection.Count, Is.EqualTo(2), "There should be two entries in the collection."); Assert.That(collection.First(), Is.EqualTo(activeFile1), "This should be the first in the collection."); Assert.That(collection.Last(), Is.EqualTo(activeFile2), "This should be the last in the collection."); }
public static void TestConstructor() { AesKey key = new AesKey(); ILauncher process = new FakeLauncher(String.Empty); IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_testTextPath); IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_helloWorldAxxPath); using (ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, process)) { decryptedFileInfo = activeFile.DecryptedFileInfo; Assert.That(decryptedFileInfo.Exists, Is.True, "The file should exist in the fake file system."); Assert.That(decryptedFileInfo.FullName, Is.EqualTo(_testTextPath), "The file should be named as it was in the constructor"); Assert.That(decryptedFileInfo.LastWriteTimeUtc, Is.EqualTo(decryptedFileInfo.LastWriteTimeUtc), "When a LastWriteTime is not specified, the decrypted file should be used to determine the value."); Assert.That(activeFile.Process, Is.EqualTo(process), "The process should be set from the constructor."); SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return DateTime.UtcNow.AddMinutes(1); }); using (ActiveFile otherFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted)) { Assert.That(otherFile.Status, Is.EqualTo(ActiveFileStatus.AssumedOpenAndDecrypted), "The status should be as given in the constructor."); Assert.That(otherFile.DecryptedFileInfo.FullName, Is.EqualTo(activeFile.DecryptedFileInfo.FullName), "This should be copied from the original instance."); Assert.That(otherFile.EncryptedFileInfo.FullName, Is.EqualTo(activeFile.EncryptedFileInfo.FullName), "This should be copied from the original instance."); Assert.That(otherFile.Key, Is.EqualTo(activeFile.Key), "This should be copied from the original instance."); Assert.That(otherFile.LastActivityTimeUtc, Is.GreaterThan(activeFile.LastActivityTimeUtc), "This should not be copied from the original instance, but should be a later time."); Assert.That(otherFile.Process, Is.EqualTo(process), "This should be copied from the original instance."); Assert.That(activeFile.Process, Is.Null, "The process should only be owned by one instance at a time."); Assert.That(otherFile.ThumbprintMatch(activeFile.Key), Is.True, "The thumbprints should match."); } using (ActiveFile otherFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted, process)) { Assert.That(otherFile.Process, Is.EqualTo(process), "This should be copied from the instance provided in the constructor."); } activeFile.DecryptedFileInfo.LastWriteTimeUtc = activeFile.DecryptedFileInfo.LastWriteTimeUtc.AddDays(1); using (ActiveFile otherFile = new ActiveFile(activeFile, OS.Current.UtcNow, ActiveFileStatus.AssumedOpenAndDecrypted)) { Assert.That(activeFile.IsModified, Is.True, "The original instance has not been encrypted since the last change."); Assert.That(otherFile.IsModified, Is.False, "The copy indicates that it has been encrypted and thus is not modified."); } } }
/// <summary> /// Remove a file from the volatile file system state. To persist, call Save(). /// </summary> /// <param name="activeFile">An active file to remove</param> public void Remove(ActiveFile activeFile) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } lock (_lock) { _activeFilesByDecryptedPath.Remove(activeFile.DecryptedFileInfo.FullName); _activeFilesByEncryptedPath.Remove(activeFile.EncryptedFileInfo.FullName); } activeFile = new ActiveFile(activeFile, activeFile.Status | ActiveFileStatus.NoLongerActive); OnChanged(new ActiveFileChangedEventArgs(activeFile)); }
public static void TestChangedEvent() { using (FileSystemState state = new FileSystemState()) { state.Load(OS.Current.FileInfo(_mystateXmlPath)); bool wasHere; state.Changed += new EventHandler<ActiveFileChangedEventArgs>((object sender, ActiveFileChangedEventArgs e) => { wasHere = true; }); ActiveFile activeFile = new ActiveFile(OS.Current.FileInfo(_encryptedAxxPath), OS.Current.FileInfo(_decryptedTxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null); wasHere = false; state.Add(activeFile); Assert.That(state.ActiveFiles.Count(), Is.EqualTo(1), "After the Add() the state should have one active file."); Assert.That(wasHere, Is.True, "After the Add(), the changed event should have been raised."); wasHere = false; state.Remove(activeFile); Assert.That(wasHere, Is.True, "After the Remove(), the changed event should have been raised."); Assert.That(state.ActiveFiles.Count(), Is.EqualTo(0), "After the Remove() the state should have no active files."); } }
private void AddInternal(ActiveFile activeFile) { _activeFilesByEncryptedPath[activeFile.EncryptedFileInfo.FullName] = activeFile; _activeFilesByDecryptedPath[activeFile.DecryptedFileInfo.FullName] = activeFile; }
public static void TestLoadExisting() { ActiveFile activeFile; using (FileSystemState state = new FileSystemState()) { state.Load(OS.Current.FileInfo(_mystateXmlPath)); Assert.That(state, Is.Not.Null, "An instance should always be instantiated."); Assert.That(state.ActiveFiles.Count(), Is.EqualTo(0), "A new state should not have any active files."); activeFile = new ActiveFile(OS.Current.FileInfo(_encryptedAxxPath), OS.Current.FileInfo(_decryptedTxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null); state.Add(activeFile); state.Save(); } using (FileSystemState reloadedState = new FileSystemState()) { reloadedState.Load(OS.Current.FileInfo(_mystateXmlPath)); Assert.That(reloadedState, Is.Not.Null, "An instance should always be instantiated."); Assert.That(reloadedState.ActiveFiles.Count(), Is.EqualTo(1), "The reloaded state should have one active file."); Assert.That(reloadedState.ActiveFiles.First().ThumbprintMatch(activeFile.Key), Is.True, "The reloaded thumbprint should match the key."); } }
public static void TestStatusMaskAtLoad() { using (FileSystemState state = new FileSystemState()) { state.Load(OS.Current.FileInfo(_mystateXmlPath)); ActiveFile activeFile = new ActiveFile(OS.Current.FileInfo(_encryptedAxxPath), OS.Current.FileInfo(_decryptedTxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, null); state.Add(activeFile); state.Save(); FileSystemState reloadedState = new FileSystemState(); reloadedState.Load(OS.Current.FileInfo(_mystateXmlPath)); Assert.That(reloadedState, Is.Not.Null, "An instance should always be instantiated."); Assert.That(reloadedState.ActiveFiles.Count(), Is.EqualTo(1), "The reloaded state should have one active file."); Assert.That(reloadedState.ActiveFiles.First().Status, Is.EqualTo(ActiveFileStatus.AssumedOpenAndDecrypted), "When reloading saved state, some statuses should be masked away."); } }
public ActiveFile(ActiveFile activeFile, ActiveFileStatus status) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile); Status = status; }
public static void TestThumbprintNullKey() { IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_testTextPath); IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_helloWorldAxxPath); ILauncher process = new FakeLauncher(String.Empty); AesKey key = new AesKey(); using (MemoryStream stream = new MemoryStream()) { using (ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, process)) { Assert.Throws<ArgumentNullException>(() => { AesKey nullKey = null; activeFile.ThumbprintMatch(nullKey); }); } } }
public static void TestDecryptedActiveFiles() { using (FileSystemState state = new FileSystemState()) { state.Load(OS.Current.FileInfo(_mystateXmlPath)); ActiveFile decryptedFile1 = new ActiveFile(OS.Current.FileInfo(_encryptedAxxPath), OS.Current.FileInfo(_decryptedTxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null); state.Add(decryptedFile1); ActiveFile decryptedFile2 = new ActiveFile(OS.Current.FileInfo(_encrypted2AxxPath), OS.Current.FileInfo(_decrypted2TxtPath), new AesKey(), ActiveFileStatus.DecryptedIsPendingDelete, null); state.Add(decryptedFile2); ActiveFile notDecryptedFile = new ActiveFile(OS.Current.FileInfo(_encrypted3AxxPath), OS.Current.FileInfo(_decrypted3TxtPath), new AesKey(), ActiveFileStatus.NotDecrypted, null); state.Add(notDecryptedFile); ActiveFile errorFile = new ActiveFile(OS.Current.FileInfo(_encrypted4AxxPath), OS.Current.FileInfo(_decrypted4TxtPath), new AesKey(), ActiveFileStatus.Error, null); state.Add(errorFile); IList<ActiveFile> decryptedFiles = state.DecryptedActiveFiles; Assert.That(decryptedFiles.Count, Is.EqualTo(2), "There should be two decrypted files."); Assert.That(decryptedFiles.Contains(decryptedFile1), "A file marked as AssumedOpenAndDecrypted should be found."); Assert.That(decryptedFiles.Contains(decryptedFile2), "A file marked as DecryptedIsPendingDelete should be found."); Assert.That(decryptedFiles.Contains(notDecryptedFile), Is.Not.True, "A file marked as NotDecrypted should not be found."); } }
public static void TestFindEncryptedAndDecryptedPath() { using (FileSystemState state = new FileSystemState()) { state.Load(OS.Current.FileInfo(_mystateXmlPath)); ActiveFile activeFile = new ActiveFile(OS.Current.FileInfo(_encryptedAxxPath), OS.Current.FileInfo(_decryptedTxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, null); state.Add(activeFile); ActiveFile byDecryptedPath = state.FindDecryptedPath(_decryptedTxtPath); Assert.That(byDecryptedPath, Is.EqualTo(activeFile), "The search should return the same instance."); ActiveFile byEncryptedPath = state.FindEncryptedPath(_encryptedAxxPath); Assert.That(byEncryptedPath, Is.EqualTo(byDecryptedPath), "The search should return the same instance."); ActiveFile notFoundEncrypted = state.FindEncryptedPath(Path.Combine(_rootPath, "notfoundfile.txt")); Assert.That(notFoundEncrypted, Is.Null, "A search that does not succeed should return null."); ActiveFile notFoundDecrypted = state.FindDecryptedPath(Path.Combine(_rootPath, "notfoundfile.txt")); Assert.That(notFoundDecrypted, Is.Null, "A search that does not succeed should return null."); } }
private static ActiveFile CheckKeysForAlreadyDecryptedFile(ActiveFile destinationActiveFile, IEnumerable<AesKey> keys, ProgressContext progress) { foreach (AesKey key in keys) { using (AxCryptDocument document = AxCryptFile.Document(destinationActiveFile.EncryptedFileInfo, key, progress)) { if (document.PassphraseIsValid) { if (OS.Log.IsWarningEnabled) { OS.Log.LogWarning("File was already decrypted and the key was known for '{0}' to '{1}'".InvariantFormat(destinationActiveFile.EncryptedFileInfo.FullName, destinationActiveFile.DecryptedFileInfo.FullName)); } return new ActiveFile(destinationActiveFile, key); } } } return null; }
private void Initialize(ActiveFile other) { Initialize(other.EncryptedFileInfo, other.DecryptedFileInfo, other.LastEncryptionWriteTimeUtc, other.Key, other.Thumbprint, other.Status, other.Process); if (other.Process != null) { other.Process = null; } }
private void SetRangeInternal(IEnumerable<ActiveFile> activeFiles, ActiveFileStatus mask) { _activeFilesByDecryptedPath = new Dictionary<string, ActiveFile>(); _activeFilesByEncryptedPath = new Dictionary<string, ActiveFile>(); foreach (ActiveFile activeFile in activeFiles) { ActiveFile thisActiveFile = activeFile; if ((activeFile.Status & mask) != 0) { thisActiveFile = new ActiveFile(activeFile, activeFile.Status & ~mask, null); } AddInternal(thisActiveFile); } }
public static void TestCopyConstructorWithKey() { ILauncher process = new FakeLauncher(String.Empty); AesKey key = new AesKey(); IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_testTextPath); IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_helloWorldAxxPath); using (ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, process)) { AesKey newKey = new AesKey(); using (ActiveFile newActiveFile = new ActiveFile(activeFile, newKey)) { Assert.That(activeFile.Key, Is.Not.EqualTo(newKey), "Ensure that it's really a different key."); Assert.That(newActiveFile.Key, Is.EqualTo(newKey), "The constructor should assign the new key to the new ActiveFile instance."); } } }
private static ActiveFile DecryptActiveFileDocument(IRuntimeFileInfo sourceFileInfo, IRuntimeFileInfo destinationFolderInfo, AxCryptDocument document, ProgressContext progress) { string destinationName = document.DocumentHeaders.FileName; string destinationPath = Path.Combine(destinationFolderInfo.FullName, destinationName); IRuntimeFileInfo destinationFileInfo = OS.Current.FileInfo(destinationPath); using (FileLock fileLock = FileLock.Lock(destinationFileInfo)) { AxCryptFile.Decrypt(document, destinationFileInfo, AxCryptOptions.SetFileTimes, progress); } ActiveFile destinationActiveFile = new ActiveFile(sourceFileInfo, destinationFileInfo, document.DocumentHeaders.KeyEncryptingKey, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.IgnoreChange, null); if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("File decrypted from '{0}' to '{1}'".InvariantFormat(sourceFileInfo.FullName, destinationActiveFile.DecryptedFileInfo.FullName)); } return destinationActiveFile; }
public static void TestMethodIsModified() { IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(Path.Combine(_rootPath, "doesnotexist.txt")); IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_helloWorldAxxPath); using (ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new AesKey(), ActiveFileStatus.None, null)) { Assert.That(activeFile.IsModified, Is.False, "A non-existing decrypted file should not be treated as modified."); } }
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."); } }
public ActiveFile(ActiveFile activeFile, DateTime lastEncryptionWriteTimeUtc, ActiveFileStatus status) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } Initialize(activeFile); LastEncryptionWriteTimeUtc = lastEncryptionWriteTimeUtc; Status = status; }
public static void TestInvalidXml() { string badXml = @"<FileSystemState xmlns=""http://www.axantum.com/Serialization/"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">"; IRuntimeFileInfo stateInfo = OS.Current.FileInfo(_mystateXmlPath); using (Stream stream = stateInfo.OpenWrite()) { byte[] bytes = Encoding.UTF8.GetBytes(badXml); stream.Write(bytes, 0, bytes.Length); } using (FileSystemState state = new FileSystemState()) { Assert.DoesNotThrow(() => state.Load(stateInfo)); Assert.That(state.ActiveFileCount, Is.EqualTo(0), "After loading damaged state, the count should be zero."); ActiveFile decryptedFile1 = new ActiveFile(OS.Current.FileInfo(_encryptedAxxPath), OS.Current.FileInfo(_decryptedTxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null); state.Add(decryptedFile1); Assert.That(state.ActiveFileCount, Is.EqualTo(1), "After adding a file, the count should be one."); } }
/// <summary> /// Add a file to the volatile file system state. To persist, call Save(). /// </summary> /// <param name="activeFile">The active file to save</param> public void Add(ActiveFile activeFile) { if (activeFile == null) { throw new ArgumentNullException("activeFile"); } lock (_lock) { AddInternal(activeFile); } OnChanged(new ActiveFileChangedEventArgs(activeFile)); }
private static IRuntimeFileInfo GetTemporaryDestinationFolder(ActiveFile destinationActiveFile) { string destinationFolder; if (destinationActiveFile != null) { destinationFolder = Path.GetDirectoryName(destinationActiveFile.DecryptedFileInfo.FullName); } else { destinationFolder = Path.Combine(OS.Current.WorkFolder.FullName, Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + Path.DirectorySeparatorChar); } IRuntimeFileInfo destinationFolderInfo = OS.Current.FileInfo(destinationFolder); destinationFolderInfo.CreateFolder(); return destinationFolderInfo; }
public ActiveFileChangedEventArgs(ActiveFile activeFile) { ActiveFile = activeFile; }
public static void TestActiveFileCollectionSimpleConstructor() { ActiveFileCollection collection = new ActiveFileCollection(); IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_testTextPath); IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_helloWorldAxxPath); ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new AesKey(), ActiveFileStatus.None, null); collection.Add(activeFile); Assert.That(collection.Count, Is.EqualTo(1), "There should be one entry in the collection."); foreach (ActiveFile member in collection) { Assert.That(member, Is.EqualTo(activeFile), "The one we added should now be in the collection."); } }
private static FileOperationStatus LaunchApplicationForDocument(FileSystemState fileSystemState, ActiveFile destinationActiveFile) { ILauncher process; try { if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("Starting process for '{0}'".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName)); } process = OS.Current.Launch(destinationActiveFile.DecryptedFileInfo.FullName); if (process.WasStarted) { process.Exited += new EventHandler(process_Exited); } else { if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("Starting process for '{0}' did not start a process, assumed handled by the shell.".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName)); } } } catch (Win32Exception w32ex) { if (OS.Log.IsErrorEnabled) { OS.Log.LogError("Could not launch application for '{0}', Win32Exception was '{1}'.".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName, w32ex.Message)); } return FileOperationStatus.CannotStartApplication; } if (OS.Log.IsWarningEnabled) { if (process.HasExited) { OS.Log.LogWarning("The process seems to exit immediately for '{0}'".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName)); } } if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("Launched and opened '{0}'.".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName)); } destinationActiveFile = new ActiveFile(destinationActiveFile, ActiveFileStatus.AssumedOpenAndDecrypted, process); fileSystemState.Add(destinationActiveFile); fileSystemState.Save(); return FileOperationStatus.Success; }
public static void TestInvalidArguments() { IRuntimeFileInfo nullFileInfo = null; ILauncher nullProcess = null; IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_testTextPath); IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_helloWorldAxxPath); AesKey key = new AesKey(); AesKey nullKey = null; ILauncher process = new FakeLauncher(String.Empty); ActiveFile nullActiveFile = null; ActiveFile originalActiveFile = new ActiveFile(decryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, process); Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullActiveFile, key) == null) { } }); Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(originalActiveFile, nullKey) == null) { } }); Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullActiveFile, ActiveFileStatus.None, nullProcess) == null) { } }); Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullActiveFile, ActiveFileStatus.None) == null) { } }); Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullActiveFile, DateTime.MinValue, ActiveFileStatus.None) == null) { } }); Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullFileInfo, decryptedFileInfo, new AesKey(), ActiveFileStatus.None, nullProcess) == null) { } }); Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(encryptedFileInfo, nullFileInfo, new AesKey(), ActiveFileStatus.None, nullProcess) == null) { } }); Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(encryptedFileInfo, decryptedFileInfo, nullKey, ActiveFileStatus.None, nullProcess) == null) { } }); }
public static FileOperationStatus OpenAndLaunchApplication(this FileSystemState fileSystemState, string file, AxCryptDocument document, ProgressContext progress) { if (fileSystemState == null) { throw new ArgumentNullException("fileSystemState"); } if (file == null) { throw new ArgumentNullException("file"); } if (document == null) { throw new ArgumentNullException("document"); } if (progress == null) { throw new ArgumentNullException("progress"); } IRuntimeFileInfo fileInfo = OS.Current.FileInfo(file); ActiveFile destinationActiveFile = fileSystemState.FindEncryptedPath(fileInfo.FullName); if (destinationActiveFile == null || !destinationActiveFile.DecryptedFileInfo.Exists) { IRuntimeFileInfo destinationFolderInfo = GetTemporaryDestinationFolder(destinationActiveFile); destinationActiveFile = DecryptActiveFileDocument(fileInfo, destinationFolderInfo, document, progress); } else { destinationActiveFile = new ActiveFile(destinationActiveFile, document.DocumentHeaders.KeyEncryptingKey); } fileSystemState.Add(destinationActiveFile); fileSystemState.Save(); FileOperationStatus status = LaunchApplicationForDocument(fileSystemState, destinationActiveFile); return status; }
public static void TestThumbprint() { IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_testTextPath); IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_helloWorldAxxPath); ILauncher process = new FakeLauncher(String.Empty); AesKey key = new AesKey(); using (MemoryStream stream = new MemoryStream()) { DataContractSerializer serializer = new DataContractSerializer(typeof(ActiveFile)); using (ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, process)) { serializer.WriteObject(stream, activeFile); } stream.Position = 0; ActiveFile deserializedActiveFile = (ActiveFile)serializer.ReadObject(stream); Assert.That(deserializedActiveFile.ThumbprintMatch(key), Is.True, "The deserialized object should match the thumbprint with the key."); } }