1 /* 2 KeePass Password Safe - The Open-Source Password Manager 3 Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 using System; 21 using System.Collections.Generic; 22 using System.ComponentModel; 23 using System.Diagnostics; 24 using System.Drawing; 25 using System.Text; 26 using System.Windows.Forms; 27 28 using KeePass.App; 29 using KeePass.Native; 30 using KeePass.Resources; 31 using KeePass.UI; 32 33 using KeePassLib; 34 using KeePassLib.Security; 35 using KeePassLib.Utility; 36 37 namespace KeePass.Forms 38 { 39 public partial class FieldPickerForm : Form 40 { 41 private string m_strTitle = null; 42 private string m_strText = null; 43 private List<FpField> m_lFields = null; 44 45 private FpField m_fpResult = null; 46 public FpField SelectedField { get { return m_fpResult; } } 47 ShowAndRestore(string strTitle, string strText, List<FpField> lFields)48 internal static FpField ShowAndRestore(string strTitle, string strText, 49 List<FpField> lFields) 50 { 51 IntPtr h = IntPtr.Zero; 52 try { h = NativeMethods.GetForegroundWindowHandle(); } 53 catch(Exception) { Debug.Assert(false); } 54 55 FieldPickerForm dlg = new FieldPickerForm(); 56 dlg.InitEx(strTitle, strText, lFields); 57 58 FpField fpResult = null; 59 if(UIUtil.ShowDialogAndDestroy(dlg) == DialogResult.OK) 60 fpResult = dlg.SelectedField; 61 62 try 63 { 64 if(h != IntPtr.Zero) 65 NativeMethods.EnsureForegroundWindow(h); 66 } 67 catch(Exception) { Debug.Assert(false); } 68 69 return fpResult; 70 } 71 FieldPickerForm()72 public FieldPickerForm() 73 { 74 InitializeComponent(); 75 GlobalWindowManager.InitializeForm(this); 76 } 77 InitEx(string strTitle, string strText, List<FpField> lFields)78 public void InitEx(string strTitle, string strText, List<FpField> lFields) 79 { 80 m_strTitle = strTitle; 81 m_strText = strText; 82 m_lFields = lFields; 83 } 84 OnFormLoad(object sender, EventArgs e)85 private void OnFormLoad(object sender, EventArgs e) 86 { 87 // Can be invoked during auto-type; don't use CenterParent 88 Debug.Assert(this.StartPosition == FormStartPosition.CenterScreen); 89 90 GlobalWindowManager.AddWindow(this); 91 92 string strTitle = (m_strTitle ?? string.Empty); 93 string strTitleEx = strTitle; 94 if(strTitle.Length > 0) strTitleEx += " - "; 95 strTitleEx += PwDefs.ShortProductName; 96 97 this.Icon = AppIcons.Default; 98 this.Text = strTitleEx; 99 100 BannerFactory.CreateBannerEx(this, m_bannerImage, 101 Properties.Resources.B48x48_Binary, strTitle, 102 (m_strText ?? string.Empty)); 103 104 UIUtil.SetExplorerTheme(m_lvFields, true); 105 106 int w = (m_lvFields.ClientSize.Width - UIUtil.GetVScrollBarWidth()) / 2; 107 m_lvFields.Columns.Add(KPRes.Name, w); 108 m_lvFields.Columns.Add(KPRes.Value, w); 109 110 if(m_lFields != null) 111 { 112 ListViewGroup lvg = null; 113 string strGroup = string.Empty; 114 115 foreach(FpField fpf in m_lFields) 116 { 117 if(fpf == null) { Debug.Assert(false); continue; } 118 119 ListViewItem lvi = new ListViewItem(fpf.Name); 120 lvi.SubItems.Add(fpf.Value.IsProtected ? PwDefs.HiddenPassword : 121 StrUtil.MultiToSingleLine(fpf.Value.ReadString())); 122 lvi.Tag = fpf; 123 124 m_lvFields.Items.Add(lvi); 125 126 if(fpf.Group.Length > 0) 127 { 128 if(fpf.Group != strGroup) 129 { 130 strGroup = fpf.Group; 131 lvg = new ListViewGroup(strGroup, HorizontalAlignment.Left); 132 133 m_lvFields.Groups.Add(lvg); 134 } 135 136 lvg.Items.Add(lvi); 137 } 138 } 139 } 140 141 this.BringToFront(); 142 this.Activate(); 143 if(m_lvFields.Items.Count > 0) 144 UIUtil.SetFocusedItem(m_lvFields, m_lvFields.Items[0], true); 145 UIUtil.SetFocus(m_lvFields, this, true); 146 } 147 OnFormClosed(object sender, FormClosedEventArgs e)148 private void OnFormClosed(object sender, FormClosedEventArgs e) 149 { 150 GlobalWindowManager.RemoveWindow(this); 151 } 152 ProcessItemSelection()153 private void ProcessItemSelection() 154 { 155 if(this.DialogResult == DialogResult.OK) return; // Already closing 156 157 ListView.SelectedListViewItemCollection lvsic = 158 m_lvFields.SelectedItems; 159 if((lvsic == null) || (lvsic.Count != 1)) { Debug.Assert(false); return; } 160 161 ListViewItem lvi = lvsic[0]; 162 if(lvi == null) { Debug.Assert(false); return; } 163 164 FpField fpf = (lvi.Tag as FpField); 165 if(fpf == null) { Debug.Assert(false); return; } 166 167 m_fpResult = fpf; 168 this.DialogResult = DialogResult.OK; 169 } 170 OnFieldItemActivate(object sender, EventArgs e)171 private void OnFieldItemActivate(object sender, EventArgs e) 172 { 173 ProcessItemSelection(); 174 } 175 176 // The item activation handler has a slight delay when clicking an 177 // item, thus as a performance optimization we additionally handle 178 // item clicks OnFieldClick(object sender, EventArgs e)179 private void OnFieldClick(object sender, EventArgs e) 180 { 181 ProcessItemSelection(); 182 } 183 } 184 185 public sealed class FpField 186 { 187 private readonly string m_strName; 188 public string Name { get { return m_strName; } } 189 190 private readonly ProtectedString m_psValue; 191 public ProtectedString Value { get { return m_psValue; } } 192 193 private readonly string m_strGroup; 194 public string Group { get { return m_strGroup; } } 195 FpField(string strName, ProtectedString psValue, string strGroup)196 public FpField(string strName, ProtectedString psValue, string strGroup) 197 { 198 m_strName = (strName ?? string.Empty); 199 m_psValue = (psValue ?? ProtectedString.Empty); 200 m_strGroup = (strGroup ?? string.Empty); 201 } 202 } 203 } 204