From 1d6924c076d2bf6b6c6be6f13def8226e6cc347b Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Mon, 10 Jan 2022 20:07:53 -0300 Subject: [PATCH 01/10] Add option to enable or disable the permutation --- StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs | 5 ++++- .../PropertyInspector/KeePassGeneratePI.html | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs index 4e7c7a3..26f4c7b 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs @@ -63,6 +63,9 @@ public static PluginSettings CreateDefaultSettings() [JsonProperty(PropertyName = "customPattern")] public string CustomPattern { get; set; } + + [JsonProperty(PropertyName = "randomlyPermute")] + public bool RandomlyPermute { get; set; } } #region Private Members @@ -111,7 +114,7 @@ public override void KeyPressed(KeyPayload payload) if (!string.IsNullOrEmpty(settings.CustomPattern)) { profile.GeneratorType = PasswordGeneratorType.Pattern; - profile.PatternPermutePassword = true; + profile.PatternPermutePassword = settings.RandomlyPermute; profile.Pattern = settings.CustomPattern; } diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassGeneratePI.html b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassGeneratePI.html index 169b461..e1867b1 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassGeneratePI.html +++ b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassGeneratePI.html @@ -50,6 +50,10 @@ +
+ + +
From a4035a61b2f83df4c20d580bc21ff5781f60daf6 Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Tue, 18 Jan 2022 21:45:51 -0300 Subject: [PATCH 02/10] Initial refactor of the project --- .../StreamDeck-KeePass/ActionGenerate.cs | 74 ++++++++ .../StreamDeck-KeePass/ActionRetrieve.cs | 76 +++++++++ .../StreamDeck-KeePass/Domain/KeePassEntry.cs | 24 +++ .../Domain/KeePassGenerate.cs | 39 +++++ .../Domain/KeePassPlugin.cs | 48 ++++++ .../Domain/KeePassRetrieve.cs | 59 +++++++ .../Domain/Settings/GenerateSettings.cs | 60 +++++++ .../Domain/Settings/RetrieveSettings.cs | 37 ++++ .../StreamDeck-KeePass/KeePassGenerate.cs | 161 ------------------ .../StreamDeck-KeePass/KeePassRetrieve.cs | 156 ----------------- .../{ => Services}/ClipboardHelper.cs | 2 +- .../StreamDeck-KeePass.csproj | 13 +- 12 files changed, 428 insertions(+), 321 deletions(-) create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassEntry.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassGenerate.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/GenerateSettings.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/RetrieveSettings.cs delete mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs delete mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/KeePassRetrieve.cs rename StreamDeck-KeePass/StreamDeck-KeePass/{ => Services}/ClipboardHelper.cs (92%) diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs new file mode 100644 index 0000000..4bcdde6 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs @@ -0,0 +1,74 @@ +using BarRaider.SdTools; +using Newtonsoft.Json.Linq; +using streamdeck_keepass.Domain; +using StreamDeck_KeePass.Domain.Settings; +using System; +using System.Threading.Tasks; + +namespace StreamDeck_KeePass +{ + [PluginActionId("com.victorgrycuk.keepass.generate")] + public class ActionGenerate : PluginBase + { + private readonly KeePassPlugin plugin; + private readonly GenerateSettings settings; + + public ActionGenerate(SDConnection connection, InitialPayload payload) : base(connection, payload) + { + settings = payload.Settings == null || payload.Settings.Count == 0 + ? GenerateSettings.CreateDefaultSettings() + : payload.Settings.ToObject(); + + plugin = new KeePassPlugin(settings); + } + + public override void Dispose() + { + Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); + } + + public override void KeyPressed(KeyPayload payload) + { + try + { + var result = plugin.GeneratePassword(); + + if (result == KeePassPlugin.Result.WARNING) + { + Connection.ShowAlert().Wait(); + Logger.Instance.LogMessage(TracingLevel.WARN, "No password was generated with the given configuration"); + return; + } + else + { + Connection.ShowOk().Wait(); + } + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message); + } + } + + public override void KeyReleased(KeyPayload payload) { } + + public override void OnTick() { } + + public override void ReceivedSettings(ReceivedSettingsPayload payload) + { + Tools.AutoPopulateSettings(settings, payload.Settings); + SaveSettings(); + } + + public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } + + #region Private Methods + + private Task SaveSettings() + { + return Connection.SetSettingsAsync(JObject.FromObject(settings)); + } + + #endregion + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs new file mode 100644 index 0000000..5c3b303 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs @@ -0,0 +1,76 @@ +using BarRaider.SdTools; +using Newtonsoft.Json.Linq; +using streamdeck_keepass.Domain; +using StreamDeck_KeePass.Domain.Settings; +using System; +using System.Threading.Tasks; + +namespace StreamDeck_KeePass +{ + [PluginActionId("com.victorgrycuk.keepass.retrieve")] + public partial class ActionRetrieve : PluginBase + { + + private readonly KeePassPlugin plugin; + private readonly RetrieveSettings settings; + + public ActionRetrieve(SDConnection connection, InitialPayload payload) : base(connection, payload) + { + settings = payload.Settings == null || payload.Settings.Count == 0 + ? RetrieveSettings.CreateDefaultSettings() + : payload.Settings.ToObject(); + + plugin = new KeePassPlugin(settings); + } + + public override void Dispose() + { + Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); + } + + public override void KeyPressed(KeyPayload payload) + { + try + { + var result = plugin.RetrievePassword(); + + if (result == KeePassPlugin.Result.WARNING) + { + Connection.ShowAlert().Wait(); + Logger.Instance.LogMessage(TracingLevel.WARN, "No password was generated with the given configuration"); + return; + } + else + { + Connection.ShowOk().Wait(); + } + } + catch (Exception ex) + { + Connection.ShowAlert(); + Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message); + } + } + + public override void KeyReleased(KeyPayload payload) { } + + public override void OnTick() { } + + public override void ReceivedSettings(ReceivedSettingsPayload payload) + { + Tools.AutoPopulateSettings(settings, payload.Settings); + SaveSettings(); + } + + public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } + + #region Private Methods + + private Task SaveSettings() + { + return Connection.SetSettingsAsync(JObject.FromObject(settings)); + } + + #endregion + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassEntry.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassEntry.cs new file mode 100644 index 0000000..6b79b83 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassEntry.cs @@ -0,0 +1,24 @@ +using KeePassLib; + +namespace streamdeck_keepass.Domain +{ + internal class KeePassEntry + { + public string Group { get; set; } + public string Title { get; set; } + public string Username { get; set; } + public string Password { get; set; } + public string URL { get; set; } + public string Notes { get; set; } + + public KeePassEntry(PwEntry entry) + { + Group = entry.ParentGroup.Name; + Title = entry.Strings.ReadSafe("Title"); + Username = entry.Strings.ReadSafe("UserName"); + Password = entry.Strings.ReadSafe("Password"); + URL = entry.Strings.ReadSafe("URL"); + Notes = entry.Strings.ReadSafe("Notes"); + } + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassGenerate.cs new file mode 100644 index 0000000..fd9d3e5 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassGenerate.cs @@ -0,0 +1,39 @@ +using KeePassLib.Cryptography.PasswordGenerator; +using KeePassLib.Security; +using StreamDeck_KeePass.Domain.Settings; + +namespace streamdeck_keepass.Domain +{ + static internal class KeePassGenerate + { + static internal string Invoke(GenerateSettings settings) + { + var profile = new PwProfile { CharSet = new PwCharSet() }; + profile.CharSet.Clear(); + + if (settings.UseLowerCase) profile.CharSet.AddCharSet('l'); + if (settings.UseUpperCase) profile.CharSet.AddCharSet('u'); + if (settings.UseDigits) profile.CharSet.AddCharSet('d'); + if (settings.UsePunctuation) profile.CharSet.AddCharSet('p'); + if (settings.UseBrackets) profile.CharSet.AddCharSet('b'); + if (settings.UseSpecial) profile.CharSet.AddCharSet('s'); + + profile.ExcludeLookAlike = settings.ExcludeLookAlike; + profile.Length = (uint)settings.Length; + profile.NoRepeatingCharacters = settings.MustOccurAtMostOnce; + profile.ExcludeCharacters = settings.ExcludeCharacters; + + if (!string.IsNullOrEmpty(settings.CustomPattern)) + { + profile.GeneratorType = PasswordGeneratorType.Pattern; + profile.PatternPermutePassword = settings.RandomlyPermute; + profile.Pattern = settings.CustomPattern; + } + + PwGenerator.Generate(out ProtectedString pw, profile, null, new CustomPwGeneratorPool()); + + return pw.IsEmpty ? string.Empty : pw.ReadString(); + } + } +} + diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs new file mode 100644 index 0000000..29f37da --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs @@ -0,0 +1,48 @@ +using streamdeck_keepass.Services; +using StreamDeck_KeePass.Domain.Settings; + +namespace streamdeck_keepass.Domain +{ + public class KeePassPlugin + { + private readonly GenerateSettings generateSettings; + private readonly RetrieveSettings retrieveSettings; + + public enum Result + { + OK, + WARNING + } + + public KeePassPlugin(GenerateSettings settings) => generateSettings = settings; + public KeePassPlugin(RetrieveSettings settings) => retrieveSettings = settings; + + public Result GeneratePassword() + { + var password = KeePassGenerate.Invoke(generateSettings); + + if (string.IsNullOrEmpty(password)) + { + return Result.WARNING; + } + + ClipboardHelper.SendToClipboard(password); + return Result.OK; + } + + public Result RetrievePassword() + { + var value = KeePassRetrieve.Invoke(retrieveSettings); + + if (string.IsNullOrEmpty(value)) + { + return Result.WARNING; + } + else + { + ClipboardHelper.SendToClipboard(value); + return Result.OK; + } + } + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs new file mode 100644 index 0000000..a5027ac --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs @@ -0,0 +1,59 @@ +using KeePassLib; +using KeePassLib.Keys; +using KeePassLib.Serialization; +using StreamDeck_KeePass.Domain.Settings; +using System.Linq; + +namespace streamdeck_keepass.Domain +{ + static internal class KeePassRetrieve + { + static internal string Invoke(RetrieveSettings settings) + { + var db = OpenDB(settings); + var foundEntry = GetKeePassEntry(db, settings.EntryTitle); + + if (foundEntry == null) + { + return string.Empty; + } + + db.Close(); + + switch (settings.Field) + { + case "Password": + return foundEntry.Password; + case "Username": + return foundEntry.Username; + case "Notes": + return foundEntry.Notes; + case "URL": + return foundEntry.URL; + default: + return string.Empty; + } + } + + static private PwDatabase OpenDB(RetrieveSettings settings) + { + var conn = new IOConnectionInfo { Path = settings.DBPath }; + var compKey = new CompositeKey(); + compKey.AddUserKey(new KcpPassword(settings.Password)); + + if (!string.IsNullOrEmpty(settings.KeyFilePath)) + { + compKey.AddUserKey(new KcpKeyFile(settings.KeyFilePath)); + } + + var db = new PwDatabase(); + db.Open(conn, compKey, null); + + return db; + } + + static private KeePassEntry GetKeePassEntry(PwDatabase db, string matchingValue) => (from entry in db.RootGroup.GetEntries(true) + where entry.Strings.ReadSafe("Title") == matchingValue + select new KeePassEntry(entry)).FirstOrDefault(); + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/GenerateSettings.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/GenerateSettings.cs new file mode 100644 index 0000000..769351e --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/GenerateSettings.cs @@ -0,0 +1,60 @@ +using Newtonsoft.Json; + +namespace StreamDeck_KeePass.Domain.Settings +{ + public class GenerateSettings + { + public static GenerateSettings CreateDefaultSettings() + { + var instance = new GenerateSettings + { + Length = 20, + UseLowerCase = true, + UseUpperCase = true, + UseDigits = true, + UsePunctuation = true, + UseBrackets = true, + UseSpecial = true, + ExcludeCharacters = string.Empty, + CustomPattern = string.Empty + }; + return instance; + } + + [JsonProperty(PropertyName = "length")] + public int Length { get; set; } + + [JsonProperty(PropertyName = "useLowerCase")] + public bool UseLowerCase { get; set; } + + [JsonProperty(PropertyName = "useUpperCase")] + public bool UseUpperCase { get; set; } + + [JsonProperty(PropertyName = "useDigits")] + public bool UseDigits { get; set; } + + [JsonProperty(PropertyName = "usePunctuation")] + public bool UsePunctuation { get; set; } + + [JsonProperty(PropertyName = "useBrackets")] + public bool UseBrackets { get; set; } + + [JsonProperty(PropertyName = "useSpecial")] + public bool UseSpecial { get; set; } + + [JsonProperty(PropertyName = "excludeLookAlike")] + public bool ExcludeLookAlike { get; set; } + + [JsonProperty(PropertyName = "mustOccurAtMostOnce")] + public bool MustOccurAtMostOnce { get; set; } + + [JsonProperty(PropertyName = "excludeCharacters")] + public string ExcludeCharacters { get; set; } + + [JsonProperty(PropertyName = "customPattern")] + public string CustomPattern { get; set; } + + [JsonProperty(PropertyName = "randomlyPermute")] + public bool RandomlyPermute { get; set; } + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/RetrieveSettings.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/RetrieveSettings.cs new file mode 100644 index 0000000..af84f7d --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/RetrieveSettings.cs @@ -0,0 +1,37 @@ +using BarRaider.SdTools; +using Newtonsoft.Json; + +namespace StreamDeck_KeePass.Domain.Settings +{ + public class RetrieveSettings + { + public static RetrieveSettings CreateDefaultSettings() + { + var instance = new RetrieveSettings + { + DBPath = string.Empty, + Password = string.Empty, + KeyFilePath = string.Empty, + EntryTitle = string.Empty, + Field = string.Empty + }; + return instance; + } + + [FilenameProperty] + [JsonProperty(PropertyName = "DBPath")] + public string DBPath { get; set; } + + [JsonProperty(PropertyName = "Password")] + public string Password { get; set; } + + [JsonProperty(PropertyName = "keyFilePath")] + public string KeyFilePath { get; set; } + + [JsonProperty(PropertyName = "entryTitle")] + public string EntryTitle { get; set; } + + [JsonProperty(PropertyName = "field")] + public string Field { get; set; } + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs deleted file mode 100644 index 26f4c7b..0000000 --- a/StreamDeck-KeePass/StreamDeck-KeePass/KeePassGenerate.cs +++ /dev/null @@ -1,161 +0,0 @@ -using BarRaider.SdTools; -using KeePassLib.Cryptography.PasswordGenerator; -using KeePassLib.Security; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using streamdeck_keepass; -using System; -using System.Threading.Tasks; - -namespace StreamDeck_KeePass -{ - [PluginActionId("com.victorgrycuk.keepass.generate")] - public class KeePassGenerate : PluginBase - { - private class PluginSettings - { - public static PluginSettings CreateDefaultSettings() - { - var instance = new PluginSettings - { - Length = 20, - UseLowerCase = true, - UseUpperCase = true, - UseDigits = true, - UsePunctuation = true, - UseBrackets = true, - UseSpecial = true, - ExcludeCharacters = string.Empty, - CustomPattern = string.Empty - }; - return instance; - } - - [JsonProperty(PropertyName = "length")] - public int Length { get; set; } - - [JsonProperty(PropertyName = "useLowerCase")] - public bool UseLowerCase { get; set; } - - [JsonProperty(PropertyName = "useUpperCase")] - public bool UseUpperCase { get; set; } - - [JsonProperty(PropertyName = "useDigits")] - public bool UseDigits { get; set; } - - [JsonProperty(PropertyName = "usePunctuation")] - public bool UsePunctuation { get; set; } - - [JsonProperty(PropertyName = "useBrackets")] - public bool UseBrackets { get; set; } - - [JsonProperty(PropertyName = "useSpecial")] - public bool UseSpecial { get; set; } - - [JsonProperty(PropertyName = "excludeLookAlike")] - public bool ExcludeLookAlike { get; set; } - - [JsonProperty(PropertyName = "mustOccurAtMostOnce")] - public bool MustOccurAtMostOnce { get; set; } - - [JsonProperty(PropertyName = "excludeCharacters")] - public string ExcludeCharacters { get; set; } - - [JsonProperty(PropertyName = "customPattern")] - public string CustomPattern { get; set; } - - [JsonProperty(PropertyName = "randomlyPermute")] - public bool RandomlyPermute { get; set; } - } - - #region Private Members - - private readonly PluginSettings settings; - - #endregion - public KeePassGenerate(SDConnection connection, InitialPayload payload) : base(connection, payload) - { - if (payload.Settings == null || payload.Settings.Count == 0) - { - settings = PluginSettings.CreateDefaultSettings(); - } - else - { - settings = payload.Settings.ToObject(); - } - } - - public override void Dispose() - { - Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); - } - - public override void KeyPressed(KeyPayload payload) - { - try - { - var pw = new ProtectedString(); - var profile = new PwProfile(); - profile.CharSet = new PwCharSet(); - profile.CharSet.Clear(); - - if (settings.UseLowerCase) profile.CharSet.AddCharSet('l'); - if (settings.UseUpperCase) profile.CharSet.AddCharSet('u'); - if (settings.UseDigits) profile.CharSet.AddCharSet('d'); - if (settings.UsePunctuation) profile.CharSet.AddCharSet('p'); - if (settings.UseBrackets) profile.CharSet.AddCharSet('b'); - if (settings.UseSpecial) profile.CharSet.AddCharSet('s'); - - profile.ExcludeLookAlike = settings.ExcludeLookAlike; - profile.Length = (uint)settings.Length; - profile.NoRepeatingCharacters = settings.MustOccurAtMostOnce; - profile.ExcludeCharacters = settings.ExcludeCharacters; - - if (!string.IsNullOrEmpty(settings.CustomPattern)) - { - profile.GeneratorType = PasswordGeneratorType.Pattern; - profile.PatternPermutePassword = settings.RandomlyPermute; - profile.Pattern = settings.CustomPattern; - } - - PwGenerator.Generate(out pw, profile, null, new CustomPwGeneratorPool()); - - if (pw.IsEmpty) - { - Connection.ShowAlert().Wait(); - Logger.Instance.LogMessage(TracingLevel.WARN, "No password was generated with the given configuration"); - return; - } - - Connection.ShowOk().Wait(); - - ClipboardHelper.SendToClipboard(pw.ReadString()); - } - catch (Exception ex) - { - Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message); - } - } - - public override void KeyReleased(KeyPayload payload) { } - - public override void OnTick() { } - - public override void ReceivedSettings(ReceivedSettingsPayload payload) - { - Tools.AutoPopulateSettings(settings, payload.Settings); - SaveSettings(); - } - - public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } - - #region Private Methods - - private Task SaveSettings() - { - return Connection.SetSettingsAsync(JObject.FromObject(settings)); - } - - #endregion - } -} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/KeePassRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/KeePassRetrieve.cs deleted file mode 100644 index ac24cd7..0000000 --- a/StreamDeck-KeePass/StreamDeck-KeePass/KeePassRetrieve.cs +++ /dev/null @@ -1,156 +0,0 @@ -using BarRaider.SdTools; -using KeePassLib.Keys; -using KeePassLib.Serialization; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using streamdeck_keepass; -using System; -using System.Linq; -using System.Threading.Tasks; - -namespace StreamDeck_KeePass -{ - [PluginActionId("com.victorgrycuk.keepass.retrieve")] - public class KeePassRetrieve : PluginBase - { - private class PluginSettings - { - public static PluginSettings CreateDefaultSettings() - { - var instance = new PluginSettings - { - DBPath = string.Empty, - Password = string.Empty, - KeyFilePath = string.Empty, - EntryTitle = string.Empty, - Field = string.Empty - }; - return instance; - } - - [FilenameProperty] - [JsonProperty(PropertyName = "DBPath")] - public string DBPath { get; set; } - - [JsonProperty(PropertyName = "Password")] - public string Password { get; set; } - - [JsonProperty(PropertyName = "keyFilePath")] - public string KeyFilePath { get; set; } - - [JsonProperty(PropertyName = "entryTitle")] - public string EntryTitle { get; set; } - - [JsonProperty(PropertyName = "field")] - public string Field { get; set; } - } - - #region Private Members - - private readonly PluginSettings settings; - - #endregion - public KeePassRetrieve(SDConnection connection, InitialPayload payload) : base(connection, payload) - { - if (payload.Settings == null || payload.Settings.Count == 0) - { - settings = PluginSettings.CreateDefaultSettings(); - } - else - { - settings = payload.Settings.ToObject(); - } - } - - public override void Dispose() - { - Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); - } - - public override void KeyPressed(KeyPayload payload) - { - try - { - var conn = new IOConnectionInfo { Path = settings.DBPath }; - var compKey = new CompositeKey(); - compKey.AddUserKey(new KcpPassword(settings.Password)); - if (!string.IsNullOrEmpty(settings.KeyFilePath)) - { - compKey.AddUserKey(new KcpKeyFile(settings.KeyFilePath)); - } - var db = new KeePassLib.PwDatabase(); - db.Open(conn, compKey, null); - var entryList = from entry in db.RootGroup.GetEntries(true) - select new - { - Group = entry.ParentGroup.Name, - Title = entry.Strings.ReadSafe("Title"), - Username = entry.Strings.ReadSafe("UserName"), - Password = entry.Strings.ReadSafe("Password"), - URL = entry.Strings.ReadSafe("URL"), - Notes = entry.Strings.ReadSafe("Notes") - - }; - - if (entryList.Count() == 0) - { - Connection.ShowAlert().Wait(); - Logger.Instance.LogMessage(TracingLevel.WARN, $"No entry found for the title '{ settings.EntryTitle }'."); - db.Close(); - - return; - } - - var firstEntry = entryList.Where(x => x.Title == settings.EntryTitle).FirstOrDefault(); - switch (settings.Field) - { - case "Password": - ClipboardHelper.SendToClipboard(firstEntry.Password); - break; - case "Username": - ClipboardHelper.SendToClipboard(firstEntry.Username); - break; - case "Notes": - ClipboardHelper.SendToClipboard(firstEntry.Notes); - break; - case "URL": - ClipboardHelper.SendToClipboard(firstEntry.URL); - break; - default: - Logger.Instance.LogMessage(TracingLevel.WARN, $"No field found with the name '{ settings.Field }'."); - break; - } - - Connection.ShowOk().Wait(); - - db.Close(); - } - catch (Exception ex) - { - Connection.ShowAlert(); - Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message); - } - } - - public override void KeyReleased(KeyPayload payload) { } - - public override void OnTick() { } - - public override void ReceivedSettings(ReceivedSettingsPayload payload) - { - Tools.AutoPopulateSettings(settings, payload.Settings); - SaveSettings(); - } - - public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } - - #region Private Methods - - private Task SaveSettings() - { - return Connection.SetSettingsAsync(JObject.FromObject(settings)); - } - - #endregion - } -} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ClipboardHelper.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Services/ClipboardHelper.cs similarity index 92% rename from StreamDeck-KeePass/StreamDeck-KeePass/ClipboardHelper.cs rename to StreamDeck-KeePass/StreamDeck-KeePass/Services/ClipboardHelper.cs index 002859f..04307ef 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/ClipboardHelper.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Services/ClipboardHelper.cs @@ -1,6 +1,6 @@ using System.Threading; -namespace streamdeck_keepass +namespace streamdeck_keepass.Services { public static class ClipboardHelper { diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj index 772cfbd..6e9720b 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj +++ b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj @@ -93,9 +93,15 @@ - - - + + + + + + + + + @@ -187,6 +193,7 @@ false + $(ProjectDir)\..\..\Tools\DistributionTool.exe -b -i $(ProjectDir)\$(OutDir) -o $(ProjectDir)\$(OutDir) From 1df7b597c3fcd69b87a9e385784c8b8dd8002870 Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Tue, 18 Jan 2022 22:44:50 -0300 Subject: [PATCH 03/10] Further refactoring --- .../StreamDeck-KeePass/ActionGenerate.cs | 4 +- .../StreamDeck-KeePass/ActionRetrieve.cs | 4 +- .../Domain/IKeePassAction.cs | 7 ++++ .../Domain/KeePassGenerate.cs | 8 +++- .../Domain/KeePassPlugin.cs | 38 ++++++------------- .../Domain/KeePassRetrieve.cs | 8 +++- .../StreamDeck-KeePass.csproj | 1 + 7 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/IKeePassAction.cs diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs index 4bcdde6..657eb36 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs @@ -31,9 +31,9 @@ public override void KeyPressed(KeyPayload payload) { try { - var result = plugin.GeneratePassword(); + var result = plugin.Invoke(); - if (result == KeePassPlugin.Result.WARNING) + if (result == Result.WARNING) { Connection.ShowAlert().Wait(); Logger.Instance.LogMessage(TracingLevel.WARN, "No password was generated with the given configuration"); diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs index 5c3b303..3e41323 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs @@ -32,9 +32,9 @@ public override void KeyPressed(KeyPayload payload) { try { - var result = plugin.RetrievePassword(); + var result = plugin.Invoke(); - if (result == KeePassPlugin.Result.WARNING) + if (result == Result.WARNING) { Connection.ShowAlert().Wait(); Logger.Instance.LogMessage(TracingLevel.WARN, "No password was generated with the given configuration"); diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/IKeePassAction.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/IKeePassAction.cs new file mode 100644 index 0000000..5b1cdb9 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/IKeePassAction.cs @@ -0,0 +1,7 @@ +namespace streamdeck_keepass.Domain +{ + internal interface IKeePassAction + { + string Invoke(); + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassGenerate.cs index fd9d3e5..2c0a17e 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassGenerate.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassGenerate.cs @@ -4,9 +4,13 @@ namespace streamdeck_keepass.Domain { - static internal class KeePassGenerate + internal class KeePassGenerate : IKeePassAction { - static internal string Invoke(GenerateSettings settings) + private readonly GenerateSettings settings; + + public KeePassGenerate(object objectSettings) => settings = objectSettings as GenerateSettings; + + public string Invoke() { var profile = new PwProfile { CharSet = new PwCharSet() }; profile.CharSet.Clear(); diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs index 29f37da..a3bb9e7 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs @@ -3,23 +3,22 @@ namespace streamdeck_keepass.Domain { - public class KeePassPlugin + public enum Result { - private readonly GenerateSettings generateSettings; - private readonly RetrieveSettings retrieveSettings; + OK, + WARNING + } - public enum Result - { - OK, - WARNING - } + public class KeePassPlugin + { + internal readonly IKeePassAction action; - public KeePassPlugin(GenerateSettings settings) => generateSettings = settings; - public KeePassPlugin(RetrieveSettings settings) => retrieveSettings = settings; + public KeePassPlugin(GenerateSettings settings) => action = new KeePassGenerate(settings); + public KeePassPlugin(RetrieveSettings settings) => action = new KeePassRetrieve(settings); - public Result GeneratePassword() + public Result Invoke() { - var password = KeePassGenerate.Invoke(generateSettings); + var password = action.Invoke(); if (string.IsNullOrEmpty(password)) { @@ -29,20 +28,5 @@ public Result GeneratePassword() ClipboardHelper.SendToClipboard(password); return Result.OK; } - - public Result RetrievePassword() - { - var value = KeePassRetrieve.Invoke(retrieveSettings); - - if (string.IsNullOrEmpty(value)) - { - return Result.WARNING; - } - else - { - ClipboardHelper.SendToClipboard(value); - return Result.OK; - } - } } } diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs index a5027ac..c768af0 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs @@ -6,9 +6,13 @@ namespace streamdeck_keepass.Domain { - static internal class KeePassRetrieve + internal class KeePassRetrieve : IKeePassAction { - static internal string Invoke(RetrieveSettings settings) + private readonly RetrieveSettings settings; + + public KeePassRetrieve(object objectSettings) => settings = objectSettings as RetrieveSettings; + + public string Invoke() { var db = OpenDB(settings); var foundEntry = GetKeePassEntry(db, settings.EntryTitle); diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj index 6e9720b..a4f0e2a 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj +++ b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj @@ -93,6 +93,7 @@ + From 904fe1bad22f632a3d7f7c0cf966d73a69bf3f62 Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Tue, 18 Jan 2022 23:49:20 -0300 Subject: [PATCH 04/10] Implement optional clipboard clear time --- .../StreamDeck-KeePass/ActionGenerate.cs | 3 ++- .../StreamDeck-KeePass/ActionRetrieve.cs | 3 ++- .../Domain/KeePassPlugin.cs | 17 ++++++++++--- .../Domain/Settings/GenerateSettings.cs | 6 ++++- .../Domain/Settings/RetrieveSettings.cs | 3 +++ .../PropertyInspector/KeePassGeneratePI.html | 4 +++ .../PropertyInspector/KeePassRetrievePI.html | 12 ++++++--- .../Services/ClipboardHelper.cs | 25 +++++++++++++------ 8 files changed, 56 insertions(+), 17 deletions(-) diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs index 657eb36..efdc380 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs @@ -10,7 +10,7 @@ namespace StreamDeck_KeePass [PluginActionId("com.victorgrycuk.keepass.generate")] public class ActionGenerate : PluginBase { - private readonly KeePassPlugin plugin; + private KeePassPlugin plugin; private readonly GenerateSettings settings; public ActionGenerate(SDConnection connection, InitialPayload payload) : base(connection, payload) @@ -58,6 +58,7 @@ public override void ReceivedSettings(ReceivedSettingsPayload payload) { Tools.AutoPopulateSettings(settings, payload.Settings); SaveSettings(); + plugin = new KeePassPlugin(settings); } public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs index 3e41323..6dfee5d 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs @@ -11,7 +11,7 @@ namespace StreamDeck_KeePass public partial class ActionRetrieve : PluginBase { - private readonly KeePassPlugin plugin; + private KeePassPlugin plugin; private readonly RetrieveSettings settings; public ActionRetrieve(SDConnection connection, InitialPayload payload) : base(connection, payload) @@ -60,6 +60,7 @@ public override void ReceivedSettings(ReceivedSettingsPayload payload) { Tools.AutoPopulateSettings(settings, payload.Settings); SaveSettings(); + plugin = new KeePassPlugin(settings); } public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs index a3bb9e7..307283a 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs @@ -12,9 +12,19 @@ public enum Result public class KeePassPlugin { internal readonly IKeePassAction action; + internal readonly int clearDelay; - public KeePassPlugin(GenerateSettings settings) => action = new KeePassGenerate(settings); - public KeePassPlugin(RetrieveSettings settings) => action = new KeePassRetrieve(settings); + public KeePassPlugin(GenerateSettings settings) + { + action = new KeePassGenerate(settings); + clearDelay = settings.ClearTime; + } + + public KeePassPlugin(RetrieveSettings settings) + { + action = new KeePassRetrieve(settings); + clearDelay = settings.ClearTime; + } public Result Invoke() { @@ -25,7 +35,8 @@ public Result Invoke() return Result.WARNING; } - ClipboardHelper.SendToClipboard(password); + ClipboardHelper.SendToClipboard(password, clearDelay); + return Result.OK; } } diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/GenerateSettings.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/GenerateSettings.cs index 769351e..04d0121 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/GenerateSettings.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/GenerateSettings.cs @@ -16,7 +16,8 @@ public static GenerateSettings CreateDefaultSettings() UseBrackets = true, UseSpecial = true, ExcludeCharacters = string.Empty, - CustomPattern = string.Empty + CustomPattern = string.Empty, + ClearTime = 0 }; return instance; } @@ -56,5 +57,8 @@ public static GenerateSettings CreateDefaultSettings() [JsonProperty(PropertyName = "randomlyPermute")] public bool RandomlyPermute { get; set; } + + [JsonProperty(PropertyName = "clearTime")] + public int ClearTime { get; set; } } } \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/RetrieveSettings.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/RetrieveSettings.cs index af84f7d..c9f44fb 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/RetrieveSettings.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/RetrieveSettings.cs @@ -33,5 +33,8 @@ public static RetrieveSettings CreateDefaultSettings() [JsonProperty(PropertyName = "field")] public string Field { get; set; } + + [JsonProperty(PropertyName = "clearTime")] + public int ClearTime { get; set; } } } \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassGeneratePI.html b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassGeneratePI.html index e1867b1..0bde875 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassGeneratePI.html +++ b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassGeneratePI.html @@ -64,6 +64,10 @@
Custom Pattern
+
+
Clear Time
+ +
diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html index 30c9777..0188d32 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html +++ b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html @@ -30,12 +30,16 @@
Select field to retrieve
+
+
Clear Time
+ +
diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Services/ClipboardHelper.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Services/ClipboardHelper.cs index 04307ef..172c7b2 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Services/ClipboardHelper.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Services/ClipboardHelper.cs @@ -1,20 +1,31 @@ using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; namespace streamdeck_keepass.Services { public static class ClipboardHelper { - internal static void SendToClipboard(string text) + internal static void SendToClipboard(string text, int clearDelay) { - var thread = new Thread(() => ClipboardThread(text)); - thread.SetApartmentState(ApartmentState.STA); - thread.IsBackground = false; - thread.Start(); + ExecuteThread(new Thread(() => Clipboard.SetText(text))); + if (clearDelay > 0) ClearClipboard(clearDelay); } - private static void ClipboardThread(string text) + private static void ClearClipboard(int delay) { - System.Windows.Forms.Clipboard.SetText(text); + Task.Factory.StartNew(() => + { + Thread.Sleep(delay * 1000); + ExecuteThread(new Thread(() => Clipboard.Clear())); + }); + } + + private static void ExecuteThread(Thread thread) + { + thread.SetApartmentState(ApartmentState.STA); + thread.IsBackground = false; + thread.Start(); } } } From da53169a7a793812715f9bdc45d2176541df2fcb Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Wed, 19 Jan 2022 22:49:01 -0300 Subject: [PATCH 05/10] Add support to retrieve by UUID --- StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs | 2 +- StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs index 6dfee5d..5878969 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs @@ -37,7 +37,7 @@ public override void KeyPressed(KeyPayload payload) if (result == Result.WARNING) { Connection.ShowAlert().Wait(); - Logger.Instance.LogMessage(TracingLevel.WARN, "No password was generated with the given configuration"); + Logger.Instance.LogMessage(TracingLevel.WARN, "No entry was found"); return; } else diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs index c768af0..2e82d53 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassRetrieve.cs @@ -57,7 +57,7 @@ static private PwDatabase OpenDB(RetrieveSettings settings) } static private KeePassEntry GetKeePassEntry(PwDatabase db, string matchingValue) => (from entry in db.RootGroup.GetEntries(true) - where entry.Strings.ReadSafe("Title") == matchingValue + where entry.Strings.ReadSafe("Title") == matchingValue || entry.Uuid.ToHexString() == matchingValue select new KeePassEntry(entry)).FirstOrDefault(); } } From e112a8c10cbcbc301657d9637a34708ce3a5ddb8 Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Thu, 20 Jan 2022 00:14:08 -0300 Subject: [PATCH 06/10] More refactoring --- .../StreamDeck-KeePass/ActionGenerate.cs | 75 ------------------ .../StreamDeck-KeePass/ActionRetrieve.cs | 77 ------------------- .../StreamDeck-KeePass/Actions/ActionBase.cs | 51 ++++++++++++ .../Actions/ActionGenerate.cs | 28 +++++++ .../Actions/ActionRetrieve.cs | 28 +++++++ .../PropertyInspector/KeePassRetrievePI.html | 4 +- .../StreamDeck-KeePass.csproj | 5 +- 7 files changed, 112 insertions(+), 156 deletions(-) delete mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs delete mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionGenerate.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionRetrieve.cs diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs deleted file mode 100644 index efdc380..0000000 --- a/StreamDeck-KeePass/StreamDeck-KeePass/ActionGenerate.cs +++ /dev/null @@ -1,75 +0,0 @@ -using BarRaider.SdTools; -using Newtonsoft.Json.Linq; -using streamdeck_keepass.Domain; -using StreamDeck_KeePass.Domain.Settings; -using System; -using System.Threading.Tasks; - -namespace StreamDeck_KeePass -{ - [PluginActionId("com.victorgrycuk.keepass.generate")] - public class ActionGenerate : PluginBase - { - private KeePassPlugin plugin; - private readonly GenerateSettings settings; - - public ActionGenerate(SDConnection connection, InitialPayload payload) : base(connection, payload) - { - settings = payload.Settings == null || payload.Settings.Count == 0 - ? GenerateSettings.CreateDefaultSettings() - : payload.Settings.ToObject(); - - plugin = new KeePassPlugin(settings); - } - - public override void Dispose() - { - Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); - } - - public override void KeyPressed(KeyPayload payload) - { - try - { - var result = plugin.Invoke(); - - if (result == Result.WARNING) - { - Connection.ShowAlert().Wait(); - Logger.Instance.LogMessage(TracingLevel.WARN, "No password was generated with the given configuration"); - return; - } - else - { - Connection.ShowOk().Wait(); - } - } - catch (Exception ex) - { - Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message); - } - } - - public override void KeyReleased(KeyPayload payload) { } - - public override void OnTick() { } - - public override void ReceivedSettings(ReceivedSettingsPayload payload) - { - Tools.AutoPopulateSettings(settings, payload.Settings); - SaveSettings(); - plugin = new KeePassPlugin(settings); - } - - public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } - - #region Private Methods - - private Task SaveSettings() - { - return Connection.SetSettingsAsync(JObject.FromObject(settings)); - } - - #endregion - } -} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs deleted file mode 100644 index 5878969..0000000 --- a/StreamDeck-KeePass/StreamDeck-KeePass/ActionRetrieve.cs +++ /dev/null @@ -1,77 +0,0 @@ -using BarRaider.SdTools; -using Newtonsoft.Json.Linq; -using streamdeck_keepass.Domain; -using StreamDeck_KeePass.Domain.Settings; -using System; -using System.Threading.Tasks; - -namespace StreamDeck_KeePass -{ - [PluginActionId("com.victorgrycuk.keepass.retrieve")] - public partial class ActionRetrieve : PluginBase - { - - private KeePassPlugin plugin; - private readonly RetrieveSettings settings; - - public ActionRetrieve(SDConnection connection, InitialPayload payload) : base(connection, payload) - { - settings = payload.Settings == null || payload.Settings.Count == 0 - ? RetrieveSettings.CreateDefaultSettings() - : payload.Settings.ToObject(); - - plugin = new KeePassPlugin(settings); - } - - public override void Dispose() - { - Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); - } - - public override void KeyPressed(KeyPayload payload) - { - try - { - var result = plugin.Invoke(); - - if (result == Result.WARNING) - { - Connection.ShowAlert().Wait(); - Logger.Instance.LogMessage(TracingLevel.WARN, "No entry was found"); - return; - } - else - { - Connection.ShowOk().Wait(); - } - } - catch (Exception ex) - { - Connection.ShowAlert(); - Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message); - } - } - - public override void KeyReleased(KeyPayload payload) { } - - public override void OnTick() { } - - public override void ReceivedSettings(ReceivedSettingsPayload payload) - { - Tools.AutoPopulateSettings(settings, payload.Settings); - SaveSettings(); - plugin = new KeePassPlugin(settings); - } - - public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } - - #region Private Methods - - private Task SaveSettings() - { - return Connection.SetSettingsAsync(JObject.FromObject(settings)); - } - - #endregion - } -} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs new file mode 100644 index 0000000..6b38bc2 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs @@ -0,0 +1,51 @@ +using BarRaider.SdTools; +using Newtonsoft.Json.Linq; +using streamdeck_keepass.Domain; +using StreamDeck_KeePass.Domain.Settings; +using System.Threading.Tasks; + +namespace streamdeck_keepass.Actions +{ + abstract public class ActionBase : PluginBase + { + private KeePassPlugin plugin; + + public ActionBase(SDConnection connection, InitialPayload payload) : base(connection, payload) { } + + internal void CreatePlugin(GenerateSettings settings) => plugin = new KeePassPlugin(settings); + + internal void CreatePlugin(RetrieveSettings settings) => plugin = new KeePassPlugin(settings); + + public override void Dispose() => Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); + + public void ExecuteAction(string logMessage) + { + var result = plugin.Invoke(); + + if (result == Result.WARNING) + { + Connection.ShowAlert().Wait(); + Logger.Instance.LogMessage(TracingLevel.WARN, logMessage); + } + else + { + Connection.ShowOk().Wait(); + } + } + + public override void KeyReleased(KeyPayload payload) { } + + public override void OnTick() { } + + public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { } + + internal T ResolveSettings(InitialPayload payload, object defaultConfig) where T : class + { + return payload.Settings == null || payload.Settings.Count == 0 + ? defaultConfig as T + : payload.Settings.ToObject(); + } + + internal Task SaveSettings(JObject settings) => Connection.SetSettingsAsync(settings); + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionGenerate.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionGenerate.cs new file mode 100644 index 0000000..c331602 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionGenerate.cs @@ -0,0 +1,28 @@ +using BarRaider.SdTools; +using Newtonsoft.Json.Linq; +using streamdeck_keepass.Actions; +using StreamDeck_KeePass.Domain.Settings; + +namespace StreamDeck_KeePass.Actions +{ + [PluginActionId("com.victorgrycuk.keepass.generate")] + public class ActionGenerate : ActionBase + { + private readonly GenerateSettings settings; + + public ActionGenerate(SDConnection connection, InitialPayload payload) : base(connection, payload) + { + settings = ResolveSettings(payload, GenerateSettings.CreateDefaultSettings()); + CreatePlugin(settings); + } + + public override void KeyPressed(KeyPayload payload) => ExecuteAction("No password was generated with the given configuration."); + + public override void ReceivedSettings(ReceivedSettingsPayload payload) + { + Tools.AutoPopulateSettings(settings, payload.Settings); + SaveSettings(JObject.FromObject(settings)); + CreatePlugin(settings); + } + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionRetrieve.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionRetrieve.cs new file mode 100644 index 0000000..611a34f --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionRetrieve.cs @@ -0,0 +1,28 @@ +using BarRaider.SdTools; +using Newtonsoft.Json.Linq; +using streamdeck_keepass.Actions; +using StreamDeck_KeePass.Domain.Settings; + +namespace StreamDeck_KeePass.Actions +{ + [PluginActionId("com.victorgrycuk.keepass.retrieve")] + public class ActionRetrieve : ActionBase + { + private readonly RetrieveSettings settings; + + public ActionRetrieve(SDConnection connection, InitialPayload payload) : base(connection, payload) + { + settings = ResolveSettings(payload, RetrieveSettings.CreateDefaultSettings()); + CreatePlugin(settings); + } + + public override void KeyPressed(KeyPayload payload) => ExecuteAction("Entry not found."); + + public override void ReceivedSettings(ReceivedSettingsPayload payload) + { + Tools.AutoPopulateSettings(settings, payload.Settings); + SaveSettings(JObject.FromObject(settings)); + CreatePlugin(settings); + } + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html index 0188d32..601381e 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html +++ b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html @@ -24,8 +24,8 @@
-
Entry Name
- +
Entry Name or UUID
+
Select field to retrieve
diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj index a4f0e2a..d968368 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj +++ b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj @@ -93,6 +93,7 @@ + @@ -101,8 +102,8 @@ - - + + From d4a59f14a59a4e9d3344b678f7c9c555a9e6fd95 Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Fri, 21 Jan 2022 00:06:24 -0300 Subject: [PATCH 07/10] Add new Aware action, update readme --- .../StreamDeck-KeePass/Actions/ActionAware.cs | 28 +++++++ .../StreamDeck-KeePass/Actions/ActionBase.cs | 2 + .../StreamDeck-KeePass/Domain/KeePassAware.cs | 76 ++++++++++++++++++ .../Domain/KeePassPlugin.cs | 6 ++ .../Domain/Settings/AwareSettings.cs | 40 +++++++++ .../StreamDeck-KeePass/Images/aware.png | Bin 0 -> 636 bytes .../StreamDeck-KeePass/Images/aware@2x.png | Bin 0 -> 1284 bytes .../Images/keepassAware.png | Bin 0 -> 2602 bytes .../Images/keepassAware@2x.png | Bin 0 -> 5073 bytes .../PropertyInspector/KeePassAwarePI.html | 48 +++++++++++ .../PropertyInspector/KeePassRetrievePI.html | 2 +- .../Services/ProcessHelper.cs | 25 ++++++ .../StreamDeck-KeePass.csproj | 21 ++++- .../StreamDeck-KeePass/manifest.json | 15 ++++ 14 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionAware.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassAware.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/AwareSettings.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Images/aware.png create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Images/aware@2x.png create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Images/keepassAware.png create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Images/keepassAware@2x.png create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassAwarePI.html create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Services/ProcessHelper.cs diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionAware.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionAware.cs new file mode 100644 index 0000000..f5237ac --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionAware.cs @@ -0,0 +1,28 @@ +using BarRaider.SdTools; +using Newtonsoft.Json.Linq; +using streamdeck_keepass.Actions; +using StreamDeck_KeePass.Domain.Settings; + +namespace StreamDeck_KeePass.Actions +{ + [PluginActionId("com.victorgrycuk.keepass.aware")] + public class ActionAware : ActionBase + { + private readonly AwareSettings settings; + + public ActionAware(SDConnection connection, InitialPayload payload) : base(connection, payload) + { + settings = ResolveSettings(payload, AwareSettings.CreateDefaultSettings()); + CreatePlugin(settings); + } + + public override void KeyPressed(KeyPayload payload) => ExecuteAction("Entry not found."); + + public override void ReceivedSettings(ReceivedSettingsPayload payload) + { + Tools.AutoPopulateSettings(settings, payload.Settings); + SaveSettings(JObject.FromObject(settings)); + CreatePlugin(settings); + } + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs index 6b38bc2..c9a88e0 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs @@ -16,6 +16,8 @@ public ActionBase(SDConnection connection, InitialPayload payload) : base(connec internal void CreatePlugin(RetrieveSettings settings) => plugin = new KeePassPlugin(settings); + internal void CreatePlugin(AwareSettings settings) => plugin = new KeePassPlugin(settings); + public override void Dispose() => Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); public void ExecuteAction(string logMessage) diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassAware.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassAware.cs new file mode 100644 index 0000000..ee27a7e --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassAware.cs @@ -0,0 +1,76 @@ +using KeePassLib; +using KeePassLib.Keys; +using KeePassLib.Serialization; +using streamdeck_keepass.Services; +using StreamDeck_KeePass.Domain.Settings; +using System.Collections.Generic; +using System.Linq; + +namespace streamdeck_keepass.Domain +{ + internal class KeePassAware : IKeePassAction + { + private readonly AwareSettings settings; + + public KeePassAware(object objectSettings) => settings = objectSettings as AwareSettings; + + public string Invoke() + { + var db = OpenDB(settings); + var mapping = GetMapping(settings.ProcessMapping); + if (!mapping.TryGetValue(ProcessHelper.GetActiveProcessFileName(), out string entryId)) return string.Empty; + var foundEntry = GetKeePassEntry(db, entryId); + + if (foundEntry == null) + { + return string.Empty; + } + + db.Close(); + + switch (settings.Field) + { + case "Password": + return foundEntry.Password; + case "Username": + return foundEntry.Username; + case "Notes": + return foundEntry.Notes; + case "URL": + return foundEntry.URL; + default: + return string.Empty; + } + } + + static private PwDatabase OpenDB(AwareSettings settings) + { + var conn = new IOConnectionInfo { Path = settings.DBPath }; + var compKey = new CompositeKey(); + compKey.AddUserKey(new KcpPassword(settings.Password)); + + if (!string.IsNullOrEmpty(settings.KeyFilePath)) + { + compKey.AddUserKey(new KcpKeyFile(settings.KeyFilePath)); + } + + var db = new PwDatabase(); + db.Open(conn, compKey, null); + + return db; + } + + private Dictionary GetMapping(string entries) + { + var dictionary = new Dictionary(); + var lines = entries.Split('\n').ToList(); + lines.ForEach(l => dictionary.Add(l.Split('=')[0], l.Split('=')[1])); + + return dictionary; + } + + static private KeePassEntry GetKeePassEntry(PwDatabase db, string matchingValue) => (from entry in db.RootGroup.GetEntries(true) + where entry.Strings.ReadSafe("Title") == matchingValue || entry.Uuid.ToHexString() == matchingValue + select new KeePassEntry(entry)).FirstOrDefault(); + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs index 307283a..d8ae965 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs @@ -26,6 +26,12 @@ public KeePassPlugin(RetrieveSettings settings) clearDelay = settings.ClearTime; } + public KeePassPlugin(AwareSettings settings) + { + action = new KeePassAware(settings); + clearDelay = settings.ClearTime; + } + public Result Invoke() { var password = action.Invoke(); diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/AwareSettings.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/AwareSettings.cs new file mode 100644 index 0000000..ebee35e --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/AwareSettings.cs @@ -0,0 +1,40 @@ +using BarRaider.SdTools; +using Newtonsoft.Json; + +namespace StreamDeck_KeePass.Domain.Settings +{ + public class AwareSettings + { + public static AwareSettings CreateDefaultSettings() + { + var instance = new AwareSettings + { + DBPath = string.Empty, + Password = string.Empty, + KeyFilePath = string.Empty, + ProcessMapping = string.Empty, + Field = string.Empty + }; + return instance; + } + + [FilenameProperty] + [JsonProperty(PropertyName = "DBPath")] + public string DBPath { get; set; } + + [JsonProperty(PropertyName = "Password")] + public string Password { get; set; } + + [JsonProperty(PropertyName = "keyFilePath")] + public string KeyFilePath { get; set; } + + [JsonProperty(PropertyName = "processMapping")] + public string ProcessMapping { get; set; } + + [JsonProperty(PropertyName = "field")] + public string Field { get; set; } + + [JsonProperty(PropertyName = "clearTime")] + public int ClearTime { get; set; } + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Images/aware.png b/StreamDeck-KeePass/StreamDeck-KeePass/Images/aware.png new file mode 100644 index 0000000000000000000000000000000000000000..6e9bd1c2fcdb6bcd3b383cd7e00c1a3ad97160d1 GIT binary patch literal 636 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 M07*qoM6N<$f&;$DegFUf literal 0 HcmV?d00001 diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Images/keepassAware@2x.png b/StreamDeck-KeePass/StreamDeck-KeePass/Images/keepassAware@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b7f8a87447a557cf2cf11a557dcc9259a0df3420 GIT binary patch literal 5073 zcmV;?6E5tDP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRa4S4l)cRCwC#oq3d0)t$#bUEMSd3drJdAcAaC2!c)mP7LCLqDB)C851-yaWr!T zM{&tGBj#vg4k43CqGO0+q7IsvL``%6mqY~w2?-7{5dx+kj*5V`F#^LM~eKu_QZpbqE) zRO{#3fmUE2uou_`>;(P_Yyq|bZ|dLg0L@96(3%QINnoVzI>kf_unAZVEC+t4JC!9+iC`FT9xxR+ zMMY65qY-!+cp7*Xc*7E?@aO}a4_peI2^?9b^S>8Z0Xzmg1MIK_iWg&nF9DxZ<+qZs z4fqxC5U|b?C|XPct_3bA0iC80I@7bjy}%2WK>6W(;3i;l4A*W`k?}V*y|)7&0w1Uu z-lA4j#{91Zx&i%E&+4l#fxh~uHimm#3f!fHvIGi%(}6ikpeWD`IKT$r&%kTI|0!8^ z00+X(AJAI~Gz=J}?t(FD0Ui<2{XY-P16EoBnQ=Vub>K2xoP5N<1~r>kDQPwX9R+-r zL5L4(B5;QOJ0J1e0sI7*tK_!?%0gEaRX6J|It=!yk7bc={q+SVj2A`%XREtm0^yyR zJAv;4cV>y$L=)&!!1ocyUl{xm_!;mN;sGuP3xgEg6zyqoXR}#{|SAZ+j z(hGt$z)XtZKPm=+u2lKmE5K(Ofd_#f0B=*-7zoT(G94A*bGuZJe6Wx=n=0UU)dF|x z1NtS;0UiGd;HwEB55QIx>*I8%^(&rx>iGE-(Aiq39cTdXQ^cd}7cZ)g6q%BkPNyS( zFvoEUVPwn&&I&kpUj*K*1Okl#eyK9v54J0D77*US7dvqZOtdQ1alRQqKiY)E4A+%2 zfhMboeYDTHlq-26ApTmNyI=XVfPV_iDD@raVkEoH4|(PRUrW-C6XR|)*XLZe0G9wuN|8Wk zBk`zi9^={&N7;g;lO|#!%|slnU3}<7Q-EcqM4%JZ_t4MB&3^%jm|NmRPoj&|>h&^Q zwj;UZ8%lvd{gK4*5gy|jfzJcaS<=Kxr1Mmb@bdO=QW7;3Q;Dtxe&K^WyY$y#$rHcW zeop6lm&dpfz|YAu6*pf3eNQa`FR^ur?ot+ou{2lcoHu!lJ5$%NC?f2ikbE2yTJ=E| z$Na0aqAfS3B4H#i#rjIbr&KTkjY2Zwybkou1b$@6Q&cj|^kMPt22KSw7D9y8>dxau zo_RsYV-Xwf)3q?62a+}uSRV?r1AQB~#beBqNG!~Ar*Ryo4!9ceV2>ucqcD|2!jNJiT?qQi# z>l)X^L7QLfp7Xgjp0u zgpnoo*Qw&{hKYz1GSCimqmP|pi(R|2$7bY6vmzUd#9B{L!4BUy-hjhaf zTtXmj1iA`yWOgA1ICpJPFua2~AE*}iXTJpMg&YiYLo)$SR9KV+7GQ1?GlLv?*0~7u z8KfbJ8x~PQMIJ38!|Rw&%k)R;bRULXk#(=QN*tzgdpe!2fr6AvDQWo0%2ZE&99Ha) zJ*3a&$RP^X9cVC8quCAX+{`(PiokD?_Ec^-1L?KqN}vlcA4>ZPX3wQXd7}-pW3hW@ zG1i$tQ$3XD|FLsi@mPep;_Fm50`rnT;=T=@urOi|YsVl0zpQF2&{913;A*_{bggSqJU2CVNVN!Wz>kl_ThqjiQr zLy%56ZdgVH6;rML6E7m1-vdaeBR7mdTs{X0bTa1H*GqPJ5(m?ocLn}Fn?U0YgPSO$ z9-bDF;Z@9M$i`8tNr3oOxS$9#C=m=xwd?K`5n6C1`T zTbMY|JB7Kj!wx%tiHE5SOpg@iqL$n3{3RYA7~VS~g}K9Tvz@=hoAP@M@71L+N8wxS zawH!64exbHp@~5uK5UT;m>h}KHFkaqj$?qaNNJogXkwO{%j+D+c@0UW*ydqgp9$QJ zM#UY+DT<|AgZZ3SSG(SkVLVcie=6>c`7YDH8<8x~9{?*|#;!z4{N4}gZpmwqswe$?e5M!De|7~@qjHR4C;AVvPD#W7(Zs_x9Ex zy`oGvZV?>Qkv2Y_6r@W0 zY7P$-H3Dma?*RV*eAi&u{Fne8b@D*9a=;DmrI74qFHCSz zoacMEO8nq1m)9?h*?2k8@LqFf2WsF@x0_tBT?PH&Y!@^Au?Vic+(lAMQqdU~Oay8G z8dA!n*9`;5T1(6mDVND!Pc%t+dtJoX0D|`l3-U~34exJ4J<%Z1UpI`vd~(A=OzR_a zyuK~M@5p8B9O3f4QDC61y&Kk(wX>`>4D61%_=1JZV=iTLUxeSW&&Beqj_H|B#vBX% z-)sWCiaDryy5&eoxCsgg)0*$kNUaQk-ty3cCRshGB+)@U-6B)E<|h4Tb2fq65!bp& z8y_C#P7)Fat12>yqQ(f!?wi%hnZtIKWgbf6Wc!0R5-3-Rc%Sn8=$)-;v3f zGYJk>?9EpERv~RH-D*W&4BTV6k`sG?Z*X|(Lke@j?x1)!$BxsA*@qVv(+%%6W=pGV z0=*U!_;#GyFB^5!6_OYL6r+$CRC^G`>rgREWG)8cZt3BR-8v+hK%`y`8-iMf`;^Jks`W)f}us1U#Unh?I2D*asNGglo*$Rf=3+VT{s zBUA}@(|;O}OvqhcJ5VEX5bj2o3w1+MEpN(m@_*KeKo?@pjw}|g1Ab^wIRBC0T^v)0 z-|c};uXjQ6osY)5GF(-T>)n~hbI$Tmo`2DqJQx(>2Y_pFcP3q-)>u9j?C(QzgvXZn zE_1Tsz3~~#Cj<`UAW%2pBEsdNH|6n+$6`LX*aAH0_Djfx*Er<3%7xzf?m+2udY|q( zrQV0bWHjVcy(Cw3y@T-Ci}^(UZ}K4Rv&sqI1OoRo%4{FVae0zx8{)K@jX0?Glpujd z8lE$s;uCc)VkvBXPuQ@@U|mbXa3PlxosH$dS%&u?QZW=tkuG;Qjx$~Lpbnq9N;Xyk z_vawhT!Nnnu0o;+_lJ0lg&yMTMGTR7F9J;lo;SSTuD*jcNhFcuIMpG2K~*|;Z8=`= z=^+`a40=k?9sE=z23qaGfu&&y1X5na)K7I4QtaqJ(n#bu&MnB1oiJwiBf#~YUOy74 zv@syW?L3Z@j|pN4uEbm#<^?_)%kyQ0W#e`gV{R;+sQ#OKeN1?zk*EjZ>j(65Ay&_j zdQeau=o%05wBw_2m7grb->c8Ygt>kd>O5WTrH1wxJ{z_(K#*N>I@7$uGM|IZVUic`3k$g19Q>iGWgfg#C z#sh%Y*8iWt%R#<0%vrB*;O#iPNabjyqm&ZLYCLqBi+pSjcSQN6CQ){kexd1L{~T4s z?yFz|?L;cfcNFa{u zV{DtQ&5|f@AdaeIj|WiBrXj(-Q!Ez(;}j&L@M0fhTada2k41eGah0um9JmC3M^sKw zbMmW}6TWey&e~gzwYiSNHq95Y*Ek7>+~-=H&c9mrXD#Au`KQziyMDN&K3E6kUmKK zW;wRJFi39IQX~zvZvcyUlFmKlP9PA6)u)lznO~fta{fW26Hd}FT%Uaf!NNfEb*>9i zDyNWQq7})a+XJIch{wGG-G^wK8AGHyR%nV-Uwz z(0=DTfrpXox{Vb^oD-A)R|F7M8T=0MM6WOOO&5zmAW8bSBSk8M<|XYz;%WOn26LG8XxlWuL3_uyx{d^LY(7~6w?{N$3tFY z4U&qnx|k1A3IqZ<2X!NI!Xa$0`u)05kbC7=kpV8LebVBMsrA!1GF+Ri(C2 zrAnX-&P8Hm=f-gDb`=NjBPT0%sFn8tQfFs>mU5n{sCuN5r8na69H9U2Lw@Jv-SC2n zs$ZAt0+l*}vUj9wkho4Am5mmpg~N&JC%Hs*j7q{*B)4ZFMeye&g+Lkf zMv})bMXFi!C{xnxLHt;cB9%~gmfHiAD}k~xM3wC+NRn0W62IR@#E0{=lBTTNXH^1$ zvM~TDO)?27AUTr!O7TX4{m2oT)ksFd8p^AkL!t=O*~A`(^z|60ru7J<2T1oA$`MbSI@r#UGT`u_s}e=(QAV*o}_00000NkvXXu0mjfP?}_$ literal 0 HcmV?d00001 diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassAwarePI.html b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassAwarePI.html new file mode 100644 index 0000000..cc19c2f --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassAwarePI.html @@ -0,0 +1,48 @@ + + + + + + + + StreamDeck_KeePass Settings + + + + +
+
+
KeePass db path
+ +
+
+
(Optional) Key File path
+ +
+
+
KeePass db password
+ +
+
+
Process Mapping
+ + + + +
+
+
Select field to retrieve
+ +
+
+
Clear Time
+ +
+
+ + diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html index 601381e..bf049b8 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html +++ b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html @@ -15,7 +15,7 @@
KeePass db path
-
+
(Optional) Key File path
diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Services/ProcessHelper.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Services/ProcessHelper.cs new file mode 100644 index 0000000..9aef456 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Services/ProcessHelper.cs @@ -0,0 +1,25 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; + +namespace streamdeck_keepass.Services +{ + public static class ProcessHelper + { + [DllImport("user32.dll")] + public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId); + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + public static string GetActiveProcessFileName() + { + var hwnd = GetForegroundWindow(); + GetWindowThreadProcessId(hwnd, out uint pid); + var p = Process.GetProcessById((int)pid); + + return Path.GetFileName(p.MainModule.FileName); + } + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj index d968368..bba3a56 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj +++ b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj @@ -29,7 +29,7 @@ true - AnyCPU + x64 true full false @@ -94,10 +94,13 @@ + + + @@ -106,6 +109,7 @@ + @@ -115,12 +119,24 @@ + + PreserveNewest + + + PreserveNewest + PreserveNewest PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -170,6 +186,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json b/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json index 22a2d50..d666b55 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json +++ b/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json @@ -29,6 +29,21 @@ "Tooltip": "Generates a custom password using Keepass", "UUID": "com.victorgrycuk.keepass.generate", "PropertyInspectorPath": "PropertyInspector/KeePassGeneratePI.html" + }, + { + "Icon": "Images/aware", + "Name": "Aware", + "States": [ + { + "Image": "Images/keepassAware", + "TitleAlignment": "middle", + "FontSize": "12" + } + ], + "SupportedInMultiActions": true, + "Tooltip": "Retrieve a password entry based on the current active window", + "UUID": "com.victorgrycuk.keepass.aware", + "PropertyInspectorPath": "PropertyInspector/KeePassAwarePI.html" } ], "Author": "Victor Grycuk", From 4ccab2d2f8b2f65c8d32f6e04d3bb2e9513bf4f2 Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Fri, 21 Jan 2022 00:06:38 -0300 Subject: [PATCH 08/10] Update plugin version --- StreamDeck-KeePass/StreamDeck-KeePass/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json b/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json index d666b55..a4a7f72 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json +++ b/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json @@ -51,7 +51,7 @@ "Description": "Simple interface to retrieve information from KeePass database. Unofficial.", "Icon": "Images/pluginIcon", "URL": "https://github.com/VictorGrycuk/StreamDeck-KeePass", - "Version": "1.4.0", + "Version": "1.5.0", "CodePath": "streamdeck-keepass", "Category": "KeePass", "CategoryIcon": "Images/categoryIcon", From 40ddbe071c8d8b2569a8b4c6df1e919e103d89d3 Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Fri, 21 Jan 2022 23:56:54 -0300 Subject: [PATCH 09/10] Add MircoBabin's KeePassCommander action --- README.md | 38 ++++++- .../StreamDeck-KeePass/Actions/ActionBase.cs | 25 +++-- .../Actions/ActionCommander.cs | 28 +++++ .../Domain/KeePassCommander.cs | 38 +++++++ .../Domain/KeePassPlugin.cs | 6 + .../Domain/Settings/CommandSettings.cs | 32 ++++++ .../StreamDeck-KeePass/Images/commander.png | Bin 0 -> 658 bytes .../Images/commander@2x.png | Bin 0 -> 1541 bytes .../Images/keepassCommander.png | Bin 0 -> 3094 bytes .../Images/keepassCommander@2x.png | Bin 0 -> 6412 bytes .../PropertyInspector/KeePassCommanderPI.html | 37 ++++++ .../PropertyInspector/KeePassRetrievePI.html | 2 +- .../Services/KeePassEntry.cs | 106 ++++++++++++++++++ .../StreamDeck-KeePass.csproj | 19 ++++ .../StreamDeck-KeePass/manifest.json | 15 +++ 15 files changed, 336 insertions(+), 10 deletions(-) create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionCommander.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassCommander.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/CommandSettings.cs create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Images/commander.png create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Images/commander@2x.png create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Images/keepassCommander.png create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Images/keepassCommander@2x.png create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassCommanderPI.html create mode 100644 StreamDeck-KeePass/StreamDeck-KeePass/Services/KeePassEntry.cs diff --git a/README.md b/README.md index 36ed6ec..13b0609 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,13 @@ It uses the following configuration: - **KeePass db path.** The absolute path to the KeePass file. - **KeePass db password.** The main password of the KeePass file. -- **Entry Name.** The name of the entry that has the desired information. +- **Entry Name or UUID.** The name or UUID of the entry that has the desired information. - **Field to retrieve.** The field whose content will be copied to the clipboard - Password - Username - Notes - URL +- **Clear Time**. The time in seconds to keep the value in the clipboard. Use `0` to leave it indefinitely (default). @@ -42,9 +43,44 @@ It uses the following configuration: - **Characters to Exclude.** Any character included in the text field will be excluded from the generated password. - **Custom Pattern.** Allows to use a custom defined password generation pattern. Refer to the section *Generating Passwords that Follow Rules* of [KeePass Password Generator](https://keepass.info/help/base/pwgenerator.html) documentation. - ***Note***: Using a custom pattern will override all the previous configuration. +- **Clear Time**. The time in seconds to keep the value in the clipboard. Use `0` to leave it indefinitely (default). Check [KeePass Password Generator](https://keepass.info/help/base/pwgenerator.html) help site for more information. + + +#### Aware + +Its function its identical to *Retrieve*, except it retrieves the stored field based on the current active window. + +It only replaces the Entry Name option with a new one: + +- **Process Mapping.** A `key=value` that maps a running process with a KeePass entry title/UUID. + - Examples: + - `steam.exe=Steam` + - `Discord.exe=2A8CC713A463524C928E1F613BA10DAC` + - Add one mapping per line. + + + +#### MircoBabin's KeePassCommander + +It allows direct communication with the KeePass application to retrieve a field of a stored entry to the clipboard. **Note**: It requires the **[KeePassCommander](https://github.com/MircoBabin/KeePassCommander)** plugin for KeePass. + +It uses the following configuration: + +- **CommandDLL path**. The absolute path to the `KeePassCommandDll.dll`. +- **Entry Name.** The name of the entry that has the desired information. + - **Note**: It does not support search by UUID. +- **Field to retrieve.** The field whose content will be copied to the clipboard + - Password + - Username + - Notes + - URL +- **Clear Time**. The time in seconds to keep the value in the clipboard. Use `0` to leave it indefinitely (default). + + + ## My other Stream Deck plugins - **[Color Picker](https://github.com/VictorGrycuk/streamdeck-color-picker)** diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs index c9a88e0..502e47b 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionBase.cs @@ -18,20 +18,29 @@ public ActionBase(SDConnection connection, InitialPayload payload) : base(connec internal void CreatePlugin(AwareSettings settings) => plugin = new KeePassPlugin(settings); - public override void Dispose() => Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called"); + internal void CreatePlugin(CommanderSettings settings) => plugin = new KeePassPlugin(settings); + + public override void Dispose() => Logger.Instance.LogMessage(TracingLevel.INFO, "Destructor called"); public void ExecuteAction(string logMessage) { - var result = plugin.Invoke(); - - if (result == Result.WARNING) + try { - Connection.ShowAlert().Wait(); - Logger.Instance.LogMessage(TracingLevel.WARN, logMessage); + var result = plugin.Invoke(); + + if (result == Result.WARNING) + { + Connection.ShowAlert().Wait(); + Logger.Instance.LogMessage(TracingLevel.WARN, logMessage); + } + else + { + Connection.ShowOk().Wait(); + } } - else + catch (System.Exception ex) { - Connection.ShowOk().Wait(); + Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message); } } diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionCommander.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionCommander.cs new file mode 100644 index 0000000..11a16f0 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Actions/ActionCommander.cs @@ -0,0 +1,28 @@ +using BarRaider.SdTools; +using Newtonsoft.Json.Linq; +using streamdeck_keepass.Actions; +using StreamDeck_KeePass.Domain.Settings; + +namespace StreamDeck_KeePass.Actions +{ + [PluginActionId("com.victorgrycuk.keepass.commander")] + public class ActionCommander : ActionBase + { + private readonly CommanderSettings settings; + + public ActionCommander(SDConnection connection, InitialPayload payload) : base(connection, payload) + { + settings = ResolveSettings(payload, CommanderSettings.CreateDefaultSettings()); + CreatePlugin(settings); + } + + public override void KeyPressed(KeyPayload payload) => ExecuteAction("Entry not found."); + + public override void ReceivedSettings(ReceivedSettingsPayload payload) + { + Tools.AutoPopulateSettings(settings, payload.Settings); + SaveSettings(JObject.FromObject(settings)); + CreatePlugin(settings); + } + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassCommander.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassCommander.cs new file mode 100644 index 0000000..769a76a --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassCommander.cs @@ -0,0 +1,38 @@ +using StreamDeck_KeePass.Domain.Settings; + +namespace streamdeck_keepass.Domain +{ + internal class KeePassCommander : IKeePassAction + { + private readonly CommanderSettings settings; + + public KeePassCommander(object objectSettings) + { + settings = objectSettings as CommanderSettings; + + if (!KeePassCommand.KeePassEntry.IsInitialized()) + KeePassCommand.KeePassEntry.Initialize(settings.CommandDLLPath); + } + + public string Invoke() + { + var entry = KeePassCommand.KeePassEntry.getfirst(settings.EntryTitle); + + if (entry == null) return string.Empty; + + switch (settings.Field) + { + case "Password": + return entry.Password; + case "Username": + return entry.Username; + case "Notes": + return entry.Notes; + case "URL": + return entry.Url; + default: + return string.Empty; + } + } + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs index d8ae965..3a62962 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/KeePassPlugin.cs @@ -32,6 +32,12 @@ public KeePassPlugin(AwareSettings settings) clearDelay = settings.ClearTime; } + public KeePassPlugin(CommanderSettings settings) + { + action = new KeePassCommander(settings); + clearDelay = settings.ClearTime; + } + public Result Invoke() { var password = action.Invoke(); diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/CommandSettings.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/CommandSettings.cs new file mode 100644 index 0000000..9c0ba2b --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Domain/Settings/CommandSettings.cs @@ -0,0 +1,32 @@ +using BarRaider.SdTools; +using Newtonsoft.Json; + +namespace StreamDeck_KeePass.Domain.Settings +{ + public class CommanderSettings + { + public static CommanderSettings CreateDefaultSettings() + { + var instance = new CommanderSettings + { + CommandDLLPath = string.Empty, + EntryTitle = string.Empty, + Field = string.Empty + }; + return instance; + } + + [FilenameProperty] + [JsonProperty(PropertyName = "commandDLLPath")] + public string CommandDLLPath { get; set; } + + [JsonProperty(PropertyName = "entryTitle")] + public string EntryTitle { get; set; } + + [JsonProperty(PropertyName = "field")] + public string Field { get; set; } + + [JsonProperty(PropertyName = "clearTime")] + public int ClearTime { get; set; } + } +} \ No newline at end of file diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Images/commander.png b/StreamDeck-KeePass/StreamDeck-KeePass/Images/commander.png new file mode 100644 index 0000000000000000000000000000000000000000..1f46be14ff8064e27999b147897998650cce0bfc GIT binary patch literal 658 zcmV;D0&V??P)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ;7)eAyRCwBq)LDp*aTo>g-+YEaOk}M0C|i~bYf8ua;iY6so10P`>m z15m(cyu?*p#J9EwtJ)!)hh2HUobetl7>GGoh+f!+)0GH!VKp}4l*(9){kWAgB#jbw zVhJXOYy$dKAUvPFqi~`vVLdit76#!l4&yF1R3Lqi*_ey9CBmLK5W?3uisP7s^=M4A z9pMXBVmk&FFh2{YF*f4w!5`elLrm>N&ue&thU(bkTowl42`0xnzwj#Lo#8ANSI1{Z zGC3t0?!hArMb{1pdgEu=cN5kWP=^nh?20}~duueUO|&J9z$IJ=$@I*>#qZKBx8_-$ zQG;;zoTEJKI&w-D45rNO32cGBeushK;rVNkaer(qVHPsP) zF79D(hHTuQx|PeDiShB=(wrHb0A}JxRk2uHjV;lp9Q8PeLy5EjE7BaUL=s7V8m^0R`_nOkg)-)3M@v^|I&Wj=0~ suvF6xNuw@Nl#Kr!H_`)Nw>|i80G%O`!0+ytBLDyZ07*qoM6N<$f|G9^MgRZ+ literal 0 HcmV?d00001 diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Images/commander@2x.png b/StreamDeck-KeePass/StreamDeck-KeePass/Images/commander@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..390647298f9706120d91959ea55bdfb37d1b702a GIT binary patch literal 1541 zcmV+g2KxDlP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ>i%CR5RCwCdnSV@`WfaFhzzYKQMXnWF-=WP{0A8hWCBxw8-ek_C?HYeoj^O#0vrJL0FA)k;Vu*t zCcufn!@#}31fTJ4T@!r9egZxM)&qy54e(OnIe{})`We^_?A3xNfioIQmPM}tZULss z%Er3ufu+E&(E#`munf3Rzdr^lfSnegfg~B22FwTYbngUE0&EENU~Gu71YiyDmcZ4@ z5_!O+CtOLq{8ekuAdxRkCwN_AT7xWj!V}OIAhZ1c8z}1S_i-A9Y9YB{z zdb||RR^UV;OMvAf_;lcyYrz);t`1mfS$LJe)c})#2Y^ClkTM`1SPP7d5a3D$Pzvz8 zYr!jl?*LCU(4g^jS+yOw0r<`3Q4w_}@Q4UF63LQ*f2u$@9 znK-_ODv>!rk6gjCwlYTfwMSW@2Z)n3tD@wKg}@}wDudjz<}mP%7Pq5zleRNoWtd5U zo``!O8KrAmh&cw!<(~MfPyS}hwJMK#9e^8wR^T>KQm@6CoxtXP7F{4Jx?aBzsnjZW zjDY3yBRz$5(D6TG!FA5VvD!v}&s8O#vn;sR2UwDJVzz!C(KSP#T#^5ujvsadiCzdZ zUndK?V#s)=>O;5W-{jn@5V(WD6Y5Qn@4u!%TqU3Tmw4Ki3-qS8e5>lh^}&fseLJ*R zpQWqb(Xj}4P(GF8&{d-~mn`DKh~<_Bx;QtiyE14Oqm z$^@r-1UTveUjuh5QI}hjn)PudUjS=WVED-_V6Hm9m#q8KRPOi4g|>*Qa57Prt_M7| zj^^PcpJ;Yvr<$K7ZgD9YtMUurX+`IBMQb52!kSy9lm_sD<$nQv-yI9=7q5-A213b3 z;HWHQw$aGVK(+jDHLz9p9|wvZa40oqh_Y&QFCZ+f!2VdJEQ7vi5CBhUn~wv}0^h5* zsME`)0q+7&S3YjqOBW4dkz&X{`e4VCdTt^E%rjmjb$MD#OMTpSYD&2@q+ zPeGO9qw5RH|FZNVUBH`I1wgZ!=tb%a0)uEXe-wSB02fJVi?WhmrJUn)KPYN4S!#vY zpuz;G-IKhi1fC5n4ukvJ70pNb0cU*h3Po*D$>AGi7*j`MUCX7r zOlx(7dp_7L(lnJwKxuKS%B108fJ#<=-Xa|V5&b-^(LK~hz)gAy`v`cns*)@fwwDdn r5%B-w5Z#r*{0-42D@XJ<#6JT7M(d28(O@K100000NkvXXu0mjf4ko~I literal 0 HcmV?d00001 diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Images/keepassCommander.png b/StreamDeck-KeePass/StreamDeck-KeePass/Images/keepassCommander.png new file mode 100644 index 0000000000000000000000000000000000000000..3c2aa0e7a69d2745708b09c27cdcacc5e7ac3da6 GIT binary patch literal 3094 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 ae-8jFZ2=!* + + + + + + + StreamDeck_KeePass Settings + + + + +
+
+
CommandDLL path
+ +
+
+
Entry Name
+ +
+
+
Select field to retrieve
+ +
+
+
Clear Time
+ +
+
+ + diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html index bf049b8..2326402 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html +++ b/StreamDeck-KeePass/StreamDeck-KeePass/PropertyInspector/KeePassRetrievePI.html @@ -13,7 +13,7 @@
KeePass db path
- +
(Optional) Key File path
diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Services/KeePassEntry.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Services/KeePassEntry.cs new file mode 100644 index 0000000..c9f71c3 --- /dev/null +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Services/KeePassEntry.cs @@ -0,0 +1,106 @@ +/* +KeePass Commander +https://github.com/MircoBabin/KeePassCommander - MIT license + +Copyright (c) 2018 Mirco Babin + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +using System; +using System.IO; +using System.Reflection; + +namespace KeePassCommand +{ + public class KeePassEntry + { + public string Title { get; set; } + public string Username { get; set; } + public string Password { get; set; } + public string Url { get; set; } + public string UrlScheme { get; set; } + public string UrlHost { get; set; } + public string UrlPort { get; set; } + public string UrlPath { get; set; } + public string Notes { get; set; } + + public static KeePassEntry getfirst(string title) + { + if (KeePassCommandDll_ApiGetfirst == null) throw new Exception("Call KeePassEntry.Initialize() first"); + + var result = KeePassCommandDll_ApiGetfirst.Invoke(null, new object[] { title }); + if (result == null) return new KeePassEntry(); + + Type ApiGetResponse = result.GetType(); + + var entry = new KeePassEntry(); + entry.Title = GetResultProperty(result, ApiGetResponse, "Title"); + entry.Username = GetResultProperty(result, ApiGetResponse, "Username"); + entry.Password = GetResultProperty(result, ApiGetResponse, "Password"); + entry.Url = GetResultProperty(result, ApiGetResponse, "Url"); + entry.UrlScheme = GetResultProperty(result, ApiGetResponse, "UrlScheme"); + entry.UrlHost = GetResultProperty(result, ApiGetResponse, "UrlHost"); + entry.UrlPort = GetResultProperty(result, ApiGetResponse, "UrlPort"); + entry.UrlPath = GetResultProperty(result, ApiGetResponse, "UrlPath"); + entry.Notes = GetResultProperty(result, ApiGetResponse, "Notes"); + + return entry; + } + + public static bool IsInitialized() => KeePassCommandDll_ApiGetfirst != null; + + protected static string GetResultProperty(object obj, Type type, string propertyName) + { + PropertyInfo prop = type.GetProperty(propertyName); + if (prop == null) return null; + + return (string)prop.GetValue(obj, null); + } + + #region KeePassCommandDll loading + protected static Assembly KeePassCommandDll = null; + protected static Type KeePassCommandDll_Api = null; + protected static MethodInfo KeePassCommandDll_ApiGetfirst = null; + + public static void Initialize(string KeePassCommandDllPath) + { + if (KeePassCommandDll_ApiGetfirst != null) throw new Exception("KeePassEntry.Initialize() has already been called"); + + if (String.IsNullOrEmpty(KeePassCommandDllPath)) + throw new Exception("KeePassCommandDllPath is not provided"); + + if (!File.Exists(KeePassCommandDllPath)) + throw new Exception("KeePassCommandDll.dll does not exist: " + KeePassCommandDllPath); + + KeePassCommandDll = Assembly.LoadFile(KeePassCommandDllPath); + if (KeePassCommandDll == null) throw new Exception("Error loading KeePassCommandDll.dll [assembly] from " + KeePassCommandDllPath); + + KeePassCommandDll_Api = KeePassCommandDll.GetType("KeePassCommandDll.Api"); + if (KeePassCommandDll_Api == null) throw new Exception("Error loading KeePassCommandDll.dll [KeePassCommandDll.Api class] from " + KeePassCommandDllPath); + + KeePassCommandDll_ApiGetfirst = KeePassCommandDll_Api.GetMethod("getfirst", new Type[] { typeof(string) }); + if (KeePassCommandDll_ApiGetfirst == null) throw new Exception("Error loading KeePassCommandDll.dll [KeePassCommandDll.Api.getfirst(string) method] from " + KeePassCommandDllPath); + } + #endregion + } +} diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj index bba3a56..6c936b6 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj +++ b/StreamDeck-KeePass/StreamDeck-KeePass/StreamDeck-KeePass.csproj @@ -95,12 +95,15 @@ + + + @@ -109,6 +112,7 @@ + @@ -131,12 +135,24 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -189,6 +205,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json b/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json index a4a7f72..6a3e3fa 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json +++ b/StreamDeck-KeePass/StreamDeck-KeePass/manifest.json @@ -44,6 +44,21 @@ "Tooltip": "Retrieve a password entry based on the current active window", "UUID": "com.victorgrycuk.keepass.aware", "PropertyInspectorPath": "PropertyInspector/KeePassAwarePI.html" + }, + { + "Icon": "Images/commander", + "Name": "MircoBabin's KeePassCommander", + "States": [ + { + "Image": "Images/keepassCommander", + "TitleAlignment": "middle", + "FontSize": "12" + } + ], + "SupportedInMultiActions": true, + "Tooltip": "Allows direct communication with KeePass using MircoBabin's KeePassCommander", + "UUID": "com.victorgrycuk.keepass.commander", + "PropertyInspectorPath": "PropertyInspector/KeePassCommanderPI.html" } ], "Author": "Victor Grycuk", From 5164f87574cf19a3c43d992ee8003dd0fcd213d0 Mon Sep 17 00:00:00 2001 From: Victor_Grycuk Date: Sat, 22 Jan 2022 00:13:36 -0300 Subject: [PATCH 10/10] Update AssemblyInfo --- .../StreamDeck-KeePass/Properties/AssemblyInfo.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/StreamDeck-KeePass/StreamDeck-KeePass/Properties/AssemblyInfo.cs b/StreamDeck-KeePass/StreamDeck-KeePass/Properties/AssemblyInfo.cs index 37017e9..2a30892 100644 --- a/StreamDeck-KeePass/StreamDeck-KeePass/Properties/AssemblyInfo.cs +++ b/StreamDeck-KeePass/StreamDeck-KeePass/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("KeePass for Stream Deck")] -[assembly: AssemblyCopyright("Copyright © Victor Grycuk 2020")] +[assembly: AssemblyCopyright("Copyright © Victor Grycuk 2022")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.3.0.0")] -[assembly: AssemblyFileVersion("1.3.0.0")] +[assembly: AssemblyVersion("1.5.0.0")] +[assembly: AssemblyFileVersion("1.5.0.0")]