/// <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 virtual async Task CheckActiveFiles(IProgressContext progress) { if (progress == null) { throw new ArgumentNullException("progress"); } progress.NotifyLevelStart(); try { progress.AddTotal(Resolve.FileSystemState.ActiveFileCount); await Resolve.FileSystemState.ForEach(async (ActiveFile activeFile) => { try { activeFile = await CheckActiveFile(activeFile, progress).Free(); if (activeFile.Status == ActiveFileStatus.NotDecrypted && !activeFile.EncryptedFileInfo.IsAvailable) { activeFile = null; } return(activeFile); } finally { progress.AddCount(1); } }).Free(); } finally { progress.NotifyLevelFinished(); } }
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(); } }
public virtual async Task EncryptFoldersUniqueWithBackupAndWipeAsync(IEnumerable <IDataContainer> containers, EncryptionParameters encryptionParameters, IProgressContext progress) { if (containers == null) { throw new ArgumentNullException("containers"); } if (progress == null) { throw new ArgumentNullException("progress"); } progress.NotifyLevelStart(); try { List <IDataStore> files = new List <IDataStore>(); foreach (IDataContainer container in containers) { files.AddRange(await container.ListEncryptableWithWarningAsync(containers, New <UserSettings>().FolderOperationMode.Policy())); } progress.AddTotal(files.Count()); foreach (IDataStore file in files) { await EncryptFileUniqueWithBackupAndWipeAsync(file, encryptionParameters, progress); progress.AddCount(1); progress.Totals.AddFileCount(1); } } finally { progress.NotifyLevelFinished(); } }
/// <summary /// Instantiates a worker group with specified maximum concurrency and external progress reporting. Progress /// will be reported on the thread instantiating the ProgressContext used. /// </summary> /// <param name="maxConcurrent">The maximum number of worker threads active at any one time</param> /// <param name="progress">The ProgressContext that receives progress notifications</param> public WorkerGroup(int maxConcurrent, IProgressContext progress) { if (progress == null) { throw new ArgumentNullException("progress"); } _concurrencyControlSemaphore = Resolve.Portable.Semaphore(maxConcurrent, maxConcurrent); _maxConcurrencyCount = maxConcurrent; _singleThread = Resolve.Portable.SingleThread(); FirstError = new FileOperationContext(String.Empty, ErrorStatus.Success); progress.NotifyLevelStart(); Progress = new WorkerGroupProgressContext(progress, _singleThread); }
public virtual async Task EncryptFileWithBackupAndWipeAsync(IDataStore sourceStore, FileLock destinationStore, EncryptionParameters encryptionParameters, IProgressContext progress) { if (sourceStore == null) { throw new ArgumentNullException("sourceStore"); } if (destinationStore == null) { throw new ArgumentNullException("destinationStore"); } if (encryptionParameters == null) { throw new ArgumentNullException("encryptionParameters"); } if (progress == null) { throw new ArgumentNullException("progress"); } progress.NotifyLevelStart(); try { using (FileLock sourceFileLock = New <FileLocker>().Acquire(sourceStore)) { using (Stream activeFileStream = sourceStore.OpenRead()) { await EncryptToFileWithBackupAsync(destinationStore, (Stream destination) => { Encrypt(sourceStore, destination, encryptionParameters, AxCryptOptions.EncryptWithCompression, progress); return(Constant.CompletedTask); }, progress); if (sourceStore.IsWriteProtected) { destinationStore.DataStore.IsWriteProtected = true; } } if (sourceStore.IsWriteProtected) { sourceStore.IsWriteProtected = false; } Wipe(sourceFileLock, progress); } } finally { 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 virtual async Task PurgeActiveFiles(IProgressContext progress) { if (progress == null) { throw new ArgumentNullException("progress"); } progress.NotifyLevelStart(); try { await Resolve.FileSystemState.ForEach(async (ActiveFile activeFile) => { if (activeFile.Status.HasMask(ActiveFileStatus.Exception)) { return(activeFile); } if (New <FileLocker>().IsLocked(activeFile.DecryptedFileInfo)) { if (Resolve.Log.IsInfoEnabled) { Resolve.Log.LogInfo("Not deleting '{0}' because it is marked as locked.".InvariantFormat(activeFile.DecryptedFileInfo.FullName)); } return(activeFile); } if (activeFile.Status.HasMask(ActiveFileStatus.NotShareable)) { activeFile = new ActiveFile(activeFile, activeFile.Status & ~ActiveFileStatus.NotShareable); } using (FileLock encryptedFileLock = New <FileLocker>().Acquire(activeFile.EncryptedFileInfo)) { using (FileLock decryptedFileLock = New <FileLocker>().Acquire(activeFile.DecryptedFileInfo)) { activeFile = await CheckIfTimeToUpdate(activeFile, encryptedFileLock, decryptedFileLock, progress).Free(); if (activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted)) { activeFile = await TryDelete(activeFile, decryptedFileLock, progress).Free(); } } } return(activeFile); }).Free(); } finally { progress.NotifyLevelFinished(); } }
public Task <FileOperationContext> DecryptFileUniqueWithWipeOfOriginalAsync(IDataStore sourceStore, LogOnIdentity logOnIdentity, IProgressContext progress) { if (sourceStore == null) { throw new ArgumentNullException("sourceStore"); } if (progress == null) { throw new ArgumentNullException("progress"); } if (sourceStore.IsWriteProtected) { return(Task.FromResult(new FileOperationContext(sourceStore.FullName, Abstractions.ErrorStatus.CannotWriteDestination))); } progress.NotifyLevelStart(); try { using (IAxCryptDocument document = New <AxCryptFile>().Document(sourceStore, logOnIdentity, progress)) { if (!document.PassphraseIsValid) { return(Task.FromResult(new FileOperationContext(sourceStore.FullName, Abstractions.ErrorStatus.Canceled))); } IDataStore destinationStore = New <IDataStore>(Resolve.Portable.Path().Combine(Resolve.Portable.Path().GetDirectoryName(sourceStore.FullName), document.FileName)); using (FileLock lockedDestination = destinationStore.FullName.CreateUniqueFile()) { DecryptFile(document, lockedDestination.DataStore.FullName, progress); } } using (FileLock sourceFileLock = New <FileLocker>().Acquire(sourceStore)) { Wipe(sourceFileLock, progress); } } finally { progress.NotifyLevelFinished(); } return(Task.FromResult(new FileOperationContext(sourceStore.FullName, Abstractions.ErrorStatus.Success))); }
/// <summary> /// Initializes a new instance of the <see cref="ProgressStream"/> class. /// </summary> /// <param name="stream">The stream. Will be disposed of when this instance is disposed.</param> /// <param name="progress">The progress.</param> /// <exception cref="System.ArgumentNullException"> /// stream /// or /// progress /// </exception> public ProgressStream(Stream stream, IProgressContext progress) { if (stream == null) { throw new ArgumentNullException("stream"); } if (progress == null) { throw new ArgumentNullException("progress"); } WrappedStream = stream; _progress = progress; _progress.NotifyLevelStart(); if (stream.CanSeek) { _progress.AddTotal(WrappedStream.Length - WrappedStream.Position); } }
private Task <bool> IntegrityCheckOperationAsync() { _progress.NotifyLevelStart(); try { Stream stream = _eventArgs.AxCryptFile.OpenRead(); using (FormatIntegrityChecker integrityChecker = new FormatIntegrityChecker(stream, _eventArgs.OpenFileFullName)) { integrityChecker.Verify(); } } catch (AxCryptException ace) { New <IReport>().Exception(ace); _eventArgs.Status = new FileOperationContext(_eventArgs.OpenFileFullName, ace.ErrorStatus); return(Task.FromResult(false)); } finally { _progress.NotifyLevelFinished(); } _eventArgs.Status = new FileOperationContext(_eventArgs.OpenFileFullName, ErrorStatus.Success); return(Task.FromResult(true)); }
/// <summary> /// Changes the encryption for all encrypted files in the provided containers, using the original identity to decrypt /// and the provided encryption parameters for the new encryption. /// </summary> /// <remarks> /// If a file is already encrypted with the appropriate parameters, nothing happens. /// </remarks> /// <param name="containers">The containers.</param> /// <param name="identity">The identity.</param> /// <param name="encryptionParameters">The encryption parameters.</param> /// <param name="progress">The progress.</param> /// <exception cref="System.ArgumentNullException"> /// containers /// or /// progress /// </exception> public virtual async Task ChangeEncryptionAsync(IEnumerable <IDataContainer> containers, LogOnIdentity identity, EncryptionParameters encryptionParameters, IProgressContext progress) { if (containers == null) { throw new ArgumentNullException("containers"); } if (progress == null) { throw new ArgumentNullException("progress"); } progress.NotifyLevelStart(); try { IEnumerable <IDataStore> files = containers.SelectMany((folder) => folder.ListEncrypted(containers, New <UserSettings>().FolderOperationMode.Policy())); await ChangeEncryptionAsync(files, identity, encryptionParameters, progress); } finally { progress.NotifyLevelFinished(); } await Resolve.SessionNotify.NotifyAsync(new SessionNotification(SessionNotificationType.ActiveFileChange)); }
public virtual void Wipe(FileLock store, IProgressContext progress) { if (progress == null) { throw new ArgumentNullException("progress"); } if (store == null) { throw new ArgumentNullException("store"); } if (!store.DataStore.IsAvailable) { return; } if (Resolve.Log.IsInfoEnabled) { Resolve.Log.LogInfo("Wiping '{0}'.".InvariantFormat(store.DataStore.Name)); } progress.Cancel = false; bool cancelPending = false; progress.NotifyLevelStart(); try { string randomName; do { randomName = GenerateRandomFileName(store.DataStore.FullName); } while (New <IDataStore>(randomName).IsAvailable); IDataStore moveToFileInfo = New <IDataStore>(store.DataStore.FullName); moveToFileInfo.MoveTo(randomName); moveToFileInfo.IsWriteProtected = false; using (Stream stream = moveToFileInfo.OpenUpdate()) { 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 = Resolve.RandomGenerator.Generate(OS.Current.StreamBufferSize); stream.Write(random, 0, random.Length); stream.Flush(); try { progress.AddCount(random.Length); } catch (OperationCanceledException) { cancelPending = true; progress.AddCount(random.Length); } } } moveToFileInfo.Delete(); } finally { progress.NotifyLevelFinished(); } if (cancelPending) { throw new OperationCanceledException("Delayed cancel during wipe."); } }
private async Task HandleNotificationInternalAsync(SessionNotification notification, IProgressContext progress) { if (Resolve.Log.IsInfoEnabled) { Resolve.Log.LogInfo("Received notification type '{0}'.".InvariantFormat(notification.NotificationType)); } EncryptionParameters encryptionParameters; switch (notification.NotificationType) { case SessionNotificationType.WatchedFolderAdded: case SessionNotificationType.WatchedFolderOptionsChanged: progress.NotifyLevelStart(); try { foreach (string fullName in notification.FullNames) { WatchedFolder watchedFolder = _fileSystemState.WatchedFolders.First(wf => wf.Path == fullName); encryptionParameters = new EncryptionParameters(Resolve.CryptoFactory.Default(New <ICryptoPolicy>()).CryptoId, notification.Identity); await encryptionParameters.AddAsync(await watchedFolder.KeyShares.ToAvailableKnownPublicKeysAsync(notification.Identity)); IDataContainer container = New <IDataContainer>(watchedFolder.Path); progress.Display = container.Name; IDataContainer[] dc = new IDataContainer[] { container }; await _axCryptFile.EncryptFoldersUniqueWithBackupAndWipeAsync(dc, encryptionParameters, progress); } } finally { progress.NotifyLevelFinished(); } progress.Totals.ShowNotification(); break; case SessionNotificationType.WatchedFolderRemoved: foreach (string fullName in notification.FullNames) { IDataContainer removedFolderInfo = New <IDataContainer>(fullName); progress.Display = removedFolderInfo.Name; if (removedFolderInfo.IsAvailable) { await _axCryptFile.DecryptFilesInsideFolderUniqueWithWipeOfOriginalAsync(removedFolderInfo, notification.Identity, _statusChecker, progress).Free(); } } break; case SessionNotificationType.SignIn: await EncryptWatchedFoldersIfSupportedAsync(notification.Identity, notification.Capabilities, progress); break; case SessionNotificationType.SignOut: New <IInternetState>().Clear(); New <ICache>().RemoveItem(CacheKey.RootKey); New <UserPublicKeyUpdateStatus>().Clear(); break; case SessionNotificationType.EncryptPendingFiles: await _activeFileAction.ClearExceptionState(); await _activeFileAction.PurgeActiveFiles(progress); if (_knownIdentities.DefaultEncryptionIdentity != LogOnIdentity.Empty) { await EncryptWatchedFoldersIfSupportedAsync(_knownIdentities.DefaultEncryptionIdentity, notification.Capabilities, progress); } break; case SessionNotificationType.UpdateActiveFiles: await _fileSystemState.UpdateActiveFiles(notification.FullNames); break; case SessionNotificationType.ActiveFileChange: case SessionNotificationType.SessionStart: case SessionNotificationType.WatchedFolderChange: case SessionNotificationType.ProcessExit: case SessionNotificationType.KnownKeyChange: case SessionNotificationType.SessionChange: case SessionNotificationType.WorkFolderChange: await _activeFileAction.CheckActiveFiles(progress); break; case SessionNotificationType.LicensePolicyChanged: case SessionNotificationType.RefreshLicensePolicy: break; default: throw new InvalidOperationException("Unhandled notification received"); } }
public void NotifyLevelStart() { _progress.NotifyLevelStart(); }
public void NotifyLevelStart() { ThrowIfCancelled(); _progress.NotifyLevelStart(); }