/// <summary>
        ///     Parses a password history from the database serialized format which is:
        ///     smmnnddddddddllll[passsword] ...
        ///     's' is a decimal status.
        ///     'mm' is a hex max number of password history entries
        ///     'nn' is a hex number of passwords in this list
        ///     The following is repeated 'nn' times:
        ///     'dddddddd' is a hex representation of 32-bit unix time when this password was changed.
        ///     'llll' is a hex representation of 16-bit length of the password that follows.
        ///     [password] is the string of the password.
        /// </summary>
        /// <param name="serialized">The serialized string</param>
        /// <returns>The decoded password history</returns>
        public static PasswordSafePasswordHistory Parse(
            string serialized)
        {
            if (serialized == null)
            {
                throw new ArgumentNullException("serialized");
            }

            var history = new PasswordSafePasswordHistory();

            if (serialized.Length < 5)
            {
                return(history);
            }

            history.Status     = byte.Parse(serialized.Substring(0, 1), NumberStyles.Integer, CultureInfo.InvariantCulture);
            history.MaxHistory = byte.Parse(serialized.Substring(1, 2), NumberStyles.HexNumber,
                                            CultureInfo.InvariantCulture);
            var numberOfPasswords = int.Parse(serialized.Substring(3, 2), NumberStyles.HexNumber,
                                              CultureInfo.InvariantCulture);
            var currentIndex = 5;

            for (var i = 0; i < numberOfPasswords; ++i)
            {
                var unixTimeChanged = int.Parse(serialized.Substring(currentIndex, 8), NumberStyles.HexNumber,
                                                CultureInfo.InvariantCulture);
                var passwordChangedUtc = PasswordSafeUtility.GetUtcFromUnixTime(unixTimeChanged);
                currentIndex += 8;

                var passwordLength = int.Parse(serialized.Substring(currentIndex, 4), NumberStyles.HexNumber,
                                               CultureInfo.InvariantCulture);
                currentIndex += 4;

                var password = serialized.Substring(currentIndex, passwordLength);
                currentIndex += passwordLength;

                history.PasswordHistoryAdd(new PasswordSafePassword(password, passwordChangedUtc));
            }

            return(history);
        }
        /// <summary>
        ///     Reads one data record.
        /// </summary>
        /// <returns>The record</returns>
        private PasswordSafeRecord ReadRecord()
        {
            var fields = ReadGenericRecord();

            if (fields == null)
            {
                return(null);
            }

            var record  = new PasswordSafeRecord();
            var endSeen = false;

            foreach (var field in fields)
            {
                if (endSeen)
                {
                    throw new InvalidDataException("The END filed must be last in the header");
                }

                var data = field.DataBuffer();

                switch ((PasswordSafeRecordTypeCode)field.Type)
                {
                case PasswordSafeRecordTypeCode.NAME:
                    throw new InvalidDataException("The NAME field type is not allowed here.");

                case PasswordSafeRecordTypeCode.UUID:
                    if (data.Length != 16)
                    {
                        throw new InvalidDataException("UUID field length wrong");
                    }

                    record.Uuid = new Guid(data);
                    break;

                case PasswordSafeRecordTypeCode.GROUP:
                    record.Group =
                        Encoding.UTF8.GetString(data, 0, data.Length);     //.UTF8.GetString(data,0,data.Length);
                    break;

                case PasswordSafeRecordTypeCode.TITLE:
                    record.Title = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.USER:
                    record.User = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.NOTES:
                    record.Notes = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.PASSWORD:
                    record.PasswordValue = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.CTIME:
                    record.TimeRecordCreatedUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.PMTIME:
                    record.TimePasswordModifiedUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.ATIME:
                    record.TimeRecordAccessedUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.LTIME:
                    record.TimePasswordExpiresUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.POLICY:
                    throw new InvalidDataException("The POLICY field type is not allowed here.");

                case PasswordSafeRecordTypeCode.RMTIME:
                    record.TimeRecordModifiedUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.URL:
                    record.ResourceLocator = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.AUTOTYPE:
                    record.AutoType = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.PWHIST:
                    var serializedHistory = Encoding.UTF8.GetString(data, 0, data.Length);
                    record.PasswordHistory = PasswordSafePasswordHistory.Parse(serializedHistory);
                    break;

                case PasswordSafeRecordTypeCode.END:
                    endSeen = true;
                    break;

                default:
                    record.UnknownFieldEntriesAdd(field);
                    break;
                }
            }

            return(record);
        }