public void TestDecryptFileWithExceptionBeforeStartingDecryption()
        {
            FileOperationsController controller = new FileOperationsController();

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                e.LogOnIdentity = new LogOnIdentity("a");
                return(Task.FromResult <object>(null));
            };
            controller.KnownKeyAdded = new AsyncDelegateAction <FileOperationEventArgs>((FileOperationEventArgs e) =>
            {
                throw new FileNotFoundException("Just kidding, but we're faking...", e.OpenFileFullName);
            });
            string destinationPath = String.Empty;
            AsyncDelegateAction <FileOperationEventArgs> previous = controller.KnownKeyAdded;

            controller.KnownKeyAdded = new AsyncDelegateAction <FileOperationEventArgs>(async(FileOperationEventArgs e) =>
            {
                await previous.ExecuteAsync(e);
                destinationPath = e.SaveFileFullName;
            });
            FileOperationContext status = new FileOperationContext(String.Empty, ErrorStatus.Unknown);

            Assert.DoesNotThrowAsync(async() => { status = await controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath)); });

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.FileDoesNotExist), "The status should indicate an exception occurred.");
            Assert.That(String.IsNullOrEmpty(destinationPath), "Since an exception occurred, the destination file should not be created.");
        }
        public async Task TestDecryptFileWithRepeatedPassphraseQueries()
        {
            FileOperationsController controller = new FileOperationsController();
            int passphraseTry = 0;

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                switch (++passphraseTry)
                {
                case 1:
                    e.LogOnIdentity = new LogOnIdentity("b");
                    break;

                case 2:
                    e.LogOnIdentity = new LogOnIdentity("d");
                    break;

                case 3:
                    e.LogOnIdentity = new LogOnIdentity("a");
                    break;

                case 4:
                    e.LogOnIdentity = new LogOnIdentity("e");
                    break;
                }
                ;
                return(Task.FromResult <object>(null));
            };
            string destinationPath = String.Empty;

            controller.Completed += (object sender, FileOperationEventArgs e) =>
            {
                destinationPath = e.SaveFileFullName;
            };
            bool knownKeyWasAdded = false;

            controller.KnownKeyAdded = new AsyncDelegateAction <FileOperationEventArgs>((FileOperationEventArgs e) =>
            {
                knownKeyWasAdded = e.LogOnIdentity.Equals(new LogOnIdentity("a"));
                return(Constant.CompletedTask);
            });
            FileOperationContext status = await controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath));

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Success), "The status should indicate success.");
            Assert.That(knownKeyWasAdded, "A new known key was used, so the KnownKeyAdded event should have been raised.");
            Assert.That(passphraseTry, Is.EqualTo(3), "The third key was the correct one.");
            IDataStore destinationInfo = New <IDataStore>(destinationPath);

            Assert.That(destinationInfo.IsAvailable, "After decryption the destination file should be created.");

            string fileContent;

            using (Stream stream = destinationInfo.OpenRead())
            {
                fileContent = new StreamReader(stream).ReadToEnd();
            }
            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
        }
        public async Task TestDecryptWithCancelDuringQueryDecryptionPassphrase()
        {
            FileOperationsController controller = new FileOperationsController();

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                e.Cancel = true;
                return(Task.FromResult <object>(null));
            };
            FileOperationContext status = await controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath));

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Canceled), "The status should indicate cancellation.");
        }
        public async Task TestDecryptWithKnownKey()
        {
            FileOperationsController controller = new FileOperationsController();
            await Resolve.KnownIdentities.AddAsync(new LogOnIdentity("b"));

            await Resolve.KnownIdentities.AddAsync(new LogOnIdentity("c"));

            await Resolve.KnownIdentities.AddAsync(new LogOnIdentity("a"));

            await Resolve.KnownIdentities.AddAsync(new LogOnIdentity("e"));

            bool passphraseWasQueried = false;

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                passphraseWasQueried = true;
                return(Task.FromResult <object>(null));
            };
            string destinationPath = String.Empty;

            controller.Completed += (object sender, FileOperationEventArgs e) =>
            {
                destinationPath = e.SaveFileFullName;
            };
            bool knownKeyWasAdded = false;

            controller.KnownKeyAdded = new AsyncDelegateAction <FileOperationEventArgs>((FileOperationEventArgs e) =>
            {
                knownKeyWasAdded = true;
                return(Constant.CompletedTask);
            });
            FileOperationContext status = await controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath));

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Success), "The status should indicate success.");
            Assert.That(!knownKeyWasAdded, "An already known key was used, so the KnownKeyAdded event should not have been raised.");
            Assert.That(!passphraseWasQueried, "An already known key was used, so the there should be no need to query for a passphrase.");
            IDataStore destinationInfo = New <IDataStore>(destinationPath);

            Assert.That(destinationInfo.IsAvailable, "After decryption the destination file should be created.");

            string fileContent;

            using (Stream stream = destinationInfo.OpenRead())
            {
                fileContent = new StreamReader(stream).ReadToEnd();
            }
            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
        }
        private Task <FileOperationContext> DecryptFileWork(IDataStore file, IProgressContext progress)
        {
            ActiveFile activeFile = New <FileSystemState>().FindActiveFileFromEncryptedPath(file.FullName);

            if (activeFile != null && activeFile.Status.HasFlag(ActiveFileStatus.AssumedOpenAndDecrypted))
            {
                return(Task.FromResult(new FileOperationContext(file.FullName, ErrorStatus.FileLocked)));
            }

            FileOperationsController operationsController = new FileOperationsController(progress);

            operationsController.QueryDecryptionPassphrase = HandleQueryDecryptionPassphraseEventAsync;

            operationsController.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
            {
                FileSelectionEventArgs fileSelectionArgs = new FileSelectionEventArgs(new string[] { e.SaveFileFullName })
                {
                    FileSelectionType = FileSelectionType.SaveAsDecrypted,
                };
                OnSelectingFiles(fileSelectionArgs);
                if (fileSelectionArgs.Cancel)
                {
                    e.Cancel = true;
                    return;
                }
                e.SaveFileFullName = fileSelectionArgs.SelectedFiles[0];
            };

            operationsController.KnownKeyAdded = new AsyncDelegateAction <FileOperationEventArgs>(async(FileOperationEventArgs e) =>
            {
                await _knownIdentities.AddAsync(e.LogOnIdentity);
            });

            operationsController.Completed += async(object sender, FileOperationEventArgs e) =>
            {
                if (e.Status.ErrorStatus == ErrorStatus.Success)
                {
                    await New <ActiveFileAction>().RemoveRecentFiles(new IDataStore[] { New <IDataStore>(e.OpenFileFullName) }, progress);
                }
            };

            return(operationsController.DecryptFileAsync(file));
        }
        public void TestDecryptWithCancelDuringQueryDecryptionPassphraseOnThreadWorker()
        {
            FileOperationsController controller = new FileOperationsController();

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                e.Cancel = true;
                return(Task.FromResult <object>(null));
            };
            FileOperationContext status = new FileOperationContext(String.Empty, ErrorStatus.Unknown);

            controller.Completed += (object sender, FileOperationEventArgs e) =>
            {
                status = e.Status;
            };

            controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath));

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Canceled), "The status should indicate cancellation.");
        }
        public void TestSimpleDecryptFileOnThreadWorker()
        {
            FileOperationsController controller = new FileOperationsController();

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                e.LogOnIdentity = new LogOnIdentity("a");
                return(Task.FromResult <object>(null));
            };
            bool knownKeyWasAdded = false;

            controller.KnownKeyAdded = new AsyncDelegateAction <FileOperationEventArgs>((FileOperationEventArgs e) =>
            {
                knownKeyWasAdded = e.LogOnIdentity.Equals(new LogOnIdentity("a"));
                return(Constant.CompletedTask);
            });
            string destinationPath      = String.Empty;
            FileOperationContext status = new FileOperationContext(String.Empty, ErrorStatus.Unknown);

            controller.Completed += (object sender, FileOperationEventArgs e) =>
            {
                destinationPath = e.SaveFileFullName;
                status          = e.Status;
            };

            controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath));

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Success), "The status should indicate success.");
            Assert.That(knownKeyWasAdded, "A new known key was used, so the KnownKeyAdded event should have been raised.");
            IDataStore destinationInfo = New <IDataStore>(destinationPath);

            Assert.That(destinationInfo.IsAvailable, "After decryption the destination file should be created.");

            string fileContent;

            using (Stream stream = destinationInfo.OpenRead())
            {
                fileContent = new StreamReader(stream).ReadToEnd();
            }
            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
        }
        public async Task TestDecryptWithAlternativeDestinationName()
        {
            IDataStore expectedDestinationInfo = New <IDataStore>(Path.Combine(Path.GetDirectoryName(_helloWorldAxxPath), "HelloWorld-Key-a.txt"));

            using (Stream stream = expectedDestinationInfo.OpenWrite())
            {
            }

            FileOperationsController controller = new FileOperationsController();

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                e.LogOnIdentity = new LogOnIdentity("a");
                return(Task.FromResult <object>(null));
            };
            controller.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
            {
                e.SaveFileFullName = Path.Combine(Path.GetDirectoryName(e.SaveFileFullName), "Other Hello World.txt");
            };
            string destinationPath = String.Empty;

            controller.Completed += (object sender, FileOperationEventArgs e) =>
            {
                destinationPath = e.SaveFileFullName;
            };
            FileOperationContext status = await controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath));

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Success), "The status should indicate success.");

            IDataStore destinationInfo = New <IDataStore>(destinationPath);
            string     fileContent;

            using (Stream stream = destinationInfo.OpenRead())
            {
                fileContent = new StreamReader(stream).ReadToEnd();
            }
            Assert.That(fileContent.Contains("Hello"), "A file named 'Other Hello World.txt' should contain that text when decrypted.");
        }
        public async Task TestDecryptWithCancelDuringQuerySaveAs()
        {
            IDataStore expectedDestinationInfo = New <IDataStore>(Path.Combine(Path.GetDirectoryName(_helloWorldAxxPath), "HelloWorld-Key-a.txt"));

            using (Stream stream = expectedDestinationInfo.OpenWrite())
            {
            }

            FileOperationsController controller = new FileOperationsController();

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                e.LogOnIdentity = new LogOnIdentity("a");
                return(Task.FromResult <object>(null));
            };
            controller.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
            {
                e.Cancel = true;
            };
            FileOperationContext status = await controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath));

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Canceled), "The status should indicate cancellation.");
        }
        public async Task TestDecryptWithSkipDuringQueryDecryptionPassphrase()
        {
            IDataStore expectedDestinationInfo = New <IDataStore>(Path.Combine(Path.GetDirectoryName(_helloWorldAxxPath), "HelloWorld-Key-a.txt"));

            using (Stream stream = expectedDestinationInfo.OpenWrite())
            {
            }

            FileOperationsController controller = new FileOperationsController();

            controller.QueryDecryptionPassphrase = (FileOperationEventArgs e) =>
            {
                e.Skip = true;
                return(Task.FromResult <object>(null));
            };
            bool saveAs = false;

            controller.QuerySaveFileAs += (sender, e) => saveAs = true;
            FileOperationContext status = await controller.DecryptFileAsync(New <IDataStore>(_helloWorldAxxPath));

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Success), "The status should indicate success.");
            Assert.That(saveAs, Is.False, "No Save As should happen, since skip was indicated.");
        }