Exemple #1
0
 /// <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();
 }
Exemple #2
0
        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();
            }
        }
Exemple #3
0
 /// <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 SessionNotificationHandler(FileSystemState fileSystemState, KnownIdentities knownIdentities, ActiveFileAction activeFileAction, AxCryptFile axCryptFile, IStatusChecker statusChecker)
 {
     _fileSystemState  = fileSystemState;
     _knownIdentities  = knownIdentities;
     _activeFileAction = activeFileAction;
     _axCryptFile      = axCryptFile;
     _statusChecker    = statusChecker;
 }
 public void EndInit()
 {
     if (DesignMode)
     {
         return;
     }
     Current = new FileSystemState();
 }
Exemple #6
0
 private static ActiveFile CheckActiveFileActions(this FileSystemState fileSystemState, ActiveFile activeFile, ProgressContext progress)
 {
     activeFile = CheckIfKeyIsKnown(fileSystemState, activeFile);
     activeFile = CheckIfCreated(activeFile);
     activeFile = CheckIfProcessExited(activeFile);
     activeFile = CheckIfTimeToUpdate(activeFile, progress);
     activeFile = CheckIfTimeToDelete(activeFile, progress);
     return(activeFile);
 }
Exemple #7
0
        /// <summary>
        /// Enumerate all apparently plaintext files in the list of watched folders.
        /// </summary>
        /// <param name="fileSystemState">The associated <see cref="FileSystemState"/>.</param>
        /// <returns>An enumeration of found files.</returns>
        public static IEnumerable <IRuntimeFileInfo> DecryptedFilesInWatchedFolders(this FileSystemState fileSystemState)
        {
            IEnumerable <IRuntimeFileInfo> newFiles = new List <IRuntimeFileInfo>();

            foreach (WatchedFolder watchedFolder in fileSystemState.WatchedFolders)
            {
                IRuntimeFileInfo fileInfo = OS.Current.FileInfo(watchedFolder.Path);
                newFiles = newFiles.Concat(fileInfo.Files);
            }
            return(newFiles.Where((IRuntimeFileInfo fileInfo) => { return !fileInfo.Name.IsEncryptedName(); }));
        }
        public static void Setup()
        {
            SetupAssembly.AssemblySetup();

            FakeRuntimeFileInfo.AddFile(_davidCopperfieldTxtPath, FakeRuntimeFileInfo.TestDate4Utc, FakeRuntimeFileInfo.TestDate5Utc, FakeRuntimeFileInfo.TestDate6Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
            FakeRuntimeFileInfo.AddFile(_uncompressedAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.uncompressable_zip));
            FakeRuntimeFileInfo.AddFile(_helloWorldAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));

            _fileSystemState = new FileSystemState();
            _fileSystemState.Load(FileSystemState.DefaultPathInfo);
        }
        public static void Setup()
        {
            SetupAssembly.AssemblySetup();

            FakeRuntimeFileInfo.AddFile(_testTextPath, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.TestDate2Utc, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("This is a short file")));
            FakeRuntimeFileInfo.AddFile(_davidCopperfieldTxtPath, FakeRuntimeFileInfo.TestDate4Utc, FakeRuntimeFileInfo.TestDate5Utc, FakeRuntimeFileInfo.TestDate6Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
            FakeRuntimeFileInfo.AddFile(_uncompressedAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.uncompressable_zip));
            FakeRuntimeFileInfo.AddFile(_helloWorldAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));

            _fileSystemState = new FileSystemState();
            _fileSystemState.Load(OS.Current.FileInfo(Path.Combine(Path.GetTempPath(), "FileSystemState.xml")));
        }
        public void Load(IRuntimeFileInfo path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (!path.Exists)
            {
                _path = path.FullName;
                if (OS.Log.IsInfoEnabled)
                {
                    OS.Log.LogInfo("No existing FileSystemState. Save location is '{0}'.".InvariantFormat(_path));
                }
                return;
            }

            DataContractSerializer serializer = CreateSerializer();
            IRuntimeFileInfo       loadInfo   = OS.Current.FileInfo(path.FullName);

            using (Stream fileSystemStateStream = loadInfo.OpenRead())
            {
                FileSystemState fileSystemState;
                try
                {
                    fileSystemState = (FileSystemState)serializer.ReadObject(fileSystemStateStream);
                }
                catch (Exception ex)
                {
                    if (OS.Log.IsErrorEnabled)
                    {
                        OS.Log.LogError("Exception {1} reading {0}. Ignoring and re-initializing state.".InvariantFormat(path.FullName, ex.Message));
                    }
                    fileSystemState = new FileSystemState();
                }
                _path = path.FullName;
                foreach (ActiveFile activeFile in fileSystemState.ActiveFiles)
                {
                    Add(activeFile);
                }
                KnownKeys         = fileSystemState.KnownKeys;
                KeyWrapIterations = fileSystemState.KeyWrapIterations;
                ThumbprintSalt    = fileSystemState.ThumbprintSalt;
                WatchedFolders    = fileSystemState.WatchedFolders;
                if (OS.Log.IsInfoEnabled)
                {
                    OS.Log.LogInfo("Loaded FileSystemState from '{0}'.".InvariantFormat(fileSystemState._path));
                }
            }
        }
Exemple #11
0
 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();
 }
        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); });
            }
        }
 protected override void Dispose(bool disposing)
 {
     if (_disposed)
     {
         return;
     }
     if (disposing)
     {
         if (Current != null)
         {
             Current.Dispose();
             Current = null;
         }
     }
     _disposed = true;
     base.Dispose(disposing);
 }
Exemple #14
0
 private static ActiveFile CheckIfKeyIsKnown(FileSystemState fileSystemState, ActiveFile activeFile)
 {
     if ((activeFile.Status & (ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.DecryptedIsPendingDelete | ActiveFileStatus.NotDecrypted)) == 0)
     {
         return(activeFile);
     }
     if (activeFile.Key != null)
     {
         return(activeFile);
     }
     foreach (AesKey key in fileSystemState.KnownKeys.Keys)
     {
         if (activeFile.ThumbprintMatch(key))
         {
             activeFile = new ActiveFile(activeFile, key);
         }
         return(activeFile);
     }
     return(activeFile);
 }
Exemple #15
0
        /// <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);
        }
Exemple #16
0
        public static FileSystemState Create(IDataStore path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (path.IsAvailable)
            {
                return(CreateFileSystemState(path));
            }

            FileSystemState fileSystemState = new FileSystemState()
            {
                _dataStore = path,
            };

            if (Resolve.Log.IsInfoEnabled)
            {
                Resolve.Log.LogInfo("No existing FileSystemState. Save location is '{0}'.".InvariantFormat(path.FullName));
            }
            return(fileSystemState);
        }
Exemple #17
0
        private static FileSystemState CreateFileSystemState(IDataStore path)
        {
            FileSystemState fileSystemState = null;

            try
            {
                fileSystemState = Resolve.Serializer.Deserialize <FileSystemState>(path);
                if (fileSystemState == null)
                {
                    if (Resolve.Log.IsErrorEnabled)
                    {
                        Resolve.Log.LogError("Empty {0}. Ignoring and re-initializing state.".InvariantFormat(path.FullName));
                    }
                }
                else
                {
                    if (Resolve.Log.IsInfoEnabled)
                    {
                        Resolve.Log.LogInfo("Loaded FileSystemState from '{0}'.".InvariantFormat(path));
                    }
                }
            }
            catch (Exception ex)
            {
                New <IReport>().Exception(ex);
                if (Resolve.Log.IsErrorEnabled)
                {
                    Resolve.Log.LogError("Exception {1} reading {0}. Ignoring and re-initializing state.".InvariantFormat(path.FullName, ex.Message));
                }
            }
            if (fileSystemState == null)
            {
                fileSystemState = new FileSystemState();
            }
            fileSystemState._dataStore = path;
            return(fileSystemState);
        }
        public static void TestWatchedFolders()
        {
            using (FileSystemState state = new FileSystemState())
            {
                IRuntimeFileInfo stateInfo = OS.Current.FileInfo(_mystateXmlPath);
                state.Load(stateInfo);

                Assert.That(state.WatchedFolders, Is.Not.Null, "There should be a Watched Folders instance.");
                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(0), "There should be no Watched folders.");

                state.AddWatchedFolder(new WatchedFolder(_rootPath));
                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1), "There should be one Watched Folder.");

                state.AddWatchedFolder(new WatchedFolder(_rootPath));
                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1), "There should still only be one Watched Folder.");

                state.Save();
            }

            using (FileSystemState state = new FileSystemState())
            {
                IRuntimeFileInfo stateInfo = OS.Current.FileInfo(_mystateXmlPath);
                state.Load(stateInfo);

                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1), "There should be one Watched Folder.");

                Assert.That(state.WatchedFolders.First(), Is.EqualTo(new WatchedFolder(_rootPath)), "The Watched Folder should be equal to this.");

                state.RemoveWatchedFolder(new WatchedFolder(_mystateXmlPath));
                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1), "There should still be one Watched folders.");

                state.RemoveWatchedFolder(new WatchedFolder(_rootPath));
                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(0), "There should still be no Watched folders now.");
            }
        }
        public static void TestLoadNew()
        {
            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.");
            }
        }
        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 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.");
            }
        }
        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 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.");
            }
        }
        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.");
            }
        }
 /// <summary>
 /// Create a new instance, reporting progress
 /// </summary>
 /// <param name="fileSystemState">The current FileSystemStatem instance</param>
 /// <param name="progress">The instance of ProgressContext to report progress via</param>
 public FileOperationsController(FileSystemState fileSystemState, ProgressContext progress)
 {
     _eventArgs = new FileOperationEventArgs();
     _fileSystemState = fileSystemState;
     _progress = progress;
 }
 /// <summary>
 /// Create a new instance, without any progress reporting.
 /// </summary>
 /// <param name="fileSystemState">The current FileSystemStatem instance</param>
 public FileOperationsController(FileSystemState fileSystemState)
     : this(fileSystemState, new ProgressContext())
 {
 }
        public void Load(IRuntimeFileInfo path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (!path.Exists)
            {
                _path = path.FullName;
                if (OS.Log.IsInfoEnabled)
                {
                    OS.Log.LogInfo("No existing FileSystemState. Save location is '{0}'.".InvariantFormat(_path));
                }
                return;
            }

            DataContractSerializer serializer = CreateSerializer();
            IRuntimeFileInfo loadInfo = OS.Current.FileInfo(path.FullName);

            using (Stream fileSystemStateStream = loadInfo.OpenRead())
            {
                FileSystemState fileSystemState;
                try
                {
                    fileSystemState = (FileSystemState)serializer.ReadObject(fileSystemStateStream);
                }
                catch (Exception ex)
                {
                    if (OS.Log.IsErrorEnabled)
                    {
                        OS.Log.LogError("Exception {1} reading {0}. Ignoring and re-initializing state.".InvariantFormat(path.FullName, ex.Message));
                    }
                    fileSystemState = new FileSystemState();
                }
                _path = path.FullName;
                foreach (ActiveFile activeFile in fileSystemState.ActiveFiles)
                {
                    Add(activeFile);
                }
                KnownKeys = fileSystemState.KnownKeys;
                KeyWrapIterations = fileSystemState.KeyWrapIterations;
                ThumbprintSalt = fileSystemState.ThumbprintSalt;
                WatchedFolders = fileSystemState.WatchedFolders;
                if (OS.Log.IsInfoEnabled)
                {
                    OS.Log.LogInfo("Loaded FileSystemState from '{0}'.".InvariantFormat(fileSystemState._path));
                }
            }
        }
 private static ActiveFile CheckIfKeyIsKnown(FileSystemState fileSystemState, ActiveFile activeFile)
 {
     if ((activeFile.Status & (ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.DecryptedIsPendingDelete | ActiveFileStatus.NotDecrypted)) == 0)
     {
         return activeFile;
     }
     if (activeFile.Key != null)
     {
         return activeFile;
     }
     foreach (AesKey key in fileSystemState.KnownKeys.Keys)
     {
         if (activeFile.ThumbprintMatch(key))
         {
             activeFile = new ActiveFile(activeFile, key);
         }
         return activeFile;
     }
     return activeFile;
 }
 public static void Initialize()
 {
     fileSystemState = new FileSystemState ();
     fileSystemState.Load (FileSystemState.DefaultPathInfo);
     OS.Current.KeyWrapIterations = fileSystemState.KeyWrapIterations;
     OS.Current.ThumbprintSalt = fileSystemState.ThumbprintSalt;
     fileSystemState.KnownKeys.Changed += delegate { OS.Current.NotifyWorkFolderStateChanged(); };
 }
        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.");
            }
        }
        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 TestDoubleDispose()
        {
            FileSystemState state = new FileSystemState();
            state.Dispose();

            Assert.DoesNotThrow(() => { state.Dispose(); });
        }
        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;
        }