Serialization to KeePass KDBX files.
Exemple #1
0
    public static void Main(string[] args)
    {
        CompositeKey key = new CompositeKey();
        KcpPassword pw = new KcpPassword("12345");
        key.AddUserKey(pw);
        byte[] pwdata = pw.KeyData.ReadData();
        Console.WriteLine("PW data:");
        Console.WriteLine(string.Join(",", pwdata.Select(x => "0x" + x.ToString("x"))));
        byte[] keydata = key.GenerateKey32(pwdata, 6000).ReadData();
        Console.WriteLine("Key data:");
        Console.WriteLine(string.Join(",", keydata.Select(x => "0x" + x.ToString("x"))));

        PwDatabase db = new PwDatabase();
        db.MasterKey = key;
        KdbxFile kdbx = new KdbxFile(db);
        kdbx.Load(@"..\resources\test.kdbx", KdbxFormat.Default, null);

        var groups = db.RootGroup.GetGroups(true);
        Console.WriteLine("Group count: " + groups.UCount);
        var entries = db.RootGroup.GetEntries(true);
        Console.WriteLine("Entry count: " + entries.UCount);

        CompositeKey key2 = new CompositeKey();
        key2.AddUserKey(pw);
        KcpKeyFile keyfile = new KcpKeyFile(@"..\resources\keyfile.key");
        key2.AddUserKey(keyfile);
        byte[] keyfiledata = keyfile.KeyData.ReadData();
        Console.WriteLine("Key file data:");
        Console.WriteLine(string.Join(",", keyfiledata.Select(x => "0x" + x.ToString("x"))));
        Console.WriteLine("Composite Key data:");
        byte[] key2data = key2.GenerateKey32(keyfiledata, 6000).ReadData();
        Console.WriteLine(string.Join(",", key2data.Select(x => "0x" + x.ToString("x"))));
    }
Exemple #2
0
		public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
			IStatusLogger slLogger)
		{
			KdbxFile kdbx = new KdbxFile(pwExportInfo.ContextDatabase);
			kdbx.Save(sOutput, pwExportInfo.DataGroup, KdbxFormat.Default, slLogger);
			return true;
		}
		public override void Import(PwDatabase pwStorage, Stream sInput,
			IStatusLogger slLogger)
		{
			KdbxFile kdbx = new KdbxFile(pwStorage);
			// CappedByteStream s = new CappedByteStream(sInput, 64);

			kdbx.RepairMode = true;

			try { kdbx.Load(sInput, KdbxFormat.Default, slLogger); }
			catch(Exception) { }
		}
		public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
			IStatusLogger slLogger)
		{
			PwDatabase pd = (pwExportInfo.ContextDatabase ?? new PwDatabase());

			PwObjectList<PwDeletedObject> vDel = null;
			if(!pwExportInfo.ExportDeletedObjects)
			{
				vDel = pd.DeletedObjects.CloneShallow();
				pd.DeletedObjects.Clear();
			}

			KdbxFile kdb = new KdbxFile(pd);
			kdb.Save(sOutput, pwExportInfo.DataGroup, KdbxFormat.PlainXml, slLogger);

			// Restore deleted objects list
			if(vDel != null) pd.DeletedObjects.Add(vDel);

			return true;
		}
Exemple #5
0
        public override void Import(PwDatabase pwStorage, Stream sInput,
			IStatusLogger slLogger)
        {
            KdbxFile kdbx = new KdbxFile(pwStorage);
            kdbx.Load(sInput, KdbxFormat.PlainXml, slLogger);
        }
Exemple #6
0
		private bool ExportEx(PwExportInfo pwExportInfo, Stream sOutput,
			IStatusLogger slLogger, string strXslFile)
		{
			XslCompiledTransform xsl = new XslCompiledTransform();

			try { xsl.Load(strXslFile); }
			catch(Exception exXsl)
			{
				throw new NotSupportedException(strXslFile + MessageService.NewParagraph +
					KPRes.NoXslFile + MessageService.NewParagraph + exXsl.Message);
			}

			MemoryStream msDataXml = new MemoryStream();

			PwDatabase pd = (pwExportInfo.ContextDatabase ?? new PwDatabase());
			KdbxFile kdb = new KdbxFile(pd);
			kdb.Save(msDataXml, pwExportInfo.DataGroup, KdbxFormat.PlainXml, slLogger);

			byte[] pbData = msDataXml.ToArray();
			msDataXml.Close();
			MemoryStream msDataRead = new MemoryStream(pbData, false);
			XmlReader xmlDataReader = XmlReader.Create(msDataRead);

			XmlWriterSettings xws = new XmlWriterSettings();
			xws.CheckCharacters = false;
			xws.Encoding = new UTF8Encoding(false);
			xws.NewLineChars = MessageService.NewLine;
			xws.NewLineHandling = NewLineHandling.None;
			xws.OmitXmlDeclaration = true;
			xws.ConformanceLevel = ConformanceLevel.Auto;

			XmlWriter xmlWriter = XmlWriter.Create(sOutput, xws);
			xsl.Transform(xmlDataReader, xmlWriter);
			xmlWriter.Close();
			xmlDataReader.Close();
			msDataRead.Close();

			Array.Clear(pbData, 0, pbData.Length);
			return true;
		}
Exemple #7
0
        public static bool WriteEntries(Stream msOutput, PwDatabase pdContext,
                                        PwEntry[] vEntries)
        {
            if (msOutput == null)
            {
                Debug.Assert(false); return(false);
            }
            // pdContext may be null
            if (vEntries == null)
            {
                Debug.Assert(false); return(false);
            }

            /* KdbxFile f = new KdbxFile(pwDatabase);
             * f.m_format = KdbxFormat.PlainXml;
             *
             * XmlTextWriter xtw = null;
             * try { xtw = new XmlTextWriter(msOutput, StrUtil.Utf8); }
             * catch(Exception) { Debug.Assert(false); return false; }
             * if(xtw == null) { Debug.Assert(false); return false; }
             *
             * f.m_xmlWriter = xtw;
             *
             * xtw.Formatting = Formatting.Indented;
             * xtw.IndentChar = '\t';
             * xtw.Indentation = 1;
             *
             * xtw.WriteStartDocument(true);
             * xtw.WriteStartElement(ElemRoot);
             *
             * foreach(PwEntry pe in vEntries)
             *      f.WriteEntry(pe, false);
             *
             * xtw.WriteEndElement();
             * xtw.WriteEndDocument();
             *
             * xtw.Flush();
             * xtw.Close();
             * return true; */

            PwDatabase pd = new PwDatabase();

            pd.New(new IOConnectionInfo(), new CompositeKey());

            PwGroup pg = pd.RootGroup;

            if (pg == null)
            {
                Debug.Assert(false); return(false);
            }

            foreach (PwEntry pe in vEntries)
            {
                PwUuid pu = pe.CustomIconUuid;
                if (!pu.Equals(PwUuid.Zero) && (pd.GetCustomIconIndex(pu) < 0))
                {
                    int i = -1;
                    if (pdContext != null)
                    {
                        i = pdContext.GetCustomIconIndex(pu);
                    }
                    if (i >= 0)
                    {
                        PwCustomIcon ci = pdContext.CustomIcons[i];
                        pd.CustomIcons.Add(ci);
                    }
                    else
                    {
                        Debug.Assert(pdContext == null);
                    }
                }

                PwEntry peCopy = pe.CloneDeep();
                pg.AddEntry(peCopy, true);
            }

            KdbxFile f = new KdbxFile(pd);

            f.Save(msOutput, null, KdbxFormat.PlainXml, null);
            return(true);
        }
		private bool ExportEx(PwExportInfo pwExportInfo, Stream sOutput,
			IStatusLogger slLogger, string strXslFile)
		{
			XslCompiledTransform xsl = new XslCompiledTransform();
			try { xsl.Load(strXslFile); }
			catch(Exception exXsl)
			{
				throw new NotSupportedException(strXslFile + MessageService.NewParagraph +
					KPRes.NoXslFile + MessageService.NewParagraph + exXsl.Message);
			}

			byte[] pbData;
			using(MemoryStream ms = new MemoryStream())
			{
				PwDatabase pd = (pwExportInfo.ContextDatabase ?? new PwDatabase());
				KdbxFile f = new KdbxFile(pd);
				f.Save(ms, pwExportInfo.DataGroup, KdbxFormat.PlainXml, slLogger);

				pbData = ms.ToArray();
			}
			if(pbData == null) throw new OutOfMemoryException();

			XmlWriterSettings xws = xsl.OutputSettings;
			if(xws == null)
			{
				xws = new XmlWriterSettings();

				xws.CheckCharacters = false;
				xws.ConformanceLevel = ConformanceLevel.Auto;
				xws.Encoding = StrUtil.Utf8;
				// xws.Indent = false;
				xws.IndentChars = "\t";
				xws.NewLineChars = MessageService.NewLine;
				xws.NewLineHandling = NewLineHandling.None;
				xws.OmitXmlDeclaration = true;
			}

			using(MemoryStream msIn = new MemoryStream(pbData, false))
			{
				using(XmlReader xrIn = XmlReader.Create(msIn))
				{
					using(XmlWriter xwOut = XmlWriter.Create(sOutput, xws))
					{
						xsl.Transform(xrIn, xwOut);
					}
				}
			}

			MemUtil.ZeroByteArray(pbData);
			return true;
		}
		private static void PerformXmlReplace(PwDatabase pd, XmlReplaceOptions opt,
			IStatusLogger sl)
		{
			if(opt.SelectNodesXPath.Length == 0) return;
			if(opt.Operation == XmlReplaceOp.None) return;

			bool bRemove = (opt.Operation == XmlReplaceOp.RemoveNodes);
			bool bReplace = (opt.Operation == XmlReplaceOp.ReplaceData);
			bool bMatchCase = ((opt.Flags & XmlReplaceFlags.CaseSensitive) != XmlReplaceFlags.None);
			bool bRegex = ((opt.Flags & XmlReplaceFlags.Regex) != XmlReplaceFlags.None);

			Regex rxFind = null;
			if(bReplace && bRegex)
				rxFind = new Regex(opt.FindText, (bMatchCase ? RegexOptions.None :
					RegexOptions.IgnoreCase));

			EnsureStandardFieldsExist(pd);

			KdbxFile kdbxOrg = new KdbxFile(pd);
			MemoryStream msOrg = new MemoryStream();
			kdbxOrg.Save(msOrg, null, KdbxFormat.PlainXml, sl);
			byte[] pbXml = msOrg.ToArray();
			msOrg.Close();
			string strXml = StrUtil.Utf8.GetString(pbXml);

			XmlDocument xd = new XmlDocument();
			xd.LoadXml(strXml);

			XPathNavigator xpNavRoot = xd.CreateNavigator();
			XPathNodeIterator xpIt = xpNavRoot.Select(opt.SelectNodesXPath);

			// XPathNavigators must be cloned to make them independent
			List<XPathNavigator> lNodes = new List<XPathNavigator>();
			while(xpIt.MoveNext()) lNodes.Add(xpIt.Current.Clone());

			if(lNodes.Count == 0) return;

			for(int i = lNodes.Count - 1; i >= 0; --i)
			{
				if((sl != null) && !sl.ContinueWork()) return;

				XPathNavigator xpNav = lNodes[i];

				if(bRemove) xpNav.DeleteSelf();
				else if(bReplace) ApplyReplace(xpNav, opt, rxFind);
				else { Debug.Assert(false); } // Unknown action
			}

			MemoryStream msMod = new MemoryStream();
			XmlWriterSettings xws = new XmlWriterSettings();
			xws.Encoding = StrUtil.Utf8;
			xws.Indent = true;
			xws.IndentChars = "\t";
			XmlWriter xw = XmlWriter.Create(msMod, xws);
			xd.Save(xw);

			byte[] pbMod = msMod.ToArray();
			msMod.Close();

			PwDatabase pdMod = new PwDatabase();
			msMod = new MemoryStream(pbMod, false);
			try
			{
				KdbxFile kdbxMod = new KdbxFile(pdMod);
				kdbxMod.Load(msMod, KdbxFormat.PlainXml, sl);
			}
			catch(Exception)
			{
				throw new Exception(KPRes.XmlModInvalid + MessageService.NewParagraph +
					KPRes.OpAborted + MessageService.NewParagraph +
					KPRes.DbNoModBy.Replace(@"{PARAM}", @"'" + KPRes.XmlReplace + @"'"));
			}
			finally { msMod.Close(); }

			PrepareModDbForMerge(pdMod, pd);

			pd.Modified = true;
			pd.UINeedsIconUpdate = true;
			pd.MergeIn(pdMod, PwMergeMethod.Synchronize, sl);
		}
Exemple #10
0
        /// <summary>
        /// Read entries from a stream.
        /// </summary>
        /// <param name="msData">Input stream to read the entries from.</param>
        /// <param name="pdContext">Context database (e.g. for storing icons).</param>
        /// <param name="bCopyIcons">If <c>true</c>, custom icons required by
        /// the loaded entries are copied to the context database.</param>
        /// <returns>Loaded entries.</returns>
        public static List <PwEntry> ReadEntries(Stream msData, PwDatabase pdContext,
                                                 bool bCopyIcons)
        {
            List <PwEntry> lEntries = new List <PwEntry>();

            if (msData == null)
            {
                Debug.Assert(false); return(lEntries);
            }
            // pdContext may be null

            /* KdbxFile f = new KdbxFile(pwDatabase);
             * f.m_format = KdbxFormat.PlainXml;
             *
             * XmlDocument doc = XmlUtilEx.CreateXmlDocument();
             * doc.Load(msData);
             *
             * XmlElement el = doc.DocumentElement;
             * if(el.Name != ElemRoot) throw new FormatException();
             *
             * List<PwEntry> vEntries = new List<PwEntry>();
             *
             * foreach(XmlNode xmlChild in el.ChildNodes)
             * {
             *      if(xmlChild.Name == ElemEntry)
             *      {
             *              PwEntry pe = f.ReadEntry(xmlChild);
             *              pe.Uuid = new PwUuid(true);
             *
             *              foreach(PwEntry peHistory in pe.History)
             *                      peHistory.Uuid = pe.Uuid;
             *
             *              vEntries.Add(pe);
             *      }
             *      else { Debug.Assert(false); }
             * }
             *
             * return vEntries; */

            PwDatabase pd = new PwDatabase();

            pd.New(new IOConnectionInfo(), new CompositeKey());

            KdbxFile f = new KdbxFile(pd);

            f.Load(msData, KdbxFormat.PlainXml, null);

            foreach (PwEntry pe in pd.RootGroup.Entries)
            {
                pe.SetUuid(new PwUuid(true), true);
                lEntries.Add(pe);

                if (bCopyIcons && (pdContext != null))
                {
                    PwUuid pu = pe.CustomIconUuid;
                    if (!pu.Equals(PwUuid.Zero))
                    {
                        int iSrc = pd.GetCustomIconIndex(pu);
                        int iDst = pdContext.GetCustomIconIndex(pu);

                        if (iSrc < 0)
                        {
                            Debug.Assert(false);
                        }
                        else if (iDst < 0)
                        {
                            pdContext.CustomIcons.Add(pd.CustomIcons[iSrc]);

                            pdContext.Modified          = true;
                            pdContext.UINeedsIconUpdate = true;
                        }
                    }
                }
            }

            return(lEntries);
        }
		public static bool WriteEntries(Stream msOutput, PwDatabase pdContext,
			PwEntry[] vEntries)
		{
			if(msOutput == null) { Debug.Assert(false); return false; }
			// pdContext may be null
			if(vEntries == null) { Debug.Assert(false); return false; }

			/* KdbxFile f = new KdbxFile(pwDatabase);
			f.m_format = KdbxFormat.PlainXml;

			XmlTextWriter xtw = null;
			try { xtw = new XmlTextWriter(msOutput, StrUtil.Utf8); }
			catch(Exception) { Debug.Assert(false); return false; }
			if(xtw == null) { Debug.Assert(false); return false; }

			f.m_xmlWriter = xtw;

			xtw.Formatting = Formatting.Indented;
			xtw.IndentChar = '\t';
			xtw.Indentation = 1;

			xtw.WriteStartDocument(true);
			xtw.WriteStartElement(ElemRoot);

			foreach(PwEntry pe in vEntries)
				f.WriteEntry(pe, false);

			xtw.WriteEndElement();
			xtw.WriteEndDocument();

			xtw.Flush();
			xtw.Close();
			return true; */

			PwDatabase pd = new PwDatabase();
			pd.New(new IOConnectionInfo(), new CompositeKey());

			PwGroup pg = pd.RootGroup;
			if(pg == null) { Debug.Assert(false); return false; }

			foreach(PwEntry pe in vEntries)
			{
				PwUuid pu = pe.CustomIconUuid;
				if(!pu.Equals(PwUuid.Zero) && (pd.GetCustomIconIndex(pu) < 0))
				{
					int i = -1;
					if(pdContext != null) i = pdContext.GetCustomIconIndex(pu);
					if(i >= 0)
					{
						PwCustomIcon ci = pdContext.CustomIcons[i];
						pd.CustomIcons.Add(ci);
					}
					else { Debug.Assert(pdContext == null); }
				}

				PwEntry peCopy = pe.CloneDeep();
				pg.AddEntry(peCopy, true);
			}

			KdbxFile f = new KdbxFile(pd);
			f.Save(msOutput, null, KdbxFormat.PlainXml, null);
			return true;
		}
Exemple #12
0
        public void PopulateDatabaseFromStream(PwDatabase db, Stream s, IStatusLogger slLogger)
        {
            KdbxFile kdbx = new KdbxFile(db);
            kdbx.DetachBinaries = db.DetachBinaries;

            kdbx.Load(s, _format, slLogger);
            HashOfLastStream = kdbx.HashOfFileOnDisk;
            s.Close();
        }
		public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
			IStatusLogger slLogger)
		{
			PwDatabase pd = pwExportInfo.ContextDatabase;
			PwGroup pgRoot = pwExportInfo.DataGroup;

			// Remove everything that requires KDBX 4 or higher;
			// see also KdbxFile.GetMinKdbxVersion

			KdfParameters pKdf = pd.KdfParameters;
			AesKdf kdfAes = new AesKdf();
			if(!kdfAes.Uuid.Equals(pKdf.KdfUuid))
				pd.KdfParameters = kdfAes.GetDefaultParameters();

			VariantDictionary vdPublic = pd.PublicCustomData;
			pd.PublicCustomData = new VariantDictionary();

			List<PwGroup> lCustomGK = new List<PwGroup>();
			List<StringDictionaryEx> lCustomGV = new List<StringDictionaryEx>();
			List<PwEntry> lCustomEK = new List<PwEntry>();
			List<StringDictionaryEx> lCustomEV = new List<StringDictionaryEx>();

			GroupHandler gh = delegate(PwGroup pg)
			{
				if(pg == null) { Debug.Assert(false); return true; }
				if(pg.CustomData.Count > 0)
				{
					lCustomGK.Add(pg);
					lCustomGV.Add(pg.CustomData);
					pg.CustomData = new StringDictionaryEx();
				}
				return true;
			};
			EntryHandler eh = delegate(PwEntry pe)
			{
				if(pe == null) { Debug.Assert(false); return true; }
				if(pe.CustomData.Count > 0)
				{
					lCustomEK.Add(pe);
					lCustomEV.Add(pe.CustomData);
					pe.CustomData = new StringDictionaryEx();
				}
				return true;
			};

			gh(pgRoot);
			pgRoot.TraverseTree(TraversalMethod.PreOrder, gh, eh);

			try
			{
				KdbxFile kdbx = new KdbxFile(pd);
				kdbx.ForceVersion = KdbxFile.FileVersion32_3;
				kdbx.Save(sOutput, pgRoot, KdbxFormat.Default, slLogger);
			}
			finally
			{
				// Restore

				pd.KdfParameters = pKdf;
				pd.PublicCustomData = vdPublic;

				for(int i = 0; i < lCustomGK.Count; ++i)
					lCustomGK[i].CustomData = lCustomGV[i];
				for(int i = 0; i < lCustomEK.Count; ++i)
					lCustomEK[i].CustomData = lCustomEV[i];
			}

			return true;
		}
Exemple #14
0
 private static string DatabaseToXml(IKp2aApp app)
 {
     KdbxFile kdb = new KdbxFile(app.GetDb().KpDatabase);
     var sOutput = new OnCloseToStringMemoryStream();
     kdb.Save(sOutput, app.GetDb().KpDatabase.RootGroup, KdbxFormat.PlainXml, null);
     return sOutput.Text;
 }
Exemple #15
0
        public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
            IStatusLogger slLogger)
        {
            string strFilter = UIUtil.CreateFileTypeFilter("xsl", KPRes.XslFileType, true);
            OpenFileDialogEx dlgXsl = UIUtil.CreateOpenFileDialog(KPRes.XslSelectFile,
                strFilter, 1, "xsl", false, AppDefs.FileDialogContext.Xsl);

            if(dlgXsl.ShowDialog() != DialogResult.OK) return false;

            string strXslFile = dlgXsl.FileName;
            XslCompiledTransform xsl = new XslCompiledTransform();

            try { xsl.Load(strXslFile); }
            catch(Exception exXsl)
            {
                throw new NotSupportedException(strXslFile + MessageService.NewParagraph +
                    KPRes.NoXslFile + MessageService.NewParagraph + exXsl.Message);
            }

            MemoryStream msDataXml = new MemoryStream();

            PwDatabase pd = (pwExportInfo.ContextDatabase ?? new PwDatabase());
            KdbxFile kdb = new KdbxFile(pd);
            kdb.Save(msDataXml, pwExportInfo.DataGroup, KdbxFormat.PlainXml, slLogger);

            byte[] pbData = msDataXml.ToArray();
            msDataXml.Close();
            MemoryStream msDataRead = new MemoryStream(pbData, false);
            XmlReader xmlDataReader = XmlReader.Create(msDataRead);

            XmlWriterSettings xws = new XmlWriterSettings();
            xws.CheckCharacters = false;
            xws.Encoding = new UTF8Encoding(false);
            xws.NewLineChars = MessageService.NewLine;
            xws.NewLineHandling = NewLineHandling.None;
            xws.OmitXmlDeclaration = true;
            xws.ConformanceLevel = ConformanceLevel.Auto;

            XmlWriter xmlWriter = XmlWriter.Create(sOutput, xws);
            xsl.Transform(xmlDataReader, xmlWriter);
            xmlWriter.Close();
            xmlDataReader.Close();
            msDataRead.Close();

            Array.Clear(pbData, 0, pbData.Length);
            return true;
        }
Exemple #16
0
        /// <summary>
        /// Write entries to a stream.
        /// </summary>
        /// <param name="msOutput">Output stream to which the entries will be written.</param>
        /// <param name="vEntries">Entries to serialize.</param>
        /// <returns>Returns <c>true</c>, if the entries were written successfully
        /// to the stream.</returns>
        public static bool WriteEntries(Stream msOutput, PwEntry[] vEntries)
        {
            /* KdbxFile f = new KdbxFile(pwDatabase);
            f.m_format = KdbxFormat.PlainXml;

            XmlTextWriter xtw = null;
            try { xtw = new XmlTextWriter(msOutput, StrUtil.Utf8); }
            catch(Exception) { Debug.Assert(false); return false; }
            if(xtw == null) { Debug.Assert(false); return false; }

            f.m_xmlWriter = xtw;

            xtw.Formatting = Formatting.Indented;
            xtw.IndentChar = '\t';
            xtw.Indentation = 1;

            xtw.WriteStartDocument(true);
            xtw.WriteStartElement(ElemRoot);

            foreach(PwEntry pe in vEntries)
                f.WriteEntry(pe, false);

            xtw.WriteEndElement();
            xtw.WriteEndDocument();

            xtw.Flush();
            xtw.Close();
            return true; */

            PwDatabase pd = new PwDatabase();
            pd.New(new IOConnectionInfo(), new CompositeKey());

            foreach(PwEntry peCopy in vEntries)
                pd.RootGroup.AddEntry(peCopy.CloneDeep(), true);

            KdbxFile f = new KdbxFile(pd);
            f.Save(msOutput, null, KdbxFormat.PlainXml, null);
            return true;
        }
Exemple #17
0
        /// <summary>
        /// Read entries from a stream.
        /// </summary>
        /// <param name="msData">Input stream to read the entries from.</param>
        /// <returns>Extracted entries.</returns>
        public static List<PwEntry> ReadEntries(Stream msData)
        {
            /* KdbxFile f = new KdbxFile(pwDatabase);
            f.m_format = KdbxFormat.PlainXml;

            XmlDocument doc = new XmlDocument();
            doc.Load(msData);

            XmlElement el = doc.DocumentElement;
            if(el.Name != ElemRoot) throw new FormatException();

            List<PwEntry> vEntries = new List<PwEntry>();

            foreach(XmlNode xmlChild in el.ChildNodes)
            {
                if(xmlChild.Name == ElemEntry)
                {
                    PwEntry pe = f.ReadEntry(xmlChild);
                    pe.Uuid = new PwUuid(true);

                    foreach(PwEntry peHistory in pe.History)
                        peHistory.Uuid = pe.Uuid;

                    vEntries.Add(pe);
                }
                else { Debug.Assert(false); }
            }

            return vEntries; */

            PwDatabase pd = new PwDatabase();
            KdbxFile f = new KdbxFile(pd);
            f.Load(msData, KdbxFormat.PlainXml, null);

            List<PwEntry> vEntries = new List<PwEntry>();
            foreach(PwEntry pe in pd.RootGroup.Entries)
            {
                pe.SetUuid(new PwUuid(true), true);
                vEntries.Add(pe);
            }

            return vEntries;
        }
		/// <summary>
		/// Read entries from a stream.
		/// </summary>
		/// <param name="msData">Input stream to read the entries from.</param>
		/// <param name="pdContext">Context database (e.g. for storing icons).</param>
		/// <param name="bCopyIcons">If <c>true</c>, custom icons required by
		/// the loaded entries are copied to the context database.</param>
		/// <returns>Loaded entries.</returns>
		public static List<PwEntry> ReadEntries(Stream msData, PwDatabase pdContext,
			bool bCopyIcons)
		{
			List<PwEntry> lEntries = new List<PwEntry>();

			if(msData == null) { Debug.Assert(false); return lEntries; }
			// pdContext may be null

			/* KdbxFile f = new KdbxFile(pwDatabase);
			f.m_format = KdbxFormat.PlainXml;

			XmlDocument doc = new XmlDocument();
			doc.Load(msData);

			XmlElement el = doc.DocumentElement;
			if(el.Name != ElemRoot) throw new FormatException();

			List<PwEntry> vEntries = new List<PwEntry>();

			foreach(XmlNode xmlChild in el.ChildNodes)
			{
				if(xmlChild.Name == ElemEntry)
				{
					PwEntry pe = f.ReadEntry(xmlChild);
					pe.Uuid = new PwUuid(true);

					foreach(PwEntry peHistory in pe.History)
						peHistory.Uuid = pe.Uuid;

					vEntries.Add(pe);
				}
				else { Debug.Assert(false); }
			}

			return vEntries; */

			PwDatabase pd = new PwDatabase();
			pd.New(new IOConnectionInfo(), new CompositeKey());

			KdbxFile f = new KdbxFile(pd);
			f.Load(msData, KdbxFormat.PlainXml, null);

			foreach(PwEntry pe in pd.RootGroup.Entries)
			{
				pe.SetUuid(new PwUuid(true), true);
				lEntries.Add(pe);

				if(bCopyIcons && (pdContext != null))
				{
					PwUuid pu = pe.CustomIconUuid;
					if(!pu.Equals(PwUuid.Zero))
					{
						int iSrc = pd.GetCustomIconIndex(pu);
						int iDst = pdContext.GetCustomIconIndex(pu);

						if(iSrc < 0) { Debug.Assert(false); }
						else if(iDst < 0)
						{
							pdContext.CustomIcons.Add(pd.CustomIcons[iSrc]);

							pdContext.Modified = true;
							pdContext.UINeedsIconUpdate = true;
						}
					}
				}
			}

			return lEntries;
		}