/// <summary> /// Read a specified clipboard data, encrypt and save it into a file. /// </summary> /// <param name="clipboardReader">The <see cref="ClipboardReader"/> used to read the data.</param> /// <param name="identifier">The data identifier.</param> /// <param name="clipboardDataPath">The full path to the clipboard data folder.</param> private void WriteClipboardDataToFile(ClipboardReader clipboardReader, DataIdentifier identifier, string clipboardDataPath) { Requires.NotNull(clipboardReader, nameof(clipboardReader)); Requires.NotNull(identifier, nameof(identifier)); Requires.NotNullOrWhiteSpace(clipboardDataPath, nameof(clipboardDataPath)); var dataFilePath = Path.Combine(clipboardDataPath, $"{identifier.Identifier}.dat"); if (File.Exists(dataFilePath)) { Logger.Instance.Fatal(new FileLoadException($"The file {dataFilePath} already exists.")); } var dataPassword = SecurityHelper.ToSecureString(SecurityHelper.EncryptString(SecurityHelper.ToSecureString(identifier.Identifier.ToString()))); Requires.NotNull(dataPassword, nameof(dataPassword)); clipboardReader.BeginRead(identifier.FormatName); Requires.IsTrue(clipboardReader.IsReadable); Requires.IsTrue(clipboardReader.CanReadNextBlock()); using (var fileStream = File.OpenWrite(dataFilePath)) using (var aesStream = new AesStream(fileStream, dataPassword, SecurityHelper.GetSaltKeys(dataPassword).GetBytes(16))) { aesStream.AutoDisposeBaseStream = false; while (clipboardReader.CanReadNextBlock()) { var buffer = clipboardReader.ReadNextBlock(); aesStream.Write(buffer, 0, buffer.Length); } aesStream.Position = 0; } clipboardReader.EndRead(); }
public void ClipboardWriterAndReader() { using (var clipboardWriter = new ClipboardWriter()) { var value = new MemoryStream(new byte[] { 72, 101, 108, 108, 111 }); // "Hello" in binary clipboardWriter.AddData("ASCIITextTest", value); clipboardWriter.Flush(); } var dataFromClipboard = (MemoryStream)System.Windows.Clipboard.GetData("ASCIITextTest"); Assert.IsTrue(dataFromClipboard.ToArray().SequenceEqual(new byte[] { 72, 101, 108, 108, 111 })); var dataFromClipboard2 = new MemoryStream(); var dataObject = (System.Windows.DataObject)System.Windows.Clipboard.GetDataObject(); using (var clipboardReader = new ClipboardReader(dataObject)) { Assert.IsFalse(clipboardReader.IsReadable); Assert.IsFalse(clipboardReader.CanReadNextBlock()); foreach (var format in dataObject.GetFormats()) { clipboardReader.BeginRead(format); Assert.IsTrue(clipboardReader.IsReadable); Assert.IsTrue(clipboardReader.CanReadNextBlock()); while (clipboardReader.CanReadNextBlock()) { var buffer = clipboardReader.ReadNextBlock(); dataFromClipboard2.Write(buffer, 0, buffer.Length); } clipboardReader.EndRead(); } } Assert.IsTrue(dataFromClipboard2.ToArray().SequenceEqual(new byte[] { 72, 101, 108, 108, 111 })); }
/// <summary> /// Called when the clipboard content has changed. /// </summary> /// <param name="sender">The <see cref="ClipboardHook"/>.</param> /// <param name="e">The information about the changes.</param> internal void ClipboardHook_ClipboardChanged(object sender, Events.ClipboardHookEventArgs e) { if (_ignoreClipboardChange) { return; } _ignoreClipboardChange = true; var mouseAndKeyboardHookService = ServiceLocator.GetService <MouseAndKeyboardHookService>(); mouseAndKeyboardHookService.Pause(); Pause(); var delayer = new Delayer <object>(TimeSpan.FromMilliseconds(10)); delayer.Action += (o, args) => { try { Logger.Instance.Information($"A data has been copied. The {nameof(ClipboardService)} tries to retrieve the data."); Requires.NotNull(e, nameof(e)); DispatcherHelper.ThrowIfNotStaThread(); var dataIgnored = false; var isCreditCard = false; var isPassword = false; var dataService = ServiceLocator.GetService <DataService>(); var foregroundWindow = ServiceLocator.GetService <WindowsService>().GetForegroundWindow(); if (_ignoredApplications.Any(app => app.ApplicationIdentifier == foregroundWindow.ApplicationIdentifier)) { dataIgnored = true; Logger.Instance.Information($"The {nameof(ClipboardService)} ignored the data because it comes from an ignored application."); } else { if (e.DataObject.ContainsText()) { var text = e.DataObject.GetText(); isCreditCard = dataService.IsCreditCard(text); if (isCreditCard && dataService.KeepOrIgnoreCreditCard(text)) { dataIgnored = true; Logger.Instance.Information($"The {nameof(ClipboardService)} ignored the data because it is a credit card number."); } isPassword = dataService.IsPassword(text, foregroundWindow); if (isPassword && dataService.KeepOrIgnorePassword(text)) { dataIgnored = true; Logger.Instance.Information($"The {nameof(ClipboardService)} ignored the data because it is a password."); } } } if (!dataIgnored) { dataService.Reset(); var identifiers = dataService.GetDataIdentifiers(e.DataObject.GetFormats()); if (identifiers.Count == 0) { Logger.Instance.Information($"The {nameof(ClipboardService)} ignored the data because it does not detected any compatible data format in the clipboard."); } else { using (Logger.Instance.Stopwatch("Persisting clipboard data to the hard drive.")) { dataService.EnsureDataFolderExists(); using (var clipboardReader = new ClipboardReader(e.DataObject)) { for (var i = 0; i < identifiers.Count; i++) { try { WriteClipboardDataToFile(clipboardReader, identifiers[i], dataService.ClipboardDataPath); } catch { identifiers.RemoveAt(i); i--; } } } } using (Logger.Instance.Stopwatch("Adding a new data entry to the data service.")) { dataService.AddDataEntry(e, identifiers, foregroundWindow, isCreditCard, isPassword); } Logger.Instance.Information($"The {nameof(ClipboardService)} successfully retrieved the data from the clipboard."); } } } catch (Exception exception) { Logger.Instance.Error(exception); } finally { delayer = new Delayer <object>(TimeSpan.FromMilliseconds(10)); delayer.Action += (sender1, eventArgs) => { _ignoreClipboardChange = false; Resume(); mouseAndKeyboardHookService.Resume(); CoreHelper.MinimizeFootprint(); }; delayer.ResetAndTick(); if (CoreHelper.IsUnitTesting()) { Task.Delay(10).Wait(); DispatcherHelper.DoEvents(); } } }; delayer.ResetAndTick(); }