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; 22 using System.Collections.Generic; 23 using System.Diagnostics; 24 using System.Text; 25 26 using KeePassLib.Interfaces; 27 28 #if KeePassLibSD 29 using KeePassLibSD; 30 #endif 31 32 namespace KeePassLib.Collections 33 { 34 public sealed class StringDictionaryEx : IDeepCloneable<StringDictionaryEx>, 35 IEnumerable<KeyValuePair<string, string>>, IEquatable<StringDictionaryEx> 36 { 37 private SortedDictionary<string, string> m_d = 38 new SortedDictionary<string, string>(); 39 40 // Non-null if and only if last mod. times should be remembered 41 private Dictionary<string, DateTime> m_dLastMod = null; 42 43 public int Count 44 { 45 get { return m_d.Count; } 46 } 47 StringDictionaryEx()48 public StringDictionaryEx() 49 { 50 } 51 StringDictionaryEx(bool bRememberLastMod)52 internal StringDictionaryEx(bool bRememberLastMod) 53 { 54 if(bRememberLastMod) m_dLastMod = new Dictionary<string, DateTime>(); 55 } 56 IEnumerable.GetEnumerator()57 IEnumerator IEnumerable.GetEnumerator() 58 { 59 return m_d.GetEnumerator(); 60 } 61 GetEnumerator()62 public IEnumerator<KeyValuePair<string, string>> GetEnumerator() 63 { 64 return m_d.GetEnumerator(); 65 } 66 CloneDeep()67 public StringDictionaryEx CloneDeep() 68 { 69 StringDictionaryEx sdNew = new StringDictionaryEx(); 70 71 foreach(KeyValuePair<string, string> kvp in m_d) 72 sdNew.m_d[kvp.Key] = kvp.Value; 73 74 if(m_dLastMod != null) 75 sdNew.m_dLastMod = new Dictionary<string, DateTime>(m_dLastMod); 76 77 Debug.Assert(Equals(sdNew)); 78 return sdNew; 79 } 80 Equals(StringDictionaryEx sdOther)81 public bool Equals(StringDictionaryEx sdOther) 82 { 83 if(sdOther == null) { Debug.Assert(false); return false; } 84 85 if(m_d.Count != sdOther.m_d.Count) return false; 86 87 foreach(KeyValuePair<string, string> kvp in sdOther.m_d) 88 { 89 string str = Get(kvp.Key); 90 if((str == null) || (str != kvp.Value)) return false; 91 } 92 93 int cLastModT = ((m_dLastMod != null) ? m_dLastMod.Count : -1); 94 int cLastModO = ((sdOther.m_dLastMod != null) ? sdOther.m_dLastMod.Count : -1); 95 if(cLastModT != cLastModO) return false; 96 97 if(m_dLastMod != null) 98 { 99 foreach(KeyValuePair<string, DateTime> kvp in sdOther.m_dLastMod) 100 { 101 DateTime? odt = GetLastModificationTime(kvp.Key); 102 if(!odt.HasValue) return false; 103 if(odt.Value != kvp.Value) return false; 104 } 105 } 106 107 return true; 108 } 109 Get(string strName)110 public string Get(string strName) 111 { 112 if(strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); } 113 114 string str; 115 m_d.TryGetValue(strName, out str); 116 return str; 117 } 118 GetLastModificationTime(string strName)119 internal DateTime? GetLastModificationTime(string strName) 120 { 121 if(strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); } 122 123 if(m_dLastMod == null) return null; 124 125 DateTime dt; 126 if(m_dLastMod.TryGetValue(strName, out dt)) return dt; 127 return null; 128 } 129 Exists(string strName)130 public bool Exists(string strName) 131 { 132 if(strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); } 133 134 return m_d.ContainsKey(strName); 135 } 136 Set(string strName, string strValue)137 public void Set(string strName, string strValue) 138 { 139 if(strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); } 140 if(strValue == null) { Debug.Assert(false); throw new ArgumentNullException("strValue"); } 141 142 m_d[strName] = strValue; 143 144 if(m_dLastMod != null) m_dLastMod[strName] = DateTime.UtcNow; 145 } 146 Set(string strName, string strValue, DateTime? odtLastMod)147 internal void Set(string strName, string strValue, DateTime? odtLastMod) 148 { 149 if(strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); } 150 if(strValue == null) { Debug.Assert(false); throw new ArgumentNullException("strValue"); } 151 152 m_d[strName] = strValue; 153 154 if(m_dLastMod != null) 155 { 156 if(odtLastMod.HasValue) m_dLastMod[strName] = odtLastMod.Value; 157 else m_dLastMod.Remove(strName); 158 } 159 } 160 Remove(string strName)161 public bool Remove(string strName) 162 { 163 if(strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); } 164 165 if(m_dLastMod != null) m_dLastMod.Remove(strName); 166 167 return m_d.Remove(strName); 168 } 169 } 170 } 171