context: /*
    KeePass Password Safe - The Open-Source Password Manager
    Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
  
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
  
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
  
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Xml;
  using System.IO;
  using System.Drawing;
  using System.Globalization;
  using System.Diagnostics;
  
  using KeePass.Resources;
  using KeePass.Util;
  
  using KeePassLib;
  using KeePassLib.Interfaces;
  using KeePassLib.Security;
  using KeePassLib.Utility;
  
  namespace KeePass.DataExchange.Formats
  {
  	// 2.6 - 5.3.0+
  	internal sealed class PwDepotXml26 : FileFormatProvider
  	{
  		private const string ElemHeader = "HEADER";
  		private const string ElemContainer = "PASSWORDS";
  
  		private const string ElemGroup = "GROUP";
  		private const string AttribGroupName = "NAME";
  
  		private const string ElemEntry = "ITEM";
  		private const string ElemEntryName = "DESCRIPTION";
  		private const string ElemEntryUser = "USERNAME";
  		private const string ElemEntryPassword = "PASSWORD";
  		private const string ElemEntryURL = "URL";
  		private const string ElemEntryNotes = "COMMENT";
  		private const string ElemEntryLastModTime = "LASTMODIFIED";
  		private const string ElemEntryExpireTime = "EXPIRYDATE";
  		private const string ElemEntryCreatedTime = "CREATED";
  		private const string ElemEntryLastAccTime = "LASTACCESSED";
  		private const string ElemEntryUsageCount = "USAGECOUNT";
  		private const string ElemEntryAutoType = "TEMPLATE";
  		private const string ElemEntryCustom = "CUSTOMFIELDS";
  
  		private static readonly string[] ElemEntryUnsupportedItems = new string[]{
  			"TYPE", "IMPORTANCE", "IMAGECUSTOM", "PARAMSTR",
  			"CATEGORY", "CUSTOMBROWSER", "AUTOCOMPLETEMETHOD",
  			"WEBFORMDATA", "TANS", "FINGERPRINT"
  		};
  
  		private const string ElemImageIndex = "IMAGEINDEX";
  
  		private const string ElemCustomField = "FIELD";
  		private const string ElemCustomFieldName = "NAME";
  		private const string ElemCustomFieldValue = "VALUE";
  
  		private const string AttribFormat = "FMT";
  
  		private const string FieldInfoText = "IDS_InformationText";
  
  		public override bool SupportsImport { get { return true; } }
  		public override bool SupportsExport { get { return false; } }
  
  		public override string FormatName { get { return "Password Depot XML"; } }
  		public override string DefaultExtension { get { return "xml"; } }
  		public override string ApplicationGroup { get { return KPRes.PasswordManagers; } }
  
  		public override Image SmallIcon
  		{
  			get { return KeePass.Properties.Resources.B16x16_Imp_PwDepot; }
  		}
  
  		public override void Import(PwDatabase pwStorage, Stream sInput,
  			IStatusLogger slLogger)
  		{
  			StreamReader sr = new StreamReader(sInput, StrUtil.Utf8);
  			string strData = sr.ReadToEnd();
  			sr.Close();
  
  			// Remove vertical tabulators
  			strData = strData.Replace("\u000B", string.Empty);
  
  			XmlDocument xmlDoc = new XmlDocument();
  			xmlDoc.LoadXml(strData);
  
  			XmlNode xmlRoot = xmlDoc.DocumentElement;
  
  			foreach(XmlNode xmlChild in xmlRoot.ChildNodes)
  			{
  				if(xmlChild.Name == ElemHeader) { } // Unsupported
  				else if(xmlChild.Name == ElemContainer)
  					ReadContainer(xmlChild, pwStorage);
  				else { Debug.Assert(false); }
  			}
  		}
  
  		private static void ReadContainer(XmlNode xmlNode, PwDatabase pwStorage)
  		{
  			foreach(XmlNode xmlChild in xmlNode.ChildNodes)
  			{
  				if(xmlChild.Name == ElemGroup)
  					ReadGroup(xmlChild, pwStorage.RootGroup, pwStorage);
  				else { Debug.Assert(false); }
  			}
  		}
  
  		private static void ReadGroup(XmlNode xmlNode, PwGroup pgParent, PwDatabase pwStorage)
  		{
  			PwGroup pg = new PwGroup(true, true);
  			pgParent.AddGroup(pg, true);
  
  			try
  			{
  				XmlAttributeCollection xac = xmlNode.Attributes;
  				pg.Name = xac.GetNamedItem(AttribGroupName).Value;
  			}
  			catch(Exception) { }
  
  			foreach(XmlNode xmlChild in xmlNode)
  			{
  				if(xmlChild.Name == ElemGroup)
  					ReadGroup(xmlChild, pg, pwStorage);
  				else if(xmlChild.Name == ElemEntry)
  					ReadEntry(xmlChild, pg, pwStorage);
  				else { Debug.Assert(false); }
  			}
  		}
  
  		private static void ReadEntry(XmlNode xmlNode, PwGroup pgParent,
  			PwDatabase pwStorage)
  		{
  			PwEntry pe = new PwEntry(true, true);
  			pgParent.AddEntry(pe, true);
  
  			DateTime? ndt;
  			foreach(XmlNode xmlChild in xmlNode)
  			{
  				if(xmlChild.Name == ElemEntryName)
  					pe.Strings.Set(PwDefs.TitleField, new ProtectedString(
  						pwStorage.MemoryProtection.ProtectTitle,
  						XmlUtil.SafeInnerText(xmlChild)));
  				else if(xmlChild.Name == ElemEntryUser)
  					pe.Strings.Set(PwDefs.UserNameField, new ProtectedString(
  						pwStorage.MemoryProtection.ProtectUserName,
  						XmlUtil.SafeInnerText(xmlChild)));
  				else if(xmlChild.Name == ElemEntryPassword)
  					pe.Strings.Set(PwDefs.PasswordField, new ProtectedString(
  						pwStorage.MemoryProtection.ProtectPassword,
  						XmlUtil.SafeInnerText(xmlChild)));
  				else if(xmlChild.Name == ElemEntryURL)
  					pe.Strings.Set(PwDefs.UrlField, new ProtectedString(
  						pwStorage.MemoryProtection.ProtectUrl,
  						XmlUtil.SafeInnerText(xmlChild)));
  				else if(xmlChild.Name == ElemEntryNotes)
  					pe.Strings.Set(PwDefs.NotesField, new ProtectedString(
  						pwStorage.MemoryProtection.ProtectNotes,
  						XmlUtil.SafeInnerText(xmlChild)));
  				else if(xmlChild.Name == ElemEntryLastModTime)
  				{
  					ndt = ReadTime(xmlChild);
  					if(ndt.HasValue) pe.LastModificationTime = ndt.Value;
  				}
  				else if(xmlChild.Name == ElemEntryExpireTime)
  				{
  					ndt = ReadTime(xmlChild);
  					if(ndt.HasValue)
  					{
  						pe.ExpiryTime = ndt.Value;
  						pe.Expires = true;
  					}
  				}
  				else if(xmlChild.Name == ElemEntryCreatedTime)
  				{
  					ndt = ReadTime(xmlChild);
  					if(ndt.HasValue) pe.CreationTime = ndt.Value;
  				}
  				else if(xmlChild.Name == ElemEntryLastAccTime)
  				{
  					ndt = ReadTime(xmlChild);
  					if(ndt.HasValue) pe.LastAccessTime = ndt.Value;
  				}
  				else if(xmlChild.Name == ElemEntryUsageCount)
  				{
  					ulong uUsageCount;
  					if(ulong.TryParse(XmlUtil.SafeInnerText(xmlChild), out uUsageCount))
  						pe.UsageCount = uUsageCount;
  				}
  				else if(xmlChild.Name == ElemEntryAutoType)
  					pe.AutoType.DefaultSequence = MapAutoType(
  						XmlUtil.SafeInnerText(xmlChild));
  				else if(xmlChild.Name == ElemEntryCustom)
  					ReadCustomContainer(xmlChild, pe);
  				else if(xmlChild.Name == ElemImageIndex)
  					pe.IconId = MapIcon(XmlUtil.SafeInnerText(xmlChild), true);
  				else if(Array.IndexOf<string>(ElemEntryUnsupportedItems,
  					xmlChild.Name) >= 0) { }
  
gt: 				else { Debug.Assert(false, xmlChild.Name); }