diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs b/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs index a5ef3c81..1ce77040 100644 --- a/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs +++ b/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs @@ -162,17 +162,6 @@ namespace KeePassLib.Serialization finally { CommonCleanUpRead(sSource, hashedStream); } } - public static void CopyStream(Stream input, Stream output) - { - byte[] buffer = new byte[4096]; - int read; - while ((read = input.Read(buffer, 0, buffer.Length)) > 0) - { - output.Write(buffer, 0, read); - } - output.Seek(0, SeekOrigin.Begin); - } - private void CommonCleanUpRead(Stream sSource, HashingStreamEx hashedStream) { hashedStream.Close(); diff --git a/src/Kp2aBusinessLogic/database/Database.cs b/src/Kp2aBusinessLogic/database/Database.cs index e939857c..4f24db31 100644 --- a/src/Kp2aBusinessLogic/database/Database.cs +++ b/src/Kp2aBusinessLogic/database/Database.cs @@ -94,7 +94,7 @@ namespace keepass2android } - public void LoadData(IKp2aApp app, IOConnectionInfo iocInfo, String password, String keyfile, ProgressDialogStatusLogger status) + public void LoadData(IKp2aApp app, IOConnectionInfo iocInfo, MemoryStream databaseData, String password, String keyfile, ProgressDialogStatusLogger status) { PwDatabase pwDatabase = new PwDatabase(); @@ -112,11 +112,12 @@ namespace keepass2android throw new KeyFileException(); } } - + + IFileStorage fileStorage = _app.GetFileStorage(iocInfo); + var filename = fileStorage.GetFilenameWithoutPathAndExt(iocInfo); try { - IFileStorage fileStorage = _app.GetFileStorage(iocInfo); - pwDatabase.Open(fileStorage.OpenFileForRead(iocInfo), fileStorage.GetFilenameWithoutPathAndExt(iocInfo), iocInfo, compositeKey, status); + pwDatabase.Open(databaseData, filename, iocInfo, compositeKey, status); } catch (Exception) { @@ -125,7 +126,8 @@ namespace keepass2android //if we don't get a password, we don't know whether this means "empty password" or "no password" //retry without password: compositeKey.RemoveUserKey(compositeKey.GetUserKey(typeof (KcpPassword))); - pwDatabase.Open(iocInfo, compositeKey, status); + databaseData.Seek(0, SeekOrigin.Begin); + pwDatabase.Open(databaseData, filename, iocInfo, compositeKey, status); } else throw; } diff --git a/src/Kp2aBusinessLogic/database/edit/LoadDB.cs b/src/Kp2aBusinessLogic/database/edit/LoadDB.cs index 239c04a9..11b6cb1c 100644 --- a/src/Kp2aBusinessLogic/database/edit/LoadDB.cs +++ b/src/Kp2aBusinessLogic/database/edit/LoadDB.cs @@ -16,21 +16,24 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; +using System.IO; using KeePassLib.Serialization; namespace keepass2android { public class LoadDb : RunnableOnFinish { private readonly IOConnectionInfo _ioc; + private readonly MemoryStream _databaseData; private readonly String _pass; private readonly String _key; private readonly IKp2aApp _app; private readonly bool _rememberKeyfile; - public LoadDb(IKp2aApp app, IOConnectionInfo ioc, String pass, String key, OnFinish finish): base(finish) + public LoadDb(IKp2aApp app, IOConnectionInfo ioc, MemoryStream databaseData, String pass, String key, OnFinish finish): base(finish) { _app = app; _ioc = ioc; + _databaseData = databaseData; _pass = pass; _key = key; @@ -44,7 +47,7 @@ namespace keepass2android try { StatusLogger.UpdateMessage(UiStringKey.loading_database); - _app.GetDb().LoadData (_app, _ioc, _pass, _key, StatusLogger); + _app.GetDb().LoadData (_app, _ioc, _databaseData, _pass, _key, StatusLogger); SaveFileData (_ioc, _key); } catch (KeyFileException) { diff --git a/src/keepass2android/PasswordActivity.cs b/src/keepass2android/PasswordActivity.cs index 21738fbb..cc82d3bd 100644 --- a/src/keepass2android/PasswordActivity.cs +++ b/src/keepass2android/PasswordActivity.cs @@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; +using System.Threading.Tasks; using Android.App; using Android.Content; using Android.OS; @@ -29,6 +30,9 @@ using Android.Text; using Android.Content.PM; using KeePassLib.Keys; using KeePassLib.Serialization; +using KeePassLib.Utility; + +using MemoryStream = System.IO.MemoryStream; namespace keepass2android { @@ -331,6 +335,9 @@ namespace keepass2android } } + // Create task to kick off file loading while the user enters the password + var loadDbTask = new Task(LoadDbFile); + AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent); SetContentView(Resource.Layout.password); @@ -364,7 +371,7 @@ namespace keepass2android App.Kp2a.GetDb().QuickUnlockKeyLength = int.Parse(_prefs.GetString(GetString(Resource.String.QuickUnlockLength_key), GetString(Resource.String.QuickUnlockLength_default))); Handler handler = new Handler(); - LoadDb task = new LoadDb(App.Kp2a, _ioConnection, pass, key, new AfterLoad(handler, this)); + LoadDb task = new LoadDb(App.Kp2a, _ioConnection, loadDbTask.Result, pass, key, new AfterLoad(handler, this)); ProgressTask pt = new ProgressTask(App.Kp2a, this, task); pt.Run(); }; @@ -439,7 +446,34 @@ namespace keepass2android RetrieveSettings(); + loadDbTask.Start(); + } + private MemoryStream LoadDbFile() + { + System.Diagnostics.Debug.WriteLine("LoadDbFile Started"); + var fileStorage = App.Kp2a.GetFileStorage(_ioConnection); + var stream = fileStorage.OpenFileForRead(_ioConnection); + + var memoryStream = stream as MemoryStream; + if (memoryStream == null) + { + // Read the file into memory + int capacity = 4096; // Default initial capacity, if stream can't report it. + if (stream.CanSeek) + { + capacity = (int)stream.Length; + System.Diagnostics.Debug.WriteLine("LoadDbFile, data size: " + capacity); + } + memoryStream = new MemoryStream(capacity); + MemUtil.CopyStream(stream, memoryStream); + stream.Close(); + memoryStream.Seek(0, System.IO.SeekOrigin.Begin); + } + + System.Diagnostics.Debug.WriteLine("LoadDbFile Done"); + + return memoryStream; } protected override void OnSaveInstanceState(Bundle outState)