Merge branch 'AlexVallat/Keepass2AndroidPerfOpt'
Conflicts: src/KeePassLib2Android/Serialization/IOConnection.cs src/Kp2aBusinessLogic/IKp2aApp.cs src/Kp2aBusinessLogic/database/Database.cs src/keepass2android/Resources/Resource.designer.cs src/keepass2android/app/App.cs src/keepass2android/fileselect/FileSelectActivity.cs
25
.gitignore
vendored
@ -1,3 +1,28 @@
|
|||||||
|
PCtest
|
||||||
|
|
||||||
|
*.suo
|
||||||
|
*.userprefs
|
||||||
|
*.user
|
||||||
|
|
||||||
|
*.designer.cs
|
||||||
|
|
||||||
|
src/java/kp2akeytransform/kp2akeytransform.zip
|
||||||
|
|
||||||
|
src/Kp2aKeyboardBinding/bin
|
||||||
|
src/Kp2aKeyboardBinding/obj
|
||||||
|
|
||||||
|
src/kp2akeytransform/bin
|
||||||
|
src/kp2akeytransform/obj
|
||||||
|
|
||||||
|
src/Kp2aBusinessLogic/bin
|
||||||
|
src/Kp2aBusinessLogic/obj
|
||||||
|
|
||||||
|
src/Kp2aUnitTests/bin
|
||||||
|
src/Kp2aUnitTests/obj
|
||||||
|
|
||||||
|
src/monodroid-unittesting/MonoDroidUnitTesting/bin
|
||||||
|
src/monodroid-unittesting/MonoDroidUnitTesting/obj
|
||||||
|
|
||||||
/src/keepass2android/todos.cs
|
/src/keepass2android/todos.cs
|
||||||
/src/keepass2android/obj
|
/src/keepass2android/obj
|
||||||
/src/keepass2android/bin
|
/src/keepass2android/bin
|
||||||
|
@ -26,17 +26,30 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
private static bool? _logToFile;
|
private static bool? _logToFile;
|
||||||
|
|
||||||
|
private static object _fileLocker = new object();
|
||||||
|
|
||||||
public static void Log(string message)
|
public static void Log(string message)
|
||||||
{
|
{
|
||||||
Android.Util.Log.Debug("KP2A", message);
|
Android.Util.Log.Debug("KP2A", message);
|
||||||
if (LogToFile)
|
if (LogToFile)
|
||||||
|
{
|
||||||
|
lock (_fileLocker)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
using (var streamWriter = File.AppendText(LogFilename))
|
using (var streamWriter = File.AppendText(LogFilename))
|
||||||
{
|
{
|
||||||
string stringToLog = DateTime.Now+":"+DateTime.Now.Millisecond+ " -- " + message;
|
string stringToLog = DateTime.Now + ":" + DateTime.Now.Millisecond + " -- " + message;
|
||||||
streamWriter.WriteLine(stringToLog);
|
streamWriter.WriteLine(stringToLog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Android.Util.Log.Debug("KP2A", "Couldn't write to log file. " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,17 +162,6 @@ namespace KeePassLib.Serialization
|
|||||||
finally { CommonCleanUpRead(sSource, hashedStream); }
|
finally { CommonCleanUpRead(sSource, hashedStream); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CopyStream(Stream input, Stream output)
|
|
||||||
{
|
|
||||||
byte[] buffer = new byte[4096];
|
|
||||||
int read;
|
|
||||||
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
|
|
||||||
{
|
|
||||||
output.Write(buffer, 0, read);
|
|
||||||
}
|
|
||||||
output.Seek(0, SeekOrigin.Begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CommonCleanUpRead(Stream sSource, HashingStreamEx hashedStream)
|
private void CommonCleanUpRead(Stream sSource, HashingStreamEx hashedStream)
|
||||||
{
|
{
|
||||||
hashedStream.Close();
|
hashedStream.Close();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
|
using System.IO;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
@ -13,11 +14,15 @@ namespace keepass2android
|
|||||||
/// This also contains methods which are UI specific and should be replacable for testing.
|
/// This also contains methods which are UI specific and should be replacable for testing.
|
||||||
public interface IKp2aApp
|
public interface IKp2aApp
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Locks the currently open database, quicklocking if available (unless false is passed for allowQuickUnlock)
|
||||||
|
/// </summary>
|
||||||
|
void LockDatabase(bool allowQuickUnlock = true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the flag that the database needs to be locked.
|
/// Loads the specified data as the currently open database, as unlocked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SetShutdown();
|
void LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, string s, string keyFile, ProgressDialogStatusLogger statusLogger);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the current database
|
/// Returns the current database
|
||||||
|
@ -72,25 +72,6 @@ namespace keepass2android
|
|||||||
set { _loaded = value; }
|
set { _loaded = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Open
|
|
||||||
{
|
|
||||||
get { return Loaded && (!Locked); }
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _locked;
|
|
||||||
public bool Locked
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _locked;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Kp2aLog.Log("Locked=" + _locked);
|
|
||||||
_locked = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DidOpenFileChange()
|
public bool DidOpenFileChange()
|
||||||
{
|
{
|
||||||
if (Loaded == false)
|
if (Loaded == false)
|
||||||
@ -102,7 +83,10 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void LoadData(IKp2aApp app, IOConnectionInfo iocInfo, String password, String keyfile, ProgressDialogStatusLogger status)
|
/// <summary>
|
||||||
|
/// Do not call this method directly. Call App.Kp2a.LoadDatabase instead.
|
||||||
|
/// </summary>
|
||||||
|
public void LoadData(IKp2aApp app, IOConnectionInfo iocInfo, MemoryStream databaseData, String password, String keyfile, ProgressDialogStatusLogger status)
|
||||||
{
|
{
|
||||||
PwDatabase pwDatabase = new PwDatabase();
|
PwDatabase pwDatabase = new PwDatabase();
|
||||||
|
|
||||||
@ -121,11 +105,12 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFileStorage fileStorage = _app.GetFileStorage(iocInfo);
|
||||||
|
var filename = fileStorage.GetFilenameWithoutPathAndExt(iocInfo);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IFileStorage fileStorage = _app.GetFileStorage(iocInfo);
|
|
||||||
var fileVersion = _app.GetFileStorage(iocInfo).GetCurrentFileVersionFast(iocInfo);
|
var fileVersion = _app.GetFileStorage(iocInfo).GetCurrentFileVersionFast(iocInfo);
|
||||||
pwDatabase.Open(fileStorage.OpenFileForRead(iocInfo), fileStorage.GetFilenameWithoutPathAndExt(iocInfo), iocInfo, compositeKey, status);
|
pwDatabase.Open(databaseData ?? fileStorage.OpenFileForRead(iocInfo), filename, iocInfo, compositeKey, status);
|
||||||
LastFileVersion = fileVersion;
|
LastFileVersion = fileVersion;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@ -135,8 +120,13 @@ namespace keepass2android
|
|||||||
//if we don't get a password, we don't know whether this means "empty password" or "no password"
|
//if we don't get a password, we don't know whether this means "empty password" or "no password"
|
||||||
//retry without password:
|
//retry without password:
|
||||||
compositeKey.RemoveUserKey(compositeKey.GetUserKey(typeof (KcpPassword)));
|
compositeKey.RemoveUserKey(compositeKey.GetUserKey(typeof (KcpPassword)));
|
||||||
pwDatabase.Open(iocInfo, compositeKey, status);
|
if (databaseData != null)
|
||||||
|
{
|
||||||
|
databaseData.Seek(0, SeekOrigin.Begin);
|
||||||
}
|
}
|
||||||
|
var fileVersion = _app.GetFileStorage(iocInfo).GetCurrentFileVersionFast(iocInfo);
|
||||||
|
pwDatabase.Open(databaseData ?? fileStorage.OpenFileForRead(iocInfo), filename, iocInfo, compositeKey, status);
|
||||||
|
LastFileVersion = fileVersion; }
|
||||||
else throw;
|
else throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,15 +141,6 @@ namespace keepass2android
|
|||||||
SearchHelper = new SearchDbHelper(app);
|
SearchHelper = new SearchDbHelper(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool QuickUnlockEnabled { get; set; }
|
|
||||||
|
|
||||||
//KeyLength of QuickUnlock at time of loading the database.
|
|
||||||
//This is important to not allow an attacker to set the length to 1 when QuickUnlock is started already.
|
|
||||||
public int QuickUnlockKeyLength
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PwGroup SearchForText(String str) {
|
public PwGroup SearchForText(String str) {
|
||||||
PwGroup group = SearchHelper.SearchForText(this, str);
|
PwGroup group = SearchHelper.SearchForText(this, str);
|
||||||
@ -225,7 +206,6 @@ namespace keepass2android
|
|||||||
Root = null;
|
Root = null;
|
||||||
KpDatabase = null;
|
KpDatabase = null;
|
||||||
_loaded = false;
|
_loaded = false;
|
||||||
_locked = false;
|
|
||||||
_reloadRequested = false;
|
_reloadRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ namespace keepass2android
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Let's not bother recovering from a failure to save a deleted entry. It is too much work.
|
// Let's not bother recovering from a failure to save a deleted entry. It is too much work.
|
||||||
App.SetShutdown();
|
App.LockDatabase();
|
||||||
}
|
}
|
||||||
}, OnFinishToRun);
|
}, OnFinishToRun);
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ namespace keepass2android
|
|||||||
Db.Dirty.Add(pgRecycleBin);
|
Db.Dirty.Add(pgRecycleBin);
|
||||||
} else {
|
} else {
|
||||||
// Let's not bother recovering from a failure to save a deleted entry. It is too much work.
|
// Let's not bother recovering from a failure to save a deleted entry. It is too much work.
|
||||||
App.SetShutdown();
|
App.LockDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, OnFinishToRun);
|
}, OnFinishToRun);
|
||||||
|
@ -108,7 +108,7 @@ namespace keepass2android
|
|||||||
Db.Dirty.Add(pgParent);
|
Db.Dirty.Add(pgParent);
|
||||||
} else {
|
} else {
|
||||||
// Let's not bother recovering from a failure to save a deleted group. It is too much work.
|
// Let's not bother recovering from a failure to save a deleted group. It is too much work.
|
||||||
App.SetShutdown();
|
App.LockDatabase();
|
||||||
}
|
}
|
||||||
}, OnFinishToRun);
|
}, OnFinishToRun);
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Let's not bother recovering from a failure to save a deleted group. It is too much work.
|
// Let's not bother recovering from a failure to save a deleted group. It is too much work.
|
||||||
_app.SetShutdown();
|
_app.LockDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Run();
|
base.Run();
|
||||||
|
@ -16,21 +16,25 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
{
|
{
|
||||||
public class LoadDb : RunnableOnFinish {
|
public class LoadDb : RunnableOnFinish {
|
||||||
private readonly IOConnectionInfo _ioc;
|
private readonly IOConnectionInfo _ioc;
|
||||||
|
private readonly Task<MemoryStream> _databaseData;
|
||||||
private readonly String _pass;
|
private readonly String _pass;
|
||||||
private readonly String _key;
|
private readonly String _key;
|
||||||
private readonly IKp2aApp _app;
|
private readonly IKp2aApp _app;
|
||||||
private readonly bool _rememberKeyfile;
|
private readonly bool _rememberKeyfile;
|
||||||
|
|
||||||
public LoadDb(IKp2aApp app, IOConnectionInfo ioc, String pass, String key, OnFinish finish): base(finish)
|
public LoadDb(IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, String pass, String key, OnFinish finish): base(finish)
|
||||||
{
|
{
|
||||||
_app = app;
|
_app = app;
|
||||||
_ioc = ioc;
|
_ioc = ioc;
|
||||||
|
_databaseData = databaseData;
|
||||||
_pass = pass;
|
_pass = pass;
|
||||||
_key = key;
|
_key = key;
|
||||||
|
|
||||||
@ -44,7 +48,7 @@ namespace keepass2android
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
StatusLogger.UpdateMessage(UiStringKey.loading_database);
|
StatusLogger.UpdateMessage(UiStringKey.loading_database);
|
||||||
_app.GetDb().LoadData (_app, _ioc, _pass, _key, StatusLogger);
|
_app.LoadDatabase(_ioc, _databaseData == null ? null : _databaseData.Result, _pass, _key, StatusLogger);
|
||||||
SaveFileData (_ioc, _key);
|
SaveFileData (_ioc, _key);
|
||||||
|
|
||||||
} catch (KeyFileException) {
|
} catch (KeyFileException) {
|
||||||
|
@ -95,7 +95,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
Database db = App.Kp2a.GetDb();
|
Database db = App.Kp2a.GetDb();
|
||||||
// Likely the app has been killed exit the activity
|
// Likely the app has been killed exit the activity
|
||||||
if (! db.Loaded)
|
if (!db.Loaded || (App.Kp2a.QuickLocked))
|
||||||
{
|
{
|
||||||
Finish();
|
Finish();
|
||||||
return;
|
return;
|
||||||
@ -600,9 +600,7 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case Resource.Id.menu_lock:
|
case Resource.Id.menu_lock:
|
||||||
App.Kp2a.SetShutdown();
|
App.Kp2a.LockDatabase();
|
||||||
SetResult(KeePass.ExitLock);
|
|
||||||
Finish();
|
|
||||||
return true;
|
return true;
|
||||||
case Resource.Id.menu_translate:
|
case Resource.Id.menu_translate:
|
||||||
try {
|
try {
|
||||||
|
@ -92,8 +92,7 @@ namespace keepass2android
|
|||||||
_closeForReload = false;
|
_closeForReload = false;
|
||||||
|
|
||||||
// Likely the app has been killed exit the activity
|
// Likely the app has been killed exit the activity
|
||||||
Database db = App.Kp2a.GetDb();
|
if (!App.Kp2a.DatabaseIsUnlocked)
|
||||||
if (! db.Open)
|
|
||||||
{
|
{
|
||||||
Finish();
|
Finish();
|
||||||
return;
|
return;
|
||||||
@ -107,6 +106,8 @@ namespace keepass2android
|
|||||||
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
Database db = App.Kp2a.GetDb();
|
||||||
|
|
||||||
App.Kp2a.EntryEditActivityState = new EntryEditActivityState();
|
App.Kp2a.EntryEditActivityState = new EntryEditActivityState();
|
||||||
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
|
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
|
||||||
State.ShowPassword = ! prefs.GetBoolean(GetString(Resource.String.maskpass_key), Resources.GetBoolean(Resource.Boolean.maskpass_default));
|
State.ShowPassword = ! prefs.GetBoolean(GetString(Resource.String.maskpass_key), Resources.GetBoolean(Resource.Boolean.maskpass_default));
|
||||||
|
@ -240,9 +240,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
case Resource.Id.menu_lock:
|
case Resource.Id.menu_lock:
|
||||||
App.Kp2a.SetShutdown();
|
App.Kp2a.LockDatabase();
|
||||||
SetResult(KeePass.ExitLock);
|
|
||||||
Finish();
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Resource.Id.menu_search:
|
case Resource.Id.menu_search:
|
||||||
@ -251,7 +249,7 @@ namespace keepass2android
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Resource.Id.menu_app_settings:
|
case Resource.Id.menu_app_settings:
|
||||||
AppSettingsActivity.Launch(this);
|
DatabaseSettingsActivity.Launch(this);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Resource.Id.menu_change_master_key:
|
case Resource.Id.menu_change_master_key:
|
||||||
@ -353,8 +351,7 @@ namespace keepass2android
|
|||||||
Toast.MakeText(_act, "Unrecoverable error: " + Message, ToastLength.Long).Show();
|
Toast.MakeText(_act, "Unrecoverable error: " + Message, ToastLength.Long).Show();
|
||||||
});
|
});
|
||||||
|
|
||||||
App.Kp2a.SetShutdown();
|
App.Kp2a.LockDatabase(false);
|
||||||
_act.Finish();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ using Android.Preferences;
|
|||||||
using Android.Content.PM;
|
using Android.Content.PM;
|
||||||
using Android.Text;
|
using Android.Text;
|
||||||
using Android.Text.Method;
|
using Android.Text.Method;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
{
|
{
|
||||||
@ -37,12 +38,8 @@ namespace keepass2android
|
|||||||
public const Result ExitLock = Result.FirstUser+1;
|
public const Result ExitLock = Result.FirstUser+1;
|
||||||
public const Result ExitRefresh = Result.FirstUser+2;
|
public const Result ExitRefresh = Result.FirstUser+2;
|
||||||
public const Result ExitRefreshTitle = Result.FirstUser+3;
|
public const Result ExitRefreshTitle = Result.FirstUser+3;
|
||||||
public const Result ExitForceLock = Result.FirstUser+4;
|
public const Result ExitCloseAfterTaskComplete = Result.FirstUser+4;
|
||||||
public const Result ExitQuickUnlock = Result.FirstUser+5;
|
public const Result ExitReloadDb = Result.FirstUser+6;
|
||||||
public const Result ExitCloseAfterTaskComplete = Result.FirstUser+6;
|
|
||||||
public const Result ExitChangeDb = Result.FirstUser+7;
|
|
||||||
public const Result ExitForceLockAndChangeDb = Result.FirstUser+8;
|
|
||||||
public const Result ExitReloadDb = Result.FirstUser+9;
|
|
||||||
|
|
||||||
AppTask _appTask;
|
AppTask _appTask;
|
||||||
|
|
||||||
@ -106,7 +103,7 @@ namespace keepass2android
|
|||||||
Dialog dialog = builder.Create();
|
Dialog dialog = builder.Create();
|
||||||
dialog.DismissEvent += (sender, e) =>
|
dialog.DismissEvent += (sender, e) =>
|
||||||
{
|
{
|
||||||
StartFileSelect();
|
LaunchNextActivity();
|
||||||
};
|
};
|
||||||
dialog.Show();
|
dialog.Show();
|
||||||
TextView message = (TextView) dialog.FindViewById(Android.Resource.Id.Message);
|
TextView message = (TextView) dialog.FindViewById(Android.Resource.Id.Message);
|
||||||
@ -119,7 +116,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
StartFileSelect();
|
LaunchNextActivity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -157,12 +154,42 @@ namespace keepass2android
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartFileSelect() {
|
IOConnectionInfo LoadIoc(string defaultFileName)
|
||||||
Intent intent = new Intent(this, typeof(FileSelectActivity));
|
{
|
||||||
//TEST Intent intent = new Intent(this, typeof(EntryActivity));
|
return App.Kp2a.FileDbHelper.CursorToIoc(App.Kp2a.FileDbHelper.FetchFileByName(defaultFileName));
|
||||||
//Intent intent = new Intent(this, typeof(SearchActivity));
|
}
|
||||||
//Intent intent = new Intent(this, typeof(QuickUnlock));
|
|
||||||
|
|
||||||
|
private void LaunchNextActivity() {
|
||||||
|
|
||||||
|
if (!App.Kp2a.GetDb().Loaded)
|
||||||
|
{
|
||||||
|
// Load default database
|
||||||
|
ISharedPreferences prefs = Android.Preferences.PreferenceManager.GetDefaultSharedPreferences(this);
|
||||||
|
String defaultFileName = prefs.GetString(PasswordActivity.KeyDefaultFilename, "");
|
||||||
|
|
||||||
|
if (defaultFileName.Length > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PasswordActivity.Launch(this, LoadIoc(defaultFileName), _appTask);
|
||||||
|
Finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Toast.MakeText(this, e.Message, ToastLength.Long);
|
||||||
|
// Ignore exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PasswordActivity.Launch(this, App.Kp2a.GetDb().Ioc, _appTask);
|
||||||
|
Finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Intent intent = new Intent(this, typeof(FileSelectActivity));
|
||||||
_appTask.ToIntent(intent);
|
_appTask.ToIntent(intent);
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,8 +56,7 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Kp2aLog.Log(" Loaded=" + App.Kp2a.GetDb().Loaded + ", Locked=" + App.Kp2a.GetDb().Locked
|
Kp2aLog.Log(" DatabaseIsUnlocked=" + App.Kp2a.DatabaseIsUnlocked);
|
||||||
+ ", shutdown=" + App.Kp2a.IsShutdown());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,10 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
|
using Android.App;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
@ -26,12 +29,25 @@ namespace keepass2android
|
|||||||
/// Checks in OnResume whether the timeout occured and the database must be locked/closed.
|
/// Checks in OnResume whether the timeout occured and the database must be locked/closed.
|
||||||
public class LockCloseActivity : LockingActivity {
|
public class LockCloseActivity : LockingActivity {
|
||||||
|
|
||||||
IOConnectionInfo _ioc;
|
private IOConnectionInfo _ioc;
|
||||||
|
private BroadcastReceiver _intentReceiver;
|
||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState)
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
base.OnCreate(savedInstanceState);
|
base.OnCreate(savedInstanceState);
|
||||||
_ioc = App.Kp2a.GetDb().Ioc;
|
_ioc = App.Kp2a.GetDb().Ioc;
|
||||||
|
|
||||||
|
_intentReceiver = new LockCloseActivityBroadcastReceiver(this);
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.AddAction(Intents.DatabaseLocked);
|
||||||
|
RegisterReceiver(_intentReceiver, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDestroy()
|
||||||
|
{
|
||||||
|
UnregisterReceiver(_intentReceiver);
|
||||||
|
|
||||||
|
base.OnDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -49,9 +65,32 @@ namespace keepass2android
|
|||||||
App.Kp2a.CheckForOpenFileChanged(this);
|
App.Kp2a.CheckForOpenFileChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnLockDatabase()
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Finishing " + ComponentName.ClassName + " due to database lock");
|
||||||
|
|
||||||
|
SetResult(KeePass.ExitLock);
|
||||||
|
Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LockCloseActivityBroadcastReceiver : BroadcastReceiver
|
||||||
|
{
|
||||||
|
readonly LockCloseActivity _service;
|
||||||
|
public LockCloseActivityBroadcastReceiver(LockCloseActivity service)
|
||||||
|
{
|
||||||
|
_service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReceive(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
switch (intent.Action)
|
||||||
|
{
|
||||||
|
case Intents.DatabaseLocked:
|
||||||
|
_service.OnLockDatabase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Runtime;
|
using Android.Runtime;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
@ -33,11 +34,18 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
|
|
||||||
IOConnectionInfo _ioc;
|
IOConnectionInfo _ioc;
|
||||||
|
private BroadcastReceiver _intentReceiver;
|
||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState)
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
base.OnCreate(savedInstanceState);
|
base.OnCreate(savedInstanceState);
|
||||||
_ioc = App.Kp2a.GetDb().Ioc;
|
_ioc = App.Kp2a.GetDb().Ioc;
|
||||||
|
|
||||||
|
_intentReceiver = new LockCloseListActivityBroadcastReceiver(this);
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.AddAction(Intents.DatabaseLocked);
|
||||||
|
RegisterReceiver(_intentReceiver, filter);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LockCloseListActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
public LockCloseListActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
||||||
@ -57,6 +65,39 @@ namespace keepass2android
|
|||||||
App.Kp2a.CheckForOpenFileChanged(this);
|
App.Kp2a.CheckForOpenFileChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDestroy()
|
||||||
|
{
|
||||||
|
UnregisterReceiver(_intentReceiver);
|
||||||
|
|
||||||
|
base.OnDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLockDatabase()
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Finishing " + ComponentName.ClassName + " due to database lock");
|
||||||
|
|
||||||
|
SetResult(KeePass.ExitLock);
|
||||||
|
Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LockCloseListActivityBroadcastReceiver : BroadcastReceiver
|
||||||
|
{
|
||||||
|
readonly LockCloseListActivity _service;
|
||||||
|
public LockCloseListActivityBroadcastReceiver(LockCloseListActivity service)
|
||||||
|
{
|
||||||
|
_service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReceive(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
switch (intent.Action)
|
||||||
|
{
|
||||||
|
case Intents.DatabaseLocked:
|
||||||
|
_service.OnLockDatabase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
@ -25,11 +26,18 @@ namespace keepass2android
|
|||||||
|
|
||||||
|
|
||||||
IOConnectionInfo _ioc;
|
IOConnectionInfo _ioc;
|
||||||
|
private BroadcastReceiver _intentReceiver;
|
||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState)
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
base.OnCreate(savedInstanceState);
|
base.OnCreate(savedInstanceState);
|
||||||
_ioc = App.Kp2a.GetDb().Ioc;
|
_ioc = App.Kp2a.GetDb().Ioc;
|
||||||
|
|
||||||
|
|
||||||
|
_intentReceiver = new LockingClosePreferenceActivityBroadcastReceiver(this);
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.AddAction(Intents.DatabaseLocked);
|
||||||
|
RegisterReceiver(_intentReceiver, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnResume() {
|
protected override void OnResume() {
|
||||||
@ -37,6 +45,41 @@ namespace keepass2android
|
|||||||
|
|
||||||
TimeoutHelper.CheckShutdown(this, _ioc);
|
TimeoutHelper.CheckShutdown(this, _ioc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override void OnDestroy()
|
||||||
|
{
|
||||||
|
UnregisterReceiver(_intentReceiver);
|
||||||
|
|
||||||
|
base.OnDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLockDatabase()
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Finishing " + ComponentName.ClassName + " due to database lock");
|
||||||
|
|
||||||
|
SetResult(KeePass.ExitLock);
|
||||||
|
Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LockingClosePreferenceActivityBroadcastReceiver : BroadcastReceiver
|
||||||
|
{
|
||||||
|
readonly LockingClosePreferenceActivity _service;
|
||||||
|
public LockingClosePreferenceActivityBroadcastReceiver(LockingClosePreferenceActivity service)
|
||||||
|
{
|
||||||
|
_service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReceive(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
switch (intent.Action)
|
||||||
|
{
|
||||||
|
case Intents.DatabaseLocked:
|
||||||
|
_service.OnLockDatabase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
@ -29,6 +30,9 @@ using Android.Text;
|
|||||||
using Android.Content.PM;
|
using Android.Content.PM;
|
||||||
using KeePassLib.Keys;
|
using KeePassLib.Keys;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
|
using KeePassLib.Utility;
|
||||||
|
|
||||||
|
using MemoryStream = System.IO.MemoryStream;
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
{
|
{
|
||||||
@ -49,11 +53,14 @@ namespace keepass2android
|
|||||||
|
|
||||||
private const String ViewIntent = "android.intent.action.VIEW";
|
private const String ViewIntent = "android.intent.action.VIEW";
|
||||||
|
|
||||||
|
private Task<MemoryStream> _loadDbTask;
|
||||||
private IOConnectionInfo _ioConnection;
|
private IOConnectionInfo _ioConnection;
|
||||||
private String _keyFile;
|
private String _keyFile;
|
||||||
private bool _rememberKeyfile;
|
private bool _rememberKeyfile;
|
||||||
ISharedPreferences _prefs;
|
ISharedPreferences _prefs;
|
||||||
|
|
||||||
|
private bool _started;
|
||||||
|
|
||||||
public PasswordActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
public PasswordActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
||||||
: base(javaReference, transfer)
|
: base(javaReference, transfer)
|
||||||
{
|
{
|
||||||
@ -123,114 +130,28 @@ namespace keepass2android
|
|||||||
public void LaunchNextActivity()
|
public void LaunchNextActivity()
|
||||||
{
|
{
|
||||||
AppTask.AfterUnlockDatabase(this);
|
AppTask.AfterUnlockDatabase(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnloadDatabase()
|
|
||||||
{
|
|
||||||
App.Kp2a.GetDb().Clear();
|
|
||||||
StopService(new Intent(this, typeof(QuickUnlockForegroundService)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void LockDatabase()
|
|
||||||
{
|
|
||||||
SetResult(KeePass.ExitLock);
|
|
||||||
SetEditText(Resource.Id.password, "");
|
|
||||||
if (App.Kp2a.GetDb().QuickUnlockEnabled)
|
|
||||||
App.Kp2a.GetDb().Locked = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnloadDatabase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LockAndClose()
|
|
||||||
{
|
|
||||||
LockDatabase();
|
|
||||||
Finish();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryStartQuickUnlock()
|
|
||||||
{
|
|
||||||
if (!App.Kp2a.GetDb().QuickUnlockEnabled)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (App.Kp2a.GetDb().KpDatabase.MasterKey.ContainsType(typeof(KcpPassword)) == false)
|
|
||||||
return false;
|
|
||||||
KcpPassword kcpPassword = (KcpPassword)App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey(typeof(KcpPassword));
|
|
||||||
String password = kcpPassword.Password.ReadString();
|
|
||||||
|
|
||||||
if (password.Length == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
App.Kp2a.GetDb().Locked = true;
|
|
||||||
|
|
||||||
Intent i = new Intent(this, typeof(QuickUnlock));
|
|
||||||
PutIoConnectionToIntent(_ioConnection, i);
|
|
||||||
Kp2aLog.Log("Starting QuickUnlock");
|
|
||||||
StartActivityForResult(i,0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StartQuickUnlockForegroundService()
|
|
||||||
{
|
|
||||||
if (App.Kp2a.GetDb().QuickUnlockEnabled)
|
|
||||||
{
|
|
||||||
StartService(new Intent(this, typeof(QuickUnlockForegroundService)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _startedWithActivityResult;
|
|
||||||
|
|
||||||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||||
{
|
{
|
||||||
base.OnActivityResult(requestCode, resultCode, data);
|
base.OnActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
_startedWithActivityResult = true;
|
|
||||||
Kp2aLog.Log("PasswordActivity.OnActivityResult "+resultCode+"/"+requestCode);
|
Kp2aLog.Log("PasswordActivity.OnActivityResult "+resultCode+"/"+requestCode);
|
||||||
|
|
||||||
if (resultCode != KeePass.ExitCloseAfterTaskComplete)
|
|
||||||
{
|
|
||||||
//Stop service when app activity is left
|
|
||||||
StopService(new Intent(this, typeof(CopyToClipboardService)));
|
|
||||||
}
|
|
||||||
|
|
||||||
//NOTE: original code from k eepassdroid used switch ((Android.App.Result)requestCode) { (but doesn't work here, although k eepassdroid works)
|
//NOTE: original code from k eepassdroid used switch ((Android.App.Result)requestCode) { (but doesn't work here, although k eepassdroid works)
|
||||||
switch(resultCode) {
|
switch(resultCode) {
|
||||||
|
|
||||||
case KeePass.ExitNormal:
|
case KeePass.ExitNormal: // Returned to this screen using the Back key, treat as locking the database
|
||||||
if (!TryStartQuickUnlock())
|
App.Kp2a.LockDatabase();
|
||||||
{
|
|
||||||
SetEditText(Resource.Id.password, "");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeePass.ExitLock:
|
case KeePass.ExitLock:
|
||||||
if (!TryStartQuickUnlock())
|
// The database has already been locked, and the quick unlock screen will be shown if appropriate
|
||||||
{
|
|
||||||
LockAndClose();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KeePass.ExitForceLock:
|
|
||||||
SetEditText(Resource.Id.password, "");
|
|
||||||
UnloadDatabase();
|
|
||||||
break;
|
|
||||||
case KeePass.ExitForceLockAndChangeDb:
|
|
||||||
UnloadDatabase();
|
|
||||||
Finish();
|
|
||||||
break;
|
|
||||||
case KeePass.ExitChangeDb:
|
|
||||||
LockAndClose();
|
|
||||||
break;
|
break;
|
||||||
case KeePass.ExitCloseAfterTaskComplete:
|
case KeePass.ExitCloseAfterTaskComplete:
|
||||||
|
// Do not lock the database
|
||||||
SetResult(KeePass.ExitCloseAfterTaskComplete);
|
SetResult(KeePass.ExitCloseAfterTaskComplete);
|
||||||
Finish();
|
Finish();
|
||||||
break;
|
break;
|
||||||
case KeePass.ExitQuickUnlock:
|
|
||||||
App.Kp2a.GetDb().Locked = false;
|
|
||||||
LaunchNextActivity();
|
|
||||||
break;
|
|
||||||
case KeePass.ExitReloadDb:
|
case KeePass.ExitReloadDb:
|
||||||
//if the activity was killed, fill password/keyfile so the user can directly hit load again
|
//if the activity was killed, fill password/keyfile so the user can directly hit load again
|
||||||
if (App.Kp2a.GetDb().Loaded)
|
if (App.Kp2a.GetDb().Loaded)
|
||||||
@ -252,9 +173,9 @@ namespace keepass2android
|
|||||||
SetEditText(Resource.Id.pass_keyfile, kcpKeyfile.Path);
|
SetEditText(Resource.Id.pass_keyfile, kcpKeyfile.Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UnloadDatabase();
|
App.Kp2a.LockDatabase(false);
|
||||||
break;
|
break;
|
||||||
case Result.Ok:
|
case Result.Ok: // Key file browse dialog OK'ed.
|
||||||
if (requestCode == Intents.RequestCodeFileBrowseForKeyfile) {
|
if (requestCode == Intents.RequestCodeFileBrowseForKeyfile) {
|
||||||
string filename = Util.IntentToFilename(data);
|
string filename = Util.IntentToFilename(data);
|
||||||
if (filename != null) {
|
if (filename != null) {
|
||||||
@ -331,6 +252,13 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (App.Kp2a.GetDb().Loaded && App.Kp2a.GetDb().Ioc != null &&
|
||||||
|
App.Kp2a.GetDb().Ioc.GetDisplayName() != _ioConnection.GetDisplayName())
|
||||||
|
{
|
||||||
|
// A different database is currently loaded, unload it before loading the new one requested
|
||||||
|
App.Kp2a.LockDatabase(false);
|
||||||
|
}
|
||||||
|
|
||||||
AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
|
AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
|
||||||
|
|
||||||
SetContentView(Resource.Layout.password);
|
SetContentView(Resource.Layout.password);
|
||||||
@ -343,8 +271,7 @@ namespace keepass2android
|
|||||||
Window.SetSoftInputMode(SoftInput.StateVisible);
|
Window.SetSoftInputMode(SoftInput.StateVisible);
|
||||||
|
|
||||||
Button confirmButton = (Button)FindViewById(Resource.Id.pass_ok);
|
Button confirmButton = (Button)FindViewById(Resource.Id.pass_ok);
|
||||||
confirmButton.Click += (sender, e) =>
|
confirmButton.Click += (sender, e) => {
|
||||||
{
|
|
||||||
String pass = GetEditText(Resource.Id.password);
|
String pass = GetEditText(Resource.Id.password);
|
||||||
String key = GetEditText(Resource.Id.pass_keyfile);
|
String key = GetEditText(Resource.Id.pass_keyfile);
|
||||||
if (pass.Length == 0 && key.Length == 0)
|
if (pass.Length == 0 && key.Length == 0)
|
||||||
@ -353,20 +280,16 @@ namespace keepass2android
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear before we load
|
|
||||||
UnloadDatabase();
|
|
||||||
|
|
||||||
// Clear the shutdown flag
|
|
||||||
App.Kp2a.ClearShutdown();
|
|
||||||
|
|
||||||
CheckBox cbQuickUnlock = (CheckBox)FindViewById(Resource.Id.enable_quickunlock);
|
CheckBox cbQuickUnlock = (CheckBox)FindViewById(Resource.Id.enable_quickunlock);
|
||||||
App.Kp2a.GetDb().QuickUnlockEnabled = cbQuickUnlock.Checked;
|
App.Kp2a.SetQuickUnlockEnabled(cbQuickUnlock.Checked);
|
||||||
App.Kp2a.GetDb().QuickUnlockKeyLength = int.Parse(_prefs.GetString(GetString(Resource.String.QuickUnlockLength_key), GetString(Resource.String.QuickUnlockLength_default)));
|
|
||||||
|
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
LoadDb task = new LoadDb(App.Kp2a, _ioConnection, pass, key, new AfterLoad(handler, this));
|
LoadDb task = new LoadDb(App.Kp2a, _ioConnection, _loadDbTask, pass, key, new AfterLoad(handler, this));
|
||||||
ProgressTask pt = new ProgressTask(App.Kp2a, this, task);
|
_loadDbTask = null; // prevent accidental re-use
|
||||||
pt.Run();
|
|
||||||
|
SetNewDefaultFile();
|
||||||
|
|
||||||
|
new ProgressTask(App.Kp2a, this, task).Run();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*CheckBox checkBox = (CheckBox) FindViewById(Resource.Id.show_password);
|
/*CheckBox checkBox = (CheckBox) FindViewById(Resource.Id.show_password);
|
||||||
@ -394,31 +317,7 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CheckBox defaultCheck = (CheckBox)FindViewById(Resource.Id.default_database);
|
|
||||||
//Don't allow the current file to be the default if we don't have stored credentials
|
|
||||||
if ((_ioConnection.IsLocalFile() == false) && (_ioConnection.CredSaveMode != IOCredSaveMode.SaveCred))
|
|
||||||
{
|
|
||||||
defaultCheck.Enabled = false;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
defaultCheck.Enabled = true;
|
|
||||||
}
|
|
||||||
defaultCheck.CheckedChange += (sender, e) =>
|
|
||||||
{
|
|
||||||
String newDefaultFileName;
|
|
||||||
|
|
||||||
if (e.IsChecked)
|
|
||||||
{
|
|
||||||
newDefaultFileName = _ioConnection.Path;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
newDefaultFileName = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
ISharedPreferencesEditor editor = _prefs.Edit();
|
|
||||||
editor.PutString(KeyDefaultFilename, newDefaultFileName);
|
|
||||||
EditorCompat.Apply(editor);
|
|
||||||
};
|
|
||||||
|
|
||||||
ImageButton browse = (ImageButton)FindViewById(Resource.Id.browse_button);
|
ImageButton browse = (ImageButton)FindViewById(Resource.Id.browse_button);
|
||||||
browse.Click += (sender, evt) =>
|
browse.Click += (sender, evt) =>
|
||||||
@ -438,8 +337,66 @@ namespace keepass2android
|
|||||||
};
|
};
|
||||||
|
|
||||||
RetrieveSettings();
|
RetrieveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetNewDefaultFile()
|
||||||
|
{
|
||||||
|
//Don't allow the current file to be the default if we don't have stored credentials
|
||||||
|
bool makeFileDefault;
|
||||||
|
if ((_ioConnection.IsLocalFile() == false) && (_ioConnection.CredSaveMode != IOCredSaveMode.SaveCred))
|
||||||
|
{
|
||||||
|
makeFileDefault = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
makeFileDefault = true;
|
||||||
|
}
|
||||||
|
String newDefaultFileName;
|
||||||
|
|
||||||
|
if (makeFileDefault)
|
||||||
|
{
|
||||||
|
newDefaultFileName = _ioConnection.Path;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newDefaultFileName = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ISharedPreferencesEditor editor = _prefs.Edit();
|
||||||
|
editor.PutString(KeyDefaultFilename, newDefaultFileName);
|
||||||
|
EditorCompat.Apply(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStart()
|
||||||
|
{
|
||||||
|
base.OnStart();
|
||||||
|
_started = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MemoryStream LoadDbFile()
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Pre-loading database file starting");
|
||||||
|
var fileStorage = App.Kp2a.GetFileStorage(_ioConnection);
|
||||||
|
var stream = fileStorage.OpenFileForRead(_ioConnection);
|
||||||
|
|
||||||
|
var memoryStream = stream as MemoryStream;
|
||||||
|
if (memoryStream == null)
|
||||||
|
{
|
||||||
|
// Read the file into memory
|
||||||
|
int capacity = 4096; // Default initial capacity, if stream can't report it.
|
||||||
|
if (stream.CanSeek)
|
||||||
|
{
|
||||||
|
capacity = (int)stream.Length;
|
||||||
|
}
|
||||||
|
memoryStream = new MemoryStream(capacity);
|
||||||
|
stream.CopyTo(memoryStream);
|
||||||
|
stream.Close();
|
||||||
|
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kp2aLog.Log("Pre-loading database file completed");
|
||||||
|
|
||||||
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSaveInstanceState(Bundle outState)
|
protected override void OnSaveInstanceState(Bundle outState)
|
||||||
@ -448,41 +405,35 @@ namespace keepass2android
|
|||||||
AppTask.ToBundle(outState);
|
AppTask.ToBundle(outState);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnResume() {
|
protected override void OnResume()
|
||||||
|
{
|
||||||
base.OnResume();
|
base.OnResume();
|
||||||
|
|
||||||
// If the application was shutdown make sure to clear the password field, if it
|
// OnResume is run every time the activity comes to the foreground. This code should only run when the activity is started (OnStart), but must
|
||||||
// was saved in the instance state
|
// be run in OnResume rather than OnStart so that it always occurrs after OnActivityResult (when re-creating a killed activity, OnStart occurs before OnActivityResult)
|
||||||
if (App.Kp2a.IsShutdown()) {
|
if (_started && !IsFinishing) //use !IsFinishing to make sure we're not starting another activity when we're already finishing (e.g. due to TaskComplete in OnActivityResult)
|
||||||
LockDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the shutdown flag
|
|
||||||
App.Kp2a.ClearShutdown();
|
|
||||||
|
|
||||||
if (_startedWithActivityResult)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (App.Kp2a.GetDb().Loaded && (App.Kp2a.GetDb().Ioc != null)
|
|
||||||
&& (_ioConnection != null) && (App.Kp2a.GetDb().Ioc.GetDisplayName() == _ioConnection.GetDisplayName()))
|
|
||||||
{
|
{
|
||||||
if (App.Kp2a.GetDb().Locked == false)
|
_started = false;
|
||||||
|
if (App.Kp2a.DatabaseIsUnlocked)
|
||||||
{
|
{
|
||||||
LaunchNextActivity();
|
LaunchNextActivity();
|
||||||
}
|
}
|
||||||
else
|
else if (App.Kp2a.QuickUnlockEnabled && App.Kp2a.QuickLocked)
|
||||||
{
|
{
|
||||||
TryStartQuickUnlock();
|
var i = new Intent(this, typeof(QuickUnlock));
|
||||||
|
PutIoConnectionToIntent(_ioConnection, i);
|
||||||
|
Kp2aLog.Log("Starting QuickUnlock");
|
||||||
|
StartActivityForResult(i, 0);
|
||||||
|
}
|
||||||
|
else if (_loadDbTask == null && _prefs.GetBoolean(GetString(Resource.String.PreloadDatabaseEnabled_key), true))
|
||||||
|
{
|
||||||
|
// Create task to kick off file loading while the user enters the password
|
||||||
|
_loadDbTask = Task.Factory.StartNew<MemoryStream>(LoadDbFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RetrieveSettings() {
|
private void RetrieveSettings() {
|
||||||
String defaultFilename = _prefs.GetString(KeyDefaultFilename, "");
|
|
||||||
if (!String.IsNullOrEmpty(_ioConnection.Path) && _ioConnection.Path.Equals(defaultFilename)) {
|
|
||||||
CheckBox checkbox = (CheckBox) FindViewById(Resource.Id.default_database);
|
|
||||||
checkbox.Checked = true;
|
|
||||||
}
|
|
||||||
CheckBox cbQuickUnlock = (CheckBox)FindViewById(Resource.Id.enable_quickunlock);
|
CheckBox cbQuickUnlock = (CheckBox)FindViewById(Resource.Id.enable_quickunlock);
|
||||||
cbQuickUnlock.Checked = _prefs.GetBoolean(GetString(Resource.String.QuickUnlockDefaultEnabled_key), true);
|
cbQuickUnlock.Checked = _prefs.GetBoolean(GetString(Resource.String.QuickUnlockDefaultEnabled_key), true);
|
||||||
}
|
}
|
||||||
@ -548,23 +499,42 @@ namespace keepass2android
|
|||||||
case Resource.Id.menu_app_settings:
|
case Resource.Id.menu_app_settings:
|
||||||
AppSettingsActivity.Launch(this);
|
AppSettingsActivity.Launch(this);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case Resource.Id.menu_change_db:
|
||||||
|
Intent intent = new Intent(this, typeof(FileSelectActivity));
|
||||||
|
AppTask.ToIntent(intent);
|
||||||
|
StartActivityForResult(intent, 0);
|
||||||
|
Finish();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return base.OnOptionsItemSelected(item);
|
return base.OnOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterLoad : OnFinish {
|
private class AfterLoad : OnFinish {
|
||||||
readonly PasswordActivity _act;
|
readonly PasswordActivity _act;
|
||||||
public AfterLoad(Handler handler, PasswordActivity act):base(handler) {
|
|
||||||
|
public AfterLoad(Handler handler, PasswordActivity act):base(handler)
|
||||||
|
{
|
||||||
_act = act;
|
_act = act;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void Run() {
|
public override void Run() {
|
||||||
if ( Success ) {
|
if ( Success )
|
||||||
_act.StartQuickUnlockForegroundService();
|
{
|
||||||
|
_act.SetEditText(Resource.Id.password, "");
|
||||||
|
|
||||||
_act.LaunchNextActivity();
|
_act.LaunchNextActivity();
|
||||||
} else {
|
|
||||||
|
GC.Collect(); // Ensure temporary memory used while loading is collected - it will contain sensitive data such as username and password, and also the large data of the encrypted database file
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
DisplayMessage(_act);
|
DisplayMessage(_act);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,18 +72,13 @@ namespace keepass2android
|
|||||||
|
|
||||||
TextView txtLabel = (TextView)FindViewById(Resource.Id.QuickUnlock_label);
|
TextView txtLabel = (TextView)FindViewById(Resource.Id.QuickUnlock_label);
|
||||||
|
|
||||||
int quickUnlockLength = App.Kp2a.GetDb().QuickUnlockKeyLength;
|
int quickUnlockLength = App.Kp2a.QuickUnlockKeyLength;
|
||||||
|
|
||||||
txtLabel.Text = GetString(Resource.String.QuickUnlock_label, new Java.Lang.Object[]{quickUnlockLength});
|
txtLabel.Text = GetString(Resource.String.QuickUnlock_label, new Java.Lang.Object[]{quickUnlockLength});
|
||||||
|
|
||||||
EditText pwd= (EditText)FindViewById(Resource.Id.QuickUnlock_password);
|
EditText pwd= (EditText)FindViewById(Resource.Id.QuickUnlock_password);
|
||||||
pwd.SetEms(quickUnlockLength);
|
pwd.SetEms(quickUnlockLength);
|
||||||
pwd.PostDelayed(() => {
|
|
||||||
InputMethodManager keyboard = (InputMethodManager)GetSystemService(Context.InputMethodService);
|
|
||||||
keyboard.ShowSoftInput(pwd, 0);
|
|
||||||
}, 50);
|
|
||||||
|
|
||||||
SetResult(KeePass.ExitChangeDb);
|
|
||||||
|
|
||||||
Button btnUnlock = (Button)FindViewById(Resource.Id.QuickUnlock_button);
|
Button btnUnlock = (Button)FindViewById(Resource.Id.QuickUnlock_button);
|
||||||
btnUnlock.Click += (object sender, EventArgs e) =>
|
btnUnlock.Click += (object sender, EventArgs e) =>
|
||||||
@ -93,11 +88,11 @@ namespace keepass2android
|
|||||||
String expectedPasswordPart = password.Substring(Math.Max(0,password.Length-quickUnlockLength),Math.Min(password.Length, quickUnlockLength));
|
String expectedPasswordPart = password.Substring(Math.Max(0,password.Length-quickUnlockLength),Math.Min(password.Length, quickUnlockLength));
|
||||||
if (pwd.Text == expectedPasswordPart)
|
if (pwd.Text == expectedPasswordPart)
|
||||||
{
|
{
|
||||||
SetResult(KeePass.ExitQuickUnlock);
|
App.Kp2a.UnlockDatabase();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetResult(KeePass.ExitForceLock);
|
App.Kp2a.LockDatabase(false);
|
||||||
Toast.MakeText(this, GetString(Resource.String.QuickUnlock_fail), ToastLength.Long).Show();
|
Toast.MakeText(this, GetString(Resource.String.QuickUnlock_fail), ToastLength.Long).Show();
|
||||||
}
|
}
|
||||||
Finish();
|
Finish();
|
||||||
@ -106,21 +101,21 @@ namespace keepass2android
|
|||||||
Button btnLock = (Button)FindViewById(Resource.Id.QuickUnlock_buttonLock);
|
Button btnLock = (Button)FindViewById(Resource.Id.QuickUnlock_buttonLock);
|
||||||
btnLock.Click += (object sender, EventArgs e) =>
|
btnLock.Click += (object sender, EventArgs e) =>
|
||||||
{
|
{
|
||||||
SetResult(KeePass.ExitForceLockAndChangeDb);
|
App.Kp2a.LockDatabase(false);
|
||||||
Finish();
|
Finish();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void OnResume()
|
protected override void OnResume()
|
||||||
{
|
{
|
||||||
base.OnResume();
|
base.OnResume();
|
||||||
|
|
||||||
if ( ! App.Kp2a.GetDb().Loaded ) {
|
EditText pwd = (EditText)FindViewById(Resource.Id.QuickUnlock_password);
|
||||||
SetResult(KeePass.ExitChangeDb);
|
pwd.PostDelayed(() =>
|
||||||
Finish();
|
{
|
||||||
return;
|
InputMethodManager keyboard = (InputMethodManager)GetSystemService(Context.InputMethodService);
|
||||||
}
|
keyboard.ShowSoftInput(pwd, 0);
|
||||||
|
}, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
src/keepass2android/Resources/drawable-hdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
src/keepass2android/Resources/drawable-mdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/keepass2android/Resources/drawable-v11/ic_unlocked_gray.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
src/keepass2android/Resources/drawable-xhdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 5.3 KiB |
BIN
src/keepass2android/Resources/drawable/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/keepass2android/Resources/drawable/ic_unlocked_gray.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
@ -91,16 +91,10 @@
|
|||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/keyfileLine" />
|
android:layout_below="@id/keyfileLine" />
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/default_database"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/pass_ok"
|
|
||||||
android:text="@string/default_checkbox" />
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/enable_quickunlock"
|
android:id="@+id/enable_quickunlock"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/default_database"
|
android:layout_below="@id/pass_ok"
|
||||||
android:text="@string/enable_quickunlock" />
|
android:text="@string/enable_quickunlock" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -79,16 +79,10 @@
|
|||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/pass_keyfile" />
|
android:layout_below="@id/pass_keyfile" />
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/default_database"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/pass_ok"
|
|
||||||
android:text="@string/default_checkbox" />
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/enable_quickunlock"
|
android:id="@+id/enable_quickunlock"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/default_database"
|
android:layout_below="@id/pass_ok"
|
||||||
android:text="@string/enable_quickunlock" />
|
android:text="@string/enable_quickunlock" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -20,6 +20,11 @@
|
|||||||
android:title="@string/menu_about"
|
android:title="@string/menu_about"
|
||||||
android:icon="@android:drawable/ic_menu_help"
|
android:icon="@android:drawable/ic_menu_help"
|
||||||
android:showAsAction="ifRoom"
|
android:showAsAction="ifRoom"
|
||||||
|
/>
|
||||||
|
<item android:id="@+id/menu_change_db"
|
||||||
|
android:icon="@drawable/collections_collection"
|
||||||
|
android:title="@string/menu_change_db"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
/>
|
/>
|
||||||
<item android:id="@+id/menu_app_settings"
|
<item android:id="@+id/menu_app_settings"
|
||||||
android:title="@string/menu_app_settings"
|
android:title="@string/menu_app_settings"
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
<item android:id="@+id/menu_app_settings"
|
<item android:id="@+id/menu_app_settings"
|
||||||
android:icon="@android:drawable/ic_menu_preferences"
|
android:icon="@android:drawable/ic_menu_preferences"
|
||||||
android:title="@string/menu_app_settings"
|
android:title="@string/menu_app_settings"
|
||||||
|
/>
|
||||||
|
<item android:id="@+id/menu_change_db"
|
||||||
|
android:icon="@drawable/collections_collection"
|
||||||
|
android:title="@string/menu_change_db"
|
||||||
/>
|
/>
|
||||||
<item android:id="@+id/menu_about"
|
<item android:id="@+id/menu_about"
|
||||||
android:icon="@android:drawable/ic_menu_help"
|
android:icon="@android:drawable/ic_menu_help"
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
<string name="omitbackup_key">omitbackup</string>
|
<string name="omitbackup_key">omitbackup</string>
|
||||||
<string name="list_size_key">list_size</string>
|
<string name="list_size_key">list_size</string>
|
||||||
<string name="sort_key">sort_key</string>
|
<string name="sort_key">sort_key</string>
|
||||||
<string name="timeout_key">timeout_key</string>
|
|
||||||
<string name="TanExpiresOnUse_key">TanExpiresOnUse_key</string>
|
<string name="TanExpiresOnUse_key">TanExpiresOnUse_key</string>
|
||||||
<string name="ShowUsernameInList_key">ShowUsernameInList_key</string>
|
<string name="ShowUsernameInList_key">ShowUsernameInList_key</string>
|
||||||
<string name="RememberRecentFiles_key">RememberRecentFiles_key</string>
|
<string name="RememberRecentFiles_key">RememberRecentFiles_key</string>
|
||||||
@ -92,4 +91,11 @@
|
|||||||
<item>20</item>
|
<item>20</item>
|
||||||
<item>28</item>
|
<item>28</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="ShowUnlockedNotification_key">ShowUnlockedNotification</string>
|
||||||
|
<bool name="ShowUnlockedNotification_default">true</bool>
|
||||||
|
|
||||||
|
<string name="PreloadDatabaseEnabled_key">PreloadDatabaseEnabled</string>
|
||||||
|
<bool name="PreloadDatabaseEnabled_default">true</bool>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -131,6 +131,7 @@
|
|||||||
<string name="menu_search">Search</string>
|
<string name="menu_search">Search</string>
|
||||||
<string name="menu_search_advanced">Advanced Search</string>
|
<string name="menu_search_advanced">Advanced Search</string>
|
||||||
<string name="menu_url">Go to URL</string>
|
<string name="menu_url">Go to URL</string>
|
||||||
|
<string name="menu_change_db">Change database…</string>
|
||||||
<string name="minus">Minus</string>
|
<string name="minus">Minus</string>
|
||||||
<string name="never">Never</string>
|
<string name="never">Never</string>
|
||||||
<string name="yes">Yes</string>
|
<string name="yes">Yes</string>
|
||||||
@ -218,7 +219,8 @@
|
|||||||
<string name="add_binary">Add file attachment...</string>
|
<string name="add_binary">Add file attachment...</string>
|
||||||
<string name="add_extra_string">Add additional string</string>
|
<string name="add_extra_string">Add additional string</string>
|
||||||
<string name="delete_extra_string">Delete additional string</string>
|
<string name="delete_extra_string">Delete additional string</string>
|
||||||
<string name="database_loaded_quickunlock_enabled">Database loaded, QuickUnlock enabled.</string>
|
<string name="database_loaded_quickunlock_enabled">%1$s: Locked. QuickUnlock enabled.</string>
|
||||||
|
<string name="database_loaded_unlocked">%1$s: Unlocked.</string>
|
||||||
<string name="credentials_dialog_title">Enter server credentials</string>
|
<string name="credentials_dialog_title">Enter server credentials</string>
|
||||||
<string name="UseFileTransactions_title">File transactions</string>
|
<string name="UseFileTransactions_title">File transactions</string>
|
||||||
<string name="UseFileTransactions_summary">Use file transactions for writing databases</string>
|
<string name="UseFileTransactions_summary">Use file transactions for writing databases</string>
|
||||||
@ -232,6 +234,12 @@
|
|||||||
<string name="OpenKp2aKeyboardAutomatically_title">Keyboard selection dialog</string>
|
<string name="OpenKp2aKeyboardAutomatically_title">Keyboard selection dialog</string>
|
||||||
<string name="OpenKp2aKeyboardAutomatically_summary">Open keyboard selection dialog when entry is available through KP2A keyboard after search.</string>
|
<string name="OpenKp2aKeyboardAutomatically_summary">Open keyboard selection dialog when entry is available through KP2A keyboard after search.</string>
|
||||||
|
|
||||||
|
<string name="ShowUnlockedNotification_title">Notification while unlocked</string>
|
||||||
|
<string name="ShowUnlockedNotification_summary">Show an ongoing notification while the database is unlocked.</string>
|
||||||
|
|
||||||
|
<string name="PreloadDatabaseEnabled_title">Pre-load database file</string>
|
||||||
|
<string name="PreloadDatabaseEnabled_summary">Start background loading or downloading of the database file during password entry.</string>
|
||||||
|
|
||||||
<string name="AskOverwriteBinary">Do you want to overwrite the existing binary with the same name?</string>
|
<string name="AskOverwriteBinary">Do you want to overwrite the existing binary with the same name?</string>
|
||||||
<string name="AskOverwriteBinary_title">Overwrite existing binary?</string>
|
<string name="AskOverwriteBinary_title">Overwrite existing binary?</string>
|
||||||
<string name="AskOverwriteBinary_yes">Overwrite</string>
|
<string name="AskOverwriteBinary_yes">Overwrite</string>
|
||||||
|
@ -71,6 +71,13 @@
|
|||||||
android:entryValues="@array/clipboard_timeout_values"
|
android:entryValues="@array/clipboard_timeout_values"
|
||||||
android:dialogTitle="@string/app_timeout"
|
android:dialogTitle="@string/app_timeout"
|
||||||
android:defaultValue="@string/clipboard_timeout_default"/>
|
android:defaultValue="@string/clipboard_timeout_default"/>
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:enabled="true"
|
||||||
|
android:persistent="true"
|
||||||
|
android:summary="@string/ShowUnlockedNotification_summary"
|
||||||
|
android:defaultValue="@bool/ShowUnlockedNotification_default"
|
||||||
|
android:title="@string/ShowUnlockedNotification_title"
|
||||||
|
android:key="@string/ShowUnlockedNotification_key" />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="@string/maskpass_key"
|
android:key="@string/maskpass_key"
|
||||||
android:title="@string/maskpass_title"
|
android:title="@string/maskpass_title"
|
||||||
@ -162,6 +169,12 @@
|
|||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:title="@string/CheckForFileChangesOnSave_title"
|
android:title="@string/CheckForFileChangesOnSave_title"
|
||||||
android:key="@string/CheckForFileChangesOnSave_key" />
|
android:key="@string/CheckForFileChangesOnSave_key" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:enabled="true"
|
||||||
|
android:persistent="true"
|
||||||
|
android:summary="@string/PreloadDatabaseEnabled_summary"
|
||||||
|
android:defaultValue="@bool/PreloadDatabaseEnabled_default"
|
||||||
|
android:title="@string/PreloadDatabaseEnabled_title"
|
||||||
|
android:key="@string/PreloadDatabaseEnabled_key" />
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@ -71,7 +71,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
Finish();
|
Finish();
|
||||||
}
|
}
|
||||||
else if (_db.Locked)
|
else if (App.Kp2a.QuickLocked)
|
||||||
{
|
{
|
||||||
PasswordActivity.Launch(this,_db.Ioc, AppTask);
|
PasswordActivity.Launch(this,_db.Ioc, AppTask);
|
||||||
Finish();
|
Finish();
|
||||||
|
@ -16,11 +16,14 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Runtime;
|
using Android.Runtime;
|
||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
|
using KeePassLib.Keys;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
using Android.Preferences;
|
using Android.Preferences;
|
||||||
using keepass2android.Io;
|
using keepass2android.Io;
|
||||||
@ -60,25 +63,96 @@ namespace keepass2android
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Kp2aApp: IKp2aApp, ICacheSupervisor
|
public class Kp2aApp: IKp2aApp, ICacheSupervisor
|
||||||
{
|
{
|
||||||
public bool IsShutdown()
|
public void LockDatabase(bool allowQuickUnlock = true)
|
||||||
{
|
{
|
||||||
return _shutdown;
|
if (GetDb().Loaded)
|
||||||
|
{
|
||||||
|
if (QuickUnlockEnabled && allowQuickUnlock &&
|
||||||
|
_db.KpDatabase.MasterKey.ContainsType(typeof(KcpPassword)) &&
|
||||||
|
!((KcpPassword)App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey(typeof(KcpPassword))).Password.IsEmpty)
|
||||||
|
{
|
||||||
|
if (!QuickLocked)
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("QuickLocking database");
|
||||||
|
|
||||||
|
QuickLocked = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Database already QuickLocked");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Locking database");
|
||||||
|
|
||||||
|
// Couldn't quick-lock, so unload database instead
|
||||||
|
_db.Clear();
|
||||||
|
QuickLocked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Database not loaded, couldn't lock");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetShutdown()
|
UpdateOngoingNotification();
|
||||||
{
|
Application.Context.SendBroadcast(new Intent(Intents.DatabaseLocked));
|
||||||
Kp2aLog.Log("set shutdown");
|
|
||||||
_shutdown = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearShutdown()
|
public void LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, string password, string keyFile, ProgressDialogStatusLogger statusLogger)
|
||||||
{
|
{
|
||||||
Kp2aLog.Log("clear shutdown");
|
_db.LoadData(this, ioConnectionInfo, memoryStream, password, keyFile, statusLogger);
|
||||||
_shutdown = false;
|
|
||||||
|
UpdateOngoingNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void UnlockDatabase()
|
||||||
|
{
|
||||||
|
QuickLocked = false;
|
||||||
|
|
||||||
|
UpdateOngoingNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateOngoingNotification()
|
||||||
|
{
|
||||||
|
// Start or update the notification icon service to reflect the current state
|
||||||
|
var ctx = Application.Context;
|
||||||
|
ctx.StartService(new Intent(ctx, typeof(OngoingNotificationsService)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DatabaseIsUnlocked
|
||||||
|
{
|
||||||
|
get { return _db.Loaded && !QuickLocked; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#region QuickUnlock
|
||||||
|
public void SetQuickUnlockEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
//Set KeyLength of QuickUnlock at time of enabling.
|
||||||
|
//This is important to not allow an attacker to set the length to 1 when QuickUnlock is started already.
|
||||||
|
|
||||||
|
var ctx = Application.Context;
|
||||||
|
var prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
|
||||||
|
QuickUnlockKeyLength = Math.Max(1, int.Parse(prefs.GetString(ctx.GetString(Resource.String.QuickUnlockLength_key), ctx.GetString(Resource.String.QuickUnlockLength_default))));
|
||||||
|
}
|
||||||
|
QuickUnlockEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool QuickUnlockEnabled { get; private set; }
|
||||||
|
|
||||||
|
public int QuickUnlockKeyLength { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, the database must be regarded as locked and not exposed to the user.
|
||||||
|
/// </summary>
|
||||||
|
public bool QuickLocked { get; private set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
private Database _db;
|
private Database _db;
|
||||||
private bool _shutdown;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// See comments to EntryEditActivityState.
|
/// See comments to EntryEditActivityState.
|
||||||
@ -124,6 +198,7 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
if (_db.ReloadRequested)
|
if (_db.ReloadRequested)
|
||||||
{
|
{
|
||||||
|
LockDatabase(false);
|
||||||
activity.SetResult(KeePass.ExitReloadDb);
|
activity.SetResult(KeePass.ExitReloadDb);
|
||||||
activity.Finish();
|
activity.Finish();
|
||||||
//todo: return?
|
//todo: return?
|
||||||
@ -143,6 +218,7 @@ namespace keepass2android
|
|||||||
(dlgSender, dlgEvt) =>
|
(dlgSender, dlgEvt) =>
|
||||||
{
|
{
|
||||||
_db.ReloadRequested = true;
|
_db.ReloadRequested = true;
|
||||||
|
LockDatabase(false);
|
||||||
activity.SetResult(KeePass.ExitReloadDb);
|
activity.SetResult(KeePass.ExitReloadDb);
|
||||||
activity.Finish();
|
activity.Finish();
|
||||||
|
|
||||||
@ -223,7 +299,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
public RealProgressDialog(Context ctx)
|
public RealProgressDialog(Context ctx)
|
||||||
{
|
{
|
||||||
this._pd = new ProgressDialog(ctx);
|
_pd = new ProgressDialog(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTitle(string title)
|
public void SetTitle(string title)
|
||||||
|
25
src/keepass2android/app/ApplicationBroadcastReceiver.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.App;
|
||||||
|
|
||||||
|
|
||||||
|
namespace keepass2android
|
||||||
|
{
|
||||||
|
[BroadcastReceiver]
|
||||||
|
[IntentFilter(new[] { Intents.LockDatabase })]
|
||||||
|
public class ApplicationBroadcastReceiver : BroadcastReceiver
|
||||||
|
{
|
||||||
|
public override void OnReceive(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Received broadcast intent: " + intent.Action);
|
||||||
|
|
||||||
|
switch (intent.Action)
|
||||||
|
{
|
||||||
|
case Intents.LockDatabase:
|
||||||
|
App.Kp2a.LockDatabase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -63,11 +63,6 @@ namespace keepass2android
|
|||||||
|
|
||||||
internal AppTask AppTask;
|
internal AppTask AppTask;
|
||||||
|
|
||||||
IOConnectionInfo LoadIoc(string defaultFileName)
|
|
||||||
{
|
|
||||||
return _DbHelper.CursorToIoc(_DbHelper.FetchFileByName(defaultFileName));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShowFilenameDialog(bool showOpenButton, bool showCreateButton, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse)
|
void ShowFilenameDialog(bool showOpenButton, bool showCreateButton, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse)
|
||||||
{
|
{
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
@ -319,14 +314,20 @@ namespace keepass2android
|
|||||||
|
|
||||||
public override void Run() {
|
public override void Run() {
|
||||||
if (Success) {
|
if (Success) {
|
||||||
|
// Update the ongoing notification
|
||||||
|
_activity.StartService(new Intent(_activity, typeof(OngoingNotificationsService)));
|
||||||
|
|
||||||
|
|
||||||
if (_activity.RememberRecentFiles())
|
if (_activity.RememberRecentFiles())
|
||||||
{
|
{
|
||||||
// Add to recent files
|
// Add to recent files
|
||||||
FileDbHelper dbHelper = App.Kp2a.FileDbHelper;
|
FileDbHelper dbHelper = App.Kp2a.FileDbHelper;
|
||||||
|
|
||||||
|
|
||||||
//TODO: getFilename always returns "" -> bug?
|
//TODO: getFilename always returns "" -> bug?
|
||||||
dbHelper.CreateFile(_ioc, Filename);
|
dbHelper.CreateFile(_ioc, Filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupActivity.Launch(_activity, _activity.AppTask);
|
GroupActivity.Launch(_activity, _activity.AppTask);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -391,6 +392,7 @@ namespace keepass2android
|
|||||||
ioc.Password = password;
|
ioc.Password = password;
|
||||||
ioc.CredSaveMode = (IOCredSaveMode)credentialRememberMode;
|
ioc.CredSaveMode = (IOCredSaveMode)credentialRememberMode;
|
||||||
PasswordActivity.Launch(this, ioc, AppTask);
|
PasswordActivity.Launch(this, ioc, AppTask);
|
||||||
|
Finish();
|
||||||
});
|
});
|
||||||
builder.SetView(LayoutInflater.Inflate(Resource.Layout.url_credentials, null));
|
builder.SetView(LayoutInflater.Inflate(Resource.Layout.url_credentials, null));
|
||||||
builder.SetNeutralButton(GetString(Android.Resource.String.Cancel),
|
builder.SetNeutralButton(GetString(Android.Resource.String.Cancel),
|
||||||
@ -406,6 +408,7 @@ namespace keepass2android
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
PasswordActivity.Launch(this, ioc, AppTask);
|
PasswordActivity.Launch(this, ioc, AppTask);
|
||||||
|
Finish();
|
||||||
} catch (Java.IO.FileNotFoundException)
|
} catch (Java.IO.FileNotFoundException)
|
||||||
{
|
{
|
||||||
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
||||||
@ -489,36 +492,6 @@ namespace keepass2android
|
|||||||
|
|
||||||
_fileSelectButtons.UpdateExternalStorageWarning();
|
_fileSelectButtons.UpdateExternalStorageWarning();
|
||||||
|
|
||||||
if (!_createdWithActivityResult)
|
|
||||||
{
|
|
||||||
if ((Intent.Action == Intent.ActionSend) && (App.Kp2a.GetDb().Loaded))
|
|
||||||
{
|
|
||||||
PasswordActivity.Launch(this, App.Kp2a.GetDb().Ioc , AppTask);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
|
|
||||||
// Load default database
|
|
||||||
ISharedPreferences prefs = Android.Preferences.PreferenceManager.GetDefaultSharedPreferences(this);
|
|
||||||
String defaultFileName = prefs.GetString(PasswordActivity.KeyDefaultFilename, "");
|
|
||||||
|
|
||||||
if (defaultFileName.Length > 0)
|
|
||||||
{
|
|
||||||
Java.IO.File db = new Java.IO.File(defaultFileName);
|
|
||||||
|
|
||||||
if (db.Exists())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
PasswordActivity.Launch(this, LoadIoc(defaultFileName), AppTask);
|
|
||||||
} catch (Exception e)
|
|
||||||
{
|
|
||||||
Toast.MakeText(this, e.Message, ToastLength.Long);
|
|
||||||
// Ignore exception
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,6 +499,15 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
base.OnStart();
|
base.OnStart();
|
||||||
Kp2aLog.Log("FileSelect.OnStart");
|
Kp2aLog.Log("FileSelect.OnStart");
|
||||||
|
|
||||||
|
var db = App.Kp2a.GetDb();
|
||||||
|
if (db.Loaded)
|
||||||
|
{
|
||||||
|
PasswordActivity.Launch(this, db.Ioc, AppTask);
|
||||||
|
Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
public override bool OnCreateOptionsMenu(IMenu menu) {
|
public override bool OnCreateOptionsMenu(IMenu menu) {
|
||||||
base.OnCreateOptionsMenu(menu);
|
base.OnCreateOptionsMenu(menu);
|
||||||
|
@ -22,8 +22,13 @@ namespace keepass2android
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains constants to be used in intents
|
/// Contains constants to be used in intents
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Intents {
|
public class Intents
|
||||||
public const String Timeout = "keepass2android.timeout";
|
{
|
||||||
|
/// <summary>Broadcast this intent to lock the database</summary>
|
||||||
|
public const String LockDatabase = "keepass2android.lock_database";
|
||||||
|
|
||||||
|
/// <summary>This intent will be broadcast once the database has been locked. Sensitive information displayed should be hidden and unloaded.</summary>
|
||||||
|
public const String DatabaseLocked = "keepass2android.database_locked";
|
||||||
|
|
||||||
public const String CopyUsername = "keepass2android.copy_username";
|
public const String CopyUsername = "keepass2android.copy_username";
|
||||||
public const String CopyPassword = "keepass2android.copy_password";
|
public const String CopyPassword = "keepass2android.copy_password";
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
<Reference Include="Mono.Android.Support.v4" />
|
<Reference Include="Mono.Android.Support.v4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="app\ApplicationBroadcastReceiver.cs" />
|
||||||
<Compile Include="icons\DrawableFactory.cs" />
|
<Compile Include="icons\DrawableFactory.cs" />
|
||||||
<Compile Include="icons\Icons.cs" />
|
<Compile Include="icons\Icons.cs" />
|
||||||
<Compile Include="Resources\Resource.designer.cs" />
|
<Compile Include="Resources\Resource.designer.cs" />
|
||||||
@ -86,6 +87,8 @@
|
|||||||
<Compile Include="fileselect\FileSelectActivity.cs" />
|
<Compile Include="fileselect\FileSelectActivity.cs" />
|
||||||
<Compile Include="fileselect\FileDbHelper.cs" />
|
<Compile Include="fileselect\FileDbHelper.cs" />
|
||||||
<Compile Include="search\SearchProvider.cs" />
|
<Compile Include="search\SearchProvider.cs" />
|
||||||
|
<Compile Include="services\OngoingNotificationsService.cs" />
|
||||||
|
<Compile Include="settings\DatabaseSettingsActivity.cs" />
|
||||||
<Compile Include="Utils\Util.cs" />
|
<Compile Include="Utils\Util.cs" />
|
||||||
<Compile Include="intents\Intents.cs" />
|
<Compile Include="intents\Intents.cs" />
|
||||||
<Compile Include="fileselect\BrowserDialog.cs" />
|
<Compile Include="fileselect\BrowserDialog.cs" />
|
||||||
@ -127,12 +130,10 @@
|
|||||||
<Compile Include="compat\EditorCompat.cs" />
|
<Compile Include="compat\EditorCompat.cs" />
|
||||||
<Compile Include="compat\ActivityCompat.cs" />
|
<Compile Include="compat\ActivityCompat.cs" />
|
||||||
<Compile Include="ShareUrlResults.cs" />
|
<Compile Include="ShareUrlResults.cs" />
|
||||||
<Compile Include="services\TimeoutService.cs" />
|
|
||||||
<Compile Include="services\CopyToClipboardService.cs" />
|
<Compile Include="services\CopyToClipboardService.cs" />
|
||||||
<Compile Include="search\SearchActivity.cs" />
|
<Compile Include="search\SearchActivity.cs" />
|
||||||
<Compile Include="QuickUnlock.cs" />
|
<Compile Include="QuickUnlock.cs" />
|
||||||
<Compile Include="LifecycleDebugActivity.cs" />
|
<Compile Include="LifecycleDebugActivity.cs" />
|
||||||
<Compile Include="services\QuickUnlockForegroundService.cs" />
|
|
||||||
<Compile Include="AssemblyInfo.cs" />
|
<Compile Include="AssemblyInfo.cs" />
|
||||||
<Compile Include="views\FileSelectButtons.cs" />
|
<Compile Include="views\FileSelectButtons.cs" />
|
||||||
<Compile Include="EntryEditActivityState.cs" />
|
<Compile Include="EntryEditActivityState.cs" />
|
||||||
@ -703,4 +704,25 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable\ic_unlocked_gray.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-v11\ic_unlocked_gray.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-mdpi\ic_launcher_red.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-xhdpi\ic_launcher_red.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-xxhdpi\ic_launcher_red.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable-hdpi\ic_launcher_red.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\drawable\ic_launcher_red.png" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -70,7 +70,7 @@ namespace keepass2android.search
|
|||||||
|
|
||||||
public override Android.Database.ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
|
public override Android.Database.ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
|
||||||
{
|
{
|
||||||
if (_db.Open) // Can't show suggestions if the database is locked!
|
if (App.Kp2a.DatabaseIsUnlocked) // Can't show suggestions if the database is locked!
|
||||||
{
|
{
|
||||||
switch ((UriMatches)UriMatcher.Match(uri))
|
switch ((UriMatches)UriMatcher.Match(uri))
|
||||||
{
|
{
|
||||||
|
@ -56,11 +56,9 @@ namespace keepass2android.search
|
|||||||
|
|
||||||
private void ProcessIntent(Intent intent)
|
private void ProcessIntent(Intent intent)
|
||||||
{
|
{
|
||||||
_db = App.Kp2a.GetDb();
|
|
||||||
|
|
||||||
|
|
||||||
// Likely the app has been killed exit the activity
|
// Likely the app has been killed exit the activity
|
||||||
if ( ! _db.Open ) {
|
if (!App.Kp2a.DatabaseIsUnlocked)
|
||||||
|
{
|
||||||
Finish();
|
Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
CopyToClipboardBroadcastReceiver _copyToClipBroadcastReceiver;
|
CopyToClipboardBroadcastReceiver _copyToClipBroadcastReceiver;
|
||||||
NotificationDeletedBroadcastReceiver _notificationDeletedBroadcastReceiver;
|
NotificationDeletedBroadcastReceiver _notificationDeletedBroadcastReceiver;
|
||||||
|
StopOnLockBroadcastReceiver _stopOnLockBroadcastReceiver;
|
||||||
|
|
||||||
public CopyToClipboardService()
|
public CopyToClipboardService()
|
||||||
{
|
{
|
||||||
@ -74,6 +74,11 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
Kp2aLog.Log("Received intent to provide access to entry");
|
Kp2aLog.Log("Received intent to provide access to entry");
|
||||||
|
|
||||||
|
_stopOnLockBroadcastReceiver = new StopOnLockBroadcastReceiver(this);
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.AddAction(Intents.DatabaseLocked);
|
||||||
|
RegisterReceiver(_stopOnLockBroadcastReceiver, filter);
|
||||||
|
|
||||||
String uuidBytes = intent.GetStringExtra(EntryActivity.KeyEntry);
|
String uuidBytes = intent.GetStringExtra(EntryActivity.KeyEntry);
|
||||||
bool closeAfterCreate = intent.GetBooleanExtra(EntryActivity.KeyCloseAfterCreate, false);
|
bool closeAfterCreate = intent.GetBooleanExtra(EntryActivity.KeyCloseAfterCreate, false);
|
||||||
|
|
||||||
@ -99,12 +104,25 @@ namespace keepass2android
|
|||||||
return StartCommandResult.RedeliverIntent;
|
return StartCommandResult.RedeliverIntent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnLockDatabase()
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Stopping clipboard service due to database lock");
|
||||||
|
|
||||||
|
StopSelf();
|
||||||
|
}
|
||||||
|
|
||||||
private NotificationManager _notificationManager;
|
private NotificationManager _notificationManager;
|
||||||
private int _numElementsToWaitFor;
|
private int _numElementsToWaitFor;
|
||||||
|
|
||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
|
Kp2aLog.Log("CopyToClipboardService.OnDestroy");
|
||||||
|
|
||||||
// These members might never get initialized if the app timed out
|
// These members might never get initialized if the app timed out
|
||||||
|
if (_stopOnLockBroadcastReceiver != null)
|
||||||
|
{
|
||||||
|
UnregisterReceiver(_stopOnLockBroadcastReceiver);
|
||||||
|
}
|
||||||
if (_copyToClipBroadcastReceiver != null)
|
if (_copyToClipBroadcastReceiver != null)
|
||||||
{
|
{
|
||||||
UnregisterReceiver(_copyToClipBroadcastReceiver);
|
UnregisterReceiver(_copyToClipBroadcastReceiver);
|
||||||
@ -114,7 +132,10 @@ namespace keepass2android
|
|||||||
UnregisterReceiver(_notificationDeletedBroadcastReceiver);
|
UnregisterReceiver(_notificationDeletedBroadcastReceiver);
|
||||||
}
|
}
|
||||||
if ( _notificationManager != null ) {
|
if ( _notificationManager != null ) {
|
||||||
_notificationManager.CancelAll();
|
_notificationManager.Cancel(NotifyPassword);
|
||||||
|
_notificationManager.Cancel(NotifyUsername);
|
||||||
|
_notificationManager.Cancel(NotifyKeyboard);
|
||||||
|
|
||||||
_numElementsToWaitFor= 0;
|
_numElementsToWaitFor= 0;
|
||||||
clearKeyboard();
|
clearKeyboard();
|
||||||
}
|
}
|
||||||
@ -143,7 +164,9 @@ namespace keepass2android
|
|||||||
// Notification Manager
|
// Notification Manager
|
||||||
_notificationManager = (NotificationManager)GetSystemService(NotificationService);
|
_notificationManager = (NotificationManager)GetSystemService(NotificationService);
|
||||||
|
|
||||||
_notificationManager.CancelAll();
|
_notificationManager.Cancel(NotifyPassword);
|
||||||
|
_notificationManager.Cancel(NotifyUsername);
|
||||||
|
_notificationManager.Cancel(NotifyKeyboard);
|
||||||
_numElementsToWaitFor = 0;
|
_numElementsToWaitFor = 0;
|
||||||
clearKeyboard();
|
clearKeyboard();
|
||||||
|
|
||||||
@ -358,7 +381,24 @@ namespace keepass2android
|
|||||||
return notify;
|
return notify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class StopOnLockBroadcastReceiver : BroadcastReceiver
|
||||||
|
{
|
||||||
|
readonly CopyToClipboardService _service;
|
||||||
|
public StopOnLockBroadcastReceiver(CopyToClipboardService service)
|
||||||
|
{
|
||||||
|
_service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReceive(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
switch (intent.Action)
|
||||||
|
{
|
||||||
|
case Intents.DatabaseLocked:
|
||||||
|
_service.OnLockDatabase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CopyToClipboardBroadcastReceiver: BroadcastReceiver
|
class CopyToClipboardBroadcastReceiver: BroadcastReceiver
|
||||||
{
|
{
|
||||||
|
187
src/keepass2android/services/OngoingNotificationsService.cs
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
||||||
|
|
||||||
|
Keepass2Android is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Keepass2Android is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Graphics;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Preferences;
|
||||||
|
using Android.Support.V4.App;
|
||||||
|
using KeePassLib.Utility;
|
||||||
|
|
||||||
|
namespace keepass2android
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service for showing ongoing notifications
|
||||||
|
///
|
||||||
|
/// Shows database unlocked warning persistent notification
|
||||||
|
/// Shows Quick-Unlock notification
|
||||||
|
/// </summary>
|
||||||
|
[Service]
|
||||||
|
public class OngoingNotificationsService : Service
|
||||||
|
{
|
||||||
|
|
||||||
|
#region Service
|
||||||
|
private const int QuickUnlockId = 100;
|
||||||
|
private const int UnlockedWarningId = 200;
|
||||||
|
|
||||||
|
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("Starting/Updating OngoingNotificationsService. Database " + (App.Kp2a.DatabaseIsUnlocked ? "Unlocked" : (App.Kp2a.QuickLocked ? "QuickLocked" : "Locked")));
|
||||||
|
|
||||||
|
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
|
||||||
|
|
||||||
|
// Set the icon to reflect the current state
|
||||||
|
if (App.Kp2a.DatabaseIsUnlocked)
|
||||||
|
{
|
||||||
|
// Clear current foreground status and QuickUnlock icon
|
||||||
|
StopForeground(true);
|
||||||
|
|
||||||
|
if (ShowUnlockedNotification)
|
||||||
|
{
|
||||||
|
// No need for task to get foreground priority, we don't need any special treatment just for showing that the database is unlocked
|
||||||
|
notificationManager.Notify(UnlockedWarningId, GetUnlockedNotification());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
notificationManager.Cancel(UnlockedWarningId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
notificationManager.Cancel(UnlockedWarningId);
|
||||||
|
|
||||||
|
if (App.Kp2a.QuickLocked)
|
||||||
|
{
|
||||||
|
// Show the Quick Unlock notification
|
||||||
|
StartForeground(QuickUnlockId, GetQuickUnlockNotification());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not showing any notification, database is locked, no point in keeping running
|
||||||
|
StopSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StartCommandResult.NotSticky;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ShowUnlockedNotification
|
||||||
|
{
|
||||||
|
get { return PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean(GetString(Resource.String.ShowUnlockedNotification_key), Resources.GetBoolean(Resource.Boolean.ShowUnlockedNotification_default)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnTaskRemoved(Intent rootIntent)
|
||||||
|
{
|
||||||
|
base.OnTaskRemoved(rootIntent);
|
||||||
|
|
||||||
|
Kp2aLog.Log("OngoingNotificationsService.OnTaskRemoved: " + rootIntent.Action);
|
||||||
|
|
||||||
|
// If the user has closed the task (probably by swiping it out of the recent apps list) then lock the database
|
||||||
|
App.Kp2a.LockDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnDestroy()
|
||||||
|
{
|
||||||
|
base.OnDestroy();
|
||||||
|
|
||||||
|
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
|
||||||
|
notificationManager.Cancel(UnlockedWarningId);
|
||||||
|
// Quick Unlock notification should be removed automatically by the service (if present), as it was the foreground notification.
|
||||||
|
|
||||||
|
Kp2aLog.Log("OngoingNotificationsService.OnDestroy");
|
||||||
|
|
||||||
|
// If the service is killed, then lock the database immediately (as the unlocked warning icon will no longer display).
|
||||||
|
if (App.Kp2a.DatabaseIsUnlocked)
|
||||||
|
{
|
||||||
|
App.Kp2a.LockDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IBinder OnBind(Intent intent)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region QuickUnlock
|
||||||
|
|
||||||
|
private Notification GetQuickUnlockNotification()
|
||||||
|
{
|
||||||
|
NotificationCompat.Builder builder =
|
||||||
|
new NotificationCompat.Builder(this)
|
||||||
|
.SetSmallIcon(Resource.Drawable.ic_launcher_gray)
|
||||||
|
.SetLargeIcon(BitmapFactory.DecodeResource(Resources, AppNames.LauncherIcon))
|
||||||
|
.SetContentTitle(GetString(Resource.String.app_name))
|
||||||
|
.SetContentText(GetString(Resource.String.database_loaded_quickunlock_enabled, GetDatabaseName()));
|
||||||
|
|
||||||
|
var startKp2APendingIntent = GetSwitchToAppPendingIntent();
|
||||||
|
builder.SetContentIntent(startKp2APendingIntent);
|
||||||
|
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Unlocked Warning
|
||||||
|
|
||||||
|
private Notification GetUnlockedNotification()
|
||||||
|
{
|
||||||
|
NotificationCompat.Builder builder =
|
||||||
|
new NotificationCompat.Builder(this)
|
||||||
|
.SetOngoing(true)
|
||||||
|
.SetSmallIcon(Resource.Drawable.ic_unlocked_gray)
|
||||||
|
.SetLargeIcon(BitmapFactory.DecodeResource(Resources, Resource.Drawable.ic_launcher_red))
|
||||||
|
.SetContentTitle(GetString(Resource.String.app_name))
|
||||||
|
.SetContentText(GetString(Resource.String.database_loaded_unlocked, GetDatabaseName()));
|
||||||
|
|
||||||
|
// Default action is to show Kp2A
|
||||||
|
builder.SetContentIntent(GetSwitchToAppPendingIntent());
|
||||||
|
// Additional action to allow locking the database
|
||||||
|
builder.AddAction(Android.Resource.Drawable.IcLockLock, GetString(Resource.String.menu_lock), PendingIntent.GetBroadcast(this, 0, new Intent(Intents.LockDatabase), PendingIntentFlags.UpdateCurrent));
|
||||||
|
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PendingIntent GetSwitchToAppPendingIntent()
|
||||||
|
{
|
||||||
|
var startKp2aIntent = new Intent(this, typeof(KeePass));
|
||||||
|
startKp2aIntent.SetAction(Intent.ActionMain);
|
||||||
|
startKp2aIntent.AddCategory(Intent.CategoryLauncher);
|
||||||
|
|
||||||
|
return PendingIntent.GetActivity(this, 0, startKp2aIntent, PendingIntentFlags.UpdateCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDatabaseName()
|
||||||
|
{
|
||||||
|
|
||||||
|
var db = App.Kp2a.GetDb().KpDatabase;
|
||||||
|
var name = db.Name;
|
||||||
|
if (String.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
//todo: if paranoid ("don't remember recent files") return "***"
|
||||||
|
name = UrlUtil.StripExtension(UrlUtil.GetFileName(db.IOConnectionInfo.Path));
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
|
|
||||||
|
|
||||||
Keepass2Android is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Keepass2Android is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.OS;
|
|
||||||
using Android.Support.V4.App;
|
|
||||||
using Android.Graphics;
|
|
||||||
|
|
||||||
namespace keepass2android
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This service is started as soon as a Database with QuickUnlock enabled is opened.
|
|
||||||
/// Its only purpose is to be a foreground service which prevents the App from being killed (in most situations)
|
|
||||||
/// </summary>
|
|
||||||
[Service]
|
|
||||||
public class QuickUnlockForegroundService : Service
|
|
||||||
{
|
|
||||||
public override IBinder OnBind(Intent intent)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int QuickUnlockForegroundServiceId = 238787;
|
|
||||||
|
|
||||||
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
|
|
||||||
{
|
|
||||||
Kp2aLog.Log("Starting QuickUnlockForegroundService");
|
|
||||||
|
|
||||||
//create notification item
|
|
||||||
NotificationCompat.Builder mBuilder =
|
|
||||||
new NotificationCompat.Builder(this)
|
|
||||||
.SetSmallIcon(Resource.Drawable.ic_launcher_gray)
|
|
||||||
.SetLargeIcon(BitmapFactory.DecodeResource(Resources, AppNames.LauncherIcon))
|
|
||||||
.SetContentTitle(GetText(Resource.String.app_name))
|
|
||||||
.SetContentText(GetText(Resource.String.database_loaded_quickunlock_enabled));
|
|
||||||
|
|
||||||
Intent startKp2aIntent = new Intent(this, typeof(KeePass));
|
|
||||||
startKp2aIntent.SetAction(Intent.ActionMain);
|
|
||||||
startKp2aIntent.AddCategory(Intent.CategoryLauncher);
|
|
||||||
|
|
||||||
PendingIntent startKp2APendingIntent =
|
|
||||||
PendingIntent.GetActivity(this, 0, startKp2aIntent, PendingIntentFlags.UpdateCurrent);
|
|
||||||
mBuilder.SetContentIntent(startKp2APendingIntent);
|
|
||||||
|
|
||||||
StartForeground(QuickUnlockForegroundServiceId , mBuilder.Build());
|
|
||||||
|
|
||||||
return StartCommandResult.NotSticky;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnCreate()
|
|
||||||
{
|
|
||||||
base.OnCreate();
|
|
||||||
Kp2aLog.Log("Creating QuickUnlockForegroundService");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnDestroy()
|
|
||||||
{
|
|
||||||
base.OnDestroy();
|
|
||||||
Kp2aLog.Log("Destroying QuickUnlockForegroundService");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
|
||||||
|
|
||||||
Keepass2Android is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Keepass2Android is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.OS;
|
|
||||||
using Android.Runtime;
|
|
||||||
using Android.Util;
|
|
||||||
|
|
||||||
namespace keepass2android
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Manages timeout to lock the database after some idle time
|
|
||||||
/// </summary>
|
|
||||||
[Service]
|
|
||||||
public class TimeoutService : Service {
|
|
||||||
private const String Tag = "KeePass2Android Timer";
|
|
||||||
private BroadcastReceiver _intentReceiver;
|
|
||||||
|
|
||||||
|
|
||||||
public TimeoutService (IntPtr javaReference, JniHandleOwnership transfer)
|
|
||||||
: base(javaReference, transfer)
|
|
||||||
{
|
|
||||||
_binder = new TimeoutBinder(this);
|
|
||||||
}
|
|
||||||
public TimeoutService()
|
|
||||||
{
|
|
||||||
_binder = new TimeoutBinder(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnCreate() {
|
|
||||||
base.OnCreate();
|
|
||||||
|
|
||||||
_intentReceiver = new MyBroadcastReceiver(this);
|
|
||||||
|
|
||||||
IntentFilter filter = new IntentFilter();
|
|
||||||
filter.AddAction(Intents.Timeout);
|
|
||||||
RegisterReceiver(_intentReceiver, filter);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override void OnStart(Intent intent, int startId) {
|
|
||||||
base.OnStart(intent, startId);
|
|
||||||
|
|
||||||
Log.Debug(Tag, "Timeout service started");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Timeout() {
|
|
||||||
Log.Debug(Tag, "Timeout");
|
|
||||||
App.Kp2a.SetShutdown();
|
|
||||||
|
|
||||||
NotificationManager nm = (NotificationManager) GetSystemService(NotificationService);
|
|
||||||
nm.CancelAll();
|
|
||||||
StopService(new Intent(this, typeof(CopyToClipboardService)));
|
|
||||||
StopSelf();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnDestroy() {
|
|
||||||
base.OnDestroy();
|
|
||||||
|
|
||||||
Log.Debug(Tag, "Timeout service stopped");
|
|
||||||
|
|
||||||
UnregisterReceiver(_intentReceiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TimeoutBinder : Binder
|
|
||||||
{
|
|
||||||
readonly TimeoutService _service;
|
|
||||||
|
|
||||||
public TimeoutBinder(TimeoutService service)
|
|
||||||
{
|
|
||||||
_service = service;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeoutService GetService() {
|
|
||||||
return _service;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly IBinder _binder;
|
|
||||||
|
|
||||||
|
|
||||||
public override IBinder OnBind(Intent intent) {
|
|
||||||
return _binder;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BroadcastReceiver]
|
|
||||||
public class MyBroadcastReceiver: BroadcastReceiver
|
|
||||||
{
|
|
||||||
public MyBroadcastReceiver()
|
|
||||||
{
|
|
||||||
//dummy constructor required for MonoForAndroid, not called.
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly TimeoutService _timeoutService;
|
|
||||||
public MyBroadcastReceiver (TimeoutService timeoutService)
|
|
||||||
{
|
|
||||||
_timeoutService = timeoutService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnReceive(Context context, Intent intent) {
|
|
||||||
String action = intent.Action;
|
|
||||||
|
|
||||||
if ( action.Equals(Intents.Timeout) ) {
|
|
||||||
_timeoutService.Timeout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -16,122 +16,49 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Widget;
|
|
||||||
using Android.Preferences;
|
using Android.Preferences;
|
||||||
using KeePassLib.Cryptography.Cipher;
|
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Activity to configure the app
|
/// Activity to configure the application, without database settings. Does not require an unlocked database, or close when the database is locked
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
|
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
|
||||||
public class AppSettingsActivity : LockingClosePreferenceActivity {
|
public class AppSettingsActivity : LockingPreferenceActivity
|
||||||
public static bool KeyfileDefault = false;
|
{
|
||||||
|
public static void Launch(Context ctx)
|
||||||
public static void Launch(Context ctx) {
|
{
|
||||||
Intent i = new Intent(ctx, typeof(AppSettingsActivity));
|
ctx.StartActivity(new Intent(ctx, typeof(AppSettingsActivity)));
|
||||||
|
|
||||||
ctx.StartActivity(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState) {
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
base.OnCreate(savedInstanceState);
|
base.OnCreate(savedInstanceState);
|
||||||
|
|
||||||
AddPreferencesFromResource(Resource.Xml.preferences);
|
AddPreferencesFromResource(Resource.Xml.preferences);
|
||||||
|
|
||||||
Preference keyFile = FindPreference(GetString(Resource.String.keyfile_key));
|
FindPreference(GetString(Resource.String.keyfile_key)).PreferenceChange += OnRememberKeyFileHistoryChanged;
|
||||||
keyFile.PreferenceChange += (sender, e) =>
|
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += OnShowUnlockedNotificationChanged;;
|
||||||
{
|
|
||||||
bool value = (bool) e.NewValue;
|
|
||||||
|
|
||||||
if ( ! value ) {
|
FindPreference(GetString(Resource.String.db_key)).Enabled = false;
|
||||||
FileDbHelper helper = App.Kp2a.FileDbHelper;
|
|
||||||
|
|
||||||
helper.DeleteAllKeys();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Database db = App.Kp2a.GetDb();
|
|
||||||
if ( db.Open ) {
|
|
||||||
Preference rounds = FindPreference(GetString(Resource.String.rounds_key));
|
|
||||||
rounds.PreferenceChange += (sender, e) =>
|
|
||||||
{
|
|
||||||
setRounds(App.Kp2a.GetDb(), e.Preference);
|
|
||||||
};
|
|
||||||
|
|
||||||
Preference defaultUser = FindPreference(GetString(Resource.String.default_username_key));
|
|
||||||
((EditTextPreference)defaultUser).EditText.Text = db.KpDatabase.DefaultUserName;
|
|
||||||
((EditTextPreference)defaultUser).Text = db.KpDatabase.DefaultUserName;
|
|
||||||
defaultUser.PreferenceChange += (sender, e) =>
|
|
||||||
{
|
|
||||||
DateTime previousUsernameChanged = db.KpDatabase.DefaultUserNameChanged;
|
|
||||||
String previousUsername = db.KpDatabase.DefaultUserName;
|
|
||||||
db.KpDatabase.DefaultUserName = e.NewValue.ToString();
|
|
||||||
|
|
||||||
SaveDb save = new SaveDb(this, App.Kp2a, new ActionOnFinish( (success, message) =>
|
|
||||||
{
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
db.KpDatabase.DefaultUserName = previousUsername;
|
|
||||||
db.KpDatabase.DefaultUserNameChanged = previousUsernameChanged;
|
|
||||||
Toast.MakeText(this, message, ToastLength.Long).Show();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
ProgressTask pt = new ProgressTask(App.Kp2a, this, save);
|
|
||||||
pt.Run();
|
|
||||||
};
|
|
||||||
|
|
||||||
Preference databaseName = FindPreference(GetString(Resource.String.database_name_key));
|
|
||||||
((EditTextPreference)databaseName).EditText.Text = db.KpDatabase.Name;
|
|
||||||
((EditTextPreference)databaseName).Text = db.KpDatabase.Name;
|
|
||||||
databaseName.PreferenceChange += (sender, e) =>
|
|
||||||
{
|
|
||||||
DateTime previousNameChanged = db.KpDatabase.NameChanged;
|
|
||||||
String previousName = db.KpDatabase.Name;
|
|
||||||
db.KpDatabase.Name = e.NewValue.ToString();
|
|
||||||
|
|
||||||
SaveDb save = new SaveDb(this, App.Kp2a, new ActionOnFinish( (success, message) =>
|
|
||||||
{
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
db.KpDatabase.Name = previousName;
|
|
||||||
db.KpDatabase.NameChanged = previousNameChanged;
|
|
||||||
Toast.MakeText(this, message, ToastLength.Long).Show();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
ProgressTask pt = new ProgressTask(App.Kp2a, this, save);
|
|
||||||
pt.Run();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setRounds(db, rounds);
|
|
||||||
|
|
||||||
Preference algorithm = FindPreference(GetString(Resource.String.algorithm_key));
|
|
||||||
setAlgorithm(db, algorithm);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Preference dbSettings = FindPreference(GetString(Resource.String.db_key));
|
|
||||||
dbSettings.Enabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void OnRememberKeyFileHistoryChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (!(bool)eventArgs.NewValue)
|
||||||
|
{
|
||||||
|
App.Kp2a.FileDbHelper.DeleteAllKeys();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRounds(Database db, Preference rounds) {
|
internal static void OnShowUnlockedNotificationChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
|
||||||
rounds.Summary = db.KpDatabase.KeyEncryptionRounds.ToString(CultureInfo.InvariantCulture);
|
{
|
||||||
|
var ctx = ((Preference)sender).Context;
|
||||||
|
ctx.StartService(new Intent(ctx, typeof(OngoingNotificationsService)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAlgorithm(Database db, Preference algorithm) {
|
|
||||||
|
|
||||||
algorithm.Summary = CipherPool.GlobalPool.GetCipher(db.KpDatabase.DataCipherUuid).DisplayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
121
src/keepass2android/settings/DatabaseSettingsActivity.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
||||||
|
|
||||||
|
Keepass2Android is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Keepass2Android is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Widget;
|
||||||
|
using Android.Preferences;
|
||||||
|
using KeePassLib.Cryptography.Cipher;
|
||||||
|
|
||||||
|
namespace keepass2android
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Activity to configure the application and database settings. The database must be unlocked, and this activity will close if it becomes locked.
|
||||||
|
/// </summary>
|
||||||
|
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
|
||||||
|
public class DatabaseSettingsActivity : LockingClosePreferenceActivity
|
||||||
|
{
|
||||||
|
public static void Launch(Context ctx)
|
||||||
|
{
|
||||||
|
ctx.StartActivity(new Intent(ctx, typeof(DatabaseSettingsActivity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
base.OnCreate(savedInstanceState);
|
||||||
|
|
||||||
|
AddPreferencesFromResource(Resource.Xml.preferences);
|
||||||
|
|
||||||
|
// Re-use the change handlers for the application settings
|
||||||
|
FindPreference(GetString(Resource.String.keyfile_key)).PreferenceChange += AppSettingsActivity.OnRememberKeyFileHistoryChanged;
|
||||||
|
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += AppSettingsActivity.OnShowUnlockedNotificationChanged;
|
||||||
|
|
||||||
|
Database db = App.Kp2a.GetDb();
|
||||||
|
|
||||||
|
Preference rounds = FindPreference(GetString(Resource.String.rounds_key));
|
||||||
|
rounds.PreferenceChange += (sender, e) => SetRounds(db, e.Preference);
|
||||||
|
|
||||||
|
Preference defaultUser = FindPreference(GetString(Resource.String.default_username_key));
|
||||||
|
((EditTextPreference)defaultUser).EditText.Text = db.KpDatabase.DefaultUserName;
|
||||||
|
((EditTextPreference)defaultUser).Text = db.KpDatabase.DefaultUserName;
|
||||||
|
defaultUser.PreferenceChange += (sender, e) =>
|
||||||
|
{
|
||||||
|
DateTime previousUsernameChanged = db.KpDatabase.DefaultUserNameChanged;
|
||||||
|
String previousUsername = db.KpDatabase.DefaultUserName;
|
||||||
|
db.KpDatabase.DefaultUserName = e.NewValue.ToString();
|
||||||
|
|
||||||
|
SaveDb save = new SaveDb(this, App.Kp2a, new ActionOnFinish( (success, message) =>
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
db.KpDatabase.DefaultUserName = previousUsername;
|
||||||
|
db.KpDatabase.DefaultUserNameChanged = previousUsernameChanged;
|
||||||
|
Toast.MakeText(this, message, ToastLength.Long).Show();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
ProgressTask pt = new ProgressTask(App.Kp2a, this, save);
|
||||||
|
pt.Run();
|
||||||
|
};
|
||||||
|
|
||||||
|
Preference databaseName = FindPreference(GetString(Resource.String.database_name_key));
|
||||||
|
((EditTextPreference)databaseName).EditText.Text = db.KpDatabase.Name;
|
||||||
|
((EditTextPreference)databaseName).Text = db.KpDatabase.Name;
|
||||||
|
databaseName.PreferenceChange += (sender, e) =>
|
||||||
|
{
|
||||||
|
DateTime previousNameChanged = db.KpDatabase.NameChanged;
|
||||||
|
String previousName = db.KpDatabase.Name;
|
||||||
|
db.KpDatabase.Name = e.NewValue.ToString();
|
||||||
|
|
||||||
|
SaveDb save = new SaveDb(this, App.Kp2a, new ActionOnFinish( (success, message) =>
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
db.KpDatabase.Name = previousName;
|
||||||
|
db.KpDatabase.NameChanged = previousNameChanged;
|
||||||
|
Toast.MakeText(this, message, ToastLength.Long).Show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Name is reflected in notification, so update it
|
||||||
|
StartService(new Intent(this, typeof(OngoingNotificationsService)));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
ProgressTask pt = new ProgressTask(App.Kp2a, this, save);
|
||||||
|
pt.Run();
|
||||||
|
};
|
||||||
|
|
||||||
|
SetRounds(db, rounds);
|
||||||
|
|
||||||
|
Preference algorithm = FindPreference(GetString(Resource.String.algorithm_key));
|
||||||
|
SetAlgorithm(db, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetRounds(Database db, Preference rounds)
|
||||||
|
{
|
||||||
|
rounds.Summary = db.KpDatabase.KeyEncryptionRounds.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAlgorithm(Database db, Preference algorithm)
|
||||||
|
{
|
||||||
|
algorithm.Summary = CipherPool.GlobalPool.GetCipher(db.KpDatabase.DataCipherUuid).DisplayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,7 +31,6 @@ namespace keepass2android.settings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoundsPreference : DialogPreference {
|
public class RoundsPreference : DialogPreference {
|
||||||
|
|
||||||
internal PwDatabase PwDatabase;
|
|
||||||
internal TextView RoundsView;
|
internal TextView RoundsView;
|
||||||
|
|
||||||
protected override View OnCreateDialogView() {
|
protected override View OnCreateDialogView() {
|
||||||
@ -40,8 +39,7 @@ namespace keepass2android.settings
|
|||||||
RoundsView = (TextView) view.FindViewById(Resource.Id.rounds);
|
RoundsView = (TextView) view.FindViewById(Resource.Id.rounds);
|
||||||
|
|
||||||
Database db = App.Kp2a.GetDb();
|
Database db = App.Kp2a.GetDb();
|
||||||
PwDatabase = db.KpDatabase;
|
ulong numRounds = db.KpDatabase.KeyEncryptionRounds;
|
||||||
ulong numRounds = PwDatabase.KeyEncryptionRounds;
|
|
||||||
RoundsView.Text = numRounds.ToString(CultureInfo.InvariantCulture);
|
RoundsView.Text = numRounds.ToString(CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
@ -70,14 +68,16 @@ namespace keepass2android.settings
|
|||||||
rounds = 1;
|
rounds = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong oldRounds = PwDatabase.KeyEncryptionRounds;
|
Database db = App.Kp2a.GetDb();
|
||||||
|
|
||||||
|
ulong oldRounds = db.KpDatabase.KeyEncryptionRounds;
|
||||||
|
|
||||||
if (oldRounds == rounds)
|
if (oldRounds == rounds)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PwDatabase.KeyEncryptionRounds = rounds;
|
db.KpDatabase.KeyEncryptionRounds = rounds;
|
||||||
|
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
SaveDb save = new SaveDb(Context, App.Kp2a, new AfterSave(Context, handler, oldRounds, this));
|
SaveDb save = new SaveDb(Context, App.Kp2a, new AfterSave(Context, handler, oldRounds, this));
|
||||||
@ -108,7 +108,8 @@ namespace keepass2android.settings
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DisplayMessage(_ctx);
|
DisplayMessage(_ctx);
|
||||||
_pref.PwDatabase.KeyEncryptionRounds = _oldRounds;
|
|
||||||
|
App.Kp2a.GetDb().KpDatabase.KeyEncryptionRounds = _oldRounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Run();
|
base.Run();
|
||||||
|
@ -31,21 +31,15 @@ namespace keepass2android
|
|||||||
|
|
||||||
private static class Timeout
|
private static class Timeout
|
||||||
{
|
{
|
||||||
private const int RequestId = 0;
|
|
||||||
private const long DefaultTimeout = 5 * 60 * 1000; // 5 minutes
|
private const long DefaultTimeout = 5 * 60 * 1000; // 5 minutes
|
||||||
|
|
||||||
private static PendingIntent BuildIntent(Context ctx)
|
private static PendingIntent BuildIntent(Context ctx)
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(Intents.Timeout);
|
return PendingIntent.GetBroadcast(ctx, 0, new Intent(Intents.LockDatabase), PendingIntentFlags.UpdateCurrent);
|
||||||
PendingIntent sender = PendingIntent.GetBroadcast(ctx, RequestId, intent, PendingIntentFlags.CancelCurrent);
|
|
||||||
|
|
||||||
return sender;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Start(Context ctx)
|
public static void Start(Context ctx)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
|
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
|
||||||
String sTimeout = prefs.GetString(ctx.GetString(Resource.String.app_timeout_key), ctx.GetString(Resource.String.clipboard_timeout_default));
|
String sTimeout = prefs.GetString(ctx.GetString(Resource.String.app_timeout_key), ctx.GetString(Resource.String.clipboard_timeout_default));
|
||||||
|
|
||||||
@ -61,8 +55,6 @@ namespace keepass2android
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.StartService(new Intent(ctx, typeof(TimeoutService)));
|
|
||||||
|
|
||||||
long triggerTime = Java.Lang.JavaSystem.CurrentTimeMillis() + timeout;
|
long triggerTime = Java.Lang.JavaSystem.CurrentTimeMillis() + timeout;
|
||||||
AlarmManager am = (AlarmManager)ctx.GetSystemService(Context.AlarmService);
|
AlarmManager am = (AlarmManager)ctx.GetSystemService(Context.AlarmService);
|
||||||
|
|
||||||
@ -76,69 +68,25 @@ namespace keepass2android
|
|||||||
|
|
||||||
Kp2aLog.Log("Timeout cancel");
|
Kp2aLog.Log("Timeout cancel");
|
||||||
am.Cancel(BuildIntent(ctx));
|
am.Cancel(BuildIntent(ctx));
|
||||||
|
|
||||||
ctx.StopService(new Intent(ctx, typeof(TimeoutService)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Pause(Activity act) {
|
public static void Pause(Activity act)
|
||||||
// Record timeout time in case timeout service is killed
|
{
|
||||||
long time = Java.Lang.JavaSystem.CurrentTimeMillis();
|
if ( App.Kp2a.DatabaseIsUnlocked )
|
||||||
|
{
|
||||||
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(act);
|
|
||||||
ISharedPreferencesEditor edit = prefs.Edit();
|
|
||||||
edit.PutLong(act.GetString(Resource.String.timeout_key), time);
|
|
||||||
|
|
||||||
Kp2aLog.Log("Pause: start at " + time);
|
|
||||||
|
|
||||||
EditorCompat.Apply(edit);
|
|
||||||
|
|
||||||
if ( App.Kp2a.GetDb().Open ) {
|
|
||||||
Timeout.Start(act);
|
Timeout.Start(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Resume(Activity act) {
|
public static void Resume(Activity act)
|
||||||
if ( App.Kp2a.GetDb().Loaded ) {
|
{
|
||||||
|
if ( App.Kp2a.GetDb().Loaded )
|
||||||
|
{
|
||||||
Timeout.Cancel(act);
|
Timeout.Cancel(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check whether the timeout has expired
|
|
||||||
long curTime = Java.Lang.JavaSystem.CurrentTimeMillis();
|
|
||||||
|
|
||||||
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(act);
|
|
||||||
long timeoutStart = prefs.GetLong(act.GetString(Resource.String.timeout_key), -1);
|
|
||||||
Kp2aLog.Log("timeoutStart=" + timeoutStart);
|
|
||||||
// The timeout never started
|
|
||||||
if (timeoutStart == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String sTimeout = prefs.GetString(act.GetString(Resource.String.app_timeout_key), act.GetString(Resource.String.clipboard_timeout_default));
|
|
||||||
long timeout;
|
|
||||||
if (!long.TryParse(sTimeout, out timeout) || (timeout == -1))
|
|
||||||
{
|
|
||||||
Kp2aLog.Log("exit with timeout=" + timeout + "/"+sTimeout);
|
|
||||||
// We are set to never timeout
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long diff = curTime - timeoutStart;
|
|
||||||
if (diff >= timeout)
|
|
||||||
{
|
|
||||||
// We have timed out
|
|
||||||
Kp2aLog.Log("Shutdown due to " + diff + ">=" + timeout);
|
|
||||||
App.Kp2a.SetShutdown();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Kp2aLog.Log("No shutdown due to " + diff + "<" + timeout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IocChanged(IOConnectionInfo ioc, IOConnectionInfo other)
|
static bool IocChanged(IOConnectionInfo ioc, IOConnectionInfo other)
|
||||||
@ -148,11 +96,10 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static bool CheckShutdown(Activity act, IOConnectionInfo ioc) {
|
public static bool CheckShutdown(Activity act, IOConnectionInfo ioc) {
|
||||||
if (( App.Kp2a.GetDb().Loaded && (App.Kp2a.IsShutdown() || App.Kp2a.GetDb().Locked) )
|
if (( !App.Kp2a.DatabaseIsUnlocked )
|
||||||
|| (IocChanged(ioc, App.Kp2a.GetDb().Ioc))) //file was changed from ActionSend-Intent
|
|| (IocChanged(ioc, App.Kp2a.GetDb().Ioc))) //file was changed from ActionSend-Intent
|
||||||
{
|
{
|
||||||
act.SetResult(KeePass.ExitLock);
|
App.Kp2a.LockDatabase();
|
||||||
act.Finish();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|