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.Security;
32 using KeePassLib.Utility;
33 
34 namespace KeePass.DataExchange.Formats
35 {
36 	// 5.3.0.1-6.0.4+
37 	internal sealed class EnpassTxt5 : FileFormatProvider
38 	{
39 		public override bool SupportsImport { get { return true; } }
40 		public override bool SupportsExport { get { return false; } }
41 
42 		public override string FormatName { get { return "Enpass TXT"; } }
43 		public override string DefaultExtension { get { return "txt"; } }
44 		public override string ApplicationGroup { get { return KPRes.PasswordManagers; } }
45 
46 		public override bool ImportAppendsToRootGroupOnly { get { return true; } }
47 
48 		public override Image SmallIcon
49 		{
50 			get { return KeePass.Properties.Resources.B16x16_Imp_Enpass; }
51 		}
52 
Import(PwDatabase pwStorage, Stream sInput, IStatusLogger slLogger)53 		public override void Import(PwDatabase pwStorage, Stream sInput,
54 			IStatusLogger slLogger)
55 		{
56 			StreamReader sr = new StreamReader(sInput, StrUtil.Utf8, true);
57 			string strData = sr.ReadToEnd();
58 			sr.Close();
59 
60 			PwGroup pg = pwStorage.RootGroup;
61 			const string strSep = ": "; // Both ": " and " : " are used
62 
63 			strData = StrUtil.NormalizeNewLines(strData, false);
64 
65 			int iSep = strData.IndexOf(strSep);
66 			if(iSep < 0) throw new FormatException();
67 			string strTitleKey = strData.Substring(0, iSep).Trim();
68 			if(strTitleKey.Length == 0) throw new FormatException();
69 			if(strTitleKey.IndexOf('\n') >= 0) throw new FormatException();
70 
71 			PwEntry pe = null;
72 			string strName = PwDefs.TitleField;
73 
74 			string[] vLines = strData.Split('\n');
75 			foreach(string strLine in vLines)
76 			{
77 				if(strLine == null) { Debug.Assert(false); continue; }
78 				// Do not trim strLine, otherwise strSep might not be detected
79 
80 				string strValue = strLine;
81 
82 				iSep = strLine.IndexOf(strSep);
83 				if(iSep >= 0)
84 				{
85 					string strCurName = strLine.Substring(0, iSep).Trim();
86 					strValue = strLine.Substring(iSep + strSep.Length);
87 
88 					if(strCurName == strTitleKey)
89 					{
90 						FinishEntry(pe);
91 
92 						pe = new PwEntry(true, true);
93 						pg.AddEntry(pe, true);
94 
95 						strName = PwDefs.TitleField;
96 					}
97 					else if(strName == PwDefs.NotesField)
98 						strValue = strLine; // Restore
99 					else
100 					{
101 						strName = ImportUtil.MapNameToStandardField(strCurName, true);
102 						if(string.IsNullOrEmpty(strName))
103 						{
104 							strName = strCurName;
105 							if(string.IsNullOrEmpty(strName))
106 							{
107 								Debug.Assert(false);
108 								strName = PwDefs.NotesField;
109 								strValue = strLine; // Restore
110 							}
111 						}
112 					}
113 				}
114 
115 				if(pe != null)
116 				{
117 					strValue = strValue.Trim();
118 
119 					if(strValue.Length != 0)
120 						ImportUtil.AppendToField(pe, strName, strValue, pwStorage);
121 					else if(strName == PwDefs.NotesField)
122 					{
123 						ProtectedString ps = pe.Strings.GetSafe(strName);
124 						pe.Strings.Set(strName, ps + MessageService.NewLine);
125 					}
126 				}
127 				else { Debug.Assert(false); }
128 			}
129 
130 			FinishEntry(pe);
131 		}
132 
FinishEntry(PwEntry pe)133 		private static void FinishEntry(PwEntry pe)
134 		{
135 			if(pe == null) return;
136 
137 			List<string> lKeys = pe.Strings.GetKeys();
138 			foreach(string strKey in lKeys)
139 			{
140 				ProtectedString ps = pe.Strings.GetSafe(strKey);
141 				pe.Strings.Set(strKey, new ProtectedString(
142 					ps.IsProtected, ps.ReadString().Trim()));
143 			}
144 		}
145 	}
146 }
147