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:
Philipp Crocoll
2018-11-11 06:35:06 +01:00
parent b2d791d6ea
commit f37c0a9124
39 changed files with 554 additions and 286 deletions

View File

@@ -87,8 +87,9 @@ namespace keepass2android
_app.DirtyGroups.Add(parent);
// Add entry to global
_db.Entries[_entry.Uuid] = _entry;
_db.EntriesById[_entry.Uuid] = _entry;
_db.Elements.Add(_entry);
} else
{
StatusLogger.UpdateMessage(UiStringKey.UndoingChanges);

View File

@@ -70,9 +70,11 @@ namespace keepass2android
Group.CustomIconUuid = _groupCustomIconId;
}
Parent.AddGroup(Group, true);
_app.CurrentDb.GroupsById[Group.Uuid] = Group;
_app.CurrentDb.Elements.Add(Group);
// Commit to disk
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, DontSave);
// Commit to disk
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, DontSave);
save.SetStatusLogger(StatusLogger);
save.Run();
}
@@ -92,10 +94,12 @@ namespace keepass2android
_addGroup.App.DirtyGroups.Add(_addGroup.Parent);
// 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 {
StatusLogger.UpdateMessage(UiStringKey.UndoingChanges);
_addGroup.Parent.Groups.Remove(_addGroup.Group);
}
base.Run();

View File

@@ -292,7 +292,7 @@ namespace keepass2android
{
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);
});
}
@@ -327,7 +327,7 @@ namespace keepass2android
}
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
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.EntryTemplatesGroupChanged = DateTime.Now;
_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>();
foreach (var template in TemplateEntries)
{
if (_app.CurrentDb.Entries.ContainsKey(template.Uuid))
if (_app.CurrentDb.EntriesById.ContainsKey(template.Uuid))
continue;
PwEntry entry = CreateEntry(template);
templateGroup.AddEntry(entry, true);
addedEntries.Add(entry);
_app.CurrentDb.Entries[entry.Uuid] = entry;
_app.CurrentDb.EntriesById[entry.Uuid] = entry;
}
return templateGroup;
}
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.Strings.Set(PwDefs.TitleField, new ProtectedString(false, _app.GetResourceString(template.Title)));
entry.Strings.Set("_etm_template", new ProtectedString(false, "1"));
entry.Strings.Set(TemplateIdStringKey, new ProtectedString(false, template.Uuid.ToHexString()));
int position = 0;
foreach (var field in template.Fields)
{

View File

@@ -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();
}
}
}
}

View File

@@ -31,7 +31,7 @@ namespace keepass2android
public DeleteEntry(Activity activiy, IKp2aApp app, PwEntry entry, OnFinish finish):base(activiy, finish, app) {
Ctx = activiy;
Db = app.FindDatabaseForEntryId(entry.Uuid);
Db = app.FindDatabaseForElement(entry);
_entry = entry;
}

View File

@@ -47,7 +47,7 @@ namespace keepass2android
*/
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;
DontSave = dontSave;

View File

@@ -100,7 +100,8 @@ namespace keepass2android
};
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;
bGroupListUpdateRequired = true;
@@ -185,7 +186,8 @@ namespace keepass2android
PwDeletedObject pdo = new PwDeletedObject(pe.Uuid, dtNow);
pd.DeletedObjects.Add(pdo);
touchedGroups.Add(pgParent);
Db.Entries.Remove(pe.Uuid);
Db.EntriesById.Remove(pe.Uuid);
Db.Elements.Remove(pe);
}
else // Recycle
{
@@ -223,7 +225,9 @@ namespace keepass2android
{
//remove groups from global lists if present there
App.DirtyGroups.Remove(g);
Db.Groups.Remove(g.Uuid);
Db.GroupsById.Remove(g.Uuid);
Db.Elements.Remove(g);
}
}

View File

@@ -26,7 +26,7 @@ namespace keepass2android
public class EditGroup : RunnableOnFinish {
internal Database Db
{
get { return _app.FindDatabaseForGroupId(Group.Uuid); }
get { return _app.FindDatabaseForElement(Group); }
}
public IKp2aApp App { get => _app; }

View File

@@ -151,76 +151,7 @@ namespace keepass2android
Thread.Sleep(10);
SaveFileData(_ioc, _keyfileOrProvider);
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);
Finish(true, _format.SuccessMessage);
return newDb;
}
catch (OldFormatException)

View File

@@ -52,7 +52,7 @@ namespace keepass2android.database.edit
}
HashSet<Database> removeDatabases = new HashSet<Database>();
Database addDatabase = _app.FindDatabaseForGroupId(_targetGroup.Uuid);
Database addDatabase = _app.FindDatabaseForElement(_targetGroup);
if (addDatabase == null)
{
Finish(false, "Did not find target database. Did you lock it?");
@@ -73,12 +73,14 @@ namespace keepass2android.database.edit
PwEntry entry = elementToMove as PwEntry;
if (entry != null)
{
var dbRem = _app.FindDatabaseForEntryId(entry.Uuid);
var dbRem = _app.FindDatabaseForElement(entry);
removeDatabases.Add(dbRem);
dbRem.Entries.Remove(entry.Uuid);
dbRem.EntriesById.Remove(entry.Uuid);
dbRem.Elements.Remove(entry);
pgParent.Entries.Remove(entry);
_targetGroup.AddEntry(entry, true, true);
addDatabase.Entries.Add(entry.Uuid, entry);
addDatabase.EntriesById.Add(entry.Uuid, entry);
addDatabase.Elements.Add(entry);
}
else
{
@@ -89,18 +91,20 @@ namespace keepass2android.database.edit
return;
}
var dbRem = _app.FindDatabaseForEntryId(@group.Uuid);
var dbRem = _app.FindDatabaseForElement(@group);
if (dbRem == null)
{
Finish(false, "Did not find source database. Did you lock it?");
return;
}
dbRem.Groups.Remove(group.Uuid);
dbRem.GroupsById.Remove(group.Uuid);
dbRem.Elements.Remove(group);
removeDatabases.Add(dbRem);
pgParent.Groups.Remove(group);
_targetGroup.AddGroup(group, true, true);
addDatabase.Groups.Add(group.Uuid, group);
addDatabase.GroupsById.Add(group.Uuid, group);
addDatabase.Elements.Add(group);
}
}

View File

@@ -139,6 +139,7 @@ namespace keepass2android
//small.
MergeIn(fileStorage, ioc);
PerformSaveWithoutCheck(fileStorage, ioc);
_db.UpdateGlobals();
Finish(true);
};
RunInWorkerThread(runHandler);