Ejemplo n.º 1
0
 private static KdbContext SwitchContext(KdbContext ctxCurrent,
                                         KdbContext ctxNew, XmlReader xr)
 {
     if (xr.IsEmptyElement)
     {
         return(ctxCurrent);
     }
     return(ctxNew);
 }
Ejemplo n.º 2
0
        private KdbContext EndXmlElement(KdbContext ctx, XmlReader xr)
        {
            Debug.Assert(xr.NodeType == XmlNodeType.EndElement);

            if ((ctx == KdbContext.KeePassFile) && (xr.Name == ElemDocNode))
            {
                return(KdbContext.Null);
            }
            else if ((ctx == KdbContext.Meta) && (xr.Name == ElemMeta))
            {
                return(KdbContext.KeePassFile);
            }
            else if ((ctx == KdbContext.Root) && (xr.Name == ElemRoot))
            {
                return(KdbContext.KeePassFile);
            }
            else if ((ctx == KdbContext.MemoryProtection) && (xr.Name == ElemMemoryProt))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomIcons) && (xr.Name == ElemCustomIcons))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomIcon) && (xr.Name == ElemCustomIconItem))
            {
                if (!m_uuidCustomIconID.Equals(PwUuid.Zero) &&
                    (m_pbCustomIconData != null))
                {
                    m_pwDatabase.CustomIcons.Add(new PwCustomIcon(
                                                     m_uuidCustomIconID, m_pbCustomIconData));
                }
                else
                {
                    Debug.Assert(false);
                }

                m_uuidCustomIconID = PwUuid.Zero;
                m_pbCustomIconData = null;

                return(KdbContext.CustomIcons);
            }
            else if ((ctx == KdbContext.Binaries) && (xr.Name == ElemBinaries))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomData) && (xr.Name == ElemCustomData))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomDataItem) && (xr.Name == ElemStringDictExItem))
            {
                if ((m_strCustomDataKey != null) && (m_strCustomDataValue != null))
                {
                    m_pwDatabase.CustomData.Set(m_strCustomDataKey, m_strCustomDataValue);
                }
                else
                {
                    Debug.Assert(false);
                }

                m_strCustomDataKey   = null;
                m_strCustomDataValue = null;

                return(KdbContext.CustomData);
            }
            else if ((ctx == KdbContext.Group) && (xr.Name == ElemGroup))
            {
                if (PwUuid.Zero.Equals(m_ctxGroup.Uuid))
                {
                    m_ctxGroup.Uuid = new PwUuid(true);                     // No assert (import)
                }
                m_ctxGroups.Pop();

                if (m_ctxGroups.Count == 0)
                {
                    m_ctxGroup = null;
                    return(KdbContext.Root);
                }
                else
                {
                    m_ctxGroup = m_ctxGroups.Peek();
                    return(KdbContext.Group);
                }
            }
            else if ((ctx == KdbContext.GroupTimes) && (xr.Name == ElemTimes))
            {
                return(KdbContext.Group);
            }
            else if ((ctx == KdbContext.GroupCustomData) && (xr.Name == ElemCustomData))
            {
                return(KdbContext.Group);
            }
            else if ((ctx == KdbContext.GroupCustomDataItem) && (xr.Name == ElemStringDictExItem))
            {
                if ((m_strGroupCustomDataKey != null) && (m_strGroupCustomDataValue != null))
                {
                    m_ctxGroup.CustomData.Set(m_strGroupCustomDataKey, m_strGroupCustomDataValue);
                }
                else
                {
                    Debug.Assert(false);
                }

                m_strGroupCustomDataKey   = null;
                m_strGroupCustomDataValue = null;

                return(KdbContext.GroupCustomData);
            }
            else if ((ctx == KdbContext.Entry) && (xr.Name == ElemEntry))
            {
                // Create new UUID if absent
                if (PwUuid.Zero.Equals(m_ctxEntry.Uuid))
                {
                    m_ctxEntry.Uuid = new PwUuid(true);                     // No assert (import)
                }
                if (m_bEntryInHistory)
                {
                    m_ctxEntry = m_ctxHistoryBase;
                    return(KdbContext.EntryHistory);
                }

                return(KdbContext.Group);
            }
            else if ((ctx == KdbContext.EntryTimes) && (xr.Name == ElemTimes))
            {
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryString) && (xr.Name == ElemString))
            {
                m_ctxEntry.Strings.Set(m_ctxStringName, m_ctxStringValue);
                m_ctxStringName  = null;
                m_ctxStringValue = null;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryBinary) && (xr.Name == ElemBinary))
            {
                if (string.IsNullOrEmpty(m_strDetachBins))
                {
                    m_ctxEntry.Binaries.Set(m_ctxBinaryName, m_ctxBinaryValue);
                }
                else
                {
                    SaveBinary(m_ctxBinaryName, m_ctxBinaryValue, m_strDetachBins);

                    m_ctxBinaryValue = null;
                    GC.Collect();
                }

                m_ctxBinaryName  = null;
                m_ctxBinaryValue = null;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryAutoType) && (xr.Name == ElemAutoType))
            {
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryAutoTypeItem) && (xr.Name == ElemAutoTypeItem))
            {
                AutoTypeAssociation atAssoc = new AutoTypeAssociation(m_ctxATName,
                                                                      m_ctxATSeq);
                m_ctxEntry.AutoType.Add(atAssoc);
                m_ctxATName = null;
                m_ctxATSeq  = null;
                return(KdbContext.EntryAutoType);
            }
            else if ((ctx == KdbContext.EntryCustomData) && (xr.Name == ElemCustomData))
            {
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryCustomDataItem) && (xr.Name == ElemStringDictExItem))
            {
                if ((m_strEntryCustomDataKey != null) && (m_strEntryCustomDataValue != null))
                {
                    m_ctxEntry.CustomData.Set(m_strEntryCustomDataKey, m_strEntryCustomDataValue);
                }
                else
                {
                    Debug.Assert(false);
                }

                m_strEntryCustomDataKey   = null;
                m_strEntryCustomDataValue = null;

                return(KdbContext.EntryCustomData);
            }
            else if ((ctx == KdbContext.EntryHistory) && (xr.Name == ElemHistory))
            {
                m_bEntryInHistory = false;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.RootDeletedObjects) && (xr.Name == ElemDeletedObjects))
            {
                return(KdbContext.Root);
            }
            else if ((ctx == KdbContext.DeletedObject) && (xr.Name == ElemDeletedObject))
            {
                m_ctxDeletedObject = null;
                return(KdbContext.RootDeletedObjects);
            }
            else
            {
                Debug.Assert(false);
                throw new FormatException();
            }
        }
Ejemplo n.º 3
0
        private KdbContext ReadXmlElement(KdbContext ctx, XmlReader xr)
        {
            Debug.Assert(xr.NodeType == XmlNodeType.Element);

            switch (ctx)
            {
            case KdbContext.Null:
                if (xr.Name == ElemDocNode)
                {
                    return(SwitchContext(ctx, KdbContext.KeePassFile, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.KeePassFile:
                if (xr.Name == ElemMeta)
                {
                    return(SwitchContext(ctx, KdbContext.Meta, xr));
                }
                else if (xr.Name == ElemRoot)
                {
                    return(SwitchContext(ctx, KdbContext.Root, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Meta:
                if (xr.Name == ElemGenerator)
                {
                    ReadString(xr);                             // Ignore
                }
                else if (xr.Name == ElemHeaderHash)
                {
                    // The header hash is typically only stored in
                    // KDBX <= 3.1 files, not in KDBX >= 4 files
                    // (here, the header is verified via a HMAC),
                    // but we also support it for KDBX >= 4 files
                    // (i.e. if it's present, we check it)

                    string strHash = ReadString(xr);
                    if (!string.IsNullOrEmpty(strHash) && (m_pbHashOfHeader != null) &&
                        !m_bRepairMode)
                    {
                        Debug.Assert(m_uFileVersion < FileVersion32_4);

                        byte[] pbHash = Convert.FromBase64String(strHash);
                        if (!MemUtil.ArraysEqual(pbHash, m_pbHashOfHeader))
                        {
                            throw new InvalidDataException(KLRes.FileCorrupted);
                        }
                    }
                }
                else if (xr.Name == ElemSettingsChanged)
                {
                    m_pwDatabase.SettingsChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbName)
                {
                    m_pwDatabase.Name = ReadString(xr);
                }
                else if (xr.Name == ElemDbNameChanged)
                {
                    m_pwDatabase.NameChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbDesc)
                {
                    m_pwDatabase.Description = ReadString(xr);
                }
                else if (xr.Name == ElemDbDescChanged)
                {
                    m_pwDatabase.DescriptionChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbDefaultUser)
                {
                    m_pwDatabase.DefaultUserName = ReadString(xr);
                }
                else if (xr.Name == ElemDbDefaultUserChanged)
                {
                    m_pwDatabase.DefaultUserNameChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbMntncHistoryDays)
                {
                    m_pwDatabase.MaintenanceHistoryDays = ReadUInt(xr, 365);
                }
                else if (xr.Name == ElemDbColor)
                {
                    string strColor = ReadString(xr);
                    if (!string.IsNullOrEmpty(strColor))
                    {
                        if (strColor.StartsWith("#"))
                        {
                            m_pwDatabase.Color = Color.FromArgb(0xFF, Color.FromArgb(
                                                                    Convert.ToInt32(strColor.Substring(1), 16)));
                        }
                        else
                        {
                            m_pwDatabase.Color = Color.FromName(strColor);
                        }
                    }
                }
                else if (xr.Name == ElemDbKeyChanged)
                {
                    m_pwDatabase.MasterKeyChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbKeyChangeRec)
                {
                    m_pwDatabase.MasterKeyChangeRec = ReadLong(xr, -1);
                }
                else if (xr.Name == ElemDbKeyChangeForce)
                {
                    m_pwDatabase.MasterKeyChangeForce = ReadLong(xr, -1);
                }
                else if (xr.Name == ElemDbKeyChangeForceOnce)
                {
                    m_pwDatabase.MasterKeyChangeForceOnce = ReadBool(xr, false);
                }
                else if (xr.Name == ElemMemoryProt)
                {
                    return(SwitchContext(ctx, KdbContext.MemoryProtection, xr));
                }
                else if (xr.Name == ElemCustomIcons)
                {
                    return(SwitchContext(ctx, KdbContext.CustomIcons, xr));
                }
                else if (xr.Name == ElemRecycleBinEnabled)
                {
                    m_pwDatabase.RecycleBinEnabled = ReadBool(xr, true);
                }
                else if (xr.Name == ElemRecycleBinUuid)
                {
                    m_pwDatabase.RecycleBinUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemRecycleBinChanged)
                {
                    m_pwDatabase.RecycleBinChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemEntryTemplatesGroup)
                {
                    m_pwDatabase.EntryTemplatesGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemEntryTemplatesGroupChanged)
                {
                    m_pwDatabase.EntryTemplatesGroupChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemHistoryMaxItems)
                {
                    m_pwDatabase.HistoryMaxItems = ReadInt(xr, -1);
                }
                else if (xr.Name == ElemHistoryMaxSize)
                {
                    m_pwDatabase.HistoryMaxSize = ReadLong(xr, -1);
                }
                else if (xr.Name == ElemLastSelectedGroup)
                {
                    m_pwDatabase.LastSelectedGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemLastTopVisibleGroup)
                {
                    m_pwDatabase.LastTopVisibleGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemBinaries)
                {
                    return(SwitchContext(ctx, KdbContext.Binaries, xr));
                }
                else if (xr.Name == ElemCustomData)
                {
                    return(SwitchContext(ctx, KdbContext.CustomData, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.MemoryProtection:
                if (xr.Name == ElemProtTitle)
                {
                    m_pwDatabase.MemoryProtection.ProtectTitle = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtUserName)
                {
                    m_pwDatabase.MemoryProtection.ProtectUserName = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtPassword)
                {
                    m_pwDatabase.MemoryProtection.ProtectPassword = ReadBool(xr, true);
                }
                else if (xr.Name == ElemProtUrl)
                {
                    m_pwDatabase.MemoryProtection.ProtectUrl = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtNotes)
                {
                    m_pwDatabase.MemoryProtection.ProtectNotes = ReadBool(xr, false);
                }
                // else if(xr.Name == ElemProtAutoHide)
                //	m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = ReadBool(xr, true);
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomIcons:
                if (xr.Name == ElemCustomIconItem)
                {
                    return(SwitchContext(ctx, KdbContext.CustomIcon, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomIcon:
                if (xr.Name == ElemCustomIconItemID)
                {
                    m_uuidCustomIconID = ReadUuid(xr);
                }
                else if (xr.Name == ElemCustomIconItemData)
                {
                    string strData = ReadString(xr);
                    if (!string.IsNullOrEmpty(strData))
                    {
                        m_pbCustomIconData = Convert.FromBase64String(strData);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Binaries:
                if (xr.Name == ElemBinary)
                {
                    if (xr.MoveToAttribute(AttrId))
                    {
                        string          strKey = xr.Value;
                        ProtectedBinary pbData = ReadProtectedBinary(xr);

                        int iKey;
                        if (!StrUtil.TryParseIntInvariant(strKey, out iKey))
                        {
                            throw new FormatException();
                        }
                        if (iKey < 0)
                        {
                            throw new FormatException();
                        }

                        Debug.Assert(m_pbsBinaries.Get(iKey) == null);
                        Debug.Assert(m_pbsBinaries.Find(pbData) < 0);
                        m_pbsBinaries.Set(iKey, pbData);
                    }
                    else
                    {
                        ReadUnknown(xr);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomData:
                if (xr.Name == ElemStringDictExItem)
                {
                    return(SwitchContext(ctx, KdbContext.CustomDataItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomDataItem:
                if (xr.Name == ElemKey)
                {
                    m_strCustomDataKey = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_strCustomDataValue = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Root:
                if (xr.Name == ElemGroup)
                {
                    Debug.Assert(m_ctxGroups.Count == 0);
                    if (m_ctxGroups.Count != 0)
                    {
                        throw new FormatException();
                    }

                    m_pwDatabase.RootGroup = new PwGroup(false, false);
                    m_ctxGroups.Push(m_pwDatabase.RootGroup);
                    m_ctxGroup = m_ctxGroups.Peek();

                    return(SwitchContext(ctx, KdbContext.Group, xr));
                }
                else if (xr.Name == ElemDeletedObjects)
                {
                    return(SwitchContext(ctx, KdbContext.RootDeletedObjects, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Group:
                if (xr.Name == ElemUuid)
                {
                    m_ctxGroup.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemName)
                {
                    m_ctxGroup.Name = ReadString(xr);
                }
                else if (xr.Name == ElemNotes)
                {
                    m_ctxGroup.Notes = ReadString(xr);
                }
                else if (xr.Name == ElemIcon)
                {
                    m_ctxGroup.IconId = ReadIconId(xr, PwIcon.Folder);
                }
                else if (xr.Name == ElemCustomIconID)
                {
                    m_ctxGroup.CustomIconUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemTimes)
                {
                    return(SwitchContext(ctx, KdbContext.GroupTimes, xr));
                }
                else if (xr.Name == ElemIsExpanded)
                {
                    m_ctxGroup.IsExpanded = ReadBool(xr, true);
                }
                else if (xr.Name == ElemGroupDefaultAutoTypeSeq)
                {
                    m_ctxGroup.DefaultAutoTypeSequence = ReadString(xr);
                }
                else if (xr.Name == ElemEnableAutoType)
                {
                    m_ctxGroup.EnableAutoType = StrUtil.StringToBoolEx(ReadString(xr));
                }
                else if (xr.Name == ElemEnableSearching)
                {
                    m_ctxGroup.EnableSearching = StrUtil.StringToBoolEx(ReadString(xr));
                }
                else if (xr.Name == ElemLastTopVisibleEntry)
                {
                    m_ctxGroup.LastTopVisibleEntry = ReadUuid(xr);
                }
                else if (xr.Name == ElemCustomData)
                {
                    return(SwitchContext(ctx, KdbContext.GroupCustomData, xr));
                }
                else if (xr.Name == ElemGroup)
                {
                    m_ctxGroup = new PwGroup(false, false);
                    m_ctxGroups.Peek().AddGroup(m_ctxGroup, true);

                    m_ctxGroups.Push(m_ctxGroup);

                    return(SwitchContext(ctx, KdbContext.Group, xr));
                }
                else if (xr.Name == ElemEntry)
                {
                    m_ctxEntry = new PwEntry(false, false);
                    m_ctxGroup.AddEntry(m_ctxEntry, true);

                    m_bEntryInHistory = false;
                    return(SwitchContext(ctx, KdbContext.Entry, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.GroupCustomData:
                if (xr.Name == ElemStringDictExItem)
                {
                    return(SwitchContext(ctx, KdbContext.GroupCustomDataItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.GroupCustomDataItem:
                if (xr.Name == ElemKey)
                {
                    m_strGroupCustomDataKey = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_strGroupCustomDataValue = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Entry:
                if (xr.Name == ElemUuid)
                {
                    m_ctxEntry.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemIcon)
                {
                    m_ctxEntry.IconId = ReadIconId(xr, PwIcon.Key);
                }
                else if (xr.Name == ElemCustomIconID)
                {
                    m_ctxEntry.CustomIconUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemFgColor)
                {
                    string strColor = ReadString(xr);
                    if (!string.IsNullOrEmpty(strColor))
                    {
                        m_ctxEntry.ForegroundColor = Color.FromName(strColor);
                    }
                }
                else if (xr.Name == ElemBgColor)
                {
                    string strColor = ReadString(xr);
                    if (!string.IsNullOrEmpty(strColor))
                    {
                        m_ctxEntry.BackgroundColor = Color.FromName(strColor);
                    }
                }
                else if (xr.Name == ElemOverrideUrl)
                {
                    m_ctxEntry.OverrideUrl = ReadString(xr);
                }
                else if (xr.Name == ElemTags)
                {
                    m_ctxEntry.Tags = StrUtil.StringToTags(ReadString(xr));
                }
                else if (xr.Name == ElemTimes)
                {
                    return(SwitchContext(ctx, KdbContext.EntryTimes, xr));
                }
                else if (xr.Name == ElemString)
                {
                    return(SwitchContext(ctx, KdbContext.EntryString, xr));
                }
                else if (xr.Name == ElemBinary)
                {
                    return(SwitchContext(ctx, KdbContext.EntryBinary, xr));
                }
                else if (xr.Name == ElemAutoType)
                {
                    return(SwitchContext(ctx, KdbContext.EntryAutoType, xr));
                }
                else if (xr.Name == ElemCustomData)
                {
                    return(SwitchContext(ctx, KdbContext.EntryCustomData, xr));
                }
                else if (xr.Name == ElemHistory)
                {
                    Debug.Assert(m_bEntryInHistory == false);

                    if (m_bEntryInHistory == false)
                    {
                        m_ctxHistoryBase = m_ctxEntry;
                        return(SwitchContext(ctx, KdbContext.EntryHistory, xr));
                    }
                    else
                    {
                        ReadUnknown(xr);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.GroupTimes:
            case KdbContext.EntryTimes:
                ITimeLogger tl = ((ctx == KdbContext.GroupTimes) ?
                                  (ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry);
                Debug.Assert(tl != null);

                if (xr.Name == ElemCreationTime)
                {
                    tl.CreationTime = ReadTime(xr);
                }
                else if (xr.Name == ElemLastModTime)
                {
                    tl.LastModificationTime = ReadTime(xr);
                }
                else if (xr.Name == ElemLastAccessTime)
                {
                    tl.LastAccessTime = ReadTime(xr);
                }
                else if (xr.Name == ElemExpiryTime)
                {
                    tl.ExpiryTime = ReadTime(xr);
                }
                else if (xr.Name == ElemExpires)
                {
                    tl.Expires = ReadBool(xr, false);
                }
                else if (xr.Name == ElemUsageCount)
                {
                    tl.UsageCount = ReadULong(xr, 0);
                }
                else if (xr.Name == ElemLocationChanged)
                {
                    tl.LocationChanged = ReadTime(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryString:
                if (xr.Name == ElemKey)
                {
                    m_ctxStringName = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_ctxStringValue = ReadProtectedString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryBinary:
                if (xr.Name == ElemKey)
                {
                    m_ctxBinaryName = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_ctxBinaryValue = ReadProtectedBinary(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryAutoType:
                if (xr.Name == ElemAutoTypeEnabled)
                {
                    m_ctxEntry.AutoType.Enabled = ReadBool(xr, true);
                }
                else if (xr.Name == ElemAutoTypeObfuscation)
                {
                    m_ctxEntry.AutoType.ObfuscationOptions =
                        (AutoTypeObfuscationOptions)ReadInt(xr, 0);
                }
                else if (xr.Name == ElemAutoTypeDefaultSeq)
                {
                    m_ctxEntry.AutoType.DefaultSequence = ReadString(xr);
                }
                else if (xr.Name == ElemAutoTypeItem)
                {
                    return(SwitchContext(ctx, KdbContext.EntryAutoTypeItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryAutoTypeItem:
                if (xr.Name == ElemWindow)
                {
                    m_ctxATName = ReadString(xr);
                }
                else if (xr.Name == ElemKeystrokeSequence)
                {
                    m_ctxATSeq = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryCustomData:
                if (xr.Name == ElemStringDictExItem)
                {
                    return(SwitchContext(ctx, KdbContext.EntryCustomDataItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryCustomDataItem:
                if (xr.Name == ElemKey)
                {
                    m_strEntryCustomDataKey = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_strEntryCustomDataValue = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryHistory:
                if (xr.Name == ElemEntry)
                {
                    m_ctxEntry = new PwEntry(false, false);
                    m_ctxHistoryBase.History.Add(m_ctxEntry);

                    m_bEntryInHistory = true;
                    return(SwitchContext(ctx, KdbContext.Entry, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.RootDeletedObjects:
                if (xr.Name == ElemDeletedObject)
                {
                    m_ctxDeletedObject = new PwDeletedObject();
                    m_pwDatabase.DeletedObjects.Add(m_ctxDeletedObject);

                    return(SwitchContext(ctx, KdbContext.DeletedObject, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.DeletedObject:
                if (xr.Name == ElemUuid)
                {
                    m_ctxDeletedObject.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemDeletionTime)
                {
                    m_ctxDeletedObject.DeletionTime = ReadTime(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            default:
                ReadUnknown(xr);
                break;
            }

            return(ctx);
        }
Ejemplo n.º 4
0
        private void ReadDocumentStreamed(XmlReader xr, Stream sParentStream)
        {
            Debug.Assert(xr != null);
            if (xr == null)
            {
                throw new ArgumentNullException("xr");
            }

            m_ctxGroups.Clear();

            KdbContext ctx = KdbContext.Null;

            uint uTagCounter = 0;

            bool bSupportsStatus = (m_slLogger != null);
            long lStreamLength   = 1;

            try
            {
                sParentStream.Position.ToString();                 // Test Position support
                lStreamLength = sParentStream.Length;
            }
            catch (Exception) { bSupportsStatus = false; }
            if (lStreamLength <= 0)
            {
                Debug.Assert(false); lStreamLength = 1;
            }

            m_bReadNextNode = true;

            while (true)
            {
                if (m_bReadNextNode)
                {
                    if (!xr.Read())
                    {
                        break;
                    }
                }
                else
                {
                    m_bReadNextNode = true;
                }

                switch (xr.NodeType)
                {
                case XmlNodeType.Element:
                    ctx = ReadXmlElement(ctx, xr);
                    break;

                case XmlNodeType.EndElement:
                    ctx = EndXmlElement(ctx, xr);
                    break;

                case XmlNodeType.XmlDeclaration:
                    break;                             // Ignore

                default:
                    Debug.Assert(false);
                    break;
                }

                ++uTagCounter;
                if (((uTagCounter % 256) == 0) && bSupportsStatus)
                {
                    Debug.Assert(lStreamLength == sParentStream.Length);
                    uint uPct = (uint)((sParentStream.Position * 100) /
                                       lStreamLength);

                    // Clip percent value in case the stream reports incorrect
                    // position/length values (M120413)
                    if (uPct > 100)
                    {
                        Debug.Assert(false); uPct = 100;
                    }

                    m_slLogger.SetProgress(uPct);
                }
            }

            Debug.Assert(ctx == KdbContext.Null);
            if (ctx != KdbContext.Null)
            {
                throw new FormatException();
            }

            Debug.Assert(m_ctxGroups.Count == 0);
            if (m_ctxGroups.Count != 0)
            {
                throw new FormatException();
            }
        }
Ejemplo n.º 5
0
        internal void ReadDocumentStreamed(XmlReader xr, Stream sParentStream)
        {
            Debug.Assert(xr != null);
            if (xr == null)
            {
                throw new ArgumentNullException("xr");
            }

            m_ctxGroups.Clear();

            KdbContext ctx = KdbContext.Null;

            uint uTagCounter = 0;

            bool bSupportsStatus = (m_slLogger != null);

            try
            {
                sParentStream.Position.ToString();
                sParentStream.Length.ToString();
            }
            catch (Exception) { bSupportsStatus = false; }

            m_bReadNextNode = true;

            while (true)
            {
                if (m_bReadNextNode)
                {
                    if (!xr.Read())
                    {
                        break;
                    }
                }
                else
                {
                    m_bReadNextNode = true;
                }

                switch (xr.NodeType)
                {
                case XmlNodeType.Element:
                    ctx = ReadXmlElement(ctx, xr);
                    break;

                case XmlNodeType.EndElement:
                    ctx = EndXmlElement(ctx, xr);
                    break;

                case XmlNodeType.XmlDeclaration:
                    break;                             // Ignore

                default:
                    Debug.Assert(false);
                    break;
                }

                ++uTagCounter;
                if (((uTagCounter % 256) == 0) && bSupportsStatus)
                {
                    m_slLogger.SetProgress((uint)((sParentStream.Position * 100) /
                                                  sParentStream.Length));
                }
            }

            Debug.Assert(ctx == KdbContext.Null);
            if (ctx != KdbContext.Null)
            {
                throw new FormatException();
            }

            Debug.Assert(m_ctxGroups.Count == 0);
            if (m_ctxGroups.Count != 0)
            {
                throw new FormatException();
            }
        }
Ejemplo n.º 6
0
        internal KdbContext ReadXmlElement(KdbContext ctx, XmlReader xr)
        {
            Debug.Assert(xr.NodeType == XmlNodeType.Element);

            switch (ctx)
            {
            case KdbContext.Null:
                if (xr.Name == ElemDocNode)
                {
                    return(SwitchContext(ctx, KdbContext.KeePassFile, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.KeePassFile:
                if (xr.Name == ElemMeta)
                {
                    return(SwitchContext(ctx, KdbContext.Meta, xr));
                }
                else if (xr.Name == ElemRoot)
                {
                    return(SwitchContext(ctx, KdbContext.Root, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Meta:
                if (xr.Name == ElemGenerator)
                {
                    ReadString(xr);                             // Ignore
                }
                else if (xr.Name == ElemDbName)
                {
                    m_pwDatabase.Name = ReadString(xr);
                }
                else if (xr.Name == ElemDbNameChanged)
                {
                    m_pwDatabase.NameChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbDesc)
                {
                    m_pwDatabase.Description = ReadString(xr);
                }
                else if (xr.Name == ElemDbDescChanged)
                {
                    m_pwDatabase.DescriptionChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbDefaultUser)
                {
                    m_pwDatabase.DefaultUserName = ReadString(xr);
                }
                else if (xr.Name == ElemDbDefaultUserChanged)
                {
                    m_pwDatabase.DefaultUserNameChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbMntncHistoryDays)
                {
                    m_pwDatabase.MaintenanceHistoryDays = ReadUInt(xr, 365);
                }
                else if (xr.Name == ElemMemoryProt)
                {
                    return(SwitchContext(ctx, KdbContext.MemoryProtection, xr));
                }
                else if (xr.Name == ElemCustomIcons)
                {
                    return(SwitchContext(ctx, KdbContext.CustomIcons, xr));
                }
                else if (xr.Name == ElemRecycleBinEnabled)
                {
                    m_pwDatabase.RecycleBinEnabled = ReadBool(xr, true);
                }
                else if (xr.Name == ElemRecycleBinUuid)
                {
                    m_pwDatabase.RecycleBinUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemRecycleBinChanged)
                {
                    m_pwDatabase.RecycleBinChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemEntryTemplatesGroup)
                {
                    m_pwDatabase.EntryTemplatesGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemEntryTemplatesGroupChanged)
                {
                    m_pwDatabase.EntryTemplatesGroupChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemLastSelectedGroup)
                {
                    m_pwDatabase.LastSelectedGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemLastTopVisibleGroup)
                {
                    m_pwDatabase.LastTopVisibleGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemCustomData)
                {
                    return(SwitchContext(ctx, KdbContext.CustomData, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.MemoryProtection:
                if (xr.Name == ElemProtTitle)
                {
                    m_pwDatabase.MemoryProtection.ProtectTitle = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtUserName)
                {
                    m_pwDatabase.MemoryProtection.ProtectUserName = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtPassword)
                {
                    m_pwDatabase.MemoryProtection.ProtectPassword = ReadBool(xr, true);
                }
                else if (xr.Name == ElemProtURL)
                {
                    m_pwDatabase.MemoryProtection.ProtectUrl = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtNotes)
                {
                    m_pwDatabase.MemoryProtection.ProtectNotes = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtAutoHide)
                {
                    m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = ReadBool(xr, true);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomIcons:
                if (xr.Name == ElemCustomIconItem)
                {
                    return(SwitchContext(ctx, KdbContext.CustomIcon, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomIcon:
                if (xr.Name == ElemCustomIconItemID)
                {
                    m_uuidCustomIconID = ReadUuid(xr);
                }
                else if (xr.Name == ElemCustomIconItemData)
                {
                    string strData = ReadString(xr);
                    if ((strData != null) && (strData.Length > 0))
                    {
                        m_pbCustomIconData = Convert.FromBase64String(strData);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomData:
                if (xr.Name == ElemStringDictExItem)
                {
                    return(SwitchContext(ctx, KdbContext.CustomDataItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomDataItem:
                if (xr.Name == ElemKey)
                {
                    m_strCustomDataKey = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_strCustomDataValue = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Root:
                if (xr.Name == ElemGroup)
                {
                    Debug.Assert(m_ctxGroups.Count == 0);
                    if (m_ctxGroups.Count != 0)
                    {
                        throw new FormatException();
                    }

                    m_pwDatabase.RootGroup = new PwGroup(false, false);
                    m_ctxGroups.Push(m_pwDatabase.RootGroup);
                    m_ctxGroup = m_ctxGroups.Peek();

                    return(SwitchContext(ctx, KdbContext.Group, xr));
                }
                else if (xr.Name == ElemDeletedObjects)
                {
                    return(SwitchContext(ctx, KdbContext.RootDeletedObjects, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Group:
                if (xr.Name == ElemUuid)
                {
                    m_ctxGroup.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemName)
                {
                    m_ctxGroup.Name = ReadString(xr);
                }
                else if (xr.Name == ElemNotes)
                {
                    m_ctxGroup.Notes = ReadString(xr);
                }
                else if (xr.Name == ElemIcon)
                {
                    m_ctxGroup.IconId = (PwIcon)ReadUInt(xr, (uint)PwIcon.Folder);
                }
                else if (xr.Name == ElemCustomIconID)
                {
                    m_ctxGroup.CustomIconUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemTimes)
                {
                    return(SwitchContext(ctx, KdbContext.GroupTimes, xr));
                }
                else if (xr.Name == ElemIsExpanded)
                {
                    m_ctxGroup.IsExpanded = ReadBool(xr, true);
                }
                else if (xr.Name == ElemGroupDefaultAutoTypeSeq)
                {
                    m_ctxGroup.DefaultAutoTypeSequence = ReadString(xr);
                }
                else if (xr.Name == ElemEnableAutoType)
                {
                    m_ctxGroup.EnableAutoType = StrUtil.StringToBoolEx(ReadString(xr));
                }
                else if (xr.Name == ElemEnableSearching)
                {
                    m_ctxGroup.EnableSearching = StrUtil.StringToBoolEx(ReadString(xr));
                }
                else if (xr.Name == ElemLastTopVisibleEntry)
                {
                    m_ctxGroup.LastTopVisibleEntry = ReadUuid(xr);
                }
                else if (xr.Name == ElemGroup)
                {
                    m_ctxGroup = new PwGroup(false, false);
                    m_ctxGroups.Peek().AddGroup(m_ctxGroup, true);

                    m_ctxGroups.Push(m_ctxGroup);

                    return(SwitchContext(ctx, KdbContext.Group, xr));
                }
                else if (xr.Name == ElemEntry)
                {
                    m_ctxEntry = new PwEntry(false, false);
                    m_ctxGroup.AddEntry(m_ctxEntry, true);

                    m_bEntryInHistory = false;
                    return(SwitchContext(ctx, KdbContext.Entry, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Entry:
                if (xr.Name == ElemUuid)
                {
                    m_ctxEntry.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemIcon)
                {
                    m_ctxEntry.IconId = (PwIcon)ReadUInt(xr, (uint)PwIcon.Key);
                }
                else if (xr.Name == ElemCustomIconID)
                {
                    m_ctxEntry.CustomIconUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemFgColor)
                {
                    string strColor = ReadString(xr);
                    if ((strColor != null) && (strColor.Length > 0))
                    {
                        m_ctxEntry.ForegroundColor = ColorTranslator.FromHtml(strColor);
                    }
                }
                else if (xr.Name == ElemBgColor)
                {
                    string strColor = ReadString(xr);
                    if ((strColor != null) && (strColor.Length > 0))
                    {
                        m_ctxEntry.BackgroundColor = ColorTranslator.FromHtml(strColor);
                    }
                }
                else if (xr.Name == ElemOverrideUrl)
                {
                    m_ctxEntry.OverrideUrl = ReadString(xr);
                }
                else if (xr.Name == ElemTimes)
                {
                    return(SwitchContext(ctx, KdbContext.EntryTimes, xr));
                }
                else if (xr.Name == ElemString)
                {
                    return(SwitchContext(ctx, KdbContext.EntryString, xr));
                }
                else if (xr.Name == ElemBinary)
                {
                    return(SwitchContext(ctx, KdbContext.EntryBinary, xr));
                }
                else if (xr.Name == ElemAutoType)
                {
                    return(SwitchContext(ctx, KdbContext.EntryAutoType, xr));
                }
                else if (xr.Name == ElemHistory)
                {
                    Debug.Assert(m_bEntryInHistory == false);

                    if (m_bEntryInHistory == false)
                    {
                        m_ctxHistoryBase = m_ctxEntry;
                        return(SwitchContext(ctx, KdbContext.EntryHistory, xr));
                    }
                    else
                    {
                        ReadUnknown(xr);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.GroupTimes:
            case KdbContext.EntryTimes:
                ITimeLogger tl = ((ctx == KdbContext.GroupTimes) ?
                                  (ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry);
                Debug.Assert(tl != null);

                if (xr.Name == ElemLastModTime)
                {
                    tl.LastModificationTime = ReadTime(xr);
                }
                else if (xr.Name == ElemCreationTime)
                {
                    tl.CreationTime = ReadTime(xr);
                }
                else if (xr.Name == ElemLastAccessTime)
                {
                    tl.LastAccessTime = ReadTime(xr);
                }
                else if (xr.Name == ElemExpiryTime)
                {
                    tl.ExpiryTime = ReadTime(xr);
                }
                else if (xr.Name == ElemExpires)
                {
                    tl.Expires = ReadBool(xr, false);
                }
                else if (xr.Name == ElemUsageCount)
                {
                    tl.UsageCount = ReadULong(xr, 0);
                }
                else if (xr.Name == ElemLocationChanged)
                {
                    tl.LocationChanged = ReadTime(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryString:
                if (xr.Name == ElemKey)
                {
                    m_ctxStringName = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_ctxStringValue = ReadProtectedString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryBinary:
                if (xr.Name == ElemKey)
                {
                    m_ctxBinaryName = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_ctxBinaryValue = ReadProtectedBinary(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryAutoType:
                if (xr.Name == ElemAutoTypeEnabled)
                {
                    m_ctxEntry.AutoType.Enabled = ReadBool(xr, true);
                }
                else if (xr.Name == ElemAutoTypeObfuscation)
                {
                    m_ctxEntry.AutoType.ObfuscationOptions =
                        (AutoTypeObfuscationOptions)ReadUInt(xr, 0);
                }
                else if (xr.Name == ElemAutoTypeDefaultSeq)
                {
                    m_ctxEntry.AutoType.DefaultSequence = ReadString(xr);
                }
                else if (xr.Name == ElemAutoTypeItem)
                {
                    return(SwitchContext(ctx, KdbContext.EntryAutoTypeItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryAutoTypeItem:
                if (xr.Name == ElemWindow)
                {
                    m_ctxATName = ReadString(xr);
                }
                else if (xr.Name == ElemKeystrokeSequence)
                {
                    m_ctxATSeq = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryHistory:
                if (xr.Name == ElemEntry)
                {
                    m_ctxEntry = new PwEntry(false, false);
                    m_ctxHistoryBase.History.Add(m_ctxEntry);

                    m_bEntryInHistory = true;
                    return(SwitchContext(ctx, KdbContext.Entry, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.RootDeletedObjects:
                if (xr.Name == ElemDeletedObject)
                {
                    m_ctxDeletedObject = new PwDeletedObject();
                    m_pwDatabase.DeletedObjects.Add(m_ctxDeletedObject);

                    return(SwitchContext(ctx, KdbContext.DeletedObject, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.DeletedObject:
                if (xr.Name == ElemUuid)
                {
                    m_ctxDeletedObject.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemDeletionTime)
                {
                    m_ctxDeletedObject.DeletionTime = ReadTime(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            default:
                ReadUnknown(xr);
                break;
            }

            return(ctx);
        }
		private static KdbContext SwitchContext(KdbContext ctxCurrent,
			KdbContext ctxNew, XmlReader xr)
		{
			if(xr.IsEmptyElement) return ctxCurrent;
			return ctxNew;
		}
		private KdbContext EndXmlElement(KdbContext ctx, XmlReader xr)
		{
			Debug.Assert(xr.NodeType == XmlNodeType.EndElement);

			if((ctx == KdbContext.KeePassFile) && (xr.Name == ElemDocNode))
				return KdbContext.Null;
			else if((ctx == KdbContext.Meta) && (xr.Name == ElemMeta))
				return KdbContext.KeePassFile;
			else if((ctx == KdbContext.Root) && (xr.Name == ElemRoot))
				return KdbContext.KeePassFile;
			else if((ctx == KdbContext.MemoryProtection) && (xr.Name == ElemMemoryProt))
				return KdbContext.Meta;
			else if((ctx == KdbContext.CustomIcons) && (xr.Name == ElemCustomIcons))
				return KdbContext.Meta;
			else if((ctx == KdbContext.CustomIcon) && (xr.Name == ElemCustomIconItem))
			{
				if(!m_uuidCustomIconID.Equals(PwUuid.Zero) &&
					(m_pbCustomIconData != null))
					m_pwDatabase.CustomIcons.Add(new PwCustomIcon(
						m_uuidCustomIconID, m_pbCustomIconData));
				else { Debug.Assert(false); }

				m_uuidCustomIconID = PwUuid.Zero;
				m_pbCustomIconData = null;

				return KdbContext.CustomIcons;
			}
			else if((ctx == KdbContext.Binaries) && (xr.Name == ElemBinaries))
				return KdbContext.Meta;
			else if((ctx == KdbContext.CustomData) && (xr.Name == ElemCustomData))
				return KdbContext.Meta;
			else if((ctx == KdbContext.CustomDataItem) && (xr.Name == ElemStringDictExItem))
			{
				if((m_strCustomDataKey != null) && (m_strCustomDataValue != null))
					m_pwDatabase.CustomData.Set(m_strCustomDataKey, m_strCustomDataValue);
				else { Debug.Assert(false); }

				m_strCustomDataKey = null;
				m_strCustomDataValue = null;

				return KdbContext.CustomData;
			}
			else if((ctx == KdbContext.Group) && (xr.Name == ElemGroup))
			{
				if(PwUuid.Zero.Equals(m_ctxGroup.Uuid))
					m_ctxGroup.Uuid = new PwUuid(true); // No assert (import)

				m_ctxGroups.Pop();

				if(m_ctxGroups.Count == 0)
				{
					m_ctxGroup = null;
					return KdbContext.Root;
				}
				else
				{
					m_ctxGroup = m_ctxGroups.Peek();
					return KdbContext.Group;
				}
			}
			else if((ctx == KdbContext.GroupTimes) && (xr.Name == ElemTimes))
				return KdbContext.Group;
			else if((ctx == KdbContext.Entry) && (xr.Name == ElemEntry))
			{
				// Create new UUID if absent
				if(PwUuid.Zero.Equals(m_ctxEntry.Uuid))
					m_ctxEntry.Uuid = new PwUuid(true); // No assert (import)

				if(m_bEntryInHistory)
				{
					m_ctxEntry = m_ctxHistoryBase;
					return KdbContext.EntryHistory;
				}

				return KdbContext.Group;
			}
			else if((ctx == KdbContext.EntryTimes) && (xr.Name == ElemTimes))
				return KdbContext.Entry;
			else if((ctx == KdbContext.EntryString) && (xr.Name == ElemString))
			{
				m_ctxEntry.Strings.Set(m_ctxStringName, m_ctxStringValue);
				m_ctxStringName = null;
				m_ctxStringValue = null;
				return KdbContext.Entry;
			}
			else if((ctx == KdbContext.EntryBinary) && (xr.Name == ElemBinary))
			{
				if(string.IsNullOrEmpty(m_strDetachBins))
					m_ctxEntry.Binaries.Set(m_ctxBinaryName, m_ctxBinaryValue);
				else
				{
					SaveBinary(m_ctxBinaryName, m_ctxBinaryValue, m_strDetachBins);

					m_ctxBinaryValue = null;
					GC.Collect();
				}

				m_ctxBinaryName = null;
				m_ctxBinaryValue = null;
				return KdbContext.Entry;
			}
			else if((ctx == KdbContext.EntryAutoType) && (xr.Name == ElemAutoType))
				return KdbContext.Entry;
			else if((ctx == KdbContext.EntryAutoTypeItem) && (xr.Name == ElemAutoTypeItem))
			{
				AutoTypeAssociation atAssoc = new AutoTypeAssociation(m_ctxATName,
					m_ctxATSeq);
				m_ctxEntry.AutoType.Add(atAssoc);
				m_ctxATName = null;
				m_ctxATSeq = null;
				return KdbContext.EntryAutoType;
			}
			else if((ctx == KdbContext.EntryHistory) && (xr.Name == ElemHistory))
			{
				m_bEntryInHistory = false;
				return KdbContext.Entry;
			}
			else if((ctx == KdbContext.RootDeletedObjects) && (xr.Name == ElemDeletedObjects))
				return KdbContext.Root;
			else if((ctx == KdbContext.DeletedObject) && (xr.Name == ElemDeletedObject))
			{
				m_ctxDeletedObject = null;
				return KdbContext.RootDeletedObjects;
			}
			else
			{
				Debug.Assert(false);
				throw new FormatException();
			}
		}
		private KdbContext ReadXmlElement(KdbContext ctx, XmlReader xr)
		{
			Debug.Assert(xr.NodeType == XmlNodeType.Element);

			switch(ctx)
			{
				case KdbContext.Null:
					if(xr.Name == ElemDocNode)
						return SwitchContext(ctx, KdbContext.KeePassFile, xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.KeePassFile:
					if(xr.Name == ElemMeta)
						return SwitchContext(ctx, KdbContext.Meta, xr);
					else if(xr.Name == ElemRoot)
						return SwitchContext(ctx, KdbContext.Root, xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.Meta:
					if(xr.Name == ElemGenerator)
						ReadString(xr); // Ignore
					else if(xr.Name == ElemHeaderHash)
					{
						string strHash = ReadString(xr);
						if(!string.IsNullOrEmpty(strHash) && (m_pbHashOfHeader != null) &&
							!m_bRepairMode)
						{
							byte[] pbHash = Convert.FromBase64String(strHash);
							if(!MemUtil.ArraysEqual(pbHash, m_pbHashOfHeader))
								throw new IOException(KLRes.FileCorrupted);
						}
					}
					else if(xr.Name == ElemDbName)
						m_pwDatabase.Name = ReadString(xr);
					else if(xr.Name == ElemDbNameChanged)
						m_pwDatabase.NameChanged = ReadTime(xr);
					else if(xr.Name == ElemDbDesc)
						m_pwDatabase.Description = ReadString(xr);
					else if(xr.Name == ElemDbDescChanged)
						m_pwDatabase.DescriptionChanged = ReadTime(xr);
					else if(xr.Name == ElemDbDefaultUser)
						m_pwDatabase.DefaultUserName = ReadString(xr);
					else if(xr.Name == ElemDbDefaultUserChanged)
						m_pwDatabase.DefaultUserNameChanged = ReadTime(xr);
					else if(xr.Name == ElemDbMntncHistoryDays)
						m_pwDatabase.MaintenanceHistoryDays = ReadUInt(xr, 365);
					else if(xr.Name == ElemDbColor)
					{
						string strColor = ReadString(xr);
						if(!string.IsNullOrEmpty(strColor))
							m_pwDatabase.Color = ColorTranslator.FromHtml(strColor);
					}
					else if(xr.Name == ElemDbKeyChanged)
						m_pwDatabase.MasterKeyChanged = ReadTime(xr);
					else if(xr.Name == ElemDbKeyChangeRec)
						m_pwDatabase.MasterKeyChangeRec = ReadLong(xr, -1);
					else if(xr.Name == ElemDbKeyChangeForce)
						m_pwDatabase.MasterKeyChangeForce = ReadLong(xr, -1);
					else if(xr.Name == ElemMemoryProt)
						return SwitchContext(ctx, KdbContext.MemoryProtection, xr);
					else if(xr.Name == ElemCustomIcons)
						return SwitchContext(ctx, KdbContext.CustomIcons, xr);
					else if(xr.Name == ElemRecycleBinEnabled)
						m_pwDatabase.RecycleBinEnabled = ReadBool(xr, true);
					else if(xr.Name == ElemRecycleBinUuid)
						m_pwDatabase.RecycleBinUuid = ReadUuid(xr);
					else if(xr.Name == ElemRecycleBinChanged)
						m_pwDatabase.RecycleBinChanged = ReadTime(xr);
					else if(xr.Name == ElemEntryTemplatesGroup)
						m_pwDatabase.EntryTemplatesGroup = ReadUuid(xr);
					else if(xr.Name == ElemEntryTemplatesGroupChanged)
						m_pwDatabase.EntryTemplatesGroupChanged = ReadTime(xr);
					else if(xr.Name == ElemHistoryMaxItems)
						m_pwDatabase.HistoryMaxItems = ReadInt(xr, -1);
					else if(xr.Name == ElemHistoryMaxSize)
						m_pwDatabase.HistoryMaxSize = ReadLong(xr, -1);
					else if(xr.Name == ElemLastSelectedGroup)
						m_pwDatabase.LastSelectedGroup = ReadUuid(xr);
					else if(xr.Name == ElemLastTopVisibleGroup)
						m_pwDatabase.LastTopVisibleGroup = ReadUuid(xr);
					else if(xr.Name == ElemBinaries)
						return SwitchContext(ctx, KdbContext.Binaries, xr);
					else if(xr.Name == ElemCustomData)
						return SwitchContext(ctx, KdbContext.CustomData, xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.MemoryProtection:
					if(xr.Name == ElemProtTitle)
						m_pwDatabase.MemoryProtection.ProtectTitle = ReadBool(xr, false);
					else if(xr.Name == ElemProtUserName)
						m_pwDatabase.MemoryProtection.ProtectUserName = ReadBool(xr, false);
					else if(xr.Name == ElemProtPassword)
						m_pwDatabase.MemoryProtection.ProtectPassword = ReadBool(xr, true);
					else if(xr.Name == ElemProtUrl)
						m_pwDatabase.MemoryProtection.ProtectUrl = ReadBool(xr, false);
					else if(xr.Name == ElemProtNotes)
						m_pwDatabase.MemoryProtection.ProtectNotes = ReadBool(xr, false);
					// else if(xr.Name == ElemProtAutoHide)
					//	m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = ReadBool(xr, true);
					else ReadUnknown(xr);
					break;

				case KdbContext.CustomIcons:
					if(xr.Name == ElemCustomIconItem)
						return SwitchContext(ctx, KdbContext.CustomIcon, xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.CustomIcon:
					if(xr.Name == ElemCustomIconItemID)
						m_uuidCustomIconID = ReadUuid(xr);
					else if(xr.Name == ElemCustomIconItemData)
					{
						string strData = ReadString(xr);
						if(!string.IsNullOrEmpty(strData))
							m_pbCustomIconData = Convert.FromBase64String(strData);
						else { Debug.Assert(false); }
					}
					else ReadUnknown(xr);
					break;

				case KdbContext.Binaries:
					if(xr.Name == ElemBinary)
					{
						if(xr.MoveToAttribute(AttrId))
						{
							string strKey = xr.Value;
							ProtectedBinary pbData = ReadProtectedBinary(xr);

							m_dictBinPool[strKey ?? string.Empty] = pbData;
						}
						else ReadUnknown(xr);
					}
					else ReadUnknown(xr);
					break;

				case KdbContext.CustomData:
					if(xr.Name == ElemStringDictExItem)
						return SwitchContext(ctx, KdbContext.CustomDataItem, xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.CustomDataItem:
					if(xr.Name == ElemKey)
						m_strCustomDataKey = ReadString(xr);
					else if(xr.Name == ElemValue)
						m_strCustomDataValue = ReadString(xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.Root:
					if(xr.Name == ElemGroup)
					{
						Debug.Assert(m_ctxGroups.Count == 0);
						if(m_ctxGroups.Count != 0) throw new FormatException();

						m_pwDatabase.RootGroup = new PwGroup(false, false);
						m_ctxGroups.Push(m_pwDatabase.RootGroup);
						m_ctxGroup = m_ctxGroups.Peek();

						return SwitchContext(ctx, KdbContext.Group, xr);
					}
					else if(xr.Name == ElemDeletedObjects)
						return SwitchContext(ctx, KdbContext.RootDeletedObjects, xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.Group:
					if(xr.Name == ElemUuid)
						m_ctxGroup.Uuid = ReadUuid(xr);
					else if(xr.Name == ElemName)
						m_ctxGroup.Name = ReadString(xr);
					else if(xr.Name == ElemNotes)
						m_ctxGroup.Notes = ReadString(xr);
					else if(xr.Name == ElemIcon)
						m_ctxGroup.IconId = (PwIcon)ReadInt(xr, (int)PwIcon.Folder);
					else if(xr.Name == ElemCustomIconID)
						m_ctxGroup.CustomIconUuid = ReadUuid(xr);
					else if(xr.Name == ElemTimes)
						return SwitchContext(ctx, KdbContext.GroupTimes, xr);
					else if(xr.Name == ElemIsExpanded)
						m_ctxGroup.IsExpanded = ReadBool(xr, true);
					else if(xr.Name == ElemGroupDefaultAutoTypeSeq)
						m_ctxGroup.DefaultAutoTypeSequence = ReadString(xr);
					else if(xr.Name == ElemEnableAutoType)
						m_ctxGroup.EnableAutoType = StrUtil.StringToBoolEx(ReadString(xr));
					else if(xr.Name == ElemEnableSearching)
						m_ctxGroup.EnableSearching = StrUtil.StringToBoolEx(ReadString(xr));
					else if(xr.Name == ElemLastTopVisibleEntry)
						m_ctxGroup.LastTopVisibleEntry = ReadUuid(xr);
					else if(xr.Name == ElemGroup)
					{
						m_ctxGroup = new PwGroup(false, false);
						m_ctxGroups.Peek().AddGroup(m_ctxGroup, true);

						m_ctxGroups.Push(m_ctxGroup);

						return SwitchContext(ctx, KdbContext.Group, xr);
					}
					else if(xr.Name == ElemEntry)
					{
						m_ctxEntry = new PwEntry(false, false);
						m_ctxGroup.AddEntry(m_ctxEntry, true);

						m_bEntryInHistory = false;
						return SwitchContext(ctx, KdbContext.Entry, xr);
					}
					else ReadUnknown(xr);
					break;

				case KdbContext.Entry:
					if(xr.Name == ElemUuid)
						m_ctxEntry.Uuid = ReadUuid(xr);
					else if(xr.Name == ElemIcon)
						m_ctxEntry.IconId = (PwIcon)ReadInt(xr, (int)PwIcon.Key);
					else if(xr.Name == ElemCustomIconID)
						m_ctxEntry.CustomIconUuid = ReadUuid(xr);
					else if(xr.Name == ElemFgColor)
					{
						string strColor = ReadString(xr);
						if(!string.IsNullOrEmpty(strColor))
							m_ctxEntry.ForegroundColor = ColorTranslator.FromHtml(strColor);
					}
					else if(xr.Name == ElemBgColor)
					{
						string strColor = ReadString(xr);
						if(!string.IsNullOrEmpty(strColor))
							m_ctxEntry.BackgroundColor = ColorTranslator.FromHtml(strColor);
					}
					else if(xr.Name == ElemOverrideUrl)
						m_ctxEntry.OverrideUrl = ReadString(xr);
					else if(xr.Name == ElemTags)
						m_ctxEntry.Tags = StrUtil.StringToTags(ReadString(xr));
					else if(xr.Name == ElemTimes)
						return SwitchContext(ctx, KdbContext.EntryTimes, xr);
					else if(xr.Name == ElemString)
						return SwitchContext(ctx, KdbContext.EntryString, xr);
					else if(xr.Name == ElemBinary)
						return SwitchContext(ctx, KdbContext.EntryBinary, xr);
					else if(xr.Name == ElemAutoType)
						return SwitchContext(ctx, KdbContext.EntryAutoType, xr);
					else if(xr.Name == ElemHistory)
					{
						Debug.Assert(m_bEntryInHistory == false);

						if(m_bEntryInHistory == false)
						{
							m_ctxHistoryBase = m_ctxEntry;
							return SwitchContext(ctx, KdbContext.EntryHistory, xr);
						}
						else ReadUnknown(xr);
					}
					else ReadUnknown(xr);
					break;

				case KdbContext.GroupTimes:
				case KdbContext.EntryTimes:
					ITimeLogger tl = ((ctx == KdbContext.GroupTimes) ?
						(ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry);
					Debug.Assert(tl != null);

					if(xr.Name == ElemCreationTime)
						tl.CreationTime = ReadTime(xr);
					else if(xr.Name == ElemLastModTime)
						tl.LastModificationTime = ReadTime(xr);
					else if(xr.Name == ElemLastAccessTime)
						tl.LastAccessTime = ReadTime(xr);
					else if(xr.Name == ElemExpiryTime)
						tl.ExpiryTime = ReadTime(xr);
					else if(xr.Name == ElemExpires)
						tl.Expires = ReadBool(xr, false);
					else if(xr.Name == ElemUsageCount)
						tl.UsageCount = ReadULong(xr, 0);
					else if(xr.Name == ElemLocationChanged)
						tl.LocationChanged = ReadTime(xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.EntryString:
					if(xr.Name == ElemKey)
						m_ctxStringName = ReadString(xr);
					else if(xr.Name == ElemValue)
						m_ctxStringValue = ReadProtectedString(xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.EntryBinary:
					if(xr.Name == ElemKey)
						m_ctxBinaryName = ReadString(xr);
					else if(xr.Name == ElemValue)
						m_ctxBinaryValue = ReadProtectedBinary(xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.EntryAutoType:
					if(xr.Name == ElemAutoTypeEnabled)
						m_ctxEntry.AutoType.Enabled = ReadBool(xr, true);
					else if(xr.Name == ElemAutoTypeObfuscation)
						m_ctxEntry.AutoType.ObfuscationOptions =
							(AutoTypeObfuscationOptions)ReadInt(xr, 0);
					else if(xr.Name == ElemAutoTypeDefaultSeq)
						m_ctxEntry.AutoType.DefaultSequence = ReadString(xr);
					else if(xr.Name == ElemAutoTypeItem)
						return SwitchContext(ctx, KdbContext.EntryAutoTypeItem, xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.EntryAutoTypeItem:
					if(xr.Name == ElemWindow)
						m_ctxATName = ReadString(xr);
					else if(xr.Name == ElemKeystrokeSequence)
						m_ctxATSeq = ReadString(xr);
					else ReadUnknown(xr);
					break;

				case KdbContext.EntryHistory:
					if(xr.Name == ElemEntry)
					{
						m_ctxEntry = new PwEntry(false, false);
						m_ctxHistoryBase.History.Add(m_ctxEntry);

						m_bEntryInHistory = true;
						return SwitchContext(ctx, KdbContext.Entry, xr);
					}
					else ReadUnknown(xr);
					break;

				case KdbContext.RootDeletedObjects:
					if(xr.Name == ElemDeletedObject)
					{
						m_ctxDeletedObject = new PwDeletedObject();
						m_pwDatabase.DeletedObjects.Add(m_ctxDeletedObject);

						return SwitchContext(ctx, KdbContext.DeletedObject, xr);
					}
					else ReadUnknown(xr);
					break;

				case KdbContext.DeletedObject:
					if(xr.Name == ElemUuid)
						m_ctxDeletedObject.Uuid = ReadUuid(xr);
					else if(xr.Name == ElemDeletionTime)
						m_ctxDeletedObject.DeletionTime = ReadTime(xr);
					else ReadUnknown(xr);
					break;

				default:
					ReadUnknown(xr);
					break;
			}

			return ctx;
		}
Ejemplo n.º 10
0
        private KdbContext EndXmlElement(KdbContext ctx, XmlReader xr)
        {
            Debug.Assert(xr.NodeType == XmlNodeType.EndElement);

            if ((ctx == KdbContext.KeePassFile) && (xr.Name == ElemDocNode))
            {
                return(KdbContext.Null);
            }
            else if ((ctx == KdbContext.Meta) && (xr.Name == ElemMeta))
            {
                return(KdbContext.KeePassFile);
            }
            else if ((ctx == KdbContext.Root) && (xr.Name == ElemRoot))
            {
                return(KdbContext.KeePassFile);
            }
            else if ((ctx == KdbContext.MemoryProtection) && (xr.Name == ElemMemoryProt))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomIcons) && (xr.Name == ElemCustomIcons))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomIcon) && (xr.Name == ElemCustomIconItem))
            {
                if ((m_uuidCustomIconID != PwUuid.Zero) && (m_pbCustomIconData != null))
                {
                    m_pwDatabase.CustomIcons.Add(new PwCustomIcon(
                                                     m_uuidCustomIconID, m_pbCustomIconData));

                    m_uuidCustomIconID = PwUuid.Zero;
                    m_pbCustomIconData = null;
                }
                else
                {
                    Debug.Assert(false);
                }

                return(KdbContext.CustomIcons);
            }
            else if ((ctx == KdbContext.Group) && (xr.Name == ElemGroup))
            {
                if (PwUuid.Zero.EqualsValue(m_ctxGroup.Uuid))
                {
                    Debug.Assert(false);
                    m_ctxGroup.Uuid = new PwUuid(true);
                }

                m_ctxGroups.Pop();

                if (m_ctxGroups.Count == 0)
                {
                    m_ctxGroup = null;
                    return(KdbContext.Root);
                }
                else
                {
                    m_ctxGroup = m_ctxGroups.Peek();
                    return(KdbContext.Group);
                }
            }
            else if ((ctx == KdbContext.GroupTimes) && (xr.Name == ElemTimes))
            {
                return(KdbContext.Group);
            }
            else if ((ctx == KdbContext.Entry) && (xr.Name == ElemEntry))
            {
                // Create new UUID if absent
                if (PwUuid.Zero.EqualsValue(m_ctxEntry.Uuid))
                {
                    Debug.Assert(false);
                    m_ctxEntry.Uuid = new PwUuid(true);
                }

                if (m_bEntryInHistory)
                {
                    m_ctxEntry = m_ctxHistoryBase;
                    return(KdbContext.EntryHistory);
                }

                return(KdbContext.Group);
            }
            else if ((ctx == KdbContext.EntryTimes) && (xr.Name == ElemTimes))
            {
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryString) && (xr.Name == ElemString))
            {
                m_ctxEntry.Strings.Set(m_ctxStringName, m_ctxStringValue);
                m_ctxStringName  = null;
                m_ctxStringValue = null;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryBinary) && (xr.Name == ElemBinary))
            {
                m_ctxEntry.Binaries.Set(m_ctxBinaryName, m_ctxBinaryValue);
                m_ctxBinaryName  = null;
                m_ctxBinaryValue = null;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryAutoType) && (xr.Name == ElemAutoType))
            {
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryAutoTypeItem) && (xr.Name == ElemAutoTypeItem))
            {
                m_ctxEntry.AutoType.Set(m_ctxATName, m_ctxATSeq);
                m_ctxATName = null;
                m_ctxATSeq  = null;
                return(KdbContext.EntryAutoType);
            }
            else if ((ctx == KdbContext.EntryHistory) && (xr.Name == ElemHistory))
            {
                m_bEntryInHistory = false;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.RootDeletedObjects) && (xr.Name == ElemDeletedObjects))
            {
                return(KdbContext.Root);
            }
            else if ((ctx == KdbContext.DeletedObject) && (xr.Name == ElemDeletedObject))
            {
                m_ctxDeletedObject = null;
                return(KdbContext.RootDeletedObjects);
            }
            else
            {
                Debug.Assert(false);
                throw new FormatException();
            }
        }
Ejemplo n.º 11
0
        private KdbContext ReadXmlElement(KdbContext ctx, XmlReader xr)
        {
            Debug.Assert(xr.NodeType == XmlNodeType.Element);

            switch(ctx)
            {
                case KdbContext.Null:
                    if(xr.Name == ElemDocNode)
                        return SwitchContext(ctx, KdbContext.KeePassFile, xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.KeePassFile:
                    if(xr.Name == ElemMeta)
                        return SwitchContext(ctx, KdbContext.Meta, xr);
                    else if(xr.Name == ElemRoot)
                        return SwitchContext(ctx, KdbContext.Root, xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.Meta:
                    if(xr.Name == ElemGenerator)
                        ReadString(xr); // Ignore
                    else if(xr.Name == ElemDbName)
                        m_pwDatabase.Name = ReadString(xr);
                    else if(xr.Name == ElemDbDesc)
                        m_pwDatabase.Description = ReadString(xr);
                    else if(xr.Name == ElemDbDefaultUser)
                        m_pwDatabase.DefaultUserName = ReadString(xr);
                    else if(xr.Name == ElemDbMntncHistoryDays)
                        m_pwDatabase.MaintenanceHistoryDays = ReadUInt(xr, 365);
                    else if(xr.Name == ElemMemoryProt)
                        return SwitchContext(ctx, KdbContext.MemoryProtection, xr);
                    else if(xr.Name == ElemCustomIcons)
                        return SwitchContext(ctx, KdbContext.CustomIcons, xr);
                    else if(xr.Name == ElemLastSelectedGroup)
                        m_pwDatabase.LastSelectedGroup = ReadUuid(xr);
                    else if(xr.Name == ElemLastTopVisibleGroup)
                        m_pwDatabase.LastTopVisibleGroup = ReadUuid(xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.MemoryProtection:
                    if(xr.Name == ElemProtTitle)
                        m_pwDatabase.MemoryProtection.ProtectNotes = ReadBool(xr, false);
                    else if(xr.Name == ElemProtUserName)
                        m_pwDatabase.MemoryProtection.ProtectUserName = ReadBool(xr, false);
                    else if(xr.Name == ElemProtPassword)
                        m_pwDatabase.MemoryProtection.ProtectPassword = ReadBool(xr, true);
                    else if(xr.Name == ElemProtURL)
                        m_pwDatabase.MemoryProtection.ProtectUrl = ReadBool(xr, false);
                    else if(xr.Name == ElemProtNotes)
                        m_pwDatabase.MemoryProtection.ProtectNotes = ReadBool(xr, false);
                    else if(xr.Name == ElemProtAutoHide)
                        m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = ReadBool(xr, true);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.CustomIcons:
                    if(xr.Name == ElemCustomIconItem)
                        return SwitchContext(ctx, KdbContext.CustomIcon, xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.CustomIcon:
                    if(xr.Name == ElemCustomIconItemID)
                        m_uuidCustomIconID = ReadUuid(xr);
                    else if(xr.Name == ElemCustomIconItemData)
                    {
                        string strData = ReadString(xr);
                        if((strData != null) && (strData.Length > 0))
                            m_pbCustomIconData = Convert.FromBase64String(strData);
                        else { Debug.Assert(false); }
                    }
                    else ReadUnknown(xr);
                    break;

                case KdbContext.Root:
                    if(xr.Name == ElemGroup)
                    {
                        Debug.Assert(m_ctxGroups.Count == 0);
                        if(m_ctxGroups.Count != 0) throw new FormatException();

                        m_pwDatabase.RootGroup = new PwGroup(false, false);
                        m_ctxGroups.Push(m_pwDatabase.RootGroup);
                        m_ctxGroup = m_ctxGroups.Peek();

                        return SwitchContext(ctx, KdbContext.Group, xr);
                    }
                    else if(xr.Name == ElemDeletedObjects)
                        return SwitchContext(ctx, KdbContext.RootDeletedObjects, xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.Group:
                    if(xr.Name == ElemUuid)
                        m_ctxGroup.Uuid = ReadUuid(xr);
                    else if(xr.Name == ElemName)
                        m_ctxGroup.Name = ReadString(xr);
                    else if(xr.Name == ElemNotes)
                        m_ctxGroup.Notes = ReadString(xr);
                    else if(xr.Name == ElemIcon)
                        m_ctxGroup.IconId = (PwIcon)ReadUInt(xr, (uint)PwIcon.Folder);
                    else if(xr.Name == ElemCustomIconID)
                        m_ctxGroup.CustomIconUuid = ReadUuid(xr);
                    else if(xr.Name == ElemTimes)
                        return SwitchContext(ctx, KdbContext.GroupTimes, xr);
                    else if(xr.Name == ElemIsExpanded)
                        m_ctxGroup.IsExpanded = ReadBool(xr, true);
                    else if(xr.Name == ElemGroupDefaultAutoTypeSeq)
                        m_ctxGroup.DefaultAutoTypeSequence = ReadString(xr);
                    else if(xr.Name == ElemLastTopVisibleEntry)
                        m_ctxGroup.LastTopVisibleEntry = ReadUuid(xr);
                    else if(xr.Name == ElemGroup)
                    {
                        m_ctxGroup = new PwGroup(false, false);
                        m_ctxGroups.Peek().AddGroup(m_ctxGroup, true);

                        m_ctxGroups.Push(m_ctxGroup);

                        return SwitchContext(ctx, KdbContext.Group, xr);
                    }
                    else if(xr.Name == ElemEntry)
                    {
                        m_ctxEntry = new PwEntry(false, false);
                        m_ctxGroup.AddEntry(m_ctxEntry, true);

                        m_bEntryInHistory = false;
                        return SwitchContext(ctx, KdbContext.Entry, xr);
                    }
                    else ReadUnknown(xr);
                    break;

                case KdbContext.Entry:
                    if(xr.Name == ElemUuid)
                        m_ctxEntry.Uuid = ReadUuid(xr);
                    else if(xr.Name == ElemIcon)
                        m_ctxEntry.IconId = (PwIcon)ReadUInt(xr, (uint)PwIcon.Key);
                    else if(xr.Name == ElemCustomIconID)
                        m_ctxEntry.CustomIconUuid = ReadUuid(xr);
                    else if(xr.Name == ElemFgColor)
                    {
                        string strColor = ReadString(xr);
                        if((strColor != null) && (strColor.Length > 0))
                            m_ctxEntry.ForegroundColor = ColorTranslator.FromHtml(strColor);
                    }
                    else if(xr.Name == ElemBgColor)
                    {
                        string strColor = ReadString(xr);
                        if((strColor != null) && (strColor.Length > 0))
                            m_ctxEntry.BackgroundColor = ColorTranslator.FromHtml(strColor);
                    }
                    else if(xr.Name == ElemOverrideUrl)
                        m_ctxEntry.OverrideUrl = ReadString(xr);
                    else if(xr.Name == ElemTimes)
                        return SwitchContext(ctx, KdbContext.EntryTimes, xr);
                    else if(xr.Name == ElemString)
                        return SwitchContext(ctx, KdbContext.EntryString, xr);
                    else if(xr.Name == ElemBinary)
                        return SwitchContext(ctx, KdbContext.EntryBinary, xr);
                    else if(xr.Name == ElemAutoType)
                        return SwitchContext(ctx, KdbContext.EntryAutoType, xr);
                    else if(xr.Name == ElemHistory)
                    {
                        Debug.Assert(m_bEntryInHistory == false);

                        if(m_bEntryInHistory == false)
                        {
                            m_ctxHistoryBase = m_ctxEntry;
                            return SwitchContext(ctx, KdbContext.EntryHistory, xr);
                        }
                        else ReadUnknown(xr);
                    }
                    else ReadUnknown(xr);
                    break;

                case KdbContext.GroupTimes:
                case KdbContext.EntryTimes:
                    ITimeLogger tl = ((ctx == KdbContext.GroupTimes) ?
                        (ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry);
                    Debug.Assert(tl != null);

                    if(xr.Name == ElemLastModTime)
                        tl.LastModificationTime = ReadTime(xr);
                    else if(xr.Name == ElemCreationTime)
                        tl.CreationTime = ReadTime(xr);
                    else if(xr.Name == ElemLastAccessTime)
                        tl.LastAccessTime = ReadTime(xr);
                    else if(xr.Name == ElemExpiryTime)
                        tl.ExpiryTime = ReadTime(xr);
                    else if(xr.Name == ElemExpires)
                        tl.Expires = ReadBool(xr, false);
                    else if(xr.Name == ElemUsageCount)
                        tl.UsageCount = ReadULong(xr, 0);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.EntryString:
                    if(xr.Name == ElemKey)
                        m_ctxStringName = ReadString(xr);
                    else if(xr.Name == ElemValue)
                        m_ctxStringValue = ReadProtectedString(xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.EntryBinary:
                    if(xr.Name == ElemKey)
                        m_ctxBinaryName = ReadString(xr);
                    else if(xr.Name == ElemValue)
                        m_ctxBinaryValue = ReadProtectedBinary(xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.EntryAutoType:
                    if(xr.Name == ElemAutoTypeEnabled)
                        m_ctxEntry.AutoType.Enabled = ReadBool(xr, true);
                    else if(xr.Name == ElemAutoTypeObfuscation)
                        m_ctxEntry.AutoType.ObfuscationOptions =
                            (AutoTypeObfuscationOptions)ReadUInt(xr, 0);
                    else if(xr.Name == ElemAutoTypeDefaultSeq)
                        m_ctxEntry.AutoType.DefaultSequence = ReadString(xr);
                    else if(xr.Name == ElemAutoTypeItem)
                        return SwitchContext(ctx, KdbContext.EntryAutoTypeItem, xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.EntryAutoTypeItem:
                    if(xr.Name == ElemWindow)
                        m_ctxATName = ReadString(xr);
                    else if(xr.Name == ElemKeystrokeSequence)
                        m_ctxATSeq = ReadString(xr);
                    else ReadUnknown(xr);
                    break;

                case KdbContext.EntryHistory:
                    if(xr.Name == ElemEntry)
                    {
                        m_ctxEntry = new PwEntry(false, false);
                        m_ctxHistoryBase.History.Add(m_ctxEntry);

                        m_bEntryInHistory = true;
                        return SwitchContext(ctx, KdbContext.Entry, xr);
                    }
                    else ReadUnknown(xr);
                    break;

                case KdbContext.RootDeletedObjects:
                    if(xr.Name == ElemDeletedObject)
                    {
                        m_ctxDeletedObject = new PwDeletedObject();
                        m_pwDatabase.DeletedObjects.Add(m_ctxDeletedObject);

                        return SwitchContext(ctx, KdbContext.DeletedObject, xr);
                    }
                    else ReadUnknown(xr);
                    break;

                case KdbContext.DeletedObject:
                    if(xr.Name == ElemUuid)
                        m_ctxDeletedObject.Uuid = ReadUuid(xr);
                    else if(xr.Name == ElemDeletionTime)
                        m_ctxDeletedObject.DeletionTime = ReadTime(xr);
                    else ReadUnknown(xr);
                    break;

                default:
                    ReadUnknown(xr);
                    break;
            }

            return ctx;
        }