diff --git a/src/KeePassLib2Android/PwDatabase.cs b/src/KeePassLib2Android/PwDatabase.cs
index 925ab468..425c65ec 100644
--- a/src/KeePassLib2Android/PwDatabase.cs
+++ b/src/KeePassLib2Android/PwDatabase.cs
@@ -588,7 +588,7 @@ namespace KeePassLib
kdbx.DetachBinaries = m_strDetachBins;
Stream s = IOConnection.OpenRead(ioSource);
- kdbx.Load(s, KdbxFormat.Default, slLogger);
+ kdbx.Load(s, KdbpFile.GetFormatToUse(ioSource), slLogger);
s.Close();
m_pbHashOfLastIO = kdbx.HashOfFileOnDisk;
@@ -623,7 +623,7 @@ namespace KeePassLib
Stream s = ft.OpenWrite();
KdbxFile kdb = new KdbxFile(this);
- kdb.Save(s, null, KdbxFormat.Default, slLogger);
+ kdb.Save(s, null, KdbpFile.GetFormatToUse(m_ioSource), slLogger);
ft.CommitWrite();
diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs b/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs
index 4eff0c4a..236fe138 100644
--- a/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs
+++ b/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs
@@ -82,7 +82,7 @@ namespace KeePassLib.Serialization
BinaryReaderEx brDecrypted = null;
Stream readerStream = null;
- if(kdbFormat == KdbxFormat.Default)
+ if(kdbFormat == KdbxFormat.Default || kdbFormat == KdbxFormat.ProtocolBuffers)
{
br = new BinaryReaderEx(hashedStream, encNoBom, KLRes.FileCorrupted);
ReadHeader(br);
@@ -127,34 +127,21 @@ namespace KeePassLib.Serialization
}
else m_randomStream = null; // No random stream for plain-text files
- // Test: read to memory
var stopWatch = Stopwatch.StartNew();
- var memStream = new MemoryStream((int)hashedStream.Length);
- CopyStream(readerStream, memStream);
- readerStream.Close();
- readerStream = memStream;
- System.Diagnostics.Debug.WriteLine(String.Format("Copy input stream: {0}ms", stopWatch.ElapsedMilliseconds));
- var isXml = memStream.ReadByte() == '<';
- memStream.Seek(0, SeekOrigin.Begin);
-
- if (isXml)
+ if (kdbFormat == KdbxFormat.ProtocolBuffers)
{
- stopWatch.Restart();
-
- ReadXmlStreamed(readerStream, hashedStream);
- System.Diagnostics.Debug.WriteLine(String.Format("ReadXmlStreamed: {0}ms", stopWatch.ElapsedMilliseconds));
-
- }
- else
- {
- stopWatch.Restart();
-
KdbpFile.ReadDocument(m_pwDatabase, readerStream, m_pbProtectedStreamKey, m_pbHashOfHeader);
System.Diagnostics.Debug.WriteLine(String.Format("KdbpFile.ReadDocument: {0}ms", stopWatch.ElapsedMilliseconds));
}
+ else
+ {
+ ReadXmlStreamed(readerStream, hashedStream);
+
+ System.Diagnostics.Debug.WriteLine(String.Format("ReadXmlStreamed: {0}ms", stopWatch.ElapsedMilliseconds));
+ }
readerStream.Close();
// GC.KeepAlive(br);
diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs b/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs
index fbc31e6c..3d2ba9f4 100644
--- a/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs
+++ b/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs
@@ -101,7 +101,7 @@ namespace KeePassLib.Serialization
m_pbStreamStartBytes = cr.GetRandomBytes(32);
Stream writerStream;
- if(m_format == KdbxFormat.Default)
+ if(m_format == KdbxFormat.Default || m_format == KdbxFormat.ProtocolBuffers)
{
WriteHeader(hashedStream); // Also flushes the stream
@@ -122,17 +122,24 @@ namespace KeePassLib.Serialization
writerStream = hashedStream;
else { Debug.Assert(false); throw new FormatException("KdbFormat"); }
- /*
- m_xmlWriter = new XmlTextWriter(writerStream, encNoBom);
- WriteDocument(pgDataSource);
+ var stopWatch = Stopwatch.StartNew();
- m_xmlWriter.Flush();
- m_xmlWriter.Close();
- */
+ if (m_format == KdbxFormat.ProtocolBuffers)
+ {
+ KdbpFile.WriteDocument(m_pwDatabase, writerStream, m_pbProtectedStreamKey, m_pbHashOfHeader);
+ }
+ else
+ {
+ m_xmlWriter = new XmlTextWriter(writerStream, encNoBom);
+ WriteDocument(pgDataSource);
- KdbpFile.WriteDocument(m_pwDatabase, writerStream, m_pbProtectedStreamKey, m_pbHashOfHeader);
+ m_xmlWriter.Flush();
+ m_xmlWriter.Close();
+ }
writerStream.Close();
+
+ System.Diagnostics.Debug.WriteLine(String.Format("{1}: {0}ms", stopWatch.ElapsedMilliseconds, m_format == KdbxFormat.ProtocolBuffers ? "KdbpFile.WriteDocument" : "Xml WriteDocument"));
}
finally { CommonCleanUpWrite(sSaveTo, hashedStream); }
}
diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.cs b/src/KeePassLib2Android/Serialization/KdbxFile.cs
index b1cd287a..9fc980f8 100644
--- a/src/KeePassLib2Android/Serialization/KdbxFile.cs
+++ b/src/KeePassLib2Android/Serialization/KdbxFile.cs
@@ -52,7 +52,8 @@ namespace KeePassLib.Serialization
///
/// Use this flag when exporting data to a plain-text XML file.
///
- PlainXml
+ PlainXml,
+ ProtocolBuffers
}
///
diff --git a/src/KeePassLib2Android/Serialization/ProtoBuf/KdbpFile.cs b/src/KeePassLib2Android/Serialization/ProtoBuf/KdbpFile.cs
index 326d391b..a5827357 100644
--- a/src/KeePassLib2Android/Serialization/ProtoBuf/KdbpFile.cs
+++ b/src/KeePassLib2Android/Serialization/ProtoBuf/KdbpFile.cs
@@ -1,18 +1,29 @@
using System;
using System.Collections.Generic;
-using System.Text;
-using ProtoBuf;
using System.Drawing;
-using KeePassLib.Collections;
-using KeePassLib.Security;
-using KeePassLib.Cryptography;
using System.IO;
+using KeePassLib.Collections;
+using KeePassLib.Cryptography;
+using KeePassLib.Security;
+using KeePassLib.Utility;
+using ProtoBuf;
using ProtoBuf.Meta;
namespace KeePassLib.Serialization
{
internal class KdbpFile
{
+ public const string FileNameExtension = "kdbp";
+
+ ///
+ /// Determines whether the database pointed to by the specified ioc should be (de)serialised in default (xml) or protocol buffers format.
+ ///
+ public static KdbxFormat GetFormatToUse(IOConnectionInfo ioc)
+ {
+ // If the filename ends in .kdbp, use ProtocolBuffers format.
+ return UrlUtil.GetExtension(UrlUtil.GetFileName(ioc.Path)).Equals(KdbpFile.FileNameExtension, StringComparison.OrdinalIgnoreCase) ? KdbxFormat.ProtocolBuffers : KdbxFormat.Default;
+ }
+
public static void WriteDocument(PwDatabase database, Stream stream, byte[] protectedStreamKey, byte[] hashOfHeader)
{
var context = new SerializationContext