private static PwGroup FilterCloneGroup(PwGroup pg, Dictionary <PwUuid, bool> dUuids) { PwGroup pgNew = new PwGroup(); pgNew.Uuid = pg.Uuid; pgNew.AssignProperties(pg, false, true); Debug.Assert(pgNew.EqualsGroup(pg, (PwCompareOptions.IgnoreParentGroup | PwCompareOptions.PropertiesOnly), MemProtCmpMode.Full)); foreach (PwEntry pe in pg.Entries) { if (dUuids.ContainsKey(pe.Uuid)) { pgNew.AddEntry(pe.CloneDeep(), true, false); } } foreach (PwGroup pgSub in pg.Groups) { if (dUuids.ContainsKey(pgSub.Uuid)) { pgNew.AddGroup(FilterCloneGroup(pgSub, dUuids), true, false); } } return(pgNew); }
public static PwGroup DuplicateTo(this PwGroup group, PwGroup parent) { PwGroup copy = new PwGroup(); copy.Uuid = group.Uuid; copy.AssignProperties(group, false, true); //TODO MST: clear this comment and it's ramifications! //HACK: CloneDeep introduces the copy into the parent node, therefore SetParent triggers a change of the parent // which shouldn't be - the extended ProtectionSection in KeeShare should prevent interference, but a // a clean way to clone a node without cloning children and without hooking it into a tree would be nice copy.SetParent(parent); return(copy); }
/// <summary> /// Get or create the target group of an entry in the target database (including hierarchy). /// </summary> /// <param name="entry">An entry wich is located in the folder with the target structure.</param> /// <param name="targetDatabase">The target database in which the folder structure should be created.</param> /// <param name="sourceDatabase">The source database from which the folder properties should be taken.</param> /// <returns>The target folder in the target database.</returns> private static PwGroup CreateTargetGroupInDatebase(PwEntry entry, PwDatabase targetDatabase, PwDatabase sourceDatabase) { // Collect all group names from the entry up to the root group PwGroup group = entry.ParentGroup; List <PwUuid> list = new List <PwUuid>(); while (group != null) { list.Add(group.Uuid); group = group.ParentGroup; } // Remove root group (we already changed the root group name) list.RemoveAt(list.Count - 1); // groups are in a bottom-up oder -> reverse to get top-down list.Reverse(); // Create group structure for the new entry (copying group properties) PwGroup lastGroup = targetDatabase.RootGroup; foreach (PwUuid id in list) { // Does the target group already exist? PwGroup newGroup = lastGroup.FindGroup(id, false); if (newGroup != null) { lastGroup = newGroup; continue; } // Get the source group PwGroup sourceGroup = sourceDatabase.RootGroup.FindGroup(id, true); // Create a new group and asign all properties from the source group newGroup = new PwGroup(); newGroup.AssignProperties(sourceGroup, false, true); HandleCustomIcon(targetDatabase, sourceDatabase, sourceGroup); // Add the new group at the right position in the target database lastGroup.AddGroup(newGroup, true); lastGroup = newGroup; } // Return the target folder (leaf folder) return(lastGroup); }
/// <summary> /// Synchronize the current database with another one. /// </summary> /// <param name="pwSource">Input database to synchronize with. This input /// database is used to update the current one, but is not modified! You /// must copy the current object if you want a second instance of the /// synchronized database. The input database must not be seen as valid /// database any more after calling <c>Synchronize</c>.</param> /// <param name="mm">Merge method.</param> public void MergeIn(PwDatabase pwSource, PwMergeMethod mm) { if(mm == PwMergeMethod.CreateNewUuids) { pwSource.RootGroup.CreateNewItemUuids(true, true, true); } GroupHandler gh = delegate(PwGroup pg) { if(pg == pwSource.m_pgRootGroup) return true; PwGroup pgLocal = m_pgRootGroup.FindGroup(pg.Uuid, true); if(pgLocal == null) { PwGroup pgSourceParent = pg.ParentGroup; PwGroup pgLocalContainer; if(pgSourceParent == pwSource.m_pgRootGroup) pgLocalContainer = m_pgRootGroup; else pgLocalContainer = m_pgRootGroup.FindGroup(pgSourceParent.Uuid, true); Debug.Assert(pgLocalContainer != null); PwGroup pgNew = new PwGroup(); pgNew.Uuid = pg.Uuid; pgNew.AssignProperties(pg, false); pgLocalContainer.AddGroup(pgNew, true); } else // pgLocal != null { Debug.Assert(mm != PwMergeMethod.CreateNewUuids); if(mm == PwMergeMethod.OverwriteExisting) pgLocal.AssignProperties(pg, false); else if((mm == PwMergeMethod.OverwriteIfNewer) || (mm == PwMergeMethod.Synchronize)) { pgLocal.AssignProperties(pg, true); } // else if(mm == PwMergeMethod.KeepExisting) ... } return true; }; EntryHandler eh = delegate(PwEntry pe) { PwEntry peLocal = m_pgRootGroup.FindEntry(pe.Uuid, true); if(peLocal == null) { PwGroup pgSourceParent = pe.ParentGroup; PwGroup pgLocalContainer; if(pgSourceParent == pwSource.m_pgRootGroup) pgLocalContainer = m_pgRootGroup; else pgLocalContainer = m_pgRootGroup.FindGroup(pgSourceParent.Uuid, true); Debug.Assert(pgLocalContainer != null); PwEntry peNew = new PwEntry(false, false); peNew.Uuid = pe.Uuid; peNew.AssignProperties(pe, false, true); pgLocalContainer.AddEntry(peNew, true); } else // peLocal == null { Debug.Assert(mm != PwMergeMethod.CreateNewUuids); if(mm == PwMergeMethod.OverwriteExisting) peLocal.AssignProperties(pe, false, true); else if((mm == PwMergeMethod.OverwriteIfNewer) || (mm == PwMergeMethod.Synchronize)) { peLocal.AssignProperties(pe, true, true); } // else if(mm == PwMergeMethod.KeepExisting) ... } return true; }; if(!pwSource.RootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh)) throw new InvalidOperationException(); if(mm == PwMergeMethod.Synchronize) { ApplyDeletions(pwSource.m_vDeletedObjects, true); ApplyDeletions(m_vDeletedObjects, false); } }