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.Globalization;
26 using System.Text;
27 using System.Windows.Forms;
28 using System.Xml.Serialization;
29 
30 using KeePass.Resources;
31 using KeePass.UI;
32 
33 using KeePassLib;
34 using KeePassLib.Security;
35 
36 namespace KeePass.App.Configuration
37 {
38 	public enum AceMainWindowLayout
39 	{
40 		Default = 0,
41 		SideBySide = 1
42 	}
43 
44 	[Flags]
45 	public enum AceListGrouping
46 	{
47 		Auto = 0,
48 		On = 1,
49 		Off = 2,
50 
51 		// Additional flags: use value > Primary
52 
53 		Primary = 0x0F // Auto/On/Off are primary states
54 	}
55 
56 	public enum AceEscAction
57 	{
58 		None = 0,
59 		Lock = 1,
60 		Minimize = 2,
61 		MinimizeToTray = 3,
62 		Exit = 4
63 	}
64 
65 	public sealed class AceMainWindow
66 	{
AceMainWindow()67 		public AceMainWindow()
68 		{
69 		}
70 
71 		private int m_posX = AppDefs.InvalidWindowValue;
72 		public int X
73 		{
74 			get { return m_posX; }
75 			set { m_posX = value; }
76 		}
77 
78 		private int m_posY = AppDefs.InvalidWindowValue;
79 		public int Y
80 		{
81 			get { return m_posY; }
82 			set { m_posY = value; }
83 		}
84 
85 		private int m_sizeW = AppDefs.InvalidWindowValue;
86 		public int Width
87 		{
88 			get { return m_sizeW; }
89 			set { m_sizeW = value; }
90 		}
91 
92 		private int m_sizeH = AppDefs.InvalidWindowValue;
93 		public int Height
94 		{
95 			get { return m_sizeH; }
96 			set { m_sizeH = value; }
97 		}
98 
99 		private bool m_bMax = false;
100 		[DefaultValue(false)]
101 		public bool Maximized
102 		{
103 			get { return m_bMax; }
104 			set { m_bMax = value; }
105 		}
106 
107 		private double m_dSplitterHorz = double.Epsilon;
108 		public double SplitterHorizontalFrac
109 		{
110 			get { return m_dSplitterHorz; }
111 			set { m_dSplitterHorz = value; }
112 		}
113 
114 		private double m_dSplitterVert = double.Epsilon;
115 		public double SplitterVerticalFrac
116 		{
117 			get { return m_dSplitterVert; }
118 			set { m_dSplitterVert = value; }
119 		}
120 
121 		private AceMainWindowLayout m_layout = AceMainWindowLayout.Default;
122 		[DefaultValue(AceMainWindowLayout.Default)]
123 		public AceMainWindowLayout Layout
124 		{
125 			get { return m_layout; }
126 			set { m_layout = value; }
127 		}
128 
129 		private bool m_bTop = false;
130 		[DefaultValue(false)]
131 		public bool AlwaysOnTop
132 		{
133 			get { return m_bTop; }
134 			set { m_bTop = value; }
135 		}
136 
137 		private bool m_bCloseMin = false;
138 		[DefaultValue(false)]
139 		public bool CloseButtonMinimizesWindow
140 		{
141 			get { return m_bCloseMin; }
142 			set { m_bCloseMin = value; }
143 		}
144 
145 		// For backward compatibility only; use EscAction instead
146 		private bool m_bEscMin = false;
147 		[DefaultValue(false)]
148 		public bool EscMinimizesToTray
149 		{
150 			get { return m_bEscMin; }
151 			set { m_bEscMin = value; }
152 		}
153 
154 		private AceEscAction m_aEsc = AceEscAction.Lock;
155 		[DefaultValue(AceEscAction.Lock)]
156 		public AceEscAction EscAction
157 		{
158 			get { return m_aEsc; }
159 			set { m_aEsc = value; }
160 		}
161 
162 		private bool m_bMinToTray = false;
163 		[DefaultValue(false)]
164 		public bool MinimizeToTray
165 		{
166 			get { return m_bMinToTray; }
167 			set { m_bMinToTray = value; }
168 		}
169 
170 		private bool m_bFullPath = false;
171 		[DefaultValue(false)]
172 		public bool ShowFullPathInTitle
173 		{
174 			get { return m_bFullPath; }
175 			set { m_bFullPath = value; }
176 		}
177 
178 		// private bool m_bFullPathOnTab = false;
179 		// [DefaultValue(false)]
180 		// public bool ShowFullPathOnTab
181 		// {
182 		//	get { return m_bFullPathOnTab; }
183 		//	set { m_bFullPathOnTab = value; }
184 		// }
185 
186 		// private bool m_bDbNameOnTab = false;
187 		// [DefaultValue(false)]
188 		// public bool ShowDatabaseNameOnTab
189 		// {
190 		//	get { return m_bDbNameOnTab; }
191 		//	set { m_bDbNameOnTab = value; }
192 		// }
193 
194 		private bool m_bDropToBackAfterCopy = false;
195 		[DefaultValue(false)]
196 		public bool DropToBackAfterClipboardCopy
197 		{
198 			get { return m_bDropToBackAfterCopy; }
199 			set { m_bDropToBackAfterCopy = value; }
200 		}
201 
202 		private bool m_bMinAfterCopy = false;
203 		[DefaultValue(false)]
204 		public bool MinimizeAfterClipboardCopy
205 		{
206 			get { return m_bMinAfterCopy; }
207 			set { m_bMinAfterCopy = value; }
208 		}
209 
210 		private bool m_bMinAfterAutoType = false;
211 		[DefaultValue(false)]
212 		public bool MinimizeAfterAutoType
213 		{
214 			get { return m_bMinAfterAutoType; }
215 			set { m_bMinAfterAutoType = value; }
216 		}
217 
218 		private bool m_bMinAfterLocking = true;
219 		[DefaultValue(true)]
220 		public bool MinimizeAfterLocking
221 		{
222 			get { return m_bMinAfterLocking; }
223 			set { m_bMinAfterLocking = value; }
224 		}
225 
226 		private bool m_bMinAfterOpeningDb = false;
227 		[DefaultValue(false)]
228 		public bool MinimizeAfterOpeningDatabase
229 		{
230 			get { return m_bMinAfterOpeningDb; }
231 			set { m_bMinAfterOpeningDb = value; }
232 		}
233 
234 		private bool m_bQuickFindSearchInPasswords = false;
235 		[DefaultValue(false)]
236 		public bool QuickFindSearchInPasswords
237 		{
238 			get { return m_bQuickFindSearchInPasswords; }
239 			set { m_bQuickFindSearchInPasswords = value; }
240 		}
241 
242 		private bool m_bQuickFindExcludeExpired = false;
243 		[DefaultValue(false)]
244 		public bool QuickFindExcludeExpired
245 		{
246 			get { return m_bQuickFindExcludeExpired; }
247 			set { m_bQuickFindExcludeExpired = value; }
248 		}
249 
250 		private bool m_bQuickFindDerefData = false;
251 		[DefaultValue(false)]
252 		public bool QuickFindDerefData
253 		{
254 			get { return m_bQuickFindDerefData; }
255 			set { m_bQuickFindDerefData = value; }
256 		}
257 
258 		private bool m_bFocusResAfterQuickFind = false;
259 		[DefaultValue(false)]
260 		public bool FocusResultsAfterQuickFind
261 		{
262 			get { return m_bFocusResAfterQuickFind; }
263 			set { m_bFocusResAfterQuickFind = value; }
264 		}
265 
266 		private bool m_bFocusQuickFindOnRestore = false;
267 		/// <summary>
268 		/// Focus the quick search box when restoring the main
269 		/// window. Here 'restoring' actually means unminimizing,
270 		/// i.e. restoring or maximizing the window.
271 		/// </summary>
272 		[DefaultValue(false)]
273 		public bool FocusQuickFindOnRestore
274 		{
275 			get { return m_bFocusQuickFindOnRestore; }
276 			set { m_bFocusQuickFindOnRestore = value; }
277 		}
278 
279 		private bool m_bFocusQuickFindOnUntray = false;
280 		[DefaultValue(false)]
281 		public bool FocusQuickFindOnUntray
282 		{
283 			get { return m_bFocusQuickFindOnUntray; }
284 			set { m_bFocusQuickFindOnUntray = value; }
285 		}
286 
287 		private bool m_bCopyUrls = false;
288 		[DefaultValue(false)]
289 		public bool CopyUrlsInsteadOfOpening
290 		{
291 			get { return m_bCopyUrls; }
292 			set { m_bCopyUrls = value; }
293 		}
294 
295 		private bool m_bEntrySelGroupSel = true;
296 		[DefaultValue(true)]
297 		public bool EntrySelGroupSel
298 		{
299 			get { return m_bEntrySelGroupSel; }
300 			set { m_bEntrySelGroupSel = value; }
301 		}
302 
303 		private bool m_bDisableSaveIfNotModified = false;
304 		/// <summary>
305 		/// Disable 'Save' button (instead of graying it out) if the database
306 		/// hasn't been modified.
307 		/// </summary>
308 		[DefaultValue(false)]
309 		public bool DisableSaveIfNotModified
310 		{
311 			get { return m_bDisableSaveIfNotModified; }
312 			set { m_bDisableSaveIfNotModified = value; }
313 		}
314 
315 		private bool m_bHideCloseDbTb = true;
316 		[DefaultValue(true)]
317 		public bool HideCloseDatabaseButton
318 		{
319 			get { return m_bHideCloseDbTb; }
320 			set { m_bHideCloseDbTb = value; }
321 		}
322 
323 		private AceToolBar m_tb = new AceToolBar();
324 		public AceToolBar ToolBar
325 		{
326 			get { return m_tb; }
327 			set
328 			{
329 				if(value == null) throw new ArgumentNullException("value");
330 				m_tb = value;
331 			}
332 		}
333 
334 		private AceEntryView m_ev = new AceEntryView();
335 		public AceEntryView EntryView
336 		{
337 			get { return m_ev; }
338 			set
339 			{
340 				if(value == null) throw new ArgumentNullException("value");
341 				m_ev = value;
342 			}
343 		}
344 
345 		private AceTanView m_tan = new AceTanView();
346 		public AceTanView TanView
347 		{
348 			get { return m_tan; }
349 			set
350 			{
351 				if(value == null) throw new ArgumentNullException("value");
352 				m_tan = value;
353 			}
354 		}
355 
356 		private List<AceColumn> m_lColumns = new List<AceColumn>();
357 		[XmlArray("EntryListColumnCollection")]
358 		[XmlArrayItem("Column")]
359 		public List<AceColumn> EntryListColumns
360 		{
361 			get { return m_lColumns; }
362 			set
363 			{
364 				if(value == null) throw new ArgumentNullException("value");
365 				m_lColumns = value;
366 			}
367 		}
368 
369 		private string m_strDisplayIndices = string.Empty;
370 		[DefaultValue("")]
371 		public string EntryListColumnDisplayOrder
372 		{
373 			get { return m_strDisplayIndices; }
374 			set
375 			{
376 				if(value == null) throw new ArgumentNullException("value");
377 				m_strDisplayIndices = value;
378 			}
379 		}
380 
381 		private bool m_bAutoResizeColumns = false;
382 		[DefaultValue(false)]
383 		public bool EntryListAutoResizeColumns
384 		{
385 			get { return m_bAutoResizeColumns; }
386 			set { m_bAutoResizeColumns = value; }
387 		}
388 
389 		private bool m_bAlternatingBgColor = true;
390 		[DefaultValue(true)]
391 		public bool EntryListAlternatingBgColors
392 		{
393 			get { return m_bAlternatingBgColor; }
394 			set { m_bAlternatingBgColor = value; }
395 		}
396 
397 		private int m_argbAltBgColor = 0;
398 		[DefaultValue(0)]
399 		public int EntryListAlternatingBgColor
400 		{
401 			get { return m_argbAltBgColor; }
402 			set { m_argbAltBgColor = value; }
403 		}
404 
405 		private bool m_bResolveFieldRefs = false;
406 		[DefaultValue(false)]
407 		public bool EntryListShowDerefData
408 		{
409 			get { return m_bResolveFieldRefs; }
410 			set { m_bResolveFieldRefs = value; }
411 		}
412 
413 		private bool m_bResolveFieldRefsAsync = false;
414 		[DefaultValue(false)]
415 		public bool EntryListShowDerefDataAsync
416 		{
417 			get { return m_bResolveFieldRefsAsync; }
418 			set { m_bResolveFieldRefsAsync = value; }
419 		}
420 
421 		private bool m_bDerefDataWithRefs = true;
422 		[DefaultValue(true)]
423 		public bool EntryListShowDerefDataAndRefs
424 		{
425 			get { return m_bDerefDataWithRefs; }
426 			set { m_bDerefDataWithRefs = value; }
427 		}
428 
429 		// private bool m_bGridLines = false;
430 		// public bool ShowGridLines
431 		// {
432 		//	get { return m_bGridLines; }
433 		//	set { m_bGridLines = value; }
434 		// }
435 
436 		private ListSorter m_pListSorter = null;
437 		public ListSorter ListSorting
438 		{
439 			get
440 			{
441 				if(m_pListSorter == null) m_pListSorter = new ListSorter();
442 				return m_pListSorter;
443 			}
444 			set
445 			{
446 				if(value == null) throw new ArgumentNullException("value");
447 				m_pListSorter = value;
448 			}
449 		}
450 
451 		private int m_iLgMain = (int)AceListGrouping.Auto;
452 		[DefaultValue((int)AceListGrouping.Auto)]
453 		public int ListGrouping // AceListGrouping
454 		{
455 			get { return m_iLgMain; }
456 			set { m_iLgMain = value; }
457 		}
458 
459 		private bool m_bShowEntriesOfSubGroups = false;
460 		[DefaultValue(false)]
461 		public bool ShowEntriesOfSubGroups
462 		{
463 			get { return m_bShowEntriesOfSubGroups; }
464 			set { m_bShowEntriesOfSubGroups = value; }
465 		}
466 
FindColumn(AceColumnType t)467 		public AceColumn FindColumn(AceColumnType t)
468 		{
469 			foreach(AceColumn c in m_lColumns)
470 			{
471 				if(c.Type == t) return c;
472 			}
473 
474 			return null;
475 		}
476 
FindColumns(AceColumnType t)477 		internal List<AceColumn> FindColumns(AceColumnType t)
478 		{
479 			List<AceColumn> l = new List<AceColumn>();
480 
481 			foreach(AceColumn c in m_lColumns)
482 			{
483 				if(c.Type == t) l.Add(c);
484 			}
485 
486 			return l;
487 		}
488 
IsColumnHidden(AceColumnType t)489 		public bool IsColumnHidden(AceColumnType t)
490 		{
491 			return IsColumnHidden(t, (t == AceColumnType.Password));
492 		}
493 
IsColumnHidden(AceColumnType t, bool bDefault)494 		public bool IsColumnHidden(AceColumnType t, bool bDefault)
495 		{
496 			foreach(AceColumn c in m_lColumns)
497 			{
498 				if(c.Type == t) return c.HideWithAsterisks;
499 			}
500 
501 			return bDefault;
502 		}
503 
ShouldHideCustomString(string strCustomName, ProtectedString psValue)504 		public bool ShouldHideCustomString(string strCustomName,
505 			ProtectedString psValue)
506 		{
507 			foreach(AceColumn c in m_lColumns)
508 			{
509 				if((c.Type == AceColumnType.CustomString) &&
510 					(c.CustomName == strCustomName))
511 					return c.HideWithAsterisks;
512 			}
513 			if(psValue != null) return psValue.IsProtected;
514 			return false;
515 		}
516 	}
517 
518 	public sealed class AceEntryView
519 	{
AceEntryView()520 		public AceEntryView()
521 		{
522 		}
523 
524 		private bool m_bShow = true;
525 		[DefaultValue(true)]
526 		public bool Show
527 		{
528 			get { return m_bShow; }
529 			set { m_bShow = value; }
530 		}
531 
532 		// private bool m_bHideProtectedCustomStrings = true;
533 		// [DefaultValue(true)]
534 		// public bool HideProtectedCustomStrings
535 		// {
536 		//	get { return m_bHideProtectedCustomStrings; }
537 		//	set { m_bHideProtectedCustomStrings = value; }
538 		// }
539 	}
540 
541 	public sealed class AceTanView
542 	{
AceTanView()543 		public AceTanView()
544 		{
545 		}
546 
547 		private bool m_bSimple = true;
548 		[DefaultValue(true)]
549 		public bool UseSimpleView
550 		{
551 			get { return m_bSimple; }
552 			set { m_bSimple = value; }
553 		}
554 
555 		private bool m_bIndices = true;
556 		[DefaultValue(true)]
557 		public bool ShowIndices
558 		{
559 			get { return m_bIndices; }
560 			set { m_bIndices = value; }
561 		}
562 	}
563 
564 	public enum AceColumnType
565 	{
566 		Title = 0,
567 		UserName,
568 		Password,
569 		Url,
570 		Notes,
571 		CreationTime,
572 		LastModificationTime,
573 		LastAccessTime,
574 		ExpiryTime,
575 		Uuid,
576 		Attachment,
577 
578 		CustomString,
579 
580 		PluginExt, // Column data provided by a plugin
581 
582 		OverrideUrl,
583 		Tags,
584 		ExpiryTimeDateOnly,
585 		Size,
586 		HistoryCount,
587 		AttachmentCount,
588 		LastPasswordModTime,
589 		AutoTypeEnabled,
590 		AutoTypeSequences,
591 
592 		Count // Virtual identifier representing the number of types
593 	}
594 
595 	public sealed class AceColumn
596 	{
597 		private AceColumnType m_type = AceColumnType.Count;
598 		public AceColumnType Type
599 		{
600 			get { return m_type; }
601 			set
602 			{
603 				if(((int)value >= 0) && ((int)value < (int)AceColumnType.Count))
604 					m_type = value;
605 				else { Debug.Assert(false); }
606 			}
607 		}
608 
609 		private string m_strCustomName = string.Empty;
610 		[DefaultValue("")]
611 		public string CustomName
612 		{
613 			get { return m_strCustomName; }
614 			set
615 			{
616 				if(value == null) throw new ArgumentNullException("value");
617 				m_strCustomName = value;
618 			}
619 		}
620 
621 		private int m_nWidth = -1;
622 		public int Width
623 		{
624 			get { return m_nWidth; }
625 			set { m_nWidth = value; }
626 		}
627 
628 		private bool m_bHide = false;
629 		[DefaultValue(false)]
630 		public bool HideWithAsterisks
631 		{
632 			get { return m_bHide; }
633 			set { m_bHide = value; }
634 		}
635 
AceColumn()636 		public AceColumn()
637 		{
638 		}
639 
AceColumn(AceColumnType t)640 		public AceColumn(AceColumnType t)
641 		{
642 			m_type = t;
643 		}
644 
AceColumn(AceColumnType t, string strCustomName, bool bHide, int nWidth)645 		public AceColumn(AceColumnType t, string strCustomName, bool bHide,
646 			int nWidth)
647 		{
648 			m_type = t;
649 			m_strCustomName = strCustomName;
650 			m_bHide = bHide;
651 			m_nWidth = nWidth;
652 		}
653 
GetDisplayName()654 		public string GetDisplayName()
655 		{
656 			string str = string.Empty;
657 
658 			switch(m_type)
659 			{
660 				case AceColumnType.Title: str = KPRes.Title; break;
661 				case AceColumnType.UserName: str = KPRes.UserName; break;
662 				case AceColumnType.Password: str = KPRes.Password; break;
663 				case AceColumnType.Url: str = KPRes.Url; break;
664 				case AceColumnType.Notes: str = KPRes.Notes; break;
665 				case AceColumnType.CreationTime: str = KPRes.CreationTime; break;
666 				case AceColumnType.LastModificationTime: str = KPRes.LastModificationTime; break;
667 				case AceColumnType.LastAccessTime: str = KPRes.LastAccessTime; break;
668 				case AceColumnType.ExpiryTime: str = KPRes.ExpiryTime; break;
669 				case AceColumnType.Uuid: str = KPRes.Uuid; break;
670 				case AceColumnType.Attachment: str = KPRes.Attachments; break;
671 				case AceColumnType.CustomString: str = m_strCustomName; break;
672 				case AceColumnType.PluginExt: str = m_strCustomName; break;
673 				case AceColumnType.OverrideUrl: str = KPRes.UrlOverride; break;
674 				case AceColumnType.Tags: str = KPRes.Tags; break;
675 				case AceColumnType.ExpiryTimeDateOnly: str = KPRes.ExpiryTimeDateOnly; break;
676 				case AceColumnType.Size: str = KPRes.Size; break;
677 				case AceColumnType.HistoryCount:
678 					str = KPRes.History + " (" + KPRes.Count + ")"; break;
679 				case AceColumnType.AttachmentCount:
680 					str = KPRes.Attachments + " (" + KPRes.Count + ")"; break;
681 				case AceColumnType.LastPasswordModTime: str = KPRes.LastModTimePwHist; break;
682 				case AceColumnType.AutoTypeEnabled:
683 					str = KPRes.AutoType + " - " + KPRes.Enabled; break;
684 				case AceColumnType.AutoTypeSequences:
685 					str = KPRes.AutoType + " - " + KPRes.Sequences; break;
686 				default: Debug.Assert(false); break;
687 			};
688 
689 			return str;
690 		}
691 
SafeGetWidth(int nDefaultWidth)692 		public int SafeGetWidth(int nDefaultWidth)
693 		{
694 			if(m_nWidth >= 0) return m_nWidth;
695 			return nDefaultWidth;
696 		}
697 
GetTypeNameEx()698 		internal string GetTypeNameEx()
699 		{
700 			try
701 			{
702 				string str = m_type.ToString();
703 
704 				if(!string.IsNullOrEmpty(m_strCustomName))
705 					str += " - " + m_strCustomName;
706 
707 				return str;
708 			}
709 			catch(Exception) { Debug.Assert(false); }
710 
711 			return ((long)m_type).ToString(NumberFormatInfo.InvariantInfo);
712 		}
713 
714 #if DEBUG
ToString()715 		public override string ToString()
716 		{
717 			return (GetTypeNameEx() + ", Width: " + m_nWidth.ToString() +
718 				", Hide: " + m_bHide.ToString());
719 		}
720 #endif
721 
IsTimeColumn(AceColumnType t)722 		public static bool IsTimeColumn(AceColumnType t)
723 		{
724 			return ((t == AceColumnType.CreationTime) ||
725 				(t == AceColumnType.LastModificationTime) ||
726 				(t == AceColumnType.LastAccessTime) ||
727 				(t == AceColumnType.ExpiryTime) ||
728 				(t == AceColumnType.ExpiryTimeDateOnly) ||
729 				(t == AceColumnType.LastPasswordModTime));
730 
731 			/* bool bTime = false;
732 			switch(t)
733 			{
734 				case AceColumnType.CreationTime:
735 				case AceColumnType.LastModificationTime:
736 				case AceColumnType.LastAccessTime:
737 				case AceColumnType.ExpiryTime:
738 				case AceColumnType.ExpiryTimeDateOnly:
739 				case AceColumnType.LastPasswordModTime:
740 					bTime = true;
741 					break;
742 				default:
743 					break;
744 			}
745 
746 			return bTime; */
747 		}
748 
GetTextAlign(AceColumnType t)749 		public static HorizontalAlignment GetTextAlign(AceColumnType t)
750 		{
751 			if((t == AceColumnType.Size) || (t == AceColumnType.HistoryCount) ||
752 				(t == AceColumnType.AttachmentCount))
753 				return HorizontalAlignment.Right;
754 
755 			return HorizontalAlignment.Left;
756 		}
757 	}
758 }
759