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.Resources;
30 using KeePass.UI;
31 
32 using KeePassLib;
33 using KeePassLib.Collections;
34 using KeePassLib.Utility;
35 
36 namespace KeePass.Forms
37 {
38 	public partial class FieldRefForm : Form
39 	{
40 		private PwGroup m_pgEntrySource = null;
41 		private ImageList m_ilIcons = null;
42 		private string m_strDefaultRef = string.Empty;
43 
44 		private List<KeyValuePair<string, string>> m_vColumns =
45 			new List<KeyValuePair<string, string>>();
46 
47 		private string m_strResultRef = string.Empty;
48 		public string ResultReference
49 		{
50 			get { return m_strResultRef; }
51 		}
52 
InitEx(PwGroup pgEntrySource, ImageList ilClientIcons, string strDefaultRef)53 		public void InitEx(PwGroup pgEntrySource, ImageList ilClientIcons,
54 			string strDefaultRef)
55 		{
56 			m_pgEntrySource = pgEntrySource;
57 			m_ilIcons = ilClientIcons;
58 			m_strDefaultRef = (strDefaultRef ?? string.Empty);
59 		}
60 
FieldRefForm()61 		public FieldRefForm()
62 		{
63 			InitializeComponent();
64 			GlobalWindowManager.InitializeForm(this);
65 		}
66 
OnFormLoad(object sender, EventArgs e)67 		private void OnFormLoad(object sender, EventArgs e)
68 		{
69 			if(m_pgEntrySource == null) { Debug.Assert(false); return; }
70 			if(m_ilIcons == null) { Debug.Assert(false); return; }
71 
72 			GlobalWindowManager.AddWindow(this);
73 
74 			this.Icon = AppIcons.Default;
75 
76 			UIUtil.SetExplorerTheme(m_lvEntries, true);
77 
78 			m_vColumns.Add(new KeyValuePair<string, string>(PwDefs.TitleField, KPRes.Title));
79 			m_vColumns.Add(new KeyValuePair<string, string>(PwDefs.UserNameField, KPRes.UserName));
80 			m_vColumns.Add(new KeyValuePair<string, string>(PwDefs.UrlField, KPRes.Url));
81 			m_vColumns.Add(new KeyValuePair<string, string>(PwDefs.NotesField, KPRes.Notes));
82 
83 			PwObjectList<PwEntry> vEntries = m_pgEntrySource.GetEntries(true);
84 			UIUtil.CreateEntryList(m_lvEntries, vEntries, m_vColumns, m_ilIcons);
85 
86 			m_radioIdUuid.Checked = true;
87 
88 			if(m_strDefaultRef == PwDefs.TitleField)
89 				m_radioRefTitle.Checked = true;
90 			else if(m_strDefaultRef == PwDefs.UserNameField)
91 				m_radioRefUserName.Checked = true;
92 			// else if(m_strDefaultRef == PwDefs.PasswordField)
93 			//	m_radioRefPassword.Checked = true;
94 			else if(m_strDefaultRef == PwDefs.UrlField)
95 				m_radioRefUrl.Checked = true;
96 			else if(m_strDefaultRef == PwDefs.NotesField)
97 				m_radioRefNotes.Checked = true;
98 			else m_radioRefPassword.Checked = true;
99 		}
100 
CleanUpEx()101 		private void CleanUpEx()
102 		{
103 			m_lvEntries.SmallImageList = null; // Detach event handlers
104 		}
105 
OnFormClosed(object sender, FormClosedEventArgs e)106 		private void OnFormClosed(object sender, FormClosedEventArgs e)
107 		{
108 			CleanUpEx();
109 			GlobalWindowManager.RemoveWindow(this);
110 		}
111 
GetSelectedEntry()112 		private PwEntry GetSelectedEntry()
113 		{
114 			ListView.SelectedListViewItemCollection lvsic = m_lvEntries.SelectedItems;
115 			if((lvsic == null) || (lvsic.Count != 1)) return null;
116 
117 			return (lvsic[0].Tag as PwEntry);
118 		}
119 
CreateResultRef()120 		private bool CreateResultRef()
121 		{
122 			PwEntry pe = this.GetSelectedEntry();
123 			if(pe == null) return false;
124 
125 			string str = @"{REF:";
126 			if(m_radioRefTitle.Checked) str += "T";
127 			else if(m_radioRefUserName.Checked) str += "U";
128 			else if(m_radioRefPassword.Checked) str += "P";
129 			else if(m_radioRefUrl.Checked) str += "A";
130 			else if(m_radioRefNotes.Checked) str += "N";
131 			else { Debug.Assert(false); return false; }
132 
133 			str += @"@";
134 
135 			string strId;
136 			if(m_radioIdTitle.Checked)
137 				strId = @"T:" + pe.Strings.ReadSafe(PwDefs.TitleField);
138 			else if(m_radioIdUserName.Checked)
139 				strId = @"U:" + pe.Strings.ReadSafe(PwDefs.UserNameField);
140 			else if(m_radioIdPassword.Checked)
141 				strId = @"P:" + pe.Strings.ReadSafe(PwDefs.PasswordField);
142 			else if(m_radioIdUrl.Checked)
143 				strId = @"A:" + pe.Strings.ReadSafe(PwDefs.UrlField);
144 			else if(m_radioIdNotes.Checked)
145 				strId = @"N:" + pe.Strings.ReadSafe(PwDefs.NotesField);
146 			else if(m_radioIdUuid.Checked)
147 				strId = @"I:" + pe.Uuid.ToHexString();
148 			else { Debug.Assert(false); return false; }
149 
150 			char[] vInvalidChars = new char[] { '{', '}', '\r', '\n' };
151 			if(strId.IndexOfAny(vInvalidChars) >= 0)
152 			{
153 				MessageService.ShowWarning(KPRes.FieldRefInvalidChars);
154 				return false;
155 			}
156 
157 			string strIdData = strId.Substring(2, strId.Length - 2);
158 			if(IdMatchesMultipleTimes(strIdData, strId[0]))
159 			{
160 				MessageService.ShowWarning(KPRes.FieldRefMultiMatch,
161 					KPRes.FieldRefMultiMatchHint);
162 				return false;
163 			}
164 
165 			str += strId + @"}";
166 
167 			m_strResultRef = str;
168 			return true;
169 		}
170 
IdMatchesMultipleTimes(string strSearch, char tchField)171 		private bool IdMatchesMultipleTimes(string strSearch, char tchField)
172 		{
173 			if(m_pgEntrySource == null) { Debug.Assert(false); return false; }
174 
175 			SearchParameters sp = SearchParameters.None;
176 			sp.SearchString = strSearch;
177 			sp.RespectEntrySearchingDisabled = false;
178 
179 			if(tchField == 'T') sp.SearchInTitles = true;
180 			else if(tchField == 'U') sp.SearchInUserNames = true;
181 			else if(tchField == 'P') sp.SearchInPasswords = true;
182 			else if(tchField == 'A') sp.SearchInUrls = true;
183 			else if(tchField == 'N') sp.SearchInNotes = true;
184 			else if(tchField == 'I') sp.SearchInUuids = true;
185 			else { Debug.Assert(false); return true; }
186 
187 			PwObjectList<PwEntry> l = new PwObjectList<PwEntry>();
188 			m_pgEntrySource.SearchEntries(sp, l);
189 
190 			if(l.UCount == 0) { Debug.Assert(false); return false; }
191 			if(l.UCount == 1) return false;
192 
193 			return true;
194 		}
195 
OnBtnOK(object sender, EventArgs e)196 		private void OnBtnOK(object sender, EventArgs e)
197 		{
198 			if(!CreateResultRef()) this.DialogResult = DialogResult.None;
199 		}
200 
OnBtnCancel(object sender, EventArgs e)201 		private void OnBtnCancel(object sender, EventArgs e)
202 		{
203 		}
204 
EnableChildControls()205 		private void EnableChildControls()
206 		{
207 			m_btnOK.Enabled = (GetSelectedEntry() != null);
208 		}
209 
OnEntriesSelectedIndexChanged(object sender, EventArgs e)210 		private void OnEntriesSelectedIndexChanged(object sender, EventArgs e)
211 		{
212 			EnableChildControls();
213 		}
214 
OnBtnHelp(object sender, EventArgs e)215 		private void OnBtnHelp(object sender, EventArgs e)
216 		{
217 			AppHelp.ShowHelp(AppDefs.HelpTopics.FieldRefs, null);
218 		}
219 
ProcessDialogKey(Keys keyData)220 		protected override bool ProcessDialogKey(Keys keyData)
221 		{
222 			Keys k = (keyData & Keys.KeyCode);
223 
224 			if((k == Keys.Return) && ((keyData & (Keys.Control | Keys.Alt)) ==
225 				Keys.None) && m_tbFilter.Focused) // Return == Enter
226 				return false; // Forward to TextBox
227 
228 			return base.ProcessDialogKey(keyData);
229 		}
230 
OnFilterKeyDown(object sender, KeyEventArgs e)231 		private void OnFilterKeyDown(object sender, KeyEventArgs e)
232 		{
233 			if(e.KeyCode == Keys.Return) // Return == Enter
234 			{
235 				UIUtil.SetHandled(e, true);
236 
237 				SearchParameters sp = new SearchParameters();
238 				sp.SearchString = m_tbFilter.Text;
239 				sp.SearchInPasswords = true;
240 
241 				PwObjectList<PwEntry> lResults = new PwObjectList<PwEntry>();
242 				m_pgEntrySource.SearchEntries(sp, lResults);
243 
244 				UIUtil.CreateEntryList(m_lvEntries, lResults, m_vColumns, m_ilIcons);
245 			}
246 		}
247 
OnFilterKeyUp(object sender, KeyEventArgs e)248 		private void OnFilterKeyUp(object sender, KeyEventArgs e)
249 		{
250 			if(e.KeyCode == Keys.Return) // Return == Enter
251 				UIUtil.SetHandled(e, true);
252 		}
253 	}
254 }
255