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.Diagnostics; 23 using System.Drawing; 24 using System.IO; 25 using System.Text; 26 27 using KeePass.Resources; 28 29 using KeePassLib; 30 using KeePassLib.Interfaces; 31 using KeePassLib.Utility; 32 33 namespace KeePass.DataExchange.Formats 34 { 35 // 3.5.5+ 36 internal sealed class MSecureCsv355 : FileFormatProvider 37 { 38 public override bool SupportsImport { get { return true; } } 39 public override bool SupportsExport { get { return false; } } 40 41 public override string FormatName { get { return "mSecure CSV"; } } 42 public override string DefaultExtension { get { return "csv"; } } 43 public override string ApplicationGroup { get { return KPRes.PasswordManagers; } } 44 45 public override bool ImportAppendsToRootGroupOnly { get { return false; } } 46 47 public override Image SmallIcon 48 { 49 get { return KeePass.Properties.Resources.B16x16_Imp_MSecure; } 50 } 51 Import(PwDatabase pwStorage, Stream sInput, IStatusLogger slLogger)52 public override void Import(PwDatabase pwStorage, Stream sInput, 53 IStatusLogger slLogger) 54 { 55 StreamReader sr = new StreamReader(sInput, Encoding.Default, true); 56 string str = sr.ReadToEnd(); 57 sr.Close(); 58 59 CsvOptions opt = new CsvOptions(); 60 61 // Backslashes are not escaped, even though "\\n" is used 62 // to encode new-line characters 63 opt.BackslashIsEscape = false; 64 opt.FieldSeparator = ';'; 65 66 CsvStreamReaderEx csr = new CsvStreamReaderEx(str, opt); 67 Dictionary<string, PwGroup> dGroups = new Dictionary<string, PwGroup>(); 68 69 while(true) 70 { 71 string[] vLine = csr.ReadLine(); 72 if(vLine == null) break; 73 74 AddEntry(vLine, pwStorage, dGroups); 75 } 76 } 77 AddEntry(string[] vLine, PwDatabase pd, Dictionary<string, PwGroup> dGroups)78 private static void AddEntry(string[] vLine, PwDatabase pd, 79 Dictionary<string, PwGroup> dGroups) 80 { 81 if(vLine.Length < 2) return; 82 83 string strGroup = vLine[0]; 84 PwGroup pg; 85 if(string.IsNullOrEmpty(strGroup)) 86 pg = pd.RootGroup; 87 else 88 { 89 if(!dGroups.TryGetValue(strGroup, out pg)) 90 { 91 pg = new PwGroup(true, true); 92 pg.Name = strGroup; 93 94 pd.RootGroup.AddGroup(pg, true); 95 dGroups[strGroup] = pg; 96 } 97 } 98 99 PwEntry pe = new PwEntry(true, true); 100 pg.AddEntry(pe, true); 101 102 MsAppend(pe, PwDefs.TitleField, vLine, 2, pd); 103 MsAppend(pe, PwDefs.NotesField, vLine, 3, pd); 104 105 string strType = vLine[1]; 106 int i = 3; 107 DateTime dt; 108 109 switch(strType) 110 { 111 case "Bank Accounts": 112 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 113 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 114 MsAppend(pe, "Name", vLine, ++i, pd); 115 MsAppend(pe, "Branch", vLine, ++i, pd); 116 MsAppend(pe, "Phone No.", vLine, ++i, pd); 117 118 pe.IconId = PwIcon.Money; 119 break; 120 121 case "Birthdays": 122 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 123 124 pe.IconId = PwIcon.UserCommunication; 125 break; 126 127 case "Calling Cards": 128 case "Social Security": 129 case "Voice Mail": 130 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 131 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 132 133 pe.IconId = PwIcon.UserKey; 134 break; 135 136 case "Clothes Size": 137 MsAppend(pe, "Shirt Size", vLine, ++i, pd); 138 MsAppend(pe, "Pant Size", vLine, ++i, pd); 139 MsAppend(pe, "Shoe Size", vLine, ++i, pd); 140 MsAppend(pe, "Dress Size", vLine, ++i, pd); 141 break; 142 143 case "Combinations": 144 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 145 break; 146 147 case "Credit Cards": 148 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 149 150 ++i; 151 if((vLine.Length > i) && StrUtil.TryParseDateTime( 152 vLine[i], out dt)) 153 { 154 pe.Expires = true; 155 pe.ExpiryTime = TimeUtil.ToUtc(dt, false); 156 } 157 else MsAppend(pe, "Expiration", vLine, i, pd); 158 159 MsAppend(pe, "Name", vLine, ++i, pd); 160 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 161 MsAppend(pe, "Bank", vLine, ++i, pd); 162 MsAppend(pe, "Security Code", vLine, ++i, pd); 163 164 pe.IconId = PwIcon.Money; 165 break; 166 167 case "Email Accounts": 168 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 169 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 170 MsAppend(pe, "POP3 Host", vLine, ++i, pd); 171 MsAppend(pe, "SMTP Host", vLine, ++i, pd); 172 173 pe.IconId = PwIcon.EMail; 174 break; 175 176 case "Frequent Flyer": 177 MsAppend(pe, "Number", vLine, ++i, pd); 178 MsAppend(pe, PwDefs.UrlField, vLine, ++i, pd); 179 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 180 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 181 MsAppend(pe, "Mileage", vLine, ++i, pd); 182 break; 183 184 case "Identity": 185 ++i; 186 MsAppend(pe, PwDefs.UserNameField, vLine, i + 1, pd); // Last name 187 MsAppend(pe, PwDefs.UserNameField, vLine, i, pd); // First name 188 ++i; 189 190 MsAppend(pe, "Nick Name", vLine, ++i, pd); 191 MsAppend(pe, "Company", vLine, ++i, pd); 192 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 193 MsAppend(pe, "Address", vLine, ++i, pd); 194 MsAppend(pe, "Address 2", vLine, ++i, pd); 195 MsAppend(pe, "City", vLine, ++i, pd); 196 MsAppend(pe, "State", vLine, ++i, pd); 197 MsAppend(pe, "Country", vLine, ++i, pd); 198 MsAppend(pe, "Zip", vLine, ++i, pd); 199 MsAppend(pe, "Home Phone", vLine, ++i, pd); 200 MsAppend(pe, "Office Phone", vLine, ++i, pd); 201 MsAppend(pe, "Mobile Phone", vLine, ++i, pd); 202 MsAppend(pe, "E-Mail", vLine, ++i, pd); 203 MsAppend(pe, "E-Mail 2", vLine, ++i, pd); 204 MsAppend(pe, "Skype", vLine, ++i, pd); 205 MsAppend(pe, PwDefs.UrlField, vLine, ++i, pd); 206 207 pe.IconId = PwIcon.UserCommunication; 208 break; 209 210 case "Insurance": 211 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 212 MsAppend(pe, "Group No.", vLine, ++i, pd); 213 MsAppend(pe, "Insured", vLine, ++i, pd); 214 MsAppend(pe, "Date", vLine, ++i, pd); 215 MsAppend(pe, "Phone No.", vLine, ++i, pd); 216 217 pe.IconId = PwIcon.Certificate; 218 break; 219 220 case "Memberships": 221 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 222 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 223 MsAppend(pe, "Date", vLine, ++i, pd); 224 225 pe.IconId = PwIcon.UserKey; 226 break; 227 228 case "Note": 229 pe.IconId = PwIcon.Notepad; 230 break; 231 232 case "Passport": 233 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 234 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 235 MsAppend(pe, "Type", vLine, ++i, pd); 236 MsAppend(pe, "Issuing Country", vLine, ++i, pd); 237 MsAppend(pe, "Issuing Authority", vLine, ++i, pd); 238 MsAppend(pe, "Nationality", vLine, ++i, pd); 239 240 ++i; 241 if((vLine.Length > i) && StrUtil.TryParseDateTime( 242 vLine[i], out dt)) 243 { 244 pe.Expires = true; 245 pe.ExpiryTime = TimeUtil.ToUtc(dt, false); 246 } 247 else MsAppend(pe, "Expiration", vLine, i, pd); 248 249 MsAppend(pe, "Place of Birth", vLine, ++i, pd); 250 251 pe.IconId = PwIcon.Certificate; 252 break; 253 254 case "Prescriptions": 255 MsAppend(pe, "RX Number", vLine, ++i, pd); 256 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 257 MsAppend(pe, "Doctor", vLine, ++i, pd); 258 MsAppend(pe, "Pharmacy", vLine, ++i, pd); 259 MsAppend(pe, "Phone No.", vLine, ++i, pd); 260 break; 261 262 case "Registration Codes": 263 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 264 MsAppend(pe, "Date", vLine, ++i, pd); 265 266 pe.IconId = PwIcon.UserKey; 267 break; 268 269 case "Unassigned": 270 MsAppend(pe, "Field 1", vLine, ++i, pd); 271 MsAppend(pe, "Field 2", vLine, ++i, pd); 272 MsAppend(pe, "Field 3", vLine, ++i, pd); 273 MsAppend(pe, "Field 4", vLine, ++i, pd); 274 MsAppend(pe, "Field 5", vLine, ++i, pd); 275 MsAppend(pe, "Field 6", vLine, ++i, pd); 276 break; 277 278 case "Vehicle Info": 279 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 280 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 281 MsAppend(pe, "Date Purchased", vLine, ++i, pd); 282 MsAppend(pe, "Tire Size", vLine, ++i, pd); 283 break; 284 285 case "Web Logins": 286 MsAppend(pe, PwDefs.UrlField, vLine, ++i, pd); 287 MsAppend(pe, PwDefs.UserNameField, vLine, ++i, pd); 288 MsAppend(pe, PwDefs.PasswordField, vLine, ++i, pd); 289 break; 290 291 default: 292 Debug.Assert(false); 293 break; 294 } 295 Debug.Assert((i + 1) == vLine.Length); 296 } 297 MsAppend(PwEntry pe, string strFieldName, string[] vLine, int iIndex, PwDatabase pdContext)298 private static void MsAppend(PwEntry pe, string strFieldName, 299 string[] vLine, int iIndex, PwDatabase pdContext) 300 { 301 if(iIndex >= vLine.Length) { Debug.Assert(false); return; } 302 303 string strValue = vLine[iIndex]; 304 if(string.IsNullOrEmpty(strValue)) return; 305 306 strValue = strValue.Replace("\\r\\n", "\\n"); 307 strValue = strValue.Replace("\\r", "\\n"); 308 309 if(PwDefs.IsStandardField(strFieldName) && 310 (strFieldName != PwDefs.NotesField)) 311 { 312 while(strValue.EndsWith("\\n")) 313 { 314 strValue = strValue.Substring(0, strValue.Length - 2); 315 } 316 317 strValue = strValue.Replace("\\n", ", "); 318 } 319 else strValue = strValue.Replace("\\n", MessageService.NewLine); 320 321 ImportUtil.AppendToField(pe, strFieldName, strValue, pdContext); 322 } 323 } 324 } 325