예제 #1
0
        public override void PopulateEntry(PwEntry pwEntry, PwDatabase pwDatabase, UserPrefs userPrefs, RecordType recordType)
        {
            base.PopulateEntry(pwEntry, pwDatabase, userPrefs, recordType);

            List <SecureContentsSection> sections;

            if (this.sections != null)
            {
                sections = this.sections;
            }
            else
            {
                sections = this.createSectionsFromPlainFields(recordType);
            }

            if (sections != null)
            {
                int unnamedSectionNumber = 1;
                SectionFieldLocator usernameFieldLocator = this.GetUsernameFieldLocator();
                SectionFieldLocator passwordFieldLocator = this.GetPasswordFieldLocator();
                SectionFieldLocator urlFieldLocator      = this.GetURLFieldLocator();

                foreach (SecureContentsSection section in sections)
                {
                    // Linked items are not supported
                    if (section.name.Equals(LINKED_ITEMS_SECTION_NAME))
                    {
                        continue;
                    }

                    // Section without fields, nothing to import
                    if (section.fields == null)
                    {
                        continue;
                    }

                    string sectionTitle = section.title;

                    // If it's an unnamed user-defined section, set a generic unique name (prevents field name collisions)
                    if (string.IsNullOrEmpty(section.title) && this.IsUserSection(section))
                    {
                        sectionTitle = string.Format("{0} {1}", Properties.Strings.Section_Title, unnamedSectionNumber++);
                    }

                    foreach (SectionField field in section.fields)
                    {
                        // Special treatment fields
                        if (field.k == SectionFieldType.concealed && OTP_FIELD_NAME.IsMatch(field.n ?? string.Empty))
                        {
                            // OTP fields must be formatted to comply with one of the OTP plugins
                            this.setOTPField(pwEntry, pwDatabase.MemoryProtection.ProtectPassword, field as GeneralSectionField, userPrefs.OTPFormat);
                            continue;
                        }
                        else if (field.k == SectionFieldType.address && (field as AddressSectionField).v != null)
                        {
                            // Addresses can be imported as a single composite field or splitting each component in a separate field
                            if (userPrefs.AddressFormat == AddressFormat.Compact)
                            {
                                this.setCompactAddressField(pwEntry, sectionTitle, field as AddressSectionField);
                            }
                            else if (userPrefs.AddressFormat == AddressFormat.Multiline)
                            {
                                this.setMultilineAddressField(pwEntry, sectionTitle, field as AddressSectionField);
                            }
                            else
                            {
                                this.setExpandedAddressField(pwEntry, sectionTitle, field as AddressSectionField);
                            }

                            continue;
                        }

                        string fieldLabel = field.t;
                        string fieldValue = null;

                        // If the field is in a named section, prefix its name to avoid collisions
                        if (!string.IsNullOrEmpty(sectionTitle))
                        {
                            fieldLabel = string.Concat(sectionTitle, " - ", field.t);
                        }

                        // Format the field value according to its type
                        if (field.k == SectionFieldType.date)
                        {
                            DateSectionField dateSectionField = field as DateSectionField;

                            if (!DateTime.MinValue.Equals(dateSectionField.v))
                            {
                                fieldValue = DateTimeFormatter.FormatDate(dateSectionField.v, userPrefs.DateFormat);
                            }
                        }
                        else if (field.k == SectionFieldType.monthYear)
                        {
                            MonthYearSectionField monthYearSectionField = field as MonthYearSectionField;

                            if (!DateTime.MinValue.Equals(monthYearSectionField.v))
                            {
                                fieldValue = DateTimeFormatter.FormatMonthYear(monthYearSectionField.v, userPrefs.DateFormat);
                            }
                        }
                        else if (field.k == SectionFieldType.menu || field.k == SectionFieldType.cctype || field.k == SectionFieldType.gender)
                        {
                            GeneralSectionField generalSectionField = field as GeneralSectionField;

                            // Combo-box values can't be empty
                            if (!string.IsNullOrEmpty(generalSectionField.v))
                            {
                                fieldValue = Properties.Strings.ResourceManager.GetString(string.Join("_", new string[] { "Menu", generalSectionField.n, generalSectionField.v }));
                            }
                        }
                        else
                        {
                            fieldValue = (field as GeneralSectionField).v;
                        }

                        // Use the proper line terminator in multiline values
                        if (field.a != null && field.a.multiline)
                        {
                            fieldValue = StringExt.FixNewLines(fieldValue);
                        }

                        // No point in importing an empty template field. If it's user-defined it might be there for a reason.
                        if (string.IsNullOrEmpty(fieldValue) && !this.IsUserSection(section))
                        {
                            continue;
                        }

                        bool protect;

                        if (usernameFieldLocator != null && usernameFieldLocator.Equals(section.name, field.n))
                        {
                            protect = pwDatabase.MemoryProtection.ProtectUserName;
                            pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(protect, fieldValue ?? string.Empty));
                            fieldValue = "{USERNAME}";
                        }
                        else if (passwordFieldLocator != null && passwordFieldLocator.Equals(section.name, field.n))
                        {
                            protect = pwDatabase.MemoryProtection.ProtectPassword;
                            pwEntry.Strings.Set(PwDefs.PasswordField, new ProtectedString(protect, fieldValue ?? string.Empty));
                            fieldValue = "{PASSWORD}";
                        }
                        else if (urlFieldLocator != null && urlFieldLocator.Equals(section.name, field.n))
                        {
                            protect = pwDatabase.MemoryProtection.ProtectUrl;
                            pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(protect, fieldValue ?? string.Empty));
                            fieldValue = "{URL}";
                        }
                        else
                        {
                            protect = (field.k == SectionFieldType.concealed && pwDatabase.MemoryProtection.ProtectPassword) || (field.k == SectionFieldType.URL && pwDatabase.MemoryProtection.ProtectUrl);
                        }

                        // If it's one of the three special fields (username, password, url) and the 1Password field
                        // has the same name as the KeePass entry field, don't overwrite its value with the placeholder.
                        if (!pwEntry.Strings.Exists(fieldLabel))
                        {
                            pwEntry.Strings.Set(fieldLabel, new ProtectedString(protect, fieldValue ?? string.Empty));
                        }
                    }
                }
            }

            if (!string.IsNullOrEmpty(this.notesPlain))
            {
                pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(pwDatabase.MemoryProtection.ProtectNotes, StringExt.FixNewLines(this.notesPlain)));
            }

            if (this.customIcon != null)
            {
                byte[] customIconData = null;

                try
                {
                    using (MemoryStream originalIconStream = new MemoryStream(this.customIcon))
                        using (Bitmap originalIcon = new Bitmap(originalIconStream))
                            using (MemoryStream convertedIconStream = new MemoryStream())
                            {
                                originalIcon.Save(convertedIconStream, ImageFormat.Png);
                                customIconData = convertedIconStream.ToArray();

                                using (MD5 md5 = MD5.Create())
                                {
                                    PwUuid customIconUuid = new PwUuid(md5.ComputeHash(customIconData));
                                    this.PwCustomIcon      = new PwCustomIcon(customIconUuid, customIconData);
                                    pwEntry.CustomIconUuid = customIconUuid;
                                }
                            }
                }
                catch (ArgumentException)
                {
                    // Image format is not supported or one of its dimensions is bigger than 65,535
                }
            }
        }
예제 #2
0
        private List <SecureContentsSection> createSectionsFromPlainFields(RecordType recordType)
        {
            Dictionary <string, SecureContentsSection> sectionsByName = new Dictionary <string, SecureContentsSection>();

            foreach (PropertyInfo propertyInfo in this.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance))
            {
                string fieldValue = Convert.ToString(propertyInfo.GetValue(this, null));
                if (!Attribute.IsDefined(propertyInfo, typeof(ItemFieldAttribute)) || string.IsNullOrEmpty(fieldValue))
                {
                    continue;
                }

                ItemFieldAttribute itemFieldAttribute = Attribute.GetCustomAttribute(propertyInfo, typeof(ItemFieldAttribute)) as ItemFieldAttribute;

                string sectionName = itemFieldAttribute.sectionName ?? string.Empty;

                SecureContentsSection section;
                if (!sectionsByName.TryGetValue(sectionName, out section))
                {
                    section = new SecureContentsSection()
                    {
                        name   = sectionName,
                        title  = Properties.Strings.ResourceManager.GetString(string.Join("_", new string[] { "TemplateSection", Enum.GetName(typeof(RecordType), recordType), sectionName.Replace(" ", "_") })),
                        fields = new List <SectionField>()
                    };
                    sectionsByName.Add(sectionName, section);
                }

                string fieldName = itemFieldAttribute.fieldName ?? propertyInfo.Name;

                if (itemFieldAttribute.type == SectionFieldType.address && Attribute.IsDefined(propertyInfo, typeof(AddressComponentAttribute)))
                {
                    AddressSectionField addressSectionField = section.fields.Find(field => { return(fieldName.Equals(field.n)); }) as AddressSectionField;

                    if (addressSectionField == null)
                    {
                        addressSectionField = new AddressSectionField()
                        {
                            n = fieldName,
                            t = Properties.Strings.ResourceManager.GetString(string.Join("_", new string[] { "TemplateField", Enum.GetName(typeof(RecordType), recordType), fieldName.Replace(" ", "_") })),
                            v = new AddressValue(),
                            k = itemFieldAttribute.type
                        };
                        section.fields.Add(addressSectionField);
                    }

                    AddressComponentAttribute addressAttribute = Attribute.GetCustomAttribute(propertyInfo, typeof(AddressComponentAttribute)) as AddressComponentAttribute;

                    switch (addressAttribute.addressPart)
                    {
                    case AddressComponentAttribute.AddressPart.Address1:
                        addressSectionField.v.street = string.IsNullOrEmpty(addressSectionField.v.street) ? fieldValue : string.Join(Environment.NewLine, new string[] { fieldValue, addressSectionField.v.street });
                        break;

                    case AddressComponentAttribute.AddressPart.Address2:
                        addressSectionField.v.street = string.IsNullOrEmpty(addressSectionField.v.street) ? fieldValue : string.Join(Environment.NewLine, new string[] { addressSectionField.v.street, fieldValue });
                        break;

                    case AddressComponentAttribute.AddressPart.ZIP:
                        addressSectionField.v.zip = fieldValue;
                        break;

                    case AddressComponentAttribute.AddressPart.City:
                        addressSectionField.v.city = fieldValue;
                        break;

                    case AddressComponentAttribute.AddressPart.State:
                        addressSectionField.v.state = fieldValue;
                        break;

                    case AddressComponentAttribute.AddressPart.Region:
                        addressSectionField.v.region = fieldValue;
                        break;

                    case AddressComponentAttribute.AddressPart.Country:
                        addressSectionField.v.country = fieldValue;
                        break;

                    default:
                        break;
                    }
                }
                else if (itemFieldAttribute.type == SectionFieldType.date && Attribute.IsDefined(propertyInfo, typeof(DateComponentAttribute)))
                {
                    DateSectionField dateSectionField = section.fields.Find(field => { return(fieldName.Equals(field.n)); }) as DateSectionField;

                    if (dateSectionField == null)
                    {
                        dateSectionField = new DateSectionField()
                        {
                            n = fieldName,
                            t = Properties.Strings.ResourceManager.GetString(string.Join("_", new string[] { "TemplateField", Enum.GetName(typeof(RecordType), recordType), fieldName.Replace(" ", "_") })),
                            // 2000 is a leap year and January has 31 days. This guarantees no matter the order in which we add days,
                            // months or years to this base date, we won't get an invalid intermediate date (assuming a valid target date).
                            v = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc),
                            k = itemFieldAttribute.type
                        };
                        section.fields.Add(dateSectionField);
                    }

                    DateComponentAttribute dateAttribute = Attribute.GetCustomAttribute(propertyInfo, typeof(DateComponentAttribute)) as DateComponentAttribute;

                    int intFieldValue;

                    if (int.TryParse(fieldValue, out intFieldValue))
                    {
                        switch (dateAttribute.datePart)
                        {
                        case DateComponentAttribute.DatePart.Day:
                            dateSectionField.v = dateSectionField.v.AddDays(intFieldValue - dateSectionField.v.Day);
                            break;

                        case DateComponentAttribute.DatePart.Month:
                            dateSectionField.v = dateSectionField.v.AddMonths(intFieldValue - dateSectionField.v.Month);
                            break;

                        case DateComponentAttribute.DatePart.Year:
                            dateSectionField.v = dateSectionField.v.AddYears(intFieldValue - dateSectionField.v.Year);
                            break;

                        default:
                            break;
                        }
                    }
                }
                else if (itemFieldAttribute.type == SectionFieldType.monthYear && Attribute.IsDefined(propertyInfo, typeof(MonthYearComponentAttribute)))
                {
                    MonthYearSectionField monthYearSectionField = section.fields.Find(field => { return(fieldName.Equals(field.n)); }) as MonthYearSectionField;

                    if (monthYearSectionField == null)
                    {
                        monthYearSectionField = new MonthYearSectionField()
                        {
                            n = fieldName,
                            t = Properties.Strings.ResourceManager.GetString(string.Join("_", new string[] { "TemplateField", Enum.GetName(typeof(RecordType), recordType), fieldName.Replace(" ", "_") })),
                            // 2000 is a leap year and January has 31 days. This guarantees no matter the order in which we add days,
                            // months or years to this base date, we won't get an invalid intermediate date (assuming a valid target date).
                            v = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc),
                            k = itemFieldAttribute.type
                        };
                        section.fields.Add(monthYearSectionField);
                    }

                    MonthYearComponentAttribute monthYearAttribute = Attribute.GetCustomAttribute(propertyInfo, typeof(MonthYearComponentAttribute)) as MonthYearComponentAttribute;

                    int intFieldValue;

                    if (int.TryParse(fieldValue, out intFieldValue))
                    {
                        switch (monthYearAttribute.monthYearPart)
                        {
                        case MonthYearComponentAttribute.MonthYearPart.Month:
                            monthYearSectionField.v = monthYearSectionField.v.AddMonths(intFieldValue - monthYearSectionField.v.Month);
                            break;

                        case MonthYearComponentAttribute.MonthYearPart.Year:
                            monthYearSectionField.v = monthYearSectionField.v.AddYears(intFieldValue - monthYearSectionField.v.Year);
                            break;

                        default:
                            break;
                        }
                    }
                }
                else // the remaining field types are all GeneralSectionFields
                {
                    section.fields.Add(new GeneralSectionField()
                    {
                        n = fieldName,
                        t = Properties.Strings.ResourceManager.GetString(string.Join("_", new string[] { "TemplateField", Enum.GetName(typeof(RecordType), recordType), fieldName.Replace(" ", "_") })),
                        v = fieldValue,
                        k = itemFieldAttribute.type,
                        a = new SectionFieldAttributes()
                        {
                            multiline = itemFieldAttribute.multiline
                        }
                    });
                }
            }

            return(new List <SecureContentsSection>(sectionsByName.Values));
        }