first version of KeeAutoExec functionality in Keepass2Android

This commit is contained in:
Philipp Crocoll
2018-11-19 19:06:12 +01:00
parent 58c6114840
commit 183c171da6
18 changed files with 397 additions and 147 deletions

View File

@@ -44,7 +44,7 @@ namespace keepass2android
/// <summary> /// <summary>
/// Loads the specified data as the currently open database, as unlocked. /// Loads the specified data as the currently open database, as unlocked.
/// </summary> /// </summary>
Database LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compKey, ProgressDialogStatusLogger statusLogger, IDatabaseFormat databaseFormat); Database LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compKey, ProgressDialogStatusLogger statusLogger, IDatabaseFormat databaseFormat, bool makeCurrent);
HashSet<PwGroup> DirtyGroups { get; } HashSet<PwGroup> DirtyGroups { get; }
@@ -64,12 +64,12 @@ namespace keepass2android
/// <summary> /// <summary>
/// Tell the app that the file from ioc was opened with keyfile. /// Tell the app that the file from ioc was opened with keyfile.
/// </summary> /// </summary>
void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, string displayName = ""); void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, bool updateTimestamp, string displayName = "");
/// <summary> /// <summary>
/// Creates a new database and returns it /// Creates a new database and returns it
/// </summary> /// </summary>
Database CreateNewDatabase(); Database CreateNewDatabase(bool makeCurrent);
/// <summary> /// <summary>
/// Returns the user-displayable string identified by stringKey /// Returns the user-displayable string identified by stringKey

View File

@@ -207,8 +207,7 @@ namespace keepass2android.Io
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc) public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
{ {
//TODO: required for OTP Aux file retrieval return IoUtil.GetParentPath(ioc);
throw new NotImplementedException();
} }
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename) public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)

View File

@@ -35,7 +35,7 @@ namespace keepass2android
private readonly String _name; private readonly String _name;
private readonly int _iconId; private readonly int _iconId;
private readonly PwUuid _groupCustomIconId; private readonly PwUuid _groupCustomIconId;
internal PwGroup Group; public PwGroup Group;
internal PwGroup Parent; internal PwGroup Parent;
protected bool DontSave; protected bool DontSave;
readonly Activity _ctx; readonly Activity _ctx;

View File

@@ -32,15 +32,17 @@ namespace keepass2android
private readonly Activity _ctx; private readonly Activity _ctx;
private readonly IKp2aApp _app; private readonly IKp2aApp _app;
private CompositeKey _key; private CompositeKey _key;
private readonly bool _makeCurrent;
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave): base(ctx, finish) { public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, bool makeCurrent): base(ctx, finish) {
_ctx = ctx; _ctx = ctx;
_ioc = ioc; _ioc = ioc;
_dontSave = dontSave; _dontSave = dontSave;
_app = app; _makeCurrent = makeCurrent;
_app = app;
} }
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key) public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key, bool makeCurrent)
: base(ctx, finish) : base(ctx, finish)
{ {
_ctx = ctx; _ctx = ctx;
@@ -48,12 +50,13 @@ namespace keepass2android
_dontSave = dontSave; _dontSave = dontSave;
_app = app; _app = app;
_key = key; _key = key;
_makeCurrent = makeCurrent;
} }
public override void Run() { public override void Run() {
StatusLogger.UpdateMessage(UiStringKey.progress_create); StatusLogger.UpdateMessage(UiStringKey.progress_create);
Database db = _app.CreateNewDatabase(); Database db = _app.CreateNewDatabase(_makeCurrent);
db.KpDatabase = new KeePassLib.PwDatabase(); db.KpDatabase = new KeePassLib.PwDatabase();

View File

@@ -37,21 +37,25 @@ namespace keepass2android
private readonly bool _rememberKeyfile; private readonly bool _rememberKeyfile;
IDatabaseFormat _format; IDatabaseFormat _format;
public LoadDb(Activity activity, IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish): base(activity, finish) public LoadDb(Activity activity, IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish, bool updateLastUsageTimestamp, bool makeCurrent): base(activity, finish)
{ {
_app = app; _app = app;
_ioc = ioc; _ioc = ioc;
_databaseData = databaseData; _databaseData = databaseData;
_compositeKey = compositeKey; _compositeKey = compositeKey;
_keyfileOrProvider = keyfileOrProvider; _keyfileOrProvider = keyfileOrProvider;
_updateLastUsageTimestamp = updateLastUsageTimestamp;
_makeCurrent = makeCurrent;
_rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile); _rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile);
} }
protected bool success = false; protected bool success = false;
private bool _updateLastUsageTimestamp;
public override void Run() private readonly bool _makeCurrent;
public override void Run()
{ {
try try
{ {
@@ -144,13 +148,9 @@ namespace keepass2android
//now let's go: //now let's go:
try try
{ {
Database newDb = _app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format); Database newDb = _app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format, _makeCurrent);
Kp2aLog.Log("LoadDB OK"); Kp2aLog.Log("LoadDB OK");
//make sure the stored access time for the actual file is more recent than that of its backup
Thread.Sleep(10);
SaveFileData(_ioc, _keyfileOrProvider);
Finish(true, _format.SuccessMessage); Finish(true, _format.SuccessMessage);
return newDb; return newDb;
} }
@@ -182,7 +182,7 @@ namespace keepass2android
{ {
keyfileOrProvider = ""; keyfileOrProvider = "";
} }
_app.StoreOpenedFileAsRecent(ioc, keyfileOrProvider); _app.StoreOpenedFileAsRecent(ioc, keyfileOrProvider, _updateLastUsageTimestamp);
} }

View File

@@ -110,11 +110,19 @@ namespace keepass2android
if (!KeeAutoExecExt.TryGetDatabaseIoc(autoExecItem, out ioc)) if (!KeeAutoExecExt.TryGetDatabaseIoc(autoExecItem, out ioc))
ioc = IOConnectionInfo.FromPath(entry.Strings.ReadSafe(PwDefs.UrlField)); ioc = IOConnectionInfo.FromPath(entry.Strings.ReadSafe(PwDefs.UrlField));
string path = ioc.Path; string path = ioc.Path;
var filestorage = App.Kp2a.GetFileStorage(ioc); try
if (filestorage != null)
{ {
path = filestorage.IocToPath(ioc); var filestorage = App.Kp2a.GetFileStorage(ioc);
if (filestorage != null)
{
path = filestorage.IocToPath(ioc);
}
} }
catch (NoFileStorageFoundException)
{
}
entry.Strings.Set(strUiDatabaseFile, new ProtectedString(false, path)); entry.Strings.Set(strUiDatabaseFile, new ProtectedString(false, path));
entry.Strings.Set(strUiKeyFile,new ProtectedString(false,entry.Strings.ReadSafe(PwDefs.UserNameField))); entry.Strings.Set(strUiKeyFile,new ProtectedString(false,entry.Strings.ReadSafe(PwDefs.UserNameField)));

View File

@@ -20,7 +20,10 @@ using Android.Widget;
using keepass2android.database.edit; using keepass2android.database.edit;
using KeePass.Util.Spr; using KeePass.Util.Spr;
using KeePassLib; using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Security; using KeePassLib.Security;
using KeePassLib.Serialization;
using AlertDialog = Android.App.AlertDialog;
using Object = Java.Lang.Object; using Object = Java.Lang.Object;
namespace keepass2android namespace keepass2android
@@ -92,6 +95,13 @@ namespace keepass2android
}; };
view.FindViewById<Button>(Resource.Id.child_db_open).Click += (sender, args) =>
{
View sending_view = (View)sender;
_context.OnOpen(_displayedChildDatabases[GetClickedPos(sending_view)]);
};
view.FindViewById<Button>(Resource.Id.child_db_enable_a_copy_for_this_device).Click += (sender, args) => view.FindViewById<Button>(Resource.Id.child_db_enable_a_copy_for_this_device).Click += (sender, args) =>
{ {
View sending_view = (View)sender; View sending_view = (View)sender;
@@ -144,6 +154,12 @@ namespace keepass2android
view.FindViewById(Resource.Id.child_db_disable_on_this_device).Visibility = (deviceEnabled || !deviceEnabledExplict) && autoExecItem.Enabled ? ViewStates.Visible : ViewStates.Gone; view.FindViewById(Resource.Id.child_db_disable_on_this_device).Visibility = (deviceEnabled || !deviceEnabledExplict) && autoExecItem.Enabled ? ViewStates.Visible : ViewStates.Gone;
view.FindViewById(Resource.Id.child_db_enable_a_copy_for_this_device_container).Visibility = !deviceEnabled && autoExecItem.Enabled ? ViewStates.Visible : ViewStates.Gone; view.FindViewById(Resource.Id.child_db_enable_a_copy_for_this_device_container).Visibility = !deviceEnabled && autoExecItem.Enabled ? ViewStates.Visible : ViewStates.Gone;
view.FindViewById(Resource.Id.child_db_edit).Visibility = deviceEnabledExplict || !autoExecItem.Enabled ? ViewStates.Visible : ViewStates.Gone; view.FindViewById(Resource.Id.child_db_edit).Visibility = deviceEnabledExplict || !autoExecItem.Enabled ? ViewStates.Visible : ViewStates.Gone;
IOConnectionInfo ioc;
if ((KeeAutoExecExt.TryGetDatabaseIoc(autoExecItem, out ioc)) && App.Kp2a.TryGetDatabase(ioc) == null)
{
view.FindViewById(Resource.Id.child_db_open).Visibility = ViewStates.Visible;
}
else view.FindViewById(Resource.Id.child_db_open).Visibility = ViewStates.Gone;
Database db = App.Kp2a.FindDatabaseForElement(pw); Database db = App.Kp2a.FindDatabaseForElement(pw);
@@ -181,13 +197,21 @@ namespace keepass2android
public void Update() public void Update()
{ {
_displayedChildDatabases = App.Kp2a.OpenDatabases.SelectMany(db => KeeAutoExecExt.GetAutoExecItems(db.KpDatabase)
_displayedChildDatabases = KeeAutoExecExt.GetAutoExecItems(App.Kp2a.CurrentDb.KpDatabase)
.Where(e => App.Kp2a.TryFindDatabaseForElement(e.Entry) != null) //Update() can be called while we're adding entries to the database. They may be part of the group but without saving complete
.OrderBy(e => SprEngine.Compile(e.Entry.Strings.ReadSafe(PwDefs.TitleField),new SprContext(e.Entry, App.Kp2a.FindDatabaseForElement(e.Entry).KpDatabase, SprCompileFlags.All))) .OrderBy(e => SprEngine.Compile(e.Entry.Strings.ReadSafe(PwDefs.TitleField),new SprContext(e.Entry, App.Kp2a.FindDatabaseForElement(e.Entry).KpDatabase, SprCompileFlags.All)))
.ThenByDescending(e => e.Entry.LastModificationTime)) .ThenByDescending(e => e.Entry.LastModificationTime)
.ToList(); .ToList();
} }
} }
private void OnOpen(AutoExecItem item)
{
KeeAutoExecExt.AutoOpenEntry(this, item, true);
}
private void OnEnableCopy(AutoExecItem item) private void OnEnableCopy(AutoExecItem item)
{ {
//disable this device for the cloned entry //disable this device for the cloned entry
@@ -219,7 +243,6 @@ namespace keepass2android
private void OnEdit(AutoExecItem item) private void OnEdit(AutoExecItem item)
{ {
App.Kp2a.CurrentDb = App.Kp2a.FindDatabaseForElement(item.Entry);
EntryEditActivity.Launch(this,item.Entry,new NullTask()); EntryEditActivity.Launch(this,item.Entry,new NullTask());
} }
@@ -263,6 +286,151 @@ namespace keepass2android
listView.Adapter = _adapter; listView.Adapter = _adapter;
SetSupportActionBar(FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.mytoolbar)); SetSupportActionBar(FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.mytoolbar));
FindViewById<Button>(Resource.Id.add_child_db_button).Click += (sender, args) =>
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetTitle(Resource.String.add_child_db);
List<string> items = new List<string>();
Dictionary<int, Database> indexToDb = new Dictionary<int, Database>();
foreach (var db in App.Kp2a.OpenDatabases)
{
if (db != App.Kp2a.CurrentDb)
{
indexToDb[items.Count] = db;
items.Add(App.Kp2a.GetFileStorage(db.Ioc).GetDisplayName(db.Ioc));
}
}
indexToDb[items.Count] = null;
items.Add(GetString(Resource.String.open_other_db));
builder.SetItems(items.ToArray(), (o, eventArgs) =>
{
Database db;
if (!indexToDb.TryGetValue(eventArgs.Which, out db) || (db == null))
{
StartFileSelect();
}
else
{
AddAutoOpenEntryForDatabase(db);
}
});
AlertDialog dialog = builder.Create();
dialog.Show();
};
} }
private void AddAutoOpenEntryForDatabase(Database db)
{
PwGroup autoOpenGroup = null;
var rootGroup = App.Kp2a.CurrentDb.KpDatabase.RootGroup;
foreach (PwGroup pgSub in rootGroup.Groups)
{
if (pgSub.Name == "AutoOpen")
{
autoOpenGroup = pgSub;
break;
}
}
if (autoOpenGroup == null)
{
AddGroup addGroupTask = AddGroup.GetInstance(this, App.Kp2a, "AutoOpen", 1, null, rootGroup, null, true);
addGroupTask.Run();
autoOpenGroup = addGroupTask.Group;
}
PwEntry newEntry = new PwEntry(true, true);
newEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, App.Kp2a.GetFileStorage(db.Ioc).GetDisplayName(db.Ioc)));
newEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, TryMakeRelativePath(App.Kp2a.CurrentDb, db.Ioc)));
var password = db.KpDatabase.MasterKey.GetUserKey<KcpPassword>();
newEntry.Strings.Set(PwDefs.PasswordField, password == null ? new ProtectedString(true, "") : password.Password);
var keyfile = db.KpDatabase.MasterKey.GetUserKey<KcpKeyFile>();
if ((keyfile != null) && (keyfile.Ioc != null))
{
newEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, TryMakeRelativePath(App.Kp2a.CurrentDb, keyfile.Ioc)));
}
newEntry.Strings.Set(KeeAutoExecExt._ifDevice,
new ProtectedString(false,
KeeAutoExecExt.BuildIfDevice(new Dictionary<string, bool>()
{
{KeeAutoExecExt.ThisDeviceId, true}
})));
var addTask = new AddEntry(this, App.Kp2a, newEntry, autoOpenGroup, new ActionOnFinish(this, (success, message, activity) => (activity as ConfigureChildDatabasesActivity)?.Update()));
ProgressTask pt = new ProgressTask(App.Kp2a, this, addTask);
pt.Run();
}
private string TryMakeRelativePath(Database db, IOConnectionInfo ioc)
{
try
{
var fsDb = App.Kp2a.GetFileStorage(db.Ioc);
var dbParent = fsDb.GetParentPath(db.Ioc).Path + "/";
if (ioc.Path.StartsWith(dbParent))
{
return "{DB_DIR}{ENV_DIRSEP}" + ioc.Path.Substring(dbParent.Length);
}
}
catch (NoFileStorageFoundException)
{
}
return ioc.Path;
}
private void StartFileSelect(bool noForwardToPassword = false)
{
Intent intent = new Intent(this, typeof(FileSelectActivity));
intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, noForwardToPassword);
intent.PutExtra("MakeCurrent", false);
StartActivityForResult(intent, ReqCodeOpenNewDb);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == ReqCodeOpenNewDb)
{
switch ((int)resultCode)
{
case (int)Result.Ok:
string iocString = data?.GetStringExtra("ioc");
IOConnectionInfo ioc = IOConnectionInfo.UnserializeFromString(iocString);
var db = App.Kp2a.TryGetDatabase(ioc);
if (db != null)
AddAutoOpenEntryForDatabase(db);
break;
case PasswordActivity.ResultSelectOtherFile:
StartFileSelect(true);
break;
default:
break;
}
return;
}
}
public const int ReqCodeOpenNewDb = 1;
} }
} }

View File

@@ -128,7 +128,7 @@ namespace keepass2android
FindViewById(Resource.Id.btn_create).Click += (sender, evt) => FindViewById(Resource.Id.btn_create).Click += (sender, evt) =>
{ {
CreateDatabase(); CreateDatabase(Intent.GetBooleanExtra("MakeCurrent",true));
}; };
ImageButton btnTogglePassword = (ImageButton)FindViewById(Resource.Id.toggle_password); ImageButton btnTogglePassword = (ImageButton)FindViewById(Resource.Id.toggle_password);
@@ -164,7 +164,7 @@ namespace keepass2android
} }
private void CreateDatabase() private void CreateDatabase(bool makeCurrent)
{ {
var keyfileCheckbox = FindViewById<CheckBox>(Resource.Id.use_keyfile); var keyfileCheckbox = FindViewById<CheckBox>(Resource.Id.use_keyfile);
string password; string password;
@@ -204,7 +204,7 @@ namespace keepass2android
} }
// Create the new database // Create the new database
CreateDb create = new CreateDb(App.Kp2a, this, _ioc, new LaunchGroupActivity(_ioc, this), false, newKey); CreateDb create = new CreateDb(App.Kp2a, this, _ioc, new LaunchGroupActivity(_ioc, this), false, newKey, makeCurrent);
ProgressTask createTask = new ProgressTask( ProgressTask createTask = new ProgressTask(
App.Kp2a, App.Kp2a,
this, create); this, create);
@@ -416,9 +416,7 @@ namespace keepass2android
// Add to recent files // Add to recent files
FileDbHelper dbHelper = App.Kp2a.FileDbHelper; FileDbHelper dbHelper = App.Kp2a.FileDbHelper;
dbHelper.CreateFile(_ioc, Filename, true);
//TODO: getFilename always returns "" -> bug?
dbHelper.CreateFile(_ioc, Filename);
} }
Intent data = new Intent(); Intent data = new Intent();
@@ -446,7 +444,7 @@ namespace keepass2android
} }
} }
public override bool OnOptionsItemSelected(IMenuItem item) public override bool OnOptionsItemSelected(IMenuItem item)
{ {
switch (item.ItemId) switch (item.ItemId)

View File

@@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using Android.App; using Android.App;
using Android.OS; using Android.OS;
using Android.Provider; using Android.Provider;
using Android.Webkit; using Android.Webkit;
using Android.Widget;
using Java.Nio.FileNio; using Java.Nio.FileNio;
using KeePass.DataExchange; using KeePass.DataExchange;
using KeePass.Util.Spr; using KeePass.Util.Spr;
@@ -260,36 +262,20 @@ namespace keepass2android
return a; return a;
} }
private void OnFileOpen(PwDatabase db) public static bool AutoOpenEntry(Activity activity, AutoExecItem item, bool bManual)
{
List<AutoExecItem> l = GetAutoExecItems(db);
foreach (AutoExecItem a in l)
{
if (!a.Enabled) continue;
try { AutoOpenEntryPriv(a, false); }
catch (Exception ex)
{
MessageService.ShowWarning(ex);
}
}
}
private void AutoOpenEntryPriv(AutoExecItem a, bool bManual)
{ {
string str; string str;
PwEntry pe = a.Entry; PwEntry pe = item.Entry;
SprContext ctxNoEsc = new SprContext(pe, a.Database, SprCompileFlags.All); SprContext ctxNoEsc = new SprContext(pe, item.Database, SprCompileFlags.All);
IOConnectionInfo ioc; IOConnectionInfo ioc;
if (!TryGetDatabaseIoc(a, out ioc)) return; if (!TryGetDatabaseIoc(item, out ioc)) return false;
var ob = GetBoolEx(pe, "SkipIfNotExists", ctxNoEsc); var ob = GetBoolEx(pe, "SkipIfNotExists", ctxNoEsc);
if (!ob.HasValue) // Backw. compat. if (!ob.HasValue) // Backw. compat.
ob = GetBoolEx(pe, "Skip if not exists", ctxNoEsc); ob = GetBoolEx(pe, "Skip if not exists", ctxNoEsc);
if (ob.HasValue && ob.Value) if (ob.HasValue && ob.Value)
{ {
//TODO adjust to KP2A if (!CheckFileExsts(ioc)) return false;
if (!IOConnection.FileExists(ioc)) return;
} }
CompositeKey ck = new CompositeKey(); CompositeKey ck = new CompositeKey();
@@ -303,8 +289,8 @@ namespace keepass2android
IOConnectionInfo iocKey = IOConnectionInfo.FromPath(strAbs); IOConnectionInfo iocKey = IOConnectionInfo.FromPath(strAbs);
if (iocKey.IsLocalFile() && !UrlUtil.IsAbsolutePath(strAbs)) if (iocKey.IsLocalFile() && !UrlUtil.IsAbsolutePath(strAbs))
{ {
//TODO //local relative paths not supported on Android
/* strAbs = UrlUtil.MakeAbsolutePath(WinUtil.GetExecutable(), strAbs);*/ return false;
} }
@@ -312,16 +298,14 @@ namespace keepass2android
if (ob.HasValue && ob.Value) if (ob.HasValue && ob.Value)
{ {
IOConnectionInfo iocKeyAbs = IOConnectionInfo.FromPath(strAbs); IOConnectionInfo iocKeyAbs = IOConnectionInfo.FromPath(strAbs);
//TODO adjust to KP2A if (!CheckFileExsts(iocKeyAbs)) return false;
if (!IOConnection.FileExists(iocKeyAbs)) return;
} }
try { ck.AddUserKey(new KcpKeyFile(strAbs)); } try { ck.AddUserKey(new KcpKeyFile(strAbs)); }
catch (InvalidOperationException) catch (InvalidOperationException)
{ {
//TODO Toast.MakeText(Application.Context,Resource.String.error_adding_keyfile,ToastLength.Long).Show();
throw new Exception("TODO"); return false;
//throw new Exception(strAbs + MessageService.NewParagraph + KPRes.KeyFileError);
} }
catch (Exception) { throw; } catch (Exception) { throw; }
} }
@@ -333,46 +317,32 @@ namespace keepass2android
StrUtil.DataToDataUri(pBin.ReadData(), null)))); StrUtil.DataToDataUri(pBin.ReadData(), null))));
} }
if (GetString(pe, "KeyProvider", ctxNoEsc, true, out str))
{
/*TODO KeyProvider kp = m_host.KeyProviderPool.Get(str);
if (kp == null)
throw new Exception(@"Unknown key provider: '" + str + @"'!");
KeyProviderQueryContext ctxKP = new KeyProviderQueryContext(
ioc, false, false);
bool bPerformHash = !kp.DirectKey;
byte[] pbProvKey = kp.GetKey(ctxKP);
if ((pbProvKey != null) && (pbProvKey.Length != 0))
{
ck.AddUserKey(new KcpCustomKey(str, pbProvKey, bPerformHash));
MemUtil.ZeroByteArray(pbProvKey);
}
else return; // Provider has shown error message*/
throw new Exception("KeyProvider not supported");
}
ob = GetBoolEx(pe, "UserAccount", ctxNoEsc);
if (ob.HasValue && ob.Value)
ck.AddUserKey(new KcpUserAccount());
if (ck.UserKeyCount == 0) return;
GetString(pe, "Focus", ctxNoEsc, true, out str); GetString(pe, "Focus", ctxNoEsc, true, out str);
bool bRestoreFocus = str.Equals("Restore", StrUtil.CaseIgnoreCmp); bool bRestoreFocus = str.Equals("Restore", StrUtil.CaseIgnoreCmp);
/*TODO
* PwDatabase pdPrev = m_host.MainWindow.ActiveDatabase;
m_host.MainWindow.OpenDatabase(ioc, ck, true); PasswordActivity.Launch(activity,ioc,ck,new ActivityLaunchModeSimple(), !
bRestoreFocus);
return true;
}
if (bRestoreFocus && (pdPrev != null) && !bManual) private static bool CheckFileExsts(IOConnectionInfo ioc)
{
try
{ {
PwDocument docPrev = m_host.MainWindow.DocumentManager.FindDocument( var fileStorage = App.Kp2a.GetFileStorage(ioc);
pdPrev); using (var stream = fileStorage.OpenFileForRead(ioc))
if (docPrev != null) m_host.MainWindow.MakeDocumentActive(docPrev); {
else { Debug.Assert(false); } }
}*/ }
catch (NoFileStorageFoundException e)
{
return false;
}
catch (FileNotFoundException)
{
return false;
}
return true;
} }
public static bool TryGetDatabaseIoc(AutoExecItem a, out IOConnectionInfo ioc) public static bool TryGetDatabaseIoc(AutoExecItem a, out IOConnectionInfo ioc)

View File

@@ -160,18 +160,19 @@ namespace keepass2android
static CompositeKey compositeKeyForImmediateLoad = null; static CompositeKey compositeKeyForImmediateLoad = null;
public static void Launch(Activity act, IOConnectionInfo ioc, CompositeKey compositeKey, ActivityLaunchMode launchMode) public static void Launch(Activity act, IOConnectionInfo ioc, CompositeKey compositeKey, ActivityLaunchMode launchMode, bool makeCurrent)
{ {
compositeKeyForImmediateLoad = compositeKey; compositeKeyForImmediateLoad = compositeKey;
Launch(act, ioc, launchMode); Launch(act, ioc, launchMode, makeCurrent);
} }
public static void Launch(Activity act, IOConnectionInfo ioc, ActivityLaunchMode launchMode) public static void Launch(Activity act, IOConnectionInfo ioc, ActivityLaunchMode launchMode, bool makeCurrent)
{ {
Intent i = new Intent(act, typeof(PasswordActivity)); Intent i = new Intent(act, typeof(PasswordActivity));
Util.PutIoConnectionToIntent(ioc, i); Util.PutIoConnectionToIntent(ioc, i);
i.PutExtra("MakeCurrent", makeCurrent);
launchMode.Launch(act, i); launchMode.Launch(act, i);
} }
@@ -1385,8 +1386,8 @@ namespace keepass2android
OnFinish onFinish = new AfterLoad(handler, this, _ioConnection); OnFinish onFinish = new AfterLoad(handler, this, _ioConnection);
LoadDb task = (KeyProviderTypes.Contains(KeyProviders.Otp)) LoadDb task = (KeyProviderTypes.Contains(KeyProviders.Otp))
? new SaveOtpAuxFileAndLoadDb(App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, GetKeyProviderString(), ? new SaveOtpAuxFileAndLoadDb(App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, GetKeyProviderString(),
onFinish, this) onFinish, this, true, Intent.GetBooleanExtra("MakeCurrent", true))
: new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, GetKeyProviderString(), onFinish); : new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, GetKeyProviderString(), onFinish,true, Intent.GetBooleanExtra("MakeCurrent",true));
_loadDbFileTask = null; // prevent accidental re-use _loadDbFileTask = null; // prevent accidental re-use
new ProgressTask(App.Kp2a, this, task).Run(); new ProgressTask(App.Kp2a, this, task).Run();
@@ -1734,7 +1735,7 @@ namespace keepass2android
OnFinish onFinish = new AfterLoad(handler, this, _ioConnection); OnFinish onFinish = new AfterLoad(handler, this, _ioConnection);
_performingLoad = true; _performingLoad = true;
LoadDb task = new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKeyForImmediateLoad, GetKeyProviderString(), LoadDb task = new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKeyForImmediateLoad, GetKeyProviderString(),
onFinish); onFinish, false, Intent.GetBooleanExtra("MakeCurrent",false));
_loadDbFileTask = null; // prevent accidental re-use _loadDbFileTask = null; // prevent accidental re-use
new ProgressTask(App.Kp2a, this, task).Run(); new ProgressTask(App.Kp2a, this, task).Run();
compositeKeyForImmediateLoad = null; //don't reuse or keep in memory compositeKeyForImmediateLoad = null; //don't reuse or keep in memory
@@ -2053,7 +2054,7 @@ namespace keepass2android
private readonly PasswordActivity _act; private readonly PasswordActivity _act;
public SaveOtpAuxFileAndLoadDb(IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, string keyfileOrProvider, OnFinish finish, PasswordActivity act) : base(act, app, ioc, databaseData, compositeKey, keyfileOrProvider, finish) public SaveOtpAuxFileAndLoadDb(IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, string keyfileOrProvider, OnFinish finish, PasswordActivity act, bool updateLastUsageTimestamp, bool makeCurrent) : base(act, app, ioc, databaseData, compositeKey, keyfileOrProvider, finish,updateLastUsageTimestamp,makeCurrent)
{ {
_act = act; _act = act;
} }

View File

@@ -80,6 +80,11 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/edit"/> android:text="@string/edit"/>
<Button
android:id="@+id/child_db_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_open"/>
<LinearLayout <LinearLayout
android:id="@+id/child_db_enable_a_copy_for_this_device_container" android:id="@+id/child_db_enable_a_copy_for_this_device_container"

View File

@@ -1,7 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ListView <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"
android:id="@android:id/list" android:background="?activityBackgroundColor"
android:layout_width="fill_parent" android:layout_height="fill_parent">
android:layout_height="fill_parent"
android:padding="8dp" /> <RelativeLayout
android:id="@+id/bottom_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:baselineAligned="false">
<Button
android:id="@+id/add_child_db_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="@string/add_child_db"
android:drawableLeft="@drawable/ic_plus"
style="@style/BottomBarButton" />
</RelativeLayout>
<ListView
android:id="@android:id/list"
android:padding="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/bottom_bar"
android:layout_marginBottom="12dip"
android:layout_marginLeft="12dip"
android:layout_marginRight="12dip"
android:layout_marginTop="12dip"
android:layout_alignParentTop="true" />
</RelativeLayout>

View File

@@ -744,6 +744,7 @@
<string name="child_db_enable_on_this_device">Enable on this device</string> <string name="child_db_enable_on_this_device">Enable on this device</string>
<string name="child_db_disable_on_this_device">Disable on this device</string> <string name="child_db_disable_on_this_device">Disable on this device</string>
<string name="child_db_enable_a_copy_for_this_device">Copy for this device</string> <string name="child_db_enable_a_copy_for_this_device">Copy for this device</string>
<string name="add_child_db">Add child database...</string>
<string name="EnableCopyForThisDevice_Info">This will create and enable a copy of the child database settings. These copied settings can then be adjusted specifically for this device.</string> <string name="EnableCopyForThisDevice_Info">This will create and enable a copy of the child database settings. These copied settings can then be adjusted specifically for this device.</string>
<string name="Visible_title">Visible</string> <string name="Visible_title">Visible</string>

View File

@@ -140,7 +140,7 @@ namespace keepass2android
private void OnOpenOther() private void OnOpenOther()
{ {
StartFileSelect(true); StartFileSelect(true, true);
} }
private void OnItemSelected(Database selectedDatabase) private void OnItemSelected(Database selectedDatabase)
@@ -267,7 +267,7 @@ namespace keepass2android
{ {
if (App.Kp2a.OpenDatabases.Any() == false) if (App.Kp2a.OpenDatabases.Any() == false)
{ {
StartFileSelect(); StartFileSelect(true);
return; return;
} }
@@ -281,6 +281,13 @@ namespace keepass2android
return; return;
} }
//see if there are any AutoOpen items to open
foreach (var db in App.Kp2a.OpenDatabases)
{
if (OpenAutoExecEntries(db)) return;
}
//database(s) unlocked //database(s) unlocked
if (App.Kp2a.OpenDatabases.Count() == 1) if (App.Kp2a.OpenDatabases.Count() == 1)
{ {
@@ -293,28 +300,55 @@ namespace keepass2android
_adapter.Update(); _adapter.Update();
_adapter.NotifyDataSetChanged(); _adapter.NotifyDataSetChanged();
} }
base.OnResume(); base.OnResume();
} }
private bool OpenAutoExecEntries(Database db)
{
string thisDevice = KeeAutoExecExt.ThisDeviceId;
foreach (var autoOpenItem in KeeAutoExecExt.GetAutoExecItems(db.KpDatabase))
{
if (!autoOpenItem.Enabled)
continue;
if (!KeeAutoExecExt.IsDeviceEnabled(autoOpenItem, thisDevice, out _))
continue;
IOConnectionInfo dbIoc;
if (KeeAutoExecExt.TryGetDatabaseIoc(autoOpenItem, out dbIoc) &&
App.Kp2a.TryGetDatabase(dbIoc) == null &&
App.Kp2a.AttemptedToOpenBefore(dbIoc) == false
)
{
if (KeeAutoExecExt.AutoOpenEntry(this, autoOpenItem, false))
{
LaunchingOther = true;
return true;
}
}
}
return false;
}
protected override void OnPause() protected override void OnPause()
{ {
LaunchingOther = false; LaunchingOther = false;
base.OnPause(); base.OnPause();
} }
private void StartFileSelect(bool noForwardToPassword = false) private void StartFileSelect(bool makeCurrent, bool noForwardToPassword = false)
{ {
Intent intent = new Intent(this, typeof(FileSelectActivity)); Intent intent = new Intent(this, typeof(FileSelectActivity));
AppTask.ToIntent(intent); AppTask.ToIntent(intent);
intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, noForwardToPassword); intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, noForwardToPassword);
intent.PutExtra("MakeCurrent", makeCurrent);
LaunchingOther = true; LaunchingOther = true;
StartActivityForResult(intent, ReqCodeOpenNewDb); StartActivityForResult(intent, ReqCodeOpenNewDb);
} }
internal AppTask AppTask; internal AppTask AppTask;
private bool _loadAnotherDatabase;
private OpenDatabaseAdapter _adapter; private OpenDatabaseAdapter _adapter;
private MyBroadcastReceiver _intentReceiver; private MyBroadcastReceiver _intentReceiver;
@@ -350,6 +384,7 @@ namespace keepass2android
IOConnectionInfo ioc = IOConnectionInfo.UnserializeFromString(iocString); IOConnectionInfo ioc = IOConnectionInfo.UnserializeFromString(iocString);
if (App.Kp2a.TrySelectCurrentDb(ioc)) if (App.Kp2a.TrySelectCurrentDb(ioc))
{ {
if (OpenAutoExecEntries(App.Kp2a.CurrentDb)) return;
LaunchingOther = true; LaunchingOther = true;
AppTask.CanActivateSearchViewOnStart = true; AppTask.CanActivateSearchViewOnStart = true;
AppTask.LaunchFirstGroupActivity(this); AppTask.LaunchFirstGroupActivity(this);
@@ -358,7 +393,7 @@ namespace keepass2android
break; break;
case PasswordActivity.ResultSelectOtherFile: case PasswordActivity.ResultSelectOtherFile:
StartFileSelect(true); StartFileSelect(true, true);
break; break;
case (int)Result.Canceled: case (int)Result.Canceled:
if (App.Kp2a.OpenDatabases.Any() == false) if (App.Kp2a.OpenDatabases.Any() == false)
@@ -410,7 +445,7 @@ namespace keepass2android
break; break;
case KeePass.ExitLoadAnotherDb: case KeePass.ExitLoadAnotherDb:
StartFileSelect(true); StartFileSelect(true, true);
break; break;
} }
@@ -419,7 +454,7 @@ namespace keepass2android
private void LaunchPasswordActivityForReload(IOConnectionInfo ioc, CompositeKey compositeKey) private void LaunchPasswordActivityForReload(IOConnectionInfo ioc, CompositeKey compositeKey)
{ {
LaunchingOther = true; LaunchingOther = true;
PasswordActivity.Launch(this, ioc, compositeKey, new ActivityLaunchModeRequestCode(ReqCodeOpenNewDb)); PasswordActivity.Launch(this, ioc, compositeKey, new ActivityLaunchModeRequestCode(ReqCodeOpenNewDb), false);
} }
public bool LaunchingOther { get; set; } public bool LaunchingOther { get; set; }

View File

@@ -129,6 +129,7 @@ namespace keepass2android
BroadcastDatabaseAction(Application.Context, Strings.ActionCloseDatabase); BroadcastDatabaseAction(Application.Context, Strings.ActionCloseDatabase);
// Couldn't quick-lock, so unload database(s) instead // Couldn't quick-lock, so unload database(s) instead
_openAttempts.Clear();
_openDatabases.Clear(); _openDatabases.Clear();
_currentDatabase = null; _currentDatabase = null;
LastOpenedEntry = null; LastOpenedEntry = null;
@@ -164,7 +165,7 @@ namespace keepass2android
public Database LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compositeKey, ProgressDialogStatusLogger statusLogger, IDatabaseFormat databaseFormat) public Database LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compositeKey, ProgressDialogStatusLogger statusLogger, IDatabaseFormat databaseFormat, bool makeCurrent)
{ {
var prefs = PreferenceManager.GetDefaultSharedPreferences(Application.Context); var prefs = PreferenceManager.GetDefaultSharedPreferences(Application.Context);
var createBackup = prefs.GetBoolean(Application.Context.GetString(Resource.String.CreateBackups_key), true) var createBackup = prefs.GetBoolean(Application.Context.GetString(Resource.String.CreateBackups_key), true)
@@ -190,12 +191,14 @@ namespace keepass2android
} }
_openAttempts.Add(ioConnectionInfo);
var newDb = new Database(new DrawableFactory(), this); var newDb = new Database(new DrawableFactory(), this);
newDb.LoadData(this, ioConnectionInfo, memoryStream, compositeKey, statusLogger, databaseFormat); newDb.LoadData(this, ioConnectionInfo, memoryStream, compositeKey, statusLogger, databaseFormat);
_currentDatabase = newDb; if ((_currentDatabase == null) || makeCurrent)
_currentDatabase = newDb;
_openDatabases.Add(newDb); _openDatabases.Add(newDb);
@@ -228,8 +231,8 @@ namespace keepass2android
Java.Lang.Object baseIocDisplayName = baseDisplayName; Java.Lang.Object baseIocDisplayName = baseDisplayName;
string keyfile = App.Kp2a.FileDbHelper.GetKeyFileForFile(ioConnectionInfo.Path); string keyfile = App.Kp2a.FileDbHelper.GetKeyFileForFile(ioConnectionInfo.Path);
App.Kp2a.StoreOpenedFileAsRecent(targetIoc, keyfile, Application.Context. App.Kp2a.StoreOpenedFileAsRecent(targetIoc, keyfile, false, Application.Context.
GetString(Resource.String.LocalBackupOf, new Java.Lang.Object[]{baseIocDisplayName})); GetString(Resource.String.LocalBackupOf, new Java.Lang.Object[]{baseIocDisplayName}));
prefs.Edit() prefs.Edit()
.PutBoolean(IoUtil.GetIocPrefKey(ioConnectionInfo, "has_local_backup"), true) .PutBoolean(IoUtil.GetIocPrefKey(ioConnectionInfo, "has_local_backup"), true)
@@ -341,6 +344,7 @@ namespace keepass2android
public FileDbHelper FileDbHelper; public FileDbHelper FileDbHelper;
private List<IFileStorage> _fileStorages; private List<IFileStorage> _fileStorages;
private readonly List<IOConnectionInfo> _openAttempts = new List<IOConnectionInfo>(); //stores which files have been attempted to open. Used to avoid that we repeatedly try to load files which failed to load.
private readonly List<Database> _openDatabases = new List<Database>(); private readonly List<Database> _openDatabases = new List<Database>();
private Database _currentDatabase; private Database _currentDatabase;
@@ -352,6 +356,16 @@ namespace keepass2android
public readonly HashSet<PwGroup> dirty = new HashSet<PwGroup>(new PwGroupEqualityFromIdComparer()); public readonly HashSet<PwGroup> dirty = new HashSet<PwGroup>(new PwGroupEqualityFromIdComparer());
public HashSet<PwGroup> DirtyGroups { get { return dirty; } } public HashSet<PwGroup> DirtyGroups { get { return dirty; } }
public bool AttemptedToOpenBefore(IOConnectionInfo ioc)
{
foreach (var attemptedIoc in _openAttempts)
{
if (attemptedIoc.IsSameFileAs(ioc))
return true;
}
return false;
}
public void MarkAllGroupsAsDirty() public void MarkAllGroupsAsDirty()
{ {
@@ -456,9 +470,9 @@ namespace keepass2android
dialog.Show(); dialog.Show();
} }
public void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, string displayName = "") public void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, bool updateTimestamp, string displayName = "")
{ {
FileDbHelper.CreateFile(ioc, keyfile, displayName); FileDbHelper.CreateFile(ioc, keyfile, updateTimestamp, displayName);
} }
public string GetResourceString(UiStringKey key) public string GetResourceString(UiStringKey key)
@@ -841,11 +855,13 @@ namespace keepass2android
} }
public Database CreateNewDatabase() public Database CreateNewDatabase(bool makeCurrent)
{ {
_currentDatabase = new Database(new DrawableFactory(), this); Database newDatabase = new Database(new DrawableFactory(), this);
_openDatabases.Add(_currentDatabase); if ((_currentDatabase == null) || makeCurrent)
return _currentDatabase; _currentDatabase = newDatabase;
_openDatabases.Add(newDatabase);
return newDatabase;
} }
internal void ShowToast(string message) internal void ShowToast(string message)
@@ -989,14 +1005,22 @@ namespace keepass2android
} }
} }
public Database GetDatabase(IOConnectionInfo dbIoc) public Database TryGetDatabase(IOConnectionInfo dbIoc)
{ {
foreach (Database db in OpenDatabases) foreach (Database db in OpenDatabases)
{ {
if (db.Ioc.IsSameFileAs(dbIoc)) if (db.Ioc.IsSameFileAs(dbIoc))
return db; return db;
} }
throw new Exception("Database not found for dbIoc!"); return null;
}
public Database GetDatabase(IOConnectionInfo dbIoc)
{
Database result = TryGetDatabase(dbIoc);
if (result == null)
throw new Exception("Database not found for dbIoc!");
return result;
} }
public Database GetDatabase(string databaseId) public Database GetDatabase(string databaseId)

View File

@@ -36,7 +36,7 @@ namespace keepass2android
private const String FileTable = "files"; private const String FileTable = "files";
private const int DatabaseVersion = 2; private const int DatabaseVersion = 2;
private const int MaxFiles = 15; private const int MaxFiles = 1000;
public const String KeyFileId = "_id"; public const String KeyFileId = "_id";
public const String KeyFileFilename = "fileName"; public const String KeyFileFilename = "fileName";
@@ -101,7 +101,7 @@ namespace keepass2android
mDb.Close(); mDb.Close();
} }
public long CreateFile(IOConnectionInfo ioc, string keyFile, string displayName = "") { public long CreateFile(IOConnectionInfo ioc, string keyFile, bool updateLastUsageTimestamp, string displayName = "") {
// Check to see if this filename is already used // Check to see if this filename is already used
ICursor cursor; ICursor cursor;
@@ -128,7 +128,8 @@ namespace keepass2android
var vals = new ContentValues(); var vals = new ContentValues();
vals.Put(KeyFileKeyfile, keyFile); vals.Put(KeyFileKeyfile, keyFile);
vals.Put(KeyFileUpdated, Java.Lang.JavaSystem.CurrentTimeMillis()); if (updateLastUsageTimestamp)
vals.Put(KeyFileUpdated, Java.Lang.JavaSystem.CurrentTimeMillis());
vals.Put(KeyFileUsername, iocToStore.UserName); vals.Put(KeyFileUsername, iocToStore.UserName);
vals.Put(KeyFilePassword, iocToStore.Password); vals.Put(KeyFilePassword, iocToStore.Password);
@@ -145,7 +146,7 @@ namespace keepass2android
vals.Put(KeyFileUsername, iocToStore.UserName); vals.Put(KeyFileUsername, iocToStore.UserName);
vals.Put(KeyFilePassword, iocToStore.Password); vals.Put(KeyFilePassword, iocToStore.Password);
vals.Put(KeyFileCredsavemode, (int)iocToStore.CredSaveMode); vals.Put(KeyFileCredsavemode, (int)iocToStore.CredSaveMode);
vals.Put(KeyFileUpdated, Java.Lang.JavaSystem.CurrentTimeMillis()); vals.Put(KeyFileUpdated, updateLastUsageTimestamp ? Java.Lang.JavaSystem.CurrentTimeMillis(): 0);
vals.Put(KeyFileDisplayname, displayName); vals.Put(KeyFileDisplayname, displayName);
result = mDb.Insert(FileTable, null, vals); result = mDb.Insert(FileTable, null, vals);

View File

@@ -301,7 +301,7 @@ namespace keepass2android
private void EditFileEntry(string filename, IOConnectionInfo newConnectionInfo) private void EditFileEntry(string filename, IOConnectionInfo newConnectionInfo)
{ {
_dbHelper.CreateFile(newConnectionInfo, _dbHelper.GetKeyFileForFile(filename)); _dbHelper.CreateFile(newConnectionInfo, _dbHelper.GetKeyFileForFile(filename), false);
_dbHelper.DeleteFile(filename); _dbHelper.DeleteFile(filename);
LaunchPasswordActivityForIoc(newConnectionInfo); LaunchPasswordActivityForIoc(newConnectionInfo);
@@ -342,7 +342,7 @@ namespace keepass2android
{ {
try try
{ {
PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward()); PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward(), Intent.GetBooleanExtra("MakeCurrent",true));
Finish(); Finish();
} catch (Java.IO.FileNotFoundException) } catch (Java.IO.FileNotFoundException)
{ {
@@ -355,7 +355,7 @@ namespace keepass2android
private void AfterQueryCredentials(IOConnectionInfo ioc) private void AfterQueryCredentials(IOConnectionInfo ioc)
{ {
PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward()); PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward(), Intent.GetBooleanExtra("MakeCurrent", true));
Finish(); Finish();
} }
@@ -437,14 +437,19 @@ namespace keepass2android
//if no database is loaded: load the most recent database //if no database is loaded: load the most recent database
if ( (Intent.GetBooleanExtra(NoForwardToPasswordActivity, false)==false) && _dbHelper.HasRecentFiles() && !App.Kp2a.OpenDatabases.Any()) if ( (Intent.GetBooleanExtra(NoForwardToPasswordActivity, false)==false) && _dbHelper.HasRecentFiles() && !App.Kp2a.OpenDatabases.Any())
{ {
ICursor filesCursor = _dbHelper.FetchAllFiles(); var fileStorage = new LocalFileStorage(App.Kp2a);
StartManagingCursor(filesCursor); ICursor filesCursor = _dbHelper.FetchAllFiles();
filesCursor.MoveToFirst(); filesCursor = new FilteredCursor(filesCursor, cursor => !fileStorage.IsLocalBackup(IOConnectionInfo.FromPath(cursor.GetString(1))));
IOConnectionInfo ioc = _dbHelper.CursorToIoc(filesCursor); StartManagingCursor(filesCursor);
if (App.Kp2a.GetFileStorage(ioc).RequiresSetup(ioc) == false) if (filesCursor.Count > 0)
{ {
LaunchPasswordActivityForIoc(ioc); filesCursor.MoveToFirst();
} IOConnectionInfo ioc = _dbHelper.CursorToIoc(filesCursor);
if (App.Kp2a.GetFileStorage(ioc).RequiresSetup(ioc) == false)
{
LaunchPasswordActivityForIoc(ioc);
}
}
} }

View File

@@ -876,7 +876,7 @@ namespace keepass2android
var newIoc = IoUtil.ImportFileToInternalDirectory(sourceIoc, Activity, App.Kp2a); var newIoc = IoUtil.ImportFileToInternalDirectory(sourceIoc, Activity, App.Kp2a);
((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).ResetIoc(newIoc); ((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).ResetIoc(newIoc);
var keyfileString = IOConnectionInfo.SerializeToString(newIoc); var keyfileString = IOConnectionInfo.SerializeToString(newIoc);
App.Kp2a.StoreOpenedFileAsRecent(App.Kp2a.CurrentDb.Ioc, keyfileString); App.Kp2a.StoreOpenedFileAsRecent(App.Kp2a.CurrentDb.Ioc, keyfileString, false);
return () => return () =>
{ {
UpdateImportKeyfilePref(); UpdateImportKeyfilePref();
@@ -952,7 +952,7 @@ namespace keepass2android
{ {
var key = App.Kp2a.CurrentDb.KpDatabase.MasterKey; var key = App.Kp2a.CurrentDb.KpDatabase.MasterKey;
App.Kp2a.CloseDatabase(App.Kp2a.CurrentDb); App.Kp2a.CloseDatabase(App.Kp2a.CurrentDb);
PasswordActivity.Launch(Activity, newIoc, key, new ActivityLaunchModeSimple()); PasswordActivity.Launch(Activity, newIoc, key, new ActivityLaunchModeSimple(), false);
}); });
builder.Show(); builder.Show();