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.Globalization;
25 using System.IO;
26 using System.Text;
27 
28 using KeePass.Resources;
29 
30 using KeePassLib;
31 using KeePassLib.Interfaces;
32 using KeePassLib.Security;
33 using KeePassLib.Utility;
34 
35 namespace KeePass.DataExchange.Formats
36 {
37 	// 1.44 & Pro 1.07
38 	internal sealed class AnyPwCsv144 : FileFormatProvider
39 	{
40 		public override bool SupportsImport { get { return true; } }
41 		public override bool SupportsExport { get { return false; } }
42 
43 		public override string FormatName { get { return "Any Password CSV"; } }
44 		public override string DefaultExtension { get { return "csv"; } }
45 		public override string ApplicationGroup { get { return KPRes.PasswordManagers; } }
46 
47 		public override bool ImportAppendsToRootGroupOnly { get { return true; } }
48 
49 		public override Image SmallIcon
50 		{
51 			get { return KeePass.Properties.Resources.B16x16_Imp_AnyPw; }
52 		}
53 
Import(PwDatabase pwStorage, Stream sInput, IStatusLogger slLogger)54 		public override void Import(PwDatabase pwStorage, Stream sInput,
55 			IStatusLogger slLogger)
56 		{
57 			StreamReader sr = new StreamReader(sInput, Encoding.Default);
58 			string strData = sr.ReadToEnd();
59 			sr.Close();
60 
61 			string[] vLines = strData.Split(new char[] { '\r', '\n' },
62 				StringSplitOptions.RemoveEmptyEntries);
63 
64 			foreach(string strLine in vLines)
65 			{
66 				if(strLine.Length > 5) ProcessCsvLine(strLine, pwStorage);
67 			}
68 		}
69 
ProcessCsvLine(string strLine, PwDatabase pwStorage)70 		private static void ProcessCsvLine(string strLine, PwDatabase pwStorage)
71 		{
72 			List<string> list = ImportUtil.SplitCsvLine(strLine, ",");
73 			Debug.Assert((list.Count == 6) || (list.Count == 7));
74 			if(list.Count < 6) return;
75 			bool bIsPro = (list.Count >= 7); // Std exports 6 fields only
76 
77 			PwEntry pe = new PwEntry(true, true);
78 			pwStorage.RootGroup.AddEntry(pe, true);
79 
80 			pe.Strings.Set(PwDefs.TitleField, new ProtectedString(
81 				pwStorage.MemoryProtection.ProtectTitle,
82 				ParseCsvWord(list[0], false)));
83 			pe.Strings.Set(PwDefs.UserNameField, new ProtectedString(
84 				pwStorage.MemoryProtection.ProtectUserName,
85 				ParseCsvWord(list[1], false)));
86 			pe.Strings.Set(PwDefs.PasswordField, new ProtectedString(
87 				pwStorage.MemoryProtection.ProtectPassword,
88 				ParseCsvWord(list[2], false)));
89 			pe.Strings.Set(PwDefs.UrlField, new ProtectedString(
90 				pwStorage.MemoryProtection.ProtectUrl,
91 				ParseCsvWord(list[3], false)));
92 
93 			int p = 3;
94 			if(bIsPro)
95 				pe.Strings.Set(KPRes.Custom, new ProtectedString(false,
96 					ParseCsvWord(list[++p], false)));
97 
98 			pe.Strings.Set(PwDefs.NotesField, new ProtectedString(
99 				pwStorage.MemoryProtection.ProtectNotes,
100 				ParseCsvWord(list[++p], true)));
101 
102 			DateTime dt;
103 			if(DateTime.TryParse(ParseCsvWord(list[++p], false), out dt))
104 				pe.CreationTime = pe.LastAccessTime = pe.LastModificationTime =
105 					TimeUtil.ToUtc(dt, false);
106 			else { Debug.Assert(false); }
107 		}
108 
ParseCsvWord(string strWord, bool bFixCodes)109 		private static string ParseCsvWord(string strWord, bool bFixCodes)
110 		{
111 			string str = strWord.Trim();
112 
113 			if((str.Length >= 2) && str.StartsWith("\"") && str.EndsWith("\""))
114 				str = str.Substring(1, str.Length - 2);
115 
116 			str = str.Replace("\"\"", "\"");
117 
118 			if(bFixCodes)
119 			{
120 				str = str.Replace("<13>", string.Empty);
121 				str = str.Replace("<10>", "\r\n");
122 			}
123 
124 			return str;
125 		}
126 	}
127 }
128