diff options
Diffstat (limited to 'src/format/OpVaultReaderSections.cpp')
-rw-r--r-- | src/format/OpVaultReaderSections.cpp | 64 |
1 files changed, 48 insertions, 16 deletions
diff --git a/src/format/OpVaultReaderSections.cpp b/src/format/OpVaultReaderSections.cpp index 4dcf80e48..e59dd9f02 100644 --- a/src/format/OpVaultReaderSections.cpp +++ b/src/format/OpVaultReaderSections.cpp @@ -31,10 +31,29 @@ #include <QUrlQuery> #include <QUuid> +namespace +{ + QDateTime resolveDate(const QString& kind, const QJsonValue& value) + { + QDateTime date; + if (kind == "monthYear") { + // 1Password programmers are sadistic... + auto dateValue = QString::number(value.toInt()); + date = QDateTime::fromString(dateValue, "yyyyMM"); + date.setTimeSpec(Qt::UTC); + } else if (value.isString()) { + date = QDateTime::fromTime_t(value.toString().toUInt(), Qt::UTC); + } else { + date = QDateTime::fromTime_t(value.toInt(), Qt::UTC); + } + return date; + } +} // namespace + void OpVaultReader::fillFromSection(Entry* entry, const QJsonObject& section) { const auto uuid = entry->uuid(); - const QString& sectionName = section["name"].toString(); + QString sectionName = section["name"].toString(); if (!section.contains("fields")) { auto sectionNameLC = sectionName.toLower(); @@ -47,6 +66,12 @@ void OpVaultReader::fillFromSection(Entry* entry, const QJsonObject& section) qWarning() << R"(Skipping non-Array "fields" in UUID ")" << uuid << "\"\n"; return; } + + // If we have a default section name then replace with the section title if not empty + if (sectionName.startsWith("Section_") && !section["title"].toString().isEmpty()) { + sectionName = section["title"].toString(); + } + QJsonArray sectionFields = section["fields"].toArray(); for (const QJsonValue sectionField : sectionFields) { if (!sectionField.isObject()) { @@ -68,7 +93,7 @@ void OpVaultReader::fillFromSectionField(Entry* entry, const QString& sectionNam // Ignore "a" and "inputTraits" fields, they don't apply to KPXC auto attrName = resolveAttributeName(sectionName, field["n"].toString(), field["t"].toString()); - auto attrValue = field.value("v").toVariant().toString(); + auto attrValue = field.value("v").toString(); auto kind = field["k"].toString(); if (attrName.startsWith("TOTP_")) { @@ -82,30 +107,37 @@ void OpVaultReader::fillFromSectionField(Entry* entry, const QString& sectionNam query.addQueryItem("period", QString("%1").arg(Totp::DEFAULT_STEP)); } attrValue = query.toString(QUrl::FullyEncoded); - } - entry->setTotp(Totp::parseSettings(attrValue)); - } else if (attrName.startsWith("expir", Qt::CaseInsensitive)) { - QDateTime expiry; - if (kind == "date") { - expiry = QDateTime::fromTime_t(attrValue.toUInt(), Qt::UTC); + entry->setTotp(Totp::parseSettings(attrValue)); } else { - expiry = QDateTime::fromString(attrValue, "yyyyMM"); - expiry.setTimeSpec(Qt::UTC); + entry->setTotp(Totp::parseSettings({}, attrValue)); } + } else if (attrName.startsWith("expir", Qt::CaseInsensitive)) { + QDateTime expiry = resolveDate(kind, field.value("v")); if (expiry.isValid()) { entry->setExpiryTime(expiry); entry->setExpires(true); + } else { + qWarning() << QString("[%1] Invalid expiration date found: %2").arg(entry->title(), attrValue); } } else { - if (kind == "date") { - auto date = QDateTime::fromTime_t(attrValue.toUInt(), Qt::UTC); + if (kind == "date" || kind == "monthYear") { + QDateTime date = resolveDate(kind, field.value("v")); if (date.isValid()) { - attrValue = date.toString(); + entry->attributes()->set(attrName, date.toString(Qt::SystemLocaleShortDate)); + } else { + qWarning() + << QString("[%1] Invalid date attribute found: %2 = %3").arg(entry->title(), attrName, attrValue); } + } else if (kind == "address") { + // Expand address into multiple attributes + auto addrFields = field.value("v").toObject().toVariantMap(); + for (auto part : addrFields.keys()) { + entry->attributes()->set(attrName + QString("_%1").arg(part), addrFields.value(part).toString()); + } + } else { + entry->attributes()->set(attrName, attrValue, (kind == "password" || kind == "concealed")); } - - entry->attributes()->set(attrName, attrValue, (kind == "password" || kind == "concealed")); } } @@ -118,7 +150,7 @@ QString OpVaultReader::resolveAttributeName(const QString& section, const QStrin auto lowName = name.toLower(); auto lowText = text.toLower(); - if (section.isEmpty()) { + if (section.isEmpty() || name.startsWith("address")) { // Empty section implies these are core attributes // try to find username, password, url if (lowName == "password" || lowText == "password") { |