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.App.Configuration; 30 using KeePass.Resources; 31 using KeePass.UI; 32 using KeePass.Util; 33 34 using KeePassLib; 35 using KeePassLib.Collections; 36 using KeePassLib.Interfaces; 37 using KeePassLib.Utility; 38 39 namespace KeePass.Forms 40 { 41 public partial class SearchForm : Form 42 { 43 private readonly string ProfileCustom = "(" + KPRes.Custom + ")"; 44 45 private PwDatabase m_pdContext = null; 46 private PwGroup m_pgRoot = null; 47 48 private uint m_uBlockProfileAuto = 0; 49 50 private PwGroup m_pgResults = null; 51 public PwGroup SearchResultsGroup 52 { 53 get { return m_pgResults; } 54 } 55 56 private SearchParameters m_spResult = null; 57 internal SearchParameters SearchResultParameters 58 { 59 get { return m_spResult; } 60 } 61 62 private string m_strInitProfile = string.Empty; 63 [Browsable(false)] 64 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 65 [DefaultValue("")] 66 internal string InitProfile 67 { 68 get { return m_strInitProfile; } 69 set { m_strInitProfile = value; } 70 } 71 SearchForm()72 public SearchForm() 73 { 74 InitializeComponent(); 75 GlobalWindowManager.InitializeForm(this); 76 } 77 78 /// <summary> 79 /// Initialize the form. Must be called before the dialog is displayed. 80 /// </summary> InitEx(PwDatabase pdContext, PwGroup pgRoot)81 public void InitEx(PwDatabase pdContext, PwGroup pgRoot) 82 { 83 m_pdContext = pdContext; 84 m_pgRoot = pgRoot; 85 } 86 OnFormLoad(object sender, EventArgs e)87 private void OnFormLoad(object sender, EventArgs e) 88 { 89 if(m_pgRoot == null) { Debug.Assert(false); throw new InvalidOperationException(); } 90 91 GlobalWindowManager.AddWindow(this); 92 93 string strTitle = KPRes.SearchTitle; 94 string strDesc = KPRes.SearchDesc2; 95 if((m_pgRoot.ParentGroup != null) && !string.IsNullOrEmpty(m_pgRoot.Name)) 96 { 97 strTitle += " (" + KPRes.SelectedGroup + ")"; 98 strDesc = KPRes.Group + ": '" + m_pgRoot.Name + "'."; 99 } 100 101 BannerFactory.CreateBannerEx(this, m_bannerImage, 102 Properties.Resources.B48x48_XMag, strTitle, strDesc); 103 this.Icon = AppIcons.Default; 104 this.Text = KPRes.SearchTitle; 105 106 UIUtil.SetButtonImage(m_btnProfileAdd, 107 Properties.Resources.B16x16_FileSaveAs, false); 108 UIUtil.SetButtonImage(m_btnProfileDelete, 109 Properties.Resources.B16x16_EditDelete, true); 110 111 UIUtil.SetText(m_cbDerefData, m_cbDerefData.Text + " (" + KPRes.Slow + ")"); 112 113 UIUtil.ConfigureToolTip(m_ttMain); 114 UIUtil.SetToolTip(m_ttMain, m_btnProfileAdd, KPRes.ProfileSaveDesc, false); 115 UIUtil.SetToolTip(m_ttMain, m_btnProfileDelete, KPRes.ProfileDeleteDesc, false); 116 117 UIUtil.AccSetName(m_btnProfileAdd, KPRes.ProfileSave); 118 UIUtil.AccSetName(m_btnProfileDelete, KPRes.ProfileDelete); 119 120 SearchParameters sp = (!string.IsNullOrEmpty(m_strInitProfile) ? 121 Program.Config.Search.FindProfile(m_strInitProfile) : null); 122 Debug.Assert(string.IsNullOrEmpty(m_strInitProfile) || (sp != null)); 123 UpdateProfilesList((sp != null) ? sp.Name : ProfileCustom); 124 SetSearchParameters(sp ?? Program.Config.Search.LastUsedProfile); 125 126 m_tbSearch.TextChanged += this.OnProfilePropertyChanged; 127 m_rbModeSimple.CheckedChanged += this.OnProfilePropertyChanged; 128 m_rbModeRegular.CheckedChanged += this.OnProfilePropertyChanged; 129 m_rbModeXPath.CheckedChanged += this.OnProfilePropertyChanged; 130 131 CheckBox[] v = new CheckBox[] { 132 m_cbTitle, m_cbUserName, m_cbPassword, m_cbUrl, m_cbNotes, 133 m_cbStringsOther, m_cbStringName, m_cbTags, m_cbUuid, 134 m_cbGroupPath, m_cbGroupName, m_cbHistory, 135 m_cbCaseSensitive, m_cbExcludeExpired, m_cbIgnoreGroupSettings, 136 m_cbDerefData 137 }; 138 foreach(CheckBox cb in v) cb.CheckedChanged += this.OnProfilePropertyChanged; 139 140 UpdateUIState(); 141 m_tbSearch.SelectAll(); 142 } 143 OnFormClosed(object sender, FormClosedEventArgs e)144 private void OnFormClosed(object sender, FormClosedEventArgs e) 145 { 146 Program.Config.Search.LastUsedProfile = GetSearchParameters(); 147 148 GlobalWindowManager.RemoveWindow(this); 149 } 150 OnBtnOK(object sender, EventArgs e)151 private void OnBtnOK(object sender, EventArgs e) 152 { 153 SearchParameters sp = GetSearchParameters(); 154 155 Form fOptDialog; 156 IStatusLogger sl = StatusUtil.CreateStatusDialog(this, out fOptDialog, 157 null, KPRes.SearchingOp + "...", true, false); 158 // if(fOptDialog != null) Program.MainForm.RedirectActivationPush(fOptDialog); 159 this.Enabled = false; 160 161 PwGroup pgResults = null; 162 Exception exFind = null; 163 try { pgResults = SearchUtil.Find(sp, m_pgRoot, sl); } 164 catch(Exception ex) { exFind = ex; } 165 166 this.Enabled = true; 167 // if(fOptDialog != null) Program.MainForm.RedirectActivationPop(); 168 sl.EndLogging(); 169 170 if(exFind != null) 171 { 172 MessageService.ShowWarning(sp.SearchString, exFind); 173 this.DialogResult = DialogResult.None; 174 } 175 else if(pgResults != null) 176 { 177 m_pgResults = pgResults; 178 m_spResult = sp; 179 } 180 else 181 { 182 Debug.Assert(false); 183 this.DialogResult = DialogResult.None; 184 } 185 } 186 UpdateProfilesList(string strSelect)187 private void UpdateProfilesList(string strSelect) 188 { 189 ++m_uBlockProfileAuto; 190 191 List<object> l = new List<object>(); 192 int iSel = 0; 193 194 l.Add(ProfileCustom); 195 196 Program.Config.Search.SortProfiles(); 197 foreach(SearchParameters sp in Program.Config.Search.UserProfiles) 198 { 199 string strName = sp.Name; 200 if(strName == strSelect) iSel = l.Count; 201 l.Add(strName); 202 } 203 204 m_cmbProfiles.Items.Clear(); 205 m_cmbProfiles.Items.AddRange(l.ToArray()); 206 207 Debug.Assert((strSelect == ProfileCustom) || (iSel != 0)); 208 m_cmbProfiles.SelectedIndex = iSel; 209 210 --m_uBlockProfileAuto; 211 } 212 SetSearchParameters(SearchParameters sp)213 private void SetSearchParameters(SearchParameters sp) 214 { 215 if(sp == null) { Debug.Assert(false); sp = new SearchParameters(); } 216 217 ++m_uBlockProfileAuto; 218 219 Debug.Assert((m_cmbProfiles.Text == ProfileCustom) || 220 (m_cmbProfiles.Text == sp.Name)); 221 222 m_tbSearch.Text = sp.SearchString; 223 224 if(sp.SearchMode == PwSearchMode.Regular) 225 m_rbModeRegular.Checked = true; 226 else if(sp.SearchMode == PwSearchMode.XPath) 227 m_rbModeXPath.Checked = true; 228 else 229 { 230 Debug.Assert(sp.SearchMode == PwSearchMode.Simple); 231 m_rbModeSimple.Checked = true; 232 } 233 234 m_cbTitle.Checked = sp.SearchInTitles; 235 m_cbUserName.Checked = sp.SearchInUserNames; 236 m_cbPassword.Checked = sp.SearchInPasswords; 237 m_cbUrl.Checked = sp.SearchInUrls; 238 m_cbNotes.Checked = sp.SearchInNotes; 239 m_cbStringsOther.Checked = sp.SearchInOther; 240 m_cbStringName.Checked = sp.SearchInStringNames; 241 m_cbTags.Checked = sp.SearchInTags; 242 m_cbUuid.Checked = sp.SearchInUuids; 243 m_cbGroupPath.Checked = sp.SearchInGroupPaths; 244 m_cbGroupName.Checked = sp.SearchInGroupNames; 245 m_cbHistory.Checked = sp.SearchInHistory; 246 247 StringComparison sc = sp.ComparisonMode; 248 m_cbCaseSensitive.Checked = ((sc != StringComparison.CurrentCultureIgnoreCase) && 249 (sc != StringComparison.InvariantCultureIgnoreCase) && 250 (sc != StringComparison.OrdinalIgnoreCase)); 251 252 m_cbExcludeExpired.Checked = sp.ExcludeExpired; 253 m_cbIgnoreGroupSettings.Checked = !sp.RespectEntrySearchingDisabled; 254 255 string strTrf = SearchUtil.GetTransformation(sp); 256 m_cbDerefData.Checked = (strTrf == SearchUtil.StrTrfDeref); 257 258 --m_uBlockProfileAuto; 259 } 260 GetSearchParameters()261 private SearchParameters GetSearchParameters() 262 { 263 SearchParameters sp = new SearchParameters(); 264 265 sp.Name = m_cmbProfiles.Text; 266 sp.SearchString = m_tbSearch.Text; 267 268 if(m_rbModeRegular.Checked) 269 sp.SearchMode = PwSearchMode.Regular; 270 else if(m_rbModeXPath.Checked) 271 sp.SearchMode = PwSearchMode.XPath; 272 else 273 { 274 Debug.Assert(m_rbModeSimple.Checked); 275 sp.SearchMode = PwSearchMode.Simple; 276 } 277 278 sp.SearchInTitles = m_cbTitle.Checked; 279 sp.SearchInUserNames = m_cbUserName.Checked; 280 sp.SearchInPasswords = m_cbPassword.Checked; 281 sp.SearchInUrls = m_cbUrl.Checked; 282 sp.SearchInNotes = m_cbNotes.Checked; 283 sp.SearchInOther = m_cbStringsOther.Checked; 284 sp.SearchInStringNames = m_cbStringName.Checked; 285 sp.SearchInTags = m_cbTags.Checked; 286 sp.SearchInUuids = m_cbUuid.Checked; 287 sp.SearchInGroupPaths = m_cbGroupPath.Checked; 288 sp.SearchInGroupNames = m_cbGroupName.Checked; 289 sp.SearchInHistory = m_cbHistory.Checked; 290 291 sp.ComparisonMode = (m_cbCaseSensitive.Checked ? 292 StringComparison.InvariantCulture : 293 StringComparison.InvariantCultureIgnoreCase); 294 295 sp.ExcludeExpired = m_cbExcludeExpired.Checked; 296 sp.RespectEntrySearchingDisabled = !m_cbIgnoreGroupSettings.Checked; 297 298 SearchUtil.SetTransformation(sp, (m_cbDerefData.Checked ? 299 SearchUtil.StrTrfDeref : string.Empty)); 300 301 return sp; 302 } 303 UpdateUIState()304 private void UpdateUIState() 305 { 306 ++m_uBlockProfileAuto; 307 308 bool bCustom = (m_cmbProfiles.Text == ProfileCustom); 309 bool bXPath = m_rbModeXPath.Checked; 310 311 m_btnProfileDelete.Enabled = !bCustom; 312 313 m_cbStringName.Enabled = !bXPath; 314 if(bXPath) m_cbStringName.Checked = true; 315 316 m_cbUuid.Enabled = !bXPath; 317 if(bXPath) m_cbUuid.Checked = true; 318 319 m_cbGroupPath.Enabled = !bXPath; 320 if(bXPath) m_cbGroupPath.Checked = false; 321 322 bool bGroupPath = m_cbGroupPath.Checked; 323 m_cbGroupName.Enabled = !bGroupPath; 324 if(bGroupPath) m_cbGroupName.Checked = true; 325 326 m_cbCaseSensitive.Enabled = !bXPath; 327 if(bXPath) m_cbCaseSensitive.Checked = true; 328 329 m_cbDerefData.Enabled = !bXPath; 330 if(bXPath) m_cbDerefData.Checked = false; 331 332 --m_uBlockProfileAuto; 333 } 334 OnProfilesSelectedIndexChanged(object sender, EventArgs e)335 private void OnProfilesSelectedIndexChanged(object sender, EventArgs e) 336 { 337 if(m_uBlockProfileAuto != 0) return; 338 339 string strName = m_cmbProfiles.Text; 340 if(strName != ProfileCustom) 341 SetSearchParameters(Program.Config.Search.FindProfile(strName)); 342 343 UpdateUIState(); 344 } 345 OnProfilePropertyChanged(object sender, EventArgs e)346 private void OnProfilePropertyChanged(object sender, EventArgs e) 347 { 348 if(m_uBlockProfileAuto != 0) return; 349 350 Debug.Assert((m_cmbProfiles.Items.Count != 0) && !m_cmbProfiles.Sorted && 351 ((m_cmbProfiles.Items[0] as string) == ProfileCustom)); 352 if(m_cmbProfiles.Items.Count != 0) 353 m_cmbProfiles.SelectedIndex = 0; 354 355 UpdateUIState(); 356 } 357 OnBtnProfileAdd(object sender, EventArgs e)358 private void OnBtnProfileAdd(object sender, EventArgs e) 359 { 360 List<string> lNames = new List<string>(); 361 foreach(SearchParameters sp in Program.Config.Search.UserProfiles) 362 lNames.Add(sp.Name); 363 364 SingleLineEditForm dlg = new SingleLineEditForm(); 365 dlg.InitEx(KPRes.ProfileSave, KPRes.ProfileSaveDesc, 366 KPRes.ProfileSavePrompt, Properties.Resources.B48x48_KMag, 367 string.Empty, lNames.ToArray()); 368 369 if(dlg.ShowDialog() == DialogResult.OK) 370 { 371 string strName = dlg.ResultString; 372 373 if(string.IsNullOrEmpty(strName) || (strName == ProfileCustom)) 374 MessageService.ShowWarning(KPRes.FieldNameInvalid); 375 else 376 { 377 SearchParameters sp = GetSearchParameters(); 378 sp.Name = strName; 379 380 AceSearch aceSearch = Program.Config.Search; 381 int i = aceSearch.FindProfileIndex(strName); 382 if(i >= 0) aceSearch.UserProfiles[i] = sp; 383 else aceSearch.UserProfiles.Add(sp); 384 385 UpdateProfilesList(strName); 386 UpdateUIState(); 387 } 388 } 389 UIUtil.DestroyForm(dlg); 390 } 391 OnBtnProfileDelete(object sender, EventArgs e)392 private void OnBtnProfileDelete(object sender, EventArgs e) 393 { 394 string strName = m_cmbProfiles.Text; 395 if(strName == ProfileCustom) { Debug.Assert(false); return; } 396 397 AceSearch aceSearch = Program.Config.Search; 398 int i = aceSearch.FindProfileIndex(strName); 399 if(i >= 0) 400 { 401 aceSearch.UserProfiles.RemoveAt(i); 402 403 UpdateProfilesList(ProfileCustom); 404 UpdateUIState(); 405 } 406 else { Debug.Assert(false); } 407 } 408 OnBtnHelp(object sender, EventArgs e)409 private void OnBtnHelp(object sender, EventArgs e) 410 { 411 AppHelp.ShowHelp(AppDefs.HelpTopics.Search, null); 412 } 413 } 414 } 415