/// <summary> /// Deserializes this node by using the <see cref="KdbxMetadata"/> binary collection /// to dereference @Ref. /// </summary> /// <param name="xml"></param> /// <param name="metadata">Used to dereference the Ref attribute.</param> /// <param name="parameters"></param> public KdbxBinAttachment(XElement xml, KdbxMetadata metadata, KdbxSerializationParameters parameters) : base(xml) { FileName = GetString("Key", true); XElement valueNode = GetNode("Value"); if (valueNode == null) { throw new KdbxParseException( ReaderResult.FromXmlParseFailure($"Node {rootName} missing required child Value") ); } int refId; string refAttr = valueNode.Attribute("Ref")?.Value; if (refAttr == null || !int.TryParse(refAttr, out refId)) { throw new KdbxParseException( ReaderResult.FromXmlParseFailure($"Child Value node of {rootName} missing required int @Ref") ); } Data = metadata.Binaries.GetById(refId); this.binaryCollection = metadata.Binaries; }
public KdbxEntry(IKeePassGroup parent, IRandomNumberGenerator rng, KdbxMetadata metadata) : this(false) { DebugHelper.Assert(parent != null); DebugHelper.Assert(rng != null); if (rng == null) { throw new ArgumentNullException("rng"); } DebugHelper.Assert(metadata != null); if (metadata == null) { throw new ArgumentNullException("metadata"); } Parent = parent ?? throw new ArgumentNullException("parent"); Uuid = new KeePassUuid(); IconID = KdbxEntry.DefaultIconId; Times = new KdbxTimes(); History = new KdbxHistory(metadata); KdbxMemoryProtection memProtection = metadata.MemoryProtection; Title = new KdbxString("Title", string.Empty, rng, memProtection.ProtectTitle); string initialUsername = metadata.DefaultUserName ?? string.Empty; UserName = new KdbxString("UserName", initialUsername, rng, memProtection.ProtectUserName); Password = new KdbxString("Password", string.Empty, rng, memProtection.ProtectPassword); Url = new KdbxString("URL", string.Empty, rng, memProtection.ProtectUrl); Notes = new KdbxString("Notes", string.Empty, rng, memProtection.ProtectNotes); Tags = string.Empty; OverrideUrl = string.Empty; this._metadata = metadata; }
/// <summary> /// Parses a KeePass document from the specified XML. /// </summary> /// <param name="xml">XML to deserialize.</param> /// <param name="headerBinaries">Any binaries that were parsed from a header.</param> /// <param name="rng">RNG used to encrypt protected strings.</param> /// <param name="parameters">Parameters controlling serialization.</param> public KdbxDocument(XElement xml, IEnumerable <ProtectedBinary> headerBinaries, IRandomNumberGenerator rng, KdbxSerializationParameters parameters) : base(xml) { XElement metadata = GetNode(KdbxMetadata.RootName); if (metadata == null) { throw new KdbxParseException( ReaderResult.FromXmlParseFailure($"Document has no {KdbxMetadata.RootName} node") ); } Metadata = new KdbxMetadata(metadata, headerBinaries, parameters); XElement root = GetNode(KdbxRoot.RootName); if (root == null) { throw new KdbxParseException( ReaderResult.FromXmlParseFailure($"Document has no {KdbxRoot.RootName} node") ); } Root = new KdbxRoot(root, rng, Metadata, parameters); }
public KdbxGroup(XElement xml, IKeePassGroup parent, IRandomNumberGenerator rng, KdbxMetadata metadata, KdbxSerializationParameters parameters) : base(xml, parameters) { InitializeCollections(); Parent = parent; Title = new KdbxString("Name", GetString("Name"), null); Notes = new KdbxString("Notes", GetString("Notes"), null); IsExpanded = GetBool("IsExpanded"); DefaultAutoTypeSequence = GetString("DefaultAutoTypeSequence"); EnableAutoType = GetNullableBool("EnableAutoType"); EnableSearching = GetNullableBool("EnableSearching"); LastTopVisibleEntry = GetUuid("LastTopVisibleEntry", false) ?? KeePassUuid.Empty; // The order in which we deserialize entries and groups matters. // They must be constructed in the order that they appear in the XML, // or the RNG will enter undefined territory. ForgetNodes(KdbxEntry.RootName); ForgetNodes(KdbxGroup.RootName); // First, we need to select each XElement that represents either a group or an entry. // From these, we construct KdbxEntries and KdbxGroups. // Then we sort them, groups first, and add them to the child collection. IEnumerable <IKeePassNode> nodes = xml.Elements() .Where(element => element.Name == KdbxEntry.RootName || element.Name == KdbxGroup.RootName) .Select( matchedElement => { if (matchedElement.Name == KdbxEntry.RootName) { return(new KdbxEntry(matchedElement, this, rng, metadata, parameters) as IKeePassNode); } else { return(new KdbxGroup(matchedElement, this, rng, metadata, parameters) as IKeePassNode); } } ) .OrderBy( node => node is IKeePassGroup, Comparer <bool> .Create((b1, b2) => b1.CompareTo(b2)) ); foreach (IKeePassNode node in nodes) { this._children.Add(node); } }
public KdbxRoot(XElement xml, IRandomNumberGenerator rng, KdbxMetadata metadata, KdbxSerializationParameters parameters) : base(xml) { DatabaseGroup = new KdbxGroup(GetNode(KdbxGroup.RootName), null, rng, metadata, parameters); this.deletedObjs = GetNode("DeletedObjects"); }
public override bool Equals(object obj) { KdbxMetadata other = obj as KdbxMetadata; if (other == null) { return(false); } if (Generator != other.Generator) { return(false); } if (DatabaseName != other.DatabaseName || DatabaseDescription != other.DatabaseDescription) { return(false); } if (DatabaseNameChanged != other.DatabaseNameChanged || DatabaseDescriptionChanged != other.DatabaseDescriptionChanged) { return(false); } if (DefaultUserName != other.DefaultUserName || DefaultUserNameChanged != other.DefaultUserNameChanged) { return(false); } if (MaintenanceHistoryDays != other.MaintenanceHistoryDays) { return(false); } if (DbColor != other.DbColor) { return(false); } if (MasterKeyChanged != other.MasterKeyChanged || MasterKeyChangeRec != other.MasterKeyChangeRec || MasterKeyChangeForce != other.MasterKeyChangeForce) { return(false); } if (!MemoryProtection.Equals(other.MemoryProtection)) { return(false); } if (CustomIcons != null) { if (!CustomIcons.Equals(other.CustomIcons)) { return(false); } } else { if (other.CustomIcons != null) { return(false); } } if (RecycleBinEnabled != other.RecycleBinEnabled || !RecycleBinUuid.Equals(other.RecycleBinUuid) || RecycleBinChanged != other.RecycleBinChanged) { return(false); } if (!EntryTemplatesGroup.Equals(other.EntryTemplatesGroup) || EntryTemplatesGroupChanged != other.EntryTemplatesGroupChanged) { return(false); } if (HistoryMaxItems != other.HistoryMaxItems || HistoryMaxSize != other.HistoryMaxSize) { return(false); } if (!LastSelectedGroup.Equals(other.LastSelectedGroup) || !LastTopVisibleGroup.Equals(other.LastTopVisibleGroup)) { return(false); } if (Binaries != null) { if (!Binaries.Equals(other.Binaries)) { return(false); } } else { if (other.Binaries != null) { return(false); } } if (CustomData != null) { if (!CustomData.Equals(other.CustomData)) { return(false); } } else { if (other.CustomData != null) { return(false); } } return(true); }
/// <summary> /// Initializes an empty document with provided metadata. /// </summary> /// <param name="metadata"></param> public KdbxDocument(KdbxMetadata metadata) { Metadata = metadata; Root = new KdbxRoot(); }
public KdbxEntry(XElement xml, IKeePassGroup parent, IRandomNumberGenerator rng, KdbxMetadata metadata, KdbxSerializationParameters parameters) : base(xml, parameters) { Parent = parent; ForegroundColor = GetNullableColor("ForegroundColor"); BackgroundColor = GetNullableColor("BackgroundColor"); OverrideUrl = GetString("OverrideURL") ?? string.Empty; Tags = GetString("Tags") ?? string.Empty; Fields = new ObservableCollection <IProtectedString>(); IEnumerable <KdbxString> strings = GetNodes(KdbxString.RootName) .Select(x => new KdbxString(x, rng)); foreach (KdbxString s in strings) { switch (s.Key) { case "Notes": Notes = s; break; case "Password": Password = s; break; case "Title": Title = s; break; case "URL": Url = s; break; case "UserName": UserName = s; break; default: Fields.Add(s); break; } } KdbxMemoryProtection memProtection = metadata.MemoryProtection; if (Password == null) { Password = new KdbxString("Password", string.Empty, rng, memProtection.ProtectPassword); } if (Title == null) { Title = new KdbxString("Title", string.Empty, rng, memProtection.ProtectTitle); } if (Url == null) { Url = new KdbxString("URL", string.Empty, rng, memProtection.ProtectUrl); } if (UserName == null) { UserName = new KdbxString("UserName", string.Empty, rng, memProtection.ProtectUserName); } if (Notes == null) { Notes = new KdbxString("Notes", string.Empty, rng, memProtection.ProtectNotes); } IEnumerable <KdbxBinAttachment> binNodes = GetNodes(KdbxBinAttachment.RootName).Select(x => new KdbxBinAttachment(x, metadata, parameters)); Binaries = new ObservableCollection <IKeePassBinAttachment>(binNodes); XElement autoTypeNode = GetNode(KdbxAutoType.RootName); if (autoTypeNode != null) { AutoType = new KdbxAutoType(autoTypeNode); } XElement historyElement = GetNode(KdbxHistory.RootName); if (historyElement != null) { History = new KdbxHistory(historyElement, rng, metadata, parameters); } else { History = new KdbxHistory(metadata); } this._metadata = metadata; }
/// <summary> /// Helper that deserializes an entry as a history entry (no parent). /// </summary> /// <param name="xml"></param> /// <param name="rng"></param> /// <param name="metadata"></param> /// <param name="parameters"></param> public KdbxEntry(XElement xml, IRandomNumberGenerator rng, KdbxMetadata metadata, KdbxSerializationParameters parameters) : this(xml, null, rng, metadata, parameters) { this.isHistoryEntry = true; History = null; }