diff --git a/src/Config.cs b/src/Config.cs index 5195f42..5f79f29 100644 --- a/src/Config.cs +++ b/src/Config.cs @@ -1,213 +1,217 @@ -using KeePass.App.Configuration; -using System; +using System; using System.Drawing; +using KeePass.App.Configuration; namespace GlobalSearch { - public static class Util - { - public static readonly Version KeePassVersion_2_54 = new Version(2, 54); - } - public static class Config - { - private static AceCustomConfig CustomConfig = KeePass.Program.Config.CustomConfig; - private const string ConfigActive = "GlobalSearch.HookSearchForm"; - private const string ConfigPWDisplay = "GlobalSearch.PWDisplay"; - private const string ConfigAllowResize = "GlobalSearch.AllowResize"; - private const string ConfigSearchResultSize = "GlobalSearch.SearchResultSize"; - private const string ConfigSearchResultLocation = "GlobalSearch.SearchResultLocation"; - private const string ConfigUseEntryListColumnWidths = "GlobalSearch.UseEntryListColumnWidths"; - - public static bool SearchForm - { - get { return CustomConfig.GetBool(ConfigActive, true); } - set { CustomConfig.SetBool(ConfigActive, value); m_SearchFormGlobalSession = value; } - - } - - private static bool? m_SearchFormGlobalSession = null; - public static bool SearchFormGlobalSession - { - get - { - if (!m_SearchFormGlobalSession.HasValue) m_SearchFormGlobalSession = SearchForm; - return m_SearchFormGlobalSession.Value; ; - } - set { m_SearchFormGlobalSession = value; } - } - - private const string ConfigShowMultiDBInfoSearchForm = "GlobalSearch.ShowMultiDBInfoSearchForm"; - public static bool ShowMultiDBInfoSearchForm - { - get { return CustomConfig.GetBool(ConfigShowMultiDBInfoSearchForm, true); } - set { CustomConfig.SetBool(ConfigShowMultiDBInfoSearchForm, value); } - } - - private const string ConfigShowMultiDBInfoSingleSearch = "GlobalSearch.ShowMultiDBInfoSingleSearch"; - public static bool ShowMultiDBInfoSingleSearch - { - get { return CustomConfig.GetBool(ConfigShowMultiDBInfoSingleSearch, true); } - set { CustomConfig.SetBool(ConfigShowMultiDBInfoSingleSearch, value); } - } - - private const string ConfigHookSearchDupPw = "GlobalSearch.HookSearchDupPw"; - public static bool HookSearchDupPw - { - get { return CustomConfig.GetBool(ConfigHookSearchDupPw, true); } - set { CustomConfig.SetBool(ConfigHookSearchDupPw, value); } - } - - private const string ConfigHookSearchPwPairs = "GlobalSearch.HookSearchPwPairs"; - public static bool HookSearchPwPairs - { - get { return CustomConfig.GetBool(ConfigHookSearchPwPairs, true); } - set { CustomConfig.SetBool(ConfigHookSearchPwPairs, value); } - } - - private const string ConfigHookSearchPwCluster = "GlobalSearch.HookSearchPwCluster"; - public static bool HookSearchPwCluster - { - get { return CustomConfig.GetBool(ConfigHookSearchPwCluster, true); } - set { CustomConfig.SetBool(ConfigHookSearchPwCluster, value); } - } - - private const string ConfigHookPwQuality = "GlobalSearch.HookPwQuality"; - public static bool HookPwQuality - { - get { return CustomConfig.GetBool(ConfigHookPwQuality, true); } - set { CustomConfig.SetBool(ConfigHookPwQuality, value); } - } - - private const string ConfigHookLargeEntries = "GlobalSearch.HookLargeEntries"; - public static bool HookLargeEntries - { - get { return CustomConfig.GetBool(ConfigHookLargeEntries, true); } - set { CustomConfig.SetBool(ConfigHookLargeEntries, value); } - } - - private const string ConfigHookLastMod = "GlobalSearch.HookLastMod"; - public static bool HookLastMod - { - get { return CustomConfig.GetBool(ConfigHookLastMod, true); } - set { CustomConfig.SetBool(ConfigHookLastMod, value); } - } - - private const string ConfigHookAllExpired = "GlobalSearch.HookAllExpired"; - public static bool HookAllExpired - { - get { return CustomConfig.GetBool(ConfigHookAllExpired, true); } - set { CustomConfig.SetBool(ConfigHookAllExpired, value); } - } - - public enum PasswordDisplayMode - { - Always, - Never, - EntryviewBased, - } - public static PasswordDisplayMode PasswordDisplay - { - get - { - string s = CustomConfig.GetString(ConfigPWDisplay, string.Empty); - if (string.IsNullOrEmpty(s)) - { - PasswordDisplay = PasswordDisplayMode.Always; - return PasswordDisplayMode.Always; - } - try - { - PasswordDisplayMode r = (PasswordDisplayMode)Enum.Parse(typeof(PasswordDisplayMode), s); - return r; - } - catch - { - PasswordDisplay = PasswordDisplayMode.Always; - return PasswordDisplayMode.Always; - } - } - set { CustomConfig.SetString(ConfigPWDisplay, value.ToString()); } - } - - public static bool AllowResize - { - get { return CustomConfig.GetBool(ConfigAllowResize, true); } - set { CustomConfig.SetBool(ConfigAllowResize, value); } - } - - public static Size SearchResultSize - { - get - { - string sSizeString = CustomConfig.GetString(ConfigSearchResultSize, "-9999/-9999"); - try - { - Size s = ResizableListViewForm.NoSize; - string[] aSizeString = sSizeString.Split(new char[] { '/' }); - int i; - if (!int.TryParse(aSizeString[0], out i)) i = -9999; - s.Width = i; - if (!int.TryParse(aSizeString[1], out i)) i = -9999; - s.Height = i; - return s; - } - catch { return ResizableListViewForm.NoSize; } - } - set { - CustomConfig.SetString(ConfigSearchResultSize, value.Width.ToString() + "/" + value.Height.ToString()); } - } - - public static Point SearchResultLocation - { - get - { - string sPointString = CustomConfig.GetString(ConfigSearchResultLocation, "-9999/-9999"); - try - { - Point p = ResizableListViewForm.NoLocation; - string[] aSizeString = sPointString.Split(new char[] { '/' }); - int i; - if (!int.TryParse(aSizeString[0], out i)) i = -9999; - p.X = i; - if (!int.TryParse(aSizeString[1], out i)) i = -9999; - p.Y = i; - return p; - } - catch { return ResizableListViewForm.NoLocation; } - } - set { - CustomConfig.SetString(ConfigSearchResultLocation, value.X.ToString() + "/" + value.Y.ToString()); } - } - - public static bool UseEntryListColumnWidths - { - get { return CustomConfig.GetBool(ConfigUseEntryListColumnWidths, true); } - set { CustomConfig.SetBool(ConfigUseEntryListColumnWidths, value); } - } - - public static bool HookActive(string menuName) - { - switch (menuName) - { - case SearchHelp.SearchForm: return SearchForm; - case SearchHelp.SearchDupPw: return HookSearchDupPw; - case SearchHelp.SearchPasswordPairs: return HookSearchPwPairs; - case SearchHelp.SearchPasswordClusters: return HookSearchPwCluster; - case SearchHelp.SearchPasswordQuality: return HookPwQuality; - case SearchHelp.SearchLargeEntries: return HookLargeEntries; - case SearchHelp.SearchLastMod: return HookLastMod; - case SearchHelp.SearchExpired: return HookAllExpired; - case SearchHelp.SearchExpired_1D: return HookAllExpired; - case SearchHelp.SearchExpired_2D: return HookAllExpired; - case SearchHelp.SearchExpired_3D: return HookAllExpired; - case SearchHelp.SearchExpired_7D: return HookAllExpired; - case SearchHelp.SearchExpired_14D: return HookAllExpired; - case SearchHelp.SearchExpired_1M: return HookAllExpired; - case SearchHelp.SearchExpired_2M: return HookAllExpired; - case SearchHelp.SearchExpired_F: return HookAllExpired; - } - return true; - throw new Exception("Invalid parameter: " + menuName); - } - } -} \ No newline at end of file + public static class Util + { + public static readonly Version KeePassVersion_2_54 = new Version(2, 54); + } + public static class Config + { + private static AceCustomConfig CustomConfig = KeePass.Program.Config.CustomConfig; + private const string ConfigActive = "GlobalSearch.HookSearchForm"; + private const string ConfigPWDisplay = "GlobalSearch.PWDisplay"; + private const string ConfigAllowResize = "GlobalSearch.AllowResize"; + private const string ConfigSearchResultSize = "GlobalSearch.SearchResultSize"; + private const string ConfigSearchResultLocation = "GlobalSearch.SearchResultLocation"; + private const string ConfigUseEntryListColumnWidths = "GlobalSearch.UseEntryListColumnWidths"; + + public static bool SearchForm + { + get { return CustomConfig.GetBool(ConfigActive, true); } + set { CustomConfig.SetBool(ConfigActive, value); m_SearchFormGlobalSession = value; } + + } + + private static bool? m_SearchFormGlobalSession = null; + public static bool SearchFormGlobalSession + { + get + { + if (!m_SearchFormGlobalSession.HasValue) m_SearchFormGlobalSession = SearchForm; + return m_SearchFormGlobalSession.Value; ; + } + set { m_SearchFormGlobalSession = value; } + } + + private const string ConfigShowMultiDBInfoSearchForm = "GlobalSearch.ShowMultiDBInfoSearchForm"; + public static bool ShowMultiDBInfoSearchForm + { + get { return CustomConfig.GetBool(ConfigShowMultiDBInfoSearchForm, true); } + set { CustomConfig.SetBool(ConfigShowMultiDBInfoSearchForm, value); } + } + + private const string ConfigShowMultiDBInfoSingleSearch = "GlobalSearch.ShowMultiDBInfoSingleSearch"; + public static bool ShowMultiDBInfoSingleSearch + { + get { return CustomConfig.GetBool(ConfigShowMultiDBInfoSingleSearch, true); } + set { CustomConfig.SetBool(ConfigShowMultiDBInfoSingleSearch, value); } + } + + private const string ConfigHookSearchDupPw = "GlobalSearch.HookSearchDupPw"; + public static bool HookSearchDupPw + { + get { return CustomConfig.GetBool(ConfigHookSearchDupPw, true); } + set { CustomConfig.SetBool(ConfigHookSearchDupPw, value); } + } + + private const string ConfigHookSearchPwPairs = "GlobalSearch.HookSearchPwPairs"; + public static bool HookSearchPwPairs + { + get { return CustomConfig.GetBool(ConfigHookSearchPwPairs, true); } + set { CustomConfig.SetBool(ConfigHookSearchPwPairs, value); } + } + + private const string ConfigHookSearchPwCluster = "GlobalSearch.HookSearchPwCluster"; + public static bool HookSearchPwCluster + { + get { return CustomConfig.GetBool(ConfigHookSearchPwCluster, true); } + set { CustomConfig.SetBool(ConfigHookSearchPwCluster, value); } + } + + private const string ConfigHookPwQuality = "GlobalSearch.HookPwQuality"; + public static bool HookPwQuality + { + get { return CustomConfig.GetBool(ConfigHookPwQuality, true); } + set { CustomConfig.SetBool(ConfigHookPwQuality, value); } + } + + private const string ConfigHookLargeEntries = "GlobalSearch.HookLargeEntries"; + public static bool HookLargeEntries + { + get { return CustomConfig.GetBool(ConfigHookLargeEntries, true); } + set { CustomConfig.SetBool(ConfigHookLargeEntries, value); } + } + + private const string ConfigHookLastMod = "GlobalSearch.HookLastMod"; + public static bool HookLastMod + { + get { return CustomConfig.GetBool(ConfigHookLastMod, true); } + set { CustomConfig.SetBool(ConfigHookLastMod, value); } + } + + private const string ConfigHookAllExpired = "GlobalSearch.HookAllExpired"; + public static bool HookAllExpired + { + get { return CustomConfig.GetBool(ConfigHookAllExpired, true); } + set { CustomConfig.SetBool(ConfigHookAllExpired, value); } + } + + public enum PasswordDisplayMode + { + Always, + Never, + EntryviewBased, + } + public static PasswordDisplayMode PasswordDisplay + { + get + { + string s = CustomConfig.GetString(ConfigPWDisplay, string.Empty); + if (string.IsNullOrEmpty(s)) + { + PasswordDisplay = PasswordDisplayMode.Always; + return PasswordDisplayMode.Always; + } + try + { + PasswordDisplayMode r = (PasswordDisplayMode)Enum.Parse(typeof(PasswordDisplayMode), s); + return r; + } + catch + { + PasswordDisplay = PasswordDisplayMode.Always; + return PasswordDisplayMode.Always; + } + } + set { CustomConfig.SetString(ConfigPWDisplay, value.ToString()); } + } + + public static bool AllowResize + { + get { return CustomConfig.GetBool(ConfigAllowResize, true); } + set { CustomConfig.SetBool(ConfigAllowResize, value); } + } + + public static Size SearchResultSize + { + get + { + string sSizeString = CustomConfig.GetString(ConfigSearchResultSize, "-9999/-9999"); + try + { + Size s = ResizableListViewForm.NoSize; + string[] aSizeString = sSizeString.Split(new char[] { '/' }); + int i; + if (!int.TryParse(aSizeString[0], out i)) i = -9999; + s.Width = i; + if (!int.TryParse(aSizeString[1], out i)) i = -9999; + s.Height = i; + return s; + } + catch { return ResizableListViewForm.NoSize; } + } + set + { + CustomConfig.SetString(ConfigSearchResultSize, value.Width.ToString() + "/" + value.Height.ToString()); + } + } + + public static Point SearchResultLocation + { + get + { + string sPointString = CustomConfig.GetString(ConfigSearchResultLocation, "-9999/-9999"); + try + { + Point p = ResizableListViewForm.NoLocation; + string[] aSizeString = sPointString.Split(new char[] { '/' }); + int i; + if (!int.TryParse(aSizeString[0], out i)) i = -9999; + p.X = i; + if (!int.TryParse(aSizeString[1], out i)) i = -9999; + p.Y = i; + return p; + } + catch { return ResizableListViewForm.NoLocation; } + } + set + { + CustomConfig.SetString(ConfigSearchResultLocation, value.X.ToString() + "/" + value.Y.ToString()); + } + } + + public static bool UseEntryListColumnWidths + { + get { return CustomConfig.GetBool(ConfigUseEntryListColumnWidths, true); } + set { CustomConfig.SetBool(ConfigUseEntryListColumnWidths, value); } + } + + public static bool HookActive(string menuName) + { + switch (menuName) + { + case SearchHelp.SearchForm: return SearchForm; + case SearchHelp.SearchDupPw: return HookSearchDupPw; + case SearchHelp.SearchPasswordPairs: return HookSearchPwPairs; + case SearchHelp.SearchPasswordClusters: return HookSearchPwCluster; + case SearchHelp.SearchPasswordQuality: return HookPwQuality; + case SearchHelp.SearchLargeEntries: return HookLargeEntries; + case SearchHelp.SearchLastMod: return HookLastMod; + case SearchHelp.SearchExpired: return HookAllExpired; + case SearchHelp.SearchExpired_1D: return HookAllExpired; + case SearchHelp.SearchExpired_2D: return HookAllExpired; + case SearchHelp.SearchExpired_3D: return HookAllExpired; + case SearchHelp.SearchExpired_7D: return HookAllExpired; + case SearchHelp.SearchExpired_14D: return HookAllExpired; + case SearchHelp.SearchExpired_1M: return HookAllExpired; + case SearchHelp.SearchExpired_2M: return HookAllExpired; + case SearchHelp.SearchExpired_F: return HookAllExpired; + } + return true; + throw new Exception("Invalid parameter: " + menuName); + } + } +} diff --git a/src/GlobalSearch.cs b/src/GlobalSearch.cs index 19d8cc1..4e4b94c 100644 --- a/src/GlobalSearch.cs +++ b/src/GlobalSearch.cs @@ -1,4 +1,12 @@ -using KeePass.App.Configuration; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Reflection; +using System.Windows.Forms; +using KeePass.App.Configuration; using KeePass.Forms; using KeePass.Plugins; using KeePass.Resources; @@ -7,1004 +15,996 @@ using KeePassLib.Interfaces; using PluginTools; using PluginTranslation; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Linq; -using System.Reflection; -using System.Windows.Forms; namespace GlobalSearch { - public sealed class GlobalSearchExt : Plugin - { - private IPluginHost m_host = null; - private ToolStripMenuItem m_menu = null; - private Image m_img = null; - - private SearchForm m_sf = null; - private Button m_btnOK = null; - private CheckBox m_cbSearchAllDatabases = null; - private List m_lEntryListColumns = null; - private MethodInfo m_miUpdateColumnsEx = null; - private MethodInfo m_miGetEntryFieldEx = null; - private MethodInfo m_miSprCompileFn = null; - private Dictionary m_dDBGroups = new Dictionary(); - - private ListView m_lvEntries = null; - - private Action m_aStandardLvInit = null; - - public override bool Initialize(IPluginHost host) - { - m_host = host; - PluginTranslate.Init(this, KeePass.Program.Translation.Properties.Iso6391Code); - Tools.DefaultCaption = PluginTranslate.PluginName; - Tools.PluginURL = "https://github.com/rookiestyle/globalsearch/"; - - GetStandardMethods(); - - m_lvEntries = (ListView)Tools.GetControl("m_lvEntries"); - if (m_lvEntries == null) PluginDebug.AddError("Could not get 'm_lvEntries'", 0); - - Tools.OptionsFormShown += Tools_OptionsFormShown; - Tools.OptionsFormClosed += Tools_OptionsFormClosed; - - Activate(); - FindInfo fi = SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchForm); - if (fi != null) m_img = fi.img; - if (m_img == null) - { - try { m_img = (Image)KeePass.Program.Resources.GetObject("B16x16_XMag"); } - catch { } - } - if (m_img == null) m_img = m_host.MainWindow.ClientIcons.Images[(int)PwIcon.EMailSearch]; - - m_menu = new ToolStripMenuItem(); - m_menu.Click += OnShowOptions; - m_menu.Text = PluginTranslate.PluginName + "..."; - m_menu.Image = m_img; - m_host.MainWindow.ToolsMenu.DropDownItems.Add(m_menu); - - return true; - } - - #region Search form - private void OnSearchFormAdded(object sender, GwmWindowEventArgs e) - { - if (e.Form is SearchForm) - { - OnSearchFormClosed(null, null); - int iOpenDB = m_host.MainWindow.DocumentManager.GetOpenDatabases().Count; - StackFrame[] sf = new StackTrace().GetFrames(); - bool bSFRelevant = false; - - List lSF = new List(); - foreach (StackFrame f in sf) - { - bSFRelevant = f.GetMethod().Name == "OnFindInDatabase"; - bSFRelevant |= f.GetMethod().Name == "OnPwListFind"; //KeePass 2.41 - bSFRelevant |= f.GetMethod().Name == "PerformSearchDialog"; //KeePass 2.41 - lSF.Add(f.GetMethod().Name); - if (bSFRelevant) break; - } - bool bAddCheckbox = (iOpenDB > 1) && bSFRelevant; - PluginDebug.AddInfo("Search form added", 0, - "Open databases: " + iOpenDB.ToString(), - "Callstack relevant: " + bSFRelevant.ToString(), - "Add 'Search db' checkbox: " + bAddCheckbox.ToString()); - if (!bSFRelevant) PluginDebug.AddInfo("Callstack", 0, lSF.ToArray()); - if (!bAddCheckbox || !AddCheckBox(e.Form)) return; - m_sf = e.Form as SearchForm; - m_sf.Shown += OnSearchFormShown; - m_sf.Closed += OnSearchFormClosed; - } - if (e.Form is ListViewForm) - { - ListViewFormAdded(e.Form as ListViewForm); - } - } - - private void ListViewFormAdded(ListViewForm f) - { - var lv = f.Controls.OfType().ToList().FirstOrDefault(); - if (lv == null) return; - lv.RS_Sortable(true); - f.Shown += OnShowListviewForm; - } - - private void OnShowListviewForm(object sender, EventArgs e) - { - if (Tools.KeePassVersion == Util.KeePassVersion_2_54) return; - if (Config.PasswordDisplay == Config.PasswordDisplayMode.Always) return; - - if (Config.PasswordDisplay == Config.PasswordDisplayMode.EntryviewBased) - { - AceColumn c = KeePass.Program.Config.MainWindow.EntryListColumns.Where(x => x.Type == AceColumnType.Password).FirstOrDefault(); - if (c != null && !c.HideWithAsterisks) return; - } - - var lv = (sender as Form).Controls.OfType().ToList().FirstOrDefault(); - if (lv == null) return; - ColumnHeader h = null; - foreach (ColumnHeader x in lv.Columns) - { - if (x.Text == KPRes.Password) - { - h = x; - break; - } - } - if (h == null) return; - foreach (ListViewItem x in lv.Items) - { - x.SubItems[h.Index].Text = PwDefs.HiddenPassword; - } - } - - private void OnSearchFormClosed(object sender, EventArgs e) - { - //m_sf = null; - //m_btnOK = null; - m_cbSearchAllDatabases = null; - m_lEntryListColumns = null; - } - - private bool AddCheckBox(Form form) - { - CheckBox m_cbIgnoreGroupSettings = (CheckBox)Tools.GetControl("m_cbIgnoreGroupSettings", form); - CheckBox m_cbDerefData = (CheckBox)Tools.GetControl("m_cbDerefData", form); - m_btnOK = (Button)Tools.GetControl("m_btnOK", form); - Button btnCancel = (Button)Tools.GetControl("m_btnCancel", form); - Button btnHelp = (Button)Tools.GetControl("m_btnHelp", form); //KeePass 2.47 - if ((m_cbIgnoreGroupSettings == null) || (m_cbDerefData == null) || (m_btnOK == null) || (btnCancel == null)) - { - PluginDebug.AddError("Could not add 'Search in all DB' checkbox", 0, - "m_cbIgnoreGroupSettings: " + (m_cbIgnoreGroupSettings == null).ToString(), - "m_cbDerefData: " + (m_cbDerefData == null).ToString(), - "m_btnOK: " + (m_btnOK == null).ToString(), - "m_btnCancel: " + (btnCancel == null).ToString(), - "m_btnHelp: " + (btnHelp == null).ToString()); - return false; - } - m_cbSearchAllDatabases = new CheckBox(); - m_cbSearchAllDatabases.Name = "m_cbRookieSearchAllDB"; - m_cbSearchAllDatabases.Text = PluginTranslate.Search; - m_cbSearchAllDatabases.AutoSize = true; - m_cbSearchAllDatabases.Left = m_cbDerefData.Left; - int spacing = m_cbDerefData.Top - m_cbIgnoreGroupSettings.Top; - m_cbSearchAllDatabases.Top = m_cbDerefData.Top + spacing; - Control c = m_cbDerefData.Parent; - while (c != null) - { - c.Height += spacing; - c = c.Parent; - } - m_btnOK.Top += spacing; - btnCancel.Top += spacing; - if (btnHelp != null) btnHelp.Top += spacing; - m_cbDerefData.Parent.Controls.Add(m_cbSearchAllDatabases); - PluginDebug.AddInfo("'Search db' checkbox added", 0); - if (m_cbSearchAllDatabases.Enabled) - m_cbSearchAllDatabases.CheckedChanged += OnSelectAllDB_CheckedChanged; - else - { - PluginDebug.AddInfo("'Search db' checkbox is disabled, something went terribly wrong", 0); - m_cbSearchAllDatabases.Enabled = true; - m_cbSearchAllDatabases.CheckedChanged += OnSelectAllDB_CheckedChanged; - } - return true; - } - - private void OnSelectAllDB_CheckedChanged(object sender, EventArgs e) - { - if ((m_cbSearchAllDatabases == null) || !m_cbSearchAllDatabases.Enabled) return; - FindInfo fi = SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchForm); - Config.SearchFormGlobalSession = m_cbSearchAllDatabases.Checked; - if (m_cbSearchAllDatabases.Checked) - { - fi.StandardEventHandlers = m_btnOK.GetEventHandlers("Click"); - List lInfos = new List(); - foreach (Delegate d in fi.StandardEventHandlers) - lInfos.Add(d.Method.DeclaringType.FullName + " " + d.Method.Name); - lInfos.Insert(0, "Count: " + lInfos.Count.ToString()); - lInfos.Insert(0, fi.ToString()); - PluginDebug.AddInfo("Replaced eventhandler", 0, lInfos.ToArray()); - m_btnOK.RemoveEventHandlers("Click", fi.StandardEventHandlers); - m_btnOK.Click += OnSearchExecute; - if (fi.StandardEventHandlers.Count == 0) - { - m_btnOK.DialogResult = DialogResult.None; - m_sf.AcceptButton = null; - } - } - else - { - m_btnOK.Click -= OnSearchExecute; - m_btnOK.AddEventHandlers("Click", fi.StandardEventHandlers); - PluginDebug.AddInfo("Restored eventhandler", 0); - m_btnOK.DialogResult = DialogResult.OK; - m_sf.AcceptButton = m_btnOK; - } - } - - private void OnSearchFormShown(object sender, EventArgs e) - { - m_sf.Shown -= OnSearchFormShown; - if ((m_cbSearchAllDatabases == null) || !m_cbSearchAllDatabases.Enabled) return; - m_cbSearchAllDatabases.Checked = Config.SearchFormGlobalSession; - } - - private void OnSearchExecute(object sender, EventArgs e) - { - //Perform search in all open databases - m_dDBGroups = new Dictionary(); - PwGroup g = null; - List lOpenDB = m_host.MainWindow.DocumentManager.GetOpenDatabases(); - m_btnOK.Click -= OnSearchExecute; - List lMsg = new List(); - foreach (PwDatabase db in lOpenDB) - { - lMsg.Clear(); - lMsg.Add("DB: " + db.IOConnectionInfo.Path); - if ((m_sf != null) && (m_sf.SearchResultsGroup != null) && (m_sf.SearchResultsGroup.Entries != null)) - { - lMsg.Add("Previos search results cleared: " + true.ToString()); - m_sf.SearchResultsGroup.Entries.Clear(); - } - m_sf.InitEx(db, db.RootGroup); - FindInfo fi = SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchForm); - if (fi.StandardEventHandlers.Count > 0) - { - using (MonoWorkaroundDialogResult mwaDR = new MonoWorkaroundDialogResult(sender)) - { - foreach (Delegate onclick in fi.StandardEventHandlers) - { - lMsg.Add("Calling method: " + onclick.Method.Name + " - " + onclick.Method.ReflectedType.Name); - onclick.DynamicInvoke(new object[] { sender, e }); - } - } - } - else - { - lMsg.Add("Calling standard method"); - m_btnOK.PerformClick(); - } - if ((m_sf.SearchResultsGroup == null) || (m_sf.SearchResultsGroup.Entries == null)) - { - lMsg.Add("Found entries: 0"); - } - else - { - lMsg.Add("Found entries: " + m_sf.SearchResultsGroup.Entries.UCount.ToString()); - } - - //Do NOT use m_sf.SearchResultsGroup.CloneDeep - //It makes the virtual SearchResultsGroup the - //parent group of the found entries - if (g == null) g = new PwGroup(true, true, m_sf.SearchResultsGroup.Name, m_sf.SearchResultsGroup.IconId); - foreach (PwEntry pe in m_sf.SearchResultsGroup.Entries) g.AddEntry(pe, false); - PluginDebug.AddInfo("Executing search", 0, lMsg.ToArray()); - } - - //Don't continue if not even a single entry was found - if ((g == null) || (g.GetEntriesCount(true) == 0)) - { - if (m_sf.DialogResult == DialogResult.None) m_sf.DialogResult = DialogResult.OK; - return; - } - //Prepare ImageList (CustomIcons can be different per database) - ImageList il = new ImageList(); - ImageList il2 = (ImageList)Tools.GetField("m_ilCurrentIcons", m_host.MainWindow); - foreach (Image img in il2.Images) - il.Images.Add(img); - Dictionary dEntryIconIndex = new Dictionary(); - PwDatabase dbFirst = null; - bool bMultipleDB = false; - - foreach (PwEntry pe in g.Entries) - { - PwDatabase db = m_host.MainWindow.DocumentManager.FindContainerOf(pe); - if (db == null) - { - PluginDebug.AddError("Could not get database for entry", 0, pe.Uuid.ToHexString()); - continue; - } - if (!m_dDBGroups.ContainsKey(db)) m_dDBGroups[db] = new PwGroup(true, false, SearchHelp.GetDBName(pe), PwIcon.Folder) { IsVirtual = true }; - m_dDBGroups[db].AddEntry(pe, false); - if (dbFirst == null) dbFirst = db; - bMultipleDB |= db != dbFirst; - if (!pe.CustomIconUuid.Equals(PwUuid.Zero)) - { - il.Images.Add(db.GetCustomIcon(pe.CustomIconUuid, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16))); - dEntryIconIndex[pe] = dEntryIconIndex.Count - 1; - } - else dEntryIconIndex[pe] = (int)pe.IconId; - } - - //If all found entries are contained in the same database - //simply activate this database (might not be active yet) and return - if (!bMultipleDB) - { - PwGroup pgSF = (PwGroup)Tools.GetField("m_pgResultsGroup", m_sf); - if (pgSF != null) - { - //clear list of found entries - //otherwise duplicates might be shown if last searched db is the only one that is to be shown - pgSF.Entries.Clear(); - pgSF.Entries.Add(g.Entries); - } - else //KeePass 2.47 - { - pgSF = new PwGroup(true, true, g.Name, g.IconId); - pgSF.IsVirtual = true; - pgSF.Entries.Add(g.Entries); - } - PluginDebug.AddInfo("Found "+pgSF.Entries.UCount.ToString()+" entries in 1 database"); - m_host.MainWindow.UpdateUI(false, m_host.MainWindow.DocumentManager.FindDocument(dbFirst), true, pgSF, false, null, false); - il.Dispose(); - m_sf.SearchResultsGroup.Entries.Clear(); - m_sf.SearchResultsGroup.Entries.Add(pgSF.Entries); - m_sf.DialogResult = DialogResult.OK; - return; - } - - //We found entries from at least 2 databases - //Show the results in ListViewForm and close SearchForm - try - { - PluginDebug.AddInfo("Found " + g.Entries.UCount.ToString() + " entries in multiple database"); - m_sf.DialogResult = DialogResult.Abort; - m_sf.Visible = false; - m_sf.Close(); - } - catch (Exception ex) - { - PluginDebug.AddError("Error closing searchform", new string[] { ex.Message }); - } - - m_aStandardLvInit = InitListViewMain; - List l = GetFoundEntriesList(g, dEntryIconIndex); - - int iCount = l.FindAll(x => (x as ListViewItem) != null).Count; - string sSubTitle = iCount == 1 ? KPRes.SearchEntriesFound1 : KPRes.SearchEntriesFound; - sSubTitle = sSubTitle.Replace("{PARAM}", iCount.ToString()); - ResizableListViewForm dlg = new ResizableListViewForm(KPRes.Search, sSubTitle); - dlg.RememberColumnWidths = !Config.UseEntryListColumnWidths; - dlg.InitEx(KPRes.Search, sSubTitle, null, null, l, il, InitListView); - m_bUsedEntryViewColumnWidths = false; - ShowMultiDBInfo(true); - PluginDebug.AddInfo("Multi-DB results: Show", 0); - if (dlg.ShowDialog(m_host.MainWindow) != DialogResult.OK) - { - PluginDebug.AddInfo("Multi-DB results: Shown", 0); - UIUtil.DestroyForm(dlg); - return; - } - PluginDebug.AddInfo("Multi-DB results: Show and navigate", 0); - il.Dispose(); - NavigateToSelectedEntry(dlg, true); - PluginDebug.AddInfo("Multi-DB results: Dispose form", 0); - UIUtil.DestroyForm(dlg); - PluginDebug.AddInfo("Multi-DB results: Disposed form", 0); - } - - private List GetFoundEntriesList(PwGroup g, Dictionary dEntryIconIndex) - { - List l = new List(); - m_lEntryListColumns = new List(); - List lColumns = null; - if (m_miGetEntryFieldEx != null) - lColumns = KeePass.Program.Config.MainWindow.EntryListColumns; - else //add a basic set of columns - { - lColumns = new List(); - AddColumn(lColumns, AceColumnType.Title, false); - AddColumn(lColumns, AceColumnType.UserName, false); - AddColumn(lColumns, AceColumnType.Password, true); - AddColumn(lColumns, AceColumnType.Url, false); - AddColumn(lColumns, AceColumnType.Notes, false); - } - foreach (PwEntry pe in g.Entries) - { - PwGroup pg = pe.ParentGroup; - if (pg != null) - { - if (l.Find(x => (x is ListViewGroup) && ((x as ListViewGroup).Tag == pg)) == null) - { - ListViewGroup lvg = new ListViewGroup(pg.GetFullPath(" - ", pg.ParentGroup == null)); - lvg.Tag = pg; - l.Add(lvg); - } - } - ListViewItem lvi = new ListViewItem(); - lvi.Tag = new object[] { pe, g }; - lvi.Text = SearchHelp.GetDBName(pe); - lvi.ImageIndex = dEntryIconIndex[pe]; - ListViewItem.ListViewSubItem lvsi = null; - //Show all columns that are shown in the entry list view if possible - if (m_miGetEntryFieldEx != null) - { - for (int i = 0; i < lColumns.Count; i++) - { - lvsi = new ListViewItem.ListViewSubItem(); - lvsi.Text = (string)m_miGetEntryFieldEx.Invoke(m_host.MainWindow, new object[] { pe, i, true, null }); - if (!m_lEntryListColumns.Contains(lColumns[i])) m_lEntryListColumns.Add(lColumns[i]); - lvi.SubItems.Add(lvsi); - } - } - else //Show a basic set of columns - { - foreach (AceColumn c in lColumns) - { - lvsi = new ListViewItem.ListViewSubItem(); - if (c.Type == AceColumnType.Title) - lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : pe.Strings.ReadSafe(PwDefs.TitleField); - if (c.Type == AceColumnType.UserName) - lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : pe.Strings.ReadSafe(PwDefs.UserNameField); - if (c.Type == AceColumnType.Password) - lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : pe.Strings.ReadSafe(PwDefs.PasswordField); - if (c.Type == AceColumnType.Url) - lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : pe.Strings.ReadSafe(PwDefs.UrlField); - if (c.Type == AceColumnType.Notes) - lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : KeePassLib.Utility.StrUtil.MultiToSingleLine(pe.Strings.ReadSafe(PwDefs.NotesField)); - //Deref data if required - lvsi.Text = DerefString(lvsi.Text, pe); - if (!m_lEntryListColumns.Contains(c)) m_lEntryListColumns.Add(c); - lvi.SubItems.Add(lvsi); - }; - }; - l.Add(lvi); - } - return l; - } - - private string DerefString(string text, PwEntry pe) - { - if (m_miSprCompileFn == null) return text; - if (!KeePass.Program.Config.MainWindow.EntryListShowDerefData) return text; - if (KeePass.Program.Config.MainWindow.EntryListShowDerefDataAsync) return text; - if (!text.Contains("{")) return text; - PwListItem pli = new PwListItem(pe); - return (string)m_miSprCompileFn.Invoke(null, new object[] { text, pli }); - } - - private void AddColumn(List lColumns, AceColumnType ColType, bool hide) - { - AceColumn c = KeePass.Program.Config.MainWindow.EntryListColumns.Find(x => x.Type == ColType); - if (c == null) - { - c = new AceColumn(ColType); - c.HideWithAsterisks = hide; - } - else c = new AceColumn(c.Type, c.CustomName, c.HideWithAsterisks, c.SafeGetWidth(1)); - lColumns.Add(c); - } - - private bool m_bUsedEntryViewColumnWidths = false; - private void InitListViewMain(ListView lv) - { - int w = lv.ClientSize.Width - UIUtil.GetVScrollBarWidth(); - int wf = w / (m_lEntryListColumns.Count); - int di = Math.Min(UIUtil.GetSmallIconSize().Width, wf); - - List lIndices = new List(); - - lIndices.Add(0); - for (int i = 0; i < m_lEntryListColumns.Count; i++) - { - lIndices.Add(i + 1); - int cw = wf; - if (i == 0) cw = wf + di; - if (i == m_lEntryListColumns.Count - 1) cw = wf - di; - - lv.Columns.Add(m_lEntryListColumns[i].GetDisplayName(), Config.UseEntryListColumnWidths ? m_lEntryListColumns[i].Width : cw); - } - UIUtil.SetDisplayIndices(lv, lIndices.ToArray()); - m_lEntryListColumns = null; - - m_bUsedEntryViewColumnWidths = Config.UseEntryListColumnWidths; - } - #endregion - - #region All 'Find' functions beside 'Search...' - private void OnClickFindEntry(object sender, EventArgs e) - { - string f = (sender as ToolStripItem).Name; - FindInfo fi = SearchHelp.FindList.Find(x => x.Name == (sender as ToolStripItem).Name); - - if (CallStandardSearch(fi, (sender as ToolStripItem).Name)) - { - if (fi != null) - { - foreach (Delegate d in fi.StandardEventHandlers) - d.DynamicInvoke(new object[] { sender, e }); - } - return; - } - - PluginDebug.AddInfo("Call own find routine", 0, "Action: " + f); - //Show status logger - Form fOptDialog = null; - IStatusLogger sl = StatusUtil.CreateStatusDialog(m_host.MainWindow, out fOptDialog, null, - (KPRes.SearchingOp ?? "..."), true, false); - m_host.MainWindow.UIBlockInteraction(true); - - m_aStandardLvInit = null; - - //Perform find for all open databases - PwDatabase dbAll = MergeDatabases(); - List l = null; - try - { - object[] parameters; - if (fi.SearchType != SearchType.BuiltIn) parameters = new object[] { dbAll, sl, null, fi }; - else parameters = new object[] { dbAll, sl, null }; - - l = (List)fi.StandardMethod.Invoke(m_host, parameters); - m_aStandardLvInit = (Action)parameters[2]; - } - catch (Exception ex) - { - l = null; - PluginDebug.AddError("Call standard find routine", 0, "Action: " + f, "Reason for standard call: " + ex.Message); - foreach (Delegate d in fi.StandardEventHandlers) - d.DynamicInvoke(new object[] { sender, e }); - } - finally { dbAll.Close(); } - - m_host.MainWindow.UIBlockInteraction(false); - sl.EndLogging(); - - if (l == null) return; - - //Fill db column - ImageList il = new ImageList(); - ImageList il2 = (ImageList)Tools.GetField("m_ilCurrentIcons", m_host.MainWindow); - foreach (Image img in il2.Images) - il.Images.Add(img); - - for (int i = 0; i < l.Count; i++) - { - ListViewItem lvi = GetObjectAsListViewItem(l[i]); - if (lvi == null) continue; - ListViewItem.ListViewSubItem lvsi = new ListViewItem.ListViewSubItem(); - if (lvi.Tag is PwEntry) - { - lvsi.Text = SearchHelp.GetDBName(lvi.Tag as PwEntry); - PwEntry pe = lvi.Tag as PwEntry; - PwDatabase db = m_host.MainWindow.DocumentManager.FindContainerOf(pe); - if (!pe.CustomIconUuid.Equals(PwUuid.Zero)) - { - il.Images.Add(db.GetCustomIcon(pe.CustomIconUuid, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16))); - lvi.ImageIndex = il.Images.Count - 1; - } - else lvi.ImageIndex = (int)pe.IconId; - } - else if (lvi.Tag is PwGroup) - { - PwGroup pg = lvi.Tag as PwGroup; - lvsi.Text = SearchHelp.GetDBName(pg.Entries.GetAt(0)); - } - l[i] = AddSubItemToListViewObject(l[i], lvi, lvsi); - } - - if ((l.Count == 0) && !string.IsNullOrEmpty(fi.NothingFound)) - { - Tools.ShowInfo(fi.NothingFound); - il.Dispose(); - return; - } - - //Show results - var dlg = new ResizableListViewForm(fi.Title, fi.SubTitle); - //Prepare ImageList (CustomIcons can be different per database) - dlg.InitEx(fi.Title, fi.SubTitle, fi.Note, fi.img, l, il, InitListView); - UIUtil.ShowDialogAndDestroy(dlg); - if (dlg.DialogResult != DialogResult.OK) return; - il.Dispose(); - NavigateToSelectedEntry(dlg, false); - } - - private object AddSubItemToListViewObject(object o, ListViewItem lvi, ListViewItem.ListViewSubItem lvsi) + public sealed class GlobalSearchExt : Plugin + { + private IPluginHost m_host = null; + private ToolStripMenuItem m_menu = null; + private Image m_img = null; + + private SearchForm m_sf = null; + private Button m_btnOK = null; + private CheckBox m_cbSearchAllDatabases = null; + private List m_lEntryListColumns = null; + private MethodInfo m_miUpdateColumnsEx = null; + private MethodInfo m_miGetEntryFieldEx = null; + private MethodInfo m_miSprCompileFn = null; + private Dictionary m_dDBGroups = new Dictionary(); + + private ListView m_lvEntries = null; + + private Action m_aStandardLvInit = null; + + public override bool Initialize(IPluginHost host) + { + m_host = host; + PluginTranslate.Init(this, KeePass.Program.Translation.Properties.Iso6391Code); + Tools.DefaultCaption = PluginTranslate.PluginName; + Tools.PluginURL = "https://github.com/rookiestyle/globalsearch/"; + + GetStandardMethods(); + + m_lvEntries = (ListView)Tools.GetControl("m_lvEntries"); + if (m_lvEntries == null) PluginDebug.AddError("Could not get 'm_lvEntries'", 0); + + Tools.OptionsFormShown += Tools_OptionsFormShown; + Tools.OptionsFormClosed += Tools_OptionsFormClosed; + + Activate(); + FindInfo fi = SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchForm); + if (fi != null) m_img = fi.img; + if (m_img == null) + { + try { m_img = (Image)KeePass.Program.Resources.GetObject("B16x16_XMag"); } + catch { } + } + if (m_img == null) m_img = m_host.MainWindow.ClientIcons.Images[(int)PwIcon.EMailSearch]; + + m_menu = new ToolStripMenuItem(); + m_menu.Click += OnShowOptions; + m_menu.Text = PluginTranslate.PluginName + "..."; + m_menu.Image = m_img; + m_host.MainWindow.ToolsMenu.DropDownItems.Add(m_menu); + + return true; + } + + #region Search form + private void OnSearchFormAdded(object sender, GwmWindowEventArgs e) + { + if (e.Form is SearchForm) + { + OnSearchFormClosed(null, null); + int iOpenDB = m_host.MainWindow.DocumentManager.GetOpenDatabases().Count; + StackFrame[] sf = new StackTrace().GetFrames(); + bool bSFRelevant = false; + + List lSF = new List(); + foreach (StackFrame f in sf) + { + bSFRelevant = f.GetMethod().Name == "OnFindInDatabase"; + bSFRelevant |= f.GetMethod().Name == "OnPwListFind"; //KeePass 2.41 + bSFRelevant |= f.GetMethod().Name == "PerformSearchDialog"; //KeePass 2.41 + lSF.Add(f.GetMethod().Name); + if (bSFRelevant) break; + } + bool bAddCheckbox = (iOpenDB > 1) && bSFRelevant; + PluginDebug.AddInfo("Search form added", 0, + "Open databases: " + iOpenDB.ToString(), + "Callstack relevant: " + bSFRelevant.ToString(), + "Add 'Search db' checkbox: " + bAddCheckbox.ToString()); + if (!bSFRelevant) PluginDebug.AddInfo("Callstack", 0, lSF.ToArray()); + if (!bAddCheckbox || !AddCheckBox(e.Form)) return; + m_sf = e.Form as SearchForm; + m_sf.Shown += OnSearchFormShown; + m_sf.Closed += OnSearchFormClosed; + } + if (e.Form is ListViewForm) + { + ListViewFormAdded(e.Form as ListViewForm); + } + } + + private void ListViewFormAdded(ListViewForm f) + { + var lv = f.Controls.OfType().ToList().FirstOrDefault(); + if (lv == null) return; + lv.RS_Sortable(true); + f.Shown += OnShowListviewForm; + } + + private void OnShowListviewForm(object sender, EventArgs e) + { + if (Tools.KeePassVersion == Util.KeePassVersion_2_54) return; + if (Config.PasswordDisplay == Config.PasswordDisplayMode.Always) return; + + if (Config.PasswordDisplay == Config.PasswordDisplayMode.EntryviewBased) + { + AceColumn c = KeePass.Program.Config.MainWindow.EntryListColumns.Where(x => x.Type == AceColumnType.Password).FirstOrDefault(); + if (c != null && !c.HideWithAsterisks) return; + } + + var lv = (sender as Form).Controls.OfType().ToList().FirstOrDefault(); + if (lv == null) return; + ColumnHeader h = null; + foreach (ColumnHeader x in lv.Columns) + { + if (x.Text == KPRes.Password) + { + h = x; + break; + } + } + if (h == null) return; + foreach (ListViewItem x in lv.Items) + { + x.SubItems[h.Index].Text = PwDefs.HiddenPassword; + } + } + + private void OnSearchFormClosed(object sender, EventArgs e) + { + //m_sf = null; + //m_btnOK = null; + m_cbSearchAllDatabases = null; + m_lEntryListColumns = null; + } + + private bool AddCheckBox(Form form) + { + CheckBox m_cbIgnoreGroupSettings = (CheckBox)Tools.GetControl("m_cbIgnoreGroupSettings", form); + CheckBox m_cbDerefData = (CheckBox)Tools.GetControl("m_cbDerefData", form); + m_btnOK = (Button)Tools.GetControl("m_btnOK", form); + Button btnCancel = (Button)Tools.GetControl("m_btnCancel", form); + Button btnHelp = (Button)Tools.GetControl("m_btnHelp", form); //KeePass 2.47 + if ((m_cbIgnoreGroupSettings == null) || (m_cbDerefData == null) || (m_btnOK == null) || (btnCancel == null)) + { + PluginDebug.AddError("Could not add 'Search in all DB' checkbox", 0, + "m_cbIgnoreGroupSettings: " + (m_cbIgnoreGroupSettings == null).ToString(), + "m_cbDerefData: " + (m_cbDerefData == null).ToString(), + "m_btnOK: " + (m_btnOK == null).ToString(), + "m_btnCancel: " + (btnCancel == null).ToString(), + "m_btnHelp: " + (btnHelp == null).ToString()); + return false; + } + m_cbSearchAllDatabases = new CheckBox(); + m_cbSearchAllDatabases.Name = "m_cbRookieSearchAllDB"; + m_cbSearchAllDatabases.Text = PluginTranslate.Search; + m_cbSearchAllDatabases.AutoSize = true; + m_cbSearchAllDatabases.Left = m_cbDerefData.Left; + int spacing = m_cbDerefData.Top - m_cbIgnoreGroupSettings.Top; + m_cbSearchAllDatabases.Top = m_cbDerefData.Top + spacing; + Control c = m_cbDerefData.Parent; + while (c != null) + { + c.Height += spacing; + c = c.Parent; + } + m_btnOK.Top += spacing; + btnCancel.Top += spacing; + if (btnHelp != null) btnHelp.Top += spacing; + m_cbDerefData.Parent.Controls.Add(m_cbSearchAllDatabases); + PluginDebug.AddInfo("'Search db' checkbox added", 0); + if (m_cbSearchAllDatabases.Enabled) + m_cbSearchAllDatabases.CheckedChanged += OnSelectAllDB_CheckedChanged; + else + { + PluginDebug.AddInfo("'Search db' checkbox is disabled, something went terribly wrong", 0); + m_cbSearchAllDatabases.Enabled = true; + m_cbSearchAllDatabases.CheckedChanged += OnSelectAllDB_CheckedChanged; + } + return true; + } + + private void OnSelectAllDB_CheckedChanged(object sender, EventArgs e) + { + if ((m_cbSearchAllDatabases == null) || !m_cbSearchAllDatabases.Enabled) return; + FindInfo fi = SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchForm); + Config.SearchFormGlobalSession = m_cbSearchAllDatabases.Checked; + if (m_cbSearchAllDatabases.Checked) + { + fi.StandardEventHandlers = m_btnOK.GetEventHandlers("Click"); + List lInfos = new List(); + foreach (Delegate d in fi.StandardEventHandlers) + lInfos.Add(d.Method.DeclaringType.FullName + " " + d.Method.Name); + lInfos.Insert(0, "Count: " + lInfos.Count.ToString()); + lInfos.Insert(0, fi.ToString()); + PluginDebug.AddInfo("Replaced eventhandler", 0, lInfos.ToArray()); + m_btnOK.RemoveEventHandlers("Click", fi.StandardEventHandlers); + m_btnOK.Click += OnSearchExecute; + if (fi.StandardEventHandlers.Count == 0) { - if (o is ListViewItem) + m_btnOK.DialogResult = DialogResult.None; + m_sf.AcceptButton = null; + } + } + else + { + m_btnOK.Click -= OnSearchExecute; + m_btnOK.AddEventHandlers("Click", fi.StandardEventHandlers); + PluginDebug.AddInfo("Restored eventhandler", 0); + m_btnOK.DialogResult = DialogResult.OK; + m_sf.AcceptButton = m_btnOK; + } + } + + private void OnSearchFormShown(object sender, EventArgs e) + { + m_sf.Shown -= OnSearchFormShown; + if ((m_cbSearchAllDatabases == null) || !m_cbSearchAllDatabases.Enabled) return; + m_cbSearchAllDatabases.Checked = Config.SearchFormGlobalSession; + } + + private void OnSearchExecute(object sender, EventArgs e) + { + //Perform search in all open databases + m_dDBGroups = new Dictionary(); + PwGroup g = null; + List lOpenDB = m_host.MainWindow.DocumentManager.GetOpenDatabases(); + m_btnOK.Click -= OnSearchExecute; + List lMsg = new List(); + foreach (PwDatabase db in lOpenDB) + { + lMsg.Clear(); + lMsg.Add("DB: " + db.IOConnectionInfo.Path); + if ((m_sf != null) && (m_sf.SearchResultsGroup != null) && (m_sf.SearchResultsGroup.Entries != null)) + { + lMsg.Add("Previos search results cleared: " + true.ToString()); + m_sf.SearchResultsGroup.Entries.Clear(); + } + m_sf.InitEx(db, db.RootGroup); + FindInfo fi = SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchForm); + if (fi.StandardEventHandlers.Count > 0) + { + using (MonoWorkaroundDialogResult mwaDR = new MonoWorkaroundDialogResult(sender)) + { + foreach (Delegate onclick in fi.StandardEventHandlers) { - (o as ListViewItem).SubItems.Insert(0, lvsi); - return o; + lMsg.Add("Calling method: " + onclick.Method.Name + " - " + onclick.Method.ReflectedType.Name); + onclick.DynamicInvoke(new object[] { sender, e }); } - if (Tools.KeePassVersion < Util.KeePassVersion_2_54) return o; - //Could be KeePass 2.54 or higher and type LvfItem - lvi.SubItems.Insert(0, lvsi); - var c = o.GetType().GetConstructor(new Type[] { typeof(ListViewItem) }); - if (c != null) o = c.Invoke(new object[] { lvi }); - return o; - } - - private ListViewItem GetObjectAsListViewItem(object o) + } + } + else + { + lMsg.Add("Calling standard method"); + m_btnOK.PerformClick(); + } + if ((m_sf.SearchResultsGroup == null) || (m_sf.SearchResultsGroup.Entries == null)) + { + lMsg.Add("Found entries: 0"); + } + else + { + lMsg.Add("Found entries: " + m_sf.SearchResultsGroup.Entries.UCount.ToString()); + } + + //Do NOT use m_sf.SearchResultsGroup.CloneDeep + //It makes the virtual SearchResultsGroup the + //parent group of the found entries + if (g == null) g = new PwGroup(true, true, m_sf.SearchResultsGroup.Name, m_sf.SearchResultsGroup.IconId); + foreach (PwEntry pe in m_sf.SearchResultsGroup.Entries) g.AddEntry(pe, false); + PluginDebug.AddInfo("Executing search", 0, lMsg.ToArray()); + } + + //Don't continue if not even a single entry was found + if ((g == null) || (g.GetEntriesCount(true) == 0)) + { + if (m_sf.DialogResult == DialogResult.None) m_sf.DialogResult = DialogResult.OK; + return; + } + //Prepare ImageList (CustomIcons can be different per database) + ImageList il = new ImageList(); + ImageList il2 = (ImageList)Tools.GetField("m_ilCurrentIcons", m_host.MainWindow); + foreach (Image img in il2.Images) + il.Images.Add(img); + Dictionary dEntryIconIndex = new Dictionary(); + PwDatabase dbFirst = null; + bool bMultipleDB = false; + + foreach (PwEntry pe in g.Entries) + { + PwDatabase db = m_host.MainWindow.DocumentManager.FindContainerOf(pe); + if (db == null) + { + PluginDebug.AddError("Could not get database for entry", 0, pe.Uuid.ToHexString()); + continue; + } + if (!m_dDBGroups.ContainsKey(db)) m_dDBGroups[db] = new PwGroup(true, false, SearchHelp.GetDBName(pe), PwIcon.Folder) { IsVirtual = true }; + m_dDBGroups[db].AddEntry(pe, false); + if (dbFirst == null) dbFirst = db; + bMultipleDB |= db != dbFirst; + if (!pe.CustomIconUuid.Equals(PwUuid.Zero)) + { + il.Images.Add(db.GetCustomIcon(pe.CustomIconUuid, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16))); + dEntryIconIndex[pe] = dEntryIconIndex.Count - 1; + } + else dEntryIconIndex[pe] = (int)pe.IconId; + } + + //If all found entries are contained in the same database + //simply activate this database (might not be active yet) and return + if (!bMultipleDB) + { + PwGroup pgSF = (PwGroup)Tools.GetField("m_pgResultsGroup", m_sf); + if (pgSF != null) + { + //clear list of found entries + //otherwise duplicates might be shown if last searched db is the only one that is to be shown + pgSF.Entries.Clear(); + pgSF.Entries.Add(g.Entries); + } + else //KeePass 2.47 + { + pgSF = new PwGroup(true, true, g.Name, g.IconId); + pgSF.IsVirtual = true; + pgSF.Entries.Add(g.Entries); + } + PluginDebug.AddInfo("Found " + pgSF.Entries.UCount.ToString() + " entries in 1 database"); + m_host.MainWindow.UpdateUI(false, m_host.MainWindow.DocumentManager.FindDocument(dbFirst), true, pgSF, false, null, false); + il.Dispose(); + m_sf.SearchResultsGroup.Entries.Clear(); + m_sf.SearchResultsGroup.Entries.Add(pgSF.Entries); + m_sf.DialogResult = DialogResult.OK; + return; + } + + //We found entries from at least 2 databases + //Show the results in ListViewForm and close SearchForm + try + { + PluginDebug.AddInfo("Found " + g.Entries.UCount.ToString() + " entries in multiple database"); + m_sf.DialogResult = DialogResult.Abort; + m_sf.Visible = false; + m_sf.Close(); + } + catch (Exception ex) + { + PluginDebug.AddError("Error closing searchform", new string[] { ex.Message }); + } + + m_aStandardLvInit = InitListViewMain; + List l = GetFoundEntriesList(g, dEntryIconIndex); + + int iCount = l.FindAll(x => (x as ListViewItem) != null).Count; + string sSubTitle = iCount == 1 ? KPRes.SearchEntriesFound1 : KPRes.SearchEntriesFound; + sSubTitle = sSubTitle.Replace("{PARAM}", iCount.ToString()); + ResizableListViewForm dlg = new ResizableListViewForm(KPRes.Search, sSubTitle); + dlg.RememberColumnWidths = !Config.UseEntryListColumnWidths; + dlg.InitEx(KPRes.Search, sSubTitle, null, null, l, il, InitListView); + m_bUsedEntryViewColumnWidths = false; + ShowMultiDBInfo(true); + PluginDebug.AddInfo("Multi-DB results: Show", 0); + if (dlg.ShowDialog(m_host.MainWindow) != DialogResult.OK) + { + PluginDebug.AddInfo("Multi-DB results: Shown", 0); + UIUtil.DestroyForm(dlg); + return; + } + PluginDebug.AddInfo("Multi-DB results: Show and navigate", 0); + il.Dispose(); + NavigateToSelectedEntry(dlg, true); + PluginDebug.AddInfo("Multi-DB results: Dispose form", 0); + UIUtil.DestroyForm(dlg); + PluginDebug.AddInfo("Multi-DB results: Disposed form", 0); + } + + private List GetFoundEntriesList(PwGroup g, Dictionary dEntryIconIndex) + { + List l = new List(); + m_lEntryListColumns = new List(); + List lColumns = null; + if (m_miGetEntryFieldEx != null) + lColumns = KeePass.Program.Config.MainWindow.EntryListColumns; + else //add a basic set of columns + { + lColumns = new List(); + AddColumn(lColumns, AceColumnType.Title, false); + AddColumn(lColumns, AceColumnType.UserName, false); + AddColumn(lColumns, AceColumnType.Password, true); + AddColumn(lColumns, AceColumnType.Url, false); + AddColumn(lColumns, AceColumnType.Notes, false); + } + foreach (PwEntry pe in g.Entries) + { + PwGroup pg = pe.ParentGroup; + if (pg != null) + { + if (l.Find(x => (x is ListViewGroup) && ((x as ListViewGroup).Tag == pg)) == null) + { + ListViewGroup lvg = new ListViewGroup(pg.GetFullPath(" - ", pg.ParentGroup == null)); + lvg.Tag = pg; + l.Add(lvg); + } + } + ListViewItem lvi = new ListViewItem(); + lvi.Tag = new object[] { pe, g }; + lvi.Text = SearchHelp.GetDBName(pe); + lvi.ImageIndex = dEntryIconIndex[pe]; + ListViewItem.ListViewSubItem lvsi = null; + //Show all columns that are shown in the entry list view if possible + if (m_miGetEntryFieldEx != null) + { + for (int i = 0; i < lColumns.Count; i++) + { + lvsi = new ListViewItem.ListViewSubItem(); + lvsi.Text = (string)m_miGetEntryFieldEx.Invoke(m_host.MainWindow, new object[] { pe, i, true, null }); + if (!m_lEntryListColumns.Contains(lColumns[i])) m_lEntryListColumns.Add(lColumns[i]); + lvi.SubItems.Add(lvsi); + } + } + else //Show a basic set of columns + { + foreach (AceColumn c in lColumns) + { + lvsi = new ListViewItem.ListViewSubItem(); + if (c.Type == AceColumnType.Title) + lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : pe.Strings.ReadSafe(PwDefs.TitleField); + if (c.Type == AceColumnType.UserName) + lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : pe.Strings.ReadSafe(PwDefs.UserNameField); + if (c.Type == AceColumnType.Password) + lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : pe.Strings.ReadSafe(PwDefs.PasswordField); + if (c.Type == AceColumnType.Url) + lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : pe.Strings.ReadSafe(PwDefs.UrlField); + if (c.Type == AceColumnType.Notes) + lvsi.Text = c.HideWithAsterisks ? PwDefs.HiddenPassword : KeePassLib.Utility.StrUtil.MultiToSingleLine(pe.Strings.ReadSafe(PwDefs.NotesField)); + //Deref data if required + lvsi.Text = DerefString(lvsi.Text, pe); + if (!m_lEntryListColumns.Contains(c)) m_lEntryListColumns.Add(c); + lvi.SubItems.Add(lvsi); + }; + }; + l.Add(lvi); + } + return l; + } + + private string DerefString(string text, PwEntry pe) + { + if (m_miSprCompileFn == null) return text; + if (!KeePass.Program.Config.MainWindow.EntryListShowDerefData) return text; + if (KeePass.Program.Config.MainWindow.EntryListShowDerefDataAsync) return text; + if (!text.Contains("{")) return text; + PwListItem pli = new PwListItem(pe); + return (string)m_miSprCompileFn.Invoke(null, new object[] { text, pli }); + } + + private void AddColumn(List lColumns, AceColumnType ColType, bool hide) + { + AceColumn c = KeePass.Program.Config.MainWindow.EntryListColumns.Find(x => x.Type == ColType); + if (c == null) + { + c = new AceColumn(ColType); + c.HideWithAsterisks = hide; + } + else c = new AceColumn(c.Type, c.CustomName, c.HideWithAsterisks, c.SafeGetWidth(1)); + lColumns.Add(c); + } + + private bool m_bUsedEntryViewColumnWidths = false; + private void InitListViewMain(ListView lv) + { + int w = lv.ClientSize.Width - UIUtil.GetVScrollBarWidth(); + int wf = w / (m_lEntryListColumns.Count); + int di = Math.Min(UIUtil.GetSmallIconSize().Width, wf); + + List lIndices = new List(); + + lIndices.Add(0); + for (int i = 0; i < m_lEntryListColumns.Count; i++) + { + lIndices.Add(i + 1); + int cw = wf; + if (i == 0) cw = wf + di; + if (i == m_lEntryListColumns.Count - 1) cw = wf - di; + + lv.Columns.Add(m_lEntryListColumns[i].GetDisplayName(), Config.UseEntryListColumnWidths ? m_lEntryListColumns[i].Width : cw); + } + UIUtil.SetDisplayIndices(lv, lIndices.ToArray()); + m_lEntryListColumns = null; + + m_bUsedEntryViewColumnWidths = Config.UseEntryListColumnWidths; + } + #endregion + + #region All 'Find' functions beside 'Search...' + private void OnClickFindEntry(object sender, EventArgs e) + { + string f = (sender as ToolStripItem).Name; + FindInfo fi = SearchHelp.FindList.Find(x => x.Name == (sender as ToolStripItem).Name); + + if (CallStandardSearch(fi, (sender as ToolStripItem).Name)) + { + if (fi != null) + { + foreach (Delegate d in fi.StandardEventHandlers) + d.DynamicInvoke(new object[] { sender, e }); + } + return; + } + + PluginDebug.AddInfo("Call own find routine", 0, "Action: " + f); + //Show status logger + Form fOptDialog = null; + IStatusLogger sl = StatusUtil.CreateStatusDialog(m_host.MainWindow, out fOptDialog, null, + (KPRes.SearchingOp ?? "..."), true, false); + m_host.MainWindow.UIBlockInteraction(true); + + m_aStandardLvInit = null; + + //Perform find for all open databases + PwDatabase dbAll = MergeDatabases(); + List l = null; + try + { + object[] parameters; + if (fi.SearchType != SearchType.BuiltIn) parameters = new object[] { dbAll, sl, null, fi }; + else parameters = new object[] { dbAll, sl, null }; + + l = (List)fi.StandardMethod.Invoke(m_host, parameters); + m_aStandardLvInit = (Action)parameters[2]; + } + catch (Exception ex) + { + l = null; + PluginDebug.AddError("Call standard find routine", 0, "Action: " + f, "Reason for standard call: " + ex.Message); + foreach (Delegate d in fi.StandardEventHandlers) + d.DynamicInvoke(new object[] { sender, e }); + } + finally { dbAll.Close(); } + + m_host.MainWindow.UIBlockInteraction(false); + sl.EndLogging(); + + if (l == null) return; + + //Fill db column + ImageList il = new ImageList(); + ImageList il2 = (ImageList)Tools.GetField("m_ilCurrentIcons", m_host.MainWindow); + foreach (Image img in il2.Images) + il.Images.Add(img); + + for (int i = 0; i < l.Count; i++) + { + ListViewItem lvi = GetObjectAsListViewItem(l[i]); + if (lvi == null) continue; + ListViewItem.ListViewSubItem lvsi = new ListViewItem.ListViewSubItem(); + if (lvi.Tag is PwEntry) + { + lvsi.Text = SearchHelp.GetDBName(lvi.Tag as PwEntry); + PwEntry pe = lvi.Tag as PwEntry; + PwDatabase db = m_host.MainWindow.DocumentManager.FindContainerOf(pe); + if (!pe.CustomIconUuid.Equals(PwUuid.Zero)) + { + il.Images.Add(db.GetCustomIcon(pe.CustomIconUuid, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16))); + lvi.ImageIndex = il.Images.Count - 1; + } + else lvi.ImageIndex = (int)pe.IconId; + } + else if (lvi.Tag is PwGroup) + { + PwGroup pg = lvi.Tag as PwGroup; + lvsi.Text = SearchHelp.GetDBName(pg.Entries.GetAt(0)); + } + l[i] = AddSubItemToListViewObject(l[i], lvi, lvsi); + } + + if ((l.Count == 0) && !string.IsNullOrEmpty(fi.NothingFound)) + { + Tools.ShowInfo(fi.NothingFound); + il.Dispose(); + return; + } + + //Show results + var dlg = new ResizableListViewForm(fi.Title, fi.SubTitle); + //Prepare ImageList (CustomIcons can be different per database) + dlg.InitEx(fi.Title, fi.SubTitle, fi.Note, fi.img, l, il, InitListView); + UIUtil.ShowDialogAndDestroy(dlg); + if (dlg.DialogResult != DialogResult.OK) return; + il.Dispose(); + NavigateToSelectedEntry(dlg, false); + } + + private object AddSubItemToListViewObject(object o, ListViewItem lvi, ListViewItem.ListViewSubItem lvsi) + { + if (o is ListViewItem) + { + (o as ListViewItem).SubItems.Insert(0, lvsi); + return o; + } + if (Tools.KeePassVersion < Util.KeePassVersion_2_54) return o; + //Could be KeePass 2.54 or higher and type LvfItem + lvi.SubItems.Insert(0, lvsi); + var c = o.GetType().GetConstructor(new Type[] { typeof(ListViewItem) }); + if (c != null) o = c.Invoke(new object[] { lvi }); + return o; + } + + private ListViewItem GetObjectAsListViewItem(object o) + { + ListViewItem lvi = o as ListViewItem; + if (lvi != null) return lvi; + if (Tools.KeePassVersion >= Util.KeePassVersion_2_54) + { + //Could be KeePass 2.54 or higher and type LvfItem + lvi = Tools.GetField("m_lvi", o) as ListViewItem; + } + return lvi; + } + + private void NavigateToSelectedEntry(ListViewForm dlg, bool CalledFromSearchForm) + { + PwGroup pg = dlg.ResultGroup as PwGroup; //parent group of selected entry + PwEntry pe = dlg.ResultItem as PwEntry; + if (pe == null) //try getting the virtual group for the selected entries database + { + object[] oEntryAndGroup = dlg.ResultItem as object[]; + if ((oEntryAndGroup != null) && (oEntryAndGroup.Length == 2)) + { + pe = oEntryAndGroup[0] as PwEntry; + pg = oEntryAndGroup[1] as PwGroup; + } + } + if (pe != null) ActivateDB(pe); + if ((pg == null) && (pe == null)) + pg = (dlg.ResultItem as PwGroup); + if ((pg != null) || (pe != null)) + { + if (pg != null) + { + PwDocument doc = null; + if (pe == null) + doc = m_host.MainWindow.DocumentManager.FindDocument(m_host.MainWindow.DocumentManager.SafeFindContainerOf(pg.Entries.GetAt(0))); + else + doc = m_host.MainWindow.DocumentManager.FindDocument(m_host.MainWindow.DocumentManager.SafeFindContainerOf(pe)); + bool bCleanUpDone = false; + for (int i = (int)pg.Entries.UCount - 1; i >= 0; i--) + { + if (doc != m_host.MainWindow.DocumentManager.FindDocument(m_host.MainWindow.DocumentManager.SafeFindContainerOf(pg.Entries.GetAt((uint)i)))) + { + bCleanUpDone = true; + pg.Entries.RemoveAt((uint)i); + } + } + if (bCleanUpDone && !CalledFromSearchForm) ShowMultiDBInfo(CalledFromSearchForm); + if (pg != null) + { + if (pe == null) pe = pg.Entries.GetAt(0); + foreach (KeyValuePair kvp in m_dDBGroups) + { + if (kvp.Value.FindEntry(pe.Uuid, true) != null) + { + pg = kvp.Value; + break; + } + } + } + m_host.MainWindow.UpdateUI(false, doc, false, null, true, pg, false, m_lvEntries); + } + else + { + PwDocument doc = m_host.MainWindow.DocumentManager.FindDocument(m_host.MainWindow.DocumentManager.SafeFindContainerOf(pe)); + m_host.MainWindow.UpdateUI(false, doc, true, pe.ParentGroup, true, null, false, m_lvEntries); + } + + MethodInfo mi = null; + if (pe != null) + { + KeePassLib.Collections.PwObjectList lSel = new KeePassLib.Collections.PwObjectList(); + lSel.Add(pe); + m_host.MainWindow.SelectEntries(lSel, true, true); + mi = m_host.MainWindow.GetType().GetMethod("EnsureVisibleSelected", BindingFlags.Instance | BindingFlags.NonPublic); + if (mi != null) mi.Invoke(m_host.MainWindow, new object[] { false }); + } + else + { + mi = m_host.MainWindow.GetType().GetMethod("SelectFirstEntryIfNoneSelected", BindingFlags.Instance | BindingFlags.NonPublic); + if (mi != null) mi.Invoke(m_host.MainWindow, null); + } + + mi = m_host.MainWindow.GetType().GetMethod("UpdateUIState", BindingFlags.Instance | BindingFlags.NonPublic, null, + new Type[] { typeof(bool) }, null); + if (mi != null) mi.Invoke(m_host.MainWindow, new object[] { false }); + } + m_dDBGroups.Clear(); + } + + private void ActivateDB(PwEntry pe) + { + PwDatabase db = m_host.MainWindow.DocumentManager.FindContainerOf(pe); + if (db == null) return; + PwDocument doc = m_host.MainWindow.DocumentManager.FindDocument(db); + if (doc == null) return; + m_host.MainWindow.MakeDocumentActive(doc); + } + + private bool CallStandardSearch(FindInfo fi, string sendername) + { + if (fi == null) + { + PluginDebug.AddError("Call standard find routine", 0, "Reason for standard call: FindInfo empty", "Event sender: " + sendername); + return true; + } + if (fi.StandardMethod == null) + { + PluginDebug.AddError("Call standard find routine", 0, "Action: " + fi.Name, "Reason for standard call: No hook for " + fi.Name); + return true; + } + if (m_host.MainWindow.DocumentManager.GetOpenDatabases().Count < 2) + { + PluginDebug.AddInfo("Call standard find routine", 0, "Action: " + fi.Name, "Reason for standard call: No more than one db opened"); + return true; + } + return false; + } + + private void InitListView(ListView lv) + { + if (m_aStandardLvInit == null) return; + m_aStandardLvInit(lv); + m_aStandardLvInit = null; + + int[] iDisplayIndices = new int[lv.Columns.Count + 1]; + int w = lv.ClientSize.Width - UIUtil.GetVScrollBarWidth(); + int wf = w / iDisplayIndices.Length; + iDisplayIndices[0] = 0; + int di = Math.Min(UIUtil.GetSmallIconSize().Width, wf); + for (int i = 0; i < lv.Columns.Count; i++) + { + iDisplayIndices[i + 1] = lv.Columns[i].DisplayIndex + 1; + if (!m_bUsedEntryViewColumnWidths) lv.Columns[i].Width = (i == lv.Columns.Count - 1) ? wf - di : wf; + } + lv.Columns.Insert(0, KPRes.Database, wf + di); + + if (ResizableListViewForm.ColumnsWidth.Count == lv.Columns.Count && !m_bUsedEntryViewColumnWidths) + { + for (int i = 0; i < lv.Columns.Count; i++) lv.Columns[i].Width = ResizableListViewForm.ColumnsWidth[i]; + } + m_bUsedEntryViewColumnWidths = false; + + UIUtil.SetDisplayIndices(lv, iDisplayIndices); + } + + private PwDatabase MergeDatabases() + { + PwDatabase dbAll = new PwDatabase(); + dbAll.New(new KeePassLib.Serialization.IOConnectionInfo(), new KeePassLib.Keys.CompositeKey()); + foreach (PwDatabase db in m_host.MainWindow.DocumentManager.GetOpenDatabases()) + { + dbAll.RootGroup.AddGroup(db.RootGroup, false, false); + } + return dbAll; + } + + private void ReplaceFindHandlers() + { + GetFindHandlers(); + foreach (FindInfo fi in SearchHelp.FindList) + { + if (string.IsNullOrEmpty(fi.Func)) + continue; + if (!Config.HookActive(fi.Name)) continue; + if (fi.tsiMenuItem == null) continue; + if (fi.tsiMenuItem.IsDisposed) continue; + fi.tsiMenuItem.RemoveEventHandlers("Click", fi.StandardEventHandlers); + fi.tsiMenuItem.Click += OnClickFindEntry; + } + } + + private void GetFindHandlers() + { + foreach (FindInfo fi in SearchHelp.FindList) + { + if (string.IsNullOrEmpty(fi.Func)) continue; + if (fi.img == null) fi.img = SmallIcon; + if (fi.tsiMenuItem == null) + fi.StandardEventHandlers = new List(); + else + fi.StandardEventHandlers = fi.tsiMenuItem.GetEventHandlers("Click"); + } + } + + private void RestoreFindHandlers() + { + foreach (FindInfo fi in SearchHelp.FindList) + { + if (fi.tsiMenuItem == null) continue; + if (fi.tsiMenuItem.IsDisposed) continue; + fi.tsiMenuItem.Click -= OnClickFindEntry; + fi.tsiMenuItem.RemoveEventHandlers("Click", fi.StandardEventHandlers); + fi.tsiMenuItem.AddEventHandlers("Click", fi.StandardEventHandlers); + } + } + #endregion + + #region Options + private void OnShowOptions(object sender, EventArgs e) + { + Tools.ShowOptions(); + } + + private void Tools_OptionsFormShown(object sender, Tools.OptionsFormsEventArgs e) + { + Options o = new Options(); + o.InitEx(); + Tools.AddPluginToOptionsForm(this, o); + } + + private void Tools_OptionsFormClosed(object sender, Tools.OptionsFormsEventArgs e) + { + if (e.form.DialogResult != DialogResult.OK) return; + bool bShown = false; + Options o = (Options)Tools.GetPluginFromOptions(this, out bShown); + if (!bShown) return; + o.UpdateConfig(); + Activate(); + } + #endregion + + #region General stuff + private void GetStandardMethods() + { + m_miUpdateColumnsEx = m_host.MainWindow.GetType().GetMethod("UpdateColumnsEx", BindingFlags.Instance | BindingFlags.NonPublic); + if (m_miUpdateColumnsEx == null) PluginDebug.AddError("Could not get method 'UpdateColumnsEx'", 0); + + m_miGetEntryFieldEx = m_host.MainWindow.GetType().GetMethod("GetEntryFieldEx", BindingFlags.Instance | BindingFlags.NonPublic); + if (m_miGetEntryFieldEx == null) PluginDebug.AddError("Could not get method 'GetEntryFieldEx'", 0); + + try + { + Type t = typeof(KeePass.Program).Assembly.GetType("KeePass.UI.AsyncPwListUpdate"); + m_miSprCompileFn = t.GetMethod("SprCompileFn", BindingFlags.Static | BindingFlags.NonPublic); + } + catch { } + if (m_miSprCompileFn == null) PluginDebug.AddError("Could not get method 'SprCompileFn'", 0); + } + + private void Activate() + { + if ((m_miUpdateColumnsEx == null) || (m_lvEntries == null)) + { + Tools.ShowError(string.Format(PluginTranslate.ErrorNoActivation, PluginTranslate.PluginName)); + return; + } + + GlobalWindowManager.WindowAdded -= OnSearchFormAdded; + GlobalWindowManager.WindowAdded += OnSearchFormAdded; + + RestoreFindHandlers(); + ReplaceFindHandlers(); + } + + public void ShowMultiDBInfo(bool CalledFromSearchForm) + { + if (CalledFromSearchForm && Config.ShowMultiDBInfoSearchForm) + { + DialogResult dr = MessageBox.Show(string.Format(PluginTranslate.MultiDBSearchInfoSearchForm, KPRes.No), PluginTranslate.PluginName, MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button2); + Config.ShowMultiDBInfoSearchForm = dr == DialogResult.Yes; + } + else if (!CalledFromSearchForm && Config.ShowMultiDBInfoSingleSearch) + { + DialogResult dr = MessageBox.Show(string.Format(PluginTranslate.MultiDBSearchInfoSingleSearch, KPRes.No), PluginTranslate.PluginName, MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button2); + Config.ShowMultiDBInfoSingleSearch = dr == DialogResult.Yes; + } + } + #endregion + + public override void Terminate() + { + if (m_host == null) return; + + RestoreFindHandlers(); + + GlobalWindowManager.WindowAdded -= OnSearchFormAdded; + m_host.MainWindow.ToolsMenu.DropDownItems.Remove(m_menu); + Tools.OptionsFormShown -= Tools_OptionsFormShown; + Tools.OptionsFormClosed -= Tools_OptionsFormClosed; + m_menu.Click -= OnShowOptions; + + if ((m_menu != null) && !m_menu.IsDisposed) + m_menu.Dispose(); + if ((m_cbSearchAllDatabases != null) && !m_cbSearchAllDatabases.IsDisposed) + m_cbSearchAllDatabases.Dispose(); + + PluginDebug.SaveOrShow(); + + m_host = null; + } + + public override string UpdateUrl + { + get { return "https://raw.githubusercontent.com/rookiestyle/globalsearch/master/version.info"; } + } + + public override Image SmallIcon + { + get { return m_img; } + } + } + + internal class ResizableListViewForm : ListViewForm + { + internal static readonly Size NoSize = new Size(-9999, -9999); + internal static readonly Point NoLocation = new Point(-9999, -9999); + private string m_sTitle; + private string m_sSubtitle; + + public static List ColumnsWidth = new List(); + internal ResizableListViewForm(string sTitle, string sSubtitle) : base() + { + PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, "Active: " + Config.AllowResize.ToString()); + if (!Config.AllowResize) return; + m_sTitle = sTitle; + m_sSubtitle = sSubtitle; + FormBorderStyle = FormBorderStyle.Sizable; + FormClosed += ResizableListViewForm_FormClosed; + Activated += ResizableListViewForm_Activated; + Resize += ResizableListViewForm_Resize; + } + + private void ResizableListViewForm_Activated(object sender, EventArgs e) + { + Activated -= ResizableListViewForm_Activated; + var sSize = Config.SearchResultSize; + var pLocation = Config.SearchResultLocation; + if (sSize.Width == NoSize.Width || sSize.Height == NoSize.Height) return; + if (pLocation.X == NoLocation.X || pLocation.Y == NoLocation.Y) return; + + Rectangle rectRestWindow = new Rectangle(pLocation, sSize); + bool bWndPartVisible = UIUtil.IsScreenAreaVisible(rectRestWindow); + if (!bWndPartVisible) + { + PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, + "Restore size and position", + "Restored window would not be visible", + "Size:" + sSize.ToString(), + "Location: " + pLocation.ToString()); + } + PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, + "Restore size and position", + "Size:" + sSize.ToString(), + "Location: " + pLocation.ToString()); + + Location = pLocation; + Size = sSize; + } + + public bool RememberColumnWidths = true; + + private void ResizableListViewForm_FormClosed(object sender, FormClosedEventArgs e) + { + Config.SearchResultSize = Size; + Config.SearchResultLocation = Location; + if (RememberColumnWidths) ColumnsWidth.Clear(); + ListView lvMain = Tools.GetControl("m_lvMain", this) as ListView; + if (lvMain == null) + { + PluginDebug.AddError("GlobalSearch - Make resizable", 0, "Saved size & position", "Saved 0 column widths", "Could not get m_lvMain"); + return; + } + if (RememberColumnWidths) + { + foreach (ColumnHeader c in lvMain.Columns) { - ListViewItem lvi = o as ListViewItem; - if (lvi != null) return lvi; - if (Tools.KeePassVersion >= Util.KeePassVersion_2_54) - { - //Could be KeePass 2.54 or higher and type LvfItem - lvi = Tools.GetField("m_lvi", o) as ListViewItem; - } - return lvi; - } - - private void NavigateToSelectedEntry(ListViewForm dlg, bool CalledFromSearchForm) - { - PwGroup pg = dlg.ResultGroup as PwGroup; //parent group of selected entry - PwEntry pe = dlg.ResultItem as PwEntry; - if (pe == null) //try getting the virtual group for the selected entries database - { - object[] oEntryAndGroup = dlg.ResultItem as object[]; - if ((oEntryAndGroup != null) && (oEntryAndGroup.Length == 2)) - { - pe = oEntryAndGroup[0] as PwEntry; - pg = oEntryAndGroup[1] as PwGroup; - } - } - if (pe != null) ActivateDB(pe); - if ((pg == null) && (pe == null)) - pg = (dlg.ResultItem as PwGroup); - if ((pg != null) || (pe != null)) - { - if (pg != null) - { - PwDocument doc = null; - if (pe == null) - doc = m_host.MainWindow.DocumentManager.FindDocument(m_host.MainWindow.DocumentManager.SafeFindContainerOf(pg.Entries.GetAt(0))); - else - doc = m_host.MainWindow.DocumentManager.FindDocument(m_host.MainWindow.DocumentManager.SafeFindContainerOf(pe)); - bool bCleanUpDone = false; - for (int i = (int)pg.Entries.UCount - 1; i >= 0; i--) - { - if (doc != m_host.MainWindow.DocumentManager.FindDocument(m_host.MainWindow.DocumentManager.SafeFindContainerOf(pg.Entries.GetAt((uint)i)))) - { - bCleanUpDone = true; - pg.Entries.RemoveAt((uint)i); - } - } - if (bCleanUpDone && !CalledFromSearchForm) ShowMultiDBInfo(CalledFromSearchForm); - if (pg != null) - { - if (pe == null) pe = pg.Entries.GetAt(0); - foreach (KeyValuePair kvp in m_dDBGroups) - { - if (kvp.Value.FindEntry(pe.Uuid, true) != null) - { - pg = kvp.Value; - break; - } - } - } - m_host.MainWindow.UpdateUI(false, doc, false, null, true, pg, false, m_lvEntries); - } - else - { - PwDocument doc = m_host.MainWindow.DocumentManager.FindDocument(m_host.MainWindow.DocumentManager.SafeFindContainerOf(pe)); - m_host.MainWindow.UpdateUI(false, doc, true, pe.ParentGroup, true, null, false, m_lvEntries); - } - - MethodInfo mi = null; - if (pe != null) - { - KeePassLib.Collections.PwObjectList lSel = new KeePassLib.Collections.PwObjectList(); - lSel.Add(pe); - m_host.MainWindow.SelectEntries(lSel, true, true); - mi = m_host.MainWindow.GetType().GetMethod("EnsureVisibleSelected", BindingFlags.Instance | BindingFlags.NonPublic); - if (mi != null) mi.Invoke(m_host.MainWindow, new object[] { false }); - } - else - { - mi = m_host.MainWindow.GetType().GetMethod("SelectFirstEntryIfNoneSelected", BindingFlags.Instance | BindingFlags.NonPublic); - if (mi != null) mi.Invoke(m_host.MainWindow, null); - } - - mi = m_host.MainWindow.GetType().GetMethod("UpdateUIState", BindingFlags.Instance | BindingFlags.NonPublic, null, - new Type[] { typeof(bool) }, null); - if (mi != null) mi.Invoke(m_host.MainWindow, new object[] { false }); - } - m_dDBGroups.Clear(); - } - - private void ActivateDB(PwEntry pe) - { - PwDatabase db = m_host.MainWindow.DocumentManager.FindContainerOf(pe); - if (db == null) return; - PwDocument doc = m_host.MainWindow.DocumentManager.FindDocument(db); - if (doc == null) return; - m_host.MainWindow.MakeDocumentActive(doc); - } - - private bool CallStandardSearch(FindInfo fi, string sendername) - { - if (fi == null) - { - PluginDebug.AddError("Call standard find routine", 0, "Reason for standard call: FindInfo empty", "Event sender: " + sendername); - return true; - } - if (fi.StandardMethod == null) - { - PluginDebug.AddError("Call standard find routine", 0, "Action: " + fi.Name, "Reason for standard call: No hook for " + fi.Name); - return true; - } - if (m_host.MainWindow.DocumentManager.GetOpenDatabases().Count < 2) - { - PluginDebug.AddInfo("Call standard find routine", 0, "Action: " + fi.Name, "Reason for standard call: No more than one db opened"); - return true; - } - return false; - } - - private void InitListView(ListView lv) - { - if (m_aStandardLvInit == null) return; - m_aStandardLvInit(lv); - m_aStandardLvInit = null; - - int[] iDisplayIndices = new int[lv.Columns.Count + 1]; - int w = lv.ClientSize.Width - UIUtil.GetVScrollBarWidth(); - int wf = w / iDisplayIndices.Length; - iDisplayIndices[0] = 0; - int di = Math.Min(UIUtil.GetSmallIconSize().Width, wf); - for (int i = 0; i < lv.Columns.Count; i++) - { - iDisplayIndices[i + 1] = lv.Columns[i].DisplayIndex + 1; - if (!m_bUsedEntryViewColumnWidths) lv.Columns[i].Width = (i == lv.Columns.Count - 1) ? wf - di : wf; - } - lv.Columns.Insert(0, KPRes.Database, wf + di); - - if (ResizableListViewForm.ColumnsWidth.Count == lv.Columns.Count && !m_bUsedEntryViewColumnWidths) - { - for (int i = 0; i < lv.Columns.Count; i++) lv.Columns[i].Width = ResizableListViewForm.ColumnsWidth[i]; - } - m_bUsedEntryViewColumnWidths = false; - - UIUtil.SetDisplayIndices(lv, iDisplayIndices); - } - - private PwDatabase MergeDatabases() - { - PwDatabase dbAll = new PwDatabase(); - dbAll.New(new KeePassLib.Serialization.IOConnectionInfo(), new KeePassLib.Keys.CompositeKey()); - foreach (PwDatabase db in m_host.MainWindow.DocumentManager.GetOpenDatabases()) - { - dbAll.RootGroup.AddGroup(db.RootGroup, false, false); - } - return dbAll; - } - - private void ReplaceFindHandlers() - { - GetFindHandlers(); - foreach (FindInfo fi in SearchHelp.FindList) - { - if (string.IsNullOrEmpty(fi.Func)) - continue; - if (!Config.HookActive(fi.Name)) continue; - if (fi.tsiMenuItem == null) continue; - if (fi.tsiMenuItem.IsDisposed) continue; - fi.tsiMenuItem.RemoveEventHandlers("Click", fi.StandardEventHandlers); - fi.tsiMenuItem.Click += OnClickFindEntry; - } - } - - private void GetFindHandlers() - { - foreach (FindInfo fi in SearchHelp.FindList) - { - if (string.IsNullOrEmpty(fi.Func)) continue; - if (fi.img == null) fi.img = SmallIcon; - if (fi.tsiMenuItem == null) - fi.StandardEventHandlers = new List(); - else - fi.StandardEventHandlers = fi.tsiMenuItem.GetEventHandlers("Click"); - } - } - - private void RestoreFindHandlers() - { - foreach (FindInfo fi in SearchHelp.FindList) - { - if (fi.tsiMenuItem == null) continue; - if (fi.tsiMenuItem.IsDisposed) continue; - fi.tsiMenuItem.Click -= OnClickFindEntry; - fi.tsiMenuItem.RemoveEventHandlers("Click", fi.StandardEventHandlers); - fi.tsiMenuItem.AddEventHandlers("Click", fi.StandardEventHandlers); - } - } - #endregion - - #region Options - private void OnShowOptions(object sender, EventArgs e) - { - Tools.ShowOptions(); - } - - private void Tools_OptionsFormShown(object sender, Tools.OptionsFormsEventArgs e) - { - Options o = new Options(); - o.InitEx(); - Tools.AddPluginToOptionsForm(this, o); - } - - private void Tools_OptionsFormClosed(object sender, Tools.OptionsFormsEventArgs e) - { - if (e.form.DialogResult != DialogResult.OK) return; - bool bShown = false; - Options o = (Options)Tools.GetPluginFromOptions(this, out bShown); - if (!bShown) return; - o.UpdateConfig(); - Activate(); - } - #endregion - - #region General stuff - private void GetStandardMethods() - { - m_miUpdateColumnsEx = m_host.MainWindow.GetType().GetMethod("UpdateColumnsEx", BindingFlags.Instance | BindingFlags.NonPublic); - if (m_miUpdateColumnsEx == null) PluginDebug.AddError("Could not get method 'UpdateColumnsEx'", 0); - - m_miGetEntryFieldEx = m_host.MainWindow.GetType().GetMethod("GetEntryFieldEx", BindingFlags.Instance | BindingFlags.NonPublic); - if (m_miGetEntryFieldEx == null) PluginDebug.AddError("Could not get method 'GetEntryFieldEx'", 0); - - try - { - Type t = typeof(KeePass.Program).Assembly.GetType("KeePass.UI.AsyncPwListUpdate"); - m_miSprCompileFn = t.GetMethod("SprCompileFn", BindingFlags.Static | BindingFlags.NonPublic); - } - catch { } - if (m_miSprCompileFn == null) PluginDebug.AddError("Could not get method 'SprCompileFn'", 0); - } - - private void Activate() - { - if ((m_miUpdateColumnsEx == null) || (m_lvEntries == null)) - { - Tools.ShowError(string.Format(PluginTranslate.ErrorNoActivation, PluginTranslate.PluginName)); - return; - } - - GlobalWindowManager.WindowAdded -= OnSearchFormAdded; - GlobalWindowManager.WindowAdded += OnSearchFormAdded; - - RestoreFindHandlers(); - ReplaceFindHandlers(); - } - - public void ShowMultiDBInfo(bool CalledFromSearchForm) - { - if (CalledFromSearchForm && Config.ShowMultiDBInfoSearchForm) - { - DialogResult dr = MessageBox.Show(string.Format(PluginTranslate.MultiDBSearchInfoSearchForm, KPRes.No), PluginTranslate.PluginName, MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button2); - Config.ShowMultiDBInfoSearchForm = dr == DialogResult.Yes; - } - else if (!CalledFromSearchForm && Config.ShowMultiDBInfoSingleSearch) - { - DialogResult dr = MessageBox.Show(string.Format(PluginTranslate.MultiDBSearchInfoSingleSearch, KPRes.No), PluginTranslate.PluginName, MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button2); - Config.ShowMultiDBInfoSingleSearch = dr == DialogResult.Yes; - } - } - #endregion - - public override void Terminate() - { - if (m_host == null) return; - - RestoreFindHandlers(); - - GlobalWindowManager.WindowAdded -= OnSearchFormAdded; - m_host.MainWindow.ToolsMenu.DropDownItems.Remove(m_menu); - Tools.OptionsFormShown -= Tools_OptionsFormShown; - Tools.OptionsFormClosed -= Tools_OptionsFormClosed; - m_menu.Click -= OnShowOptions; - - if ((m_menu != null) && !m_menu.IsDisposed) - m_menu.Dispose(); - if ((m_cbSearchAllDatabases != null) && !m_cbSearchAllDatabases.IsDisposed) - m_cbSearchAllDatabases.Dispose(); - - PluginDebug.SaveOrShow(); - - m_host = null; - } - - public override string UpdateUrl - { - get { return "https://raw.githubusercontent.com/rookiestyle/globalsearch/master/version.info"; } - } - - public override Image SmallIcon - { - get { return m_img; } - } - } - - internal class ResizableListViewForm : ListViewForm - { - internal static readonly Size NoSize = new Size(-9999, -9999); - internal static readonly Point NoLocation = new Point(-9999, -9999); - private string m_sTitle; - private string m_sSubtitle; - - public static List ColumnsWidth = new List(); - internal ResizableListViewForm(string sTitle, string sSubtitle) : base() - { - PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, "Active: " + Config.AllowResize.ToString()); - if (!Config.AllowResize) return; - m_sTitle = sTitle; - m_sSubtitle = sSubtitle; - FormBorderStyle = FormBorderStyle.Sizable; - FormClosed += ResizableListViewForm_FormClosed; - Activated += ResizableListViewForm_Activated; - Resize += ResizableListViewForm_Resize; - } - - private void ResizableListViewForm_Activated(object sender, EventArgs e) - { - Activated -= ResizableListViewForm_Activated; - var sSize = Config.SearchResultSize; - var pLocation = Config.SearchResultLocation; - if (sSize.Width == NoSize.Width || sSize.Height == NoSize.Height) return; - if (pLocation.X == NoLocation.X || pLocation.Y == NoLocation.Y) return; - - Rectangle rectRestWindow = new Rectangle(pLocation, sSize); - bool bWndPartVisible = UIUtil.IsScreenAreaVisible(rectRestWindow); - if (!bWndPartVisible) - { - PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, - "Restore size and position", - "Restored window would not be visible", - "Size:" + sSize.ToString(), - "Location: " + pLocation.ToString()); - } - PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, - "Restore size and position", - "Size:" + sSize.ToString(), - "Location: " + pLocation.ToString()); - - Location = pLocation; - Size = sSize; - } - - public bool RememberColumnWidths = true; - - private void ResizableListViewForm_FormClosed(object sender, FormClosedEventArgs e) - { - Config.SearchResultSize = Size; - Config.SearchResultLocation = Location; - if (RememberColumnWidths) ColumnsWidth.Clear(); - ListView lvMain = Tools.GetControl("m_lvMain", this) as ListView; - if (lvMain == null) - { - PluginDebug.AddError("GlobalSearch - Make resizable", 0, "Saved size & position", "Saved 0 column widths", "Could not get m_lvMain"); - return; - } - if (RememberColumnWidths) - { - foreach (ColumnHeader c in lvMain.Columns) - { - ColumnsWidth.Add(c.Width); - } - PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, "Saved size & position", "Saved 0 column widths"); - } - else PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, "Saved size & position", "Saved " + lvMain.Columns.Count.ToString() + " column widths"); - } - - private void ResizableListViewForm_Resize(object sender, EventArgs e) - { - foreach (Control c in Controls) - { - int iDummy = 1; - c.Width = ClientSize.Width - c.Left * 2; - if (c is PictureBox) BannerFactory.UpdateBanner(this, c as PictureBox, null, m_sTitle, m_sSubtitle, ref iDummy); - if (c is ListView) c.Height = ClientSize.Height - c.Top - c.Margin.Top - c.Parent.Margin.Top - c.Margin.Bottom - c.Parent.Margin.Bottom; - } - } - } + ColumnsWidth.Add(c.Width); + } + PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, "Saved size & position", "Saved 0 column widths"); + } + else PluginDebug.AddInfo("GlobalSearch - Make resizable", 0, "Saved size & position", "Saved " + lvMain.Columns.Count.ToString() + " column widths"); + } + + private void ResizableListViewForm_Resize(object sender, EventArgs e) + { + foreach (Control c in Controls) + { + int iDummy = 1; + c.Width = ClientSize.Width - c.Left * 2; + if (c is PictureBox) BannerFactory.UpdateBanner(this, c as PictureBox, null, m_sTitle, m_sSubtitle, ref iDummy); + if (c is ListView) c.Height = ClientSize.Height - c.Top - c.Margin.Top - c.Parent.Margin.Top - c.Margin.Bottom - c.Parent.Margin.Bottom; + } + } + } } diff --git a/src/Options.cs b/src/Options.cs index a14c884..8b53339 100644 --- a/src/Options.cs +++ b/src/Options.cs @@ -1,141 +1,139 @@ using System; using System.ComponentModel; +using System.Drawing; using System.Reflection; using System.Windows.Forms; -using System.Drawing; - using KeePass.Plugins; using KeePass.UI; using KeePassLib; - -using PluginTranslation; using PluginTools; +using PluginTranslation; namespace GlobalSearch { - /// - /// Description of Options. - /// - /// - public partial class Options : UserControl - { - private TreeNode tvnSearchForm { get { return tvHookedSearches.Nodes.Find("tvnSearchForm", true)[0]; } } - private TreeNode tvnUseEntryListColummnWidth { get { return tvHookedSearches.Nodes.Find("tvnUseEntryListColummnWidth", true)[0]; } } - private TreeNode tvnLastMod { get { return tvHookedSearches.Nodes.Find("tvnLastMod", true)[0]; } } - private TreeNode tvnLargeEntries { get { return tvHookedSearches.Nodes.Find("tvnLargeEntries", true)[0]; } } - private TreeNode tvnDupPw { get { return tvHookedSearches.Nodes.Find("tvnDupPw", true)[0]; } } - private TreeNode tvnSimPwPairs { get { return tvHookedSearches.Nodes.Find("tvnSimPwPairs", true)[0]; } } - private TreeNode tvnSimPwCluster { get { return tvHookedSearches.Nodes.Find("tvnSimPwCluster", true)[0]; } } - private TreeNode tvnPwQuality { get { return tvHookedSearches.Nodes.Find("tvnPwQuality", true)[0]; } } - private TreeNode tvnExpired { get { return tvHookedSearches.Nodes.Find("tvnExpired", true)[0]; } } - - public Options() - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - // - // TODO: Add constructor code after the InitializeComponent() call. - // - Text = PluginTranslate.PluginName; - tpOptions.Text = PluginTranslate.OptionsCaption; - tpHelp.Text = KeePass.Resources.KPRes.Description; - AdjustNode(tvnSearchForm, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchForm)); - - tvnUseEntryListColummnWidth.Text = PluginTranslate.UseEntryListColumnWidths; - - AdjustNode(tvnLastMod, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchLastMod)); - AdjustNode(tvnLargeEntries, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchLargeEntries)); - AdjustNode(tvnDupPw, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchDupPw)); - AdjustNode(tvnSimPwPairs, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchPasswordPairs)); - AdjustNode(tvnSimPwCluster, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchPasswordClusters)); - AdjustNode(tvnPwQuality, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchPasswordQuality)); - AdjustNode(tvnExpired, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchExpired)); - tvnExpired.Text = KeePass.Resources.KPRes.ExpiredEntries; - - cbMultiDBSearchInfoSearchFormActive.Text = string.Format(PluginTranslate.MultiDBSearchInfoSearchFormActive, tvnSearchForm.Text); - cbMultiDBSearchInfoSingleSearchActive.Text = PluginTranslate.MultiDBSearchInfoSingleSearchActive; - string sDesc = string.Format(PluginTranslate.Description, PluginTranslate.PluginName, tvnSearchForm.Text); - tbDesc.Lines = sDesc.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); - - gSearches.Text = KeePass.Resources.KPRes.SearchingOp; - gPWDisplay.Text = PluginTranslate.PWDisplayMode; - rbPWDisplayAlways.Text = PluginTranslate.PWDisplayModeAlways; - rbPWDisplayNever.Text = PluginTranslate.PWDisplayModeNever; - rbPWDisplayEntryList.Text = PluginTranslate.PWDisplayModeEntryView; - } - - private void SetDisabled(TreeNode t) - { - t.NodeFont = new Font(t.NodeFont == null ? t.TreeView.Font : t.NodeFont, FontStyle.Strikeout); - } - - private bool IsEnabled(TreeNode t) - { - return t.NodeFont == null || !t.NodeFont.Strikeout; - } - - public void InitEx() - { - tvnSearchForm.Checked = Config.SearchForm; - tvnUseEntryListColummnWidth.Checked = Config.UseEntryListColumnWidths; - tvnDupPw.Checked = IsEnabled(tvnDupPw) && Config.HookSearchDupPw; - tvnSimPwPairs.Checked = IsEnabled(tvnSimPwPairs) && Config.HookSearchPwPairs; - tvnSimPwCluster.Checked = IsEnabled(tvnSimPwCluster) && Config.HookSearchPwCluster; - tvnPwQuality.Checked = IsEnabled(tvnPwQuality) && Config.HookPwQuality; - tvnLargeEntries.Checked = IsEnabled(tvnLargeEntries) && Config.HookLargeEntries; - tvnLastMod.Checked = IsEnabled(tvnLastMod) && Config.HookLastMod; - tvnExpired.Checked = IsEnabled(tvnExpired) && Config.HookAllExpired; - cbMultiDBSearchInfoSearchFormActive.Checked = Config.ShowMultiDBInfoSearchForm; - cbMultiDBSearchInfoSingleSearchActive.Checked = Config.ShowMultiDBInfoSingleSearch; - SetPwDisplayMode(Config.PasswordDisplay); - } - - public void UpdateConfig() - { - Config.SearchForm = tvnSearchForm.Checked; - Config.UseEntryListColumnWidths = tvnUseEntryListColummnWidth.Checked; - if (IsEnabled(tvnDupPw)) Config.HookSearchDupPw = tvnDupPw.Checked; - if (IsEnabled(tvnSimPwPairs)) Config.HookSearchPwPairs = tvnSimPwPairs.Checked; - if (IsEnabled(tvnSimPwCluster)) Config.HookSearchPwCluster = tvnSimPwCluster.Checked; - if (IsEnabled(tvnPwQuality)) Config.HookPwQuality = tvnPwQuality.Checked; - if (IsEnabled(tvnLargeEntries)) Config.HookLargeEntries = tvnLargeEntries.Checked; - if (IsEnabled(tvnLastMod)) Config.HookLastMod = tvnLastMod.Checked; - if (IsEnabled(tvnExpired)) Config.HookAllExpired = tvnExpired.Checked; - Config.ShowMultiDBInfoSearchForm = cbMultiDBSearchInfoSearchFormActive.Checked; - Config.ShowMultiDBInfoSingleSearch = cbMultiDBSearchInfoSingleSearchActive.Checked; - Config.PasswordDisplay = GetPwDisplayMode(); - } - - private void AdjustNode(TreeNode t, FindInfo fiInfo) - { - t.Text = fiInfo.OptionsText.Replace("&", string.Empty); - if (fiInfo.StandardMethod != null || (fiInfo.Name == SearchHelp.SearchForm)) return; - SetDisabled(t); - } - - private void SetPwDisplayMode(Config.PasswordDisplayMode m) - { - gPWDisplay.Visible = gPWDisplay.Enabled = Tools.KeePassVersion < Util.KeePassVersion_2_54; - rbPWDisplayAlways.Checked = true; - if (m == Config.PasswordDisplayMode.Never) rbPWDisplayNever.Checked = true; - if (m == Config.PasswordDisplayMode.EntryviewBased) rbPWDisplayEntryList.Checked = true; - } - - private Config.PasswordDisplayMode GetPwDisplayMode() - { - if (rbPWDisplayNever.Checked) return Config.PasswordDisplayMode.Never; - if (rbPWDisplayEntryList.Checked) return Config.PasswordDisplayMode.EntryviewBased; - return Config.PasswordDisplayMode.Always; - } - - private void tvHookedSearches_BeforeChecked(object sender, TreeViewCancelEventArgs e) - { - if (IsEnabled(e.Node)) return; - e.Cancel = true; - } - } + /// + /// Description of Options. + /// + /// + public partial class Options : UserControl + { + private TreeNode tvnSearchForm { get { return tvHookedSearches.Nodes.Find("tvnSearchForm", true)[0]; } } + private TreeNode tvnUseEntryListColummnWidth { get { return tvHookedSearches.Nodes.Find("tvnUseEntryListColummnWidth", true)[0]; } } + private TreeNode tvnLastMod { get { return tvHookedSearches.Nodes.Find("tvnLastMod", true)[0]; } } + private TreeNode tvnLargeEntries { get { return tvHookedSearches.Nodes.Find("tvnLargeEntries", true)[0]; } } + private TreeNode tvnDupPw { get { return tvHookedSearches.Nodes.Find("tvnDupPw", true)[0]; } } + private TreeNode tvnSimPwPairs { get { return tvHookedSearches.Nodes.Find("tvnSimPwPairs", true)[0]; } } + private TreeNode tvnSimPwCluster { get { return tvHookedSearches.Nodes.Find("tvnSimPwCluster", true)[0]; } } + private TreeNode tvnPwQuality { get { return tvHookedSearches.Nodes.Find("tvnPwQuality", true)[0]; } } + private TreeNode tvnExpired { get { return tvHookedSearches.Nodes.Find("tvnExpired", true)[0]; } } + + public Options() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + // + // TODO: Add constructor code after the InitializeComponent() call. + // + Text = PluginTranslate.PluginName; + tpOptions.Text = PluginTranslate.OptionsCaption; + tpHelp.Text = KeePass.Resources.KPRes.Description; + AdjustNode(tvnSearchForm, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchForm)); + + tvnUseEntryListColummnWidth.Text = PluginTranslate.UseEntryListColumnWidths; + + AdjustNode(tvnLastMod, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchLastMod)); + AdjustNode(tvnLargeEntries, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchLargeEntries)); + AdjustNode(tvnDupPw, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchDupPw)); + AdjustNode(tvnSimPwPairs, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchPasswordPairs)); + AdjustNode(tvnSimPwCluster, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchPasswordClusters)); + AdjustNode(tvnPwQuality, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchPasswordQuality)); + AdjustNode(tvnExpired, SearchHelp.FindList.Find(x => x.Name == SearchHelp.SearchExpired)); + tvnExpired.Text = KeePass.Resources.KPRes.ExpiredEntries; + + cbMultiDBSearchInfoSearchFormActive.Text = string.Format(PluginTranslate.MultiDBSearchInfoSearchFormActive, tvnSearchForm.Text); + cbMultiDBSearchInfoSingleSearchActive.Text = PluginTranslate.MultiDBSearchInfoSingleSearchActive; + string sDesc = string.Format(PluginTranslate.Description, PluginTranslate.PluginName, tvnSearchForm.Text); + tbDesc.Lines = sDesc.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + + gSearches.Text = KeePass.Resources.KPRes.SearchingOp; + gPWDisplay.Text = PluginTranslate.PWDisplayMode; + rbPWDisplayAlways.Text = PluginTranslate.PWDisplayModeAlways; + rbPWDisplayNever.Text = PluginTranslate.PWDisplayModeNever; + rbPWDisplayEntryList.Text = PluginTranslate.PWDisplayModeEntryView; + } + + private void SetDisabled(TreeNode t) + { + t.NodeFont = new Font(t.NodeFont == null ? t.TreeView.Font : t.NodeFont, FontStyle.Strikeout); + } + + private bool IsEnabled(TreeNode t) + { + return t.NodeFont == null || !t.NodeFont.Strikeout; + } + + public void InitEx() + { + tvnSearchForm.Checked = Config.SearchForm; + tvnUseEntryListColummnWidth.Checked = Config.UseEntryListColumnWidths; + tvnDupPw.Checked = IsEnabled(tvnDupPw) && Config.HookSearchDupPw; + tvnSimPwPairs.Checked = IsEnabled(tvnSimPwPairs) && Config.HookSearchPwPairs; + tvnSimPwCluster.Checked = IsEnabled(tvnSimPwCluster) && Config.HookSearchPwCluster; + tvnPwQuality.Checked = IsEnabled(tvnPwQuality) && Config.HookPwQuality; + tvnLargeEntries.Checked = IsEnabled(tvnLargeEntries) && Config.HookLargeEntries; + tvnLastMod.Checked = IsEnabled(tvnLastMod) && Config.HookLastMod; + tvnExpired.Checked = IsEnabled(tvnExpired) && Config.HookAllExpired; + cbMultiDBSearchInfoSearchFormActive.Checked = Config.ShowMultiDBInfoSearchForm; + cbMultiDBSearchInfoSingleSearchActive.Checked = Config.ShowMultiDBInfoSingleSearch; + SetPwDisplayMode(Config.PasswordDisplay); + } + + public void UpdateConfig() + { + Config.SearchForm = tvnSearchForm.Checked; + Config.UseEntryListColumnWidths = tvnUseEntryListColummnWidth.Checked; + if (IsEnabled(tvnDupPw)) Config.HookSearchDupPw = tvnDupPw.Checked; + if (IsEnabled(tvnSimPwPairs)) Config.HookSearchPwPairs = tvnSimPwPairs.Checked; + if (IsEnabled(tvnSimPwCluster)) Config.HookSearchPwCluster = tvnSimPwCluster.Checked; + if (IsEnabled(tvnPwQuality)) Config.HookPwQuality = tvnPwQuality.Checked; + if (IsEnabled(tvnLargeEntries)) Config.HookLargeEntries = tvnLargeEntries.Checked; + if (IsEnabled(tvnLastMod)) Config.HookLastMod = tvnLastMod.Checked; + if (IsEnabled(tvnExpired)) Config.HookAllExpired = tvnExpired.Checked; + Config.ShowMultiDBInfoSearchForm = cbMultiDBSearchInfoSearchFormActive.Checked; + Config.ShowMultiDBInfoSingleSearch = cbMultiDBSearchInfoSingleSearchActive.Checked; + Config.PasswordDisplay = GetPwDisplayMode(); + } + + private void AdjustNode(TreeNode t, FindInfo fiInfo) + { + t.Text = fiInfo.OptionsText.Replace("&", string.Empty); + if (fiInfo.StandardMethod != null || (fiInfo.Name == SearchHelp.SearchForm)) return; + SetDisabled(t); + } + + private void SetPwDisplayMode(Config.PasswordDisplayMode m) + { + gPWDisplay.Visible = gPWDisplay.Enabled = Tools.KeePassVersion < Util.KeePassVersion_2_54; + rbPWDisplayAlways.Checked = true; + if (m == Config.PasswordDisplayMode.Never) rbPWDisplayNever.Checked = true; + if (m == Config.PasswordDisplayMode.EntryviewBased) rbPWDisplayEntryList.Checked = true; + } + + private Config.PasswordDisplayMode GetPwDisplayMode() + { + if (rbPWDisplayNever.Checked) return Config.PasswordDisplayMode.Never; + if (rbPWDisplayEntryList.Checked) return Config.PasswordDisplayMode.EntryviewBased; + return Config.PasswordDisplayMode.Always; + } + + private void tvHookedSearches_BeforeChecked(object sender, TreeViewCancelEventArgs e) + { + if (IsEnabled(e.Node)) return; + e.Cancel = true; + } + } } diff --git a/src/PluginTranslation.cs b/src/PluginTranslation.cs index a015490..9147374 100644 --- a/src/PluginTranslation.cs +++ b/src/PluginTranslation.cs @@ -1,54 +1,52 @@ using System; using System.Collections.Generic; -using System.Xml; -using System.Xml.Serialization; using System.IO; using System.Reflection; - +using System.Windows.Forms; +using System.Xml; +using System.Xml.Serialization; using KeePass.Plugins; using KeePass.Util; using KeePassLib.Utility; - using PluginTools; -using System.Windows.Forms; namespace PluginTranslation { - public class TranslationChangedEventArgs : EventArgs - { - public string OldLanguageIso6391 = string.Empty; - public string NewLanguageIso6391 = string.Empty; + public class TranslationChangedEventArgs : EventArgs + { + public string OldLanguageIso6391 = string.Empty; + public string NewLanguageIso6391 = string.Empty; - public TranslationChangedEventArgs(string OldLanguageIso6391, string NewLanguageIso6391) - { - this.OldLanguageIso6391 = OldLanguageIso6391; - this.NewLanguageIso6391 = NewLanguageIso6391; - } - } + public TranslationChangedEventArgs(string OldLanguageIso6391, string NewLanguageIso6391) + { + this.OldLanguageIso6391 = OldLanguageIso6391; + this.NewLanguageIso6391 = NewLanguageIso6391; + } + } - public static class PluginTranslate - { - public static long TranslationVersion = 0; - public static event EventHandler TranslationChanged = null; - private static string LanguageIso6391 = string.Empty; - #region Definitions of translated texts go here - public const string PluginName = "Global Search"; - /// - /// Please select the search functions that {0} shall enhance. - /// - /// {0} will perform the search in all open databases and will enrich the result shown with the database a found entry is contained in. - /// - /// KeePass as well as many of the available plugins assume that all entries shown in the entry list are contained in the currently active database. - /// To not break compatibility and to avoid inconsistencies like flagging the wrong database as changed, {0} will behave as follows: - /// - /// If a search returns results from multiple databases, the results will be shown in a separate window. - /// Selecting an entry will - /// - Activate the selected entry's database - /// - Show all found entries in the entry list, that are contained in this database - /// - /// If '{1}' returns only entries from exactly one database, this database will be activated and the search results will be shown as usual. - /// - public static readonly string Description = @"Please select the search functions that {0} shall enhance. + public static class PluginTranslate + { + public static long TranslationVersion = 0; + public static event EventHandler TranslationChanged = null; + private static string LanguageIso6391 = string.Empty; + #region Definitions of translated texts go here + public const string PluginName = "Global Search"; + /// + /// Please select the search functions that {0} shall enhance. + /// + /// {0} will perform the search in all open databases and will enrich the result shown with the database a found entry is contained in. + /// + /// KeePass as well as many of the available plugins assume that all entries shown in the entry list are contained in the currently active database. + /// To not break compatibility and to avoid inconsistencies like flagging the wrong database as changed, {0} will behave as follows: + /// + /// If a search returns results from multiple databases, the results will be shown in a separate window. + /// Selecting an entry will + /// - Activate the selected entry's database + /// - Show all found entries in the entry list, that are contained in this database + /// + /// If '{1}' returns only entries from exactly one database, this database will be activated and the search results will be shown as usual. + /// + public static readonly string Description = @"Please select the search functions that {0} shall enhance. {0} will perform the search in all open databases and will enrich the result shown with the database a found entry is contained in. @@ -61,237 +59,237 @@ Selecting an entry will - Show all found entries in the entry list, that are contained in this database If '{1}' returns only entries from exactly one database, this database will be activated and the search results will be shown as usual."; - /// - /// Enhance searches - /// - public static readonly string OptionsCaption = @"Enhance searches"; - /// - /// Search in all open databases - /// - public static readonly string Search = @"Search in all open databases"; - /// - /// Show info if '{0}' returns entries from multiple databases - /// - public static readonly string MultiDBSearchInfoSearchFormActive = @"Show info if '{0}' returns entries from multiple databases"; - /// - /// The result of this search contain entries from multiple databases and will be displayed in a separate window. - /// After selecting an entry, the entry list will show only found entries contained in the selected entry's database. - /// - /// To disable this message, choose '{0}' or visit the plugin's options - /// - public static readonly string MultiDBSearchInfoSearchForm = @"The result of this search contain entries from multiple databases and will be displayed in a separate window. + /// + /// Enhance searches + /// + public static readonly string OptionsCaption = @"Enhance searches"; + /// + /// Search in all open databases + /// + public static readonly string Search = @"Search in all open databases"; + /// + /// Show info if '{0}' returns entries from multiple databases + /// + public static readonly string MultiDBSearchInfoSearchFormActive = @"Show info if '{0}' returns entries from multiple databases"; + /// + /// The result of this search contain entries from multiple databases and will be displayed in a separate window. + /// After selecting an entry, the entry list will show only found entries contained in the selected entry's database. + /// + /// To disable this message, choose '{0}' or visit the plugin's options + /// + public static readonly string MultiDBSearchInfoSearchForm = @"The result of this search contain entries from multiple databases and will be displayed in a separate window. After selecting an entry, the entry list will show only found entries contained in the selected entry's database. To disable this message, choose '{0}' or visit the plugin's options"; - /// - /// Show info if other searches return entries from multiple databases - /// - public static readonly string MultiDBSearchInfoSingleSearchActive = @"Show info if other searches return entries from multiple databases"; - /// - /// You selected an entry from a multi-db search result. - /// The entry list will show only found entries contained in the selected entry's database. - /// - /// To disable this message, choose '{0}' or visit the plugin's options - /// - public static readonly string MultiDBSearchInfoSingleSearch = @"You selected an entry from a multi-db search result. + /// + /// Show info if other searches return entries from multiple databases + /// + public static readonly string MultiDBSearchInfoSingleSearchActive = @"Show info if other searches return entries from multiple databases"; + /// + /// You selected an entry from a multi-db search result. + /// The entry list will show only found entries contained in the selected entry's database. + /// + /// To disable this message, choose '{0}' or visit the plugin's options + /// + public static readonly string MultiDBSearchInfoSingleSearch = @"You selected an entry from a multi-db search result. The entry list will show only found entries contained in the selected entry's database. To disable this message, choose '{0}' or visit the plugin's options"; - /// - /// Activation of {0} not possible. - /// - /// Could not find required objects - /// - public static readonly string ErrorNoActivation = @"Activation of {0} not possible. + /// + /// Activation of {0} not possible. + /// + /// Could not find required objects + /// + public static readonly string ErrorNoActivation = @"Activation of {0} not possible. Could not find required objects"; - /// - /// Password display - /// - public static readonly string PWDisplayMode = @"Password display"; - /// - /// Always - /// - public static readonly string PWDisplayModeAlways = @"Always"; - /// - /// Never - /// - public static readonly string PWDisplayModeNever = @"Never"; - /// - /// Like Entry List - /// - public static readonly string PWDisplayModeEntryView = @"Like Entry List"; - /// - /// Column widths like entry list - /// - public static readonly string UseEntryListColumnWidths = @"Column widths like Entry List"; - #endregion + /// + /// Password display + /// + public static readonly string PWDisplayMode = @"Password display"; + /// + /// Always + /// + public static readonly string PWDisplayModeAlways = @"Always"; + /// + /// Never + /// + public static readonly string PWDisplayModeNever = @"Never"; + /// + /// Like Entry List + /// + public static readonly string PWDisplayModeEntryView = @"Like Entry List"; + /// + /// Column widths like entry list + /// + public static readonly string UseEntryListColumnWidths = @"Column widths like Entry List"; + #endregion - #region NO changes in this area - private static StringDictionary m_translation = new StringDictionary(); + #region NO changes in this area + private static StringDictionary m_translation = new StringDictionary(); - public static void Init(Plugin plugin, string LanguageCodeIso6391) - { - List lDebugStrings = new List(); - m_translation.Clear(); - bool bError = true; - LanguageCodeIso6391 = InitTranslation(plugin, lDebugStrings, LanguageCodeIso6391, out bError); - if (bError && (LanguageCodeIso6391.Length > 2)) - { - LanguageCodeIso6391 = LanguageCodeIso6391.Substring(0, 2); - lDebugStrings.Add("Trying fallback: " + LanguageCodeIso6391); - LanguageCodeIso6391 = InitTranslation(plugin, lDebugStrings, LanguageCodeIso6391, out bError); - } - if (bError) - { - PluginDebug.AddError("Reading translation failed", 0, lDebugStrings.ToArray()); - LanguageCodeIso6391 = "en"; - } - else - { - List lTranslatable = new List( - typeof(PluginTranslate).GetFields(BindingFlags.Static | BindingFlags.Public) - ).FindAll(x => x.IsInitOnly); - lDebugStrings.Add("Parsing complete"); - lDebugStrings.Add("Translated texts read: " + m_translation.Count.ToString()); - lDebugStrings.Add("Translatable texts: " + lTranslatable.Count.ToString()); - foreach (FieldInfo f in lTranslatable) - { - if (m_translation.ContainsKey(f.Name)) - { - lDebugStrings.Add("Key found: " + f.Name); - f.SetValue(null, m_translation[f.Name]); - } - else - lDebugStrings.Add("Key not found: " + f.Name); - } - PluginDebug.AddInfo("Reading translations finished", 0, lDebugStrings.ToArray()); - } - if (TranslationChanged != null) - { - TranslationChanged(null, new TranslationChangedEventArgs(LanguageIso6391, LanguageCodeIso6391)); - } - LanguageIso6391 = LanguageCodeIso6391; - lDebugStrings.Clear(); - } + public static void Init(Plugin plugin, string LanguageCodeIso6391) + { + List lDebugStrings = new List(); + m_translation.Clear(); + bool bError = true; + LanguageCodeIso6391 = InitTranslation(plugin, lDebugStrings, LanguageCodeIso6391, out bError); + if (bError && (LanguageCodeIso6391.Length > 2)) + { + LanguageCodeIso6391 = LanguageCodeIso6391.Substring(0, 2); + lDebugStrings.Add("Trying fallback: " + LanguageCodeIso6391); + LanguageCodeIso6391 = InitTranslation(plugin, lDebugStrings, LanguageCodeIso6391, out bError); + } + if (bError) + { + PluginDebug.AddError("Reading translation failed", 0, lDebugStrings.ToArray()); + LanguageCodeIso6391 = "en"; + } + else + { + List lTranslatable = new List( + typeof(PluginTranslate).GetFields(BindingFlags.Static | BindingFlags.Public) + ).FindAll(x => x.IsInitOnly); + lDebugStrings.Add("Parsing complete"); + lDebugStrings.Add("Translated texts read: " + m_translation.Count.ToString()); + lDebugStrings.Add("Translatable texts: " + lTranslatable.Count.ToString()); + foreach (FieldInfo f in lTranslatable) + { + if (m_translation.ContainsKey(f.Name)) + { + lDebugStrings.Add("Key found: " + f.Name); + f.SetValue(null, m_translation[f.Name]); + } + else + lDebugStrings.Add("Key not found: " + f.Name); + } + PluginDebug.AddInfo("Reading translations finished", 0, lDebugStrings.ToArray()); + } + if (TranslationChanged != null) + { + TranslationChanged(null, new TranslationChangedEventArgs(LanguageIso6391, LanguageCodeIso6391)); + } + LanguageIso6391 = LanguageCodeIso6391; + lDebugStrings.Clear(); + } - private static string InitTranslation(Plugin plugin, List lDebugStrings, string LanguageCodeIso6391, out bool bError) - { - if (string.IsNullOrEmpty(LanguageCodeIso6391)) - { - lDebugStrings.Add("No language identifier supplied, using 'en' as fallback"); - LanguageCodeIso6391 = "en"; - } - string filename = GetFilename(plugin.GetType().Namespace, LanguageCodeIso6391); - lDebugStrings.Add("Translation file: " + filename); + private static string InitTranslation(Plugin plugin, List lDebugStrings, string LanguageCodeIso6391, out bool bError) + { + if (string.IsNullOrEmpty(LanguageCodeIso6391)) + { + lDebugStrings.Add("No language identifier supplied, using 'en' as fallback"); + LanguageCodeIso6391 = "en"; + } + string filename = GetFilename(plugin.GetType().Namespace, LanguageCodeIso6391); + lDebugStrings.Add("Translation file: " + filename); - if (!File.Exists(filename)) //If e. g. 'plugin.zh-tw.language.xml' does not exist, try 'plugin.zh.language.xml' - { - lDebugStrings.Add("File does not exist"); - bError = true; - return LanguageCodeIso6391; - } - else - { - string translation = string.Empty; - try { translation = File.ReadAllText(filename); } - catch (Exception ex) - { - lDebugStrings.Add("Error reading file: " + ex.Message); - LanguageCodeIso6391 = "en"; - bError = true; - return LanguageCodeIso6391; - } - XmlSerializer xs = new XmlSerializer(m_translation.GetType()); - lDebugStrings.Add("File read, parsing content"); - try - { - m_translation = (StringDictionary)xs.Deserialize(new StringReader(translation)); - } - catch (Exception ex) - { - string sException = ex.Message; - if (ex.InnerException != null) sException += "\n" + ex.InnerException.Message; - lDebugStrings.Add("Error parsing file: " + sException); - LanguageCodeIso6391 = "en"; - MessageBox.Show("Error parsing translation file\n\n" + sException, PluginName, MessageBoxButtons.OK, MessageBoxIcon.Error); - bError = true; - return LanguageCodeIso6391; - } - bError = false; - return LanguageCodeIso6391; - } - } + if (!File.Exists(filename)) //If e. g. 'plugin.zh-tw.language.xml' does not exist, try 'plugin.zh.language.xml' + { + lDebugStrings.Add("File does not exist"); + bError = true; + return LanguageCodeIso6391; + } + else + { + string translation = string.Empty; + try { translation = File.ReadAllText(filename); } + catch (Exception ex) + { + lDebugStrings.Add("Error reading file: " + ex.Message); + LanguageCodeIso6391 = "en"; + bError = true; + return LanguageCodeIso6391; + } + XmlSerializer xs = new XmlSerializer(m_translation.GetType()); + lDebugStrings.Add("File read, parsing content"); + try + { + m_translation = (StringDictionary)xs.Deserialize(new StringReader(translation)); + } + catch (Exception ex) + { + string sException = ex.Message; + if (ex.InnerException != null) sException += "\n" + ex.InnerException.Message; + lDebugStrings.Add("Error parsing file: " + sException); + LanguageCodeIso6391 = "en"; + MessageBox.Show("Error parsing translation file\n\n" + sException, PluginName, MessageBoxButtons.OK, MessageBoxIcon.Error); + bError = true; + return LanguageCodeIso6391; + } + bError = false; + return LanguageCodeIso6391; + } + } - private static string GetFilename(string plugin, string lang) - { - string filename = UrlUtil.GetFileDirectory(WinUtil.GetExecutable(), true, true); - filename += KeePass.App.AppDefs.PluginsDir + UrlUtil.LocalDirSepChar + "Translations" + UrlUtil.LocalDirSepChar; - filename += plugin + "." + lang + ".language.xml"; - return filename; - } - #endregion - } + private static string GetFilename(string plugin, string lang) + { + string filename = UrlUtil.GetFileDirectory(WinUtil.GetExecutable(), true, true); + filename += KeePass.App.AppDefs.PluginsDir + UrlUtil.LocalDirSepChar + "Translations" + UrlUtil.LocalDirSepChar; + filename += plugin + "." + lang + ".language.xml"; + return filename; + } + #endregion + } - #region NO changes in this area - [XmlRoot("Translation")] - public class StringDictionary : Dictionary, IXmlSerializable - { - public System.Xml.Schema.XmlSchema GetSchema() - { - return null; - } + #region NO changes in this area + [XmlRoot("Translation")] + public class StringDictionary : Dictionary, IXmlSerializable + { + public System.Xml.Schema.XmlSchema GetSchema() + { + return null; + } - public void ReadXml(XmlReader reader) - { - bool wasEmpty = reader.IsEmptyElement; - reader.Read(); - if (wasEmpty) return; - bool bFirst = true; - while (reader.NodeType != XmlNodeType.EndElement) - { - if (bFirst) - { - bFirst = false; - try - { - reader.ReadStartElement("TranslationVersion"); - PluginTranslate.TranslationVersion = reader.ReadContentAsLong(); - reader.ReadEndElement(); - } - catch { } - } - reader.ReadStartElement("item"); - reader.ReadStartElement("key"); - string key = reader.ReadContentAsString(); - reader.ReadEndElement(); - reader.ReadStartElement("value"); - string value = reader.ReadContentAsString(); - reader.ReadEndElement(); - this.Add(key, value); - reader.ReadEndElement(); - reader.MoveToContent(); - } - reader.ReadEndElement(); - } + public void ReadXml(XmlReader reader) + { + bool wasEmpty = reader.IsEmptyElement; + reader.Read(); + if (wasEmpty) return; + bool bFirst = true; + while (reader.NodeType != XmlNodeType.EndElement) + { + if (bFirst) + { + bFirst = false; + try + { + reader.ReadStartElement("TranslationVersion"); + PluginTranslate.TranslationVersion = reader.ReadContentAsLong(); + reader.ReadEndElement(); + } + catch { } + } + reader.ReadStartElement("item"); + reader.ReadStartElement("key"); + string key = reader.ReadContentAsString(); + reader.ReadEndElement(); + reader.ReadStartElement("value"); + string value = reader.ReadContentAsString(); + reader.ReadEndElement(); + this.Add(key, value); + reader.ReadEndElement(); + reader.MoveToContent(); + } + reader.ReadEndElement(); + } - public void WriteXml(XmlWriter writer) - { - writer.WriteStartElement("TranslationVersion"); - writer.WriteString(PluginTranslate.TranslationVersion.ToString()); - writer.WriteEndElement(); - foreach (string key in this.Keys) - { - writer.WriteStartElement("item"); - writer.WriteStartElement("key"); - writer.WriteString(key); - writer.WriteEndElement(); - writer.WriteStartElement("value"); - writer.WriteString(this[key]); - writer.WriteEndElement(); - writer.WriteEndElement(); - } - } - } - #endregion -} \ No newline at end of file + public void WriteXml(XmlWriter writer) + { + writer.WriteStartElement("TranslationVersion"); + writer.WriteString(PluginTranslate.TranslationVersion.ToString()); + writer.WriteEndElement(); + foreach (string key in this.Keys) + { + writer.WriteStartElement("item"); + writer.WriteStartElement("key"); + writer.WriteString(key); + writer.WriteEndElement(); + writer.WriteStartElement("value"); + writer.WriteString(this[key]); + writer.WriteEndElement(); + writer.WriteEndElement(); + } + } + } + #endregion +} diff --git a/src/SpecialSearches/GlobalSearchExpired.cs b/src/SpecialSearches/GlobalSearchExpired.cs index 8f9144b..47e5fb1 100644 --- a/src/SpecialSearches/GlobalSearchExpired.cs +++ b/src/SpecialSearches/GlobalSearchExpired.cs @@ -1,112 +1,112 @@ -using KeePass.Resources; -using KeePass.UI; -using KeePassLib; -using KeePassLib.Interfaces; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; +using KeePass.Resources; +using KeePass.UI; +using KeePassLib; +using KeePassLib.Interfaces; namespace GlobalSearch.SpecialSearches { - class SearchExpired - { - internal static List FindExpired(PwDatabase db, IStatusLogger sl, out Action fInit, bool bOnlyExpired, int iExpDays, int iExpMonths) - { - List l = new List(); - fInit = PrepareListView(); - - PwGroup pg = new PwGroup(true, true, string.Empty, PwIcon.Expired); - pg.IsVirtual = true; - - bool bExpInP = bOnlyExpired; // Past - bool bExpInF = (iExpDays == int.MaxValue); // Future - bool bExpInI = !bExpInP && !bExpInF; // Interval - - DateTime dtNow = DateTime.UtcNow; - DateTime dtLimit = dtNow; - if (bExpInI) - { - if (iExpDays > 0) dtLimit = dtNow.AddDays(iExpDays); - else if (iExpMonths > 0) dtLimit = dtNow.AddMonths(iExpMonths); - - dtLimit = KeePassLib.Utility.TimeUtil.ToLocal(dtLimit, false); - dtLimit = dtLimit.Date.Add(new TimeSpan(23, 59, 59)); - dtLimit = KeePassLib.Utility.TimeUtil.ToUtc(dtLimit, false); - } - - KeePassLib.Delegates.EntryHandler eh = delegate (PwEntry pe) - { - if (!pe.Expires) return true; - if (!pe.GetSearchingEnabled()) return true; - if (PwDefs.IsTanEntry(pe)) return true; // Exclude TANs - - int iRelNow = pe.ExpiryTime.CompareTo(dtNow); - - if ((bExpInP && (iRelNow <= 0)) || - (bExpInI && (pe.ExpiryTime <= dtLimit) && (iRelNow > 0)) || - (bExpInF && (iRelNow > 0))) - pg.AddEntry(pe, false, false); - return true; - }; - - db.RootGroup.TraverseTree(TraversalMethod.PreOrder, null, eh); - - if (pg.Entries.UCount == 0) return l; - - l = MapResults(pg); - return l; - } - - private static List MapResults(PwGroup pg) - { - List l = new List(); - Dictionary dGroups = new Dictionary(); - foreach (PwEntry pe in pg.Entries) - { - string strGroup = string.Empty; - if (pe.ParentGroup != null) strGroup = pe.ParentGroup.GetFullPath(" - ", false); - - ListViewGroup lvg = null; - PwDatabase dbReal = KeePass.Program.MainForm.DocumentManager.SafeFindContainerOf(pe); - if (!dGroups.ContainsKey(dbReal)) - { - lvg = new ListViewGroup(SearchHelp.GetDBName(pe)); - lvg.Tag = new PwGroup(true, true, lvg.Header, PwIcon.Expired) { IsVirtual = true, }; - l.Add(lvg); - } - else lvg = dGroups[dbReal]; - dGroups[dbReal] = lvg; - - - ListViewItem lvi = new ListViewItem(pe.Strings.ReadSafe(PwDefs.TitleField)); - lvi.SubItems.Add(pe.Strings.ReadSafe(PwDefs.UserNameField)); - lvi.SubItems.Add(pe.ExpiryTime.ToLocalTime().ToString()); - lvi.SubItems.Add(strGroup); - - lvi.Tag = pe; - (lvg.Tag as PwGroup).AddEntry(pe, false, false); - l.Add(lvi); - } - return l; - } - - private static Action PrepareListView() - { - return delegate (ListView lv) - { - int w = lv.ClientSize.Width - UIUtil.GetVScrollBarWidth(); - int wf = w / 4; - int di = Math.Min(UIUtil.GetSmallIconSize().Width, wf); - - lv.Columns.Add(KPRes.Title, wf + di); - lv.Columns.Add(KPRes.UserName, wf); - lv.Columns.Add(KPRes.ExpiryTime, wf); - lv.Columns.Add(KPRes.Group, wf - di); - - UIUtil.SetDisplayIndices(lv, new int[] { 1, 2, 3, 0 }); - }; - } - } + class SearchExpired + { + internal static List FindExpired(PwDatabase db, IStatusLogger sl, out Action fInit, bool bOnlyExpired, int iExpDays, int iExpMonths) + { + List l = new List(); + fInit = PrepareListView(); + + PwGroup pg = new PwGroup(true, true, string.Empty, PwIcon.Expired); + pg.IsVirtual = true; + + bool bExpInP = bOnlyExpired; // Past + bool bExpInF = (iExpDays == int.MaxValue); // Future + bool bExpInI = !bExpInP && !bExpInF; // Interval + + DateTime dtNow = DateTime.UtcNow; + DateTime dtLimit = dtNow; + if (bExpInI) + { + if (iExpDays > 0) dtLimit = dtNow.AddDays(iExpDays); + else if (iExpMonths > 0) dtLimit = dtNow.AddMonths(iExpMonths); + + dtLimit = KeePassLib.Utility.TimeUtil.ToLocal(dtLimit, false); + dtLimit = dtLimit.Date.Add(new TimeSpan(23, 59, 59)); + dtLimit = KeePassLib.Utility.TimeUtil.ToUtc(dtLimit, false); + } + + KeePassLib.Delegates.EntryHandler eh = delegate (PwEntry pe) + { + if (!pe.Expires) return true; + if (!pe.GetSearchingEnabled()) return true; + if (PwDefs.IsTanEntry(pe)) return true; // Exclude TANs + + int iRelNow = pe.ExpiryTime.CompareTo(dtNow); + + if ((bExpInP && (iRelNow <= 0)) || + (bExpInI && (pe.ExpiryTime <= dtLimit) && (iRelNow > 0)) || + (bExpInF && (iRelNow > 0))) + pg.AddEntry(pe, false, false); + return true; + }; + + db.RootGroup.TraverseTree(TraversalMethod.PreOrder, null, eh); + + if (pg.Entries.UCount == 0) return l; + + l = MapResults(pg); + return l; + } + + private static List MapResults(PwGroup pg) + { + List l = new List(); + Dictionary dGroups = new Dictionary(); + foreach (PwEntry pe in pg.Entries) + { + string strGroup = string.Empty; + if (pe.ParentGroup != null) strGroup = pe.ParentGroup.GetFullPath(" - ", false); + + ListViewGroup lvg = null; + PwDatabase dbReal = KeePass.Program.MainForm.DocumentManager.SafeFindContainerOf(pe); + if (!dGroups.ContainsKey(dbReal)) + { + lvg = new ListViewGroup(SearchHelp.GetDBName(pe)); + lvg.Tag = new PwGroup(true, true, lvg.Header, PwIcon.Expired) { IsVirtual = true, }; + l.Add(lvg); + } + else lvg = dGroups[dbReal]; + dGroups[dbReal] = lvg; + + + ListViewItem lvi = new ListViewItem(pe.Strings.ReadSafe(PwDefs.TitleField)); + lvi.SubItems.Add(pe.Strings.ReadSafe(PwDefs.UserNameField)); + lvi.SubItems.Add(pe.ExpiryTime.ToLocalTime().ToString()); + lvi.SubItems.Add(strGroup); + + lvi.Tag = pe; + (lvg.Tag as PwGroup).AddEntry(pe, false, false); + l.Add(lvi); + } + return l; + } + + private static Action PrepareListView() + { + return delegate (ListView lv) + { + int w = lv.ClientSize.Width - UIUtil.GetVScrollBarWidth(); + int wf = w / 4; + int di = Math.Min(UIUtil.GetSmallIconSize().Width, wf); + + lv.Columns.Add(KPRes.Title, wf + di); + lv.Columns.Add(KPRes.UserName, wf); + lv.Columns.Add(KPRes.ExpiryTime, wf); + lv.Columns.Add(KPRes.Group, wf - di); + + UIUtil.SetDisplayIndices(lv, new int[] { 1, 2, 3, 0 }); + }; + } + } } diff --git a/src/SpecialSearches/SearchHelp.cs b/src/SpecialSearches/SearchHelp.cs index ef321a8..79ffc33 100644 --- a/src/SpecialSearches/SearchHelp.cs +++ b/src/SpecialSearches/SearchHelp.cs @@ -1,303 +1,303 @@ -using KeePass.Resources; -using KeePassLib.Interfaces; -using PluginTools; -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.Reflection; using System.Windows.Forms; +using KeePass.Resources; +using KeePassLib.Interfaces; +using PluginTools; namespace GlobalSearch { - public enum SearchType - { - BuiltIn, - Expiring, - QuickFind, //To-Do - } - - public class FindInfo - { - public string Name = string.Empty; - public string Func = string.Empty; - public Image img = null; - public string Title = string.Empty; - public string SubTitle = string.Empty; - public string Note = string.Empty; - public string NothingFound = string.Empty; - public string OptionsText = string.Empty; - public ToolStripItem tsiMenuItem = null; - public MethodInfo StandardMethod = null; - public List StandardEventHandlers = null; - public SearchType SearchType = SearchType.BuiltIn; - - public override string ToString() - { - int i = StandardEventHandlers == null ? 0 : StandardEventHandlers.Count; - return Name + ": " + Func + ": " + i.ToString() + " handlers"; - } - } - - public static class SearchHelp - { - public const string SearchForm = "m_menuFindInDatabase"; - public const string SearchDupPw = "m_menuFindDupPasswords"; - public const string SearchPasswordPairs = "m_menuFindSimPasswordsP"; - public const string SearchPasswordClusters = "m_menuFindSimPasswordsC"; - public const string SearchPasswordQuality = "m_menuFindPwQuality"; - public const string SearchLargeEntries = "m_menuFindLarge"; - public const string SearchLastMod = "m_menuFindLastMod"; - - public const string SearchExpired = "m_menuFindExp"; - public const string SearchExpired_1D = "m_menuFindExp1"; - public const string SearchExpired_2D = "m_menuFindExp2"; - public const string SearchExpired_3D = "m_menuFindExp3"; - public const string SearchExpired_7D = "m_menuFindExp7"; - public const string SearchExpired_14D = "m_menuFindExp14"; - public const string SearchExpired_1M = "m_menuFindExp30"; - public const string SearchExpired_2M = "m_menuFindExp60"; - public const string SearchExpired_F = "m_menuFindExpInF"; - - - public static List FindList = new List(); - - static SearchHelp() - { - AddStandardSearches(); - - AddExpiredSearches(); - - foreach (FindInfo fi in FindList) - PrepareFindInfoItem(fi); - } - - private static void AddExpiredSearches() - { - FindList.Add(new FindInfo() - { - Name = SearchExpired, - Func = "OnFindExp", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - - FindList.Add(new FindInfo() - { - Name = SearchExpired_1D, - Func = "OnFindExp1", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - - - FindList.Add(new FindInfo() - { - Name = SearchExpired_2D, - Func = "OnFindExp2", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - - - FindList.Add(new FindInfo() - { - Name = SearchExpired_3D, - Func = "OnFindExp3", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - - FindList.Add(new FindInfo() - { - Name = SearchExpired_7D, - Func = "OnFindExp7", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - - - FindList.Add(new FindInfo() - { - Name = SearchExpired_14D, - Func = "OnFindExp14", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - - - FindList.Add(new FindInfo() - { - Name = SearchExpired_1M, - Func = "OnFindExp30", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - - - FindList.Add(new FindInfo() - { - Name = SearchExpired_2M, - Func = "OnFindExp60", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - - - FindList.Add(new FindInfo() - { - Name = SearchExpired_F, - Func = "OnFindExpInF", - Title = KPRes.ExpiredEntries, - SubTitle = string.Empty, - Note = null, - SearchType = SearchType.Expiring, - }); - } - - private static void AddStandardSearches() - { - FindList.Add(new FindInfo - { - Name = SearchDupPw, - Func = "FindDuplicatePasswords", - Title = KPRes.DuplicatePasswords, - SubTitle = KPRes.DuplicatePasswordsList, - Note = null, - NothingFound = KPRes.DuplicatePasswordsNone - }); - - FindList.Add(new FindInfo - { - Name = SearchPasswordPairs, - Func = "FindSimilarPasswordsP", - Title = KPRes.SimilarPasswords, - SubTitle = KPRes.SimilarPasswordsList2, - Note = KPRes.SimilarPasswordsNoDup - }); - - FindList.Add(new FindInfo - { - Name = SearchPasswordClusters, - Func = "FindSimilarPasswordsC", - Title = KPRes.SimilarPasswords, - SubTitle = KPRes.ClusterCenters2, - Note = KPRes.ClusterCentersDesc - }); - - FindList.Add(new FindInfo - { - Name = SearchPasswordQuality, - Func = "CreatePwQualityList", - Title = KPRes.PasswordQuality, - SubTitle = KPRes.PasswordQualityReport2, - Note = null - }); - - FindList.Add(new FindInfo - { - Name = SearchLargeEntries, - Func = "FindLargeEntries", - Title = KPRes.LargeEntries, - SubTitle = KPRes.LargeEntriesList, - Note = null - }); - - FindList.Add(new FindInfo - { - Name = SearchLastMod, - Func = "FindLastModEntries", - Title = KPRes.LastModified, - SubTitle = KPRes.LastModified, - Note = null - }); - - FindList.Add(new FindInfo - { - Name = SearchForm, - OptionsText = KPRes.Search - }); - } - - private static void PrepareFindInfoItem(FindInfo fi) - { - if (string.IsNullOrEmpty(fi.OptionsText)) - { - if (string.IsNullOrEmpty(fi.Title)) - fi.OptionsText = fi.Name; - else - fi.OptionsText = fi.Title; - } - - if (fi.SearchType != SearchType.QuickFind) - { - try { fi.tsiMenuItem = Tools.FindToolStripMenuItem(KeePass.Program.MainForm.MainMenu.Items, fi.Name, true); } - catch { } - if (fi.tsiMenuItem == null) return; - - fi.OptionsText = fi.tsiMenuItem.Text; - fi.img = fi.tsiMenuItem.Image; - } - - if (fi.SearchType == SearchType.BuiltIn) - { - Assembly a = typeof(KeePass.Program).Assembly; - Type t = a.GetType("KeePass.Util.EntryUtil"); - fi.StandardMethod = t.GetMethod(fi.Func, BindingFlags.Static | BindingFlags.NonPublic); - } - else if (fi.SearchType == SearchType.Expiring) - { - if (!string.IsNullOrEmpty(fi.OptionsText)) - { - fi.Title = fi.OptionsText; - try { fi.Title = fi.tsiMenuItem.OwnerItem.Text + " - " + fi.OptionsText; } - catch { } - fi.Title = KeePassLib.Utility.StrUtil.RemoveAccelerator(fi.Title); - } - fi.StandardMethod = typeof(SearchHelp).GetMethod("FindWrapper", BindingFlags.Static | BindingFlags.NonPublic); - } - } - - internal static List FindWrapper(KeePassLib.PwDatabase db, - IStatusLogger sl, out Action fInit, FindInfo fi) - { - if (fi.Name == SearchExpired) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, true, 0, 0); - else if (fi.Name == SearchExpired_1D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 1, 0); - else if (fi.Name == SearchExpired_2D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 2, 0); - else if (fi.Name == SearchExpired_3D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 3, 0); - else if (fi.Name == SearchExpired_7D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 7, 0); - else if (fi.Name == SearchExpired_14D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 14, 0); - else if (fi.Name == SearchExpired_1M) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 0, 1); - else if (fi.Name == SearchExpired_2M) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 0, 2); - else if (fi.Name == SearchExpired_F) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, int.MaxValue, 0); - - List l = null; - fInit = null; - return l; - } - - public static string GetDBName(KeePassLib.PwEntry pe) - { - if (pe == null) return string.Empty; - KeePassLib.PwDatabase db = KeePass.Program.MainForm.DocumentManager.FindContainerOf(pe); - if (db == null) return string.Empty; - if (!string.IsNullOrEmpty(db.Name)) return db.Name; - return KeePassLib.Utility.UrlUtil.GetFileName(db.IOConnectionInfo.Path); - } - } + public enum SearchType + { + BuiltIn, + Expiring, + QuickFind, //To-Do + } + + public class FindInfo + { + public string Name = string.Empty; + public string Func = string.Empty; + public Image img = null; + public string Title = string.Empty; + public string SubTitle = string.Empty; + public string Note = string.Empty; + public string NothingFound = string.Empty; + public string OptionsText = string.Empty; + public ToolStripItem tsiMenuItem = null; + public MethodInfo StandardMethod = null; + public List StandardEventHandlers = null; + public SearchType SearchType = SearchType.BuiltIn; + + public override string ToString() + { + int i = StandardEventHandlers == null ? 0 : StandardEventHandlers.Count; + return Name + ": " + Func + ": " + i.ToString() + " handlers"; + } + } + + public static class SearchHelp + { + public const string SearchForm = "m_menuFindInDatabase"; + public const string SearchDupPw = "m_menuFindDupPasswords"; + public const string SearchPasswordPairs = "m_menuFindSimPasswordsP"; + public const string SearchPasswordClusters = "m_menuFindSimPasswordsC"; + public const string SearchPasswordQuality = "m_menuFindPwQuality"; + public const string SearchLargeEntries = "m_menuFindLarge"; + public const string SearchLastMod = "m_menuFindLastMod"; + + public const string SearchExpired = "m_menuFindExp"; + public const string SearchExpired_1D = "m_menuFindExp1"; + public const string SearchExpired_2D = "m_menuFindExp2"; + public const string SearchExpired_3D = "m_menuFindExp3"; + public const string SearchExpired_7D = "m_menuFindExp7"; + public const string SearchExpired_14D = "m_menuFindExp14"; + public const string SearchExpired_1M = "m_menuFindExp30"; + public const string SearchExpired_2M = "m_menuFindExp60"; + public const string SearchExpired_F = "m_menuFindExpInF"; + + + public static List FindList = new List(); + + static SearchHelp() + { + AddStandardSearches(); + + AddExpiredSearches(); + + foreach (FindInfo fi in FindList) + PrepareFindInfoItem(fi); + } + + private static void AddExpiredSearches() + { + FindList.Add(new FindInfo() + { + Name = SearchExpired, + Func = "OnFindExp", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + + FindList.Add(new FindInfo() + { + Name = SearchExpired_1D, + Func = "OnFindExp1", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + + + FindList.Add(new FindInfo() + { + Name = SearchExpired_2D, + Func = "OnFindExp2", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + + + FindList.Add(new FindInfo() + { + Name = SearchExpired_3D, + Func = "OnFindExp3", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + + FindList.Add(new FindInfo() + { + Name = SearchExpired_7D, + Func = "OnFindExp7", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + + + FindList.Add(new FindInfo() + { + Name = SearchExpired_14D, + Func = "OnFindExp14", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + + + FindList.Add(new FindInfo() + { + Name = SearchExpired_1M, + Func = "OnFindExp30", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + + + FindList.Add(new FindInfo() + { + Name = SearchExpired_2M, + Func = "OnFindExp60", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + + + FindList.Add(new FindInfo() + { + Name = SearchExpired_F, + Func = "OnFindExpInF", + Title = KPRes.ExpiredEntries, + SubTitle = string.Empty, + Note = null, + SearchType = SearchType.Expiring, + }); + } + + private static void AddStandardSearches() + { + FindList.Add(new FindInfo + { + Name = SearchDupPw, + Func = "FindDuplicatePasswords", + Title = KPRes.DuplicatePasswords, + SubTitle = KPRes.DuplicatePasswordsList, + Note = null, + NothingFound = KPRes.DuplicatePasswordsNone + }); + + FindList.Add(new FindInfo + { + Name = SearchPasswordPairs, + Func = "FindSimilarPasswordsP", + Title = KPRes.SimilarPasswords, + SubTitle = KPRes.SimilarPasswordsList2, + Note = KPRes.SimilarPasswordsNoDup + }); + + FindList.Add(new FindInfo + { + Name = SearchPasswordClusters, + Func = "FindSimilarPasswordsC", + Title = KPRes.SimilarPasswords, + SubTitle = KPRes.ClusterCenters2, + Note = KPRes.ClusterCentersDesc + }); + + FindList.Add(new FindInfo + { + Name = SearchPasswordQuality, + Func = "CreatePwQualityList", + Title = KPRes.PasswordQuality, + SubTitle = KPRes.PasswordQualityReport2, + Note = null + }); + + FindList.Add(new FindInfo + { + Name = SearchLargeEntries, + Func = "FindLargeEntries", + Title = KPRes.LargeEntries, + SubTitle = KPRes.LargeEntriesList, + Note = null + }); + + FindList.Add(new FindInfo + { + Name = SearchLastMod, + Func = "FindLastModEntries", + Title = KPRes.LastModified, + SubTitle = KPRes.LastModified, + Note = null + }); + + FindList.Add(new FindInfo + { + Name = SearchForm, + OptionsText = KPRes.Search + }); + } + + private static void PrepareFindInfoItem(FindInfo fi) + { + if (string.IsNullOrEmpty(fi.OptionsText)) + { + if (string.IsNullOrEmpty(fi.Title)) + fi.OptionsText = fi.Name; + else + fi.OptionsText = fi.Title; + } + + if (fi.SearchType != SearchType.QuickFind) + { + try { fi.tsiMenuItem = Tools.FindToolStripMenuItem(KeePass.Program.MainForm.MainMenu.Items, fi.Name, true); } + catch { } + if (fi.tsiMenuItem == null) return; + + fi.OptionsText = fi.tsiMenuItem.Text; + fi.img = fi.tsiMenuItem.Image; + } + + if (fi.SearchType == SearchType.BuiltIn) + { + Assembly a = typeof(KeePass.Program).Assembly; + Type t = a.GetType("KeePass.Util.EntryUtil"); + fi.StandardMethod = t.GetMethod(fi.Func, BindingFlags.Static | BindingFlags.NonPublic); + } + else if (fi.SearchType == SearchType.Expiring) + { + if (!string.IsNullOrEmpty(fi.OptionsText)) + { + fi.Title = fi.OptionsText; + try { fi.Title = fi.tsiMenuItem.OwnerItem.Text + " - " + fi.OptionsText; } + catch { } + fi.Title = KeePassLib.Utility.StrUtil.RemoveAccelerator(fi.Title); + } + fi.StandardMethod = typeof(SearchHelp).GetMethod("FindWrapper", BindingFlags.Static | BindingFlags.NonPublic); + } + } + + internal static List FindWrapper(KeePassLib.PwDatabase db, + IStatusLogger sl, out Action fInit, FindInfo fi) + { + if (fi.Name == SearchExpired) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, true, 0, 0); + else if (fi.Name == SearchExpired_1D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 1, 0); + else if (fi.Name == SearchExpired_2D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 2, 0); + else if (fi.Name == SearchExpired_3D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 3, 0); + else if (fi.Name == SearchExpired_7D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 7, 0); + else if (fi.Name == SearchExpired_14D) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 14, 0); + else if (fi.Name == SearchExpired_1M) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 0, 1); + else if (fi.Name == SearchExpired_2M) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, 0, 2); + else if (fi.Name == SearchExpired_F) return SpecialSearches.SearchExpired.FindExpired(db, sl, out fInit, false, int.MaxValue, 0); + + List l = null; + fInit = null; + return l; + } + + public static string GetDBName(KeePassLib.PwEntry pe) + { + if (pe == null) return string.Empty; + KeePassLib.PwDatabase db = KeePass.Program.MainForm.DocumentManager.FindContainerOf(pe); + if (db == null) return string.Empty; + if (!string.IsNullOrEmpty(db.Name)) return db.Name; + return KeePassLib.Utility.UrlUtil.GetFileName(db.IOConnectionInfo.Path); + } + } } diff --git a/src/Utilities/Debug.cs b/src/Utilities/Debug.cs index 298c44f..3d4b108 100644 --- a/src/Utilities/Debug.cs +++ b/src/Utilities/Debug.cs @@ -1,420 +1,420 @@ -using KeePass.Forms; -using KeePass.UI; -using KeePassLib.Utility; -using Microsoft.Win32; -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.Reflection; using System.Windows.Forms; +using KeePass.Forms; +using KeePass.UI; +using KeePassLib.Utility; +using Microsoft.Win32; namespace PluginTools { - public static class PluginDebug - { - [Flags] - public enum LogLevelFlags - { - None = 0, - Info = 1, - Warning = 2, - Error = 4, - Success = 8, - All = Info | Warning | Error | Success - } - - public static string DebugFile { get; private set; } - public static LogLevelFlags LogLevel = LogLevelFlags.All; - - private static bool AutoSave = false; - private static bool AutoOpen = false; - private static bool AskOpen = true; - private static List m_DebugEntries = new List(); - private static string PluginName = string.Empty; - private static string PluginVersion; - private static bool m_DebugMode = false; - public static bool DebugMode - { - get { return m_DebugMode; } - set { m_DebugMode = value; } - } - private static Dictionary m_plugins = new Dictionary(); - public static Version DotNetVersion { get; private set; } - private static int m_DotNetRelease = 0; - - private static DateTime m_Start = DateTime.UtcNow; - - //Init - static PluginDebug() - { - PluginName = Assembly.GetExecutingAssembly().GetName().Name; - PluginVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - - ulong uInst = KeePass.Util.WinUtil.GetMaxNetFrameworkVersion(); - DotNetVersion = new Version(StrUtil.VersionToString(uInst)); - try - { - RegistryKey rkRel = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full", false); - m_DotNetRelease = (int)rkRel.GetValue("Release"); - if (rkRel != null) rkRel.Close(); - } - catch { } - - DebugFile = System.IO.Path.GetTempPath() + "Debug_" + PluginName + "_" + m_Start.ToString("yyyyMMddTHHmmssZ") + ".xml"; - - string level = KeePass.Program.CommandLineArgs["debuglevel"]; - if (string.IsNullOrEmpty(level)) - level = LogLevelFlags.All.ToString(); - try - { - LogLevel = (LogLevelFlags)Enum.Parse(LogLevel.GetType(), level); - } - catch { } - AutoSave = KeePass.Program.CommandLineArgs["debugautosave"] != null; - AutoOpen = KeePass.Program.CommandLineArgs["debugautoopen"] != null; - AskOpen = KeePass.Program.CommandLineArgs["debugsaveonly"] == null; - - DebugMode = KeePass.Program.CommandLineArgs[KeePass.App.AppDefs.CommandLineOptions.Debug] != null; - if (!DebugMode && (KeePass.Program.CommandLineArgs["debugplugin"] != null)) - { - try - { - string[] plugins = KeePass.Program.CommandLineArgs["debugplugin"].ToLowerInvariant().Split(new char[] { ',' }); - DebugMode |= Array.Find(plugins, x => x.Trim() == PluginName.ToLowerInvariant()) != null; - DebugMode |= Array.Find(plugins, x => x.Trim() == "all") != null; - } - catch { } - } - KeePass.Program.MainForm.FormLoadPost += LoadPluginNames; - if (AutoSave) - AddInfo("AutoSave mode active", 0); - } - - #region Handle debug messages - public static void AddInfo(string msg) - { - AddMessage(LogLevelFlags.Info, msg, 5, null); - } - - public static void AddInfo(string msg, params string[] parameters) - { - AddMessage(LogLevelFlags.Info, msg, 5, parameters); - } - - public static void AddInfo(string msg, int CallstackFrames) - { - AddMessage(LogLevelFlags.Info, msg, CallstackFrames, null); - } - - public static void AddInfo(string msg, int CallstackFrames, params string[] parameters) - { - AddMessage(LogLevelFlags.Info, msg, CallstackFrames, parameters); - } - - public static void AddWarning(string msg) - { - AddMessage(LogLevelFlags.Warning, msg, 5, null); - } - - public static void AddWarning(string msg, params string[] parameters) - { - AddMessage(LogLevelFlags.Warning, msg, 5, parameters); - } - - public static void AddWarning(string msg, int CallstackFrames) - { - AddMessage(LogLevelFlags.Warning, msg, CallstackFrames, null); - } - - public static void AddWarning(string msg, int CallstackFrames, params string[] parameters) - { - AddMessage(LogLevelFlags.Warning, msg, CallstackFrames, parameters); - } - - public static void AddError(string msg) - { - AddMessage(LogLevelFlags.Error, msg, 5, null); - } - - public static void AddError(string msg, params string[] parameters) - { - AddMessage(LogLevelFlags.Error, msg, 5, parameters); - } - - public static void AddError(string msg, int CallstackFrames) - { - AddMessage(LogLevelFlags.Error, msg, CallstackFrames, null); - } - - public static void AddError(string msg, int CallstackFrames, params string[] parameters) - { - AddMessage(LogLevelFlags.Error, msg, CallstackFrames, parameters); - } - - public static void AddSuccess(string msg) - { - AddMessage(LogLevelFlags.Success, msg, 5, null); - } - - public static void AddSuccess(string msg, params string[] parameters) - { - AddMessage(LogLevelFlags.Success, msg, 5, parameters); - } - - public static void AddSuccess(string msg, int CallstackFrames) - { - AddMessage(LogLevelFlags.Success, msg, CallstackFrames, null); - } - - public static void AddSuccess(string msg, int CallstackFrames, params string[] parameters) - { - AddMessage(LogLevelFlags.Success, msg, CallstackFrames, parameters); - } - - private static void AddMessage(LogLevelFlags severity, string msg, int CallstackFrames, string[] parameters) - { - if (m_Saving || !DebugMode || ((severity & LogLevel) != severity)) return; - if (m_DebugEntries.Count > 0) - { - DebugEntry prev = m_DebugEntries[m_DebugEntries.Count - 1]; - if ((prev.severity == severity) && (prev.msg == msg) && ParamsEqual(prev.parameters, parameters)) - { - m_DebugEntries[m_DebugEntries.Count - 1].counter++; - return; - } - } - DebugEntry m = new DebugEntry(); - m.severity = severity; - m.msg = msg; - m.utc = DateTime.UtcNow; - m.counter = 1; - m.parameters = parameters; - if (CallstackFrames != 0) - { - System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(true); - for (int i = 0; i < st.FrameCount; i++) - { - if (m.sf.Count == CallstackFrames) break; - System.Diagnostics.StackFrame sf = st.GetFrame(i); - if (sf.GetMethod().DeclaringType.FullName != "PluginTools.PluginDebug") - m.sf.Add(sf); - } - } - m_DebugEntries.Add(m); - if (AutoSave) SaveDebugMessages(); - } - - private static bool ParamsEqual(string[] a, string[] b) - { - if ((a == null) && (b == null)) return true; - if ((a == null) && (b != null)) return false; - if ((a != null) && (b == null)) return false; - if (a.Length != b.Length) return false; - for (int i = 0; i < a.Length; i++) - if (a[i] != b[i]) return false; - return true; - } - - public static bool HasMessage(LogLevelFlags severity, string msg) - { - return m_DebugEntries.Find(x => (x.severity == severity) && (x.msg == msg)) != null; - } - #endregion - - public static void SaveOrShow() - { - if (m_DebugEntries.Count == 0) return; - SaveDebugMessages(); - if (AutoOpen || (AskOpen && Tools.AskYesNo("DebugFile: " + DebugFile + "\n\nOpen debug file?") == DialogResult.Yes)) - { - try - { - System.Diagnostics.Process.Start(DebugFile); - } - catch - { - if (KeePassLib.Native.NativeLib.IsUnix()) //The above is broken on mono - { - System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(); - psi.Arguments = DebugFile; - psi.FileName = "xdg-open"; - System.Diagnostics.Process.Start(psi); - } - } - } - } - - private static System.Xml.XmlWriter m_xw = null; - private static System.IO.StringWriter m_sw = null; - private static void StartXml() - { - m_sw = new System.IO.StringWriter(); - System.Xml.XmlWriterSettings ws = new System.Xml.XmlWriterSettings(); - ws.OmitXmlDeclaration = true; - ws.Indent = true; - ws.IndentChars = "\t"; - m_xw = System.Xml.XmlWriter.Create(m_sw, ws); - } - - private static string Xml - { - get - { - if (m_xw == null) return string.Empty; - m_sw.Flush(); - m_xw.Flush(); - string s = m_sw.ToString(); - m_xw = null; - m_sw = null; - return s; - } - } - - public static string DebugMessages - { - get - { - StartXml(); - LoadPluginNames(null, null); - string sEncoding = "\n"; - m_xw.WriteStartElement("DebugInfo"); - #region General info - m_xw.WriteStartElement("General"); - m_xw.WriteStartElement("Plugin"); - m_xw.WriteElementString("PluginName", PluginName); - m_xw.WriteElementString("PluginVersion", PluginVersion); - m_xw.WriteEndElement(); - m_xw.WriteStartElement("DebugTime"); - m_xw.WriteElementString("DebugStart", m_Start.ToString("yyyyMMddTHHmmssZ")); - m_xw.WriteElementString("DebugEnd", DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ")); - m_xw.WriteEndElement(); - m_xw.WriteElementString("LogLevel", LogLevel.ToString()); - - #region Add OS info - string os = string.Empty; - if (KeePass.Util.WinUtil.IsWindows9x) - os = "Windows 9x"; - else if (KeePass.Util.WinUtil.IsWindows2000) - os = "Windows 2000"; - else if (KeePass.Util.WinUtil.IsWindowsXP) - os = "Windows XP"; - else - { - if (KeePass.Util.WinUtil.IsAtLeastWindows10) - os = ">= Windows 10"; - else if (KeePass.Util.WinUtil.IsAtLeastWindows8) - os = ">= Windows 8"; - else if (KeePass.Util.WinUtil.IsAtLeastWindows7) - os = ">= Windows 7"; - else if (KeePass.Util.WinUtil.IsAtLeastWindowsVista) - os = ">= Windows Vista"; - else if (KeePass.Util.WinUtil.IsAtLeastWindows2000) - os = ">= Windows 2000"; - else os = "Unknown"; - } - if (KeePass.Util.WinUtil.IsAppX) - os += " (AppX)"; - os += " - " + Environment.OSVersion.ToString(); - m_xw.WriteElementString("OS", KeePass.Util.WinUtil.GetOSStr() + " " + os); - #endregion - m_xw.WriteElementString("DotNet", DotNetVersion.ToString() + (m_DotNetRelease > 0 ? " (" + m_DotNetRelease.ToString() + ")" : string.Empty)); - m_xw.WriteElementString("KeePass", Tools.KeePassVersion.ToString()); - - m_xw.WriteStartElement("LoadedPlugins"); - foreach (KeyValuePair kvp in m_plugins) - { - m_xw.WriteStartElement("Plugin"); - m_xw.WriteElementString("PluginName", kvp.Key); - m_xw.WriteElementString("PluginVersion", kvp.Value.ToString()); - m_xw.WriteEndElement(); - } - m_xw.WriteEndElement(); - m_xw.WriteEndElement(); - #endregion - - if (m_DebugEntries.Count == 0) - m_xw.WriteElementString("DebugMessages", null); - else - { - m_xw.WriteStartElement("DebugMessages"); - foreach (var m in m_DebugEntries) - m.GetXml(m_xw); - m_xw.WriteEndElement(); - } - - m_xw.WriteEndElement(); - return sEncoding + Xml; - } - } - - private static bool m_Saving = false; - public static void SaveDebugMessages() - { - if (m_Saving) return; - m_Saving = true; - try - { - System.IO.File.WriteAllText(DebugFile, DebugMessages); - } - catch (Exception ex) - { - Tools.ShowError("Can't save debug file: " + DebugFile + "\n\n" + ex.Message); - } - m_Saving = false; - } - - private static bool m_bAllPluginsLoaded = false; - private static void LoadPluginNames(object sender, EventArgs e) - { - if (m_bAllPluginsLoaded) return; - m_plugins = Tools.GetLoadedPluginsName(); - if (sender == null) return; - m_bAllPluginsLoaded = true; - KeePass.Program.MainForm.FormLoadPost -= LoadPluginNames; - } - - private class DebugEntry - { - public LogLevelFlags severity; - public string msg; - public DateTime utc; - public int counter; - public List sf = new List(); - public string[] parameters = null; - - public void GetXml(System.Xml.XmlWriter xw) - { - xw.WriteStartElement("DebugEntry"); - xw.WriteElementString("Message", msg); - xw.WriteElementString("Counter", counter.ToString()); - xw.WriteElementString("Severity", severity.ToString()); - xw.WriteElementString("DateTimeUtc", utc.ToString("yyyyMMddTHHmmssZ")); - if ((parameters == null) || parameters.Length == 0) - xw.WriteElementString("Parameters", null); - else - { - xw.WriteStartElement("Parameters"); - foreach (string p in parameters) - xw.WriteElementString("Param", p); - xw.WriteEndElement(); - } - if (sf.Count == 0) - xw.WriteElementString("StackFrames", null); - else - { - xw.WriteStartElement("StackFrames"); - foreach (var f in sf) - { - xw.WriteStartElement("StackFrame"); - xw.WriteElementString("Method", f.GetMethod().Name + " (" + f.GetMethod().DeclaringType.FullName + ")"); - xw.WriteElementString("FileName", System.IO.Path.GetFileName(f.GetFileName())); - xw.WriteElementString("Line", f.GetFileLineNumber().ToString()); - xw.WriteEndElement(); - } - xw.WriteEndElement(); - } - xw.WriteEndElement(); - } - } - } -} \ No newline at end of file + public static class PluginDebug + { + [Flags] + public enum LogLevelFlags + { + None = 0, + Info = 1, + Warning = 2, + Error = 4, + Success = 8, + All = Info | Warning | Error | Success + } + + public static string DebugFile { get; private set; } + public static LogLevelFlags LogLevel = LogLevelFlags.All; + + private static bool AutoSave = false; + private static bool AutoOpen = false; + private static bool AskOpen = true; + private static List m_DebugEntries = new List(); + private static string PluginName = string.Empty; + private static string PluginVersion; + private static bool m_DebugMode = false; + public static bool DebugMode + { + get { return m_DebugMode; } + set { m_DebugMode = value; } + } + private static Dictionary m_plugins = new Dictionary(); + public static Version DotNetVersion { get; private set; } + private static int m_DotNetRelease = 0; + + private static DateTime m_Start = DateTime.UtcNow; + + //Init + static PluginDebug() + { + PluginName = Assembly.GetExecutingAssembly().GetName().Name; + PluginVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + + ulong uInst = KeePass.Util.WinUtil.GetMaxNetFrameworkVersion(); + DotNetVersion = new Version(StrUtil.VersionToString(uInst)); + try + { + RegistryKey rkRel = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full", false); + m_DotNetRelease = (int)rkRel.GetValue("Release"); + if (rkRel != null) rkRel.Close(); + } + catch { } + + DebugFile = System.IO.Path.GetTempPath() + "Debug_" + PluginName + "_" + m_Start.ToString("yyyyMMddTHHmmssZ") + ".xml"; + + string level = KeePass.Program.CommandLineArgs["debuglevel"]; + if (string.IsNullOrEmpty(level)) + level = LogLevelFlags.All.ToString(); + try + { + LogLevel = (LogLevelFlags)Enum.Parse(LogLevel.GetType(), level); + } + catch { } + AutoSave = KeePass.Program.CommandLineArgs["debugautosave"] != null; + AutoOpen = KeePass.Program.CommandLineArgs["debugautoopen"] != null; + AskOpen = KeePass.Program.CommandLineArgs["debugsaveonly"] == null; + + DebugMode = KeePass.Program.CommandLineArgs[KeePass.App.AppDefs.CommandLineOptions.Debug] != null; + if (!DebugMode && (KeePass.Program.CommandLineArgs["debugplugin"] != null)) + { + try + { + string[] plugins = KeePass.Program.CommandLineArgs["debugplugin"].ToLowerInvariant().Split(new char[] { ',' }); + DebugMode |= Array.Find(plugins, x => x.Trim() == PluginName.ToLowerInvariant()) != null; + DebugMode |= Array.Find(plugins, x => x.Trim() == "all") != null; + } + catch { } + } + KeePass.Program.MainForm.FormLoadPost += LoadPluginNames; + if (AutoSave) + AddInfo("AutoSave mode active", 0); + } + + #region Handle debug messages + public static void AddInfo(string msg) + { + AddMessage(LogLevelFlags.Info, msg, 5, null); + } + + public static void AddInfo(string msg, params string[] parameters) + { + AddMessage(LogLevelFlags.Info, msg, 5, parameters); + } + + public static void AddInfo(string msg, int CallstackFrames) + { + AddMessage(LogLevelFlags.Info, msg, CallstackFrames, null); + } + + public static void AddInfo(string msg, int CallstackFrames, params string[] parameters) + { + AddMessage(LogLevelFlags.Info, msg, CallstackFrames, parameters); + } + + public static void AddWarning(string msg) + { + AddMessage(LogLevelFlags.Warning, msg, 5, null); + } + + public static void AddWarning(string msg, params string[] parameters) + { + AddMessage(LogLevelFlags.Warning, msg, 5, parameters); + } + + public static void AddWarning(string msg, int CallstackFrames) + { + AddMessage(LogLevelFlags.Warning, msg, CallstackFrames, null); + } + + public static void AddWarning(string msg, int CallstackFrames, params string[] parameters) + { + AddMessage(LogLevelFlags.Warning, msg, CallstackFrames, parameters); + } + + public static void AddError(string msg) + { + AddMessage(LogLevelFlags.Error, msg, 5, null); + } + + public static void AddError(string msg, params string[] parameters) + { + AddMessage(LogLevelFlags.Error, msg, 5, parameters); + } + + public static void AddError(string msg, int CallstackFrames) + { + AddMessage(LogLevelFlags.Error, msg, CallstackFrames, null); + } + + public static void AddError(string msg, int CallstackFrames, params string[] parameters) + { + AddMessage(LogLevelFlags.Error, msg, CallstackFrames, parameters); + } + + public static void AddSuccess(string msg) + { + AddMessage(LogLevelFlags.Success, msg, 5, null); + } + + public static void AddSuccess(string msg, params string[] parameters) + { + AddMessage(LogLevelFlags.Success, msg, 5, parameters); + } + + public static void AddSuccess(string msg, int CallstackFrames) + { + AddMessage(LogLevelFlags.Success, msg, CallstackFrames, null); + } + + public static void AddSuccess(string msg, int CallstackFrames, params string[] parameters) + { + AddMessage(LogLevelFlags.Success, msg, CallstackFrames, parameters); + } + + private static void AddMessage(LogLevelFlags severity, string msg, int CallstackFrames, string[] parameters) + { + if (m_Saving || !DebugMode || ((severity & LogLevel) != severity)) return; + if (m_DebugEntries.Count > 0) + { + DebugEntry prev = m_DebugEntries[m_DebugEntries.Count - 1]; + if ((prev.severity == severity) && (prev.msg == msg) && ParamsEqual(prev.parameters, parameters)) + { + m_DebugEntries[m_DebugEntries.Count - 1].counter++; + return; + } + } + DebugEntry m = new DebugEntry(); + m.severity = severity; + m.msg = msg; + m.utc = DateTime.UtcNow; + m.counter = 1; + m.parameters = parameters; + if (CallstackFrames != 0) + { + System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(true); + for (int i = 0; i < st.FrameCount; i++) + { + if (m.sf.Count == CallstackFrames) break; + System.Diagnostics.StackFrame sf = st.GetFrame(i); + if (sf.GetMethod().DeclaringType.FullName != "PluginTools.PluginDebug") + m.sf.Add(sf); + } + } + m_DebugEntries.Add(m); + if (AutoSave) SaveDebugMessages(); + } + + private static bool ParamsEqual(string[] a, string[] b) + { + if ((a == null) && (b == null)) return true; + if ((a == null) && (b != null)) return false; + if ((a != null) && (b == null)) return false; + if (a.Length != b.Length) return false; + for (int i = 0; i < a.Length; i++) + if (a[i] != b[i]) return false; + return true; + } + + public static bool HasMessage(LogLevelFlags severity, string msg) + { + return m_DebugEntries.Find(x => (x.severity == severity) && (x.msg == msg)) != null; + } + #endregion + + public static void SaveOrShow() + { + if (m_DebugEntries.Count == 0) return; + SaveDebugMessages(); + if (AutoOpen || (AskOpen && Tools.AskYesNo("DebugFile: " + DebugFile + "\n\nOpen debug file?") == DialogResult.Yes)) + { + try + { + System.Diagnostics.Process.Start(DebugFile); + } + catch + { + if (KeePassLib.Native.NativeLib.IsUnix()) //The above is broken on mono + { + System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(); + psi.Arguments = DebugFile; + psi.FileName = "xdg-open"; + System.Diagnostics.Process.Start(psi); + } + } + } + } + + private static System.Xml.XmlWriter m_xw = null; + private static System.IO.StringWriter m_sw = null; + private static void StartXml() + { + m_sw = new System.IO.StringWriter(); + System.Xml.XmlWriterSettings ws = new System.Xml.XmlWriterSettings(); + ws.OmitXmlDeclaration = true; + ws.Indent = true; + ws.IndentChars = "\t"; + m_xw = System.Xml.XmlWriter.Create(m_sw, ws); + } + + private static string Xml + { + get + { + if (m_xw == null) return string.Empty; + m_sw.Flush(); + m_xw.Flush(); + string s = m_sw.ToString(); + m_xw = null; + m_sw = null; + return s; + } + } + + public static string DebugMessages + { + get + { + StartXml(); + LoadPluginNames(null, null); + string sEncoding = "\n"; + m_xw.WriteStartElement("DebugInfo"); + #region General info + m_xw.WriteStartElement("General"); + m_xw.WriteStartElement("Plugin"); + m_xw.WriteElementString("PluginName", PluginName); + m_xw.WriteElementString("PluginVersion", PluginVersion); + m_xw.WriteEndElement(); + m_xw.WriteStartElement("DebugTime"); + m_xw.WriteElementString("DebugStart", m_Start.ToString("yyyyMMddTHHmmssZ")); + m_xw.WriteElementString("DebugEnd", DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ")); + m_xw.WriteEndElement(); + m_xw.WriteElementString("LogLevel", LogLevel.ToString()); + + #region Add OS info + string os = string.Empty; + if (KeePass.Util.WinUtil.IsWindows9x) + os = "Windows 9x"; + else if (KeePass.Util.WinUtil.IsWindows2000) + os = "Windows 2000"; + else if (KeePass.Util.WinUtil.IsWindowsXP) + os = "Windows XP"; + else + { + if (KeePass.Util.WinUtil.IsAtLeastWindows10) + os = ">= Windows 10"; + else if (KeePass.Util.WinUtil.IsAtLeastWindows8) + os = ">= Windows 8"; + else if (KeePass.Util.WinUtil.IsAtLeastWindows7) + os = ">= Windows 7"; + else if (KeePass.Util.WinUtil.IsAtLeastWindowsVista) + os = ">= Windows Vista"; + else if (KeePass.Util.WinUtil.IsAtLeastWindows2000) + os = ">= Windows 2000"; + else os = "Unknown"; + } + if (KeePass.Util.WinUtil.IsAppX) + os += " (AppX)"; + os += " - " + Environment.OSVersion.ToString(); + m_xw.WriteElementString("OS", KeePass.Util.WinUtil.GetOSStr() + " " + os); + #endregion + m_xw.WriteElementString("DotNet", DotNetVersion.ToString() + (m_DotNetRelease > 0 ? " (" + m_DotNetRelease.ToString() + ")" : string.Empty)); + m_xw.WriteElementString("KeePass", Tools.KeePassVersion.ToString()); + + m_xw.WriteStartElement("LoadedPlugins"); + foreach (KeyValuePair kvp in m_plugins) + { + m_xw.WriteStartElement("Plugin"); + m_xw.WriteElementString("PluginName", kvp.Key); + m_xw.WriteElementString("PluginVersion", kvp.Value.ToString()); + m_xw.WriteEndElement(); + } + m_xw.WriteEndElement(); + m_xw.WriteEndElement(); + #endregion + + if (m_DebugEntries.Count == 0) + m_xw.WriteElementString("DebugMessages", null); + else + { + m_xw.WriteStartElement("DebugMessages"); + foreach (var m in m_DebugEntries) + m.GetXml(m_xw); + m_xw.WriteEndElement(); + } + + m_xw.WriteEndElement(); + return sEncoding + Xml; + } + } + + private static bool m_Saving = false; + public static void SaveDebugMessages() + { + if (m_Saving) return; + m_Saving = true; + try + { + System.IO.File.WriteAllText(DebugFile, DebugMessages); + } + catch (Exception ex) + { + Tools.ShowError("Can't save debug file: " + DebugFile + "\n\n" + ex.Message); + } + m_Saving = false; + } + + private static bool m_bAllPluginsLoaded = false; + private static void LoadPluginNames(object sender, EventArgs e) + { + if (m_bAllPluginsLoaded) return; + m_plugins = Tools.GetLoadedPluginsName(); + if (sender == null) return; + m_bAllPluginsLoaded = true; + KeePass.Program.MainForm.FormLoadPost -= LoadPluginNames; + } + + private class DebugEntry + { + public LogLevelFlags severity; + public string msg; + public DateTime utc; + public int counter; + public List sf = new List(); + public string[] parameters = null; + + public void GetXml(System.Xml.XmlWriter xw) + { + xw.WriteStartElement("DebugEntry"); + xw.WriteElementString("Message", msg); + xw.WriteElementString("Counter", counter.ToString()); + xw.WriteElementString("Severity", severity.ToString()); + xw.WriteElementString("DateTimeUtc", utc.ToString("yyyyMMddTHHmmssZ")); + if ((parameters == null) || parameters.Length == 0) + xw.WriteElementString("Parameters", null); + else + { + xw.WriteStartElement("Parameters"); + foreach (string p in parameters) + xw.WriteElementString("Param", p); + xw.WriteEndElement(); + } + if (sf.Count == 0) + xw.WriteElementString("StackFrames", null); + else + { + xw.WriteStartElement("StackFrames"); + foreach (var f in sf) + { + xw.WriteStartElement("StackFrame"); + xw.WriteElementString("Method", f.GetMethod().Name + " (" + f.GetMethod().DeclaringType.FullName + ")"); + xw.WriteElementString("FileName", System.IO.Path.GetFileName(f.GetFileName())); + xw.WriteElementString("Line", f.GetFileLineNumber().ToString()); + xw.WriteEndElement(); + } + xw.WriteEndElement(); + } + xw.WriteEndElement(); + } + } + } +} diff --git a/src/Utilities/EventHelper.cs b/src/Utilities/EventHelper.cs index c935249..eabda9e 100644 --- a/src/Utilities/EventHelper.cs +++ b/src/Utilities/EventHelper.cs @@ -6,369 +6,369 @@ namespace PluginTools { - public static class EventHelper - { - public static object DoInvoke(object sender, bool bUnwrapMonoWorkaround, List handlers, params object[] parameters) - { - if (handlers == null) return null; - List lDelegates = bUnwrapMonoWorkaround ? UnwrapMonoWorkaround(sender, handlers) : handlers; - if (lDelegates.Count == 1) - { - return lDelegates[0].DynamicInvoke(parameters) as object; - } - foreach (Delegate d in lDelegates) - d.DynamicInvoke(parameters); - return true; - } - - public static List GetEventHandlers(this object obj, string EventName) - { - List result = new List(); - if (obj == null) return result; - - Type t = obj.GetType(); - List event_fields = GetTypeEventFields(t); - EventHandlerList static_event_handlers = null; - - foreach (FieldInfo fi in event_fields) - { - if (!CheckEvent(fi, EventName)) continue; - - if (fi.IsStatic) - { - - if (static_event_handlers == null) - static_event_handlers = GetStaticEventHandlerList(t, obj); - - object idx = fi.GetValue(obj); - - - Delegate eh = static_event_handlers[idx]; - if (eh == null) - { - var head = GetHead(static_event_handlers); - List lDel = new List(); - CollectEventHandler(head, lDel); - if (lDel.Count == 0) continue; - result.AddRange(lDel); - } - else - { - Delegate[] dels = eh.GetInvocationList(); - if (dels == null) continue; - result.AddRange(dels); - } - } - else - { - EventInfo ei = t.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = t.GetEvent(EventName, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(EventName, AllBindings); - if (ei != null) - { - object val = fi.GetValue(obj); - Delegate mdel = (val as Delegate); - if (mdel != null) - result.AddRange(mdel.GetInvocationList()); - } - } - } - return result; - } - - public static void RemoveEventHandlers(this object obj, string EventName, List handlers) - { - if (obj == null) return; - if (handlers == null) return; - - Type t = obj.GetType(); - List event_fields = GetTypeEventFields(t); - - foreach (FieldInfo fi in event_fields) - { - if (!CheckEvent(fi, EventName)) continue; - - if (fi.IsStatic) - { - EventInfo ei = t.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = t.GetEvent(EventName, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(EventName, AllBindings); - if (ei == null) continue; - - foreach (Delegate del in handlers) - ei.RemoveEventHandler(obj, del); - } - else - { - EventInfo ei = t.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = t.GetEvent(EventName, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(EventName, AllBindings); - if (ei != null) - { - foreach (Delegate del in handlers) - ei.RemoveEventHandler(obj, del); - } - } - } - } - - public static bool AddEventHandlers(this object obj, string EventName, List handlers) - { - if (obj == null) return false; - if (handlers == null) return false; - - Type t = obj.GetType(); - List event_fields = GetTypeEventFields(t); - - bool added = false; - foreach (FieldInfo fi in event_fields) - { - if (!CheckEvent(fi, EventName)) continue; - - if (fi.IsStatic) - { - EventInfo ei = t.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = t.GetEvent(EventName, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(EventName, AllBindings); - if (ei == null) continue; - - foreach (var del in handlers) - ei.AddEventHandler(obj, del); - added = true; - } - else - { - EventInfo ei = t.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = t.GetEvent(EventName, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); - if (ei == null) - ei = fi.DeclaringType.GetEvent(EventName, AllBindings); - if (ei != null) - { - foreach (var del in handlers) - ei.AddEventHandler(obj, del); - added = true; - } - } - } - return added; - } - - private static Dictionary> m_dicEventFieldInfos = new Dictionary>(); - - private static BindingFlags AllBindings - { - get { return BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; } - } - - private static List GetTypeEventFields(Type t) - { - if (m_dicEventFieldInfos.ContainsKey(t)) return m_dicEventFieldInfos[t]; - - List lst = new List(); - BuildEventFields(t, lst); - m_dicEventFieldInfos[t] = lst; - return lst; - } - - private static void BuildEventFields(Type t, List lst) - { - // Type.GetEvent(s) gets all Events for the type AND it's ancestors - // Type.GetField(s) gets only Fields for the exact type. - // (BindingFlags.FlattenHierarchy only works on PROTECTED & PUBLIC - // doesn't work because Fieds are PRIVATE) - var eil = t.GetEvents(AllBindings); - lst.Clear(); - Dictionary> dBuffer = new Dictionary>(); - foreach (EventInfo ei in eil) - { - Type dt = ei.DeclaringType; - if (!dBuffer.ContainsKey(dt)) - { - dBuffer[dt] = new List(); - dBuffer[dt].AddRange(dt.GetFields(AllBindings)); - } - FieldInfo fi = t.GetField(ei.Name, AllBindings); - if (fi == null) - fi = dt.GetField(ei.Name, AllBindings); - if (fi == null) - fi = t.GetField("Event" + ei.Name, AllBindings); - if (fi == null) - fi = dt.GetField("Event" + ei.Name, AllBindings); - if (fi == null) - fi = t.GetField(ei.Name + "Event", AllBindings); - if (fi == null) - fi = dt.GetField(ei.Name + "Event", AllBindings); - if ((fi == null)) // && (dt.Name == "ListView")) - { - fi = dBuffer[dt].Find(x => x.Name.ToLowerInvariant() == "event_" + ei.Name.ToLowerInvariant()); - if (fi == null) fi = dBuffer[dt].Find(x => x.Name.ToLowerInvariant() == ei.Name.ToLowerInvariant() + "_event"); - } - if (fi != null) - lst.Add(fi); - } - } - - private static EventHandlerList GetStaticEventHandlerList(Type t, object obj) - { - MethodInfo mi = t.GetMethod("get_Events", AllBindings); - while ((mi == null) & (t.BaseType != null)) - { - t = t.BaseType; - mi = t.GetMethod("get_Events", AllBindings); - } - if (mi == null) return null; - return (EventHandlerList)mi.Invoke(obj, new object[] { }); - } - - private static bool CheckEvent(FieldInfo fi, string sEventName) - { - if (string.IsNullOrEmpty(sEventName)) - return false; - if (string.Compare(sEventName, fi.Name, true) == 0) - return true; - if (string.Compare("Event" + sEventName, fi.Name, true) == 0) - return true; - if (string.Compare(sEventName + "Event", fi.Name, true) == 0) - return true; - if (string.Compare("Event_" + sEventName, fi.Name, true) == 0) - return true; - if (string.Compare(sEventName + "_Event", fi.Name, true) == 0) - return true; - return false; - } - - private static void CollectEventHandler(object obj, List lDel) - { - try - { - if (obj == null) return; - FieldInfo fHandler = obj.GetType().GetField("handler", AllBindings); - if (fHandler == null) fHandler = obj.GetType().GetField("_handler", AllBindings); - if (fHandler == null) return; - Delegate d = (Delegate)fHandler.GetValue(obj); - Delegate[] d2 = d.GetInvocationList(); - lDel.AddRange(d2); - } - catch { } - } - - private static object GetHead(EventHandlerList eh) - { - try - { - FieldInfo fHead = eh.GetType().GetField("head", AllBindings); - if (fHead == null) fHead = eh.GetType().GetField("_head", AllBindings); - return fHead.GetValue(eh); - } - catch { } - return null; - } - - private static List UnwrapMonoWorkaround(object sender, List handlers) - { - if (!handlers[0].Method.DeclaringType.Name.Contains("MonoWorkaround")) - { - Tools.ShowInfo("No unwrapping required"); - return handlers; - } - List lHandlers = new List(); - FieldInfo fiHandlers = typeof(KeePassLib.Utility.MonoWorkarounds).GetField("m_dictHandlers", BindingFlags.Static | BindingFlags.NonPublic); - if (fiHandlers == null) - { - Tools.ShowError("No unwrapping possible - fiHandlers null"); - return handlers; - } - var dictHandler = fiHandlers.GetValue(null); - MethodInfo miTryGetValue = dictHandler.GetType().GetMethod("TryGetValue", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - object[] o = new object[] { sender, null }; - miTryGetValue.Invoke(dictHandler, o); - if ((o == null) || (o.Length < 1)) - { - Tools.ShowError("No unwrapping possible - object not found"); - return handlers; - } - Delegate dUnwrapped = Tools.GetField("m_fnOrg", o[1]) as Delegate; - Tools.ShowInfo("Wrapped\n\nOld: " + handlers[0].Method.Name + " - " + handlers[0].Method.DeclaringType.Name + "\n" + dUnwrapped.Method.Name + " - " + dUnwrapped.Method.DeclaringType.Name); - lHandlers.Add(dUnwrapped); - return lHandlers; - } - } - - public class MonoWorkaroundDialogResult : IDisposable - { - private bool m_bRequired = false; - private DialogResult m_dr = DialogResult.None; - - private object m_oMwaHandlerInfo = null; - private FieldInfo m_fiDialogResult = null; - - public MonoWorkaroundDialogResult(object sender) - { - if (sender == null) return; - if (!KeePassLib.Native.NativeLib.IsUnix()) return; - - GetDialogResultObject(sender); - - if (m_oMwaHandlerInfo == null) return; - - SetDialogResult(DialogResult.None); - } - - public void Dispose() - { - if (!m_bRequired) return; - SetDialogResult(m_dr); - } - - private void GetDialogResultObject(object sender) - { - if (sender == null) return; - - FieldInfo fiHandlers = typeof(KeePassLib.Utility.MonoWorkarounds).GetField("m_dictHandlers", BindingFlags.Static | BindingFlags.NonPublic); - object dictHandler = null; - if (fiHandlers != null) dictHandler = fiHandlers.GetValue(null); - - //Do NOT set bRequired, spmething went wrong and we will stick to KeePass standard behaviour - if (dictHandler == null) return; - - MethodInfo miTryGetValue = dictHandler.GetType().GetMethod("TryGetValue", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - //Do NOT set bRequired, spmething went wrong and we will stick to KeePass standard behaviour - if (miTryGetValue == null) return; - - object[] o = new object[] { sender, null }; - miTryGetValue.Invoke(dictHandler, o); - //Do NOT set bRequired, spmething went wrong and we will stick to KeePass standard behaviour - if ((o == null) || (o.Length < 1)) return; - - m_oMwaHandlerInfo = o[1]; - m_fiDialogResult = m_oMwaHandlerInfo.GetType().GetField("m_dr", BindingFlags.Instance | BindingFlags.NonPublic); - - m_bRequired = true; - m_dr = (DialogResult)m_fiDialogResult.GetValue(m_oMwaHandlerInfo); - } - - private void SetDialogResult(DialogResult dr) - { - m_fiDialogResult.SetValue(m_oMwaHandlerInfo, dr); - } - } + public static class EventHelper + { + public static object DoInvoke(object sender, bool bUnwrapMonoWorkaround, List handlers, params object[] parameters) + { + if (handlers == null) return null; + List lDelegates = bUnwrapMonoWorkaround ? UnwrapMonoWorkaround(sender, handlers) : handlers; + if (lDelegates.Count == 1) + { + return lDelegates[0].DynamicInvoke(parameters) as object; + } + foreach (Delegate d in lDelegates) + d.DynamicInvoke(parameters); + return true; + } + + public static List GetEventHandlers(this object obj, string EventName) + { + List result = new List(); + if (obj == null) return result; + + Type t = obj.GetType(); + List event_fields = GetTypeEventFields(t); + EventHandlerList static_event_handlers = null; + + foreach (FieldInfo fi in event_fields) + { + if (!CheckEvent(fi, EventName)) continue; + + if (fi.IsStatic) + { + + if (static_event_handlers == null) + static_event_handlers = GetStaticEventHandlerList(t, obj); + + object idx = fi.GetValue(obj); + + + Delegate eh = static_event_handlers[idx]; + if (eh == null) + { + var head = GetHead(static_event_handlers); + List lDel = new List(); + CollectEventHandler(head, lDel); + if (lDel.Count == 0) continue; + result.AddRange(lDel); + } + else + { + Delegate[] dels = eh.GetInvocationList(); + if (dels == null) continue; + result.AddRange(dels); + } + } + else + { + EventInfo ei = t.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = t.GetEvent(EventName, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(EventName, AllBindings); + if (ei != null) + { + object val = fi.GetValue(obj); + Delegate mdel = (val as Delegate); + if (mdel != null) + result.AddRange(mdel.GetInvocationList()); + } + } + } + return result; + } + + public static void RemoveEventHandlers(this object obj, string EventName, List handlers) + { + if (obj == null) return; + if (handlers == null) return; + + Type t = obj.GetType(); + List event_fields = GetTypeEventFields(t); + + foreach (FieldInfo fi in event_fields) + { + if (!CheckEvent(fi, EventName)) continue; + + if (fi.IsStatic) + { + EventInfo ei = t.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = t.GetEvent(EventName, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(EventName, AllBindings); + if (ei == null) continue; + + foreach (Delegate del in handlers) + ei.RemoveEventHandler(obj, del); + } + else + { + EventInfo ei = t.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = t.GetEvent(EventName, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(EventName, AllBindings); + if (ei != null) + { + foreach (Delegate del in handlers) + ei.RemoveEventHandler(obj, del); + } + } + } + } + + public static bool AddEventHandlers(this object obj, string EventName, List handlers) + { + if (obj == null) return false; + if (handlers == null) return false; + + Type t = obj.GetType(); + List event_fields = GetTypeEventFields(t); + + bool added = false; + foreach (FieldInfo fi in event_fields) + { + if (!CheckEvent(fi, EventName)) continue; + + if (fi.IsStatic) + { + EventInfo ei = t.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = t.GetEvent(EventName, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(EventName, AllBindings); + if (ei == null) continue; + + foreach (var del in handlers) + ei.AddEventHandler(obj, del); + added = true; + } + else + { + EventInfo ei = t.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = t.GetEvent(EventName, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); + if (ei == null) + ei = fi.DeclaringType.GetEvent(EventName, AllBindings); + if (ei != null) + { + foreach (var del in handlers) + ei.AddEventHandler(obj, del); + added = true; + } + } + } + return added; + } + + private static Dictionary> m_dicEventFieldInfos = new Dictionary>(); + + private static BindingFlags AllBindings + { + get { return BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; } + } + + private static List GetTypeEventFields(Type t) + { + if (m_dicEventFieldInfos.ContainsKey(t)) return m_dicEventFieldInfos[t]; + + List lst = new List(); + BuildEventFields(t, lst); + m_dicEventFieldInfos[t] = lst; + return lst; + } + + private static void BuildEventFields(Type t, List lst) + { + // Type.GetEvent(s) gets all Events for the type AND it's ancestors + // Type.GetField(s) gets only Fields for the exact type. + // (BindingFlags.FlattenHierarchy only works on PROTECTED & PUBLIC + // doesn't work because Fieds are PRIVATE) + var eil = t.GetEvents(AllBindings); + lst.Clear(); + Dictionary> dBuffer = new Dictionary>(); + foreach (EventInfo ei in eil) + { + Type dt = ei.DeclaringType; + if (!dBuffer.ContainsKey(dt)) + { + dBuffer[dt] = new List(); + dBuffer[dt].AddRange(dt.GetFields(AllBindings)); + } + FieldInfo fi = t.GetField(ei.Name, AllBindings); + if (fi == null) + fi = dt.GetField(ei.Name, AllBindings); + if (fi == null) + fi = t.GetField("Event" + ei.Name, AllBindings); + if (fi == null) + fi = dt.GetField("Event" + ei.Name, AllBindings); + if (fi == null) + fi = t.GetField(ei.Name + "Event", AllBindings); + if (fi == null) + fi = dt.GetField(ei.Name + "Event", AllBindings); + if ((fi == null)) // && (dt.Name == "ListView")) + { + fi = dBuffer[dt].Find(x => x.Name.ToLowerInvariant() == "event_" + ei.Name.ToLowerInvariant()); + if (fi == null) fi = dBuffer[dt].Find(x => x.Name.ToLowerInvariant() == ei.Name.ToLowerInvariant() + "_event"); + } + if (fi != null) + lst.Add(fi); + } + } + + private static EventHandlerList GetStaticEventHandlerList(Type t, object obj) + { + MethodInfo mi = t.GetMethod("get_Events", AllBindings); + while ((mi == null) & (t.BaseType != null)) + { + t = t.BaseType; + mi = t.GetMethod("get_Events", AllBindings); + } + if (mi == null) return null; + return (EventHandlerList)mi.Invoke(obj, new object[] { }); + } + + private static bool CheckEvent(FieldInfo fi, string sEventName) + { + if (string.IsNullOrEmpty(sEventName)) + return false; + if (string.Compare(sEventName, fi.Name, true) == 0) + return true; + if (string.Compare("Event" + sEventName, fi.Name, true) == 0) + return true; + if (string.Compare(sEventName + "Event", fi.Name, true) == 0) + return true; + if (string.Compare("Event_" + sEventName, fi.Name, true) == 0) + return true; + if (string.Compare(sEventName + "_Event", fi.Name, true) == 0) + return true; + return false; + } + + private static void CollectEventHandler(object obj, List lDel) + { + try + { + if (obj == null) return; + FieldInfo fHandler = obj.GetType().GetField("handler", AllBindings); + if (fHandler == null) fHandler = obj.GetType().GetField("_handler", AllBindings); + if (fHandler == null) return; + Delegate d = (Delegate)fHandler.GetValue(obj); + Delegate[] d2 = d.GetInvocationList(); + lDel.AddRange(d2); + } + catch { } + } + + private static object GetHead(EventHandlerList eh) + { + try + { + FieldInfo fHead = eh.GetType().GetField("head", AllBindings); + if (fHead == null) fHead = eh.GetType().GetField("_head", AllBindings); + return fHead.GetValue(eh); + } + catch { } + return null; + } + + private static List UnwrapMonoWorkaround(object sender, List handlers) + { + if (!handlers[0].Method.DeclaringType.Name.Contains("MonoWorkaround")) + { + Tools.ShowInfo("No unwrapping required"); + return handlers; + } + List lHandlers = new List(); + FieldInfo fiHandlers = typeof(KeePassLib.Utility.MonoWorkarounds).GetField("m_dictHandlers", BindingFlags.Static | BindingFlags.NonPublic); + if (fiHandlers == null) + { + Tools.ShowError("No unwrapping possible - fiHandlers null"); + return handlers; + } + var dictHandler = fiHandlers.GetValue(null); + MethodInfo miTryGetValue = dictHandler.GetType().GetMethod("TryGetValue", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + object[] o = new object[] { sender, null }; + miTryGetValue.Invoke(dictHandler, o); + if ((o == null) || (o.Length < 1)) + { + Tools.ShowError("No unwrapping possible - object not found"); + return handlers; + } + Delegate dUnwrapped = Tools.GetField("m_fnOrg", o[1]) as Delegate; + Tools.ShowInfo("Wrapped\n\nOld: " + handlers[0].Method.Name + " - " + handlers[0].Method.DeclaringType.Name + "\n" + dUnwrapped.Method.Name + " - " + dUnwrapped.Method.DeclaringType.Name); + lHandlers.Add(dUnwrapped); + return lHandlers; + } + } + + public class MonoWorkaroundDialogResult : IDisposable + { + private bool m_bRequired = false; + private DialogResult m_dr = DialogResult.None; + + private object m_oMwaHandlerInfo = null; + private FieldInfo m_fiDialogResult = null; + + public MonoWorkaroundDialogResult(object sender) + { + if (sender == null) return; + if (!KeePassLib.Native.NativeLib.IsUnix()) return; + + GetDialogResultObject(sender); + + if (m_oMwaHandlerInfo == null) return; + + SetDialogResult(DialogResult.None); + } + + public void Dispose() + { + if (!m_bRequired) return; + SetDialogResult(m_dr); + } + + private void GetDialogResultObject(object sender) + { + if (sender == null) return; + + FieldInfo fiHandlers = typeof(KeePassLib.Utility.MonoWorkarounds).GetField("m_dictHandlers", BindingFlags.Static | BindingFlags.NonPublic); + object dictHandler = null; + if (fiHandlers != null) dictHandler = fiHandlers.GetValue(null); + + //Do NOT set bRequired, spmething went wrong and we will stick to KeePass standard behaviour + if (dictHandler == null) return; + + MethodInfo miTryGetValue = dictHandler.GetType().GetMethod("TryGetValue", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + //Do NOT set bRequired, spmething went wrong and we will stick to KeePass standard behaviour + if (miTryGetValue == null) return; + + object[] o = new object[] { sender, null }; + miTryGetValue.Invoke(dictHandler, o); + //Do NOT set bRequired, spmething went wrong and we will stick to KeePass standard behaviour + if ((o == null) || (o.Length < 1)) return; + + m_oMwaHandlerInfo = o[1]; + m_fiDialogResult = m_oMwaHandlerInfo.GetType().GetField("m_dr", BindingFlags.Instance | BindingFlags.NonPublic); + + m_bRequired = true; + m_dr = (DialogResult)m_fiDialogResult.GetValue(m_oMwaHandlerInfo); + } + + private void SetDialogResult(DialogResult dr) + { + m_fiDialogResult.SetValue(m_oMwaHandlerInfo, dr); + } + } } diff --git a/src/Utilities/Tools_Controls.cs b/src/Utilities/Tools_Controls.cs index 8f432c6..0b95ba4 100644 --- a/src/Utilities/Tools_Controls.cs +++ b/src/Utilities/Tools_Controls.cs @@ -4,60 +4,60 @@ namespace PluginTools { - public static partial class Tools - { - public static object GetField(string field, object obj) - { - BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; - return GetField(field, obj, bf); - } + public static partial class Tools + { + public static object GetField(string field, object obj) + { + BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; + return GetField(field, obj, bf); + } - public static object GetField(string field, object obj, BindingFlags bf) - { - if (obj == null) return null; - FieldInfo fi = obj.GetType().GetField(field, bf); - if (fi == null) return null; - return fi.GetValue(obj); - } + public static object GetField(string field, object obj, BindingFlags bf) + { + if (obj == null) return null; + FieldInfo fi = obj.GetType().GetField(field, bf); + if (fi == null) return null; + return fi.GetValue(obj); + } - public static Control GetControl(string control) - { - return GetControl(control, KeePass.Program.MainForm); - } + public static Control GetControl(string control) + { + return GetControl(control, KeePass.Program.MainForm); + } - public static Control GetControl(string control, Control form) - { - if (form == null) return null; - if (string.IsNullOrEmpty(control)) return null; - Control[] cntrls = form.Controls.Find(control, true); - if (cntrls.Length == 0) return null; - return cntrls[0]; - } + public static Control GetControl(string control, Control form) + { + if (form == null) return null; + if (string.IsNullOrEmpty(control)) return null; + Control[] cntrls = form.Controls.Find(control, true); + if (cntrls.Length == 0) return null; + return cntrls[0]; + } - public static ToolStripMenuItem FindToolStripMenuItem(ToolStripItemCollection tsic, string key, bool searchAllChildren) - { - if (tsic == null) return null; - ToolStripItem[] tsi = FindToolStripMenuItems(tsic, key, searchAllChildren); - if (tsi.Length > 0) return tsi[0] as ToolStripMenuItem; - return null; - } + public static ToolStripMenuItem FindToolStripMenuItem(ToolStripItemCollection tsic, string key, bool searchAllChildren) + { + if (tsic == null) return null; + ToolStripItem[] tsi = FindToolStripMenuItems(tsic, key, searchAllChildren); + if (tsi.Length > 0) return tsi[0] as ToolStripMenuItem; + return null; + } - public static ToolStripItem[] FindToolStripMenuItems(ToolStripItemCollection tsic, string key, bool searchAllChildren) - { - if (tsic == null) return new ToolStripItem[] { }; - ToolStripItem[] tsi = tsic.Find(key, searchAllChildren); - if (!MonoWorkaroundRequired || !searchAllChildren) return tsi; + public static ToolStripItem[] FindToolStripMenuItems(ToolStripItemCollection tsic, string key, bool searchAllChildren) + { + if (tsic == null) return new ToolStripItem[] { }; + ToolStripItem[] tsi = tsic.Find(key, searchAllChildren); + if (!MonoWorkaroundRequired || !searchAllChildren) return tsi; - //Mono does not support 'searchAllChildren' for ToolStripItemCollection - //Iterate over all items and search for given item - List lItems = new List(tsi); - foreach (var item in tsic) - { - ToolStripMenuItem tsmi = item as ToolStripMenuItem; - if (tsmi == null) continue; - lItems.AddRange(FindToolStripMenuItems(tsmi.DropDownItems, key, searchAllChildren)); - } - return lItems.ToArray(); - } - } -} \ No newline at end of file + //Mono does not support 'searchAllChildren' for ToolStripItemCollection + //Iterate over all items and search for given item + List lItems = new List(tsi); + foreach (var item in tsic) + { + ToolStripMenuItem tsmi = item as ToolStripMenuItem; + if (tsmi == null) continue; + lItems.AddRange(FindToolStripMenuItems(tsmi.DropDownItems, key, searchAllChildren)); + } + return lItems.ToArray(); + } + } +} diff --git a/src/Utilities/Tools_ListView_Sortable.cs b/src/Utilities/Tools_ListView_Sortable.cs index d7ac30c..583b068 100644 --- a/src/Utilities/Tools_ListView_Sortable.cs +++ b/src/Utilities/Tools_ListView_Sortable.cs @@ -1,90 +1,90 @@ -using KeePass.UI; -using System; +using System; using System.Windows.Forms; +using KeePass.UI; namespace PluginTools { - public static partial class Tools_ListView_Sortable - { - public static void RS_Sortable(this ListView lv, bool bSortable) - { - if (lv == null) return; - if (!bSortable) - { - lv.ListViewItemSorter = null; - return; - } - if (lv.ListViewItemSorter != null) return; - lv.ListViewItemSorter = new ListSorter() { CompareNaturally = true }; - lv.ColumnClick += DoSort; - lv.HeaderStyle = ColumnHeaderStyle.Clickable; - } + public static partial class Tools_ListView_Sortable + { + public static void RS_Sortable(this ListView lv, bool bSortable) + { + if (lv == null) return; + if (!bSortable) + { + lv.ListViewItemSorter = null; + return; + } + if (lv.ListViewItemSorter != null) return; + lv.ListViewItemSorter = new ListSorter() { CompareNaturally = true }; + lv.ColumnClick += DoSort; + lv.HeaderStyle = ColumnHeaderStyle.Clickable; + } - private static void DoSort(object sender, ColumnClickEventArgs e) - { - var lv = sender as ListView; - if (lv == null || lv.ListViewItemSorter == null) return; - var ls = lv.ListViewItemSorter as ListSorter; - DateTime dt; - ls.CompareTimes = DateTime.TryParse(lv.Items[0].SubItems[e.Column].Text, out dt); - if (e.Column == ls.Column) - { - if (ls.Order == SortOrder.Ascending) ls.Order = SortOrder.Descending; - else ls.Order = SortOrder.Ascending; - } - else - { - ls.Column = e.Column; - ls.Order = SortOrder.Ascending; - } - lv.Sort(); - lv.UpdateColumnSortingIcons(ls); - } + private static void DoSort(object sender, ColumnClickEventArgs e) + { + var lv = sender as ListView; + if (lv == null || lv.ListViewItemSorter == null) return; + var ls = lv.ListViewItemSorter as ListSorter; + DateTime dt; + ls.CompareTimes = DateTime.TryParse(lv.Items[0].SubItems[e.Column].Text, out dt); + if (e.Column == ls.Column) + { + if (ls.Order == SortOrder.Ascending) ls.Order = SortOrder.Descending; + else ls.Order = SortOrder.Ascending; + } + else + { + ls.Column = e.Column; + ls.Order = SortOrder.Ascending; + } + lv.Sort(); + lv.UpdateColumnSortingIcons(ls); + } - private static void UpdateColumnSortingIcons(this ListView lv, ListSorter ls) - { - if (lv == null) return; - if (UIUtil.SetSortIcon(lv, ls.Column, ls.Order)) return; + private static void UpdateColumnSortingIcons(this ListView lv, ListSorter ls) + { + if (lv == null) return; + if (UIUtil.SetSortIcon(lv, ls.Column, ls.Order)) return; - // if(m_lvEntries.SmallImageList == null) return; + // if(m_lvEntries.SmallImageList == null) return; - if (ls.Column < 0) return; + if (ls.Column < 0) return; - string strAsc = " \u2191"; // Must have same length - string strDsc = " \u2193"; // Must have same length - if (KeePass.Util.WinUtil.IsWindows9x || KeePass.Util.WinUtil.IsWindows2000 || KeePass.Util.WinUtil.IsWindowsXP || - KeePassLib.Native.NativeLib.IsUnix()) - { - strAsc = @" ^"; - strDsc = @" v"; - } - else if (KeePass.Util.WinUtil.IsAtLeastWindowsVista) - { - strAsc = " \u25B3"; - strDsc = " \u25BD"; - } + string strAsc = " \u2191"; // Must have same length + string strDsc = " \u2193"; // Must have same length + if (KeePass.Util.WinUtil.IsWindows9x || KeePass.Util.WinUtil.IsWindows2000 || KeePass.Util.WinUtil.IsWindowsXP || + KeePassLib.Native.NativeLib.IsUnix()) + { + strAsc = @" ^"; + strDsc = @" v"; + } + else if (KeePass.Util.WinUtil.IsAtLeastWindowsVista) + { + strAsc = " \u25B3"; + strDsc = " \u25BD"; + } - foreach (ColumnHeader ch in lv.Columns) - { - string strCur = ch.Text, strNew = null; + foreach (ColumnHeader ch in lv.Columns) + { + string strCur = ch.Text, strNew = null; - if (strCur.EndsWith(strAsc) || strCur.EndsWith(strDsc)) - { - strNew = strCur.Substring(0, strCur.Length - strAsc.Length); - strCur = strNew; - } + if (strCur.EndsWith(strAsc) || strCur.EndsWith(strDsc)) + { + strNew = strCur.Substring(0, strCur.Length - strAsc.Length); + strCur = strNew; + } - if ((ch.Index == ls.Column) && - (ls.Order != SortOrder.None)) - { - if (ls.Order == SortOrder.Ascending) - strNew = strCur + strAsc; - else if (ls.Order == SortOrder.Descending) - strNew = strCur + strDsc; - } + if ((ch.Index == ls.Column) && + (ls.Order != SortOrder.None)) + { + if (ls.Order == SortOrder.Ascending) + strNew = strCur + strAsc; + else if (ls.Order == SortOrder.Descending) + strNew = strCur + strDsc; + } - if (strNew != null) ch.Text = strNew; - } - } - } -} \ No newline at end of file + if (strNew != null) ch.Text = strNew; + } + } + } +} diff --git a/src/Utilities/Tools_Main.cs b/src/Utilities/Tools_Main.cs index 67c123a..df6d347 100644 --- a/src/Utilities/Tools_Main.cs +++ b/src/Utilities/Tools_Main.cs @@ -1,93 +1,93 @@ -using KeePass.UI; -using System; +using System; using System.Windows.Forms; +using KeePass.UI; namespace PluginTools { - public static partial class Tools - { - public static Version KeePassVersion { get; private set; } - public static string DefaultCaption = string.Empty; - public static string PluginURL = string.Empty; - public static string KeePassLanguageIso6391 { get; private set; } + public static partial class Tools + { + public static Version KeePassVersion { get; private set; } + public static string DefaultCaption = string.Empty; + public static string PluginURL = string.Empty; + public static string KeePassLanguageIso6391 { get; private set; } - private static bool MonoWorkaroundRequired = KeePassLib.Native.NativeLib.IsUnix(); + private static bool MonoWorkaroundRequired = KeePassLib.Native.NativeLib.IsUnix(); - static Tools() - { - KeePass.UI.GlobalWindowManager.WindowAdded += OnWindowAdded; - KeePass.UI.GlobalWindowManager.WindowRemoved += OnWindowRemoved; - KeePassVersion = typeof(KeePass.Program).Assembly.GetName().Version; - KeePassLanguageIso6391 = KeePass.Program.Translation.Properties.Iso6391Code; - if (string.IsNullOrEmpty(KeePassLanguageIso6391)) KeePassLanguageIso6391 = "en"; - m_sPluginClassname = typeof(Tools).Assembly.GetName().Name + "Ext"; - } + static Tools() + { + KeePass.UI.GlobalWindowManager.WindowAdded += OnWindowAdded; + KeePass.UI.GlobalWindowManager.WindowRemoved += OnWindowRemoved; + KeePassVersion = typeof(KeePass.Program).Assembly.GetName().Version; + KeePassLanguageIso6391 = KeePass.Program.Translation.Properties.Iso6391Code; + if (string.IsNullOrEmpty(KeePassLanguageIso6391)) KeePassLanguageIso6391 = "en"; + m_sPluginClassname = typeof(Tools).Assembly.GetName().Name + "Ext"; + } - public static void OpenUrl(string sURL) - { - OpenUrl(sURL, null); - } + public static void OpenUrl(string sURL) + { + OpenUrl(sURL, null); + } - public static void OpenUrl(string sURL, KeePassLib.PwEntry pe) - { - //Use KeePass built-in logic instead of System.Diagnostics.Process.Start - //For details see: https://sourceforge.net/p/keepass/discussion/329221/thread/f399b6d74b/#4801 - KeePass.Util.WinUtil.OpenUrl(sURL, pe, true); - } + public static void OpenUrl(string sURL, KeePassLib.PwEntry pe) + { + //Use KeePass built-in logic instead of System.Diagnostics.Process.Start + //For details see: https://sourceforge.net/p/keepass/discussion/329221/thread/f399b6d74b/#4801 + KeePass.Util.WinUtil.OpenUrl(sURL, pe, true); + } - #region MessageBox shortcuts - public static DialogResult ShowError(string msg) - { - return ShowError(msg, DefaultCaption); - } + #region MessageBox shortcuts + public static DialogResult ShowError(string msg) + { + return ShowError(msg, DefaultCaption); + } - public static DialogResult ShowInfo(string msg) - { - return ShowInfo(msg, DefaultCaption); - } + public static DialogResult ShowInfo(string msg) + { + return ShowInfo(msg, DefaultCaption); + } - public static DialogResult AskYesNo(string msg) - { - return AskYesNo(msg, DefaultCaption); - } + public static DialogResult AskYesNo(string msg) + { + return AskYesNo(msg, DefaultCaption); + } - public static DialogResult ShowError(string msg, string caption) - { - PluginDebug.AddError("Show error", 6, caption, msg); - return MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); - } + public static DialogResult ShowError(string msg, string caption) + { + PluginDebug.AddError("Show error", 6, caption, msg); + return MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); + } - public static DialogResult ShowInfo(string msg, string caption) - { - PluginDebug.AddInfo("Show info", 6, caption, msg); - return MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Information); - } + public static DialogResult ShowInfo(string msg, string caption) + { + PluginDebug.AddInfo("Show info", 6, caption, msg); + return MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Information); + } - public static DialogResult AskYesNo(string msg, string caption) - { - DialogResult result = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question); - PluginDebug.AddInfo("Ask question", 6, caption, msg, "Result: " + result.ToString()); - return result; - } - #endregion + public static DialogResult AskYesNo(string msg, string caption) + { + DialogResult result = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question); + PluginDebug.AddInfo("Ask question", 6, caption, msg, "Result: " + result.ToString()); + return result; + } + #endregion - #region GlobalWindowManager - public static void GlobalWindowManager(Form form) - { - if ((form == null) || (form.IsDisposed)) return; - form.Load += FormLoaded; - form.FormClosed += FormClosed; - } + #region GlobalWindowManager + public static void GlobalWindowManager(Form form) + { + if ((form == null) || (form.IsDisposed)) return; + form.Load += FormLoaded; + form.FormClosed += FormClosed; + } - private static void FormLoaded(object sender, EventArgs e) - { - KeePass.UI.GlobalWindowManager.AddWindow(sender as Form, sender as IGwmWindow); - } + private static void FormLoaded(object sender, EventArgs e) + { + KeePass.UI.GlobalWindowManager.AddWindow(sender as Form, sender as IGwmWindow); + } - private static void FormClosed(object sender, FormClosedEventArgs e) - { - KeePass.UI.GlobalWindowManager.RemoveWindow(sender as Form); - } - #endregion - } -} \ No newline at end of file + private static void FormClosed(object sender, FormClosedEventArgs e) + { + KeePass.UI.GlobalWindowManager.RemoveWindow(sender as Form); + } + #endregion + } +} diff --git a/src/Utilities/Tools_Options.cs b/src/Utilities/Tools_Options.cs index 51eb9fe..567c450 100644 --- a/src/Utilities/Tools_Options.cs +++ b/src/Utilities/Tools_Options.cs @@ -1,375 +1,375 @@ -using KeePass.Forms; -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.Reflection; using System.Windows.Forms; +using KeePass.Forms; namespace PluginTools { - public static partial class Tools - { - public static object GetPluginInstance(string PluginName) - { - string comp = PluginName + "." + PluginName + "Ext"; - BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; - try - { - var PluginManager = GetField("m_pluginManager", KeePass.Program.MainForm); - var PluginList = GetField("m_vPlugins", PluginManager); - MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); - IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); - while (PluginIterator.MoveNext()) - { - object result = GetField("m_pluginInterface", PluginIterator.Current); - if (comp == result.GetType().ToString()) return result; - } - } + public static partial class Tools + { + public static object GetPluginInstance(string PluginName) + { + string comp = PluginName + "." + PluginName + "Ext"; + BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; + try + { + var PluginManager = GetField("m_pluginManager", KeePass.Program.MainForm); + var PluginList = GetField("m_vPlugins", PluginManager); + MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); + IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); + while (PluginIterator.MoveNext()) + { + object result = GetField("m_pluginInterface", PluginIterator.Current); + if (comp == result.GetType().ToString()) return result; + } + } - catch (Exception) { } - return null; - } + catch (Exception) { } + return null; + } - public static Dictionary GetLoadedPluginsName() - { - Dictionary dPlugins = new Dictionary(); - BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; - try - { - var PluginManager = GetField("m_pluginManager", KeePass.Program.MainForm); - var PluginList = GetField("m_vPlugins", PluginManager); - MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); - IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); - while (PluginIterator.MoveNext()) - { - object result = GetField("m_pluginInterface", PluginIterator.Current); - var x = result.GetType().Assembly; - object[] v = x.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), true); - Version ver = null; - if ((v != null) && (v.Length > 0)) - ver = new Version(((AssemblyFileVersionAttribute)v[0]).Version); - else - ver = result.GetType().Assembly.GetName().Version; - if (ver.Build < 0) ver = new Version(ver.Major, ver.Minor, 0, 0); - if (ver.Revision < 0) ver = new Version(ver.Major, ver.Minor, ver.Build, 0); - dPlugins[result.GetType().FullName] = ver; - } - } - catch (Exception) { } - return dPlugins; - } + public static Dictionary GetLoadedPluginsName() + { + Dictionary dPlugins = new Dictionary(); + BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; + try + { + var PluginManager = GetField("m_pluginManager", KeePass.Program.MainForm); + var PluginList = GetField("m_vPlugins", PluginManager); + MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); + IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); + while (PluginIterator.MoveNext()) + { + object result = GetField("m_pluginInterface", PluginIterator.Current); + var x = result.GetType().Assembly; + object[] v = x.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), true); + Version ver = null; + if ((v != null) && (v.Length > 0)) + ver = new Version(((AssemblyFileVersionAttribute)v[0]).Version); + else + ver = result.GetType().Assembly.GetName().Version; + if (ver.Build < 0) ver = new Version(ver.Major, ver.Minor, 0, 0); + if (ver.Revision < 0) ver = new Version(ver.Major, ver.Minor, ver.Build, 0); + dPlugins[result.GetType().FullName] = ver; + } + } + catch (Exception) { } + return dPlugins; + } - public static event EventHandler OptionsFormShown; - public static event EventHandler OptionsFormClosed; + public static event EventHandler OptionsFormShown; + public static event EventHandler OptionsFormClosed; - private static bool OptionsEnabled = (KeePass.Program.Config.UI.UIFlags & (ulong)KeePass.App.Configuration.AceUIFlags.DisableOptions) != (ulong)KeePass.App.Configuration.AceUIFlags.DisableOptions; - private static bool m_ActivatePluginTab = false; - private static string m_sPluginClassname = string.Empty; - private static OptionsForm m_of = null; - private const string c_tabRookiestyle = "m_tabRookiestyle"; - private const string c_tabControlRookiestyle = "m_tabControlRookiestyle"; - private static string m_TabPageName = string.Empty; - private static bool m_OptionsShown = false; - private static bool m_PluginContainerShown = false; + private static bool OptionsEnabled = (KeePass.Program.Config.UI.UIFlags & (ulong)KeePass.App.Configuration.AceUIFlags.DisableOptions) != (ulong)KeePass.App.Configuration.AceUIFlags.DisableOptions; + private static bool m_ActivatePluginTab = false; + private static string m_sPluginClassname = string.Empty; + private static OptionsForm m_of = null; + private const string c_tabRookiestyle = "m_tabRookiestyle"; + private const string c_tabControlRookiestyle = "m_tabControlRookiestyle"; + private static string m_TabPageName = string.Empty; + private static bool m_OptionsShown = false; + private static bool m_PluginContainerShown = false; - public static void AddPluginToOptionsForm(KeePass.Plugins.Plugin p, UserControl uc) - { - m_OptionsShown = m_PluginContainerShown = false; - TabPage tPlugin = new TabPage(DefaultCaption); - tPlugin.CreateControl(); - tPlugin.Name = m_TabPageName = c_tabRookiestyle + p.GetType().Name; - uc.Dock = DockStyle.Fill; - uc.Padding = new Padding(15, 10, 15, 10); - tPlugin.Controls.Add(uc); - PluginDebug.AddInfo("Adding/Searching " + c_tabControlRookiestyle); - TabControl tcPlugins = AddPluginTabContainer(); - int i = 0; - bool insert = false; - for (int j = 0; j < tcPlugins.TabPages.Count; j++) - { - if (string.Compare(tPlugin.Text, tcPlugins.TabPages[j].Text, StringComparison.CurrentCultureIgnoreCase) < 0) - { - i = j; - insert = true; - break; - } - } - if (!insert) - { - i = tcPlugins.TabPages.Count; - PluginDebug.AddInfo(p.GetType().Name + " tab index : " + i.ToString() + " - insert!", 0); - } - else PluginDebug.AddInfo(p.GetType().Name + " tab index : " + i.ToString(), 0); - tcPlugins.TabPages.Insert(i, tPlugin); - AddPluginToOverview(tPlugin.Name.Replace(c_tabRookiestyle, string.Empty), tcPlugins); - if (p.SmallIcon != null) - { - tcPlugins.ImageList.Images.Add(tPlugin.Name, p.SmallIcon); - tPlugin.ImageKey = tPlugin.Name; - } - TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; - if (!string.IsNullOrEmpty(PluginURL)) AddPluginLink(uc); - } + public static void AddPluginToOptionsForm(KeePass.Plugins.Plugin p, UserControl uc) + { + m_OptionsShown = m_PluginContainerShown = false; + TabPage tPlugin = new TabPage(DefaultCaption); + tPlugin.CreateControl(); + tPlugin.Name = m_TabPageName = c_tabRookiestyle + p.GetType().Name; + uc.Dock = DockStyle.Fill; + uc.Padding = new Padding(15, 10, 15, 10); + tPlugin.Controls.Add(uc); + PluginDebug.AddInfo("Adding/Searching " + c_tabControlRookiestyle); + TabControl tcPlugins = AddPluginTabContainer(); + int i = 0; + bool insert = false; + for (int j = 0; j < tcPlugins.TabPages.Count; j++) + { + if (string.Compare(tPlugin.Text, tcPlugins.TabPages[j].Text, StringComparison.CurrentCultureIgnoreCase) < 0) + { + i = j; + insert = true; + break; + } + } + if (!insert) + { + i = tcPlugins.TabPages.Count; + PluginDebug.AddInfo(p.GetType().Name + " tab index : " + i.ToString() + " - insert!", 0); + } + else PluginDebug.AddInfo(p.GetType().Name + " tab index : " + i.ToString(), 0); + tcPlugins.TabPages.Insert(i, tPlugin); + AddPluginToOverview(tPlugin.Name.Replace(c_tabRookiestyle, string.Empty), tcPlugins); + if (p.SmallIcon != null) + { + tcPlugins.ImageList.Images.Add(tPlugin.Name, p.SmallIcon); + tPlugin.ImageKey = tPlugin.Name; + } + TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; + if (!string.IsNullOrEmpty(PluginURL)) AddPluginLink(uc); + } - public static void AddPluginToOverview(string sPluginName) - { - AddPluginToOverview(sPluginName, null); - } + public static void AddPluginToOverview(string sPluginName) + { + AddPluginToOverview(sPluginName, null); + } - private static void AddPluginToOverview(string sPluginName, TabControl tcPlugins) - { - if (tcPlugins == null) tcPlugins = AddPluginTabContainer(); - TabPage tpOverview = null; - ListView lv = null; - string sTabName = c_tabRookiestyle + "_PluginOverview"; - string sListViewName = c_tabRookiestyle + "_PluginOverviewListView"; - if (tcPlugins.TabPages.ContainsKey(sTabName)) - { - tpOverview = tcPlugins.TabPages[sTabName]; - lv = (ListView)tpOverview.Controls.Find(sListViewName, true)[0]; - PluginDebug.AddInfo("Found " + sTabName, 0, "Listview: " + (lv == null ? "null" : lv.Items.Count.ToString() + " /" + lv.Name.ToString())); - } - else - { - tpOverview = new TabPage("Overview"); - tpOverview.CreateControl(); - tpOverview.Name = sTabName; - UserControl uc = new UserControl(); - uc.Dock = DockStyle.Fill; - uc.Padding = new Padding(15, 10, 15, 10); - tpOverview.Controls.Add(uc); - lv = new ListView(); - lv.Name = sListViewName; - lv.Dock = DockStyle.Fill; - lv.View = View.Details; - lv.Columns.Add("Plugin"); - lv.Columns.Add("Version"); - lv.CheckBoxes = true; - tpOverview.Layout += TpOverview_Layout; - Label lInfo = new Label(); - lInfo.AutoSize = true; - lInfo.Text = "Use the checkbox to activate/deactivate debug mode"; - lInfo.Dock = DockStyle.Bottom; - uc.Controls.Add(lv); - uc.Controls.Add(lInfo); - } - lv.ItemCheck += Lv_ItemCheck; - lv.Sorting = SortOrder.Ascending; - lv.FullRowSelect = true; - ListViewItem lvi = new ListViewItem(); - lvi.Name = sPluginName; - lvi.Checked = PluginDebug.DebugMode; - lvi.Text = DefaultCaption; - Version v = new Version(0, 0); - GetLoadedPluginsName().TryGetValue(sPluginName.Replace("Ext", string.Empty) + "." + sPluginName, out v); - if (v == null) PluginDebug.AddError("Could not get loaded plugins' data", 0); - string ver = (v == null) ? "???" : v.ToString(); - if (ver.EndsWith(".0")) ver = ver.Substring(0, ver.Length - 2); - else ver += " (Dev)"; - lvi.SubItems.Add(ver); - lv.Items.Add(lvi); - tcPlugins.TabPages.Remove(tpOverview); - tcPlugins.TabPages.Add(tpOverview); - PluginDebug.AddInfo("Added " + sTabName, 0, "Listview: " + (lv == null ? "null" : lv.Items.Count.ToString() + " /" + lv.Name.ToString())); - } + private static void AddPluginToOverview(string sPluginName, TabControl tcPlugins) + { + if (tcPlugins == null) tcPlugins = AddPluginTabContainer(); + TabPage tpOverview = null; + ListView lv = null; + string sTabName = c_tabRookiestyle + "_PluginOverview"; + string sListViewName = c_tabRookiestyle + "_PluginOverviewListView"; + if (tcPlugins.TabPages.ContainsKey(sTabName)) + { + tpOverview = tcPlugins.TabPages[sTabName]; + lv = (ListView)tpOverview.Controls.Find(sListViewName, true)[0]; + PluginDebug.AddInfo("Found " + sTabName, 0, "Listview: " + (lv == null ? "null" : lv.Items.Count.ToString() + " /" + lv.Name.ToString())); + } + else + { + tpOverview = new TabPage("Overview"); + tpOverview.CreateControl(); + tpOverview.Name = sTabName; + UserControl uc = new UserControl(); + uc.Dock = DockStyle.Fill; + uc.Padding = new Padding(15, 10, 15, 10); + tpOverview.Controls.Add(uc); + lv = new ListView(); + lv.Name = sListViewName; + lv.Dock = DockStyle.Fill; + lv.View = View.Details; + lv.Columns.Add("Plugin"); + lv.Columns.Add("Version"); + lv.CheckBoxes = true; + tpOverview.Layout += TpOverview_Layout; + Label lInfo = new Label(); + lInfo.AutoSize = true; + lInfo.Text = "Use the checkbox to activate/deactivate debug mode"; + lInfo.Dock = DockStyle.Bottom; + uc.Controls.Add(lv); + uc.Controls.Add(lInfo); + } + lv.ItemCheck += Lv_ItemCheck; + lv.Sorting = SortOrder.Ascending; + lv.FullRowSelect = true; + ListViewItem lvi = new ListViewItem(); + lvi.Name = sPluginName; + lvi.Checked = PluginDebug.DebugMode; + lvi.Text = DefaultCaption; + Version v = new Version(0, 0); + GetLoadedPluginsName().TryGetValue(sPluginName.Replace("Ext", string.Empty) + "." + sPluginName, out v); + if (v == null) PluginDebug.AddError("Could not get loaded plugins' data", 0); + string ver = (v == null) ? "???" : v.ToString(); + if (ver.EndsWith(".0")) ver = ver.Substring(0, ver.Length - 2); + else ver += " (Dev)"; + lvi.SubItems.Add(ver); + lv.Items.Add(lvi); + tcPlugins.TabPages.Remove(tpOverview); + tcPlugins.TabPages.Add(tpOverview); + PluginDebug.AddInfo("Added " + sTabName, 0, "Listview: " + (lv == null ? "null" : lv.Items.Count.ToString() + " /" + lv.Name.ToString())); + } - private static void TpOverview_Layout(object sender, LayoutEventArgs e) - { - string sListViewName = c_tabRookiestyle + "_PluginOverviewListView"; - ListView lv = (sender as TabPage).Controls.Find(sListViewName, true)[0] as ListView; - lv.BeginUpdate(); - lv.Columns[1].DisplayIndex = 0; - lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); - int w = lv.Columns[1].Width; - lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); - lv.Columns[1].Width = Math.Max(w, lv.Columns[1].Width); - lv.Columns[0].Width = lv.ClientSize.Width - lv.Columns[1].Width; - if (lv.Columns[0].Width < 150) - { - lv.Columns[1].Width = 100; - lv.Columns[0].Width = lv.ClientSize.Width - lv.Columns[1].Width; - } - lv.Columns[1].DisplayIndex = 1; - lv.EndUpdate(); - } + private static void TpOverview_Layout(object sender, LayoutEventArgs e) + { + string sListViewName = c_tabRookiestyle + "_PluginOverviewListView"; + ListView lv = (sender as TabPage).Controls.Find(sListViewName, true)[0] as ListView; + lv.BeginUpdate(); + lv.Columns[1].DisplayIndex = 0; + lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); + int w = lv.Columns[1].Width; + lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); + lv.Columns[1].Width = Math.Max(w, lv.Columns[1].Width); + lv.Columns[0].Width = lv.ClientSize.Width - lv.Columns[1].Width; + if (lv.Columns[0].Width < 150) + { + lv.Columns[1].Width = 100; + lv.Columns[0].Width = lv.ClientSize.Width - lv.Columns[1].Width; + } + lv.Columns[1].DisplayIndex = 1; + lv.EndUpdate(); + } - private static void Lv_ItemCheck(object sender, ItemCheckEventArgs e) - { - ListViewItem lvi = (sender as ListView).Items[e.Index]; - if (lvi == null) return; - if (lvi.Text != DefaultCaption) return; - PluginDebug.DebugMode = e.NewValue == CheckState.Checked; - } + private static void Lv_ItemCheck(object sender, ItemCheckEventArgs e) + { + ListViewItem lvi = (sender as ListView).Items[e.Index]; + if (lvi == null) return; + if (lvi.Text != DefaultCaption) return; + PluginDebug.DebugMode = e.NewValue == CheckState.Checked; + } - private static void OnPluginTabsSelected(object sender, TabControlEventArgs e) - { - m_OptionsShown |= (e.TabPage.Name == m_TabPageName); - m_PluginContainerShown |= (m_OptionsShown || (e.TabPage.Name == c_tabRookiestyle)); - } + private static void OnPluginTabsSelected(object sender, TabControlEventArgs e) + { + m_OptionsShown |= (e.TabPage.Name == m_TabPageName); + m_PluginContainerShown |= (m_OptionsShown || (e.TabPage.Name == c_tabRookiestyle)); + } - public static UserControl GetPluginFromOptions(KeePass.Plugins.Plugin p, out bool PluginOptionsShown) - { - PluginOptionsShown = m_OptionsShown && m_PluginContainerShown; - TabPage tPlugin = Tools.GetControl(c_tabRookiestyle + p.GetType().Name, m_of) as TabPage; - if (tPlugin == null) return null; - return tPlugin.Controls[0] as UserControl; - } + public static UserControl GetPluginFromOptions(KeePass.Plugins.Plugin p, out bool PluginOptionsShown) + { + PluginOptionsShown = m_OptionsShown && m_PluginContainerShown; + TabPage tPlugin = Tools.GetControl(c_tabRookiestyle + p.GetType().Name, m_of) as TabPage; + if (tPlugin == null) return null; + return tPlugin.Controls[0] as UserControl; + } - public static void ShowOptions() - { - m_ActivatePluginTab = true; - if (OptionsEnabled) - KeePass.Program.MainForm.ToolsMenu.DropDownItems["m_menuToolsOptions"].PerformClick(); - else - { - m_of = new OptionsForm(); - m_of.InitEx(KeePass.Program.MainForm.ClientIcons); - m_of.ShowDialog(); - } - } + public static void ShowOptions() + { + m_ActivatePluginTab = true; + if (OptionsEnabled) + KeePass.Program.MainForm.ToolsMenu.DropDownItems["m_menuToolsOptions"].PerformClick(); + else + { + m_of = new OptionsForm(); + m_of.InitEx(KeePass.Program.MainForm.ClientIcons); + m_of.ShowDialog(); + } + } - private static void AddPluginLink(UserControl uc) - { - LinkLabel llUrl = new LinkLabel(); - llUrl.Links.Add(0, PluginURL.Length, PluginURL); - llUrl.Text = PluginURL; - uc.Controls.Add(llUrl); - llUrl.Dock = DockStyle.Bottom; - llUrl.AutoSize = true; - llUrl.LinkClicked += new LinkLabelLinkClickedEventHandler(PluginURLClicked); - } + private static void AddPluginLink(UserControl uc) + { + LinkLabel llUrl = new LinkLabel(); + llUrl.Links.Add(0, PluginURL.Length, PluginURL); + llUrl.Text = PluginURL; + uc.Controls.Add(llUrl); + llUrl.Dock = DockStyle.Bottom; + llUrl.AutoSize = true; + llUrl.LinkClicked += new LinkLabelLinkClickedEventHandler(PluginURLClicked); + } - private static void PluginURLClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - string target = e.Link.LinkData as string; - OpenUrl(target); - } + private static void PluginURLClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + string target = e.Link.LinkData as string; + OpenUrl(target); + } - private static void OnOptionsFormShown(object sender, EventArgs e) - { - m_of.Shown -= OnOptionsFormShown; - TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; - if (!tcMain.TabPages.ContainsKey(c_tabRookiestyle)) return; - TabPage tPlugins = tcMain.TabPages[c_tabRookiestyle]; - TabControl tcPlugins = Tools.GetControl(c_tabControlRookiestyle, tPlugins) as TabControl; - if (m_ActivatePluginTab) - { - tcMain.SelectedIndex = tcMain.TabPages.IndexOfKey(c_tabRookiestyle); - KeePass.Program.Config.Defaults.OptionsTabIndex = (uint)tcMain.SelectedIndex; - tcPlugins.SelectedIndex = tcPlugins.TabPages.IndexOfKey(c_tabRookiestyle + m_sPluginClassname); - } - m_ActivatePluginTab = false; - tcMain.Selected += OnPluginTabsSelected; - tcPlugins.Selected += OnPluginTabsSelected; - tcMain.ImageList.Images.Add(c_tabRookiestyle + "Icon", (Image)KeePass.Program.Resources.GetObject("B16x16_BlockDevice")); - tPlugins.ImageKey = c_tabRookiestyle + "Icon"; - m_PluginContainerShown |= tcMain.SelectedTab == tPlugins; - m_OptionsShown |= (tcPlugins.SelectedTab.Name == m_TabPageName); - CheckKeeTheme(tPlugins); - } + private static void OnOptionsFormShown(object sender, EventArgs e) + { + m_of.Shown -= OnOptionsFormShown; + TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; + if (!tcMain.TabPages.ContainsKey(c_tabRookiestyle)) return; + TabPage tPlugins = tcMain.TabPages[c_tabRookiestyle]; + TabControl tcPlugins = Tools.GetControl(c_tabControlRookiestyle, tPlugins) as TabControl; + if (m_ActivatePluginTab) + { + tcMain.SelectedIndex = tcMain.TabPages.IndexOfKey(c_tabRookiestyle); + KeePass.Program.Config.Defaults.OptionsTabIndex = (uint)tcMain.SelectedIndex; + tcPlugins.SelectedIndex = tcPlugins.TabPages.IndexOfKey(c_tabRookiestyle + m_sPluginClassname); + } + m_ActivatePluginTab = false; + tcMain.Selected += OnPluginTabsSelected; + tcPlugins.Selected += OnPluginTabsSelected; + tcMain.ImageList.Images.Add(c_tabRookiestyle + "Icon", (Image)KeePass.Program.Resources.GetObject("B16x16_BlockDevice")); + tPlugins.ImageKey = c_tabRookiestyle + "Icon"; + m_PluginContainerShown |= tcMain.SelectedTab == tPlugins; + m_OptionsShown |= (tcPlugins.SelectedTab.Name == m_TabPageName); + CheckKeeTheme(tPlugins); + } - private static void CheckKeeTheme(Control c) - { - Control check = GetControl("Rookiestyle_KeeTheme_Check", m_of); - if (check != null) return; - PluginDebug.AddInfo("Checking for KeeTheme"); - check = new Control(); - check.Name = "Rookiestyle_KeeTheme_Check"; - check.Visible = false; - m_of.Controls.Add(check); - KeePass.Plugins.Plugin p = (KeePass.Plugins.Plugin)GetPluginInstance("KeeTheme"); - if (p == null) return; - var t = GetField("_theme", p); - if (t == null) return; - bool bKeeThemeEnabled = (bool)t.GetType().GetProperty("Enabled").GetValue(t, null); - if (!bKeeThemeEnabled) return; - var v = GetField("_controlVisitor", p); - if (v == null) return; - MethodInfo miVisit = v.GetType().GetMethod("Visit", new Type[] { typeof(Control) }); - if (miVisit == null) return; - miVisit.Invoke(v, new object[] { c }); - } + private static void CheckKeeTheme(Control c) + { + Control check = GetControl("Rookiestyle_KeeTheme_Check", m_of); + if (check != null) return; + PluginDebug.AddInfo("Checking for KeeTheme"); + check = new Control(); + check.Name = "Rookiestyle_KeeTheme_Check"; + check.Visible = false; + m_of.Controls.Add(check); + KeePass.Plugins.Plugin p = (KeePass.Plugins.Plugin)GetPluginInstance("KeeTheme"); + if (p == null) return; + var t = GetField("_theme", p); + if (t == null) return; + bool bKeeThemeEnabled = (bool)t.GetType().GetProperty("Enabled").GetValue(t, null); + if (!bKeeThemeEnabled) return; + var v = GetField("_controlVisitor", p); + if (v == null) return; + MethodInfo miVisit = v.GetType().GetMethod("Visit", new Type[] { typeof(Control) }); + if (miVisit == null) return; + miVisit.Invoke(v, new object[] { c }); + } - private static void OnWindowAdded(object sender, KeePass.UI.GwmWindowEventArgs e) - { - if (OptionsFormShown == null) return; - if (e.Form is OptionsForm) - { - m_of = e.Form as OptionsForm; - m_of.Shown += OnOptionsFormShown; - OptionsFormsEventArgs o = new OptionsFormsEventArgs(m_of); - OptionsFormShown(sender, o); - } - } + private static void OnWindowAdded(object sender, KeePass.UI.GwmWindowEventArgs e) + { + if (OptionsFormShown == null) return; + if (e.Form is OptionsForm) + { + m_of = e.Form as OptionsForm; + m_of.Shown += OnOptionsFormShown; + OptionsFormsEventArgs o = new OptionsFormsEventArgs(m_of); + OptionsFormShown(sender, o); + } + } - private static void OnWindowRemoved(object sender, KeePass.UI.GwmWindowEventArgs e) - { - if (OptionsFormClosed == null) return; - if (e.Form is OptionsForm) - { - OptionsFormsEventArgs o = new OptionsFormsEventArgs(m_of); - OptionsFormClosed(sender, o); - } - } + private static void OnWindowRemoved(object sender, KeePass.UI.GwmWindowEventArgs e) + { + if (OptionsFormClosed == null) return; + if (e.Form is OptionsForm) + { + OptionsFormsEventArgs o = new OptionsFormsEventArgs(m_of); + OptionsFormClosed(sender, o); + } + } - private static TabControl AddPluginTabContainer() - { - if (m_of == null) - { - PluginDebug.AddError("Could not identify KeePass options form", 0); - return null; - } - TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; - if (tcMain == null) - { - PluginDebug.AddError("Could not locate m_tabMain", 0); - return null; - } - TabPage tPlugins = null; - TabControl tcPlugins = null; - if (tcMain.TabPages.ContainsKey(c_tabRookiestyle)) - { - tPlugins = tcMain.TabPages[c_tabRookiestyle]; - tcPlugins = (TabControl)tPlugins.Controls[c_tabControlRookiestyle]; - if (tcPlugins == null) - { - PluginDebug.AddError("Could not locate " + c_tabControlRookiestyle, 0); - return null; - } - tcPlugins.Multiline = false; //Older version of PluginTools might still be used by other plugins - PluginDebug.AddInfo("Found " + c_tabControlRookiestyle, 0); - return tcPlugins; - } - tPlugins = new TabPage(KeePass.Resources.KPRes.Plugin + " " + m_of.Text); - tPlugins.Name = c_tabRookiestyle; - tPlugins.CreateControl(); - if (!OptionsEnabled) - { - while (tcMain.TabCount > 0) - tcMain.TabPages.RemoveAt(0); - PluginDebug.AddInfo("Removed tab pages from KeePass options form", 0); - } - tcMain.TabPages.Add(tPlugins); - tcPlugins = new TabControl(); - tcPlugins.Name = c_tabControlRookiestyle; - tcPlugins.Dock = DockStyle.Fill; - tcPlugins.Multiline = false; - tcPlugins.CreateControl(); - if (tcPlugins.ImageList == null) - tcPlugins.ImageList = new ImageList(); - tPlugins.Controls.Add(tcPlugins); - PluginDebug.AddInfo("Added " + c_tabControlRookiestyle, 0); - return tcPlugins; - } + private static TabControl AddPluginTabContainer() + { + if (m_of == null) + { + PluginDebug.AddError("Could not identify KeePass options form", 0); + return null; + } + TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; + if (tcMain == null) + { + PluginDebug.AddError("Could not locate m_tabMain", 0); + return null; + } + TabPage tPlugins = null; + TabControl tcPlugins = null; + if (tcMain.TabPages.ContainsKey(c_tabRookiestyle)) + { + tPlugins = tcMain.TabPages[c_tabRookiestyle]; + tcPlugins = (TabControl)tPlugins.Controls[c_tabControlRookiestyle]; + if (tcPlugins == null) + { + PluginDebug.AddError("Could not locate " + c_tabControlRookiestyle, 0); + return null; + } + tcPlugins.Multiline = false; //Older version of PluginTools might still be used by other plugins + PluginDebug.AddInfo("Found " + c_tabControlRookiestyle, 0); + return tcPlugins; + } + tPlugins = new TabPage(KeePass.Resources.KPRes.Plugin + " " + m_of.Text); + tPlugins.Name = c_tabRookiestyle; + tPlugins.CreateControl(); + if (!OptionsEnabled) + { + while (tcMain.TabCount > 0) + tcMain.TabPages.RemoveAt(0); + PluginDebug.AddInfo("Removed tab pages from KeePass options form", 0); + } + tcMain.TabPages.Add(tPlugins); + tcPlugins = new TabControl(); + tcPlugins.Name = c_tabControlRookiestyle; + tcPlugins.Dock = DockStyle.Fill; + tcPlugins.Multiline = false; + tcPlugins.CreateControl(); + if (tcPlugins.ImageList == null) + tcPlugins.ImageList = new ImageList(); + tPlugins.Controls.Add(tcPlugins); + PluginDebug.AddInfo("Added " + c_tabControlRookiestyle, 0); + return tcPlugins; + } - public class OptionsFormsEventArgs : EventArgs - { - public Form form; + public class OptionsFormsEventArgs : EventArgs + { + public Form form; - public OptionsFormsEventArgs(Form form) - { - this.form = form; - } - } - } -} \ No newline at end of file + public OptionsFormsEventArgs(Form form) + { + this.form = form; + } + } + } +}