public static bool? Import(PwDatabase pwDatabase, FileFormatProvider fmtImp, IOConnectionInfo[] vConnections, bool bSynchronize, IUIOperations uiOps, bool bForceSave, Form fParent) { if(pwDatabase == null) throw new ArgumentNullException("pwDatabase"); if(!pwDatabase.IsOpen) return null; if(fmtImp == null) throw new ArgumentNullException("fmtImp"); if(vConnections == null) throw new ArgumentNullException("vConnections"); if(!AppPolicy.Try(AppPolicyId.Import)) return false; if(!fmtImp.TryBeginImport()) return false; bool bUseTempDb = (fmtImp.SupportsUuids || fmtImp.RequiresKey); bool bAllSuccess = true; // if(bSynchronize) { Debug.Assert(vFiles.Length == 1); } IStatusLogger dlgStatus; if(Program.Config.UI.ShowImportStatusDialog) dlgStatus = new OnDemandStatusDialog(false, fParent); else dlgStatus = new UIBlockerStatusLogger(fParent); dlgStatus.StartLogging(PwDefs.ShortProductName + " - " + (bSynchronize ? KPRes.Synchronizing : KPRes.ImportingStatusMsg), false); dlgStatus.SetText(bSynchronize ? KPRes.Synchronizing : KPRes.ImportingStatusMsg, LogStatusType.Info); if(vConnections.Length == 0) { try { fmtImp.Import(pwDatabase, null, dlgStatus); } catch(Exception exSingular) { if((exSingular.Message != null) && (exSingular.Message.Length > 0)) { // slf.SetText(exSingular.Message, LogStatusType.Warning); MessageService.ShowWarning(exSingular); } } dlgStatus.EndLogging(); return true; } foreach(IOConnectionInfo iocIn in vConnections) { Stream s = null; try { s = IOConnection.OpenRead(iocIn); } catch(Exception exFile) { MessageService.ShowWarning(iocIn.GetDisplayName(), exFile); bAllSuccess = false; continue; } if(s == null) { Debug.Assert(false); bAllSuccess = false; continue; } PwDatabase pwImp; if(bUseTempDb) { pwImp = new PwDatabase(); pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey); pwImp.MemoryProtection = pwDatabase.MemoryProtection.CloneDeep(); } else pwImp = pwDatabase; if(fmtImp.RequiresKey && !bSynchronize) { KeyPromptForm kpf = new KeyPromptForm(); kpf.InitEx(iocIn, false, true); if(UIUtil.ShowDialogNotValue(kpf, DialogResult.OK)) { s.Close(); continue; } pwImp.MasterKey = kpf.CompositeKey; UIUtil.DestroyForm(kpf); } else if(bSynchronize) pwImp.MasterKey = pwDatabase.MasterKey; dlgStatus.SetText((bSynchronize ? KPRes.Synchronizing : KPRes.ImportingStatusMsg) + " (" + iocIn.GetDisplayName() + ")", LogStatusType.Info); try { fmtImp.Import(pwImp, s, dlgStatus); } catch(Exception excpFmt) { string strMsgEx = excpFmt.Message; if(bSynchronize && (excpFmt is InvalidCompositeKeyException)) strMsgEx = KLRes.InvalidCompositeKey + MessageService.NewParagraph + KPRes.SynchronizingHint; MessageService.ShowWarning(strMsgEx); s.Close(); bAllSuccess = false; continue; } s.Close(); if(bUseTempDb) { PwMergeMethod mm; if(!fmtImp.SupportsUuids) mm = PwMergeMethod.CreateNewUuids; else if(bSynchronize) mm = PwMergeMethod.Synchronize; else { ImportMethodForm imf = new ImportMethodForm(); if(UIUtil.ShowDialogNotValue(imf, DialogResult.OK)) continue; mm = imf.MergeMethod; UIUtil.DestroyForm(imf); } // slf.SetText(KPRes.MergingData, LogStatusType.Info); try { pwDatabase.MergeIn(pwImp, mm, dlgStatus); } catch(Exception exMerge) { MessageService.ShowWarning(iocIn.GetDisplayName(), KPRes.ImportFailed, exMerge); bAllSuccess = false; continue; } } } dlgStatus.EndLogging(); if(bSynchronize && bAllSuccess) { Debug.Assert(uiOps != null); if(uiOps == null) throw new ArgumentNullException("uiOps"); if(uiOps.UIFileSave(bForceSave)) { foreach(IOConnectionInfo ioc in vConnections) { try { if(ioc.Path != pwDatabase.IOConnectionInfo.Path) { if(pwDatabase.IOConnectionInfo.IsLocalFile() && ioc.IsLocalFile()) { File.Copy(pwDatabase.IOConnectionInfo.Path, ioc.Path, true); } else pwDatabase.SaveAs(ioc, false, null); } else { } // No assert (sync on save) Program.MainForm.FileMruList.AddItem(ioc.GetDisplayName(), ioc.CloneDeep(), true); } catch(Exception exSync) { MessageService.ShowWarning(KPRes.SyncFailed, pwDatabase.IOConnectionInfo.GetDisplayName() + MessageService.NewLine + ioc.GetDisplayName(), exSync); bAllSuccess = false; continue; } } } else { MessageService.ShowWarning(KPRes.SyncFailed, pwDatabase.IOConnectionInfo.GetDisplayName()); bAllSuccess = false; } } return bAllSuccess; }
public static bool? Import(PwDatabase pd, FileFormatProvider fmtImp, IOConnectionInfo iocImp, PwMergeMethod mm, CompositeKey cmpKey) { if(pd == null) { Debug.Assert(false); return false; } if(fmtImp == null) { Debug.Assert(false); return false; } if(iocImp == null) { Debug.Assert(false); return false; } if(cmpKey == null) cmpKey = new CompositeKey(); if(!AppPolicy.Try(AppPolicyId.Import)) return false; if(!fmtImp.TryBeginImport()) return false; PwDatabase pdImp = new PwDatabase(); pdImp.New(new IOConnectionInfo(), cmpKey); pdImp.MemoryProtection = pd.MemoryProtection.CloneDeep(); Stream s = IOConnection.OpenRead(iocImp); if(s == null) throw new FileNotFoundException(iocImp.GetDisplayName() + MessageService.NewLine + KPRes.FileNotFoundError); try { fmtImp.Import(pdImp, s, null); } finally { s.Close(); } pd.MergeIn(pdImp, mm); return true; }
private static void PerformXmlReplace(PwDatabase pd, XmlReplaceOptions opt, IStatusLogger sl) { if(opt.SelectNodesXPath.Length == 0) return; if(opt.Operation == XmlReplaceOp.None) return; bool bRemove = (opt.Operation == XmlReplaceOp.RemoveNodes); bool bReplace = (opt.Operation == XmlReplaceOp.ReplaceData); bool bMatchCase = ((opt.Flags & XmlReplaceFlags.CaseSensitive) != XmlReplaceFlags.None); bool bRegex = ((opt.Flags & XmlReplaceFlags.Regex) != XmlReplaceFlags.None); Regex rxFind = null; if(bReplace && bRegex) rxFind = new Regex(opt.FindText, (bMatchCase ? RegexOptions.None : RegexOptions.IgnoreCase)); EnsureStandardFieldsExist(pd); KdbxFile kdbxOrg = new KdbxFile(pd); MemoryStream msOrg = new MemoryStream(); kdbxOrg.Save(msOrg, null, KdbxFormat.PlainXml, sl); byte[] pbXml = msOrg.ToArray(); msOrg.Close(); string strXml = StrUtil.Utf8.GetString(pbXml); XmlDocument xd = new XmlDocument(); xd.LoadXml(strXml); XPathNavigator xpNavRoot = xd.CreateNavigator(); XPathNodeIterator xpIt = xpNavRoot.Select(opt.SelectNodesXPath); // XPathNavigators must be cloned to make them independent List<XPathNavigator> lNodes = new List<XPathNavigator>(); while(xpIt.MoveNext()) lNodes.Add(xpIt.Current.Clone()); if(lNodes.Count == 0) return; for(int i = lNodes.Count - 1; i >= 0; --i) { if((sl != null) && !sl.ContinueWork()) return; XPathNavigator xpNav = lNodes[i]; if(bRemove) xpNav.DeleteSelf(); else if(bReplace) ApplyReplace(xpNav, opt, rxFind); else { Debug.Assert(false); } // Unknown action } MemoryStream msMod = new MemoryStream(); XmlWriterSettings xws = new XmlWriterSettings(); xws.Encoding = StrUtil.Utf8; xws.Indent = true; xws.IndentChars = "\t"; XmlWriter xw = XmlWriter.Create(msMod, xws); xd.Save(xw); byte[] pbMod = msMod.ToArray(); msMod.Close(); PwDatabase pdMod = new PwDatabase(); msMod = new MemoryStream(pbMod, false); try { KdbxFile kdbxMod = new KdbxFile(pdMod); kdbxMod.Load(msMod, KdbxFormat.PlainXml, sl); } catch(Exception) { throw new Exception(KPRes.XmlModInvalid + MessageService.NewParagraph + KPRes.OpAborted + MessageService.NewParagraph + KPRes.DbNoModBy.Replace(@"{PARAM}", @"'" + KPRes.XmlReplace + @"'")); } finally { msMod.Close(); } PrepareModDbForMerge(pdMod, pd); pd.Modified = true; pd.UINeedsIconUpdate = true; pd.MergeIn(pdMod, PwMergeMethod.Synchronize, sl); }
protected void MergeIn(PwDatabase target, PwDatabase source) { //remember stats of destDB to guess if we merged in something //maybe we only look for the lastChanged entry var clone = source.CloneDeep(target.RootGroup); clone.Register(KeeShare.TemporaryDatabaseId, KeeShare.TemporaryDatabaseTag); var cyclicEntries = new List<PwEntry>(); foreach (var cloneEntry in clone.RootGroup.GetEntries(true).ToList()) { if(cloneEntry.HasExportSource(target.RootGroup.Uuid.ToHexString())) { cloneEntry.DeleteFrom(cloneEntry.ParentGroup); cyclicEntries.Add(cloneEntry); } } Console.WriteLine("Prevent import of nodes which are exported from here: " + String.Join(",", cyclicEntries.Select(e => e.GetTitle()).ToArray())); DateTime lastChange = DateTime.MinValue; foreach (var entry in target.RootGroup.GetEntries(true)) { if (entry.LastModificationTime.Ticks > lastChange.Ticks) { lastChange = entry.LastModificationTime; } } target.MergeIn(clone, PwMergeMethod.Synchronize); foreach (var entry in source.RootGroup.GetEntries(true)) { if (entry.LastModificationTime.Ticks > lastChange.Ticks) { //set the modified flag of the database true, so the uiUpdate knows which tab should be marked as changed target.Modified = true; } } if (Imported != null) Imported.Invoke(this, target.RootGroup); }
private static bool PerformImport(PwDatabase pwDatabase, FileFormatProvider fmtImp, IOConnectionInfo[] vConnections, bool bSynchronize, IUIOperations uiOps, bool bForceSave) { if(fmtImp.TryBeginImport() == false) return false; bool bUseTempDb = (fmtImp.SupportsUuids || fmtImp.RequiresKey); bool bAllSuccess = true; // if(bSynchronize) { Debug.Assert(vFiles.Length == 1); } StatusLoggerForm slf = new StatusLoggerForm(); slf.InitEx(false); slf.Show(); if(bSynchronize) slf.StartLogging(KPRes.Synchronize, false); else slf.StartLogging(KPRes.ImportingStatusMsg, false); if(vConnections.Length == 0) { try { fmtImp.Import(pwDatabase, null, slf); } catch(Exception exSingular) { if((exSingular.Message != null) && (exSingular.Message.Length > 0)) { slf.SetText(exSingular.Message, LogStatusType.Warning); MessageService.ShowWarning(exSingular); } } slf.EndLogging(); slf.Close(); return true; } foreach(IOConnectionInfo iocIn in vConnections) { Stream s = null; try { s = IOConnection.OpenRead(iocIn); } catch(Exception exFile) { MessageService.ShowWarning(iocIn.GetDisplayName(), exFile); bAllSuccess = false; continue; } if(s == null) { Debug.Assert(false); bAllSuccess = false; continue; } PwDatabase pwImp; if(bUseTempDb) { pwImp = new PwDatabase(); pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey); pwImp.MemoryProtection = pwDatabase.MemoryProtection.CloneDeep(); } else pwImp = pwDatabase; if(fmtImp.RequiresKey && !bSynchronize) { KeyPromptForm kpf = new KeyPromptForm(); kpf.InitEx(iocIn.GetDisplayName(), false); if(kpf.ShowDialog() != DialogResult.OK) { s.Close(); continue; } pwImp.MasterKey = kpf.CompositeKey; } else if(bSynchronize) pwImp.MasterKey = pwDatabase.MasterKey; slf.SetText((bSynchronize ? KPRes.Synchronizing : KPRes.ImportingStatusMsg) + " " + iocIn.GetDisplayName(), LogStatusType.Info); try { fmtImp.Import(pwImp, s, slf); } catch(Exception excpFmt) { string strMsgEx = excpFmt.Message; if(bSynchronize) { strMsgEx += MessageService.NewParagraph + KPRes.SynchronizingHint; } MessageService.ShowWarning(strMsgEx); s.Close(); bAllSuccess = false; continue; } s.Close(); if(bUseTempDb) { PwMergeMethod mm; if(!fmtImp.SupportsUuids) mm = PwMergeMethod.CreateNewUuids; else if(bSynchronize) mm = PwMergeMethod.Synchronize; else { ImportMethodForm imf = new ImportMethodForm(); if(imf.ShowDialog() != DialogResult.OK) continue; mm = imf.MergeMethod; } slf.SetText(KPRes.MergingData, LogStatusType.Info); try { pwDatabase.MergeIn(pwImp, mm); } catch(Exception exMerge) { MessageService.ShowWarning(iocIn.GetDisplayName(), KPRes.ImportFailed, exMerge); bAllSuccess = false; continue; } } } slf.EndLogging(); slf.Close(); if(bSynchronize && bAllSuccess) { Debug.Assert(uiOps != null); if(uiOps == null) throw new ArgumentNullException("uiOps"); if(uiOps.UIFileSave(bForceSave)) { foreach(IOConnectionInfo ioc in vConnections) { try { if(pwDatabase.IOConnectionInfo.IsLocalFile()) { if((pwDatabase.IOConnectionInfo.Path != ioc.Path) && ioc.IsLocalFile()) { File.Copy(pwDatabase.IOConnectionInfo.Path, ioc.Path, true); } } else pwDatabase.SaveAs(ioc, false, null); } catch(Exception exSync) { MessageService.ShowWarning(KPRes.SyncFailed, pwDatabase.IOConnectionInfo.GetDisplayName() + MessageService.NewLine + ioc.GetDisplayName(), exSync); bAllSuccess = false; continue; } } } else { MessageService.ShowWarning(KPRes.SyncFailed, pwDatabase.IOConnectionInfo.GetDisplayName()); bAllSuccess = false; } } else if(bSynchronize) // Synchronized but not successfully imported { MessageService.ShowWarning(KPRes.SyncFailed, pwDatabase.IOConnectionInfo.GetDisplayName()); bAllSuccess = false; } return bAllSuccess; }
public static bool? Import(PwDatabase pwDatabase, FileFormatProvider fmtImp, IOConnectionInfo[] vConnections, bool bSynchronize, IUIOperations uiOps, bool bForceSave, Form fParent) { if(pwDatabase == null) throw new ArgumentNullException("pwDatabase"); if(!pwDatabase.IsOpen) return null; if(fmtImp == null) throw new ArgumentNullException("fmtImp"); if(vConnections == null) throw new ArgumentNullException("vConnections"); if(!AppPolicy.Try(AppPolicyId.Import)) return false; if(!fmtImp.TryBeginImport()) return false; bool bUseTempDb = (fmtImp.SupportsUuids || fmtImp.RequiresKey); bool bAllSuccess = true; // if(bSynchronize) { Debug.Assert(vFiles.Length == 1); } IStatusLogger dlgStatus; if(Program.Config.UI.ShowImportStatusDialog) dlgStatus = new OnDemandStatusDialog(false, fParent); else dlgStatus = new UIBlockerStatusLogger(fParent); dlgStatus.StartLogging(PwDefs.ShortProductName + " - " + (bSynchronize ? KPRes.Synchronizing : KPRes.ImportingStatusMsg), false); dlgStatus.SetText(bSynchronize ? KPRes.Synchronizing : KPRes.ImportingStatusMsg, LogStatusType.Info); if(vConnections.Length == 0) { try { fmtImp.Import(pwDatabase, null, dlgStatus); } catch(Exception exSingular) { if((exSingular.Message != null) && (exSingular.Message.Length > 0)) { // slf.SetText(exSingular.Message, LogStatusType.Warning); MessageService.ShowWarning(exSingular); } } dlgStatus.EndLogging(); return true; } foreach(IOConnectionInfo iocIn in vConnections) { Stream s = null; try { s = IOConnection.OpenRead(iocIn); } catch(Exception exFile) { // Transacted-file operations can leave behind intact *.kdbx.tmp files when // the file rename doesn't get completed (can happen easily with slow/unreliable // remote collections. We check if that's the case here and fix the situation if // an kdbx file does *not* exist (to avoid possibly overwriting good data with bad // data (i.e. an interrupted kdbx.tmp write). // Make a copy of the IOC like FileTransactionEx.cs:Initialize does IOConnectionInfo iocTemp = iocIn.CloneDeep(); iocTemp.Path += FileTransactionEx.StrTempSuffix; if (IOConnection.FileExists(iocTemp) && !IOConnection.FileExists(iocIn)) { // Try and rename iocTemp to ioc.Path, then retry file opening. IOConnection.RenameFile(iocTemp, iocIn); try { s = IOConnection.OpenRead(iocIn); } catch(Exception nexFile) { MessageService.ShowWarning(iocIn.GetDisplayName(), nexFile); bAllSuccess = false; continue; } } else { MessageService.ShowWarning(iocIn.GetDisplayName(), exFile); bAllSuccess = false; continue; } } if(s == null) { Debug.Assert(false); bAllSuccess = false; continue; } PwDatabase pwImp; if(bUseTempDb) { pwImp = new PwDatabase(); pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey); pwImp.MemoryProtection = pwDatabase.MemoryProtection.CloneDeep(); } else pwImp = pwDatabase; if(fmtImp.RequiresKey && !bSynchronize) { KeyPromptForm kpf = new KeyPromptForm(); kpf.InitEx(iocIn, false, true); if(UIUtil.ShowDialogNotValue(kpf, DialogResult.OK)) { s.Close(); continue; } pwImp.MasterKey = kpf.CompositeKey; UIUtil.DestroyForm(kpf); } else if(bSynchronize) pwImp.MasterKey = pwDatabase.MasterKey; dlgStatus.SetText((bSynchronize ? KPRes.Synchronizing : KPRes.ImportingStatusMsg) + " (" + iocIn.GetDisplayName() + ")", LogStatusType.Info); try { fmtImp.Import(pwImp, s, dlgStatus); } catch(Exception excpFmt) { string strMsgEx = excpFmt.Message; if(bSynchronize && (excpFmt is InvalidCompositeKeyException)) strMsgEx = KLRes.InvalidCompositeKey + MessageService.NewParagraph + KPRes.SynchronizingHint; MessageService.ShowWarning(strMsgEx); s.Close(); bAllSuccess = false; continue; } s.Close(); if(bUseTempDb) { PwMergeMethod mm; if(!fmtImp.SupportsUuids) mm = PwMergeMethod.CreateNewUuids; else if(bSynchronize) mm = PwMergeMethod.Synchronize; else { ImportMethodForm imf = new ImportMethodForm(); if(UIUtil.ShowDialogNotValue(imf, DialogResult.OK)) continue; mm = imf.MergeMethod; UIUtil.DestroyForm(imf); } try { pwDatabase.MergeIn(pwImp, mm, dlgStatus); } catch(Exception exMerge) { MessageService.ShowWarning(iocIn.GetDisplayName(), KPRes.ImportFailed, exMerge); bAllSuccess = false; continue; } } } if(bSynchronize && bAllSuccess) { Debug.Assert(uiOps != null); if(uiOps == null) throw new ArgumentNullException("uiOps"); dlgStatus.SetText(KPRes.Synchronizing + " (" + KPRes.SavingDatabase + ")", LogStatusType.Info); MainForm mf = Program.MainForm; // Null for KPScript if(mf != null) { try { mf.DocumentManager.ActiveDatabase = pwDatabase; } catch(Exception) { Debug.Assert(false); } } if(uiOps.UIFileSave(bForceSave)) { foreach(IOConnectionInfo ioc in vConnections) { try { // dlgStatus.SetText(KPRes.Synchronizing + " (" + // KPRes.SavingDatabase + " " + ioc.GetDisplayName() + // ")", LogStatusType.Info); if(ioc.Path != pwDatabase.IOConnectionInfo.Path) { if(pwDatabase.IOConnectionInfo.IsLocalFile() && ioc.IsLocalFile()) { File.Copy(pwDatabase.IOConnectionInfo.Path, ioc.Path, true); } else pwDatabase.SaveAs(ioc, false, null); } // else { } // No assert (sync on save) if(mf != null) mf.FileMruList.AddItem(ioc.GetDisplayName(), ioc.CloneDeep()); } catch(Exception exSync) { MessageService.ShowWarning(KPRes.SyncFailed, pwDatabase.IOConnectionInfo.GetDisplayName() + MessageService.NewLine + ioc.GetDisplayName(), exSync); bAllSuccess = false; continue; } } } else { MessageService.ShowWarning(KPRes.SyncFailed, pwDatabase.IOConnectionInfo.GetDisplayName()); bAllSuccess = false; } } dlgStatus.EndLogging(); return bAllSuccess; }