bug fixes and improvements after adding multi-database support
This commit is contained in:
		@@ -88,7 +88,8 @@ namespace keepass2android
 | 
			
		||||
		                    EventHandler<DialogClickEventArgs> yesHandler,
 | 
			
		||||
		                    EventHandler<DialogClickEventArgs> noHandler,
 | 
			
		||||
		                    EventHandler<DialogClickEventArgs> cancelHandler,
 | 
			
		||||
		                    Context ctx);
 | 
			
		||||
		                    Context ctx,
 | 
			
		||||
                            string messageSuffix = "");
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Asks the user the question "messageKey" with the options Yes/No/Cancel, but the yes/no strings can be selected freely, calls the handler corresponding to the answer.
 | 
			
		||||
@@ -98,7 +99,8 @@ namespace keepass2android
 | 
			
		||||
		                    EventHandler<DialogClickEventArgs> yesHandler,
 | 
			
		||||
		                    EventHandler<DialogClickEventArgs> noHandler,
 | 
			
		||||
		                    EventHandler<DialogClickEventArgs> cancelHandler,
 | 
			
		||||
		                    Context ctx);
 | 
			
		||||
		                    Context ctx,
 | 
			
		||||
		                    string messageSuffix = "");
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Returns a Handler object which can run tasks on the UI thread
 | 
			
		||||
@@ -127,6 +129,5 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -211,6 +211,8 @@ namespace keepass2android
 | 
			
		||||
				}
 | 
			
		||||
				Entries [e.Uuid] = e;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		    Groups[currentGroup.Uuid] = currentGroup;
 | 
			
		||||
			foreach (PwGroup g in childGroups) 
 | 
			
		||||
			{
 | 
			
		||||
				if (checkForDuplicateUuids)
 | 
			
		||||
@@ -222,7 +224,6 @@ namespace keepass2android
 | 
			
		||||
					}
 | 
			
		||||
					 * */
 | 
			
		||||
				}
 | 
			
		||||
				Groups[g.Uuid] = g;
 | 
			
		||||
				PopulateGlobals(g);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -232,6 +233,12 @@ namespace keepass2android
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	    public void UpdateGlobals()
 | 
			
		||||
	    {
 | 
			
		||||
	        Entries.Clear();
 | 
			
		||||
	        Groups.Clear();
 | 
			
		||||
            PopulateGlobals(Root);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[Serializable]
 | 
			
		||||
 
 | 
			
		||||
@@ -89,6 +89,8 @@ namespace keepass2android
 | 
			
		||||
			_onFinishToRun = null;
 | 
			
		||||
			save.Run();
 | 
			
		||||
 | 
			
		||||
		    db.UpdateGlobals();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ namespace keepass2android
 | 
			
		||||
			//determine once. The property is queried for each delete operation, but might return false
 | 
			
		||||
			//after one entry/group is deleted (and thus in recycle bin and thus can't be recycled anymore)
 | 
			
		||||
			_canRecycle = DetermineCanRecycle();
 | 
			
		||||
		    ShowDatabaseIocInStatus = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private bool DetermineCanRecycle()
 | 
			
		||||
 
 | 
			
		||||
@@ -121,6 +121,8 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
		public void Start()
 | 
			
		||||
		{
 | 
			
		||||
            string messageSuffix = ShowDatabaseIocInStatus ? "(" + App.GetFileStorage(Db.Ioc).GetDisplayName(Db.Ioc) + ")" : "";
 | 
			
		||||
 | 
			
		||||
            if (CanRecycle)
 | 
			
		||||
			{
 | 
			
		||||
				App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title,
 | 
			
		||||
@@ -139,7 +141,7 @@ namespace keepass2android
 | 
			
		||||
				    pt.Run();
 | 
			
		||||
				},
 | 
			
		||||
				(dlgSender, dlgEvt) => { },
 | 
			
		||||
				Ctx);
 | 
			
		||||
				Ctx, messageSuffix);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -155,7 +157,7 @@ namespace keepass2android
 | 
			
		||||
					},
 | 
			
		||||
				null,
 | 
			
		||||
				(dlgSender, dlgEvt) => { },
 | 
			
		||||
				Ctx);
 | 
			
		||||
				Ctx, messageSuffix);
 | 
			
		||||
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
@@ -234,12 +236,20 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
			// Commit database
 | 
			
		||||
			SaveDb save = new SaveDb(Ctx, App, Db, OnFinishToRun, false);
 | 
			
		||||
		    save.ShowDatabaseIocInStatus = ShowDatabaseIocInStatus;
 | 
			
		||||
 | 
			
		||||
            save.SetStatusLogger(StatusLogger);
 | 
			
		||||
			save.Run();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	    public bool ShowDatabaseIocInStatus
 | 
			
		||||
	    {
 | 
			
		||||
	        get;
 | 
			
		||||
	        set;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    protected abstract void PerformDelete(List<PwGroup> touchedGroups, List<PwGroup> permanentlyDeletedGroups);
 | 
			
		||||
 | 
			
		||||
		public abstract UiStringKey StatusMessage { get; }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using Android.App;
 | 
			
		||||
@@ -50,11 +51,20 @@ namespace keepass2android.database.edit
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
		    HashSet<Database> removeDatabases = new HashSet<Database>();
 | 
			
		||||
            Database addDatabase = _app.FindDatabaseForGroupId(_targetGroup.Uuid);
 | 
			
		||||
		    if (addDatabase == null)
 | 
			
		||||
		    {
 | 
			
		||||
		        Finish(false, "Did not find target database. Did you lock it?");
 | 
			
		||||
		        return;
 | 
			
		||||
		    }
 | 
			
		||||
 | 
			
		||||
		    foreach (var elementToMove in _elementsToMove)
 | 
			
		||||
		    {
 | 
			
		||||
 | 
			
		||||
                _app.DirtyGroups.Add(elementToMove.ParentGroup);
 | 
			
		||||
                //TODO is this safe when transferring between databases?
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                PwGroup pgParent = elementToMove.ParentGroup;
 | 
			
		||||
                if (pgParent != _targetGroup)
 | 
			
		||||
                {
 | 
			
		||||
@@ -63,8 +73,12 @@ namespace keepass2android.database.edit
 | 
			
		||||
                        PwEntry entry = elementToMove as PwEntry;
 | 
			
		||||
                        if (entry != null)
 | 
			
		||||
                        {
 | 
			
		||||
                            var dbRem = _app.FindDatabaseForEntryId(entry.Uuid);
 | 
			
		||||
                            removeDatabases.Add(dbRem);
 | 
			
		||||
                            dbRem.Entries.Remove(entry.Uuid);
 | 
			
		||||
                            pgParent.Entries.Remove(entry);
 | 
			
		||||
                            _targetGroup.AddEntry(entry, true, true);
 | 
			
		||||
                            addDatabase.Entries.Add(entry.Uuid, entry);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
@@ -74,29 +88,57 @@ namespace keepass2android.database.edit
 | 
			
		||||
                                Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            var dbRem = _app.FindDatabaseForEntryId(@group.Uuid);
 | 
			
		||||
                            if (dbRem == null)
 | 
			
		||||
                            {
 | 
			
		||||
                                Finish(false, "Did not find source database. Did you lock it?");
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            dbRem.Groups.Remove(group.Uuid);
 | 
			
		||||
                            removeDatabases.Add(dbRem);
 | 
			
		||||
                            pgParent.Groups.Remove(group);
 | 
			
		||||
                            _targetGroup.AddGroup(group, true, true);
 | 
			
		||||
                        }
 | 
			
		||||
                            addDatabase.Groups.Add(group.Uuid, group);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
		    }
 | 
			
		||||
 | 
			
		||||
			_onFinishToRun = new ActionOnFinish(ActiveActivity, (success, message, activity) =>
 | 
			
		||||
		    
 | 
			
		||||
            
 | 
			
		||||
		    
 | 
			
		||||
		    //first save the database where we added the elements
 | 
			
		||||
            var allDatabasesToSave = new List<Database> {addDatabase};
 | 
			
		||||
            //then all databases where we removed elements:
 | 
			
		||||
		    removeDatabases.RemoveWhere(db => db == addDatabase);
 | 
			
		||||
            allDatabasesToSave.AddRange(removeDatabases);
 | 
			
		||||
 | 
			
		||||
		    int indexToSave = 0;
 | 
			
		||||
		    bool allSavesSuccess = true;
 | 
			
		||||
		    void ContinueSave(bool success, string message, Activity activeActivity)
 | 
			
		||||
		    {
 | 
			
		||||
				if (!success)
 | 
			
		||||
				{	// Let's not bother recovering from a failure.
 | 
			
		||||
					_app.Lock(false);
 | 
			
		||||
		        allSavesSuccess &= success;
 | 
			
		||||
                indexToSave++;
 | 
			
		||||
		        if (indexToSave == allDatabasesToSave.Count)
 | 
			
		||||
		        {
 | 
			
		||||
		            OnFinishToRun.SetResult(allSavesSuccess);
 | 
			
		||||
		            OnFinishToRun.Run();
 | 
			
		||||
		            return;
 | 
			
		||||
		        }
 | 
			
		||||
		        SaveDb saveDb = new SaveDb(_ctx, _app, allDatabasesToSave[indexToSave], new ActionOnFinish(activeActivity, ContinueSave), false);
 | 
			
		||||
		        saveDb.SetStatusLogger(StatusLogger);
 | 
			
		||||
		        saveDb.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
 | 
			
		||||
		        saveDb.Run();
 | 
			
		||||
		    }
 | 
			
		||||
			}, OnFinishToRun);
 | 
			
		||||
 | 
			
		||||
            //Unchecked
 | 
			
		||||
            //TODO save the right database
 | 
			
		||||
 | 
			
		||||
			// Save
 | 
			
		||||
			SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, false);
 | 
			
		||||
		    SaveDb save = new SaveDb(_ctx, _app, allDatabasesToSave[0], new ActionOnFinish(ActiveActivity, ContinueSave), false);
 | 
			
		||||
            save.SetStatusLogger(StatusLogger);
 | 
			
		||||
		    save.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
 | 
			
		||||
            save.Run();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,7 @@ namespace keepass2android
 | 
			
		||||
		    _dontSave = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	    public bool ShowDatabaseIocInStatus { get; set; }
 | 
			
		||||
	    
 | 
			
		||||
	    public override void Run ()
 | 
			
		||||
		{
 | 
			
		||||
@@ -95,7 +96,13 @@ namespace keepass2android
 | 
			
		||||
						return;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					StatusLogger.UpdateMessage(UiStringKey.saving_database);
 | 
			
		||||
				    string message = _app.GetResourceString(UiStringKey.saving_database);
 | 
			
		||||
 | 
			
		||||
				    if (ShowDatabaseIocInStatus)
 | 
			
		||||
				        message += " (" + _app.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")";
 | 
			
		||||
 | 
			
		||||
                    StatusLogger.UpdateMessage(message);
 | 
			
		||||
                    
 | 
			
		||||
					IOConnectionInfo ioc = _db.Ioc;
 | 
			
		||||
					IFileStorage fileStorage = _app.GetFileStorage(ioc);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										50
									
								
								src/keepass2android/ActivityLaunchMode.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/keepass2android/ActivityLaunchMode.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using Android.App;
 | 
			
		||||
using Android.Content;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using Android.Runtime;
 | 
			
		||||
using Android.Views;
 | 
			
		||||
using Android.Widget;
 | 
			
		||||
 | 
			
		||||
namespace keepass2android
 | 
			
		||||
{
 | 
			
		||||
    public abstract class ActivityLaunchMode
 | 
			
		||||
    {
 | 
			
		||||
        public abstract void Launch(Activity act, Intent i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class ActivityLaunchModeForward : ActivityLaunchMode
 | 
			
		||||
    {
 | 
			
		||||
        public override void Launch(Activity act, Intent i)
 | 
			
		||||
        {
 | 
			
		||||
            i.AddFlags(ActivityFlags.ForwardResult);
 | 
			
		||||
            act.StartActivity(i);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class ActivityLaunchModeRequestCode : ActivityLaunchMode
 | 
			
		||||
    {
 | 
			
		||||
        private readonly int _reqCode;
 | 
			
		||||
 | 
			
		||||
        public ActivityLaunchModeRequestCode(int reqCode)
 | 
			
		||||
        {
 | 
			
		||||
            _reqCode = reqCode;
 | 
			
		||||
        }
 | 
			
		||||
        public override void Launch(Activity act, Intent i)
 | 
			
		||||
        {
 | 
			
		||||
            act.StartActivityForResult(i, _reqCode);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class ActivityLaunchModeSimple : ActivityLaunchMode
 | 
			
		||||
    {
 | 
			
		||||
        public override void Launch(Activity act, Intent i)
 | 
			
		||||
        {
 | 
			
		||||
            act.StartActivity(i);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -497,7 +497,12 @@ namespace keepass2android
 | 
			
		||||
						dbHelper.CreateFile(_ioc, Filename);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					GroupActivity.Launch(_activity, _activity._appTask);
 | 
			
		||||
				    Intent data = new Intent();
 | 
			
		||||
				    data.PutExtra("ioc", IOConnectionInfo.SerializeToString(_ioc));
 | 
			
		||||
 | 
			
		||||
				    _activity.SetResult(Result.Ok, data);
 | 
			
		||||
 | 
			
		||||
				    
 | 
			
		||||
                    _activity.Finish();
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 
 | 
			
		||||
@@ -207,7 +207,14 @@ namespace keepass2android
 | 
			
		||||
			{
 | 
			
		||||
				Kp2aLog.Log("FP: StopListening ");
 | 
			
		||||
				_selfCancelled = true;
 | 
			
		||||
			    try
 | 
			
		||||
			    {
 | 
			
		||||
			        _cancellationSignal.Cancel();
 | 
			
		||||
                }
 | 
			
		||||
			    catch (System.ObjectDisposedException e)
 | 
			
		||||
			    {
 | 
			
		||||
			        Kp2aLog.LogUnexpectedError(e);
 | 
			
		||||
			    }
 | 
			
		||||
				_cancellationSignal = null;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -63,11 +63,11 @@ namespace keepass2android
 | 
			
		||||
		private const String Tag = "Group Activity:";
 | 
			
		||||
		private const string Askaddtemplates = "AskAddTemplates";
 | 
			
		||||
 | 
			
		||||
		public static void Launch(Activity act, AppTask appTask) {
 | 
			
		||||
			Launch(act, null, appTask);
 | 
			
		||||
		public static void Launch(Activity act, AppTask appTask, ActivityLaunchMode launchMode) {
 | 
			
		||||
			Launch(act, null, appTask, launchMode);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		public static void Launch (Activity act, PwGroup g, AppTask appTask)
 | 
			
		||||
		public static void Launch (Activity act, PwGroup g, AppTask appTask, ActivityLaunchMode launchMode)
 | 
			
		||||
		{
 | 
			
		||||
			Intent i = new Intent(act, typeof(GroupActivity));
 | 
			
		||||
				
 | 
			
		||||
@@ -76,7 +76,7 @@ namespace keepass2android
 | 
			
		||||
			}
 | 
			
		||||
			appTask.ToIntent(i);
 | 
			
		||||
 | 
			
		||||
			act.StartActivityForResult(i,0);
 | 
			
		||||
		    launchMode.Launch(act, i);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected PwUuid RetrieveGroupId(Intent i)
 | 
			
		||||
 
 | 
			
		||||
@@ -199,6 +199,12 @@ namespace keepass2android
 | 
			
		||||
                Finish();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (resultCode == KeePass.ExitLoadAnotherDb)
 | 
			
		||||
            {
 | 
			
		||||
                AppTask.SetActivityResult(this, KeePass.ExitLoadAnotherDb);
 | 
			
		||||
                Finish();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (resultCode == KeePass.ExitReloadDb)
 | 
			
		||||
            {
 | 
			
		||||
                AppTask.SetActivityResult(this, KeePass.ExitReloadDb);
 | 
			
		||||
 
 | 
			
		||||
@@ -67,8 +67,7 @@ namespace keepass2android
 | 
			
		||||
		ConfigurationChanges = ConfigChanges.Orientation,
 | 
			
		||||
		LaunchMode = LaunchMode.SingleInstance,
 | 
			
		||||
		WindowSoftInputMode = SoftInput.AdjustResize,
 | 
			
		||||
		Theme = "@style/MyTheme_Blue")] /*caution: also contained in AndroidManifest.xml*/
 | 
			
		||||
	//CAUTION: don't add intent filters here, they must be set in the manifest xml file
 | 
			
		||||
		Theme = "@style/MyTheme_Blue")] 
 | 
			
		||||
	public class PasswordActivity : LockingActivity, IFingerprintAuthCallback
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
@@ -84,10 +83,9 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
		public const String KeyDefaultFilename = "defaultFileName";
 | 
			
		||||
 | 
			
		||||
	    private const String KeyKeyfile = "keyFile";
 | 
			
		||||
	    private const String KeyPassword = "password";
 | 
			
		||||
	    public const String KeyKeyfile = "keyFile";
 | 
			
		||||
	    public const String KeyPassword = "password";
 | 
			
		||||
 | 
			
		||||
        private const String ViewIntent = "android.intent.action.VIEW";
 | 
			
		||||
		private const string ShowpasswordKey = "ShowPassword";
 | 
			
		||||
		private const string KeyProviderIdOtp = "KP2A-OTP";
 | 
			
		||||
		private const string KeyProviderIdOtpRecovery = "KP2A-OTPSecret";
 | 
			
		||||
@@ -103,6 +101,8 @@ namespace keepass2android
 | 
			
		||||
		private const int RequestCodePrepareKeyFile = 1004;
 | 
			
		||||
		private const int RequestCodeSelectAuxFile = 1005;
 | 
			
		||||
 | 
			
		||||
	    public const int ResultSelectOtherFile = (int) Result.FirstUser;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private Task<MemoryStream> _loadDbFileTask;
 | 
			
		||||
		private bool _loadDbTaskOffline; //indicate if preloading was started with offline mode
 | 
			
		||||
@@ -111,7 +111,6 @@ namespace keepass2android
 | 
			
		||||
		private String _keyFile;
 | 
			
		||||
		bool _showPassword;
 | 
			
		||||
 | 
			
		||||
		internal AppTask AppTask;
 | 
			
		||||
		private bool _killOnDestroy;
 | 
			
		||||
		private string _password = "";
 | 
			
		||||
		//OTPs which should be entered into the OTP fields as soon as these become visible
 | 
			
		||||
@@ -160,52 +159,31 @@ namespace keepass2android
 | 
			
		||||
        //can be set before launching the Activity. Will be used once to immediately open the database
 | 
			
		||||
        static CompositeKey compositeKeyForImmediateLoad = null;
 | 
			
		||||
 | 
			
		||||
	    public static void Launch(Activity act, IOConnectionInfo ioc, AppTask appTask, CompositeKey compositeKey)
 | 
			
		||||
 | 
			
		||||
        public static void Launch(Activity act, IOConnectionInfo ioc, CompositeKey compositeKey, ActivityLaunchMode launchMode)
 | 
			
		||||
	    {
 | 
			
		||||
	        compositeKeyForImmediateLoad = compositeKey;
 | 
			
		||||
	        Launch(act, ioc, appTask);
 | 
			
		||||
	        Launch(act, ioc, launchMode);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
        public static void Launch(Activity act, String fileName, AppTask appTask)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		public static void Launch(Activity act, IOConnectionInfo ioc, ActivityLaunchMode launchMode)
 | 
			
		||||
		{
 | 
			
		||||
			File dbFile = new File(fileName);
 | 
			
		||||
			if ( ! dbFile.Exists() ) {
 | 
			
		||||
				throw new FileNotFoundException();
 | 
			
		||||
			}
 | 
			
		||||
	
 | 
			
		||||
			
 | 
			
		||||
			Intent i = new Intent(act, typeof(PasswordActivity));
 | 
			
		||||
			i.SetFlags(ActivityFlags.ForwardResult);
 | 
			
		||||
			i.PutExtra(Util.KeyFilename, fileName);
 | 
			
		||||
			appTask.ToIntent(i);
 | 
			
		||||
 | 
			
		||||
			act.StartActivity(i);
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		public static void Launch(Activity act, IOConnectionInfo ioc, AppTask appTask)
 | 
			
		||||
		{
 | 
			
		||||
			if (ioc.IsLocalFile())
 | 
			
		||||
			{
 | 
			
		||||
				Launch(act, ioc.Path, appTask);
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Intent i = new Intent(act, typeof(PasswordActivity));
 | 
			
		||||
 | 
			
		||||
		    Util.PutIoConnectionToIntent(ioc, i);
 | 
			
		||||
			i.SetFlags(ActivityFlags.ForwardResult);
 | 
			
		||||
 | 
			
		||||
			appTask.ToIntent(i);
 | 
			
		||||
 | 
			
		||||
			act.StartActivity(i);
 | 
			
		||||
 | 
			
		||||
		    launchMode.Launch(act, i);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void LaunchNextActivity()
 | 
			
		||||
		{
 | 
			
		||||
            //StackBaseActivity will launch the next activity
 | 
			
		||||
            Intent data = new Intent();
 | 
			
		||||
		    data.PutExtra("ioc", IOConnectionInfo.SerializeToString(_ioConnection));
 | 
			
		||||
 | 
			
		||||
		    SetResult(Result.Ok, data);
 | 
			
		||||
 | 
			
		||||
		    Finish();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -215,8 +193,6 @@ namespace keepass2android
 | 
			
		||||
			_keepPasswordInOnResume = true; 
 | 
			
		||||
			Kp2aLog.Log("PasswordActivity.OnActivityResult "+resultCode+"/"+requestCode);
 | 
			
		||||
 | 
			
		||||
			AppTask.TryGetFromActivityResult(data, ref AppTask);
 | 
			
		||||
 | 
			
		||||
			switch(resultCode) {
 | 
			
		||||
 | 
			
		||||
				
 | 
			
		||||
@@ -678,19 +654,6 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
			Intent i = Intent;
 | 
			
		||||
 | 
			
		||||
			//only load the AppTask if this is the "first" OnCreate (not because of kill/resume, i.e. savedInstanceState==null)
 | 
			
		||||
			// and if the activity is not launched from history (i.e. recent tasks) because this would mean that
 | 
			
		||||
			// the Activity was closed already (user cancelling the task or task complete) but is restarted due recent tasks.
 | 
			
		||||
			// Don't re-start the task (especially bad if tak was complete already)
 | 
			
		||||
			if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
 | 
			
		||||
			{
 | 
			
		||||
				AppTask = new NullTask();
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			String action = i.Action;
 | 
			
		||||
 | 
			
		||||
@@ -700,11 +663,7 @@ namespace keepass2android
 | 
			
		||||
			_ioConnection = new IOConnectionInfo();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			if (action != null && action.Equals(ViewIntent))
 | 
			
		||||
			{
 | 
			
		||||
				if (!GetIocFromViewIntent(i)) return;
 | 
			
		||||
			}
 | 
			
		||||
			else if ((action != null) && (action.Equals(Intents.StartWithOtp)))
 | 
			
		||||
            if ((action != null) && (action.Equals(Intents.StartWithOtp)))
 | 
			
		||||
			{
 | 
			
		||||
				if (!GetIocFromOtpIntent(savedInstanceState, i)) return;
 | 
			
		||||
				_keepPasswordInOnResume = true;
 | 
			
		||||
@@ -802,11 +761,10 @@ namespace keepass2android
 | 
			
		||||
				RequestPermissions(new[] { Manifest.Permission.UseFingerprint }, FingerprintPermissionRequestCode);
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
		    var matchingOpenDb = App.Kp2a.OpenDatabases.FirstOrDefault(db => db.Ioc.IsSameFileAs(_ioConnection));
 | 
			
		||||
		    if (matchingOpenDb != null)
 | 
			
		||||
		    if (App.Kp2a.TrySelectCurrentDb(_ioConnection))
 | 
			
		||||
            { 
 | 
			
		||||
		        App.Kp2a.CurrentDb = matchingOpenDb;
 | 
			
		||||
		        Finish();
 | 
			
		||||
                //database already opened. return the ioc and we're good.
 | 
			
		||||
		        LaunchNextActivity();
 | 
			
		||||
		    }
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
@@ -1137,50 +1095,6 @@ namespace keepass2android
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private bool GetIocFromViewIntent(Intent i)
 | 
			
		||||
		{
 | 
			
		||||
			//started from "view" intent (e.g. from file browser)
 | 
			
		||||
			_ioConnection.Path = i.DataString;
 | 
			
		||||
 | 
			
		||||
			if (_ioConnection.Path.StartsWith("file://"))
 | 
			
		||||
			{
 | 
			
		||||
				_ioConnection.Path = URLDecoder.Decode(_ioConnection.Path.Substring(7));
 | 
			
		||||
 | 
			
		||||
				if (_ioConnection.Path.Length == 0)
 | 
			
		||||
				{
 | 
			
		||||
					// No file name
 | 
			
		||||
					Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
 | 
			
		||||
					Finish();
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				File dbFile = new File(_ioConnection.Path);
 | 
			
		||||
				if (!dbFile.Exists())
 | 
			
		||||
				{
 | 
			
		||||
					// File does not exist
 | 
			
		||||
					Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
 | 
			
		||||
					Finish();
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				if (!_ioConnection.Path.StartsWith("content://"))
 | 
			
		||||
				{
 | 
			
		||||
			
 | 
			
		||||
					Toast.MakeText(this, Resource.String.error_can_not_handle_uri, ToastLength.Long).Show();
 | 
			
		||||
					Finish();
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
				IoUtil.TryTakePersistablePermissions(this.ContentResolver, i.Data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
			SetKeyProviderFromString(LoadKeyProviderStringForIoc(_ioConnection.Path));
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void InitializeBottomBarButtons()
 | 
			
		||||
		{
 | 
			
		||||
@@ -1607,7 +1521,6 @@ namespace keepass2android
 | 
			
		||||
		        CopyToClipboardService.ActivateKeyboard(this);
 | 
			
		||||
		    }
 | 
			
		||||
 | 
			
		||||
                AppTask.CanActivateSearchViewOnStart = true;
 | 
			
		||||
            DonateReminder.ShowDonateReminderIfAppropriate(this);
 | 
			
		||||
			
 | 
			
		||||
			
 | 
			
		||||
@@ -1635,7 +1548,6 @@ namespace keepass2android
 | 
			
		||||
		protected override void OnSaveInstanceState(Bundle outState)
 | 
			
		||||
		{
 | 
			
		||||
			base.OnSaveInstanceState(outState);
 | 
			
		||||
			AppTask.ToBundle(outState);
 | 
			
		||||
			outState.PutBoolean(ShowpasswordKey, _showPassword);
 | 
			
		||||
 | 
			
		||||
			outState.PutString(KeyFileOrProviderKey, GetKeyProviderString());
 | 
			
		||||
@@ -1751,6 +1663,7 @@ namespace keepass2android
 | 
			
		||||
				killButton.Click += (sender, args) =>
 | 
			
		||||
				{
 | 
			
		||||
					_killOnDestroy = true;
 | 
			
		||||
                    SetResult(Result.Canceled);
 | 
			
		||||
					Finish();
 | 
			
		||||
 | 
			
		||||
				};
 | 
			
		||||
@@ -1986,11 +1899,7 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
		private void GoToFileSelectActivity()
 | 
			
		||||
		{
 | 
			
		||||
			Intent intent = new Intent(this, typeof (FileSelectActivity));
 | 
			
		||||
			intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, true);
 | 
			
		||||
			AppTask.ToIntent(intent);
 | 
			
		||||
			intent.AddFlags(ActivityFlags.ForwardResult);
 | 
			
		||||
			StartActivity(intent);
 | 
			
		||||
		    SetResult((Result) ResultSelectOtherFile);
 | 
			
		||||
            Finish();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -2014,7 +1923,6 @@ namespace keepass2android
 | 
			
		||||
					_act.BroadcastOpenDatabase();
 | 
			
		||||
					_act.InvalidCompositeKeyCount = 0;
 | 
			
		||||
				    _act.LoadingErrorCount = 0;
 | 
			
		||||
                    _act.Finish();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    GC.Collect(); // Ensure temporary memory used while loading is collected
 | 
			
		||||
@@ -2080,7 +1988,10 @@ namespace keepass2android
 | 
			
		||||
					                                                (sender, args) =>
 | 
			
		||||
						                                                {
 | 
			
		||||
							                                                ((Dialog) sender).Dismiss();
 | 
			
		||||
						                                                    if (Success)
 | 
			
		||||
						                                                    {
 | 
			
		||||
						                                                        _act.LaunchNextActivity();
 | 
			
		||||
						                                                    }
 | 
			
		||||
                                                                        })
 | 
			
		||||
												.SetCancelable(false)
 | 
			
		||||
												.Show();
 | 
			
		||||
@@ -2094,7 +2005,6 @@ namespace keepass2android
 | 
			
		||||
				        _act.LaunchNextActivity();
 | 
			
		||||
				    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			    //re-init fingerprint unlock in case something went wrong with opening the database 
 | 
			
		||||
@@ -2207,6 +2117,7 @@ namespace keepass2android
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	    
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </activity>
 | 
			
		||||
		
 | 
			
		||||
		<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity"  android:windowSoftInputMode="adjustResize">
 | 
			
		||||
		<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity"  android:windowSoftInputMode="adjustResize">
 | 
			
		||||
			<intent-filter android:label="@string/app_name">
 | 
			
		||||
				<action android:name="android.intent.action.VIEW" />
 | 
			
		||||
				<category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
@@ -64,7 +64,7 @@
 | 
			
		||||
			  </intent-filter>
 | 
			
		||||
			  
 | 
			
		||||
			  <intent-filter>
 | 
			
		||||
				<action android:name="kp2a.action.PasswordActivity" />
 | 
			
		||||
				<action android:name="kp2a.action.SelectCurrentDbActivity" />
 | 
			
		||||
				<category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
			  </intent-filter>
 | 
			
		||||
			  
 | 
			
		||||
@@ -97,13 +97,15 @@
 | 
			
		||||
				<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
 | 
			
		||||
				<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
 | 
			
		||||
			</intent-filter>
 | 
			
		||||
 | 
			
		||||
			<intent-filter android:label="@string/kp2a_findUrl">
 | 
			
		||||
				<action android:name="android.intent.action.SEND" />
 | 
			
		||||
				<category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
				<data android:mimeType="text/plain" />
 | 
			
		||||
			</intent-filter>
 | 
			
		||||
			<intent-filter>
 | 
			
		||||
				<action android:name="android.intent.action.VIEW"/>
 | 
			
		||||
				<category android:name="android.intent.category.BROWSABLE"/>
 | 
			
		||||
				<data
 | 
			
		||||
					android:scheme="https"
 | 
			
		||||
					android:host="my.yubico.com"
 | 
			
		||||
					android:pathPrefix="/neo"/>
 | 
			
		||||
				<action android:name="keepass2android.ACTION_START_WITH_TASK" />
 | 
			
		||||
				<category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
			</intent-filter>
 | 
			
		||||
		</activity>
 | 
			
		||||
		<uses-library required="false" name="com.sec.android.app.multiwindow" />
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@
 | 
			
		||||
                <category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </activity>
 | 
			
		||||
		<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity"  android:windowSoftInputMode="adjustResize">
 | 
			
		||||
		<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity"  android:windowSoftInputMode="adjustResize">
 | 
			
		||||
      <intent-filter android:label="@string/app_name">
 | 
			
		||||
        <action android:name="android.intent.action.VIEW" />
 | 
			
		||||
        <category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
@@ -69,7 +69,7 @@
 | 
			
		||||
      </intent-filter>
 | 
			
		||||
	  
 | 
			
		||||
	  <intent-filter>
 | 
			
		||||
        <action android:name="kp2a.action.PasswordActivity" />
 | 
			
		||||
        <action android:name="kp2a.action.SelectCurrentDbActivity" />
 | 
			
		||||
        <category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
      </intent-filter>
 | 
			
		||||
	  
 | 
			
		||||
@@ -121,14 +121,15 @@
 | 
			
		||||
        <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
 | 
			
		||||
        <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
 | 
			
		||||
        <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
 | 
			
		||||
      </intent-filter>
 | 
			
		||||
	  			<intent-filter android:label="@string/kp2a_findUrl">
 | 
			
		||||
				<action android:name="android.intent.action.SEND" />
 | 
			
		||||
				<category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
				<data android:mimeType="text/plain" />
 | 
			
		||||
			</intent-filter>
 | 
			
		||||
			<intent-filter>
 | 
			
		||||
        <action android:name="android.intent.action.VIEW"/>
 | 
			
		||||
        <category android:name="android.intent.category.BROWSABLE"/>
 | 
			
		||||
        <data
 | 
			
		||||
          android:scheme="https"
 | 
			
		||||
          android:host="my.yubico.com"
 | 
			
		||||
          android:pathPrefix="/neo"/>
 | 
			
		||||
				<action android:name="keepass2android.ACTION_START_WITH_TASK" />
 | 
			
		||||
				<category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
			</intent-filter>
 | 
			
		||||
		</activity>
 | 
			
		||||
			<uses-library required="false" name="com.sec.android.app.multiwindow" />
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </activity>
 | 
			
		||||
 
 | 
			
		||||
		<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" android:windowSoftInputMode="adjustResize">
 | 
			
		||||
		<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize">
 | 
			
		||||
      <intent-filter android:label="@string/app_name">
 | 
			
		||||
        <action android:name="android.intent.action.VIEW" />
 | 
			
		||||
        <category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
@@ -52,7 +52,7 @@
 | 
			
		||||
      </intent-filter>
 | 
			
		||||
 | 
			
		||||
	  <intent-filter>
 | 
			
		||||
        <action android:name="kp2a.action.PasswordActivity" />
 | 
			
		||||
        <action android:name="kp2a.action.SelectCurrentDbActivity" />
 | 
			
		||||
        <category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
      </intent-filter>
 | 
			
		||||
	  
 | 
			
		||||
@@ -111,6 +111,16 @@
 | 
			
		||||
          android:scheme="https"
 | 
			
		||||
          android:host="my.yubico.com"
 | 
			
		||||
          android:pathPrefix="/neo"/>
 | 
			
		||||
      </intent-filter>
 | 
			
		||||
	  
 | 
			
		||||
			<intent-filter android:label="@string/kp2a_findUrl">
 | 
			
		||||
				<action android:name="android.intent.action.SEND" />
 | 
			
		||||
				<category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
				<data android:mimeType="text/plain" />
 | 
			
		||||
			</intent-filter>
 | 
			
		||||
			<intent-filter>
 | 
			
		||||
				<action android:name="keepass2android.ACTION_START_WITH_TASK" />
 | 
			
		||||
				<category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
			</intent-filter>
 | 
			
		||||
		</activity>
 | 
			
		||||
		<uses-library required="false" name="com.sec.android.app.multiwindow" />
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@ using Android.Text;
 | 
			
		||||
using Android.Util;
 | 
			
		||||
using Android.Views;
 | 
			
		||||
using Android.Widget;
 | 
			
		||||
using Java.IO;
 | 
			
		||||
using Java.Net;
 | 
			
		||||
using keepass2android.Io;
 | 
			
		||||
using keepass2android.Utils;
 | 
			
		||||
using KeePassLib.Keys;
 | 
			
		||||
@@ -24,9 +26,12 @@ using Object = Java.Lang.Object;
 | 
			
		||||
 | 
			
		||||
namespace keepass2android
 | 
			
		||||
{
 | 
			
		||||
    [Activity(Label = AppNames.AppName, MainLauncher = false, Theme = "@style/MyTheme_Blue", LaunchMode = LaunchMode.SingleInstance)]
 | 
			
		||||
    [Activity(Label = AppNames.AppName, MainLauncher = false, Theme = "@style/MyTheme_Blue", LaunchMode = LaunchMode.SingleInstance)] //caution, see manifest file
 | 
			
		||||
    public class SelectCurrentDbActivity : AppCompatActivity
 | 
			
		||||
    {
 | 
			
		||||
        private int ReqCodeOpenNewDb = 1;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        public class OpenDatabaseAdapter : BaseAdapter
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
@@ -135,12 +140,13 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
        private void OnOpenOther()
 | 
			
		||||
        {
 | 
			
		||||
            StartFileSelect();
 | 
			
		||||
            StartFileSelect(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnItemSelected(Database selectedDatabase)
 | 
			
		||||
        {
 | 
			
		||||
            App.Kp2a.CurrentDb = selectedDatabase;
 | 
			
		||||
            LaunchingOther = true;
 | 
			
		||||
            AppTask.LaunchFirstGroupActivity(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -155,7 +161,12 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
            SupportActionBar.Title = GetString(Resource.String.select_database);
 | 
			
		||||
 | 
			
		||||
            if ((AppTask == null) && (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory)))
 | 
			
		||||
 | 
			
		||||
            //only load the AppTask if this is the "first" OnCreate (not because of kill/resume, i.e. savedInstanceState==null)
 | 
			
		||||
            // and if the activity is not launched from history (i.e. recent tasks) because this would mean that
 | 
			
		||||
            // the Activity was closed already (user cancelling the task or task complete) but is restarted due recent tasks.
 | 
			
		||||
            // Don't re-start the task (especially bad if tak was complete already)
 | 
			
		||||
            if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
 | 
			
		||||
            {
 | 
			
		||||
                AppTask = new NullTask();
 | 
			
		||||
            }
 | 
			
		||||
@@ -169,18 +180,90 @@ namespace keepass2android
 | 
			
		||||
            gridView.ItemClick += (sender, args) => OnItemSelected(_adapter._displayedDatabases[args.Position]);
 | 
			
		||||
            gridView.Adapter = _adapter;
 | 
			
		||||
 | 
			
		||||
            if (!string.IsNullOrEmpty(Intent.GetStringExtra(Util.KeyFilename)))
 | 
			
		||||
            {
 | 
			
		||||
                //forward to password activity
 | 
			
		||||
                Intent i = new Intent(this, typeof(PasswordActivity));
 | 
			
		||||
                IOConnectionInfo ioc = new IOConnectionInfo();
 | 
			
		||||
                Util.SetIoConnectionFromIntent(ioc, Intent);
 | 
			
		||||
                Util.PutIoConnectionToIntent(ioc, i);
 | 
			
		||||
                i.PutExtra(PasswordActivity.KeyKeyfile, i.GetStringExtra(PasswordActivity.KeyKeyfile));
 | 
			
		||||
                i.PutExtra(PasswordActivity.KeyPassword, i.GetStringExtra(PasswordActivity.KeyPassword));
 | 
			
		||||
                LaunchingOther = true;
 | 
			
		||||
                StartActivityForResult(i, ReqCodeOpenNewDb);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (Intent.Action == Intent.ActionView)
 | 
			
		||||
                {
 | 
			
		||||
                    GetIocFromViewIntent(Intent);
 | 
			
		||||
                }
 | 
			
		||||
                else if (Intent.Action == Intent.ActionSend)
 | 
			
		||||
                {
 | 
			
		||||
                    AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _intentReceiver = new MyBroadcastReceiver(this);
 | 
			
		||||
            IntentFilter filter = new IntentFilter();
 | 
			
		||||
            filter.AddAction(Intents.DatabaseLocked);
 | 
			
		||||
            RegisterReceiver(_intentReceiver, filter);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool GetIocFromViewIntent(Intent intent)
 | 
			
		||||
        {
 | 
			
		||||
            IOConnectionInfo ioc = new IOConnectionInfo();
 | 
			
		||||
 | 
			
		||||
            //started from "view" intent (e.g. from file browser)
 | 
			
		||||
            ioc.Path = intent.DataString;
 | 
			
		||||
 | 
			
		||||
            if (ioc.Path.StartsWith("file://"))
 | 
			
		||||
            {
 | 
			
		||||
                ioc.Path = URLDecoder.Decode(ioc.Path.Substring(7));
 | 
			
		||||
 | 
			
		||||
                if (ioc.Path.Length == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    // No file name
 | 
			
		||||
                    Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                File dbFile = new File(ioc.Path);
 | 
			
		||||
                if (!dbFile.Exists())
 | 
			
		||||
                {
 | 
			
		||||
                    // File does not exist
 | 
			
		||||
                    Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (!ioc.Path.StartsWith("content://"))
 | 
			
		||||
                {
 | 
			
		||||
                    Toast.MakeText(this, Resource.String.error_can_not_handle_uri, ToastLength.Long).Show();
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
                IoUtil.TryTakePersistablePermissions(this.ContentResolver, intent.Data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
                Intent launchIntent = new Intent(this, typeof(PasswordActivity));
 | 
			
		||||
                Util.PutIoConnectionToIntent(ioc, launchIntent);
 | 
			
		||||
                LaunchingOther = true;
 | 
			
		||||
                StartActivityForResult(launchIntent, ReqCodeOpenNewDb);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        IOConnectionInfo LoadIoc(string defaultFileName)
 | 
			
		||||
        {
 | 
			
		||||
            return App.Kp2a.FileDbHelper.CursorToIoc(App.Kp2a.FileDbHelper.FetchFileByName(defaultFileName));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        protected override void OnResume()
 | 
			
		||||
        {
 | 
			
		||||
            base.OnResume();
 | 
			
		||||
            if (!IsFinishing && !LaunchingPasswordActivity)
 | 
			
		||||
            if (!IsFinishing && !LaunchingOther)
 | 
			
		||||
            {
 | 
			
		||||
                if (App.Kp2a.OpenDatabases.Any() == false)
 | 
			
		||||
                {
 | 
			
		||||
@@ -188,13 +271,6 @@ namespace keepass2android
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (_loadAnotherDatabase)
 | 
			
		||||
                {
 | 
			
		||||
                    StartFileSelect();
 | 
			
		||||
                    _loadAnotherDatabase = false;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                //database loaded
 | 
			
		||||
                if (App.Kp2a.QuickLocked)
 | 
			
		||||
                {
 | 
			
		||||
@@ -208,6 +284,7 @@ namespace keepass2android
 | 
			
		||||
                //database(s) unlocked
 | 
			
		||||
                if (App.Kp2a.OpenDatabases.Count() == 1)
 | 
			
		||||
                {
 | 
			
		||||
                    LaunchingOther = true;
 | 
			
		||||
                    AppTask.LaunchFirstGroupActivity(this);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
@@ -223,21 +300,23 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
        protected override void OnPause()
 | 
			
		||||
        {
 | 
			
		||||
            LaunchingPasswordActivity = false;
 | 
			
		||||
            LaunchingOther = false;
 | 
			
		||||
            base.OnPause();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void StartFileSelect()
 | 
			
		||||
        private void StartFileSelect(bool noForwardToPassword = false)
 | 
			
		||||
        {
 | 
			
		||||
            Intent intent = new Intent(this, typeof(FileSelectActivity));
 | 
			
		||||
            AppTask.ToIntent(intent);
 | 
			
		||||
            intent.AddFlags(ActivityFlags.ForwardResult);
 | 
			
		||||
            StartActivity(intent);
 | 
			
		||||
            intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, noForwardToPassword);
 | 
			
		||||
            LaunchingOther = true;
 | 
			
		||||
            StartActivityForResult(intent, ReqCodeOpenNewDb);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal AppTask AppTask;
 | 
			
		||||
        private bool _loadAnotherDatabase;
 | 
			
		||||
        private OpenDatabaseAdapter _adapter;
 | 
			
		||||
        private MyBroadcastReceiver _intentReceiver;
 | 
			
		||||
 | 
			
		||||
        public override void OnBackPressed()
 | 
			
		||||
        {
 | 
			
		||||
@@ -261,6 +340,40 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
            AppTask.TryGetFromActivityResult(data, ref AppTask);
 | 
			
		||||
 | 
			
		||||
            if (requestCode == ReqCodeOpenNewDb)
 | 
			
		||||
            {
 | 
			
		||||
                switch ((int)resultCode)
 | 
			
		||||
                {
 | 
			
		||||
                    case (int)Result.Ok:
 | 
			
		||||
 | 
			
		||||
                        string iocString = data?.GetStringExtra("ioc");
 | 
			
		||||
                        IOConnectionInfo ioc = IOConnectionInfo.UnserializeFromString(iocString);
 | 
			
		||||
                        if (App.Kp2a.TrySelectCurrentDb(ioc))
 | 
			
		||||
                        {
 | 
			
		||||
                            LaunchingOther = true;
 | 
			
		||||
                            AppTask.CanActivateSearchViewOnStart = true;
 | 
			
		||||
                            AppTask.LaunchFirstGroupActivity(this);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                    case PasswordActivity.ResultSelectOtherFile:
 | 
			
		||||
                        StartFileSelect(true);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case (int)Result.Canceled:
 | 
			
		||||
                        if (App.Kp2a.OpenDatabases.Any() == false)
 | 
			
		||||
                        {
 | 
			
		||||
                            //don't open fileselect/password activity again
 | 
			
		||||
                            OnBackPressed();
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch (resultCode)
 | 
			
		||||
            {
 | 
			
		||||
                case KeePass.ExitNormal: // Returned to this screen using the Back key
 | 
			
		||||
@@ -297,7 +410,7 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
                    break;
 | 
			
		||||
                case KeePass.ExitLoadAnotherDb:
 | 
			
		||||
                    _loadAnotherDatabase = true;
 | 
			
		||||
                    StartFileSelect(true);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        
 | 
			
		||||
@@ -305,10 +418,39 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
        private void LaunchPasswordActivityForReload(IOConnectionInfo ioc, CompositeKey compositeKey)
 | 
			
		||||
        {
 | 
			
		||||
            LaunchingPasswordActivity = true;
 | 
			
		||||
            PasswordActivity.Launch(this, ioc, AppTask, compositeKey);
 | 
			
		||||
            LaunchingOther = true;
 | 
			
		||||
            PasswordActivity.Launch(this, ioc, compositeKey, new ActivityLaunchModeRequestCode(ReqCodeOpenNewDb));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool LaunchingPasswordActivity { get; set; }
 | 
			
		||||
        public bool LaunchingOther { get; set; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private class MyBroadcastReceiver : BroadcastReceiver
 | 
			
		||||
        {
 | 
			
		||||
            readonly SelectCurrentDbActivity _activity;
 | 
			
		||||
            public MyBroadcastReceiver(SelectCurrentDbActivity activity)
 | 
			
		||||
            {
 | 
			
		||||
                _activity = activity;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public override void OnReceive(Context context, Intent intent)
 | 
			
		||||
            {
 | 
			
		||||
                switch (intent.Action)
 | 
			
		||||
                {
 | 
			
		||||
                    case Intents.DatabaseLocked:
 | 
			
		||||
                        _activity.OnLockDatabase();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case Intent.ActionScreenOff:
 | 
			
		||||
                        App.Kp2a.OnScreenOff();
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnLockDatabase()
 | 
			
		||||
        {
 | 
			
		||||
            //app tasks are assumed to be finished/cancelled when the database is locked
 | 
			
		||||
            AppTask = new NullTask();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -56,11 +56,11 @@ namespace keepass2android
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static void Launch(Activity act, SearchUrlTask task)
 | 
			
		||||
		public static void Launch(Activity act, SearchUrlTask task, ActivityLaunchMode launchMode)
 | 
			
		||||
		{
 | 
			
		||||
			Intent i = new Intent(act, typeof(ShareUrlResults));
 | 
			
		||||
			task.ToIntent(i);
 | 
			
		||||
			act.StartActivityForResult(i, 0);
 | 
			
		||||
		    launchMode.Launch(act, i);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -171,7 +171,8 @@ namespace keepass2android
 | 
			
		||||
		        newTask.ShowUserNotifications = currentSelectTask.ShowUserNotifications;
 | 
			
		||||
            
 | 
			
		||||
            selectOtherEntry.Click += (sender, e) => {
 | 
			
		||||
				GroupActivity.Launch (this, newTask);
 | 
			
		||||
				GroupActivity.Launch (this, newTask, new ActivityLaunchModeRequestCode(0));
 | 
			
		||||
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
@@ -182,7 +183,7 @@ namespace keepass2android
 | 
			
		||||
				createUrlEntry.Visibility = ViewStates.Visible;
 | 
			
		||||
				createUrlEntry.Click += (sender, e) =>
 | 
			
		||||
				{
 | 
			
		||||
					GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = url, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? true });
 | 
			
		||||
					GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = url, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? true }, new ActivityLaunchModeRequestCode(0));
 | 
			
		||||
					Toast.MakeText(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[] { GetString(Resource.String.add_entry) }), ToastLength.Long).Show();
 | 
			
		||||
				};
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -500,14 +500,10 @@ namespace keepass2android
 | 
			
		||||
			return Application.Context.Resources.GetDrawable((int)field.GetValue(null));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
 | 
			
		||||
			EventHandler<DialogClickEventArgs> yesHandler,
 | 
			
		||||
			EventHandler<DialogClickEventArgs> noHandler,
 | 
			
		||||
			EventHandler<DialogClickEventArgs> cancelHandler,
 | 
			
		||||
			Context ctx)
 | 
			
		||||
		public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey, EventHandler<DialogClickEventArgs> yesHandler, EventHandler<DialogClickEventArgs> noHandler, EventHandler<DialogClickEventArgs> cancelHandler, Context ctx, string messageSuffix)
 | 
			
		||||
		{
 | 
			
		||||
			AskYesNoCancel(titleKey, messageKey, UiStringKey.yes, UiStringKey.no,
 | 
			
		||||
				yesHandler, noHandler, cancelHandler, ctx);
 | 
			
		||||
				yesHandler, noHandler, cancelHandler, ctx, messageSuffix);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
 | 
			
		||||
@@ -515,9 +511,9 @@ namespace keepass2android
 | 
			
		||||
			EventHandler<DialogClickEventArgs> yesHandler,
 | 
			
		||||
			EventHandler<DialogClickEventArgs> noHandler,
 | 
			
		||||
			EventHandler<DialogClickEventArgs> cancelHandler,
 | 
			
		||||
			Context ctx)
 | 
			
		||||
			Context ctx, string messageSuffix = "")
 | 
			
		||||
		{
 | 
			
		||||
			AskYesNoCancel(titleKey, messageKey, yesString, noString, yesHandler, noHandler, cancelHandler, null, ctx);
 | 
			
		||||
			AskYesNoCancel(titleKey, messageKey, yesString, noString, yesHandler, noHandler, cancelHandler, null, ctx, messageSuffix);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
 | 
			
		||||
@@ -526,7 +522,7 @@ namespace keepass2android
 | 
			
		||||
            EventHandler<DialogClickEventArgs> noHandler,
 | 
			
		||||
            EventHandler<DialogClickEventArgs> cancelHandler,
 | 
			
		||||
			EventHandler dismissHandler,
 | 
			
		||||
            Context ctx)
 | 
			
		||||
            Context ctx, string messageSuffix = "")
 | 
			
		||||
        {
 | 
			
		||||
	        Handler handler = new Handler(Looper.MainLooper);
 | 
			
		||||
			handler.Post(() =>
 | 
			
		||||
@@ -534,7 +530,7 @@ namespace keepass2android
 | 
			
		||||
					AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
 | 
			
		||||
					builder.SetTitle(GetResourceString(titleKey));
 | 
			
		||||
 | 
			
		||||
					builder.SetMessage(GetResourceString(messageKey));
 | 
			
		||||
					builder.SetMessage(GetResourceString(messageKey)+(messageSuffix != "" ? " " + messageSuffix: ""));
 | 
			
		||||
 | 
			
		||||
					string yesText = GetResourceString(yesString);
 | 
			
		||||
					builder.SetPositiveButton(yesText, yesHandler);
 | 
			
		||||
@@ -787,6 +783,7 @@ namespace keepass2android
 | 
			
		||||
		}
 | 
			
		||||
	    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	    public class CertificateErrorHandlerImpl : Java.Lang.Object, Keepass2android.Javafilestorage.ICertificateErrorHandler
 | 
			
		||||
		{
 | 
			
		||||
			private readonly Kp2aApp _app;
 | 
			
		||||
@@ -1022,9 +1019,9 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
	    public PwGroup FindGroup(PwUuid uuid)
 | 
			
		||||
	    {
 | 
			
		||||
	        PwGroup result;
 | 
			
		||||
	        foreach (Database db in OpenDatabases)
 | 
			
		||||
	        {
 | 
			
		||||
	            PwGroup result;
 | 
			
		||||
	            if (db.Groups.TryGetValue(uuid, out result))
 | 
			
		||||
	                return result;
 | 
			
		||||
	        }
 | 
			
		||||
@@ -1044,6 +1041,18 @@ namespace keepass2android
 | 
			
		||||
            }
 | 
			
		||||
	        return null;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    public bool TrySelectCurrentDb(IOConnectionInfo ioConnection)
 | 
			
		||||
	    {
 | 
			
		||||
	        var matchingOpenDb = App.Kp2a.OpenDatabases.FirstOrDefault(db => db.Ioc.IsSameFileAs(ioConnection));
 | 
			
		||||
	        if (matchingOpenDb != null)
 | 
			
		||||
	        {
 | 
			
		||||
	            CurrentDb = matchingOpenDb;
 | 
			
		||||
	            return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
	        
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -187,7 +187,7 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
		public virtual void LaunchFirstGroupActivity(Activity act)
 | 
			
		||||
		{
 | 
			
		||||
			GroupActivity.Launch(act, this);
 | 
			
		||||
			GroupActivity.Launch(act, this, new ActivityLaunchModeRequestCode(0));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public virtual void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry)
 | 
			
		||||
@@ -403,11 +403,11 @@ namespace keepass2android
 | 
			
		||||
		{
 | 
			
		||||
			if (String.IsNullOrEmpty(UrlToSearchFor))
 | 
			
		||||
			{
 | 
			
		||||
				GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications =  ShowUserNotifications});
 | 
			
		||||
				GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications =  ShowUserNotifications}, new ActivityLaunchModeRequestCode(0));
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				ShareUrlResults.Launch(act, this);
 | 
			
		||||
				ShareUrlResults.Launch(act, this, new ActivityLaunchModeRequestCode(0));
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
@@ -792,7 +792,6 @@ namespace keepass2android
 | 
			
		||||
		#endif
 | 
			
		||||
 | 
			
		||||
		private LinkedList<string> _groupUuid;
 | 
			
		||||
	    private readonly Database _db;
 | 
			
		||||
	    protected AppTask TaskToBeLaunchedAfterNavigation;
 | 
			
		||||
 | 
			
		||||
		protected String FullGroupName {
 | 
			
		||||
@@ -817,8 +816,7 @@ namespace keepass2android
 | 
			
		||||
		/// <param name="groups">Groups.</param>
 | 
			
		||||
		/// <param name="taskToBeLaunchedAfterNavigation">Task to be launched after navigation.</param>
 | 
			
		||||
		/// <param name="toastEnable">If set to <c>true</c>, toast will be displayed after navigation.</param>
 | 
			
		||||
		protected NavigateAndLaunchTask(Database db, PwGroup groups, AppTask taskToBeLaunchedAfterNavigation, bool toastEnable = false) {
 | 
			
		||||
		    _db = db;
 | 
			
		||||
		protected NavigateAndLaunchTask(PwGroup groups, AppTask taskToBeLaunchedAfterNavigation, bool toastEnable = false) {
 | 
			
		||||
		    TaskToBeLaunchedAfterNavigation = taskToBeLaunchedAfterNavigation;
 | 
			
		||||
			PopulateGroups (groups);
 | 
			
		||||
			ToastEnable = toastEnable;
 | 
			
		||||
@@ -935,7 +933,7 @@ namespace keepass2android
 | 
			
		||||
				groupBaseActivity.StartTask (TaskToBeLaunchedAfterNavigation);
 | 
			
		||||
				return;
 | 
			
		||||
 | 
			
		||||
			} else if (_groupUuid.Contains(groupBaseActivity.UuidGroup)) { // Need to go up in groups tree
 | 
			
		||||
			} else if (_groupUuid.Contains(groupBaseActivity.UuidGroup)) { // Need to down up in groups tree
 | 
			
		||||
 | 
			
		||||
				// Get next Group Uuid
 | 
			
		||||
				var linkedListNode = _groupUuid.Find(groupBaseActivity.UuidGroup);
 | 
			
		||||
@@ -947,15 +945,26 @@ namespace keepass2android
 | 
			
		||||
					PwUuid nextGroupPwUuid = new PwUuid (MemUtil.HexStringToByteArray (nextGroupUuid));
 | 
			
		||||
 | 
			
		||||
					// Create Group Activity
 | 
			
		||||
					PwGroup nextGroup = _db.Groups[nextGroupPwUuid];
 | 
			
		||||
					GroupActivity.Launch (groupBaseActivity, nextGroup, this);
 | 
			
		||||
					PwGroup nextGroup = App.Kp2a.CurrentDb.Groups[nextGroupPwUuid];
 | 
			
		||||
					GroupActivity.Launch (groupBaseActivity, nextGroup, this, new ActivityLaunchModeRequestCode(0));
 | 
			
		||||
				}
 | 
			
		||||
				return;
 | 
			
		||||
 | 
			
		||||
			} else { // Need to go down in groups tree
 | 
			
		||||
			} else { // Need to go up in groups tree
 | 
			
		||||
			    var targetUuid = new PwUuid(MemUtil.HexStringToByteArray(_groupUuid.Last.Value));
 | 
			
		||||
			    var targetDb = App.Kp2a.FindDatabaseForGroupId(targetUuid);
 | 
			
		||||
			    if (App.Kp2a.CurrentDb != targetDb)
 | 
			
		||||
			    {
 | 
			
		||||
			        App.Kp2a.CurrentDb = targetDb;
 | 
			
		||||
                    GroupActivity.Launch(groupBaseActivity,targetDb.Root,this,new ActivityLaunchModeForward());
 | 
			
		||||
			    }
 | 
			
		||||
			    else
 | 
			
		||||
			    {
 | 
			
		||||
			        SetActivityResult(groupBaseActivity, KeePass.ExitNormal);
 | 
			
		||||
                }
 | 
			
		||||
			    groupBaseActivity.Finish();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            } 
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
@@ -972,9 +981,14 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
	public class NavigateToFolder: NavigateAndLaunchTask {
 | 
			
		||||
 | 
			
		||||
	    public NavigateToFolder()
 | 
			
		||||
	    {
 | 
			
		||||
	        
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public NavigateToFolder(Database db, PwGroup groups, bool toastEnable = false)
 | 
			
		||||
			: base(db, groups, new NullTask(), toastEnable) 
 | 
			
		||||
			: base(groups, new NullTask(), toastEnable) 
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -983,8 +997,13 @@ namespace keepass2android
 | 
			
		||||
	public class NavigateToFolderAndLaunchMoveElementTask: NavigateAndLaunchTask {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	    public NavigateToFolderAndLaunchMoveElementTask()
 | 
			
		||||
	    {
 | 
			
		||||
	        
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
        public NavigateToFolderAndLaunchMoveElementTask(Database db, PwGroup groups, List<PwUuid> uuids, bool toastEnable = false)
 | 
			
		||||
			:base(db, groups, new MoveElementsTask() { Uuids = uuids }, toastEnable) {
 | 
			
		||||
			:base(groups, new MoveElementsTask() { Uuids = uuids }, toastEnable) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Setup(Bundle b) {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,12 +44,6 @@ namespace keepass2android
 | 
			
		||||
	           ConfigurationChanges=ConfigChanges.Orientation|
 | 
			
		||||
	           ConfigChanges.KeyboardHidden,
 | 
			
		||||
               Theme = "@style/MyTheme_Blue")]
 | 
			
		||||
	[IntentFilter(new [] { Intent.ActionSend }, 
 | 
			
		||||
		Label = "@string/kp2a_findUrl", 
 | 
			
		||||
		Categories=new[]{Intent.CategoryDefault}, 
 | 
			
		||||
		DataMimeType="text/plain")]
 | 
			
		||||
	[IntentFilter(new[] { Strings.ActionStartWithTask },
 | 
			
		||||
		Categories = new[] { Intent.CategoryDefault })]
 | 
			
		||||
	public class FileSelectActivity : AppCompatActivity
 | 
			
		||||
	{
 | 
			
		||||
		private readonly ActivityDesign _design;
 | 
			
		||||
@@ -72,7 +66,7 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
		private bool _recentMode;
 | 
			
		||||
		
 | 
			
		||||
		internal AppTask AppTask;
 | 
			
		||||
		
 | 
			
		||||
		private const int RequestCodeSelectIoc = 456;
 | 
			
		||||
	    private const int RequestCodeEditIoc = 457;
 | 
			
		||||
 | 
			
		||||
@@ -85,24 +79,7 @@ namespace keepass2android
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			Kp2aLog.Log("FileSelect.OnCreate");
 | 
			
		||||
			Kp2aLog.Log("FileSelect:apptask="+Intent.GetStringExtra("KP2A_APPTASK"));
 | 
			
		||||
			
 | 
			
		||||
			if (Intent.Action == Intent.ActionSend)
 | 
			
		||||
			{
 | 
			
		||||
				AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				//see PasswordActivity for an explanation
 | 
			
		||||
				if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
 | 
			
		||||
				{
 | 
			
		||||
					AppTask = new NullTask();
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			_dbHelper = App.Kp2a.FileDbHelper;
 | 
			
		||||
@@ -150,7 +127,7 @@ namespace keepass2android
 | 
			
		||||
				{
 | 
			
		||||
					//ShowFilenameDialog(false, true, true, Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path), "", Intents.RequestCodeFileBrowseForCreate)
 | 
			
		||||
					Intent i = new Intent(this, typeof (CreateDatabaseActivity));
 | 
			
		||||
					this.AppTask.ToIntent(i);
 | 
			
		||||
					
 | 
			
		||||
				    i.SetFlags(ActivityFlags.ForwardResult);
 | 
			
		||||
					StartActivity(i);
 | 
			
		||||
				    Finish();
 | 
			
		||||
@@ -177,7 +154,6 @@ namespace keepass2android
 | 
			
		||||
			
 | 
			
		||||
			if (savedInstanceState != null)
 | 
			
		||||
			{
 | 
			
		||||
				AppTask = AppTask.CreateFromBundle(savedInstanceState);
 | 
			
		||||
				_recentMode = savedInstanceState.GetBoolean(BundleKeyRecentMode, _recentMode);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -202,7 +178,7 @@ namespace keepass2android
 | 
			
		||||
		protected override void OnSaveInstanceState(Bundle outState)
 | 
			
		||||
		{
 | 
			
		||||
			base.OnSaveInstanceState(outState);
 | 
			
		||||
			AppTask.ToBundle(outState);
 | 
			
		||||
		
 | 
			
		||||
			outState.PutBoolean(BundleKeyRecentMode, _recentMode);
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
@@ -366,7 +342,7 @@ namespace keepass2android
 | 
			
		||||
			{
 | 
			
		||||
				try
 | 
			
		||||
				{
 | 
			
		||||
					PasswordActivity.Launch(this, ioc, AppTask);
 | 
			
		||||
					PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward());
 | 
			
		||||
					Finish();
 | 
			
		||||
				} catch (Java.IO.FileNotFoundException)
 | 
			
		||||
				{
 | 
			
		||||
@@ -379,7 +355,7 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
		private void AfterQueryCredentials(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			PasswordActivity.Launch(this, ioc, AppTask);
 | 
			
		||||
			PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward());
 | 
			
		||||
			Finish();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -399,11 +375,6 @@ namespace keepass2android
 | 
			
		||||
		{
 | 
			
		||||
			base.OnActivityResult(requestCode, resultCode, data);
 | 
			
		||||
 | 
			
		||||
			//update app task.
 | 
			
		||||
			//this is important even if we're about to close, because then we should get a NullTask here 
 | 
			
		||||
			//in order not to do the same task next time again!
 | 
			
		||||
			AppTask.TryGetFromActivityResult(data, ref AppTask);
 | 
			
		||||
 | 
			
		||||
			if (resultCode == KeePass.ExitCloseAfterTaskComplete)
 | 
			
		||||
			{
 | 
			
		||||
				//no need to set the result ExitCloseAfterTaskComplete here, there's no parent Activity on the stack
 | 
			
		||||
 
 | 
			
		||||
@@ -173,6 +173,7 @@
 | 
			
		||||
    </Reference>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="ActivityLaunchMode.cs" />
 | 
			
		||||
    <Compile Include="ChallengeXCKey.cs" />
 | 
			
		||||
    <Compile Include="EntryActivityClasses\ViewImagePopupItem.cs" />
 | 
			
		||||
    <Compile Include="FileSaveProcessManager.cs" />
 | 
			
		||||
 
 | 
			
		||||
@@ -952,7 +952,7 @@ namespace keepass2android
 | 
			
		||||
                        {
 | 
			
		||||
                            var key = App.Kp2a.CurrentDb.KpDatabase.MasterKey;
 | 
			
		||||
                            App.Kp2a.CloseDatabase(App.Kp2a.CurrentDb);
 | 
			
		||||
                            PasswordActivity.Launch(Activity, newIoc, new NullTask(), key);
 | 
			
		||||
                            PasswordActivity.Launch(Activity, newIoc, key, new ActivityLaunchModeSimple());
 | 
			
		||||
 | 
			
		||||
                        });
 | 
			
		||||
                        builder.Show();
 | 
			
		||||
 
 | 
			
		||||
@@ -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/>.
 | 
			
		||||
  */
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Android.Graphics;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using Android.Runtime;
 | 
			
		||||
@@ -165,6 +166,10 @@ namespace keepass2android.view
 | 
			
		||||
 | 
			
		||||
			else {
 | 
			
		||||
				String groupDetail = pw.ParentGroup.GetFullPath();
 | 
			
		||||
			    if (App.Kp2a.OpenDatabases.Count() > 1)
 | 
			
		||||
			    {
 | 
			
		||||
			        groupDetail += "(" + App.Kp2a.GetFileStorage(db.Ioc).GetDisplayName(db.Ioc) + ")";
 | 
			
		||||
			    }
 | 
			
		||||
 | 
			
		||||
				var strGroupDetail = new SpannableString (groupDetail);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -130,7 +130,7 @@ namespace keepass2android.view
 | 
			
		||||
		
 | 
			
		||||
		
 | 
			
		||||
		private void LaunchGroup() {
 | 
			
		||||
			GroupActivity.Launch(_groupBaseActivity, _pwGroup, _groupBaseActivity.AppTask);
 | 
			
		||||
			GroupActivity.Launch(_groupBaseActivity, _pwGroup, _groupBaseActivity.AppTask, new ActivityLaunchModeRequestCode(0));
 | 
			
		||||
			//_groupBaseActivity.OverridePendingTransition(Resource.Animation.anim_enter, Resource.Animation.anim_leave);
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user