From c63302ef5e7c5af0ea32e25cc3c4c44e4fecdcbe Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Wed, 14 Aug 2013 06:05:25 +0200 Subject: [PATCH] * CachingFileStorage: Added more callbacks to provide user with more information what's going on * Changed TestCacheSupervisor for easier use of the many callbacks * Adapted tests for new callbacks * GroupBaseActivity: Added sync menu command * Preferences: Added option to enable/disable offline caching * App: don't lock database when user wants to reload. This is done in PasswordActivity and should be done there after the password was filled into the pw field * CheckDatabaseForChanges.cs: used when syncing a non-cached database --- .../Io/CachingFileStorage.cs | 39 +- .../Kp2aBusinessLogic.csproj | 1 + src/Kp2aBusinessLogic/UiStringKey.cs | 4 +- .../database/CheckDatabaseForChanges.cs | 74 + src/Kp2aBusinessLogic/database/edit/LoadDB.cs | 5 +- .../Kp2aKeyboardBinding.csproj | 4 +- src/Kp2aUnitTests/MainActivity.cs | 2 +- src/Kp2aUnitTests/TestBase.cs | 2 +- src/Kp2aUnitTests/TestCacheSupervisor.cs | 61 +- src/Kp2aUnitTests/TestCachingFileStorage.cs | 49 +- src/Kp2aUnitTests/TestKp2aApp.cs | 13 + src/Kp2aUnitTests/TestLoadDb.cs | 10 +- src/Kp2aUnitTests/TestSaveDbCached.cs | 18 +- .../TestSynchronizeCachedDatabase.cs | 16 +- src/keepass2android/GroupBaseActivity.cs | 39 +- .../Resources/Resource.designer.cs | 1484 +++++++++-------- .../Resources/menu-v11/group.xml | 15 +- src/keepass2android/Resources/menu/group.xml | 7 +- .../Resources/values/config.xml | 1 + .../Resources/values/strings.xml | 23 +- .../Resources/xml/preferences.xml | 8 + src/keepass2android/app/App.cs | 50 +- .../settings/AppSettingsActivity.cs | 42 + 23 files changed, 1174 insertions(+), 793 deletions(-) create mode 100644 src/Kp2aBusinessLogic/database/CheckDatabaseForChanges.cs diff --git a/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs b/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs index 668d6892..c418844c 100644 --- a/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs @@ -27,12 +27,29 @@ namespace keepass2android.Io /// void CouldntOpenFromRemote(IOConnectionInfo ioc, Exception ex); + /// + /// Called when the local file either didn't exist or was unmodified, so the remote file + /// was loaded and the cache was updated during the load operation. + /// + void UpdatedCachedFileOnLoad(IOConnectionInfo ioc); + + /// + /// Called when the remote file either didn't exist or was unmodified, so the local file + /// was loaded and the remote file was updated during the load operation. + /// + void UpdatedRemoteFileOnLoad(IOConnectionInfo ioc); + /// /// Called to notify the supervisor that the file described by ioc is opened from the cache because there's a conflict /// with local and remote changes /// /// void NotifyOpenFromLocalDueToConflict(IOConnectionInfo ioc); + + /// + /// Called when the load operation was performed and the remote file was identical with the local file + /// + void LoadedFromRemoteInSync(IOConnectionInfo ioc); } /// @@ -148,7 +165,8 @@ namespace keepass2android.Io //no changes in remote file -> upload using (Stream localData = File.OpenRead(CachedFilePath(ioc))) { - TryUpdateRemoteFile(localData, ioc, true, hash); + if (TryUpdateRemoteFile(localData, ioc, true, hash)) + _cacheSupervisor.UpdatedRemoteFileOnLoad(ioc); } } else @@ -197,20 +215,34 @@ namespace keepass2android.Io cachedFile.Close(); fileHash = MemUtil.ByteArrayToHexString(cachedFile.Hash); } + + //remember current hash + string previousHash = null; + string baseVersionFilePath = BaseVersionFilePath(ioc); + if (File.Exists(baseVersionFilePath)) + previousHash = File.ReadAllText(baseVersionFilePath); + //save hash in cache files: File.WriteAllText(VersionFilePath(ioc), fileHash); - File.WriteAllText(BaseVersionFilePath(ioc), fileHash); + File.WriteAllText(baseVersionFilePath, fileHash); + + //notify supervisor what we did: + if (previousHash != fileHash) + _cacheSupervisor.UpdatedCachedFileOnLoad(ioc); + else + _cacheSupervisor.LoadedFromRemoteInSync(ioc); return File.OpenRead(cachedFilePath); } } - private void TryUpdateRemoteFile(Stream cachedData, IOConnectionInfo ioc, bool useFileTransaction, string hash) + private bool TryUpdateRemoteFile(Stream cachedData, IOConnectionInfo ioc, bool useFileTransaction, string hash) { try { UpdateRemoteFile(cachedData, ioc, useFileTransaction, hash); + return true; } catch (Exception e) { @@ -218,6 +250,7 @@ namespace keepass2android.Io Kp2aLog.Log(e.ToString()); //notify the supervisor so it might display a warning or schedule a retry _cacheSupervisor.CouldntSaveToRemote(ioc, e); + return false; } } diff --git a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj index c2bdbd5f..d6e41354 100644 --- a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj +++ b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj @@ -51,6 +51,7 @@ + diff --git a/src/Kp2aBusinessLogic/UiStringKey.cs b/src/Kp2aBusinessLogic/UiStringKey.cs index e595e373..e8cdf05e 100644 --- a/src/Kp2aBusinessLogic/UiStringKey.cs +++ b/src/Kp2aBusinessLogic/UiStringKey.cs @@ -40,6 +40,8 @@ namespace keepass2android UploadingFile, FilesInSync, SynchronizedDatabaseSuccessfully, - RestoringRemoteFile + RestoringRemoteFile, + CheckingDatabaseForChanges, + RemoteDatabaseUnchanged } } \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/database/CheckDatabaseForChanges.cs b/src/Kp2aBusinessLogic/database/CheckDatabaseForChanges.cs new file mode 100644 index 00000000..3bc976b9 --- /dev/null +++ b/src/Kp2aBusinessLogic/database/CheckDatabaseForChanges.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using Android.App; +using Android.Content; +using KeePassLib.Cryptography; +using KeePassLib.Serialization; +using KeePassLib.Utility; +using keepass2android.Io; + +namespace keepass2android +{ + public class CheckDatabaseForChanges: RunnableOnFinish + { + private readonly Context _context; + private readonly IKp2aApp _app; + + + public CheckDatabaseForChanges(Context context, IKp2aApp app, OnFinish finish) + : base(finish) + { + _context = context; + _app = app; + } + + public override void Run() + { + try + { + IOConnectionInfo ioc = _app.GetDb().Ioc; + IFileStorage fileStorage = _app.GetFileStorage(ioc); + if (fileStorage is CachingFileStorage) + { + throw new Exception("Cannot sync a cached database!"); + } + StatusLogger.UpdateMessage(UiStringKey.CheckingDatabaseForChanges); + + //download file from remote location and calculate hash: + StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.DownloadingRemoteFile)); + + + MemoryStream remoteData = new MemoryStream(); + using ( + HashingStreamEx hashingRemoteStream = new HashingStreamEx(fileStorage.OpenFileForRead(ioc), false, + new SHA256Managed())) + { + hashingRemoteStream.CopyTo(remoteData); + hashingRemoteStream.Close(); + + if (!MemUtil.ArraysEqual(_app.GetDb().KpDatabase.HashOfFileOnDisk, hashingRemoteStream.Hash)) + { + _app.TriggerReload(_context); + Finish(true); + } + else + { + Finish(true, _app.GetResourceString(UiStringKey.RemoteDatabaseUnchanged)); + } + } + + + + } + catch (Exception e) + { + Finish(false, e.Message); + } + + } + + } +} diff --git a/src/Kp2aBusinessLogic/database/edit/LoadDB.cs b/src/Kp2aBusinessLogic/database/edit/LoadDB.cs index 9e71164d..21eb05f1 100644 --- a/src/Kp2aBusinessLogic/database/edit/LoadDB.cs +++ b/src/Kp2aBusinessLogic/database/edit/LoadDB.cs @@ -48,7 +48,8 @@ namespace keepass2android try { StatusLogger.UpdateMessage(UiStringKey.loading_database); - _app.LoadDatabase(_ioc, _databaseData == null ? null : _databaseData.Result, _pass, _key, StatusLogger); + MemoryStream memoryStream = _databaseData == null ? null : _databaseData.Result; + _app.LoadDatabase(_ioc, memoryStream, _pass, _key, StatusLogger); SaveFileData (_ioc, _key); } catch (KeyFileException) { @@ -56,7 +57,7 @@ namespace keepass2android Finish(false, /*TODO Localize: use Keepass error text KPRes.KeyFileError (including "or invalid format")*/ _app.GetResourceString(UiStringKey.keyfile_does_not_exist)); } catch (Exception e) { - Kp2aLog.Log("Exception: " + e.Message); + Kp2aLog.Log("Exception: " + e); Finish(false, "An error occured: " + e.Message); return; } diff --git a/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj b/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj index e28826e1..0c5f7cf5 100644 --- a/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj +++ b/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj @@ -51,9 +51,11 @@ + + project.zip + - diff --git a/src/Kp2aUnitTests/MainActivity.cs b/src/Kp2aUnitTests/MainActivity.cs index 84e43dd6..880cf121 100644 --- a/src/Kp2aUnitTests/MainActivity.cs +++ b/src/Kp2aUnitTests/MainActivity.cs @@ -19,7 +19,7 @@ namespace Kp2aUnitTests TestRunner runner = new TestRunner(); // Run all tests from this assembly runner.AddTests(Assembly.GetExecutingAssembly()); - //runner.AddTests(new List { typeof(TestSaveDbCached) }); + //runner.AddTests(new List { typeof(TestSynchronizeCachedDatabase) }); //runner.AddTests(typeof(TestSaveDbCached).GetMethod("TestLoadEditSaveWhenModified")); //runner.AddTests(new List { typeof(TestSaveDb) }); diff --git a/src/Kp2aUnitTests/TestBase.cs b/src/Kp2aUnitTests/TestBase.cs index eb6a0eb4..7bb04da3 100644 --- a/src/Kp2aUnitTests/TestBase.cs +++ b/src/Kp2aUnitTests/TestBase.cs @@ -66,7 +66,7 @@ namespace Kp2aUnitTests var app = CreateTestKp2aApp(); app.CreateNewDatabase(); bool loadSuccesful = false; - LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = filename }, password, keyfile, new ActionOnFinish((success, message) => + LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = filename }, null, password, keyfile, new ActionOnFinish((success, message) => { if (!success) Kp2aLog.Log(message); diff --git a/src/Kp2aUnitTests/TestCacheSupervisor.cs b/src/Kp2aUnitTests/TestCacheSupervisor.cs index b66fd47a..8bb0cf56 100644 --- a/src/Kp2aUnitTests/TestCacheSupervisor.cs +++ b/src/Kp2aUnitTests/TestCacheSupervisor.cs @@ -1,29 +1,78 @@ using System; +using System.Collections.Generic; +using System.Linq; using KeePassLib.Serialization; +using Microsoft.VisualStudio.TestTools.UnitTesting; using keepass2android.Io; namespace Kp2aUnitTests { class TestCacheSupervisor: ICacheSupervisor { - public bool CouldntOpenFromRemoteCalled { get; set; } - public bool CouldntSaveToRemoteCalled { get; set; } - public bool NotifyOpenFromLocalDueToConflictCalled { get; set; } + public const string CouldntOpenFromRemoteId = "CouldntOpenFromRemote"; + public const string CouldntSaveToRemoteId = "CouldntSaveToRemote"; + public const string NotifyOpenFromLocalDueToConflictId = "CouldntSaveToRemote"; + public const string UpdatedCachedFileOnLoadId = "UpdatedCachedFileOnLoad"; + public const string LoadedFromRemoteInSyncId = "LoadedFromRemoteInSync"; + public const string UpdatedRemoteFileOnLoadId = "UpdatedRemoteFileOnLoad"; + private HashSet _callsMade = new HashSet(); + + public void Reset() + { + _callsMade.Clear(); + } + + public void AssertNoCall() + { + string allCalls = _callsMade.Aggregate("", (current, s) => current + s + ","); + Assert.AreEqual("", allCalls); + } + + public void AssertSingleCall(string id) + { + if ((_callsMade.Count == 1) + && _callsMade.Single() == id) + { + Reset(); + return; + } + + + Assert.Fail("expected only "+id+", but received: "+_callsMade.Aggregate("", (current, s) => current + s + ",")); + + } public void CouldntSaveToRemote(IOConnectionInfo ioc, Exception e) { - CouldntSaveToRemoteCalled = true; + _callsMade.Add(CouldntSaveToRemoteId); } public void CouldntOpenFromRemote(IOConnectionInfo ioc, Exception ex) { - CouldntOpenFromRemoteCalled = true; + _callsMade.Add(CouldntOpenFromRemoteId); + } + + public void UpdatedCachedFileOnLoad(IOConnectionInfo ioc) + { + _callsMade.Add(UpdatedCachedFileOnLoadId); + } + + public void UpdatedRemoteFileOnLoad(IOConnectionInfo ioc) + { + _callsMade.Add(UpdatedRemoteFileOnLoadId); } public void NotifyOpenFromLocalDueToConflict(IOConnectionInfo ioc) { - NotifyOpenFromLocalDueToConflictCalled = true; + _callsMade.Add(NotifyOpenFromLocalDueToConflictId); } + + public void LoadedFromRemoteInSync(IOConnectionInfo ioc) + { + _callsMade.Add(LoadedFromRemoteInSyncId); + } + + } } \ No newline at end of file diff --git a/src/Kp2aUnitTests/TestCachingFileStorage.cs b/src/Kp2aUnitTests/TestCachingFileStorage.cs index 2f25ea94..9c90e98f 100644 --- a/src/Kp2aUnitTests/TestCachingFileStorage.cs +++ b/src/Kp2aUnitTests/TestCachingFileStorage.cs @@ -30,6 +30,8 @@ namespace Kp2aUnitTests //read the file once. Should now be in the cache. MemoryStream fileContents = ReadToMemoryStream(_fileStorage, CachingTestFile); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.UpdatedCachedFileOnLoadId); + //check it's the correct data: Assert.AreEqual(MemoryStreamToString(fileContents), _defaultCacheFileContents); @@ -41,8 +43,7 @@ namespace Kp2aUnitTests AssertEqual(fileContents, fileContents2); - Assert.IsTrue(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntOpenFromRemoteId); } @@ -67,8 +68,7 @@ namespace Kp2aUnitTests //read the file once. Should now be in the cache. ReadToMemoryStream(_fileStorage, CachingTestFile); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.UpdatedCachedFileOnLoadId); //let the base file storage go offline: _testFileStorage.Offline = true; @@ -77,16 +77,13 @@ namespace Kp2aUnitTests string newContent = "new content"; WriteContentToCacheFile(newContent); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsTrue(_testCacheSupervisor.CouldntSaveToRemoteCalled); - _testCacheSupervisor.CouldntSaveToRemoteCalled = false; + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntSaveToRemoteId); //now try to read the file again: MemoryStream fileContents2 = ReadToMemoryStream(_fileStorage, CachingTestFile); - Assert.IsTrue(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); - _testCacheSupervisor.CouldntOpenFromRemoteCalled = false; + + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntOpenFromRemoteId); //should return the written content: Assert.AreEqual(MemoryStreamToString(fileContents2), newContent); @@ -96,8 +93,7 @@ namespace Kp2aUnitTests MemoryStream fileContents3 = ReadToMemoryStream(_fileStorage, CachingTestFile); Assert.AreEqual(MemoryStreamToString(fileContents3), newContent); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.UpdatedRemoteFileOnLoadId); //ensure the data on the remote was synced: MemoryStream fileContents4 = ReadToMemoryStream(_testFileStorage, CachingTestFile); @@ -115,8 +111,7 @@ namespace Kp2aUnitTests //read the file once. Should now be in the cache. ReadToMemoryStream(_fileStorage, CachingTestFile); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.UpdatedCachedFileOnLoadId); //let the base file storage go offline: _testFileStorage.Offline = true; @@ -125,9 +120,7 @@ namespace Kp2aUnitTests string newLocalContent = "new local content"; WriteContentToCacheFile(newLocalContent); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsTrue(_testCacheSupervisor.CouldntSaveToRemoteCalled); - _testCacheSupervisor.CouldntSaveToRemoteCalled = false; + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntSaveToRemoteId); //write something to the remote file: File.WriteAllText(CachingTestFile, "new remote content"); @@ -142,12 +135,7 @@ namespace Kp2aUnitTests Assert.AreEqual(MemoryStreamToString(fileContents2), newLocalContent); //but a notification about the conflict should be made: - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); - Assert.IsTrue(_testCacheSupervisor.NotifyOpenFromLocalDueToConflictCalled); - _testCacheSupervisor.NotifyOpenFromLocalDueToConflictCalled = false; - - + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.NotifyOpenFromLocalDueToConflictId); } @@ -160,13 +148,13 @@ namespace Kp2aUnitTests //read the file once. Should now be in the cache. ReadToMemoryStream(_fileStorage, CachingTestFile); + _testCacheSupervisor.Reset(); //write something to the cache: string newContent = "new content"; WriteContentToCacheFile(newContent); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertNoCall(); Assert.AreEqual(newContent, File.ReadAllText(CachingTestFile)); } @@ -180,17 +168,19 @@ namespace Kp2aUnitTests //read the file once. Should now be in the cache. ReadToMemoryStream(_fileStorage, CachingTestFile); + _testCacheSupervisor.Reset(); + //delete remote file: _testFileStorage.DeleteFile(IocForCacheFile); + //read again. shouldn't throw and give the same result: var memStream = ReadToMemoryStream(_fileStorage, CachingTestFile); //check if we received the correct content: - Assert.AreEqual(_defaultCacheFileContents, MemoryStreamToString(memStream)); + Assert.AreEqual(_defaultCacheFileContents, MemoryStreamToString(memStream)); - Assert.IsTrue(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntOpenFromRemoteId); } @@ -216,7 +206,8 @@ namespace Kp2aUnitTests { _testFileStorage = new TestFileStorage(); _testCacheSupervisor = new TestCacheSupervisor(); - _fileStorage = new CachingFileStorage(_testFileStorage, Application.Context.CacheDir.Path, _testCacheSupervisor); + //_fileStorage = new CachingFileStorage(_testFileStorage, Application.Context.CacheDir.Path, _testCacheSupervisor); + _fileStorage = new CachingFileStorage(_testFileStorage, "/mnt/sdcard/kp2atest_cache", _testCacheSupervisor); _fileStorage.ClearCache(); File.WriteAllText(CachingTestFile, _defaultCacheFileContents); } diff --git a/src/Kp2aUnitTests/TestKp2aApp.cs b/src/Kp2aUnitTests/TestKp2aApp.cs index ffdbaac9..3ca08ecf 100644 --- a/src/Kp2aUnitTests/TestKp2aApp.cs +++ b/src/Kp2aUnitTests/TestKp2aApp.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using Android.App; using Android.Content; using Android.OS; @@ -29,6 +30,18 @@ namespace Kp2aUnitTests } + public void LockDatabase(bool allowQuickUnlock = true) + { + throw new NotImplementedException(); + } + + public void LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, string password, string keyFile, + ProgressDialogStatusLogger statusLogger) + { + _db.LoadData(this, ioConnectionInfo, memoryStream, password, keyFile, statusLogger); + + } + public Database GetDb() { return _db; diff --git a/src/Kp2aUnitTests/TestLoadDb.cs b/src/Kp2aUnitTests/TestLoadDb.cs index 4e4d9ef9..dc3b8743 100644 --- a/src/Kp2aUnitTests/TestLoadDb.cs +++ b/src/Kp2aUnitTests/TestLoadDb.cs @@ -21,7 +21,7 @@ namespace Kp2aUnitTests IKp2aApp app = new TestKp2aApp(); app.CreateNewDatabase(); bool loadSuccesful = false; - LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = TestDbDirectory+filenameWithoutDir }, + LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = TestDbDirectory+filenameWithoutDir }, null, password, keyfile, new ActionOnFinish((success, message) => { if (!success) @@ -78,7 +78,7 @@ namespace Kp2aUnitTests app.CreateNewDatabase(); bool loadSuccesful = false; - LoadDb task = new LoadDb(app, ioc, "a", null, new ActionOnFinish((success, message) => + LoadDb task = new LoadDb(app, ioc, null, "a", null, new ActionOnFinish((success, message) => { if (!success) Android.Util.Log.Debug("KP2ATest", "error loading db: " + message); @@ -102,7 +102,7 @@ namespace Kp2aUnitTests app.CreateNewDatabase(); bool loadSuccesful = false; - LoadDb task = new LoadDb(app, ioc, "test", null, new ActionOnFinish((success, message) => + LoadDb task = new LoadDb(app, ioc, null, "test", null, new ActionOnFinish((success, message) => { if (!success) Android.Util.Log.Debug("KP2ATest", "error loading db: " + message); @@ -128,7 +128,7 @@ namespace Kp2aUnitTests bool loadSuccesful = false; bool gotError = false; - LoadDb task = new LoadDb(app, ioc, "test", null, new ActionOnFinish((success, message) => + LoadDb task = new LoadDb(app, ioc, null, "test", null, new ActionOnFinish((success, message) => { if (!success) { @@ -156,7 +156,7 @@ namespace Kp2aUnitTests bool loadSuccesful = false; bool gotError = false; - LoadDb task = new LoadDb(app, ioc, "test", null, new ActionOnFinish((success, message) => + LoadDb task = new LoadDb(app, ioc, null, "test", null, new ActionOnFinish((success, message) => { if (!success) { diff --git a/src/Kp2aUnitTests/TestSaveDbCached.cs b/src/Kp2aUnitTests/TestSaveDbCached.cs index 11c738ae..d341818c 100644 --- a/src/Kp2aUnitTests/TestSaveDbCached.cs +++ b/src/Kp2aUnitTests/TestSaveDbCached.cs @@ -39,14 +39,15 @@ namespace Kp2aUnitTests IOConnection.DeleteFile(new IOConnectionInfo { Path = DefaultFilename }); //save it and reload it so we have a base version SaveDatabase(app); + _testCacheSupervisor.AssertNoCall(); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId); //modify the database by adding a group: app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); //save the database again: SaveDatabase(app); Assert.IsNull(((TestKp2aApp)app).LastYesNoCancelQuestionTitle); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertNoCall(); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); @@ -71,10 +72,10 @@ namespace Kp2aUnitTests //modify the database by adding a group: app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); //save the database again: + _testCacheSupervisor.Reset(); SaveDatabase(app); Assert.IsNull(((TestKp2aApp) app).LastYesNoCancelQuestionTitle); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertNoCall(); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); @@ -109,11 +110,12 @@ namespace Kp2aUnitTests SaveDatabase(app2); + _testCacheSupervisor.Reset(); + foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups) Kp2aLog.Log("app d: " + group.Name); Assert.IsNull(((TestKp2aApp)app).LastYesNoCancelQuestionTitle); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertNoCall(); //modify the database by adding a group: PwGroup group1 = new PwGroup(true, true, "TestGroup", PwIcon.Apple); @@ -124,10 +126,10 @@ namespace Kp2aUnitTests //save the database again: + _testCacheSupervisor.Reset(); SaveDatabase(app); Assert.AreEqual(((TestKp2aApp)app).LastYesNoCancelQuestionTitle, UiStringKey.TitleSyncQuestion); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); - Assert.IsFalse(_testCacheSupervisor.CouldntSaveToRemoteCalled); + _testCacheSupervisor.AssertNoCall(); //load database to a new app instance: diff --git a/src/Kp2aUnitTests/TestSynchronizeCachedDatabase.cs b/src/Kp2aUnitTests/TestSynchronizeCachedDatabase.cs index e0f543f3..1e8aa792 100644 --- a/src/Kp2aUnitTests/TestSynchronizeCachedDatabase.cs +++ b/src/Kp2aUnitTests/TestSynchronizeCachedDatabase.cs @@ -47,6 +47,7 @@ namespace Kp2aUnitTests //save it and reload it so we have a base version ("remote" and in the cache) SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId); string resultMessage; bool wasSuccessful; @@ -68,8 +69,8 @@ namespace Kp2aUnitTests app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); //save the database again (will be saved locally only) SaveDatabase(app); - Assert.IsTrue(_testCacheSupervisor.CouldntSaveToRemoteCalled); - _testCacheSupervisor.CouldntSaveToRemoteCalled = false; + + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntSaveToRemoteId); //go online again: _testFileStorage.Offline = false; @@ -82,10 +83,10 @@ namespace Kp2aUnitTests //ensure both files are identical and up to date now: _testFileStorage.Offline = true; var appOfflineLoaded = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); - _testCacheSupervisor.CouldntOpenFromRemoteCalled = false; + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntOpenFromRemoteId); _testFileStorage.Offline = false; var appRemoteLoaded = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); - Assert.IsFalse(_testCacheSupervisor.CouldntOpenFromRemoteCalled); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId); AssertDatabasesAreEqual(app.GetDb().KpDatabase, appOfflineLoaded.GetDb().KpDatabase); AssertDatabasesAreEqual(app.GetDb().KpDatabase, appRemoteLoaded.GetDb().KpDatabase); @@ -101,6 +102,7 @@ namespace Kp2aUnitTests //save it and reload it so we have a base version ("remote" and in the cache) SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId); //delete remote: IOConnection.DeleteFile(new IOConnectionInfo { Path = DefaultFilename }); @@ -128,8 +130,11 @@ namespace Kp2aUnitTests //save it and reload it so we have a base version ("remote" and in the cache) SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId); + var app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); app2.FileStorage = _testFileStorage; //give app2 direct access to the remote file + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId); //go offline: _testFileStorage.Offline = true; @@ -145,8 +150,7 @@ namespace Kp2aUnitTests app2.GetDb().KpDatabase.RootGroup.AddGroup(newGroup2, true); //save the database again (will be saved locally only for "app") SaveDatabase(app); - Assert.IsTrue(_testCacheSupervisor.CouldntSaveToRemoteCalled); - _testCacheSupervisor.CouldntSaveToRemoteCalled = false; + _testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntSaveToRemoteId); //go online again: _testFileStorage.Offline = false; diff --git a/src/keepass2android/GroupBaseActivity.cs b/src/keepass2android/GroupBaseActivity.cs index 395c5a77..dead0e9d 100644 --- a/src/keepass2android/GroupBaseActivity.cs +++ b/src/keepass2android/GroupBaseActivity.cs @@ -24,6 +24,7 @@ using Android.Views; using Android.Widget; using KeePassLib; using Android.Preferences; +using keepass2android.Io; using keepass2android.view; using Android.Graphics.Drawables; @@ -201,6 +202,14 @@ namespace keepass2android searchView.SetSearchableInfo(searchManager.GetSearchableInfo(ComponentName)); } + var item = menu.FindItem(Resource.Id.menu_sync); + if (item != null) + { + if (App.Kp2a.GetDb().Ioc.IsLocalFile()) + item.SetVisible(false); + else + item.SetVisible(true); + } return true; } @@ -255,6 +264,10 @@ namespace keepass2android case Resource.Id.menu_change_master_key: SetPassword(); return true; + + case Resource.Id.menu_sync: + Synchronize(); + return true; case Resource.Id.menu_sort: ToggleSort(); @@ -292,7 +305,31 @@ namespace keepass2android return base.OnOptionsItemSelected(item); } - + + private void Synchronize() + { + var filestorage = App.Kp2a.GetFileStorage(App.Kp2a.GetDb().Ioc); + RunnableOnFinish task; + ActionOnFinish onFinishShowMessage = new ActionOnFinish((success, message) => + { + if (!String.IsNullOrEmpty(message)) + Toast.MakeText(this, message, ToastLength.Long).Show(); + }); + if (filestorage is CachingFileStorage) + { + + task = new SynchronizeCachedDatabase(this, App.Kp2a, onFinishShowMessage); + } + else + { + + task = new CheckDatabaseForChanges(this, App.Kp2a, onFinishShowMessage); + } + var progressTask = new ProgressTask(App.Kp2a, this, task); + progressTask.Run(); + + } + private void ToggleSort() { // Toggle setting String sortKey = GetString(Resource.String.sort_key); diff --git a/src/keepass2android/Resources/Resource.designer.cs b/src/keepass2android/Resources/Resource.designer.cs index 99abc84d..89528bb8 100644 --- a/src/keepass2android/Resources/Resource.designer.cs +++ b/src/keepass2android/Resources/Resource.designer.cs @@ -104,9 +104,15 @@ namespace keepass2android // aapt resource value: 0x7f090009 public const int OpenKp2aKeyboardAutomatically_default = 2131296265; + // aapt resource value: 0x7f09000b + public const int PreloadDatabaseEnabled_default = 2131296267; + // aapt resource value: 0x7f090006 public const int RememberRecentFiles_default = 2131296262; + // aapt resource value: 0x7f09000a + public const int ShowUnlockedNotification_default = 2131296266; + // aapt resource value: 0x7f090005 public const int ShowUsernameInList_default = 2131296261; @@ -483,70 +489,76 @@ namespace keepass2android public const int ic_launcher_offline = 2130837591; // aapt resource value: 0x7f020058 - public const int ic_menu_add_field_holo_light = 2130837592; + public const int ic_launcher_red = 2130837592; // aapt resource value: 0x7f020059 - public const int ic_menu_remove_field_holo_light = 2130837593; + public const int ic_menu_add_field_holo_light = 2130837593; // aapt resource value: 0x7f02005a - public const int ic_menu_view = 2130837594; + public const int ic_menu_remove_field_holo_light = 2130837594; // aapt resource value: 0x7f02005b - public const int location_web_site = 2130837595; + public const int ic_menu_view = 2130837595; // aapt resource value: 0x7f02005c - public const int navigation_accept = 2130837596; + public const int ic_unlocked_gray = 2130837596; // aapt resource value: 0x7f02005d - public const int navigation_accept_dark = 2130837597; + public const int location_web_site = 2130837597; // aapt resource value: 0x7f02005e - public const int navigation_cancel = 2130837598; + public const int navigation_accept = 2130837598; // aapt resource value: 0x7f02005f - public const int navigation_previous_item = 2130837599; + public const int navigation_accept_dark = 2130837599; // aapt resource value: 0x7f020060 - public const int navigation_previous_item_dark = 2130837600; + public const int navigation_cancel = 2130837600; // aapt resource value: 0x7f020061 - public const int notify = 2130837601; + public const int navigation_previous_item = 2130837601; // aapt resource value: 0x7f020062 - public const int notify_keyboard = 2130837602; + public const int navigation_previous_item_dark = 2130837602; // aapt resource value: 0x7f020063 - public const int RedButton = 2130837603; + public const int notify = 2130837603; // aapt resource value: 0x7f020064 - public const int section_header = 2130837604; + public const int notify_keyboard = 2130837604; // aapt resource value: 0x7f020065 - public const int sym_keyboard = 2130837605; + public const int RedButton = 2130837605; // aapt resource value: 0x7f020066 - public const int sym_keyboard_delete = 2130837606; + public const int section_header = 2130837606; // aapt resource value: 0x7f020067 - public const int sym_keyboard_done = 2130837607; + public const int sym_keyboard = 2130837607; // aapt resource value: 0x7f020068 - public const int sym_keyboard_kp2a = 2130837608; + public const int sym_keyboard_delete = 2130837608; // aapt resource value: 0x7f020069 - public const int sym_keyboard_return = 2130837609; + public const int sym_keyboard_done = 2130837609; // aapt resource value: 0x7f02006a - public const int sym_keyboard_search = 2130837610; + public const int sym_keyboard_kp2a = 2130837610; // aapt resource value: 0x7f02006b - public const int sym_keyboard_shift = 2130837611; + public const int sym_keyboard_return = 2130837611; // aapt resource value: 0x7f02006c - public const int sym_keyboard_space = 2130837612; + public const int sym_keyboard_search = 2130837612; // aapt resource value: 0x7f02006d - public const int YellowButton = 2130837613; + public const int sym_keyboard_shift = 2130837613; + + // aapt resource value: 0x7f02006e + public const int sym_keyboard_space = 2130837614; + + // aapt resource value: 0x7f02006f + public const int YellowButton = 2130837615; static Drawable() { @@ -567,17 +579,17 @@ namespace keepass2android // aapt resource value: 0x7f0d0072 public const int IconGridView = 2131558514; - // aapt resource value: 0x7f0d0082 - public const int QuickUnlock_button = 2131558530; + // aapt resource value: 0x7f0d0081 + public const int QuickUnlock_button = 2131558529; - // aapt resource value: 0x7f0d0083 - public const int QuickUnlock_buttonLock = 2131558531; + // aapt resource value: 0x7f0d0082 + public const int QuickUnlock_buttonLock = 2131558530; + + // aapt resource value: 0x7f0d007f + public const int QuickUnlock_label = 2131558527; // aapt resource value: 0x7f0d0080 - public const int QuickUnlock_label = 2131558528; - - // aapt resource value: 0x7f0d0081 - public const int QuickUnlock_password = 2131558529; + public const int QuickUnlock_password = 2131558528; // aapt resource value: 0x7f0d0056 public const int RelativeLayout = 2131558486; @@ -603,8 +615,8 @@ namespace keepass2android // aapt resource value: 0x7f0d0068 public const int add_group = 2131558504; - // aapt resource value: 0x7f0d0096 - public const int add_url_entry = 2131558550; + // aapt resource value: 0x7f0d0095 + public const int add_url_entry = 2131558549; // aapt resource value: 0x7f0d0027 public const int advanced_container = 2131558439; @@ -639,38 +651,38 @@ namespace keepass2android // aapt resource value: 0x7f0d0054 public const int cancel_button = 2131558484; - // aapt resource value: 0x7f0d0093 - public const int cbCaseSensitive = 2131558547; - - // aapt resource value: 0x7f0d0094 - public const int cbExcludeExpiredEntries = 2131558548; - - // aapt resource value: 0x7f0d0089 - public const int cbRegEx = 2131558537; - // aapt resource value: 0x7f0d0092 - public const int cbSearchInGroupName = 2131558546; + public const int cbCaseSensitive = 2131558546; - // aapt resource value: 0x7f0d008f - public const int cbSearchInNotes = 2131558543; + // aapt resource value: 0x7f0d0093 + public const int cbExcludeExpiredEntries = 2131558547; - // aapt resource value: 0x7f0d0090 - public const int cbSearchInOtherStrings = 2131558544; - - // aapt resource value: 0x7f0d008e - public const int cbSearchInPassword = 2131558542; + // aapt resource value: 0x7f0d0088 + public const int cbRegEx = 2131558536; // aapt resource value: 0x7f0d0091 - public const int cbSearchInTags = 2131558545; + public const int cbSearchInGroupName = 2131558545; - // aapt resource value: 0x7f0d008b - public const int cbSearchInTitle = 2131558539; + // aapt resource value: 0x7f0d008e + public const int cbSearchInNotes = 2131558542; - // aapt resource value: 0x7f0d008c - public const int cbSearchInUrl = 2131558540; + // aapt resource value: 0x7f0d008f + public const int cbSearchInOtherStrings = 2131558543; // aapt resource value: 0x7f0d008d - public const int cbSearchInUsername = 2131558541; + public const int cbSearchInPassword = 2131558541; + + // aapt resource value: 0x7f0d0090 + public const int cbSearchInTags = 2131558544; + + // aapt resource value: 0x7f0d008a + public const int cbSearchInTitle = 2131558538; + + // aapt resource value: 0x7f0d008b + public const int cbSearchInUrl = 2131558539; + + // aapt resource value: 0x7f0d008c + public const int cbSearchInUsername = 2131558540; // aapt resource value: 0x7f0d0066 public const int cb_brackets = 2131558502; @@ -699,17 +711,14 @@ namespace keepass2android // aapt resource value: 0x7f0d004f public const int create = 2131558479; - // aapt resource value: 0x7f0d009c - public const int cred_password = 2131558556; - - // aapt resource value: 0x7f0d009d - public const int cred_remember_mode = 2131558557; - // aapt resource value: 0x7f0d009b - public const int cred_username = 2131558555; + public const int cred_password = 2131558555; - // aapt resource value: 0x7f0d007b - public const int default_database = 2131558523; + // aapt resource value: 0x7f0d009c + public const int cred_remember_mode = 2131558556; + + // aapt resource value: 0x7f0d009a + public const int cred_username = 2131558554; // aapt resource value: 0x7f0d0014 public const int delete_extra = 2131558420; @@ -729,8 +738,8 @@ namespace keepass2android // aapt resource value: 0x7f0d0032 public const int edit_extra = 2131558450; - // aapt resource value: 0x7f0d007c - public const int enable_quickunlock = 2131558524; + // aapt resource value: 0x7f0d007b + public const int enable_quickunlock = 2131558523; // aapt resource value: 0x7f0d0043 public const int entry_accessed = 2131558467; @@ -918,8 +927,8 @@ namespace keepass2android // aapt resource value: 0x7f0d0073 public const int keyboard = 2131558515; - // aapt resource value: 0x7f0d007e - public const int keyfileLine = 2131558526; + // aapt resource value: 0x7f0d007d + public const int keyfileLine = 2131558525; // aapt resource value: 0x7f0d004b public const int label_open_by_filename = 2131558475; @@ -936,35 +945,38 @@ namespace keepass2android // aapt resource value: 0x7f0d0059 public const int length_label = 2131558489; - // aapt resource value: 0x7f0d0088 - public const int linearLayout1 = 2131558536; - - // aapt resource value: 0x7f0d00a7 - public const int menu_about = 2131558567; + // aapt resource value: 0x7f0d0087 + public const int linearLayout1 = 2131558535; // aapt resource value: 0x7f0d00a6 - public const int menu_app_settings = 2131558566; + public const int menu_about = 2131558566; // aapt resource value: 0x7f0d00a5 - public const int menu_cancel_edit = 2131558565; + public const int menu_app_settings = 2131558565; - // aapt resource value: 0x7f0d00a9 - public const int menu_change_master_key = 2131558569; + // aapt resource value: 0x7f0d00a4 + public const int menu_cancel_edit = 2131558564; - // aapt resource value: 0x7f0d009e - public const int menu_donate = 2131558558; - - // aapt resource value: 0x7f0d00a0 - public const int menu_goto_url = 2131558560; - - // aapt resource value: 0x7f0d00a1 - public const int menu_lock = 2131558561; - - // aapt resource value: 0x7f0d00a3 - public const int menu_rate = 2131558563; + // aapt resource value: 0x7f0d00ac + public const int menu_change_db = 2131558572; // aapt resource value: 0x7f0d00a8 - public const int menu_search = 2131558568; + public const int menu_change_master_key = 2131558568; + + // aapt resource value: 0x7f0d009d + public const int menu_donate = 2131558557; + + // aapt resource value: 0x7f0d009f + public const int menu_goto_url = 2131558559; + + // aapt resource value: 0x7f0d00a0 + public const int menu_lock = 2131558560; + + // aapt resource value: 0x7f0d00a2 + public const int menu_rate = 2131558562; + + // aapt resource value: 0x7f0d00a7 + public const int menu_search = 2131558567; // aapt resource value: 0x7f0d00ab public const int menu_search_advanced = 2131558571; @@ -972,17 +984,20 @@ namespace keepass2android // aapt resource value: 0x7f0d00aa public const int menu_sort = 2131558570; - // aapt resource value: 0x7f0d00a2 - public const int menu_suggest_improvements = 2131558562; + // aapt resource value: 0x7f0d00a1 + public const int menu_suggest_improvements = 2131558561; - // aapt resource value: 0x7f0d009f - public const int menu_toggle_pass = 2131558559; + // aapt resource value: 0x7f0d00a9 + public const int menu_sync = 2131558569; - // aapt resource value: 0x7f0d00a4 - public const int menu_translate = 2131558564; + // aapt resource value: 0x7f0d009e + public const int menu_toggle_pass = 2131558558; - // aapt resource value: 0x7f0d0097 - public const int no_results = 2131558551; + // aapt resource value: 0x7f0d00a3 + public const int menu_translate = 2131558563; + + // aapt resource value: 0x7f0d0096 + public const int no_results = 2131558550; // aapt resource value: 0x7f0d006b public const int ok = 2131558507; @@ -990,8 +1005,8 @@ namespace keepass2android // aapt resource value: 0x7f0d004e public const int open = 2131558478; - // aapt resource value: 0x7f0d0099 - public const int pass_conf_password = 2131558553; + // aapt resource value: 0x7f0d0098 + public const int pass_conf_password = 2131558552; // aapt resource value: 0x7f0d0079 public const int pass_keyfile = 2131558521; @@ -999,14 +1014,14 @@ namespace keepass2android // aapt resource value: 0x7f0d007a public const int pass_ok = 2131558522; - // aapt resource value: 0x7f0d0098 - public const int pass_password = 2131558552; + // aapt resource value: 0x7f0d0097 + public const int pass_password = 2131558551; // aapt resource value: 0x7f0d0057 public const int password = 2131558487; - // aapt resource value: 0x7f0d007d - public const int passwordLine = 2131558525; + // aapt resource value: 0x7f0d007c + public const int passwordLine = 2131558524; // aapt resource value: 0x7f0d0077 public const int password_label = 2131558519; @@ -1014,8 +1029,8 @@ namespace keepass2android // aapt resource value: 0x7f0d0013 public const int protection = 2131558419; - // aapt resource value: 0x7f0d007f - public const int qu_filename = 2131558527; + // aapt resource value: 0x7f0d007e + public const int qu_filename = 2131558526; // aapt resource value: 0x7f0d000f public const int rounds = 2131558415; @@ -1023,29 +1038,29 @@ namespace keepass2android // aapt resource value: 0x7f0d0010 public const int rounds_explaination = 2131558416; - // aapt resource value: 0x7f0d0087 - public const int scrollView1 = 2131558535; - // aapt resource value: 0x7f0d0086 - public const int searchEditText = 2131558534; + public const int scrollView1 = 2131558534; // aapt resource value: 0x7f0d0085 - public const int search_button = 2131558533; - - // aapt resource value: 0x7f0d008a - public const int search_in_label = 2131558538; + public const int searchEditText = 2131558533; // aapt resource value: 0x7f0d0084 - public const int search_label = 2131558532; + public const int search_button = 2131558532; - // aapt resource value: 0x7f0d0095 - public const int select_other_entry = 2131558549; + // aapt resource value: 0x7f0d0089 + public const int search_in_label = 2131558537; + + // aapt resource value: 0x7f0d0083 + public const int search_label = 2131558531; + + // aapt resource value: 0x7f0d0094 + public const int select_other_entry = 2131558548; // aapt resource value: 0x7f0d0049 public const int start_create = 2131558473; - // aapt resource value: 0x7f0d009a - public const int start_create_import = 2131558554; + // aapt resource value: 0x7f0d0099 + public const int start_create_import = 2131558553; // aapt resource value: 0x7f0d0047 public const int start_open_file = 2131558471; @@ -1245,335 +1260,392 @@ namespace keepass2android public partial class String { - // aapt resource value: 0x7f080035 - public const int AboutText = 2131230773; + // aapt resource value: 0x7f080037 + public const int AboutText = 2131230775; - // aapt resource value: 0x7f080126 - public const int AddingEntry = 2131231014; + // aapt resource value: 0x7f080132 + public const int AddingEntry = 2131231026; - // aapt resource value: 0x7f080127 - public const int AddingGroup = 2131231015; + // aapt resource value: 0x7f080133 + public const int AddingGroup = 2131231027; - // aapt resource value: 0x7f08011c - public const int AskDeletePermanentlyEntry = 2131231004; + // aapt resource value: 0x7f080128 + public const int AskDeletePermanentlyEntry = 2131231016; - // aapt resource value: 0x7f08011d - public const int AskDeletePermanentlyGroup = 2131231005; + // aapt resource value: 0x7f080129 + public const int AskDeletePermanentlyGroup = 2131231017; - // aapt resource value: 0x7f08011e - public const int AskDeletePermanently_title = 2131231006; + // aapt resource value: 0x7f08012a + public const int AskDeletePermanently_title = 2131231018; - // aapt resource value: 0x7f080121 - public const int AskDiscardChanges = 2131231009; + // aapt resource value: 0x7f08012d + public const int AskDiscardChanges = 2131231021; + + // aapt resource value: 0x7f08012e + public const int AskDiscardChanges_title = 2131231022; // aapt resource value: 0x7f080122 - public const int AskDiscardChanges_title = 2131231010; + public const int AskOverwriteBinary = 2131231010; - // aapt resource value: 0x7f080116 - public const int AskOverwriteBinary = 2131230998; + // aapt resource value: 0x7f080125 + public const int AskOverwriteBinary_no = 2131231013; - // aapt resource value: 0x7f080119 - public const int AskOverwriteBinary_no = 2131231001; + // aapt resource value: 0x7f080123 + public const int AskOverwriteBinary_title = 2131231011; - // aapt resource value: 0x7f080117 - public const int AskOverwriteBinary_title = 2131230999; + // aapt resource value: 0x7f080124 + public const int AskOverwriteBinary_yes = 2131231012; - // aapt resource value: 0x7f080118 - public const int AskOverwriteBinary_yes = 2131231000; + // aapt resource value: 0x7f08012c + public const int AskReloadFile = 2131231020; - // aapt resource value: 0x7f080120 - public const int AskReloadFile = 2131231008; + // aapt resource value: 0x7f08012b + public const int AskReloadFile_title = 2131231019; - // aapt resource value: 0x7f08011f - public const int AskReloadFile_title = 2131231007; - - // aapt resource value: 0x7f08011a - public const int AttachFailed = 2131231002; - - // aapt resource value: 0x7f080023 - public const int BinaryDirectory_default = 2131230755; + // aapt resource value: 0x7f080126 + public const int AttachFailed = 2131231014; // aapt resource value: 0x7f080022 - public const int BinaryDirectory_key = 2131230754; + public const int BinaryDirectory_default = 2131230754; - // aapt resource value: 0x7f0800fb - public const int BinaryDirectory_summary = 2131230971; + // aapt resource value: 0x7f080021 + public const int BinaryDirectory_key = 2131230753; - // aapt resource value: 0x7f0800fa - public const int BinaryDirectory_title = 2131230970; + // aapt resource value: 0x7f0800fe + public const int BinaryDirectory_summary = 2131230974; - // aapt resource value: 0x7f080143 - public const int ChangeLog = 2131231043; + // aapt resource value: 0x7f0800fd + public const int BinaryDirectory_title = 2131230973; - // aapt resource value: 0x7f080142 - public const int ChangeLog_0_7 = 2131231042; + // aapt resource value: 0x7f080158 + public const int ChangeLog = 2131231064; - // aapt resource value: 0x7f080140 - public const int ChangeLog_0_8 = 2131231040; + // aapt resource value: 0x7f080157 + public const int ChangeLog_0_7 = 2131231063; - // aapt resource value: 0x7f08013f - public const int ChangeLog_0_8_1 = 2131231039; + // aapt resource value: 0x7f080155 + public const int ChangeLog_0_8 = 2131231061; - // aapt resource value: 0x7f08013e - public const int ChangeLog_0_8_2 = 2131231038; + // aapt resource value: 0x7f080154 + public const int ChangeLog_0_8_1 = 2131231060; - // aapt resource value: 0x7f08013d - public const int ChangeLog_0_8_3 = 2131231037; + // aapt resource value: 0x7f080153 + public const int ChangeLog_0_8_2 = 2131231059; - // aapt resource value: 0x7f08013c - public const int ChangeLog_0_8_4 = 2131231036; + // aapt resource value: 0x7f080152 + public const int ChangeLog_0_8_3 = 2131231058; - // aapt resource value: 0x7f080141 - public const int ChangeLog_keptDonate = 2131231041; + // aapt resource value: 0x7f080151 + public const int ChangeLog_0_8_4 = 2131231057; - // aapt resource value: 0x7f08013b - public const int ChangeLog_title = 2131231035; + // aapt resource value: 0x7f080156 + public const int ChangeLog_keptDonate = 2131231062; + + // aapt resource value: 0x7f080150 + public const int ChangeLog_title = 2131231056; // aapt resource value: 0x7f08002a public const int CheckForFileChangesOnSave_key = 2131230762; - // aapt resource value: 0x7f08010f - public const int CheckForFileChangesOnSave_summary = 2131230991; + // aapt resource value: 0x7f080117 + public const int CheckForFileChangesOnSave_summary = 2131230999; - // aapt resource value: 0x7f08010e - public const int CheckForFileChangesOnSave_title = 2131230990; + // aapt resource value: 0x7f080116 + public const int CheckForFileChangesOnSave_title = 2131230998; - // aapt resource value: 0x7f08012f - public const int CheckingTargetFileForChanges = 2131231023; + // aapt resource value: 0x7f080147 + public const int CheckingDatabaseForChanges = 2131231047; - // aapt resource value: 0x7f08004a - public const int ClearClipboard = 2131230794; + // aapt resource value: 0x7f08013b + public const int CheckingTargetFileForChanges = 2131231035; + + // aapt resource value: 0x7f08004c + public const int ClearClipboard = 2131230796; + + // aapt resource value: 0x7f080115 + public const int ClearOfflineCache_question = 2131230997; + + // aapt resource value: 0x7f080114 + public const int ClearOfflineCache_title = 2131230996; // aapt resource value: 0x7f08002e public const int CopyToClipboardNotification_key = 2131230766; - // aapt resource value: 0x7f080036 - public const int CreditsText = 2131230774; + // aapt resource value: 0x7f080149 + public const int CouldNotLoadFromRemote = 2131231049; - // aapt resource value: 0x7f08012d - public const int DecodingDatabase = 2131231021; + // aapt resource value: 0x7f080148 + public const int CouldNotSaveToRemote = 2131231048; - // aapt resource value: 0x7f080128 - public const int DeletingEntry = 2131231016; - - // aapt resource value: 0x7f080129 - public const int DeletingGroup = 2131231017; - - // aapt resource value: 0x7f080136 - public const int DownloadingRemoteFile = 2131231030; - - // aapt resource value: 0x7f080083 - public const int FileNotFound = 2131230851; + // aapt resource value: 0x7f080038 + public const int CreditsText = 2131230776; // aapt resource value: 0x7f080139 - public const int FilesInSync = 2131231033; + public const int DecodingDatabase = 2131231033; - // aapt resource value: 0x7f080096 - public const int InvalidPassword = 2131230870; + // aapt resource value: 0x7f080134 + public const int DeletingEntry = 2131231028; - // aapt resource value: 0x7f080028 - public const int LastInfoVersionCode_key = 2131230760; + // aapt resource value: 0x7f080135 + public const int DeletingGroup = 2131231029; + + // aapt resource value: 0x7f080142 + public const int DownloadingRemoteFile = 2131231042; + + // aapt resource value: 0x7f080085 + public const int FileNotFound = 2131230853; + + // aapt resource value: 0x7f080145 + public const int FilesInSync = 2131231045; + + // aapt resource value: 0x7f080098 + public const int InvalidPassword = 2131230872; + + // aapt resource value: 0x7f080027 + public const int LastInfoVersionCode_key = 2131230759; + + // aapt resource value: 0x7f08014c + public const int LoadedFromRemoteInSync = 2131231052; // aapt resource value: 0x7f08002b public const int MarketURL = 2131230763; - // aapt resource value: 0x7f0800a0 - public const int MaskedPassword = 2131230880; + // aapt resource value: 0x7f0800a2 + public const int MaskedPassword = 2131230882; - // aapt resource value: 0x7f080131 - public const int MessageSyncQuestion = 2131231025; + // aapt resource value: 0x7f08013d + public const int MessageSyncQuestion = 2131231037; - // aapt resource value: 0x7f080134 - public const int NoOverwrite = 2131231028; + // aapt resource value: 0x7f080140 + public const int NoOverwrite = 2131231040; + + // aapt resource value: 0x7f08014b + public const int NotifyOpenFromLocalDueToConflict = 2131231051; // aapt resource value: 0x7f080030 public const int OpenKp2aKeyboardAutomatically_key = 2131230768; - // aapt resource value: 0x7f080115 - public const int OpenKp2aKeyboardAutomatically_summary = 2131230997; + // aapt resource value: 0x7f08011d + public const int OpenKp2aKeyboardAutomatically_summary = 2131231005; - // aapt resource value: 0x7f080114 - public const int OpenKp2aKeyboardAutomatically_title = 2131230996; + // aapt resource value: 0x7f08011c + public const int OpenKp2aKeyboardAutomatically_title = 2131231004; - // aapt resource value: 0x7f08012e - public const int ParsingDatabase = 2131231022; + // aapt resource value: 0x7f08013a + public const int ParsingDatabase = 2131231034; - // aapt resource value: 0x7f080024 - public const int QuickUnlockDefaultEnabled_key = 2131230756; + // aapt resource value: 0x7f080034 + public const int PreloadDatabaseEnabled_key = 2131230772; - // aapt resource value: 0x7f0800f6 - public const int QuickUnlockDefaultEnabled_summary = 2131230966; + // aapt resource value: 0x7f080121 + public const int PreloadDatabaseEnabled_summary = 2131231009; - // aapt resource value: 0x7f0800f5 - public const int QuickUnlockDefaultEnabled_title = 2131230965; + // aapt resource value: 0x7f080120 + public const int PreloadDatabaseEnabled_title = 2131231008; - // aapt resource value: 0x7f080026 - public const int QuickUnlockLength_default = 2131230758; - - // aapt resource value: 0x7f080025 - public const int QuickUnlockLength_key = 2131230757; - - // aapt resource value: 0x7f0800f8 - public const int QuickUnlockLength_summary = 2131230968; - - // aapt resource value: 0x7f0800f7 - public const int QuickUnlockLength_title = 2131230967; - - // aapt resource value: 0x7f0800f3 - public const int QuickUnlock_button = 2131230963; + // aapt resource value: 0x7f080023 + public const int QuickUnlockDefaultEnabled_key = 2131230755; // aapt resource value: 0x7f0800f9 - public const int QuickUnlock_fail = 2131230969; + public const int QuickUnlockDefaultEnabled_summary = 2131230969; - // aapt resource value: 0x7f0800f2 - public const int QuickUnlock_label = 2131230962; + // aapt resource value: 0x7f0800f8 + public const int QuickUnlockDefaultEnabled_title = 2131230968; - // aapt resource value: 0x7f0800f4 - public const int QuickUnlock_lockButton = 2131230964; + // aapt resource value: 0x7f080025 + public const int QuickUnlockLength_default = 2131230757; - // aapt resource value: 0x7f08011b - public const int RecycleBin = 2131231003; + // aapt resource value: 0x7f080024 + public const int QuickUnlockLength_key = 2131230756; - // aapt resource value: 0x7f08001f - public const int RememberRecentFiles_key = 2131230751; + // aapt resource value: 0x7f0800fb + public const int QuickUnlockLength_summary = 2131230971; - // aapt resource value: 0x7f0800e6 - public const int RememberRecentFiles_summary = 2131230950; + // aapt resource value: 0x7f0800fa + public const int QuickUnlockLength_title = 2131230970; - // aapt resource value: 0x7f0800e5 - public const int RememberRecentFiles_title = 2131230949; - - // aapt resource value: 0x7f080138 - public const int RestoringRemoteFile = 2131231032; - - // aapt resource value: 0x7f0800ff - public const int SaveAttachmentDialog_open = 2131230975; - - // aapt resource value: 0x7f0800fe - public const int SaveAttachmentDialog_save = 2131230974; - - // aapt resource value: 0x7f0800fd - public const int SaveAttachmentDialog_text = 2131230973; + // aapt resource value: 0x7f0800f6 + public const int QuickUnlock_button = 2131230966; // aapt resource value: 0x7f0800fc - public const int SaveAttachmentDialog_title = 2131230972; + public const int QuickUnlock_fail = 2131230972; - // aapt resource value: 0x7f080101 - public const int SaveAttachment_Failed = 2131230977; + // aapt resource value: 0x7f0800f5 + public const int QuickUnlock_label = 2131230965; - // aapt resource value: 0x7f080100 - public const int SaveAttachment_doneMessage = 2131230976; + // aapt resource value: 0x7f0800f7 + public const int QuickUnlock_lockButton = 2131230967; - // aapt resource value: 0x7f08012a - public const int SettingPassword = 2131231018; - - // aapt resource value: 0x7f080111 - public const int ShowCopyToClipboardNotification_summary = 2131230993; - - // aapt resource value: 0x7f080110 - public const int ShowCopyToClipboardNotification_title = 2131230992; - - // aapt resource value: 0x7f080113 - public const int ShowKp2aKeyboardNotification_summary = 2131230995; - - // aapt resource value: 0x7f080112 - public const int ShowKp2aKeyboardNotification_title = 2131230994; + // aapt resource value: 0x7f080127 + public const int RecycleBin = 2131231015; // aapt resource value: 0x7f08001e - public const int ShowUsernameInList_key = 2131230750; + public const int RememberRecentFiles_key = 2131230750; - // aapt resource value: 0x7f0800e4 - public const int ShowUsernameInList_summary = 2131230948; + // aapt resource value: 0x7f0800e9 + public const int RememberRecentFiles_summary = 2131230953; - // aapt resource value: 0x7f0800e3 - public const int ShowUsernameInList_title = 2131230947; + // aapt resource value: 0x7f0800e8 + public const int RememberRecentFiles_title = 2131230952; + + // aapt resource value: 0x7f08014e + public const int RemoteDatabaseUnchanged = 2131231054; + + // aapt resource value: 0x7f080144 + public const int RestoringRemoteFile = 2131231044; + + // aapt resource value: 0x7f080102 + public const int SaveAttachmentDialog_open = 2131230978; + + // aapt resource value: 0x7f080101 + public const int SaveAttachmentDialog_save = 2131230977; + + // aapt resource value: 0x7f080100 + public const int SaveAttachmentDialog_text = 2131230976; + + // aapt resource value: 0x7f0800ff + public const int SaveAttachmentDialog_title = 2131230975; + + // aapt resource value: 0x7f080104 + public const int SaveAttachment_Failed = 2131230980; + + // aapt resource value: 0x7f080103 + public const int SaveAttachment_doneMessage = 2131230979; + + // aapt resource value: 0x7f080136 + public const int SettingPassword = 2131231030; + + // aapt resource value: 0x7f080119 + public const int ShowCopyToClipboardNotification_summary = 2131231001; + + // aapt resource value: 0x7f080118 + public const int ShowCopyToClipboardNotification_title = 2131231000; + + // aapt resource value: 0x7f08011b + public const int ShowKp2aKeyboardNotification_summary = 2131231003; + + // aapt resource value: 0x7f08011a + public const int ShowKp2aKeyboardNotification_title = 2131231002; + + // aapt resource value: 0x7f080033 + public const int ShowUnlockedNotification_key = 2131230771; + + // aapt resource value: 0x7f08011f + public const int ShowUnlockedNotification_summary = 2131231007; + + // aapt resource value: 0x7f08011e + public const int ShowUnlockedNotification_title = 2131231006; + + // aapt resource value: 0x7f08001d + public const int ShowUsernameInList_key = 2131230749; + + // aapt resource value: 0x7f0800e7 + public const int ShowUsernameInList_summary = 2131230951; + + // aapt resource value: 0x7f0800e6 + public const int ShowUsernameInList_title = 2131230950; // aapt resource value: 0x7f08002c public const int SuggestionsURL = 2131230764; - // aapt resource value: 0x7f08013a - public const int SynchronizedDatabaseSuccessfully = 2131231034; + // aapt resource value: 0x7f080146 + public const int SynchronizedDatabaseSuccessfully = 2131231046; - // aapt resource value: 0x7f080135 - public const int SynchronizingCachedDatabase = 2131231029; + // aapt resource value: 0x7f080141 + public const int SynchronizingCachedDatabase = 2131231041; - // aapt resource value: 0x7f080132 - public const int SynchronizingDatabase = 2131231026; + // aapt resource value: 0x7f08013e + public const int SynchronizingDatabase = 2131231038; - // aapt resource value: 0x7f08001d - public const int TanExpiresOnUse_key = 2131230749; + // aapt resource value: 0x7f08001c + public const int TanExpiresOnUse_key = 2131230748; - // aapt resource value: 0x7f0800e2 - public const int TanExpiresOnUse_summary = 2131230946; + // aapt resource value: 0x7f0800e5 + public const int TanExpiresOnUse_summary = 2131230949; - // aapt resource value: 0x7f0800e1 - public const int TanExpiresOnUse_title = 2131230945; + // aapt resource value: 0x7f0800e4 + public const int TanExpiresOnUse_title = 2131230948; - // aapt resource value: 0x7f080130 - public const int TitleSyncQuestion = 2131231024; + // aapt resource value: 0x7f08013c + public const int TitleSyncQuestion = 2131231036; - // aapt resource value: 0x7f08012c - public const int TransformingKey = 2131231020; + // aapt resource value: 0x7f080138 + public const int TransformingKey = 2131231032; // aapt resource value: 0x7f08002d public const int TranslationURL = 2131230765; - // aapt resource value: 0x7f08012b - public const int UndoingChanges = 2131231019; - // aapt resource value: 0x7f080137 - public const int UploadingFile = 2131231031; + public const int UndoingChanges = 2131231031; - // aapt resource value: 0x7f080027 - public const int UsageCount_key = 2131230759; + // aapt resource value: 0x7f08014d + public const int UpdatedCachedFileOnLoad = 2131231053; - // aapt resource value: 0x7f080029 - public const int UseFileTransactions_key = 2131230761; + // aapt resource value: 0x7f08014a + public const int UpdatedRemoteFileOnLoad = 2131231050; - // aapt resource value: 0x7f08010d - public const int UseFileTransactions_summary = 2131230989; + // aapt resource value: 0x7f080143 + public const int UploadingFile = 2131231043; - // aapt resource value: 0x7f08010c - public const int UseFileTransactions_title = 2131230988; + // aapt resource value: 0x7f080026 + public const int UsageCount_key = 2131230758; + + // aapt resource value: 0x7f080028 + public const int UseFileTransactions_key = 2131230760; + + // aapt resource value: 0x7f080111 + public const int UseFileTransactions_summary = 2131230993; + + // aapt resource value: 0x7f080110 + public const int UseFileTransactions_title = 2131230992; // aapt resource value: 0x7f08002f public const int UseKp2aKeyboard_key = 2131230767; - // aapt resource value: 0x7f080133 - public const int YesSynchronize = 2131231027; + // aapt resource value: 0x7f080029 + public const int UseOfflineCache_key = 2131230761; - // aapt resource value: 0x7f080033 - public const int about_feedback = 2131230771; + // aapt resource value: 0x7f080113 + public const int UseOfflineCache_summary = 2131230995; - // aapt resource value: 0x7f080034 - public const int about_homepage = 2131230772; + // aapt resource value: 0x7f080112 + public const int UseOfflineCache_title = 2131230994; - // aapt resource value: 0x7f080037 - public const int accept = 2131230775; + // aapt resource value: 0x7f08013f + public const int YesSynchronize = 2131231039; - // aapt resource value: 0x7f080107 - public const int add_binary = 2131230983; + // aapt resource value: 0x7f080035 + public const int about_feedback = 2131230773; - // aapt resource value: 0x7f080038 - public const int add_entry = 2131230776; - - // aapt resource value: 0x7f080108 - public const int add_extra_string = 2131230984; - - // aapt resource value: 0x7f08003a - public const int add_group = 2131230778; - - // aapt resource value: 0x7f08003b - public const int add_group_title = 2131230779; + // aapt resource value: 0x7f080036 + public const int about_homepage = 2131230774; // aapt resource value: 0x7f080039 - public const int add_url_entry = 2131230777; + public const int accept = 2131230777; + + // aapt resource value: 0x7f08010a + public const int add_binary = 2131230986; + + // aapt resource value: 0x7f08003a + public const int add_entry = 2131230778; + + // aapt resource value: 0x7f08010b + public const int add_extra_string = 2131230987; // aapt resource value: 0x7f08003c - public const int algorithm = 2131230780; + public const int add_group = 2131230780; // aapt resource value: 0x7f08003d - public const int algorithm_colon = 2131230781; + public const int add_group_title = 2131230781; + + // aapt resource value: 0x7f08003b + public const int add_url_entry = 2131230779; + + // aapt resource value: 0x7f08003e + public const int algorithm = 2131230782; + + // aapt resource value: 0x7f08003f + public const int algorithm_colon = 2131230783; // aapt resource value: 0x7f080011 public const int algorithm_key = 2131230737; @@ -1581,50 +1653,50 @@ namespace keepass2android // aapt resource value: 0x7f080012 public const int app_key = 2131230738; - // aapt resource value: 0x7f08003e - public const int app_name = 2131230782; - // aapt resource value: 0x7f080040 - public const int app_name_nonet = 2131230784; + public const int app_name = 2131230784; // aapt resource value: 0x7f080042 - public const int app_timeout = 2131230786; + public const int app_name_nonet = 2131230786; + + // aapt resource value: 0x7f080044 + public const int app_timeout = 2131230788; // aapt resource value: 0x7f080013 public const int app_timeout_key = 2131230739; - // aapt resource value: 0x7f080043 - public const int app_timeout_summary = 2131230787; - - // aapt resource value: 0x7f080044 - public const int application = 2131230788; - // aapt resource value: 0x7f080045 - public const int application_settings = 2131230789; - - // aapt resource value: 0x7f08004f - public const int available_through_keyboard = 2131230799; + public const int app_timeout_summary = 2131230789; // aapt resource value: 0x7f080046 - public const int brackets = 2131230790; + public const int application = 2131230790; // aapt resource value: 0x7f080047 - public const int browser_intall_text = 2131230791; + public const int application_settings = 2131230791; + + // aapt resource value: 0x7f080051 + public const int available_through_keyboard = 2131230801; // aapt resource value: 0x7f080048 - public const int building_search_idx = 2131230792; + public const int brackets = 2131230792; // aapt resource value: 0x7f080049 - public const int cancel = 2131230793; + public const int browser_intall_text = 2131230793; - // aapt resource value: 0x7f0800ea - public const int caseSensitive = 2131230954; + // aapt resource value: 0x7f08004a + public const int building_search_idx = 2131230794; + + // aapt resource value: 0x7f08004b + public const int cancel = 2131230795; + + // aapt resource value: 0x7f0800ed + public const int caseSensitive = 2131230957; // aapt resource value: 0x7f080002 public const int change_entry = 2131230722; - // aapt resource value: 0x7f08004b - public const int clipboard_timeout = 2131230795; + // aapt resource value: 0x7f08004d + public const int clipboard_timeout = 2131230797; // aapt resource value: 0x7f080031 public const int clipboard_timeout_default = 2131230769; @@ -1632,263 +1704,266 @@ namespace keepass2android // aapt resource value: 0x7f080014 public const int clipboard_timeout_key = 2131230740; - // aapt resource value: 0x7f08004c - public const int clipboard_timeout_summary = 2131230796; - // aapt resource value: 0x7f08004e - public const int copy_password = 2131230798; + public const int clipboard_timeout_summary = 2131230798; - // aapt resource value: 0x7f08004d - public const int copy_username = 2131230797; + // aapt resource value: 0x7f080050 + public const int copy_password = 2131230800; - // aapt resource value: 0x7f080052 - public const int creating_db_key = 2131230802; - - // aapt resource value: 0x7f08010b - public const int credentials_dialog_title = 2131230987; - - // aapt resource value: 0x7f080053 - public const int current_group = 2131230803; + // aapt resource value: 0x7f08004f + public const int copy_username = 2131230799; // aapt resource value: 0x7f080054 - public const int current_group_root = 2131230804; + public const int creating_db_key = 2131230804; + + // aapt resource value: 0x7f08010f + public const int credentials_dialog_title = 2131230991; // aapt resource value: 0x7f080055 - public const int database = 2131230805; + public const int current_group = 2131230805; - // aapt resource value: 0x7f08010a - public const int database_loaded_quickunlock_enabled = 2131230986; + // aapt resource value: 0x7f080056 + public const int current_group_root = 2131230806; - // aapt resource value: 0x7f0800cb - public const int database_name = 2131230923; + // aapt resource value: 0x7f080057 + public const int database = 2131230807; - // aapt resource value: 0x7f080021 - public const int database_name_key = 2131230753; + // aapt resource value: 0x7f08010d + public const int database_loaded_quickunlock_enabled = 2131230989; + + // aapt resource value: 0x7f08010e + public const int database_loaded_unlocked = 2131230990; + + // aapt resource value: 0x7f0800ce + public const int database_name = 2131230926; + + // aapt resource value: 0x7f080020 + public const int database_name_key = 2131230752; // aapt resource value: 0x7f080015 public const int db_key = 2131230741; - // aapt resource value: 0x7f080056 - public const int decrypting_db = 2131230806; - - // aapt resource value: 0x7f080057 - public const int decrypting_entry = 2131230807; - // aapt resource value: 0x7f080058 - public const int default_checkbox = 2131230808; + public const int decrypting_db = 2131230808; + + // aapt resource value: 0x7f080059 + public const int decrypting_entry = 2131230809; + + // aapt resource value: 0x7f08005a + public const int default_checkbox = 2131230810; // aapt resource value: 0x7f08000a public const int default_file_path = 2131230730; - // aapt resource value: 0x7f0800cc - public const int default_username = 2131230924; + // aapt resource value: 0x7f0800cf + public const int default_username = 2131230927; - // aapt resource value: 0x7f080020 - public const int default_username_key = 2131230752; + // aapt resource value: 0x7f08001f + public const int default_username_key = 2131230751; - // aapt resource value: 0x7f080109 - public const int delete_extra_string = 2131230985; + // aapt resource value: 0x7f08010c + public const int delete_extra_string = 2131230988; - // aapt resource value: 0x7f080059 - public const int digits = 2131230809; + // aapt resource value: 0x7f08005b + public const int digits = 2131230811; - // aapt resource value: 0x7f08005a - public const int disclaimer_formal = 2131230810; + // aapt resource value: 0x7f08005c + public const int disclaimer_formal = 2131230812; // aapt resource value: 0x7f08000b public const int donate_url = 2131230731; - // aapt resource value: 0x7f08005b - public const int ellipsis = 2131230811; - - // aapt resource value: 0x7f0800f1 - public const int enable_quickunlock = 2131230961; - - // aapt resource value: 0x7f08005c - public const int enter_filename = 2131230812; - - // aapt resource value: 0x7f0800f0 - public const int enter_filename_details_create_import = 2131230960; - - // aapt resource value: 0x7f0800ef - public const int enter_filename_details_url = 2131230959; - // aapt resource value: 0x7f08005d - public const int entry_accessed = 2131230813; + public const int ellipsis = 2131230813; + + // aapt resource value: 0x7f0800f4 + public const int enable_quickunlock = 2131230964; // aapt resource value: 0x7f08005e - public const int entry_and_or = 2131230814; + public const int enter_filename = 2131230814; - // aapt resource value: 0x7f08006e - public const int entry_binaries = 2131230830; + // aapt resource value: 0x7f0800f3 + public const int enter_filename_details_create_import = 2131230963; + + // aapt resource value: 0x7f0800f2 + public const int enter_filename_details_url = 2131230962; // aapt resource value: 0x7f08005f - public const int entry_cancel = 2131230815; + public const int entry_accessed = 2131230815; // aapt resource value: 0x7f080060 - public const int entry_comment = 2131230816; - - // aapt resource value: 0x7f080063 - public const int entry_confpassword = 2131230819; - - // aapt resource value: 0x7f080064 - public const int entry_created = 2131230820; - - // aapt resource value: 0x7f080065 - public const int entry_expires = 2131230821; - - // aapt resource value: 0x7f08006d - public const int entry_extra_strings = 2131230829; - - // aapt resource value: 0x7f080066 - public const int entry_keyfile = 2131230822; - - // aapt resource value: 0x7f080067 - public const int entry_modified = 2131230823; - - // aapt resource value: 0x7f080062 - public const int entry_override_url = 2131230818; - - // aapt resource value: 0x7f080068 - public const int entry_password = 2131230824; - - // aapt resource value: 0x7f080069 - public const int entry_save = 2131230825; - - // aapt resource value: 0x7f080061 - public const int entry_tags = 2131230817; - - // aapt resource value: 0x7f08006a - public const int entry_title = 2131230826; - - // aapt resource value: 0x7f08006b - public const int entry_url = 2131230827; - - // aapt resource value: 0x7f08006c - public const int entry_user_name = 2131230828; - - // aapt resource value: 0x7f08006f - public const int error_arc4 = 2131230831; + public const int entry_and_or = 2131230816; // aapt resource value: 0x7f080070 - public const int error_can_not_handle_uri = 2131230832; + public const int entry_binaries = 2131230832; + + // aapt resource value: 0x7f080061 + public const int entry_cancel = 2131230817; + + // aapt resource value: 0x7f080062 + public const int entry_comment = 2131230818; + + // aapt resource value: 0x7f080065 + public const int entry_confpassword = 2131230821; + + // aapt resource value: 0x7f080066 + public const int entry_created = 2131230822; + + // aapt resource value: 0x7f080067 + public const int entry_expires = 2131230823; + + // aapt resource value: 0x7f08006f + public const int entry_extra_strings = 2131230831; + + // aapt resource value: 0x7f080068 + public const int entry_keyfile = 2131230824; + + // aapt resource value: 0x7f080069 + public const int entry_modified = 2131230825; + + // aapt resource value: 0x7f080064 + public const int entry_override_url = 2131230820; + + // aapt resource value: 0x7f08006a + public const int entry_password = 2131230826; + + // aapt resource value: 0x7f08006b + public const int entry_save = 2131230827; + + // aapt resource value: 0x7f080063 + public const int entry_tags = 2131230819; + + // aapt resource value: 0x7f08006c + public const int entry_title = 2131230828; + + // aapt resource value: 0x7f08006d + public const int entry_url = 2131230829; + + // aapt resource value: 0x7f08006e + public const int entry_user_name = 2131230830; // aapt resource value: 0x7f080071 - public const int error_could_not_create_group = 2131230833; + public const int error_arc4 = 2131230833; // aapt resource value: 0x7f080072 - public const int error_could_not_create_parent = 2131230834; + public const int error_can_not_handle_uri = 2131230834; // aapt resource value: 0x7f080073 - public const int error_database_exists = 2131230835; + public const int error_could_not_create_group = 2131230835; // aapt resource value: 0x7f080074 - public const int error_database_settings = 2131230836; + public const int error_could_not_create_parent = 2131230836; // aapt resource value: 0x7f080075 - public const int error_failed_to_launch_link = 2131230837; - - // aapt resource value: 0x7f080077 - public const int error_file_not_create = 2131230839; + public const int error_database_exists = 2131230837; // aapt resource value: 0x7f080076 - public const int error_filename_required = 2131230838; + public const int error_database_settings = 2131230838; - // aapt resource value: 0x7f080078 - public const int error_invalid_db = 2131230840; - - // aapt resource value: 0x7f080102 - public const int error_invalid_expiry_date = 2131230978; + // aapt resource value: 0x7f080077 + public const int error_failed_to_launch_link = 2131230839; // aapt resource value: 0x7f080079 - public const int error_invalid_path = 2131230841; + public const int error_file_not_create = 2131230841; + + // aapt resource value: 0x7f080078 + public const int error_filename_required = 2131230840; // aapt resource value: 0x7f08007a - public const int error_no_name = 2131230842; - - // aapt resource value: 0x7f08007b - public const int error_nopass = 2131230843; - - // aapt resource value: 0x7f08007c - public const int error_out_of_memory = 2131230844; - - // aapt resource value: 0x7f08007d - public const int error_pass_gen_type = 2131230845; - - // aapt resource value: 0x7f08007e - public const int error_pass_match = 2131230846; - - // aapt resource value: 0x7f08007f - public const int error_rounds_not_number = 2131230847; - - // aapt resource value: 0x7f080080 - public const int error_rounds_too_large = 2131230848; - - // aapt resource value: 0x7f080103 - public const int error_string_key = 2131230979; - - // aapt resource value: 0x7f080081 - public const int error_title_required = 2131230849; - - // aapt resource value: 0x7f080082 - public const int error_wrong_length = 2131230850; - - // aapt resource value: 0x7f0800e8 - public const int excludeExpiredEntries = 2131230952; - - // aapt resource value: 0x7f080104 - public const int field_name = 2131230980; + public const int error_invalid_db = 2131230842; // aapt resource value: 0x7f080105 - public const int field_value = 2131230981; + public const int error_invalid_expiry_date = 2131230981; + + // aapt resource value: 0x7f08007b + public const int error_invalid_path = 2131230843; + + // aapt resource value: 0x7f08007c + public const int error_no_name = 2131230844; + + // aapt resource value: 0x7f08007d + public const int error_nopass = 2131230845; + + // aapt resource value: 0x7f08007e + public const int error_out_of_memory = 2131230846; + + // aapt resource value: 0x7f08007f + public const int error_pass_gen_type = 2131230847; + + // aapt resource value: 0x7f080080 + public const int error_pass_match = 2131230848; + + // aapt resource value: 0x7f080081 + public const int error_rounds_not_number = 2131230849; + + // aapt resource value: 0x7f080082 + public const int error_rounds_too_large = 2131230850; + + // aapt resource value: 0x7f080106 + public const int error_string_key = 2131230982; + + // aapt resource value: 0x7f080083 + public const int error_title_required = 2131230851; // aapt resource value: 0x7f080084 - public const int file_browser = 2131230852; + public const int error_wrong_length = 2131230852; - // aapt resource value: 0x7f080085 - public const int generate_password = 2131230853; + // aapt resource value: 0x7f0800eb + public const int excludeExpiredEntries = 2131230955; + + // aapt resource value: 0x7f080107 + public const int field_name = 2131230983; + + // aapt resource value: 0x7f080108 + public const int field_value = 2131230984; // aapt resource value: 0x7f080086 - public const int group = 2131230854; + public const int file_browser = 2131230854; // aapt resource value: 0x7f080087 - public const int hint_comment = 2131230855; + public const int generate_password = 2131230855; // aapt resource value: 0x7f080088 - public const int hint_conf_pass = 2131230856; + public const int group = 2131230856; // aapt resource value: 0x7f080089 - public const int hint_generated_password = 2131230857; + public const int hint_comment = 2131230857; // aapt resource value: 0x7f08008a - public const int hint_group_name = 2131230858; + public const int hint_conf_pass = 2131230858; // aapt resource value: 0x7f08008b - public const int hint_keyfile = 2131230859; + public const int hint_generated_password = 2131230859; // aapt resource value: 0x7f08008c - public const int hint_length = 2131230860; - - // aapt resource value: 0x7f08008e - public const int hint_login_pass = 2131230862; - - // aapt resource value: 0x7f080091 - public const int hint_override_url = 2131230865; + public const int hint_group_name = 2131230860; // aapt resource value: 0x7f08008d - public const int hint_pass = 2131230861; + public const int hint_keyfile = 2131230861; - // aapt resource value: 0x7f080092 - public const int hint_tags = 2131230866; - - // aapt resource value: 0x7f08008f - public const int hint_title = 2131230863; + // aapt resource value: 0x7f08008e + public const int hint_length = 2131230862; // aapt resource value: 0x7f080090 - public const int hint_url = 2131230864; + public const int hint_login_pass = 2131230864; // aapt resource value: 0x7f080093 - public const int hint_username = 2131230867; + public const int hint_override_url = 2131230867; + + // aapt resource value: 0x7f08008f + public const int hint_pass = 2131230863; + + // aapt resource value: 0x7f080094 + public const int hint_tags = 2131230868; + + // aapt resource value: 0x7f080091 + public const int hint_title = 2131230865; + + // aapt resource value: 0x7f080092 + public const int hint_url = 2131230866; + + // aapt resource value: 0x7f080095 + public const int hint_username = 2131230869; // aapt resource value: 0x7f08000c public const int homepage = 2131230732; @@ -1899,32 +1974,32 @@ namespace keepass2android // aapt resource value: 0x7f080000 public const int ime_name = 2131230720; - // aapt resource value: 0x7f080094 - public const int install_from_market = 2131230868; - - // aapt resource value: 0x7f080095 - public const int install_from_website = 2131230869; + // aapt resource value: 0x7f080096 + public const int install_from_market = 2131230870; // aapt resource value: 0x7f080097 - public const int invalid_algorithm = 2131230871; + public const int install_from_website = 2131230871; - // aapt resource value: 0x7f080098 - public const int invalid_db_sig = 2131230872; + // aapt resource value: 0x7f080099 + public const int invalid_algorithm = 2131230873; + + // aapt resource value: 0x7f08009a + public const int invalid_db_sig = 2131230874; // aapt resource value: 0x7f08000e public const int issues = 2131230734; - // aapt resource value: 0x7f080099 - public const int keyfile_does_not_exist = 2131230873; + // aapt resource value: 0x7f08009b + public const int keyfile_does_not_exist = 2131230875; - // aapt resource value: 0x7f08009a - public const int keyfile_is_empty = 2131230874; + // aapt resource value: 0x7f08009c + public const int keyfile_is_empty = 2131230876; // aapt resource value: 0x7f080017 public const int keyfile_key = 2131230743; - // aapt resource value: 0x7f0800e7 - public const int kp2a_findUrl = 2131230951; + // aapt resource value: 0x7f0800ea + public const int kp2a_findUrl = 2131230954; // aapt resource value: 0x7f080005 public const int label_go_key = 2131230725; @@ -1938,8 +2013,8 @@ namespace keepass2android // aapt resource value: 0x7f080008 public const int label_subtype_generic = 2131230728; - // aapt resource value: 0x7f08009b - public const int length = 2131230875; + // aapt resource value: 0x7f08009d + public const int length = 2131230877; // aapt resource value: 0x7f080009 public const int library_name = 2131230729; @@ -1950,101 +2025,104 @@ namespace keepass2android // aapt resource value: 0x7f08001a public const int list_size_key = 2131230746; - // aapt resource value: 0x7f08009d - public const int list_size_summary = 2131230877; - - // aapt resource value: 0x7f08009c - public const int list_size_title = 2131230876; + // aapt resource value: 0x7f08009f + public const int list_size_summary = 2131230879; // aapt resource value: 0x7f08009e - public const int loading_database = 2131230878; + public const int list_size_title = 2131230878; - // aapt resource value: 0x7f08009f - public const int lowercase = 2131230879; + // aapt resource value: 0x7f0800a0 + public const int loading_database = 2131230880; + + // aapt resource value: 0x7f0800a1 + public const int lowercase = 2131230881; // aapt resource value: 0x7f080018 public const int maskpass_key = 2131230744; - // aapt resource value: 0x7f0800a2 - public const int maskpass_summary = 2131230882; - - // aapt resource value: 0x7f0800a1 - public const int maskpass_title = 2131230881; + // aapt resource value: 0x7f0800a4 + public const int maskpass_summary = 2131230884; // aapt resource value: 0x7f0800a3 - public const int menu_about = 2131230883; - - // aapt resource value: 0x7f0800a8 - public const int menu_app_settings = 2131230888; - - // aapt resource value: 0x7f0800a4 - public const int menu_change_key = 2131230884; + public const int maskpass_title = 2131230883; // aapt resource value: 0x7f0800a5 - public const int menu_copy_pass = 2131230885; - - // aapt resource value: 0x7f0800a6 - public const int menu_copy_user = 2131230886; - - // aapt resource value: 0x7f0800a7 - public const int menu_create = 2131230887; - - // aapt resource value: 0x7f0800a9 - public const int menu_db_settings = 2131230889; + public const int menu_about = 2131230885; // aapt resource value: 0x7f0800aa - public const int menu_delete = 2131230890; + public const int menu_app_settings = 2131230890; + + // aapt resource value: 0x7f0800b7 + public const int menu_change_db = 2131230903; + + // aapt resource value: 0x7f0800a6 + public const int menu_change_key = 2131230886; + + // aapt resource value: 0x7f0800a7 + public const int menu_copy_pass = 2131230887; + + // aapt resource value: 0x7f0800a8 + public const int menu_copy_user = 2131230888; + + // aapt resource value: 0x7f0800a9 + public const int menu_create = 2131230889; // aapt resource value: 0x7f0800ab - public const int menu_donate = 2131230891; + public const int menu_db_settings = 2131230891; // aapt resource value: 0x7f0800ac - public const int menu_edit = 2131230892; + public const int menu_delete = 2131230892; // aapt resource value: 0x7f0800ad - public const int menu_hide_password = 2131230893; + public const int menu_donate = 2131230893; // aapt resource value: 0x7f0800ae - public const int menu_homepage = 2131230894; + public const int menu_edit = 2131230894; // aapt resource value: 0x7f0800af - public const int menu_lock = 2131230895; + public const int menu_hide_password = 2131230895; // aapt resource value: 0x7f0800b0 - public const int menu_open = 2131230896; + public const int menu_homepage = 2131230896; // aapt resource value: 0x7f0800b1 - public const int menu_rename = 2131230897; + public const int menu_lock = 2131230897; // aapt resource value: 0x7f0800b2 - public const int menu_search = 2131230898; + public const int menu_open = 2131230898; // aapt resource value: 0x7f0800b3 - public const int menu_search_advanced = 2131230899; + public const int menu_rename = 2131230899; // aapt resource value: 0x7f0800b4 - public const int menu_url = 2131230900; + public const int menu_search = 2131230900; // aapt resource value: 0x7f0800b5 - public const int minus = 2131230901; + public const int menu_search_advanced = 2131230901; // aapt resource value: 0x7f0800b6 - public const int never = 2131230902; + public const int menu_url = 2131230902; // aapt resource value: 0x7f0800b8 - public const int no = 2131230904; + public const int minus = 2131230904; // aapt resource value: 0x7f0800b9 - public const int no_keys = 2131230905; - - // aapt resource value: 0x7f0800ba - public const int no_results = 2131230906; + public const int never = 2131230905; // aapt resource value: 0x7f0800bb - public const int no_url_handler = 2131230907; + public const int no = 2131230907; - // aapt resource value: 0x7f080050 - public const int not_possible_im_picker = 2131230800; + // aapt resource value: 0x7f0800bc + public const int no_keys = 2131230908; + + // aapt resource value: 0x7f0800bd + public const int no_results = 2131230909; + + // aapt resource value: 0x7f0800be + public const int no_url_handler = 2131230910; + + // aapt resource value: 0x7f080052 + public const int not_possible_im_picker = 2131230802; // aapt resource value: 0x7f08000f public const int oi_filemanager_market = 2131230735; @@ -2055,11 +2133,11 @@ namespace keepass2android // aapt resource value: 0x7f080019 public const int omitbackup_key = 2131230745; - // aapt resource value: 0x7f0800be - public const int omitbackup_summary = 2131230910; + // aapt resource value: 0x7f0800c1 + public const int omitbackup_summary = 2131230913; - // aapt resource value: 0x7f0800bd - public const int omitbackup_title = 2131230909; + // aapt resource value: 0x7f0800c0 + public const int omitbackup_title = 2131230912; // aapt resource value: 0x7f080003 public const int open_entry = 2131230723; @@ -2067,155 +2145,155 @@ namespace keepass2android // aapt resource value: 0x7f080004 public const int open_entry_for_app = 2131230724; - // aapt resource value: 0x7f0800bc - public const int open_recent = 2131230908; - // aapt resource value: 0x7f0800bf - public const int pass_filename = 2131230911; - - // aapt resource value: 0x7f0800c0 - public const int password_title = 2131230912; - - // aapt resource value: 0x7f080051 - public const int please_activate_keyboard = 2131230801; - - // aapt resource value: 0x7f0800c1 - public const int progress_create = 2131230913; + public const int open_recent = 2131230911; // aapt resource value: 0x7f0800c2 - public const int progress_title = 2131230914; - - // aapt resource value: 0x7f080106 - public const int protection = 2131230982; - - // aapt resource value: 0x7f080124 - public const int rate_app = 2131231012; - - // aapt resource value: 0x7f0800e0 - public const int regular_expression = 2131230944; + public const int pass_filename = 2131230914; // aapt resource value: 0x7f0800c3 - public const int remember_keyfile_summary = 2131230915; + public const int password_title = 2131230915; + + // aapt resource value: 0x7f080053 + public const int please_activate_keyboard = 2131230803; // aapt resource value: 0x7f0800c4 - public const int remember_keyfile_title = 2131230916; + public const int progress_create = 2131230916; // aapt resource value: 0x7f0800c5 - public const int remove_from_filelist = 2131230917; + public const int progress_title = 2131230917; + + // aapt resource value: 0x7f080109 + public const int protection = 2131230985; + + // aapt resource value: 0x7f080130 + public const int rate_app = 2131231024; + + // aapt resource value: 0x7f0800e3 + public const int regular_expression = 2131230947; // aapt resource value: 0x7f0800c6 - public const int rijndael = 2131230918; + public const int remember_keyfile_summary = 2131230918; // aapt resource value: 0x7f0800c7 - public const int root = 2131230919; + public const int remember_keyfile_title = 2131230919; // aapt resource value: 0x7f0800c8 - public const int rounds = 2131230920; + public const int remove_from_filelist = 2131230920; // aapt resource value: 0x7f0800c9 - public const int rounds_explaination = 2131230921; + public const int rijndael = 2131230921; // aapt resource value: 0x7f0800ca - public const int rounds_hint = 2131230922; + public const int root = 2131230922; + + // aapt resource value: 0x7f0800cb + public const int rounds = 2131230923; + + // aapt resource value: 0x7f0800cc + public const int rounds_explaination = 2131230924; + + // aapt resource value: 0x7f0800cd + public const int rounds_hint = 2131230925; // aapt resource value: 0x7f080016 public const int rounds_key = 2131230742; - // aapt resource value: 0x7f0800cd - public const int saving_database = 2131230925; - - // aapt resource value: 0x7f0800d4 - public const int search_hint = 2131230932; - - // aapt resource value: 0x7f0800d6 - public const int search_in = 2131230934; - - // aapt resource value: 0x7f0800cf - public const int search_label = 2131230927; - - // aapt resource value: 0x7f0800e9 - public const int search_options = 2131230953; - - // aapt resource value: 0x7f0800d5 - public const int search_results = 2131230933; - - // aapt resource value: 0x7f0800d8 - public const int select_group_then_add = 2131230936; + // aapt resource value: 0x7f0800d0 + public const int saving_database = 2131230928; // aapt resource value: 0x7f0800d7 - public const int select_other_entry = 2131230935; + public const int search_hint = 2131230935; - // aapt resource value: 0x7f08003f - public const int short_app_name = 2131230783; - - // aapt resource value: 0x7f080041 - public const int short_app_name_nonet = 2131230785; - - // aapt resource value: 0x7f0800d0 - public const int show_password = 2131230928; + // aapt resource value: 0x7f0800d9 + public const int search_in = 2131230937; // aapt resource value: 0x7f0800d2 - public const int sort_db = 2131230930; + public const int search_label = 2131230930; + + // aapt resource value: 0x7f0800ec + public const int search_options = 2131230956; + + // aapt resource value: 0x7f0800d8 + public const int search_results = 2131230936; + + // aapt resource value: 0x7f0800db + public const int select_group_then_add = 2131230939; + + // aapt resource value: 0x7f0800da + public const int select_other_entry = 2131230938; + + // aapt resource value: 0x7f080041 + public const int short_app_name = 2131230785; + + // aapt resource value: 0x7f080043 + public const int short_app_name_nonet = 2131230787; + + // aapt resource value: 0x7f0800d3 + public const int show_password = 2131230931; + + // aapt resource value: 0x7f0800d5 + public const int sort_db = 2131230933; // aapt resource value: 0x7f08001b public const int sort_key = 2131230747; + // aapt resource value: 0x7f0800d4 + public const int sort_name = 2131230932; + // aapt resource value: 0x7f0800d1 - public const int sort_name = 2131230929; + public const int space = 2131230929; - // aapt resource value: 0x7f0800ce - public const int space = 2131230926; + // aapt resource value: 0x7f0800d6 + public const int special = 2131230934; - // aapt resource value: 0x7f0800d3 - public const int special = 2131230931; + // aapt resource value: 0x7f0800ef + public const int start_create = 2131230959; - // aapt resource value: 0x7f0800ec - public const int start_create = 2131230956; + // aapt resource value: 0x7f0800f1 + public const int start_create_import = 2131230961; // aapt resource value: 0x7f0800ee - public const int start_create_import = 2131230958; + public const int start_open_file = 2131230958; - // aapt resource value: 0x7f0800eb - public const int start_open_file = 2131230955; + // aapt resource value: 0x7f0800f0 + public const int start_open_url = 2131230960; - // aapt resource value: 0x7f0800ed - public const int start_open_url = 2131230957; + // aapt resource value: 0x7f08012f + public const int suggest_improvements = 2131231023; - // aapt resource value: 0x7f080123 - public const int suggest_improvements = 2131231011; + // aapt resource value: 0x7f08014f + public const int synchronize_database_menu = 2131231055; - // aapt resource value: 0x7f08001c - public const int timeout_key = 2131230748; - - // aapt resource value: 0x7f080125 - public const int translate_app = 2131231013; - - // aapt resource value: 0x7f0800d9 - public const int twofish = 2131230937; - - // aapt resource value: 0x7f0800da - public const int underline = 2131230938; - - // aapt resource value: 0x7f0800db - public const int unsupported_db_version = 2131230939; + // aapt resource value: 0x7f080131 + public const int translate_app = 2131231025; // aapt resource value: 0x7f0800dc - public const int uppercase = 2131230940; - - // aapt resource value: 0x7f0800df - public const int version_label = 2131230943; + public const int twofish = 2131230940; // aapt resource value: 0x7f0800dd - public const int warning_read_only = 2131230941; + public const int underline = 2131230941; // aapt resource value: 0x7f0800de - public const int warning_unmounted = 2131230942; + public const int unsupported_db_version = 2131230942; + + // aapt resource value: 0x7f0800df + public const int uppercase = 2131230943; + + // aapt resource value: 0x7f0800e2 + public const int version_label = 2131230946; + + // aapt resource value: 0x7f0800e0 + public const int warning_read_only = 2131230944; + + // aapt resource value: 0x7f0800e1 + public const int warning_unmounted = 2131230945; // aapt resource value: 0x7f080001 public const int word_separators = 2131230721; - // aapt resource value: 0x7f0800b7 - public const int yes = 2131230903; + // aapt resource value: 0x7f0800ba + public const int yes = 2131230906; static String() { diff --git a/src/keepass2android/Resources/menu-v11/group.xml b/src/keepass2android/Resources/menu-v11/group.xml index ccaff7c9..91a020ca 100644 --- a/src/keepass2android/Resources/menu-v11/group.xml +++ b/src/keepass2android/Resources/menu-v11/group.xml @@ -41,11 +41,17 @@ android:title="@string/menu_app_settings" android:showAsAction="ifRoom" /> - - + + - + - diff --git a/src/keepass2android/Resources/values/config.xml b/src/keepass2android/Resources/values/config.xml index e480ab06..8447f3f8 100644 --- a/src/keepass2android/Resources/values/config.xml +++ b/src/keepass2android/Resources/values/config.xml @@ -63,6 +63,7 @@ LastInfoVersion UseFileTransactions + UseOfflineCache CheckForFileChangesOnSave market://details?id= diff --git a/src/keepass2android/Resources/values/strings.xml b/src/keepass2android/Resources/values/strings.xml index db1ea018..5b2e8239 100644 --- a/src/keepass2android/Resources/values/strings.xml +++ b/src/keepass2android/Resources/values/strings.xml @@ -224,6 +224,10 @@ Enter server credentials File transactions Use file transactions for writing databases + Database caching + Keep a copy of remote database files in the application cache directory. This allows to use remote databases even when offline. + Clear cache? + This will delete all cached database files. Any changes you made while being offline which have not yet been synchronized will be lost! Continue? Check for modifications Check whether the file was modified externally before saving changes. @@ -272,12 +276,23 @@ Yes, merge No, overwrite - Synchronizing cached database... - Downloading remote file... - Uploading file... - Restoring remote file... + Synchronizing cached database… + Downloading remote file… + Uploading file… + Restoring remote file… Files are in sync. Database synchronized successfully! + Checking database for changes… + + Could not save to remote: %1$s. Save again or use the Synchronize menu when remote connection is available again. + Could not open from remote: %1$s. Loaded file from local cache. You can still make changes in the database and synchronize them later. + Updated remote file. + Opened local file due to conflict with changes in remote file. Use Synchronize menu to merge. + Remote file and cache are synchronized. + Updated local cache copy of database. + No changes detected. + + Synchronize database… Change log diff --git a/src/keepass2android/Resources/xml/preferences.xml b/src/keepass2android/Resources/xml/preferences.xml index b2424ad5..4672ef88 100644 --- a/src/keepass2android/Resources/xml/preferences.xml +++ b/src/keepass2android/Resources/xml/preferences.xml @@ -156,6 +156,14 @@ android:defaultValue="true" android:title="@string/UseFileTransactions_title" android:key="@string/UseFileTransactions_key" /> + + { _db.ReloadRequested = true; - LockDatabase(false); activity.SetResult(KeePass.ExitReloadDb); activity.Finish(); @@ -334,14 +333,25 @@ namespace keepass2android return new BuiltInFileStorage(); else { - //todo: check if desired - return new CachingFileStorage(new BuiltInFileStorage(), Application.Context.CacheDir.Path, this); + var prefs = PreferenceManager.GetDefaultSharedPreferences(Application.Context); + if (prefs.GetBoolean(Application.Context.Resources.GetString(Resource.String.UseOfflineCache_key), true)) + { + return new CachingFileStorage(new BuiltInFileStorage(), Application.Context.CacheDir.Path, this); + } + else + { + return new BuiltInFileStorage(); + } } } public void TriggerReload(Context ctx) { - AskForReload((Activity)ctx); + Handler handler = new Handler(Looper.MainLooper); + handler.Post(() => + { + AskForReload((Activity) ctx); + }); } @@ -386,21 +396,38 @@ namespace keepass2android public void CouldntSaveToRemote(IOConnectionInfo ioc, Exception e) { - //TODO use resource strings - ShowToast("Couldn't save to remote: "+e.Message+". Save again or use Sync menu when remote connection is available again."); + ShowToast(Application.Context.GetString(Resource.String.CouldNotSaveToRemote, e.Message)); } - //todo: test changes in SaveDb with Cache: Save without conflict, save with conflict - //add test? - + public void CouldntOpenFromRemote(IOConnectionInfo ioc, Exception ex) { - ShowToast("Couldn't open from remote: " + ex.Message+". Loaded file from local cache. You can still make changes in the database and sync them later."); + ShowToast(Application.Context.GetString(Resource.String.CouldNotLoadFromRemote, ex.Message)); + } + + public void UpdatedCachedFileOnLoad(IOConnectionInfo ioc) + { + ShowToast(Application.Context.GetString(Resource.String.UpdatedCachedFileOnLoad)); + } + + public void UpdatedRemoteFileOnLoad(IOConnectionInfo ioc) + { + ShowToast(Application.Context.GetString(Resource.String.UpdatedRemoteFileOnLoad)); } public void NotifyOpenFromLocalDueToConflict(IOConnectionInfo ioc) { - ShowToast("Opened local file due to conflict with changes in remote file. Use Synchronize menu to merge."); + ShowToast(Application.Context.GetString(Resource.String.NotifyOpenFromLocalDueToConflict)); + } + + public void LoadedFromRemoteInSync(IOConnectionInfo ioc) + { + ShowToast(Application.Context.GetString(Resource.String.LoadedFromRemoteInSync)); + } + + public void ClearOfflineCache() + { + new CachingFileStorage(new BuiltInFileStorage(), Application.Context.CacheDir.Path, this).ClearCache(); } } @@ -408,6 +435,7 @@ namespace keepass2android ///Application class for Keepass2Android: Contains static Database variable to be used by all components. #if NoNet [Application(Debuggable=false, Label=AppNames.AppName)] + todo: remove caching preference #else #if RELEASE [Application(Debuggable=false, Label=AppNames.AppName)] diff --git a/src/keepass2android/settings/AppSettingsActivity.cs b/src/keepass2android/settings/AppSettingsActivity.cs index 23596856..dab20311 100644 --- a/src/keepass2android/settings/AppSettingsActivity.cs +++ b/src/keepass2android/settings/AppSettingsActivity.cs @@ -20,6 +20,8 @@ using Android.App; using Android.Content; using Android.OS; using Android.Preferences; +using Android.Widget; +using keepass2android.Io; namespace keepass2android { @@ -42,10 +44,50 @@ namespace keepass2android FindPreference(GetString(Resource.String.keyfile_key)).PreferenceChange += OnRememberKeyFileHistoryChanged; FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += OnShowUnlockedNotificationChanged;; + FindPreference(GetString(Resource.String.UseOfflineCache_key)).PreferenceChange += OnUseOfflineCacheChanged; FindPreference(GetString(Resource.String.db_key)).Enabled = false; } + private void OnUseOfflineCacheChanged(object sender, Preference.PreferenceChangeEventArgs e) + { + //ensure the user gets a matching database + if (App.Kp2a.GetDb().Loaded && !App.Kp2a.GetDb().Ioc.IsLocalFile()) + App.Kp2a.LockDatabase(false); + + if (!(bool)e.NewValue) + { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.SetTitle(GetString(Resource.String.ClearOfflineCache_title)); + + builder.SetMessage(GetString(Resource.String.ClearOfflineCache_question)); + + builder.SetPositiveButton(App.Kp2a.GetResourceString(UiStringKey.yes), (o, args) => + { + try + { + App.Kp2a.ClearOfflineCache(); + } + catch (Exception ex) + { + Kp2aLog.Log(ex.ToString()); + Toast.MakeText(Application.Context, ex.Message, ToastLength.Long).Show(); + } + } + ); + + builder.SetNegativeButton(App.Kp2a.GetResourceString(UiStringKey.no), (o, args) => + { + } + ); + + Dialog dialog = builder.Create(); + dialog.Show(); + + + } + } + internal static void OnRememberKeyFileHistoryChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs) { if (!(bool)eventArgs.NewValue)