allow opening several databases which contain elements with same IDs (required as KeepassHttp stores their settings in an entry with a fixed ID)
This commit is contained in:
		| @@ -65,9 +65,9 @@ | |||||||
|     <TransformFile Include="Transforms\EnumMethods.xml" /> |     <TransformFile Include="Transforms\EnumMethods.xml" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <EmbeddedJar Include="..\java\KP2AKdbLibrary\bin\kp2akdblibrary.jar"> |     <InputJar Include="..\java\KP2AKdbLibrary\bin\kp2akdblibrary.jar"> | ||||||
|       <Link>Jars\kp2akdblibrary.jar</Link> |       <Link>Jars\kp2akdblibrary.jar</Link> | ||||||
|     </EmbeddedJar> |     </InputJar> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" /> |   <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" /> | ||||||
|   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.  |   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.  | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								src/Kp2aBusinessLogic/ElementAndDatabaseId.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/Kp2aBusinessLogic/ElementAndDatabaseId.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | 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; | ||||||
|  | using keepass2android.Io; | ||||||
|  | using KeePassLib; | ||||||
|  | using KeePassLib.Interfaces; | ||||||
|  | using KeePassLib.Utility; | ||||||
|  |  | ||||||
|  | namespace keepass2android | ||||||
|  | { | ||||||
|  |     public class ElementAndDatabaseId | ||||||
|  |     { | ||||||
|  |         private const char Separator = '+'; | ||||||
|  |  | ||||||
|  |         public ElementAndDatabaseId(Database db, IStructureItem element) | ||||||
|  |         { | ||||||
|  |             DatabaseId = db.IocAsHexString(); | ||||||
|  |             ElementIdString = element.Uuid.ToHexString(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public ElementAndDatabaseId(string fullId) | ||||||
|  |         { | ||||||
|  |             string[] parts = fullId.Split(Separator); | ||||||
|  |             if (parts.Length != 2) | ||||||
|  |                 throw new Exception("Invalid full id " + fullId); | ||||||
|  |             DatabaseId = parts[0]; | ||||||
|  |             ElementIdString = parts[1]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public string DatabaseId { get; set; } | ||||||
|  |         public string ElementIdString { get; set; } | ||||||
|  |         public PwUuid ElementId {  get {  return new PwUuid(MemUtil.HexStringToByteArray(ElementIdString));} } | ||||||
|  |  | ||||||
|  |         public string FullId | ||||||
|  |         { | ||||||
|  |             get { return DatabaseId + Separator + ElementIdString; } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -10,6 +10,7 @@ using KeePassLib; | |||||||
| using KeePassLib.Keys; | using KeePassLib.Keys; | ||||||
| using KeePassLib.Serialization; | using KeePassLib.Serialization; | ||||||
| using keepass2android.Io; | using keepass2android.Io; | ||||||
|  | using KeePassLib.Interfaces; | ||||||
| #if !NoNet | #if !NoNet | ||||||
| using Keepass2android.Javafilestorage; | using Keepass2android.Javafilestorage; | ||||||
| #endif  | #endif  | ||||||
| @@ -58,9 +59,8 @@ namespace keepass2android | |||||||
| 	    IEnumerable<Database> OpenDatabases { get; } | 	    IEnumerable<Database> OpenDatabases { get; } | ||||||
| 	    void CloseDatabase(Database db); | 	    void CloseDatabase(Database db); | ||||||
|  |  | ||||||
|         Database FindDatabaseForGroupId(PwUuid groupKey); | 	    Database FindDatabaseForElement(IStructureItem element); | ||||||
| 	    Database FindDatabaseForEntryId(PwUuid entryId); |          | ||||||
|  |  | ||||||
|         /// <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> | ||||||
| @@ -129,5 +129,6 @@ namespace keepass2android | |||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  | 	     | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -90,7 +90,6 @@ | |||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Compile Include="database\CheckDatabaseForChanges.cs" /> |     <Compile Include="database\CheckDatabaseForChanges.cs" /> | ||||||
|     <Compile Include="database\edit\AddTemplateEntries.cs" /> |     <Compile Include="database\edit\AddTemplateEntries.cs" /> | ||||||
|     <Compile Include="database\edit\ChangeTemplateIds.cs" /> |  | ||||||
|     <Compile Include="database\edit\CopyEntry.cs" /> |     <Compile Include="database\edit\CopyEntry.cs" /> | ||||||
|     <Compile Include="database\edit\DeleteMultipleItemsFromOneDatabase.cs" /> |     <Compile Include="database\edit\DeleteMultipleItemsFromOneDatabase.cs" /> | ||||||
|     <Compile Include="database\edit\EditGroup.cs" /> |     <Compile Include="database\edit\EditGroup.cs" /> | ||||||
| @@ -104,6 +103,7 @@ | |||||||
|     <Compile Include="DataExchange\Formats\KeePassKdb2x.cs" /> |     <Compile Include="DataExchange\Formats\KeePassKdb2x.cs" /> | ||||||
|     <Compile Include="DataExchange\Formats\KeePassXml2x.cs" /> |     <Compile Include="DataExchange\Formats\KeePassXml2x.cs" /> | ||||||
|     <Compile Include="DataExchange\PwExportInfo.cs" /> |     <Compile Include="DataExchange\PwExportInfo.cs" /> | ||||||
|  |     <Compile Include="ElementAndDatabaseId.cs" /> | ||||||
|     <Compile Include="Io\AndroidContentStorage.cs" /> |     <Compile Include="Io\AndroidContentStorage.cs" /> | ||||||
|     <Compile Include="Io\BuiltInFileStorage.cs" /> |     <Compile Include="Io\BuiltInFileStorage.cs" /> | ||||||
|     <Compile Include="Io\CachingFileStorage.cs" /> |     <Compile Include="Io\CachingFileStorage.cs" /> | ||||||
|   | |||||||
| @@ -103,7 +103,7 @@ namespace keepass2android | |||||||
| 			PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch) {IsVirtual = true}; | 			PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch) {IsVirtual = true}; | ||||||
| 			if (String.IsNullOrWhiteSpace(host)) | 			if (String.IsNullOrWhiteSpace(host)) | ||||||
| 				return pgResults; | 				return pgResults; | ||||||
| 			foreach (PwEntry entry in database.Entries.Values) | 			foreach (PwEntry entry in database.EntriesById.Values) | ||||||
| 			{ | 			{ | ||||||
| 				string otherUrl = entry.Strings.ReadSafe(PwDefs.UrlField); | 				string otherUrl = entry.Strings.ReadSafe(PwDefs.UrlField); | ||||||
| 				otherUrl = SprEngine.Compile(otherUrl, new SprContext(entry, database.KpDatabase, SprCompileFlags.References)); | 				otherUrl = SprEngine.Compile(otherUrl, new SprContext(entry, database.KpDatabase, SprCompileFlags.References)); | ||||||
|   | |||||||
| @@ -87,9 +87,6 @@ namespace keepass2android | |||||||
| 		ReadOnlyReason_ReadOnlyFlag, | 		ReadOnlyReason_ReadOnlyFlag, | ||||||
| 		ReadOnlyReason_ReadOnlyKitKat, | 		ReadOnlyReason_ReadOnlyKitKat, | ||||||
|         ReadOnlyReason_LocalBackup, |         ReadOnlyReason_LocalBackup, | ||||||
|         UpdatingTemplateIds, |  | ||||||
|         ChangleLegacyTemplateIds_Message, |  | ||||||
|         ChangleLegacyTemplateIds_Title, |  | ||||||
|         Ok, |         Ok, | ||||||
|         cancel |         cancel | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ using KeePassLib; | |||||||
| using KeePassLib.Keys; | using KeePassLib.Keys; | ||||||
| using KeePassLib.Serialization; | using KeePassLib.Serialization; | ||||||
| using keepass2android.Io; | using keepass2android.Io; | ||||||
|  | using KeePassLib.Interfaces; | ||||||
| using KeePassLib.Utility; | using KeePassLib.Utility; | ||||||
| using Exception = System.Exception; | using Exception = System.Exception; | ||||||
| using String = System.String; | using String = System.String; | ||||||
| @@ -33,18 +34,20 @@ using String = System.String; | |||||||
| namespace keepass2android | namespace keepass2android | ||||||
| { | { | ||||||
|  |  | ||||||
| 	public class Database { | 	public class Database | ||||||
| 		 | 	{ | ||||||
|  | 	    public HashSet<IStructureItem> Elements = new HashSet<IStructureItem>(); | ||||||
| 		public Dictionary<PwUuid, PwGroup> Groups = new Dictionary<PwUuid, PwGroup>(new PwUuidEqualityComparer()); | 		public Dictionary<PwUuid, PwGroup> GroupsById = new Dictionary<PwUuid, PwGroup>(new PwUuidEqualityComparer()); | ||||||
| 		public Dictionary<PwUuid, PwEntry> Entries = new Dictionary<PwUuid, PwEntry>(new PwUuidEqualityComparer()); | 		public Dictionary<PwUuid, PwEntry> EntriesById = new Dictionary<PwUuid, PwEntry>(new PwUuidEqualityComparer()); | ||||||
| 		public PwGroup Root; | 		public PwGroup Root; | ||||||
| 		public PwDatabase KpDatabase; | 		public PwDatabase KpDatabase; | ||||||
| 		public IOConnectionInfo Ioc  | 		public IOConnectionInfo Ioc  | ||||||
| 		{ | 		{ | ||||||
| 			get | 			get | ||||||
| 			{ | 			{ | ||||||
| 				return KpDatabase?.IOConnectionInfo; |                  | ||||||
|  |                 return KpDatabase?.IOConnectionInfo; | ||||||
|  |                  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -203,16 +206,18 @@ namespace keepass2android | |||||||
| 			{ | 			{ | ||||||
| 				if (checkForDuplicateUuids) | 				if (checkForDuplicateUuids) | ||||||
| 				{ | 				{ | ||||||
| 					if (Entries.ContainsKey(e.Uuid)) | 					if (EntriesById.ContainsKey(e.Uuid)) | ||||||
| 					{ | 					{ | ||||||
| 						throw new DuplicateUuidsException("Same UUID for entries '"+Entries[e.Uuid].Strings.ReadSafe(PwDefs.TitleField)+"' and '"+e.Strings.ReadSafe(PwDefs.TitleField)+"'."); | 						throw new DuplicateUuidsException("Same UUID for entries '"+EntriesById[e.Uuid].Strings.ReadSafe(PwDefs.TitleField)+"' and '"+e.Strings.ReadSafe(PwDefs.TitleField)+"'."); | ||||||
| 					} | 					} | ||||||
| 					 | 					 | ||||||
| 				} | 				} | ||||||
| 				Entries [e.Uuid] = e; | 				EntriesById [e.Uuid] = e; | ||||||
|  | 			    Elements.Add(e); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 		    Groups[currentGroup.Uuid] = currentGroup; | 		    GroupsById[currentGroup.Uuid] = currentGroup; | ||||||
|  | 		    Elements.Add(currentGroup); | ||||||
| 			foreach (PwGroup g in childGroups)  | 			foreach (PwGroup g in childGroups)  | ||||||
| 			{ | 			{ | ||||||
| 				if (checkForDuplicateUuids) | 				if (checkForDuplicateUuids) | ||||||
| @@ -235,8 +240,9 @@ namespace keepass2android | |||||||
|  |  | ||||||
| 	    public void UpdateGlobals() | 	    public void UpdateGlobals() | ||||||
| 	    { | 	    { | ||||||
| 	        Entries.Clear(); | 	        EntriesById.Clear(); | ||||||
| 	        Groups.Clear(); | 	        GroupsById.Clear(); | ||||||
|  | 	        Elements.Clear(); | ||||||
|             PopulateGlobals(Root); |             PopulateGlobals(Root); | ||||||
| 	    } | 	    } | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -73,6 +73,8 @@ namespace keepass2android | |||||||
| 							}), _app.CurrentDb, false, remoteData); | 							}), _app.CurrentDb, false, remoteData); | ||||||
| 						_saveDb.Run(); | 						_saveDb.Run(); | ||||||
|  |  | ||||||
|  |                         _app.CurrentDb.UpdateGlobals(); | ||||||
|  |  | ||||||
| 						_app.MarkAllGroupsAsDirty(); | 						_app.MarkAllGroupsAsDirty(); | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
|   | |||||||
| @@ -87,8 +87,9 @@ namespace keepass2android | |||||||
| 					_app.DirtyGroups.Add(parent); | 					_app.DirtyGroups.Add(parent); | ||||||
| 					 | 					 | ||||||
| 					// Add entry to global | 					// Add entry to global | ||||||
| 					_db.Entries[_entry.Uuid] = _entry; | 					_db.EntriesById[_entry.Uuid] = _entry; | ||||||
| 					 | 				    _db.Elements.Add(_entry); | ||||||
|  |  | ||||||
| 				} else | 				} else | ||||||
| 				{ | 				{ | ||||||
| 					StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); | 					StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); | ||||||
|   | |||||||
| @@ -70,9 +70,11 @@ namespace keepass2android | |||||||
| 				Group.CustomIconUuid = _groupCustomIconId; | 				Group.CustomIconUuid = _groupCustomIconId; | ||||||
| 			} | 			} | ||||||
| 			Parent.AddGroup(Group, true); | 			Parent.AddGroup(Group, true); | ||||||
|  | 		    _app.CurrentDb.GroupsById[Group.Uuid] = Group; | ||||||
|  | 		    _app.CurrentDb.Elements.Add(Group); | ||||||
|  |  | ||||||
| 			// Commit to disk |             // Commit to disk | ||||||
| 			SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, DontSave); |             SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, DontSave); | ||||||
| 			save.SetStatusLogger(StatusLogger); | 			save.SetStatusLogger(StatusLogger); | ||||||
| 			save.Run(); | 			save.Run(); | ||||||
| 		} | 		} | ||||||
| @@ -92,10 +94,12 @@ namespace keepass2android | |||||||
| 					_addGroup.App.DirtyGroups.Add(_addGroup.Parent); | 					_addGroup.App.DirtyGroups.Add(_addGroup.Parent); | ||||||
| 					 | 					 | ||||||
| 					// Add group to global list | 					// Add group to global list | ||||||
| 					_addGroup.Db.Groups[_addGroup.Group.Uuid] = _addGroup.Group; | 					_addGroup.Db.GroupsById[_addGroup.Group.Uuid] = _addGroup.Group; | ||||||
|  | 				    _addGroup.Db.Elements.Add(_addGroup.Group); | ||||||
| 				} else { | 				} else { | ||||||
| 					StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); | 					StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); | ||||||
| 					_addGroup.Parent.Groups.Remove(_addGroup.Group); | 					_addGroup.Parent.Groups.Remove(_addGroup.Group); | ||||||
|  |  | ||||||
| 				} | 				} | ||||||
| 				 | 				 | ||||||
| 				base.Run(); | 				base.Run(); | ||||||
|   | |||||||
| @@ -292,7 +292,7 @@ namespace keepass2android | |||||||
| 			{ | 			{ | ||||||
| 			    string hexId = t.Uuid.ToHexString(); | 			    string hexId = t.Uuid.ToHexString(); | ||||||
|                  |                  | ||||||
|                 return db.Entries.Any(kvp => kvp.Key.Equals(t.Uuid) || |                 return db.EntriesById.Any(kvp => kvp.Key.Equals(t.Uuid) || | ||||||
|                     kvp.Value.Strings.ReadSafe(TemplateIdStringKey) == hexId); |                     kvp.Value.Strings.ReadSafe(TemplateIdStringKey) == hexId); | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| @@ -327,7 +327,7 @@ namespace keepass2android | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			PwGroup templateGroup; | 			PwGroup templateGroup; | ||||||
| 			if (!_app.CurrentDb.Groups.TryGetValue(_app.CurrentDb.KpDatabase.EntryTemplatesGroup, out templateGroup)) | 			if (!_app.CurrentDb.GroupsById.TryGetValue(_app.CurrentDb.KpDatabase.EntryTemplatesGroup, out templateGroup)) | ||||||
| 			{ | 			{ | ||||||
| 				//create template group | 				//create template group | ||||||
| 				templateGroup = new PwGroup(true, true, _app.GetResourceString(UiStringKey.TemplateGroupName), PwIcon.Folder); | 				templateGroup = new PwGroup(true, true, _app.GetResourceString(UiStringKey.TemplateGroupName), PwIcon.Folder); | ||||||
| @@ -335,30 +335,31 @@ namespace keepass2android | |||||||
| 				_app.CurrentDb.KpDatabase.EntryTemplatesGroup = templateGroup.Uuid; | 				_app.CurrentDb.KpDatabase.EntryTemplatesGroup = templateGroup.Uuid; | ||||||
| 				_app.CurrentDb.KpDatabase.EntryTemplatesGroupChanged = DateTime.Now; | 				_app.CurrentDb.KpDatabase.EntryTemplatesGroupChanged = DateTime.Now; | ||||||
| 				_app.DirtyGroups.Add(_app.CurrentDb.KpDatabase.RootGroup); | 				_app.DirtyGroups.Add(_app.CurrentDb.KpDatabase.RootGroup); | ||||||
| 				_app.CurrentDb.Groups[templateGroup.Uuid] = templateGroup; | 				_app.CurrentDb.GroupsById[templateGroup.Uuid] = templateGroup; | ||||||
|  | 			    _app.CurrentDb.Elements.Add(templateGroup); | ||||||
|  |  | ||||||
| 			} | 			} | ||||||
| 			addedEntries = new List<PwEntry>(); | 			addedEntries = new List<PwEntry>(); | ||||||
|  |  | ||||||
| 			foreach (var template in TemplateEntries) | 			foreach (var template in TemplateEntries) | ||||||
| 			{ | 			{ | ||||||
| 				if (_app.CurrentDb.Entries.ContainsKey(template.Uuid)) | 				if (_app.CurrentDb.EntriesById.ContainsKey(template.Uuid)) | ||||||
| 					continue; | 					continue; | ||||||
| 				PwEntry entry = CreateEntry(template); | 				PwEntry entry = CreateEntry(template); | ||||||
| 				templateGroup.AddEntry(entry, true); | 				templateGroup.AddEntry(entry, true); | ||||||
| 				addedEntries.Add(entry); | 				addedEntries.Add(entry); | ||||||
| 				_app.CurrentDb.Entries[entry.Uuid] = entry; | 				_app.CurrentDb.EntriesById[entry.Uuid] = entry; | ||||||
| 			} | 			} | ||||||
| 			return templateGroup; | 			return templateGroup; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		private PwEntry CreateEntry(TemplateEntry template) | 		private PwEntry CreateEntry(TemplateEntry template) | ||||||
| 		{ | 		{ | ||||||
| 			PwEntry entry = new PwEntry(true, true); | 			PwEntry entry = new PwEntry(false, true); | ||||||
| 			 | 			entry.Uuid = template.Uuid; | ||||||
| 			entry.IconId = template.Icon; | 			entry.IconId = template.Icon; | ||||||
| 			entry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, _app.GetResourceString(template.Title))); | 			entry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, _app.GetResourceString(template.Title))); | ||||||
| 			entry.Strings.Set("_etm_template", new ProtectedString(false, "1")); | 			entry.Strings.Set("_etm_template", new ProtectedString(false, "1")); | ||||||
|             entry.Strings.Set(TemplateIdStringKey, new ProtectedString(false, template.Uuid.ToHexString())); |  | ||||||
| 			int position = 0; | 			int position = 0; | ||||||
| 			foreach (var field in template.Fields) | 			foreach (var field in template.Fields) | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -1,76 +0,0 @@ | |||||||
| 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; |  | ||||||
| using KeePassLib; |  | ||||||
| using KeePassLib.Security; |  | ||||||
|  |  | ||||||
| namespace keepass2android.database.edit |  | ||||||
| { |  | ||||||
|     public class ChangeTemplateIds: RunnableOnFinish |  | ||||||
|     { |  | ||||||
|         private readonly IKp2aApp _app; |  | ||||||
|         private readonly Database _db; |  | ||||||
|         private string _etmTemplateUuid { get { return "_etm_template_uuid"; } } |  | ||||||
|         public static string TemplateIdStringKey |  | ||||||
|         { |  | ||||||
|             get { return "KP2A_TemplateId"; } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public ChangeTemplateIds(Activity activeActivity, IKp2aApp app, Database db, OnFinish finish) : base(activeActivity, finish) |  | ||||||
|         { |  | ||||||
|             _app = app; |  | ||||||
|             _db = db; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public override void Run() |  | ||||||
|         { |  | ||||||
|             StatusLogger.UpdateMessage(UiStringKey.UpdatingTemplateIds); |  | ||||||
|             Dictionary<string, string> uuidMap = new Dictionary<string, string>(); |  | ||||||
|             foreach (var templateEntry in AddTemplateEntries.TemplateEntries) |  | ||||||
|             { |  | ||||||
|                 PwEntry entry; |  | ||||||
|                 if (_db.Entries.TryGetValue(templateEntry.Uuid, out entry)) |  | ||||||
|                 { |  | ||||||
|                     PwUuid oldUuid = entry.Uuid; |  | ||||||
|                     entry.Uuid = new PwUuid(true); |  | ||||||
|                     uuidMap[oldUuid.ToHexString()] = entry.Uuid.ToHexString(); |  | ||||||
|                     entry.Strings.Set(TemplateIdStringKey,new ProtectedString(false, oldUuid.ToHexString())); |  | ||||||
|                     _db.Entries.Remove(oldUuid); |  | ||||||
|                     _db.Entries[entry.Uuid] = entry; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             foreach (var entry in _db.Entries.Values) |  | ||||||
|             { |  | ||||||
|                 string templateUuid = entry.Strings.ReadSafe(_etmTemplateUuid); |  | ||||||
|                 if (templateUuid != null) |  | ||||||
|                 { |  | ||||||
|                     string newTemplateUuid; |  | ||||||
|                     if (uuidMap.TryGetValue(templateUuid, out newTemplateUuid)) |  | ||||||
|                     { |  | ||||||
|                         entry.Strings.Set(_etmTemplateUuid, new ProtectedString(false, newTemplateUuid)); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (uuidMap.Any()) |  | ||||||
|             { |  | ||||||
|                 SaveDb save = new SaveDb( ActiveActivity, _app, _db, OnFinishToRun); |  | ||||||
|                 save.SetStatusLogger(StatusLogger); |  | ||||||
|                 save.Run(); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 OnFinishToRun?.Run(); |  | ||||||
|             } |  | ||||||
|              |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -31,7 +31,7 @@ namespace keepass2android | |||||||
|  |  | ||||||
| 	    public DeleteEntry(Activity activiy, IKp2aApp app, PwEntry entry, OnFinish finish):base(activiy, finish, app) { | 	    public DeleteEntry(Activity activiy, IKp2aApp app, PwEntry entry, OnFinish finish):base(activiy, finish, app) { | ||||||
| 			Ctx = activiy; | 			Ctx = activiy; | ||||||
| 			Db = app.FindDatabaseForEntryId(entry.Uuid); | 			Db = app.FindDatabaseForElement(entry); | ||||||
| 			_entry = entry; | 			_entry = entry; | ||||||
| 			 | 			 | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ namespace keepass2android | |||||||
|         */ |         */ | ||||||
|         private void SetMembers(Activity activity, IKp2aApp app, PwGroup group, bool dontSave) |         private void SetMembers(Activity activity, IKp2aApp app, PwGroup group, bool dontSave) | ||||||
|         { |         { | ||||||
| 			base.SetMembers(activity, app.FindDatabaseForGroupId(group.Uuid)); | 			base.SetMembers(activity, app.FindDatabaseForElement(group)); | ||||||
|  |  | ||||||
| 			_group = group; | 			_group = group; | ||||||
| 	        DontSave = dontSave; | 	        DontSave = dontSave; | ||||||
|   | |||||||
| @@ -100,7 +100,8 @@ namespace keepass2android | |||||||
| 						}; | 						}; | ||||||
|  |  | ||||||
| 				Db.KpDatabase.RootGroup.AddGroup(pgRecycleBin, true); | 				Db.KpDatabase.RootGroup.AddGroup(pgRecycleBin, true); | ||||||
| 				Db.Groups[pgRecycleBin.Uuid] = pgRecycleBin; | 				Db.GroupsById[pgRecycleBin.Uuid] = pgRecycleBin; | ||||||
|  | 			    Db.Elements.Add(pgRecycleBin); | ||||||
| 				Db.KpDatabase.RecycleBinUuid = pgRecycleBin.Uuid; | 				Db.KpDatabase.RecycleBinUuid = pgRecycleBin.Uuid; | ||||||
|  |  | ||||||
| 				bGroupListUpdateRequired = true; | 				bGroupListUpdateRequired = true; | ||||||
| @@ -185,7 +186,8 @@ namespace keepass2android | |||||||
| 					PwDeletedObject pdo = new PwDeletedObject(pe.Uuid, dtNow); | 					PwDeletedObject pdo = new PwDeletedObject(pe.Uuid, dtNow); | ||||||
| 					pd.DeletedObjects.Add(pdo); | 					pd.DeletedObjects.Add(pdo); | ||||||
| 					touchedGroups.Add(pgParent); | 					touchedGroups.Add(pgParent); | ||||||
| 				    Db.Entries.Remove(pe.Uuid); | 				    Db.EntriesById.Remove(pe.Uuid); | ||||||
|  | 				    Db.Elements.Remove(pe); | ||||||
| 				} | 				} | ||||||
| 				else // Recycle | 				else // Recycle | ||||||
| 				{ | 				{ | ||||||
| @@ -223,7 +225,9 @@ namespace keepass2android | |||||||
| 					{ | 					{ | ||||||
|                         //remove groups from global lists if present there |                         //remove groups from global lists if present there | ||||||
| 					    App.DirtyGroups.Remove(g); | 					    App.DirtyGroups.Remove(g); | ||||||
| 						Db.Groups.Remove(g.Uuid); | 						Db.GroupsById.Remove(g.Uuid); | ||||||
|  | 					    Db.Elements.Remove(g); | ||||||
|  |  | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 				} | 				} | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ namespace keepass2android | |||||||
| 	public class EditGroup : RunnableOnFinish { | 	public class EditGroup : RunnableOnFinish { | ||||||
| 		internal Database Db | 		internal Database Db | ||||||
| 		{ | 		{ | ||||||
| 			get { return _app.FindDatabaseForGroupId(Group.Uuid); } | 			get { return _app.FindDatabaseForElement(Group); } | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|         public IKp2aApp App { get => _app; } |         public IKp2aApp App { get => _app; } | ||||||
|   | |||||||
| @@ -151,76 +151,7 @@ namespace keepass2android | |||||||
| 			    Thread.Sleep(10); | 			    Thread.Sleep(10); | ||||||
|                 SaveFileData(_ioc, _keyfileOrProvider); |                 SaveFileData(_ioc, _keyfileOrProvider); | ||||||
|  |  | ||||||
|  |                 Finish(true, _format.SuccessMessage); | ||||||
| 			    bool hasLegacyTemplateIds = false; |  | ||||||
| 			    //make sure we never have entries with same Uuids |  | ||||||
| 			    foreach (var entryKey in newDb.Entries.Keys) |  | ||||||
| 			    { |  | ||||||
|                     foreach (Database otherDb in _app.OpenDatabases) |  | ||||||
|                     { |  | ||||||
|                         if (otherDb == newDb) |  | ||||||
|                             continue; |  | ||||||
| 			            if (otherDb.Entries.ContainsKey(entryKey)) |  | ||||||
| 			            { |  | ||||||
| 			                if (AddTemplateEntries.IsTemplateId(entryKey)) |  | ||||||
| 			                { |  | ||||||
| 			                    hasLegacyTemplateIds = true; |  | ||||||
| 			                } |  | ||||||
| 			                else |  | ||||||
| 			                { |  | ||||||
| 			                    _app.CloseDatabase(newDb); |  | ||||||
| 			                    throw new Exception("Database contains entry id " + entryKey.ToHexString() + "(" + |  | ||||||
| 			                                        newDb.Entries[entryKey].Strings.ReadSafe(PwDefs.TitleField) |  | ||||||
| 			                                        + ") which is already contained in " + |  | ||||||
| 			                                        _app.GetFileStorage(otherDb.Ioc).GetDisplayName(otherDb.Ioc) + |  | ||||||
| 			                                        "! Please close the other database before opening this one."); |  | ||||||
| 			                } |  | ||||||
| 			            } |  | ||||||
| 			        } |  | ||||||
| 			    } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 			    foreach (var groupKey in newDb.Groups.Keys) |  | ||||||
| 			    { |  | ||||||
| 			        foreach (Database otherDb in _app.OpenDatabases) |  | ||||||
| 			        { |  | ||||||
| 			            if (otherDb == newDb) |  | ||||||
| 			                continue; |  | ||||||
| 			            if (otherDb.Groups.ContainsKey(groupKey)) |  | ||||||
| 			            { |  | ||||||
| 			                throw new Exception("Database contains group id " + groupKey.ToHexString() + "(" + |  | ||||||
| 			                                    newDb.Groups[groupKey].Name + ") which is already contained in " + |  | ||||||
| 			                                    _app.GetFileStorage(otherDb.Ioc).GetDisplayName(otherDb.Ioc) + |  | ||||||
| 			                                    "! Please close the other database before opening this one."); |  | ||||||
| 			            } |  | ||||||
| 			        } |  | ||||||
| 			    } |  | ||||||
|  |  | ||||||
| 			    if (hasLegacyTemplateIds) |  | ||||||
| 			    { |  | ||||||
|                     _app.AskYesNoCancel(UiStringKey.ChangleLegacyTemplateIds_Title, UiStringKey.ChangleLegacyTemplateIds_Message,UiStringKey.Ok, UiStringKey.cancel, |  | ||||||
|                         /*yes*/ |  | ||||||
|                         (sender, args) => |  | ||||||
|                         { |  | ||||||
|                             ChangeTemplateIds cti = new ChangeTemplateIds(ActiveActivity, _app, newDb, new ActionOnFinish(ActiveActivity, (b, message, activity) => Finish(b, message))); |  | ||||||
|                             cti.Run(); |  | ||||||
|                         }, |  | ||||||
|                         /*no*/ |  | ||||||
|                         (sender, args) => |  | ||||||
|                         { |  | ||||||
|                             _app.CloseDatabase(newDb); |  | ||||||
|                             Finish(false); |  | ||||||
|                         },  |  | ||||||
|                         null, |  | ||||||
|                         ActiveActivity |  | ||||||
|                          |  | ||||||
|                     ); |  | ||||||
| 			         |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 			    } |  | ||||||
|                 else |  | ||||||
|                     Finish(true, _format.SuccessMessage); |  | ||||||
| 			    return newDb; | 			    return newDb; | ||||||
| 			} | 			} | ||||||
| 			catch (OldFormatException) | 			catch (OldFormatException) | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ namespace keepass2android.database.edit | |||||||
|             } |             } | ||||||
|  |  | ||||||
| 		    HashSet<Database> removeDatabases = new HashSet<Database>(); | 		    HashSet<Database> removeDatabases = new HashSet<Database>(); | ||||||
|             Database addDatabase = _app.FindDatabaseForGroupId(_targetGroup.Uuid); |             Database addDatabase = _app.FindDatabaseForElement(_targetGroup); | ||||||
| 		    if (addDatabase == null) | 		    if (addDatabase == null) | ||||||
| 		    { | 		    { | ||||||
| 		        Finish(false, "Did not find target database. Did you lock it?"); | 		        Finish(false, "Did not find target database. Did you lock it?"); | ||||||
| @@ -73,12 +73,14 @@ namespace keepass2android.database.edit | |||||||
|                         PwEntry entry = elementToMove as PwEntry; |                         PwEntry entry = elementToMove as PwEntry; | ||||||
|                         if (entry != null) |                         if (entry != null) | ||||||
|                         { |                         { | ||||||
|                             var dbRem = _app.FindDatabaseForEntryId(entry.Uuid); |                             var dbRem = _app.FindDatabaseForElement(entry); | ||||||
|                             removeDatabases.Add(dbRem); |                             removeDatabases.Add(dbRem); | ||||||
|                             dbRem.Entries.Remove(entry.Uuid); |                             dbRem.EntriesById.Remove(entry.Uuid); | ||||||
|  |                             dbRem.Elements.Remove(entry); | ||||||
|                             pgParent.Entries.Remove(entry); |                             pgParent.Entries.Remove(entry); | ||||||
|                             _targetGroup.AddEntry(entry, true, true); |                             _targetGroup.AddEntry(entry, true, true); | ||||||
|                             addDatabase.Entries.Add(entry.Uuid, entry); |                             addDatabase.EntriesById.Add(entry.Uuid, entry); | ||||||
|  |                             addDatabase.Elements.Add(entry); | ||||||
|                         } |                         } | ||||||
|                         else |                         else | ||||||
|                         { |                         { | ||||||
| @@ -89,18 +91,20 @@ namespace keepass2android.database.edit | |||||||
|                                 return; |                                 return; | ||||||
|                             } |                             } | ||||||
|  |  | ||||||
|                             var dbRem = _app.FindDatabaseForEntryId(@group.Uuid); |                             var dbRem = _app.FindDatabaseForElement(@group); | ||||||
|                             if (dbRem == null) |                             if (dbRem == null) | ||||||
|                             { |                             { | ||||||
|                                 Finish(false, "Did not find source database. Did you lock it?"); |                                 Finish(false, "Did not find source database. Did you lock it?"); | ||||||
|                                 return; |                                 return; | ||||||
|                             } |                             } | ||||||
|  |  | ||||||
|                             dbRem.Groups.Remove(group.Uuid); |                             dbRem.GroupsById.Remove(group.Uuid); | ||||||
|  |                             dbRem.Elements.Remove(group); | ||||||
|                             removeDatabases.Add(dbRem); |                             removeDatabases.Add(dbRem); | ||||||
|                             pgParent.Groups.Remove(group); |                             pgParent.Groups.Remove(group); | ||||||
|                             _targetGroup.AddGroup(group, true, true); |                             _targetGroup.AddGroup(group, true, true); | ||||||
|                             addDatabase.Groups.Add(group.Uuid, group); |                             addDatabase.GroupsById.Add(group.Uuid, group); | ||||||
|  |                             addDatabase.Elements.Add(group); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -139,6 +139,7 @@ namespace keepass2android | |||||||
| 										//small. | 										//small. | ||||||
| 										MergeIn(fileStorage, ioc); | 										MergeIn(fileStorage, ioc); | ||||||
| 										PerformSaveWithoutCheck(fileStorage, ioc); | 										PerformSaveWithoutCheck(fileStorage, ioc); | ||||||
|  |                                         _db.UpdateGlobals(); | ||||||
| 										Finish(true); | 										Finish(true); | ||||||
| 									}; | 									}; | ||||||
| 								RunInWorkerThread(runHandler); | 								RunInWorkerThread(runHandler); | ||||||
|   | |||||||
| @@ -67,5 +67,4 @@ | |||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Folder Include="libs\" /> |     <Folder Include="libs\" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|    | </Project> | ||||||
| </Project> |  | ||||||
| @@ -53,11 +53,9 @@ | |||||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> |     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\app-release.aar"> |  | ||||||
|       <Link>Jars\app-release.aar</Link> |  | ||||||
|     </LibraryProjectZip> |  | ||||||
|     <None Include="Jars\AboutJars.txt" /> |     <None Include="Jars\AboutJars.txt" /> | ||||||
|     <None Include="Additions\AboutAdditions.txt" /> |     <None Include="Additions\AboutAdditions.txt" /> | ||||||
|  |     <LibraryProjectZip Include="Jars\app-debug.aar" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <TransformFile Include="Transforms\Metadata.xml" /> |     <TransformFile Include="Transforms\Metadata.xml" /> | ||||||
|   | |||||||
| @@ -104,12 +104,13 @@ namespace keepass2android | |||||||
| 		{ | 		{ | ||||||
| 			Intent i = new Intent(act, typeof(EntryActivity)); | 			Intent i = new Intent(act, typeof(EntryActivity)); | ||||||
|  |  | ||||||
| 			i.PutExtra(KeyEntry, pw.Uuid.ToHexString()); |             var db = App.Kp2a.FindDatabaseForElement(pw); | ||||||
|  | 			i.PutExtra(KeyEntry, new ElementAndDatabaseId(db, pw).FullId); | ||||||
| 			i.PutExtra(KeyRefreshPos, pos); | 			i.PutExtra(KeyRefreshPos, pos); | ||||||
|  |  | ||||||
| 		    if (!App.Kp2a.CurrentDb.Entries.ContainsKey(pw.Uuid)) | 		    if (App.Kp2a.CurrentDb != db) | ||||||
| 		    { | 		    { | ||||||
| 		        App.Kp2a.CurrentDb = App.Kp2a.FindDatabaseForEntryId(pw.Uuid); | 		        App.Kp2a.CurrentDb = db; | ||||||
| 		    } | 		    } | ||||||
|  |  | ||||||
| 			if (flags != null) | 			if (flags != null) | ||||||
| @@ -275,7 +276,7 @@ namespace keepass2android | |||||||
| 		        App.Kp2a.LastOpenedEntry.OutputStrings.Set(key, new ProtectedString(isProtected, value)); | 		        App.Kp2a.LastOpenedEntry.OutputStrings.Set(key, new ProtectedString(isProtected, value)); | ||||||
| 		        Intent updateKeyboardIntent = new Intent(this, typeof(CopyToClipboardService)); | 		        Intent updateKeyboardIntent = new Intent(this, typeof(CopyToClipboardService)); | ||||||
| 		        updateKeyboardIntent.SetAction(Intents.UpdateKeyboard); | 		        updateKeyboardIntent.SetAction(Intents.UpdateKeyboard); | ||||||
| 		        updateKeyboardIntent.PutExtra(KeyEntry, Entry.Uuid.ToHexString()); | 		        updateKeyboardIntent.PutExtra(KeyEntry, new ElementAndDatabaseId(App.Kp2a.CurrentDb, Entry).FullId); | ||||||
| 		        StartService(updateKeyboardIntent); | 		        StartService(updateKeyboardIntent); | ||||||
|  |  | ||||||
| 		        //notify plugins | 		        //notify plugins | ||||||
| @@ -405,12 +406,13 @@ namespace keepass2android | |||||||
| 			SetResult(KeePass.ExitNormal); | 			SetResult(KeePass.ExitNormal); | ||||||
|  |  | ||||||
| 			Intent i = Intent; | 			Intent i = Intent; | ||||||
| 			PwUuid uuid = new PwUuid(MemUtil.HexStringToByteArray(i.GetStringExtra(KeyEntry))); |             ElementAndDatabaseId dbAndElementId = new ElementAndDatabaseId(i.GetStringExtra(KeyEntry)); | ||||||
|  | 			PwUuid uuid = new PwUuid(MemUtil.HexStringToByteArray(dbAndElementId.ElementIdString)); | ||||||
| 			_pos = i.GetIntExtra(KeyRefreshPos, -1); | 			_pos = i.GetIntExtra(KeyRefreshPos, -1); | ||||||
|  |  | ||||||
| 			_appTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent); | 			_appTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent); | ||||||
|  |  | ||||||
| 			Entry = db.Entries[uuid]; | 			Entry = db.EntriesById[uuid]; | ||||||
| 			 | 			 | ||||||
| 			// Refresh Menu contents in case onCreateMenuOptions was called before Entry was set | 			// Refresh Menu contents in case onCreateMenuOptions was called before Entry was set | ||||||
| 			ActivityCompat.InvalidateOptionsMenu(this); | 			ActivityCompat.InvalidateOptionsMenu(this); | ||||||
| @@ -482,7 +484,7 @@ namespace keepass2android | |||||||
| 		{ | 		{ | ||||||
| 			Intent showNotIntent = new Intent(this, typeof (CopyToClipboardService)); | 			Intent showNotIntent = new Intent(this, typeof (CopyToClipboardService)); | ||||||
| 			showNotIntent.SetAction(Intents.ShowNotification); | 			showNotIntent.SetAction(Intents.ShowNotification); | ||||||
| 			showNotIntent.PutExtra(KeyEntry, Entry.Uuid.ToHexString()); | 			showNotIntent.PutExtra(KeyEntry, new ElementAndDatabaseId(App.Kp2a.CurrentDb, Entry).FullId); | ||||||
| 			_appTask.PopulatePasswordAccessServiceIntent(showNotIntent); | 			_appTask.PopulatePasswordAccessServiceIntent(showNotIntent); | ||||||
| 			showNotIntent.PutExtra(KeyCloseAfterCreate, closeAfterCreate); | 			showNotIntent.PutExtra(KeyCloseAfterCreate, closeAfterCreate); | ||||||
|  |  | ||||||
| @@ -1303,7 +1305,7 @@ namespace keepass2android | |||||||
| 			byte[] pbData = pb.ReadData();		 | 			byte[] pbData = pb.ReadData();		 | ||||||
|  |  | ||||||
| 			Intent imageViewerIntent = new Intent(this, typeof(ImageViewActivity)); | 			Intent imageViewerIntent = new Intent(this, typeof(ImageViewActivity)); | ||||||
| 			imageViewerIntent.PutExtra("EntryId", Entry.Uuid.ToHexString()); | 			imageViewerIntent.PutExtra("EntryId", new ElementAndDatabaseId(App.Kp2a.CurrentDb, Entry).FullId); | ||||||
| 			imageViewerIntent.PutExtra("EntryKey", key); | 			imageViewerIntent.PutExtra("EntryKey", key); | ||||||
| 			StartActivity(imageViewerIntent); | 			StartActivity(imageViewerIntent); | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -144,7 +144,7 @@ namespace keepass2android | |||||||
| 					PwEntry templateEntry = null; | 					PwEntry templateEntry = null; | ||||||
| 					if (!PwUuid.Zero.Equals(templateId)) | 					if (!PwUuid.Zero.Equals(templateId)) | ||||||
| 					{ | 					{ | ||||||
| 						templateEntry = db.Entries[templateId]; | 						templateEntry = db.EntriesById[templateId]; | ||||||
| 					} | 					} | ||||||
| 					 | 					 | ||||||
| 					if (KpEntryTemplatedEdit.IsTemplate(templateEntry)) | 					if (KpEntryTemplatedEdit.IsTemplate(templateEntry)) | ||||||
| @@ -170,7 +170,7 @@ namespace keepass2android | |||||||
| 					 | 					 | ||||||
| 					Debug.Assert(entryId != null); | 					Debug.Assert(entryId != null); | ||||||
| 					 | 					 | ||||||
| 					State.EntryInDatabase = db.Entries [entryId]; | 					State.EntryInDatabase = db.EntriesById [entryId]; | ||||||
| 					State.IsNew = false; | 					State.IsNew = false; | ||||||
| 					 | 					 | ||||||
| 					 | 					 | ||||||
| @@ -921,7 +921,7 @@ namespace keepass2android | |||||||
| 		    { | 		    { | ||||||
| 			    if (_additionalKeys == null) | 			    if (_additionalKeys == null) | ||||||
| 			    { | 			    { | ||||||
| 				    _additionalKeys = App.Kp2a.CurrentDb.Entries | 				    _additionalKeys = App.Kp2a.CurrentDb.EntriesById | ||||||
| 						.Select(kvp => kvp.Value) | 						.Select(kvp => kvp.Value) | ||||||
| 						.SelectMany(x => x.Strings.GetKeys().Where(k => !PwDefs.IsStandardField(k))) | 						.SelectMany(x => x.Strings.GetKeys().Where(k => !PwDefs.IsStandardField(k))) | ||||||
| 						.Where(k => (k != null) && !k.StartsWith("_etm_") ) | 						.Where(k => (k != null) && !k.StartsWith("_etm_") ) | ||||||
|   | |||||||
| @@ -192,7 +192,7 @@ namespace keepass2android | |||||||
| 			if (id == null) { | 			if (id == null) { | ||||||
| 				Group = db.Root; | 				Group = db.Root; | ||||||
| 			} else { | 			} else { | ||||||
| 				Group = db.Groups[id]; | 				Group = db.GroupsById[id]; | ||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 			Log.Warn (Tag, "Retrieved group"); | 			Log.Warn (Tag, "Retrieved group"); | ||||||
| @@ -286,7 +286,7 @@ namespace keepass2android | |||||||
| 				&& (App.Kp2a.CurrentDb.KpDatabase.RootGroup.FindGroup(App.Kp2a.CurrentDb.KpDatabase.EntryTemplatesGroup, true) != null)) | 				&& (App.Kp2a.CurrentDb.KpDatabase.RootGroup.FindGroup(App.Kp2a.CurrentDb.KpDatabase.EntryTemplatesGroup, true) != null)) | ||||||
| 			{ | 			{ | ||||||
| 				templates.AddRange( | 				templates.AddRange( | ||||||
| 					App.Kp2a.CurrentDb.Groups[App.Kp2a.CurrentDb.KpDatabase.EntryTemplatesGroup].Entries.OrderBy( | 					App.Kp2a.CurrentDb.GroupsById[App.Kp2a.CurrentDb.KpDatabase.EntryTemplatesGroup].Entries.OrderBy( | ||||||
| 						entr => entr.Strings.ReadSafe(PwDefs.TitleField))); | 						entr => entr.Strings.ReadSafe(PwDefs.TitleField))); | ||||||
| 			} | 			} | ||||||
| 			if (templates.Count > 1) | 			if (templates.Count > 1) | ||||||
| @@ -316,6 +316,11 @@ namespace keepass2android | |||||||
| 	        get { return true; } | 	        get { return true; } | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
|  | 	    public override ElementAndDatabaseId FullGroupId | ||||||
|  | 	    { | ||||||
|  | 	        get  { return new ElementAndDatabaseId(App.Kp2a.FindDatabaseForElement(Group), Group); }  | ||||||
|  | 	    } | ||||||
|  |  | ||||||
| 	    public override void OnBackPressed() | 	    public override void OnBackPressed() | ||||||
| 		{ | 		{ | ||||||
| 			base.OnBackPressed(); | 			base.OnBackPressed(); | ||||||
|   | |||||||
| @@ -277,7 +277,7 @@ namespace keepass2android | |||||||
|                 { |                 { | ||||||
|                     applicableInfoTextKeys.Add(backupKey); |                     applicableInfoTextKeys.Add(backupKey); | ||||||
|                 } |                 } | ||||||
|                 if (App.Kp2a.CurrentDb.Entries.Count > 15) |                 if (App.Kp2a.CurrentDb.EntriesById.Count > 15) | ||||||
|                 { |                 { | ||||||
|                     applicableInfoTextKeys.Add(emergencyKey); |                     applicableInfoTextKeys.Add(emergencyKey); | ||||||
|                 } |                 } | ||||||
| @@ -741,9 +741,10 @@ namespace keepass2android | |||||||
|             { |             { | ||||||
|                 var cursor = _suggestionsAdapter.Cursor; |                 var cursor = _suggestionsAdapter.Cursor; | ||||||
|                 cursor.MoveToPosition(position); |                 cursor.MoveToPosition(position); | ||||||
|                 string entryIdAsHexString = cursor.GetString(cursor.GetColumnIndexOrThrow(SearchManager.SuggestColumnIntentDataId)); |                  | ||||||
|                 var entryId = new PwUuid(MemUtil.HexStringToByteArray(entryIdAsHexString)); |                 ElementAndDatabaseId fullId = new ElementAndDatabaseId(cursor.GetString(cursor.GetColumnIndexOrThrow(SearchManager.SuggestColumnIntentDataId))); | ||||||
|                 EntryActivity.Launch(_activity, App.Kp2a.FindDatabaseForEntryId(entryId).Entries[entryId], -1, _activity.AppTask); |                 var entryId = fullId.ElementId; | ||||||
|  |                 EntryActivity.Launch(_activity, App.Kp2a.GetDatabase(fullId.DatabaseId).EntriesById[entryId], -1, _activity.AppTask); | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -861,6 +862,8 @@ namespace keepass2android | |||||||
|  |  | ||||||
|         public abstract bool EntriesBelongToCurrentDatabaseOnly { get; } |         public abstract bool EntriesBelongToCurrentDatabaseOnly { get; } | ||||||
|  |  | ||||||
|  |         public abstract ElementAndDatabaseId FullGroupId { get; } | ||||||
|  |  | ||||||
|  |  | ||||||
|         public override bool OnPrepareOptionsMenu(IMenu menu) |         public override bool OnPrepareOptionsMenu(IMenu menu) | ||||||
|         { |         { | ||||||
| @@ -1390,7 +1393,7 @@ namespace keepass2android | |||||||
|                 new List<KeyValuePair<Database, List<IStructureItem>>>(); |                 new List<KeyValuePair<Database, List<IStructureItem>>>(); | ||||||
|             foreach (var item in checkedItems) |             foreach (var item in checkedItems) | ||||||
|             { |             { | ||||||
|                 var db = app.FindDatabaseForEntryId(item.Uuid) ?? app.FindDatabaseForGroupId(item.Uuid); |                 var db = app.FindDatabaseForElement(item); | ||||||
|                 if (db != null) |                 if (db != null) | ||||||
|                 { |                 { | ||||||
|                     bool foundDatabase = false; |                     bool foundDatabase = false; | ||||||
|   | |||||||
| @@ -118,7 +118,7 @@ namespace keepass2android | |||||||
| 			if (Intent.HasExtra(KeyGroupUuid)) | 			if (Intent.HasExtra(KeyGroupUuid)) | ||||||
| 			{ | 			{ | ||||||
| 				string groupUuid = Intent.Extras.GetString(KeyGroupUuid); | 				string groupUuid = Intent.Extras.GetString(KeyGroupUuid); | ||||||
| 				_groupToEdit = App.Kp2a.CurrentDb.Groups[new PwUuid(MemUtil.HexStringToByteArray(groupUuid))]; | 				_groupToEdit = App.Kp2a.CurrentDb.GroupsById[new PwUuid(MemUtil.HexStringToByteArray(groupUuid))]; | ||||||
| 				_selectedIconId = (int) _groupToEdit.IconId; | 				_selectedIconId = (int) _groupToEdit.IconId; | ||||||
| 				_selectedCustomIconId = _groupToEdit.CustomIconUuid; | 				_selectedCustomIconId = _groupToEdit.CustomIconUuid; | ||||||
| 				TextView nameField = (TextView)FindViewById(Resource.Id.group_name); | 				TextView nameField = (TextView)FindViewById(Resource.Id.group_name); | ||||||
|   | |||||||
| @@ -315,9 +315,12 @@ namespace keepass2android | |||||||
| 			_activityDesign.ApplyTheme();  | 			_activityDesign.ApplyTheme();  | ||||||
| 			base.OnCreate(savedInstanceState); | 			base.OnCreate(savedInstanceState); | ||||||
| 			SetContentView(Resource.Layout.ImageViewActivity); | 			SetContentView(Resource.Layout.ImageViewActivity); | ||||||
| 			var uuid = new PwUuid(MemUtil.HexStringToByteArray(Intent.GetStringExtra("EntryId"))); |  | ||||||
|  | 		    ElementAndDatabaseId fullId = new ElementAndDatabaseId(Intent.GetStringExtra("EntryId")); | ||||||
|  |  | ||||||
|  |             var uuid = new PwUuid(MemUtil.HexStringToByteArray(fullId.ElementIdString)); | ||||||
| 			string key = Intent.GetStringExtra("EntryKey"); | 			string key = Intent.GetStringExtra("EntryKey"); | ||||||
| 			var binary = App.Kp2a.FindDatabaseForEntryId(uuid).Entries[uuid].Binaries.Get(key); | 			var binary = App.Kp2a.GetDatabase(fullId.DatabaseId).EntriesById[uuid].Binaries.Get(key); | ||||||
| 			SupportActionBar.Title = key; | 			SupportActionBar.Title = key; | ||||||
| 			byte[] pbdata = binary.ReadData(); | 			byte[] pbdata = binary.ReadData(); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										304
									
								
								src/keepass2android/KeeAutoExec.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								src/keepass2android/KeeAutoExec.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,304 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Diagnostics; | ||||||
|  | using Android.Webkit; | ||||||
|  | using KeePass.Util.Spr; | ||||||
|  | using KeePassLib; | ||||||
|  | using KeePassLib.Keys; | ||||||
|  | using KeePassLib.Security; | ||||||
|  | using KeePassLib.Serialization; | ||||||
|  | using KeePassLib.Utility; | ||||||
|  |  | ||||||
|  | namespace keepass2android | ||||||
|  | { | ||||||
|  |     public sealed class AutoExecItem | ||||||
|  |     { | ||||||
|  |         private PwEntry m_pe; | ||||||
|  |         public PwEntry Entry | ||||||
|  |         { | ||||||
|  |             get { return m_pe; } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private PwDatabase m_pdContext; | ||||||
|  |         public PwDatabase Database | ||||||
|  |         { | ||||||
|  |             get { return m_pdContext; } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public bool Enabled = true; | ||||||
|  |         public bool Visible = true; | ||||||
|  |  | ||||||
|  |         public long Priority = 0; | ||||||
|  |  | ||||||
|  |         public AutoExecItem(PwEntry pe, PwDatabase pdContext) | ||||||
|  |         { | ||||||
|  |             if (pe == null) throw new ArgumentNullException("pe"); | ||||||
|  |  | ||||||
|  |             m_pe = pe; | ||||||
|  |             m_pdContext = pdContext; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public sealed class KeeAutoExecExt | ||||||
|  |     { | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         private static int PrioritySort(AutoExecItem x, AutoExecItem y) | ||||||
|  |         { | ||||||
|  |             if (x == null) { Debug.Assert(false); return ((y == null) ? 0 : -1); } | ||||||
|  |             if (y == null) { Debug.Assert(false); return 1; } | ||||||
|  |  | ||||||
|  |             return x.Priority.CompareTo(y.Priority); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void AddAutoExecEntries(List<PwEntry> l, PwGroup pg) | ||||||
|  |         { | ||||||
|  |             if (pg.Name.Equals("AutoOpen", StrUtil.CaseIgnoreCmp)) | ||||||
|  |                 l.AddRange(pg.GetEntries(true)); | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 foreach (PwGroup pgSub in pg.Groups) | ||||||
|  |                     AddAutoExecEntries(l, pgSub); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static List<AutoExecItem> GetAutoExecItems(PwDatabase pd) | ||||||
|  |         { | ||||||
|  |             List<AutoExecItem> l = new List<AutoExecItem>(); | ||||||
|  |             if (pd == null) { Debug.Assert(false); return l; } | ||||||
|  |             if (!pd.IsOpen) return l; | ||||||
|  |  | ||||||
|  |             PwGroup pgRoot = pd.RootGroup; | ||||||
|  |             if (pgRoot == null) { Debug.Assert(false); return l; } | ||||||
|  |  | ||||||
|  |             List<PwEntry> lAutoEntries = new List<PwEntry>(); | ||||||
|  |             AddAutoExecEntries(lAutoEntries, pgRoot); | ||||||
|  |  | ||||||
|  |             long lPriStd = 0; | ||||||
|  |             foreach (PwEntry pe in lAutoEntries) | ||||||
|  |             { | ||||||
|  |                 string str = pe.Strings.ReadSafe(PwDefs.UrlField); | ||||||
|  |                 if (str.Length == 0) continue; | ||||||
|  |  | ||||||
|  |                 AutoExecItem a = new AutoExecItem(pe, pd); | ||||||
|  |                 l.Add(a); | ||||||
|  |  | ||||||
|  |                 SprContext ctx = new SprContext(pe, pd, SprCompileFlags.All); | ||||||
|  |  | ||||||
|  |                 if (pe.Expires && (pe.ExpiryTime <= DateTime.UtcNow)) | ||||||
|  |                     a.Enabled = false; | ||||||
|  |  | ||||||
|  |                 bool? ob = GetBoolEx(pe, "Enabled", ctx); | ||||||
|  |                 if (ob.HasValue) a.Enabled = ob.Value; | ||||||
|  |  | ||||||
|  |                 ob = GetBoolEx(pe, "Visible", ctx); | ||||||
|  |                 if (ob.HasValue) a.Visible = ob.Value; | ||||||
|  |  | ||||||
|  |                 long lItemPri = lPriStd; | ||||||
|  |                 if (GetString(pe, "Priority", ctx, true, out str)) | ||||||
|  |                     long.TryParse(str, out lItemPri); | ||||||
|  |                 a.Priority = lItemPri; | ||||||
|  |  | ||||||
|  |                 ++lPriStd; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             l.Sort(KeeAutoExecExt.PrioritySort); | ||||||
|  |             return l; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void OnFileOpen(PwDatabase db) | ||||||
|  |         { | ||||||
|  |             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) | ||||||
|  |         { | ||||||
|  |             PwEntry pe = a.Entry; | ||||||
|  |             PwDatabase pdContext = a.Database; | ||||||
|  |  | ||||||
|  |             SprContext ctxNoEsc = new SprContext(pe, pdContext, SprCompileFlags.All); | ||||||
|  |             SprContext ctxEsc = new SprContext(pe, pdContext, SprCompileFlags.All, | ||||||
|  |                 false, true); | ||||||
|  |  | ||||||
|  |             string strDb; | ||||||
|  |             if (!GetString(pe, PwDefs.UrlField, ctxEsc, true, out strDb)) return; | ||||||
|  |  | ||||||
|  |             IOConnectionInfo ioc = IOConnectionInfo.FromPath(strDb); | ||||||
|  |             //TODO | ||||||
|  |             /*if (ioc.IsLocalFile() && !UrlUtil.IsAbsolutePath(strDb)) | ||||||
|  |                 ioc = IOConnectionInfo.FromPath(UrlUtil.MakeAbsolutePath( | ||||||
|  |                     WinUtil.GetExecutable(), strDb));*/ | ||||||
|  |             if (ioc.Path.Length == 0) return; | ||||||
|  |  | ||||||
|  |             string strIocUserName; | ||||||
|  |             if (GetString(pe, "IocUserName", ctxNoEsc, true, out strIocUserName)) | ||||||
|  |                 ioc.UserName = strIocUserName; | ||||||
|  |  | ||||||
|  |             string strIocPassword; | ||||||
|  |             if (GetString(pe, "IocPassword", ctxNoEsc, true, out strIocPassword)) | ||||||
|  |                 ioc.Password = strIocPassword; | ||||||
|  |  | ||||||
|  |             if ((strIocUserName.Length != 0) && (strIocPassword.Length != 0)) | ||||||
|  |                 ioc.IsComplete = true; | ||||||
|  |  | ||||||
|  |             string str; | ||||||
|  |             if (GetString(pe, "IocTimeout", ctxNoEsc, true, out str)) | ||||||
|  |             { | ||||||
|  |                 long l; | ||||||
|  |                 if (long.TryParse(str, out l)) | ||||||
|  |                     ioc.Properties.SetLong(IocKnownProperties.Timeout, l); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             bool? ob = GetBoolEx(pe, "IocPreAuth", ctxNoEsc); | ||||||
|  |             if (ob.HasValue) | ||||||
|  |                 ioc.Properties.SetBool(IocKnownProperties.PreAuth, ob.Value); | ||||||
|  |  | ||||||
|  |             if (GetString(pe, "IocUserAgent", ctxNoEsc, true, out str)) | ||||||
|  |                 ioc.Properties.Set(IocKnownProperties.UserAgent, str); | ||||||
|  |  | ||||||
|  |             ob = GetBoolEx(pe, "IocExpect100Continue", ctxNoEsc); | ||||||
|  |             if (ob.HasValue) | ||||||
|  |                 ioc.Properties.SetBool(IocKnownProperties.Expect100Continue, ob.Value); | ||||||
|  |  | ||||||
|  |             ob = GetBoolEx(pe, "IocPassive", ctxNoEsc); | ||||||
|  |             if (ob.HasValue) | ||||||
|  |                 ioc.Properties.SetBool(IocKnownProperties.Passive, ob.Value); | ||||||
|  |  | ||||||
|  |             ob = GetBoolEx(pe, "SkipIfNotExists", ctxNoEsc); | ||||||
|  |             if (!ob.HasValue) // Backw. compat. | ||||||
|  |                 ob = GetBoolEx(pe, "Skip if not exists", ctxNoEsc); | ||||||
|  |             if (ob.HasValue && ob.Value) | ||||||
|  |             { | ||||||
|  |                 if (!IOConnection.FileExists(ioc)) return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             CompositeKey ck = new CompositeKey(); | ||||||
|  |  | ||||||
|  |             if (GetString(pe, PwDefs.PasswordField, ctxNoEsc, false, out str)) | ||||||
|  |                 ck.AddUserKey(new KcpPassword(str)); | ||||||
|  |  | ||||||
|  |             if (GetString(pe, PwDefs.UserNameField, ctxNoEsc, false, out str)) | ||||||
|  |             { | ||||||
|  |                 string strAbs = str; | ||||||
|  |                 IOConnectionInfo iocKey = IOConnectionInfo.FromPath(strAbs); | ||||||
|  |                 if (iocKey.IsLocalFile() && !UrlUtil.IsAbsolutePath(strAbs)) | ||||||
|  |                 { | ||||||
|  |                     //TODO | ||||||
|  |                     /*      strAbs = UrlUtil.MakeAbsolutePath(WinUtil.GetExecutable(), strAbs);*/ | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                 ob = GetBoolEx(pe, "SkipIfKeyFileNotExists", ctxNoEsc); | ||||||
|  |                 if (ob.HasValue && ob.Value) | ||||||
|  |                 { | ||||||
|  |                     IOConnectionInfo iocKeyAbs = IOConnectionInfo.FromPath(strAbs); | ||||||
|  |                     if (!IOConnection.FileExists(iocKeyAbs)) return; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 try { ck.AddUserKey(new KcpKeyFile(strAbs)); } | ||||||
|  |                 catch (InvalidOperationException) | ||||||
|  |                 { | ||||||
|  |                     //TODO | ||||||
|  |                     throw new Exception("TODO"); | ||||||
|  |                     //throw new Exception(strAbs + MessageService.NewParagraph + KPRes.KeyFileError); | ||||||
|  |                 } | ||||||
|  |                 catch (Exception) { throw; } | ||||||
|  |             } | ||||||
|  |             else // Try getting key file from attachments | ||||||
|  |             { | ||||||
|  |                 ProtectedBinary pBin = pe.Binaries.Get("KeyFile.bin"); | ||||||
|  |                 if (pBin != null) | ||||||
|  |                     ck.AddUserKey(new KcpKeyFile(IOConnectionInfo.FromPath( | ||||||
|  |                         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); | ||||||
|  |             bool bRestoreFocus = str.Equals("Restore", StrUtil.CaseIgnoreCmp); | ||||||
|  |             /*TODO | ||||||
|  |              * PwDatabase pdPrev = m_host.MainWindow.ActiveDatabase; | ||||||
|  |  | ||||||
|  |             m_host.MainWindow.OpenDatabase(ioc, ck, true); | ||||||
|  |  | ||||||
|  |             if (bRestoreFocus && (pdPrev != null) && !bManual) | ||||||
|  |             { | ||||||
|  |                 PwDocument docPrev = m_host.MainWindow.DocumentManager.FindDocument( | ||||||
|  |                     pdPrev); | ||||||
|  |                 if (docPrev != null) m_host.MainWindow.MakeDocumentActive(docPrev); | ||||||
|  |                 else { Debug.Assert(false); } | ||||||
|  |             }*/ | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static bool GetString(PwEntry pe, string strName, SprContext ctx, | ||||||
|  |         bool bTrim, out string strValue) | ||||||
|  |         { | ||||||
|  |             if ((pe == null) || (strName == null)) | ||||||
|  |             { | ||||||
|  |                 Debug.Assert(false); | ||||||
|  |                 strValue = string.Empty; | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             string str = pe.Strings.ReadSafe(strName); | ||||||
|  |             if (ctx != null) str = SprEngine.Compile(str, ctx); | ||||||
|  |             if (bTrim) str = str.Trim(); | ||||||
|  |  | ||||||
|  |             strValue = str; | ||||||
|  |             return (str.Length != 0); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static bool? GetBoolEx(PwEntry pe, string strName, SprContext ctx) | ||||||
|  |         { | ||||||
|  |             string str; | ||||||
|  |             if (GetString(pe, strName, ctx, true, out str)) | ||||||
|  |             { | ||||||
|  |                 if (str.Equals("True", StrUtil.CaseIgnoreCmp)) | ||||||
|  |                     return true; | ||||||
|  |                 if (str.Equals("False", StrUtil.CaseIgnoreCmp)) | ||||||
|  |                     return false; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public class KeeAutoExec | ||||||
|  |     { | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -52,7 +52,7 @@ namespace keepass2android | |||||||
| 				if (uuidBytes != null) | 				if (uuidBytes != null) | ||||||
| 				{ | 				{ | ||||||
| 						PwUuid templateUuid = new PwUuid(uuidBytes); | 						PwUuid templateUuid = new PwUuid(uuidBytes); | ||||||
| 						return db.Entries.ContainsKey(templateUuid); | 						return db.EntriesById.ContainsKey(templateUuid); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			return false; | 			return false; | ||||||
| @@ -63,7 +63,7 @@ namespace keepass2android | |||||||
| 			_db = db; | 			_db = db; | ||||||
| 			_entry = entry; | 			_entry = entry; | ||||||
| 			PwUuid templateUuid = new PwUuid(MemUtil.HexStringToByteArray(entry.Strings.ReadSafe(EtmTemplateUuid))); | 			PwUuid templateUuid = new PwUuid(MemUtil.HexStringToByteArray(entry.Strings.ReadSafe(EtmTemplateUuid))); | ||||||
| 			_templateEntry = db.Entries[templateUuid]; | 			_templateEntry = db.EntriesById[templateUuid]; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		public static void InitializeEntry(PwEntry entry, PwEntry templateEntry) | 		public static void InitializeEntry(PwEntry entry, PwEntry templateEntry) | ||||||
|   | |||||||
| @@ -432,9 +432,6 @@ | |||||||
|   <string name="AttachFailed">Failed to add file attachment.</string> |   <string name="AttachFailed">Failed to add file attachment.</string> | ||||||
|   <string name="RecycleBin">Recycle Bin</string> |   <string name="RecycleBin">Recycle Bin</string> | ||||||
|  |  | ||||||
|   <string name="UpdatingTemplateIds">Updating template entries </string> |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   <string name="AskDeletePermanentlyEntry">Do you want to delete this entry permanently? Press No to recycle.</string> |   <string name="AskDeletePermanentlyEntry">Do you want to delete this entry permanently? Press No to recycle.</string> | ||||||
|   <string name="AskDeletePermanentlyGroup">Do you want to delete this group permanently? Press No to recycle.</string> |   <string name="AskDeletePermanentlyGroup">Do you want to delete this group permanently? Press No to recycle.</string> | ||||||
|   <string name="AskDeletePermanentlyItems">Do you want to delete the selected elements permanently? Press No to recycle.</string> |   <string name="AskDeletePermanentlyItems">Do you want to delete the selected elements permanently? Press No to recycle.</string> | ||||||
| @@ -739,9 +736,7 @@ | |||||||
|   <string name="open_other_db">Open another database…</string> |   <string name="open_other_db">Open another database…</string> | ||||||
|   <string name="select_database">Select database</string> |   <string name="select_database">Select database</string> | ||||||
|  |  | ||||||
|   <string name="ChangleLegacyTemplateIds_Title">Identical template entry ids</string> |    | ||||||
|   <string name="ChangleLegacyTemplateIds_Message">Your database contains template entries with the same UUIDs as template entries in another open database. In order to use both databases simultaneously, Keepass2Android will modify the IDs of the database you are about to open.</string> |  | ||||||
|  |  | ||||||
|   <string name="DbUnlockedChannel_name">Database unlocked</string> |   <string name="DbUnlockedChannel_name">Database unlocked</string> | ||||||
|   <string name="DbUnlockedChannel_desc">Notification about the database being unlocked</string> |   <string name="DbUnlockedChannel_desc">Notification about the database being unlocked</string> | ||||||
|    |    | ||||||
|   | |||||||
| @@ -213,5 +213,10 @@ namespace keepass2android | |||||||
| 	    { | 	    { | ||||||
| 	        get { return false; } | 	        get { return false; } | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
|  | 	    public override ElementAndDatabaseId FullGroupId | ||||||
|  | 	    { | ||||||
|  | 	        get { return null; } | ||||||
|  | 	    } | ||||||
| 	}} | 	}} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -250,16 +250,7 @@ namespace keepass2android | |||||||
| 	        return newDb; | 	        return newDb; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    public Database FindDatabaseForEntryId(PwUuid entryKey) | 	     | ||||||
| 	    { |  | ||||||
| 	        foreach (Database db in OpenDatabases) |  | ||||||
| 	        { |  | ||||||
| 	            if (db.Entries.ContainsKey(entryKey)) |  | ||||||
| 	                return db; |  | ||||||
| 	        } |  | ||||||
| 	        return null; |  | ||||||
| 	    } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	    public void CloseDatabase(Database db) | 	    public void CloseDatabase(Database db) | ||||||
| 	    { | 	    { | ||||||
| @@ -270,7 +261,7 @@ namespace keepass2android | |||||||
| 	            Lock(false); | 	            Lock(false); | ||||||
|                 return; |                 return; | ||||||
| 	        } | 	        } | ||||||
| 	        if (LastOpenedEntry != null && db.Entries.ContainsKey(LastOpenedEntry.Uuid)) | 	        if (LastOpenedEntry != null && db.EntriesById.ContainsKey(LastOpenedEntry.Uuid)) | ||||||
| 	        { | 	        { | ||||||
| 	            LastOpenedEntry = null; | 	            LastOpenedEntry = null; | ||||||
| 	        } | 	        } | ||||||
| @@ -282,16 +273,7 @@ namespace keepass2android | |||||||
|             //TODO broadcast event so affected activities can close/update?  |             //TODO broadcast event so affected activities can close/update?  | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    public Database FindDatabaseForGroupId(PwUuid groupKey) | 	     | ||||||
| 	    { |  | ||||||
| 	        foreach (Database db in OpenDatabases) |  | ||||||
| 	        { |  | ||||||
| 	            if (db.Groups.ContainsKey(groupKey)) |  | ||||||
| 	                return db; |  | ||||||
| 	        } |  | ||||||
| 	        return null; |  | ||||||
| 	    } |  | ||||||
|  |  | ||||||
|         internal void UnlockDatabase() |         internal void UnlockDatabase() | ||||||
| 		{ | 		{ | ||||||
| 			QuickLocked = false; | 			QuickLocked = false; | ||||||
| @@ -374,7 +356,7 @@ namespace keepass2android | |||||||
|         public void MarkAllGroupsAsDirty() |         public void MarkAllGroupsAsDirty() | ||||||
| 	    { | 	    { | ||||||
|             foreach (var db in OpenDatabases) |             foreach (var db in OpenDatabases) | ||||||
| 	        foreach (PwGroup group in db.Groups.Values) | 	        foreach (PwGroup group in db.GroupsById.Values) | ||||||
| 	        { | 	        { | ||||||
| 	            DirtyGroups.Add(group); | 	            DirtyGroups.Add(group); | ||||||
| 	        } | 	        } | ||||||
| @@ -1017,12 +999,22 @@ namespace keepass2android | |||||||
| 	        throw new Exception("Database not found for dbIoc!"); | 	        throw new Exception("Database not found for dbIoc!"); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    public PwGroup FindGroup(PwUuid uuid) | 	    public Database GetDatabase(string databaseId) | ||||||
|  | 	    { | ||||||
|  | 	        foreach (Database db in OpenDatabases) | ||||||
|  | 	        { | ||||||
|  | 	            if (IoUtil.IocAsHexString(db.Ioc) == databaseId) | ||||||
|  | 	                return db; | ||||||
|  | 	        } | ||||||
|  | 	        throw new Exception("Database not found for databaseId!"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public PwGroup FindGroup(PwUuid uuid) | ||||||
| 	    { | 	    { | ||||||
| 	        foreach (Database db in OpenDatabases) | 	        foreach (Database db in OpenDatabases) | ||||||
| 	        { | 	        { | ||||||
| 	            PwGroup result; | 	            PwGroup result; | ||||||
| 	            if (db.Groups.TryGetValue(uuid, out result)) | 	            if (db.GroupsById.TryGetValue(uuid, out result)) | ||||||
| 	                return result; | 	                return result; | ||||||
| 	        } | 	        } | ||||||
| 	        return null; | 	        return null; | ||||||
| @@ -1033,10 +1025,10 @@ namespace keepass2android | |||||||
| 	        foreach (Database db in OpenDatabases) | 	        foreach (Database db in OpenDatabases) | ||||||
| 	        { | 	        { | ||||||
| 	            PwGroup resultGroup; | 	            PwGroup resultGroup; | ||||||
|                 if (db.Groups.TryGetValue(uuid, out resultGroup)) |                 if (db.GroupsById.TryGetValue(uuid, out resultGroup)) | ||||||
| 	                return resultGroup; | 	                return resultGroup; | ||||||
| 	            PwEntry resultEntry; | 	            PwEntry resultEntry; | ||||||
| 	            if (db.Entries.TryGetValue(uuid, out resultEntry)) | 	            if (db.EntriesById.TryGetValue(uuid, out resultEntry)) | ||||||
| 	                return resultEntry; | 	                return resultEntry; | ||||||
|             } |             } | ||||||
| 	        return null; | 	        return null; | ||||||
| @@ -1053,6 +1045,24 @@ namespace keepass2android | |||||||
|             return false; |             return false; | ||||||
| 	         | 	         | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
|  | 	    public Database FindDatabaseForElement(IStructureItem element) | ||||||
|  | 	    { | ||||||
|  | 	        var db = TryFindDatabaseForElement(element); | ||||||
|  |             if (db == null) | ||||||
|  |                 throw new Exception("Database element not found!"); | ||||||
|  | 	        return db; | ||||||
|  | 	    } | ||||||
|  |  | ||||||
|  | 	    public Database TryFindDatabaseForElement(IStructureItem element) | ||||||
|  | 	    { | ||||||
|  |             foreach (var db in OpenDatabases) | ||||||
|  |             { | ||||||
|  |                 if (db.Elements.Contains(element)) | ||||||
|  |                     return db; | ||||||
|  |             } | ||||||
|  | 	        return null; | ||||||
|  | 	    } | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -782,7 +782,7 @@ namespace keepass2android | |||||||
|         // All group Uuid are stored in guuidKey + indice |         // All group Uuid are stored in guuidKey + indice | ||||||
|         // The last one is the destination group  |         // The last one is the destination group  | ||||||
|         public const String NumberOfGroupsKey = "NumberOfGroups"; |         public const String NumberOfGroupsKey = "NumberOfGroups"; | ||||||
| 		public const String GUuidKey = "gUuidKey";  | 		public const String GFullIdKey = "gFullIdKey";  | ||||||
| 		public const String FullGroupNameKey = "fullGroupNameKey"; | 		public const String FullGroupNameKey = "fullGroupNameKey"; | ||||||
| 		public const String ToastEnableKey = "toastEnableKey"; | 		public const String ToastEnableKey = "toastEnableKey"; | ||||||
|  |  | ||||||
| @@ -791,7 +791,7 @@ namespace keepass2android | |||||||
| 		private LinkedList<string> groupNameList; | 		private LinkedList<string> groupNameList; | ||||||
| 		#endif | 		#endif | ||||||
|  |  | ||||||
| 		private LinkedList<string> _groupUuid; | 		private LinkedList<string> _fullGroupIds; | ||||||
| 	    protected AppTask TaskToBeLaunchedAfterNavigation; | 	    protected AppTask TaskToBeLaunchedAfterNavigation; | ||||||
|  |  | ||||||
| 		protected String FullGroupName { | 		protected String FullGroupName { | ||||||
| @@ -824,7 +824,7 @@ namespace keepass2android | |||||||
|  |  | ||||||
| 		public void PopulateGroups(PwGroup groups) { | 		public void PopulateGroups(PwGroup groups) { | ||||||
|  |  | ||||||
| 			_groupUuid = new LinkedList<String>(); | 			_fullGroupIds = new LinkedList<String>(); | ||||||
|  |  | ||||||
| 			#if INCLUDE_DEBUG_MOVE_GROUPNAME | 			#if INCLUDE_DEBUG_MOVE_GROUPNAME | ||||||
| 			groupNameList = new LinkedList<String>{}; | 			groupNameList = new LinkedList<String>{}; | ||||||
| @@ -839,7 +839,7 @@ namespace keepass2android | |||||||
| 					FullGroupName = readGroup.Name + "." + FullGroupName; | 					FullGroupName = readGroup.Name + "." + FullGroupName; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				_groupUuid.AddFirst (MemUtil.ByteArrayToHexString (readGroup.Uuid.UuidBytes)); | 				_fullGroupIds.AddFirst(new ElementAndDatabaseId(App.Kp2a.FindDatabaseForElement(readGroup),readGroup).FullId); | ||||||
|  |  | ||||||
| 				#if INCLUDE_DEBUG_MOVE_GROUPNAME | 				#if INCLUDE_DEBUG_MOVE_GROUPNAME | ||||||
| 				groupNameList.AddFirst (readGroup.Name); | 				groupNameList.AddFirst (readGroup.Name); | ||||||
| @@ -860,16 +860,17 @@ namespace keepass2android | |||||||
| 		{ | 		{ | ||||||
| 			int numberOfGroups = b.GetInt(NumberOfGroupsKey); | 			int numberOfGroups = b.GetInt(NumberOfGroupsKey); | ||||||
|  |  | ||||||
| 			_groupUuid = new LinkedList<String>(); | 			_fullGroupIds = new LinkedList<String>(); | ||||||
| 			#if INCLUDE_DEBUG_MOVE_GROUPNAME  | 			#if INCLUDE_DEBUG_MOVE_GROUPNAME  | ||||||
| 			groupNameList = new LinkedList<String>{}; | 			groupNameList = new LinkedList<String>{}; | ||||||
| 			#endif  | 			#endif  | ||||||
|  |  | ||||||
| 			int i = 0; | 			int i = 0; | ||||||
|  |  | ||||||
| 			while (i < numberOfGroups) { | 			while (i < numberOfGroups) | ||||||
|  |             { | ||||||
|  |  | ||||||
| 				_groupUuid.AddLast ( b.GetString (GUuidKey + i) ) ; | 				_fullGroupIds.AddLast ( b.GetString (GFullIdKey + i.ToString(CultureInfo.InvariantCulture)) ) ; | ||||||
|  |  | ||||||
| 				#if INCLUDE_DEBUG_MOVE_GROUPNAME  | 				#if INCLUDE_DEBUG_MOVE_GROUPNAME  | ||||||
| 				groupNameList.AddLast ( b.GetString (gNameKey + i); | 				groupNameList.AddLast ( b.GetString (gNameKey + i); | ||||||
| @@ -887,15 +888,16 @@ namespace keepass2android | |||||||
| 			get | 			get | ||||||
| 			{ | 			{ | ||||||
| 				// Return Navigate group Extras | 				// Return Navigate group Extras | ||||||
| 				IEnumerator<String> eGroupKeys = _groupUuid.GetEnumerator (); | 				 | ||||||
|  |  | ||||||
| 				#if INCLUDE_DEBUG_MOVE_GROUPNAME | 				#if INCLUDE_DEBUG_MOVE_GROUPNAME | ||||||
| 				IEnumerator<String> eGroupName = groupNameList.GetEnumerator (); | 				IEnumerator<String> eGroupName = groupNameList.GetEnumerator (); | ||||||
| 				#endif | 				#endif | ||||||
|  |  | ||||||
| 				int i = 0; | 				int i = 0; | ||||||
| 				while (eGroupKeys.MoveNext()) { | 				foreach (var fullGroupId in _fullGroupIds) | ||||||
| 					yield return new StringExtra { Key = GUuidKey + i.ToString (CultureInfo.InvariantCulture), Value = eGroupKeys.Current }; |                 { | ||||||
|  | 					yield return new StringExtra { Key = GFullIdKey + i.ToString (CultureInfo.InvariantCulture), Value = fullGroupId }; | ||||||
|  |  | ||||||
| 					#if INCLUDE_DEBUG_MOVE_GROUPNAME | 					#if INCLUDE_DEBUG_MOVE_GROUPNAME | ||||||
| 					eGroupName.MoveNext(); | 					eGroupName.MoveNext(); | ||||||
| @@ -933,26 +935,29 @@ namespace keepass2android | |||||||
| 				groupBaseActivity.StartTask (TaskToBeLaunchedAfterNavigation); | 				groupBaseActivity.StartTask (TaskToBeLaunchedAfterNavigation); | ||||||
| 				return; | 				return; | ||||||
|  |  | ||||||
| 			} else if (_groupUuid.Contains(groupBaseActivity.UuidGroup)) { // Need to down up in groups tree | 			} else if ((groupBaseActivity.FullGroupId != null) && _fullGroupIds.Contains(groupBaseActivity.FullGroupId.FullId)) { // Need to down up in groups tree | ||||||
|  |  | ||||||
| 				// Get next Group Uuid | 				// Get next Group Uuid | ||||||
| 				var linkedListNode = _groupUuid.Find(groupBaseActivity.UuidGroup); | 				var linkedListNode = _fullGroupIds.Find(groupBaseActivity.FullGroupId.FullId); | ||||||
| 				if (linkedListNode != null) | 				if (linkedListNode != null) | ||||||
| 				{ | 				{ | ||||||
| 					//Note: Resharper says there is a possible NullRefException. | 					//Note: Resharper says there is a possible NullRefException. | ||||||
| 					//This is not the case because it was checked above if we're already there or not. | 					//This is not the case because it was checked above if we're already there or not. | ||||||
| 					String nextGroupUuid = linkedListNode.Next.Value; | 					String nextGroupFullId = linkedListNode.Next.Value; | ||||||
| 					PwUuid nextGroupPwUuid = new PwUuid (MemUtil.HexStringToByteArray (nextGroupUuid)); |  | ||||||
|  |                     ElementAndDatabaseId fullId = new ElementAndDatabaseId(nextGroupFullId); | ||||||
|  |  | ||||||
|  | 					PwUuid nextGroupPwUuid = new PwUuid (MemUtil.HexStringToByteArray (fullId.ElementIdString)); | ||||||
|  |  | ||||||
| 					// Create Group Activity | 					// Create Group Activity | ||||||
| 					PwGroup nextGroup = App.Kp2a.CurrentDb.Groups[nextGroupPwUuid]; | 					PwGroup nextGroup = App.Kp2a.GetDatabase(fullId.DatabaseId).GroupsById[nextGroupPwUuid]; | ||||||
| 					GroupActivity.Launch (groupBaseActivity, nextGroup, this, new ActivityLaunchModeRequestCode(0)); | 					GroupActivity.Launch (groupBaseActivity, nextGroup, this, new ActivityLaunchModeRequestCode(0)); | ||||||
| 				} | 				} | ||||||
| 				return; | 				return; | ||||||
|  |  | ||||||
| 			} else { // Need to go up in groups tree | 			} else { // Need to go up in groups tree | ||||||
| 			    var targetUuid = new PwUuid(MemUtil.HexStringToByteArray(_groupUuid.Last.Value)); | 			    ElementAndDatabaseId fullId = new ElementAndDatabaseId(_fullGroupIds.Last.Value); | ||||||
| 			    var targetDb = App.Kp2a.FindDatabaseForGroupId(targetUuid); | 			    var targetDb = App.Kp2a.GetDatabase(fullId.DatabaseId); | ||||||
| 			    if (App.Kp2a.CurrentDb != targetDb) | 			    if (App.Kp2a.CurrentDb != targetDb) | ||||||
| 			    { | 			    { | ||||||
| 			        App.Kp2a.CurrentDb = targetDb; | 			        App.Kp2a.CurrentDb = targetDb; | ||||||
| @@ -975,7 +980,8 @@ namespace keepass2android | |||||||
|  |  | ||||||
| 		public bool GroupIsFound(GroupBaseActivity groupBaseActivity) | 		public bool GroupIsFound(GroupBaseActivity groupBaseActivity) | ||||||
| 		{ | 		{ | ||||||
| 			return _groupUuid.Last.Value.Equals (groupBaseActivity.UuidGroup); | 		    var fullId = groupBaseActivity.FullGroupId; | ||||||
|  |             return fullId != null && _fullGroupIds.Last.Value.Equals (fullId.FullId); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -216,6 +216,7 @@ | |||||||
|     <Compile Include="ChangeLog.cs" /> |     <Compile Include="ChangeLog.cs" /> | ||||||
|     <Compile Include="FingerprintUnlockMode.cs" /> |     <Compile Include="FingerprintUnlockMode.cs" /> | ||||||
|     <Compile Include="icons\DrawableFactory.cs" /> |     <Compile Include="icons\DrawableFactory.cs" /> | ||||||
|  |     <Compile Include="KeeAutoExec.cs" /> | ||||||
|     <Compile Include="KeeChallenge.cs" /> |     <Compile Include="KeeChallenge.cs" /> | ||||||
|     <Compile Include="FixedDrawerLayout.cs" /> |     <Compile Include="FixedDrawerLayout.cs" /> | ||||||
|     <Compile Include="KpEntryTemplatedEdit.cs" /> |     <Compile Include="KpEntryTemplatedEdit.cs" /> | ||||||
|   | |||||||
| @@ -303,7 +303,7 @@ namespace keepass2android.search | |||||||
| 					    builder.AppendQueryParameter(DatabaseIndexParameter, _entriesWithContexts[MPos].DatabaseIndex.ToString()); | 					    builder.AppendQueryParameter(DatabaseIndexParameter, _entriesWithContexts[MPos].DatabaseIndex.ToString()); | ||||||
|                         return builder.Build().ToString(); |                         return builder.Build().ToString(); | ||||||
| 					case 4: // SuggestColumnIntentDataId | 					case 4: // SuggestColumnIntentDataId | ||||||
| 						return CurrentEntry.Uuid.ToHexString(); | 						return new ElementAndDatabaseId(App.Kp2a.FindDatabaseForElement(CurrentEntry),CurrentEntry).FullId; | ||||||
| 					default: | 					default: | ||||||
| 						return null; | 						return null; | ||||||
| 				} | 				} | ||||||
|   | |||||||
| @@ -61,6 +61,11 @@ namespace keepass2android.search | |||||||
| 	        get { return false; } | 	        get { return false; } | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
|  | 	    public override ElementAndDatabaseId FullGroupId | ||||||
|  | 	    { | ||||||
|  | 	        get { return null; } | ||||||
|  | 	    } | ||||||
|  |  | ||||||
|  |  | ||||||
| 	    protected override void OnNewIntent(Intent intent) | 	    protected override void OnNewIntent(Intent intent) | ||||||
| 		{ | 		{ | ||||||
|   | |||||||
| @@ -283,25 +283,34 @@ namespace keepass2android | |||||||
|  |  | ||||||
| 			if ((intent.Action == Intents.ShowNotification) || (intent.Action == Intents.UpdateKeyboard)) | 			if ((intent.Action == Intents.ShowNotification) || (intent.Action == Intents.UpdateKeyboard)) | ||||||
| 			{ | 			{ | ||||||
| 				String uuidBytes = intent.GetStringExtra(EntryActivity.KeyEntry); | 				String entryId = intent.GetStringExtra(EntryActivity.KeyEntry); | ||||||
|                 String searchUrl = intent.GetStringExtra(SearchUrlTask.UrlToSearchKey); |                 String searchUrl = intent.GetStringExtra(SearchUrlTask.UrlToSearchKey); | ||||||
|  |  | ||||||
| 				PwUuid entryId = PwUuid.Zero; | 			    if (entryId == null) | ||||||
| 				if (uuidBytes != null) | 			    { | ||||||
| 					entryId = new PwUuid(MemUtil.HexStringToByteArray(uuidBytes)); | 			        Kp2aLog.Log("received intent " + intent.Action + " without KeyEntry!"); | ||||||
|  | #if DEBUG | ||||||
|  | 			        throw new Exception("invalid intent received!"); | ||||||
|  | #endif | ||||||
|  |                     return StartCommandResult.NotSticky; | ||||||
|  | 			    } | ||||||
|  |                  | ||||||
|  |  | ||||||
| 				PwEntryOutput entry; | 				PwEntryOutput entry; | ||||||
| 				try | 				try | ||||||
| 				{ | 				{ | ||||||
| 					if ((App.Kp2a.LastOpenedEntry != null) | 				    ElementAndDatabaseId fullId = new ElementAndDatabaseId(entryId); | ||||||
| 						&& (entryId.Equals(App.Kp2a.LastOpenedEntry.Uuid))) |  | ||||||
|  |  | ||||||
|  |                     if (((App.Kp2a.LastOpenedEntry != null) | ||||||
|  | 					                       && (fullId.ElementId.Equals(App.Kp2a.LastOpenedEntry.Uuid)))) | ||||||
| 					{ | 					{ | ||||||
| 						entry = App.Kp2a.LastOpenedEntry; | 						entry = App.Kp2a.LastOpenedEntry; | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
| 					{ | 					{ | ||||||
| 					    Database entryDb = App.Kp2a.FindDatabaseForEntryId(entryId); | 					    Database entryDb = App.Kp2a.GetDatabase(fullId.DatabaseId); | ||||||
| 						entry = new PwEntryOutput(entryDb.Entries[entryId], entryDb); | 						entry = new PwEntryOutput(entryDb.EntriesById[fullId.ElementId], entryDb); | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 				} | 				} | ||||||
| @@ -403,7 +412,7 @@ namespace keepass2android | |||||||
| 			var hadKeyboardData = ClearNotifications(); | 			var hadKeyboardData = ClearNotifications(); | ||||||
|  |  | ||||||
| 			String entryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField); | 			String entryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField); | ||||||
| 		    Database db = App.Kp2a.FindDatabaseForEntryId(entry.Uuid); | 		    Database db = App.Kp2a.FindDatabaseForElement(entry.Entry); | ||||||
|  |  | ||||||
| 		    var bmp = Util.DrawableToBitmap(db.DrawableFactory.GetIconDrawable(this, | 		    var bmp = Util.DrawableToBitmap(db.DrawableFactory.GetIconDrawable(this, | ||||||
| 		        db.KpDatabase, entry.Entry.IconId, entry.Entry.CustomIconUuid, false)); | 		        db.KpDatabase, entry.Entry.IconId, entry.Entry.CustomIconUuid, false)); | ||||||
|   | |||||||
| @@ -72,7 +72,7 @@ namespace keepass2android.view | |||||||
| 			_textView = (TextView)ev.FindViewById(Resource.Id.entry_text); | 			_textView = (TextView)ev.FindViewById(Resource.Id.entry_text); | ||||||
| 			_textView.TextSize = PrefsUtil.GetListTextSize(groupActivity); | 			_textView.TextSize = PrefsUtil.GetListTextSize(groupActivity); | ||||||
|  |  | ||||||
| 		    Database db = App.Kp2a.FindDatabaseForEntryId(pw.Uuid); | 		    Database db = App.Kp2a.FindDatabaseForElement(pw); | ||||||
| 			 | 			 | ||||||
| 			ev.FindViewById(Resource.Id.entry_icon_bkg).Visibility = db.DrawableFactory.IsWhiteIconSet ?  ViewStates.Visible : ViewStates.Gone; | 			ev.FindViewById(Resource.Id.entry_icon_bkg).Visibility = db.DrawableFactory.IsWhiteIconSet ?  ViewStates.Visible : ViewStates.Gone; | ||||||
|  |  | ||||||
| @@ -108,7 +108,7 @@ namespace keepass2android.view | |||||||
| 		    ev.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible; | 		    ev.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible; | ||||||
| 		    ev.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible; | 		    ev.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible; | ||||||
|  |  | ||||||
| 		    Database db = App.Kp2a.FindDatabaseForEntryId(_entry.Uuid); | 		    Database db = App.Kp2a.FindDatabaseForElement(_entry); | ||||||
|  |  | ||||||
|             ImageView iv = (ImageView)ev.FindViewById(Resource.Id.icon); |             ImageView iv = (ImageView)ev.FindViewById(Resource.Id.icon); | ||||||
| 			bool isExpired = pw.Expires && pw.ExpiryTime < DateTime.Now; | 			bool isExpired = pw.Expires && pw.ExpiryTime < DateTime.Now; | ||||||
|   | |||||||
| @@ -63,7 +63,7 @@ namespace keepass2android.view | |||||||
| 			_label = (TextView) gv.FindViewById(Resource.Id.group_label); | 			_label = (TextView) gv.FindViewById(Resource.Id.group_label); | ||||||
| 			_label.TextSize = size-8; | 			_label.TextSize = size-8; | ||||||
|  |  | ||||||
| 		    Database db = App.Kp2a.FindDatabaseForGroupId(pw.Uuid); | 		    Database db = App.Kp2a.FindDatabaseForElement(pw); | ||||||
|  |  | ||||||
|             gv.FindViewById(Resource.Id.group_icon_bkg).Visibility = db.DrawableFactory.IsWhiteIconSet ? ViewStates.Visible : ViewStates.Gone; |             gv.FindViewById(Resource.Id.group_icon_bkg).Visibility = db.DrawableFactory.IsWhiteIconSet ? ViewStates.Visible : ViewStates.Gone; | ||||||
|  |  | ||||||
| @@ -81,7 +81,7 @@ namespace keepass2android.view | |||||||
| 			_pwGroup = pw; | 			_pwGroup = pw; | ||||||
| 			 | 			 | ||||||
| 			ImageView iv = (ImageView) gv.FindViewById(Resource.Id.icon); | 			ImageView iv = (ImageView) gv.FindViewById(Resource.Id.icon); | ||||||
| 		    Database db = App.Kp2a.FindDatabaseForGroupId(pw.Uuid); | 		    Database db = App.Kp2a.FindDatabaseForElement(pw); | ||||||
|             db.DrawableFactory.AssignDrawableTo(iv, _groupBaseActivity, db.KpDatabase, pw.IconId, pw.CustomIconUuid, true); |             db.DrawableFactory.AssignDrawableTo(iv, _groupBaseActivity, db.KpDatabase, pw.IconId, pw.CustomIconUuid, true); | ||||||
| 		    gv.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible; | 		    gv.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible; | ||||||
| 		    gv.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible; | 		    gv.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll