diff --git a/client/identity/identity.cpp b/client/identity/identity.cpp index 6b0ae09..193f4b4 100644 --- a/client/identity/identity.cpp +++ b/client/identity/identity.cpp @@ -1,814 +1,804 @@ /* SPDX-FileCopyrightText: 2002-2004 Marc Mutz SPDX-FileCopyrightText: 2007 Tom Albers SPDX-License-Identifier: LGPL-2.0-or-later */ #include "identity.h" #include "editor_debug.h" #include #include #include #include #include using namespace KIdentityManagementCore; static Identity *identityNull = nullptr; Q_DECLARE_METATYPE(KIdentityManagementCore::Signature) Identity::Identity(const QString &id, const QString &fullName, const QString &emailAddr, const QString &organization, const QString &replyToAddr) { qRegisterMetaType(); setProperty(QLatin1StringView(s_uoid), 0); setProperty(QLatin1StringView(s_identity), id); setProperty(QLatin1StringView(s_name), fullName); setProperty(QLatin1StringView(s_primaryEmail), emailAddr); setProperty(QLatin1StringView(s_organization), organization); setProperty(QLatin1StringView(s_replyto), replyToAddr); // FIXME KF6: Sonnet::defaultLanguageName is gone // setDictionary( Sonnet::defaultLanguageName() ); setProperty(QLatin1StringView(s_disabledFcc), false); setProperty(QLatin1StringView(s_defaultDomainName), QHostInfo::localHostName()); } const Identity &Identity::null() { if (!identityNull) { identityNull = new Identity; } return *identityNull; } bool Identity::isNull() const { QHash::const_iterator i = mPropertiesMap.constBegin(); while (i != mPropertiesMap.constEnd()) { const QString &key = i.key(); // Take into account that the defaultDomainName for a null identity is not empty if (key == QLatin1StringView(s_defaultDomainName)) { ++i; continue; } // Take into account that the dictionary for a null identity is not empty if (key == QLatin1StringView(s_dict)) { ++i; continue; } // Take into account that disableFcc == false for a null identity if (key == QLatin1StringView(s_disabledFcc) && i.value().toBool() == false) { ++i; continue; } // The uoid is 0 by default, so ignore this if (!(key == QLatin1StringView(s_uoid) && i.value().toUInt() == 0)) { if (!i.value().isNull() || (i.value().metaType().id() == QMetaType::QString && !i.value().toString().isEmpty())) { return false; } } ++i; } return true; } void Identity::readConfig(const KConfigGroup &config) { // get all keys and convert them to our QHash. QMap entries = config.entryMap(); QMap::const_iterator i = entries.constBegin(); QMap::const_iterator end = entries.constEnd(); while (i != end) { const QString &key = i.key(); if (key == QLatin1StringView(s_emailAliases)) { // HACK: Read s_emailAliases as a stringlist mPropertiesMap.insert(key, config.readEntry(key, QStringList())); } else { mPropertiesMap.insert(key, config.readEntry(key)); } ++i; } // needs to update to v5.21.41 // Check if we update to to encryption override mode // before we had only auto_encrypt and auto_sign and no global setting if (!mPropertiesMap.contains(QLatin1StringView(s_encryptionOverride)) && !mPropertiesMap.contains(QLatin1StringView(s_warnnotencrypt)) && !mPropertiesMap.contains(QLatin1StringView(s_warnnotsign))) { setEncryptionOverride(true); } mSignature.readConfig(config); } void Identity::writeConfig(KConfigGroup &config) const { QHash::const_iterator i = mPropertiesMap.constBegin(); QHash::const_iterator end = mPropertiesMap.constEnd(); while (i != end) { config.writeEntry(i.key(), i.value()); qCDebug(EDITOR_LOG) << "Store:" << i.key() << ":" << i.value(); ++i; } if (!mPropertiesMap.contains(QLatin1StringView(s_encryptionOverride))) { config.writeEntry(QLatin1StringView(s_encryptionOverride), false); qCDebug(EDITOR_LOG) << "Add" << s_encryptionOverride << ":" << false; } mSignature.writeConfig(config); } bool Identity::mailingAllowed() const { return !property(QLatin1StringView(s_primaryEmail)).toString().isEmpty(); } QString Identity::mimeDataType() { return QStringLiteral("application/x-kmail-identity-drag"); } bool Identity::canDecode(const QMimeData *md) { if (md) { return md->hasFormat(mimeDataType()); } else { return false; } } void Identity::populateMimeData(QMimeData *md) const { QByteArray a; { QDataStream s(&a, QIODevice::WriteOnly); s << *this; } md->setData(mimeDataType(), a); } Identity Identity::fromMimeData(const QMimeData *md) { Identity i; if (canDecode(md)) { QByteArray ba = md->data(mimeDataType()); QDataStream s(&ba, QIODevice::ReadOnly); s >> i; } return i; } // ------------------ Operators --------------------------// QDataStream &KIdentityManagementCore::operator<<(QDataStream &stream, const KIdentityManagementCore::Identity &i) { return stream << static_cast(i.uoid()) << i.mPropertiesMap[QLatin1StringView(s_identity)] << i.mPropertiesMap[QLatin1StringView(s_name)] << i.mPropertiesMap[QLatin1StringView(s_organization)] << i.mPropertiesMap[QLatin1StringView(s_pgps)] << i.mPropertiesMap[QLatin1StringView(s_pgpe)] << i.mPropertiesMap[QLatin1StringView(s_smimes)] << i.mPropertiesMap[QLatin1StringView(s_smimee)] << i.mPropertiesMap[QLatin1StringView(s_primaryEmail)] << i.mPropertiesMap[QLatin1StringView(s_emailAliases)] << i.mPropertiesMap[QLatin1StringView(s_replyto)] << i.mPropertiesMap[QLatin1StringView(s_bcc)] << i.mPropertiesMap[QLatin1StringView(s_vcard)] << i.mPropertiesMap[QLatin1StringView(s_transport)] << i.mPropertiesMap[QLatin1StringView(s_fcc)] << i.mPropertiesMap[QLatin1StringView(s_drafts)] << i.mPropertiesMap[QLatin1StringView(s_templates)] << i.mSignature << i.mPropertiesMap[QLatin1StringView(s_dict)] << i.mPropertiesMap[QLatin1StringView(s_xface)] << i.mPropertiesMap[QLatin1StringView(s_xfaceenabled)] << i.mPropertiesMap[QLatin1StringView(s_face)] << i.mPropertiesMap[QLatin1StringView(s_faceenabled)] << i.mPropertiesMap[QLatin1StringView(s_prefcrypt)] << i.mPropertiesMap[QLatin1StringView(s_cc)] << i.mPropertiesMap[QLatin1StringView(s_attachVcard)] << i.mPropertiesMap[QLatin1StringView(s_autocorrectionLanguage)] << i.mPropertiesMap[QLatin1StringView(s_disabledFcc)] << i.mPropertiesMap[QLatin1StringView(s_defaultDomainName)] << i.mPropertiesMap[QLatin1StringView(s_autocryptEnabled)] << i.mPropertiesMap[QLatin1StringView(s_autocryptPrefer)] << i.mPropertiesMap[QLatin1StringView(s_encryptionOverride)] << i.mPropertiesMap[QLatin1StringView(s_pgpautosign)] << i.mPropertiesMap[QLatin1StringView(s_pgpautoencrypt)] << i.mPropertiesMap[QLatin1StringView(s_warnnotencrypt)] << i.mPropertiesMap[QLatin1StringView(s_warnnotsign)]; } QDataStream &KIdentityManagementCore::operator>>(QDataStream &stream, KIdentityManagementCore::Identity &i) { quint32 uoid; stream >> uoid >> i.mPropertiesMap[QLatin1StringView(s_identity)] >> i.mPropertiesMap[QLatin1StringView(s_name)] >> i.mPropertiesMap[QLatin1StringView(s_organization)] >> i.mPropertiesMap[QLatin1StringView(s_pgps)] >> i.mPropertiesMap[QLatin1StringView(s_pgpe)] >> i.mPropertiesMap[QLatin1StringView(s_smimes)] >> i.mPropertiesMap[QLatin1StringView(s_smimee)] >> i.mPropertiesMap[QLatin1StringView(s_primaryEmail)] >> i.mPropertiesMap[QLatin1StringView(s_emailAliases)] >> i.mPropertiesMap[QLatin1StringView(s_replyto)] >> i.mPropertiesMap[QLatin1StringView(s_bcc)] >> i.mPropertiesMap[QLatin1StringView(s_vcard)] >> i.mPropertiesMap[QLatin1StringView(s_transport)] >> i.mPropertiesMap[QLatin1StringView(s_fcc)] >> i.mPropertiesMap[QLatin1StringView(s_drafts)] >> i.mPropertiesMap[QLatin1StringView(s_templates)] >> i.mSignature >> i.mPropertiesMap[QLatin1StringView(s_dict)] >> i.mPropertiesMap[QLatin1StringView(s_xface)] >> i.mPropertiesMap[QLatin1StringView(s_xfaceenabled)] >> i.mPropertiesMap[QLatin1StringView(s_face)] >> i.mPropertiesMap[QLatin1StringView(s_faceenabled)] >> i.mPropertiesMap[QLatin1StringView(s_prefcrypt)] >> i.mPropertiesMap[QLatin1StringView(s_cc)] >> i.mPropertiesMap[QLatin1StringView(s_attachVcard)] >> i.mPropertiesMap[QLatin1StringView(s_autocorrectionLanguage)] >> i.mPropertiesMap[QLatin1StringView(s_disabledFcc)] >> i.mPropertiesMap[QLatin1StringView(s_defaultDomainName)] >> i.mPropertiesMap[QLatin1StringView(s_autocryptEnabled)] >> i.mPropertiesMap[QLatin1StringView(s_autocryptPrefer)] >> i.mPropertiesMap[QLatin1StringView(s_encryptionOverride)] >> i.mPropertiesMap[QLatin1StringView(s_pgpautosign)] >> i.mPropertiesMap[QLatin1StringView(s_pgpautoencrypt)] >> i.mPropertiesMap[QLatin1StringView(s_warnnotencrypt)] >> i.mPropertiesMap[QLatin1StringView(s_warnnotsign)]; i.setProperty(QLatin1StringView(s_uoid), uoid); return stream; } bool Identity::operator<(const Identity &other) const { if (isDefault()) { return true; } if (other.isDefault()) { return false; } return identityName() < other.identityName(); } bool Identity::operator>(const Identity &other) const { if (isDefault()) { return false; } if (other.isDefault()) { return true; } return identityName() > other.identityName(); } bool Identity::operator<=(const Identity &other) const { return !operator>(other); } bool Identity::operator>=(const Identity &other) const { return !operator<(other); } bool Identity::operator==(const Identity &other) const { // The deserializer fills in the QHash will lots of invalid variants, which // is OK, but the CTOR doesn't fill the hash with the missing fields, so // regular mPropertiesMap == other.mPropertiesMap comparison will fail. // This algo considers both maps equal even if one map does not contain the // key and the other one contains the key but with an invalid value for (const auto &pair : {qMakePair(mPropertiesMap, other.mPropertiesMap), qMakePair(other.mPropertiesMap, mPropertiesMap)}) { const auto lhs = pair.first; const auto rhs = pair.second; for (auto lhsIt = lhs.constBegin(), lhsEnd = lhs.constEnd(); lhsIt != lhsEnd; ++lhsIt) { const auto rhsIt = rhs.constFind(lhsIt.key()); // Does the other map contain the key? if (rhsIt == rhs.constEnd()) { // It does not, so check if our value is invalid, if yes, consider it // equal to not present and continue if (lhsIt->isValid()) { return false; } } else if (lhsIt.value() != rhsIt.value()) { // Both maps have the key, but different value -> different maps return false; } } } return mSignature == other.mSignature; } bool Identity::operator!=(const Identity &other) const { return !operator==(other); } // --------------------- Getters -----------------------------// QVariant Identity::property(const QString &key) const { if (key == QLatin1StringView(s_signature)) { return QVariant::fromValue(mSignature); } else { return mPropertiesMap.value(key); } } QString Identity::fullEmailAddr() const { const QString name = mPropertiesMap.value(QLatin1StringView(s_name)).toString(); const QString mail = mPropertiesMap.value(QLatin1StringView(s_primaryEmail)).toString(); if (name.isEmpty()) { return mail; } const QString specials(QStringLiteral("()<>@,.;:[]")); QString result; // add DQUOTE's if necessary: bool needsQuotes = false; const int nameLength(name.length()); for (int i = 0; i < nameLength; i++) { if (specials.contains(name[i])) { needsQuotes = true; } else if (name[i] == QLatin1Char('\\') || name[i] == QLatin1Char('"')) { needsQuotes = true; result += QLatin1Char('\\'); } result += name[i]; } if (needsQuotes) { result.insert(0, QLatin1Char('"')); result += QLatin1Char('"'); } result += QLatin1StringView(" <") + mail + QLatin1Char('>'); return result; } QString Identity::identityName() const { return property(QLatin1StringView(s_identity)).toString(); } QString Identity::signatureText(bool *ok) const { return mSignature.withSeparator(ok); } bool Identity::signatureIsInlinedHtml() const { return mSignature.isInlinedHtml(); } bool Identity::isDefault() const { return mIsDefault; } uint Identity::uoid() const { return property(QLatin1StringView(s_uoid)).toInt(); } QString Identity::fullName() const { return property(QLatin1StringView(s_name)).toString(); } QString Identity::organization() const { return property(QLatin1StringView(s_organization)).toString(); } QByteArray Identity::pgpEncryptionKey() const { return property(QLatin1StringView(s_pgpe)).toByteArray(); } QByteArray Identity::pgpSigningKey() const { return property(QLatin1StringView(s_pgps)).toByteArray(); } QByteArray Identity::smimeEncryptionKey() const { return property(QLatin1StringView(s_smimee)).toByteArray(); } QByteArray Identity::smimeSigningKey() const { return property(QLatin1StringView(s_smimes)).toByteArray(); } -QString Identity::preferredCryptoMessageFormat() const -{ - return property(QLatin1StringView(s_prefcrypt)).toString(); -} - QString Identity::primaryEmailAddress() const { return property(QLatin1StringView(s_primaryEmail)).toString(); } const QStringList Identity::emailAliases() const { return property(QLatin1StringView(s_emailAliases)).toStringList(); } QString Identity::vCardFile() const { return property(QLatin1StringView(s_vcard)).toString(); } bool Identity::attachVcard() const { return property(QLatin1StringView(s_attachVcard)).toBool(); } QString Identity::replyToAddr() const { return property(QLatin1StringView(s_replyto)).toString(); } QString Identity::bcc() const { return property(QLatin1StringView(s_bcc)).toString(); } QString Identity::cc() const { return property(QLatin1StringView(s_cc)).toString(); } Signature &Identity::signature() { return mSignature; } bool Identity::isXFaceEnabled() const { return property(QLatin1StringView(s_xfaceenabled)).toBool(); } QString Identity::xface() const { return property(QLatin1StringView(s_xface)).toString(); } bool Identity::isFaceEnabled() const { return property(QLatin1StringView(s_faceenabled)).toBool(); } QString Identity::face() const { return property(QLatin1StringView(s_face)).toString(); } QString Identity::dictionary() const { return property(QLatin1StringView(s_dict)).toString(); } QString Identity::templates() const { const QString str = property(QLatin1StringView(s_templates)).toString(); return verifyAkonadiId(str); } QString Identity::drafts() const { const QString str = property(QLatin1StringView(s_drafts)).toString(); return verifyAkonadiId(str); } QString Identity::fcc() const { const QString str = property(QLatin1StringView(s_fcc)).toString(); return verifyAkonadiId(str); } QString Identity::transport() const { return property(QLatin1StringView(s_transport)).toString(); } bool Identity::signatureIsInline() const { return mSignature.type() == Signature::Inlined; } QString Identity::signatureInlineText() const { return mSignature.text(); } QString Identity::autocorrectionLanguage() const { return property(QLatin1StringView(s_autocorrectionLanguage)).toString(); } // --------------------- Setters -----------------------------// void Identity::setProperty(const QString &key, const QVariant &value) { if (key == QLatin1StringView(s_signature)) { mSignature = value.value(); } else { if (value.isNull() || (value.metaType().id() == QMetaType::QString && value.toString().isEmpty())) { mPropertiesMap.remove(key); } else { mPropertiesMap.insert(key, value); } } } void Identity::setUoid(uint aUoid) { setProperty(QLatin1StringView(s_uoid), aUoid); } void Identity::setIdentityName(const QString &name) { setProperty(QLatin1StringView(s_identity), name); } void Identity::setFullName(const QString &str) { setProperty(QLatin1StringView(s_name), str); } void Identity::setOrganization(const QString &str) { setProperty(QLatin1StringView(s_organization), str); } void Identity::setPGPSigningKey(const QByteArray &str) { setProperty(QLatin1StringView(s_pgps), QLatin1StringView(str)); } void Identity::setPGPEncryptionKey(const QByteArray &str) { setProperty(QLatin1StringView(s_pgpe), QLatin1StringView(str)); } void Identity::setSMIMESigningKey(const QByteArray &str) { setProperty(QLatin1StringView(s_smimes), QLatin1StringView(str)); } void Identity::setSMIMEEncryptionKey(const QByteArray &str) { setProperty(QLatin1StringView(s_smimee), QLatin1StringView(str)); } void Identity::setPrimaryEmailAddress(const QString &email) { setProperty(QLatin1StringView(s_primaryEmail), email); } void Identity::setEmailAliases(const QStringList &aliases) { setProperty(QLatin1StringView(s_emailAliases), aliases); } void Identity::setVCardFile(const QString &str) { setProperty(QLatin1StringView(s_vcard), str); } void Identity::setAttachVcard(bool attachment) { setProperty(QLatin1StringView(s_attachVcard), attachment); } void Identity::setReplyToAddr(const QString &str) { setProperty(QLatin1StringView(s_replyto), str); } void Identity::setSignatureInlineText(const QString &str) { mSignature.setText(str); } void Identity::setTransport(const QString &str) { setProperty(QLatin1StringView(s_transport), str); } void Identity::setFcc(const QString &str) { setProperty(QLatin1StringView(s_fcc), str); } void Identity::setDrafts(const QString &str) { setProperty(QLatin1StringView(s_drafts), str); } void Identity::setTemplates(const QString &str) { setProperty(QLatin1StringView(s_templates), str); } void Identity::setDictionary(const QString &str) { setProperty(QLatin1StringView(s_dict), str); } void Identity::setBcc(const QString &str) { setProperty(QLatin1StringView(s_bcc), str); } void Identity::setCc(const QString &str) { setProperty(QLatin1StringView(s_cc), str); } void Identity::setIsDefault(bool flag) { mIsDefault = flag; } -void Identity::setPreferredCryptoMessageFormat(const QString &str) -{ - setProperty(QLatin1StringView(s_prefcrypt), str); -} - void Identity::setXFace(const QString &str) { QString strNew = str; strNew.remove(QLatin1Char(' ')); strNew.remove(QLatin1Char('\n')); strNew.remove(QLatin1Char('\r')); setProperty(QLatin1StringView(s_xface), strNew); } void Identity::setXFaceEnabled(bool on) { setProperty(QLatin1StringView(s_xfaceenabled), on); } void Identity::setFace(const QString &str) { QString strNew = str; strNew.remove(QLatin1Char(' ')); strNew.remove(QLatin1Char('\n')); strNew.remove(QLatin1Char('\r')); setProperty(QLatin1StringView(s_face), strNew); } void Identity::setFaceEnabled(bool on) { setProperty(QLatin1StringView(s_faceenabled), on); } void Identity::setSignature(const Signature &sig) { mSignature = sig; } bool Identity::matchesEmailAddress(const QString &addr) const { const QString addrSpec = KEmailAddress::extractEmailAddress(addr).toLower(); if (addrSpec == primaryEmailAddress().toLower()) { return true; } const QStringList lst = emailAliases(); for (const QString &alias : lst) { if (alias.toLower() == addrSpec) { return true; } } return false; } void Identity::setAutocorrectionLanguage(const QString &language) { setProperty(QLatin1StringView(s_autocorrectionLanguage), language); } bool Identity::disabledFcc() const { const QVariant var = property(QLatin1StringView(s_disabledFcc)); if (var.isNull()) { return false; } else { return var.toBool(); } } void Identity::setDisabledFcc(bool disable) { setProperty(QLatin1StringView(s_disabledFcc), disable); } bool Identity::pgpAutoSign() const { const QVariant var = property(QLatin1StringView(s_pgpautosign)); if (var.isNull()) { return false; } else { return var.toBool(); } } void Identity::setPgpAutoSign(bool autoSign) { setProperty(QLatin1StringView(s_pgpautosign), autoSign); } bool Identity::pgpAutoEncrypt() const { const QVariant var = property(QLatin1StringView(s_pgpautoencrypt)); if (var.isNull()) { return false; } else { return var.toBool(); } } void Identity::setPgpAutoEncrypt(bool autoEncrypt) { setProperty(QLatin1StringView(s_pgpautoencrypt), autoEncrypt); } bool Identity::autocryptEnabled() const { const auto var = property(QLatin1StringView(s_autocryptEnabled)); if (var.isNull()) { return false; } else { return var.toBool(); } } void Identity::setAutocryptEnabled(const bool on) { setProperty(QLatin1StringView(s_autocryptEnabled), on); } bool Identity::autocryptPrefer() const { const auto var = property(QLatin1StringView(s_autocryptPrefer)); if (var.isNull()) { return false; } else { return var.toBool(); } } void Identity::setAutocryptPrefer(const bool on) { setProperty(QLatin1StringView(s_autocryptPrefer), on); } bool Identity::encryptionOverride() const { const auto var = property(QLatin1StringView(s_encryptionOverride)); if (var.isNull()) { return false; } else { return var.toBool(); } } void Identity::setEncryptionOverride(const bool on) { setProperty(QLatin1StringView(s_encryptionOverride), on); } bool Identity::warnNotEncrypt() const { const auto var = property(QLatin1StringView(s_warnnotencrypt)); if (var.isNull()) { return false; } else { return var.toBool(); } } void Identity::setWarnNotEncrypt(const bool on) { setProperty(QLatin1StringView(s_warnnotencrypt), on); } bool Identity::warnNotSign() const { const auto var = property(QLatin1StringView(s_warnnotsign)); if (var.isNull()) { return false; } else { return var.toBool(); } } void Identity::setWarnNotSign(const bool on) { setProperty(QLatin1StringView(s_warnnotsign), on); } QString Identity::defaultDomainName() const { return property(QLatin1StringView(s_defaultDomainName)).toString(); } void Identity::setDefaultDomainName(const QString &domainName) { setProperty(QLatin1StringView(s_defaultDomainName), domainName); } QString Identity::verifyAkonadiId(const QString &str) const { if (str.isEmpty()) { return str; } bool ok = false; const qlonglong val = str.toLongLong(&ok); Q_UNUSED(val) if (ok) { return str; } else { return {}; } } #include "moc_identity.cpp" diff --git a/client/identity/identity.h b/client/identity/identity.h index 8a976e8..f956667 100644 --- a/client/identity/identity.h +++ b/client/identity/identity.h @@ -1,455 +1,451 @@ /* SPDX-FileCopyrightText: 2002-2004 Marc Mutz SPDX-FileCopyrightText: 2007 Tom Albers Author: Stefan Taferner SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "signature.h" #include #include #include #include #include namespace KIdentityManagementCore { class Identity; } class KConfigGroup; class QDataStream; class QMimeData; namespace KIdentityManagementCore { static const char s_uoid[] = "uoid"; static const char s_identity[] = "Identity"; static const char s_name[] = "Name"; static const char s_organization[] = "Organization"; static const char s_pgps[] = "PGP Signing Key"; static const char s_pgpe[] = "PGP Encryption Key"; static const char s_smimes[] = "SMIME Signing Key"; static const char s_smimee[] = "SMIME Encryption Key"; static const char s_prefcrypt[] = "Preferred Crypto Message Format"; static const char s_primaryEmail[] = "Email Address"; static const char s_replyto[] = "Reply-To Address"; static const char s_bcc[] = "Bcc"; static const char s_cc[] = "Cc"; static const char s_vcard[] = "VCardFile"; static const char s_transport[] = "Transport"; static const char s_fcc[] = "Fcc"; static const char s_drafts[] = "Drafts"; static const char s_templates[] = "Templates"; static const char s_dict[] = "Dictionary"; static const char s_xface[] = "X-Face"; static const char s_xfaceenabled[] = "X-FaceEnabled"; static const char s_face[] = "Face"; static const char s_faceenabled[] = "FaceEnabled"; static const char s_signature[] = "Signature"; static const char s_emailAliases[] = "Email Aliases"; static const char s_attachVcard[] = "Attach Vcard"; static const char s_autocorrectionLanguage[] = "Autocorrection Language"; static const char s_disabledFcc[] = "Disable Fcc"; static const char s_encryptionOverride[] = "Override Encryption Defaults"; static const char s_pgpautosign[] = "Pgp Auto Sign"; static const char s_pgpautoencrypt[] = "Pgp Auto Encrypt"; static const char s_warnnotsign[] = "Warn not Sign"; static const char s_warnnotencrypt[] = "Warn not Encrypt"; static const char s_defaultDomainName[] = "Default Domain"; static const char s_autocryptEnabled[] = "Autocrypt"; static const char s_autocryptPrefer[] = "Autocrypt Prefer"; QDataStream &operator<<(QDataStream &stream, const KIdentityManagementCore::Identity &ident); QDataStream &operator>>(QDataStream &stream, KIdentityManagementCore::Identity &ident); /** User identity information */ class Identity { Q_GADGET Q_PROPERTY(bool mailingAllowed READ mailingAllowed) Q_PROPERTY(QString identityName READ identityName WRITE setIdentityName) Q_PROPERTY(QString fullName READ fullName WRITE setFullName) Q_PROPERTY(QString organization READ organization WRITE setOrganization) Q_PROPERTY(QByteArray pgpEncryptionKey READ pgpEncryptionKey WRITE setPGPEncryptionKey) Q_PROPERTY(QByteArray pgpSigningKey READ pgpSigningKey WRITE setPGPSigningKey) Q_PROPERTY(QByteArray smimeEncryptionKey READ smimeEncryptionKey WRITE setSMIMEEncryptionKey) Q_PROPERTY(QByteArray smimeSigningKey READ smimeSigningKey WRITE setSMIMESigningKey) - Q_PROPERTY(QString preferredCryptoMessageFormat READ preferredCryptoMessageFormat WRITE setPreferredCryptoMessageFormat) Q_PROPERTY(QString primaryEmailAddress READ primaryEmailAddress WRITE setPrimaryEmailAddress) Q_PROPERTY(QStringList emailAliases READ emailAliases WRITE setEmailAliases) Q_PROPERTY(QString vCardFile READ vCardFile WRITE setVCardFile) Q_PROPERTY(QString fullEmailAddr READ fullEmailAddr) Q_PROPERTY(QString replyToAddr READ replyToAddr WRITE setReplyToAddr) Q_PROPERTY(QString bcc READ bcc WRITE setBcc) Q_PROPERTY(QString cc READ cc WRITE setCc) Q_PROPERTY(bool attachVcard READ attachVcard WRITE setAttachVcard) Q_PROPERTY(QString autocorrectionLanguage READ autocorrectionLanguage WRITE setAutocorrectionLanguage) Q_PROPERTY(bool disabledFcc READ disabledFcc WRITE setDisabledFcc) Q_PROPERTY(bool pgpAutoSign READ pgpAutoSign WRITE setPgpAutoSign) Q_PROPERTY(bool pgpAutoEncrypt READ pgpAutoEncrypt WRITE setPgpAutoEncrypt) Q_PROPERTY(bool autocryptEnabled READ autocryptEnabled WRITE setAutocryptEnabled) Q_PROPERTY(bool autocryptPrefer READ autocryptPrefer WRITE setAutocryptPrefer) Q_PROPERTY(bool encryptionOverride READ encryptionOverride WRITE setEncryptionOverride) Q_PROPERTY(bool warnNotSign READ warnNotSign WRITE setWarnNotSign) Q_PROPERTY(bool warnNotEncrypt READ warnNotEncrypt WRITE setWarnNotEncrypt) Q_PROPERTY(QString defaultDomainName READ defaultDomainName WRITE setDefaultDomainName) Q_PROPERTY(Signature signature READ signature WRITE setSignature) Q_PROPERTY(QString signatureText READ signatureText) Q_PROPERTY(bool signatureIsInlinedHtml READ signatureIsInlinedHtml) Q_PROPERTY(QString transport READ transport WRITE setTransport) Q_PROPERTY(QString fcc READ fcc WRITE setFcc) Q_PROPERTY(QString drafts READ drafts WRITE setDrafts) Q_PROPERTY(QString templates READ templates WRITE setTemplates) Q_PROPERTY(QString dictionary READ dictionary WRITE setDictionary) Q_PROPERTY(QString xface READ xface WRITE setXFace) Q_PROPERTY(bool isXFaceEnabled READ isXFaceEnabled WRITE setXFaceEnabled) Q_PROPERTY(QString face READ face WRITE setFace) Q_PROPERTY(bool isFaceEnabled READ isFaceEnabled WRITE setFaceEnabled) Q_PROPERTY(uint uoid READ uoid CONSTANT) Q_PROPERTY(bool isNull READ isNull) // only the identity manager should be able to construct and // destruct us, but then we get into problems with using // QValueList and especially qHeapSort(). friend class IdentityManager; friend QDataStream &operator<<(QDataStream &stream, const KIdentityManagementCore::Identity &ident); friend QDataStream &operator>>(QDataStream &stream, KIdentityManagementCore::Identity &ident); public: using List = QList; using Id = uint; /** Constructor */ explicit Identity(const QString &id = QString(), const QString &realName = QString(), const QString &emailAddr = QString(), const QString &organization = QString(), const QString &replyToAddress = QString()); /** used for comparison */ bool operator==(const Identity &other) const; /** used for comparison */ bool operator!=(const Identity &other) const; /** used for sorting */ bool operator<(const Identity &other) const; /** used for sorting */ bool operator>(const Identity &other) const; /** used for sorting */ bool operator<=(const Identity &other) const; /** used for sorting */ bool operator>=(const Identity &other) const; /** Tests if there are enough values set to allow mailing */ [[nodiscard]] bool mailingAllowed() const; /** Identity/nickname for this collection */ [[nodiscard]] QString identityName() const; /** Identity/nickname for this collection */ void setIdentityName(const QString &name); /** @return whether this identity is the default identity */ [[nodiscard]] bool isDefault() const; /** Unique Object Identifier for this identity */ [[nodiscard]] uint uoid() const; /** Full name of the user */ [[nodiscard]] QString fullName() const; void setFullName(const QString &); /** The user's organization (optional) */ [[nodiscard]] QString organization() const; void setOrganization(const QString &); /** The user's OpenPGP encryption key */ [[nodiscard]] QByteArray pgpEncryptionKey() const; void setPGPEncryptionKey(const QByteArray &key); /** The user's OpenPGP signing key */ [[nodiscard]] QByteArray pgpSigningKey() const; void setPGPSigningKey(const QByteArray &key); /** The user's S/MIME encryption key */ [[nodiscard]] QByteArray smimeEncryptionKey() const; void setSMIMEEncryptionKey(const QByteArray &key); /** The user's S/MIME signing key */ [[nodiscard]] QByteArray smimeSigningKey() const; void setSMIMESigningKey(const QByteArray &key); - [[nodiscard]] QString preferredCryptoMessageFormat() const; - void setPreferredCryptoMessageFormat(const QString &); - /** * The primary email address (without the user name - only name\@host). * * This email address is used for all outgoing mail. * * @since 4.6 */ [[nodiscard]] QString primaryEmailAddress() const; void setPrimaryEmailAddress(const QString &email); /** * The email address aliases * * @since 4.6 */ [[nodiscard]] const QStringList emailAliases() const; void setEmailAliases(const QStringList &aliases); /** * @param addr the email address to check * @return true if this identity contains the email address @p addr, either as primary address * or as alias * * @since 4.6 */ [[nodiscard]] bool matchesEmailAddress(const QString &addr) const; /** vCard to attach to outgoing emails */ [[nodiscard]] QString vCardFile() const; void setVCardFile(const QString &); /** * The email address in the format "username " suitable * for the "From:" field of email messages. */ [[nodiscard]] QString fullEmailAddr() const; /** @return The email address for the ReplyTo: field */ [[nodiscard]] QString replyToAddr() const; void setReplyToAddr(const QString &); /** @return The email addresses for the BCC: field */ [[nodiscard]] QString bcc() const; void setBcc(const QString &); /** * @return The email addresses for the CC: field * @since 4.9 */ [[nodiscard]] QString cc() const; void setCc(const QString &); /** * @return true if the Vcard of this identity should be attached to outgoing mail. * @since 4.10 */ [[nodiscard]] bool attachVcard() const; void setAttachVcard(bool attach); /** * @return The default language for spell checking of this identity. * @since 4.10 */ [[nodiscard]] QString autocorrectionLanguage() const; void setAutocorrectionLanguage(const QString &language); /** * @return true if Fcc is disabled for this identity. * @since 4.11 */ [[nodiscard]] bool disabledFcc() const; void setDisabledFcc(bool); /** * @return true if we should sign message sent by this identity by default. * @since 4.12 */ [[nodiscard]] bool pgpAutoSign() const; void setPgpAutoSign(bool); /** * @return true if we should encrypt message sent by this identity by default. * @since 5.4 */ [[nodiscard]] bool pgpAutoEncrypt() const; void setPgpAutoEncrypt(bool); /** * @return true if Autocrypt is enabled for this identity. * @since 5.17 */ [[nodiscard]] bool autocryptEnabled() const; void setAutocryptEnabled(const bool); /** * @return true if Autocrypt is preferred for this identity. * @since 5.22 */ [[nodiscard]] bool autocryptPrefer() const; void setAutocryptPrefer(const bool); /** * @return true if the warnNotSign and warnNotEncrypt identity configuration should * overwrite the global app-wide configuration. * @since 5.22 */ [[nodiscard]] bool encryptionOverride() const; void setEncryptionOverride(const bool); /** * @return true if we should warn if parts of the message this identity is about to send are not signed. * @since 5.22 */ [[nodiscard]] bool warnNotSign() const; void setWarnNotSign(const bool); /** * @return true if we should warn if parts of the message this identity is about to send are not encrypted. * @since 5.22 */ [[nodiscard]] bool warnNotEncrypt() const; void setWarnNotEncrypt(const bool); /** * @return The default domain name * @since 4.14 */ [[nodiscard]] QString defaultDomainName() const; void setDefaultDomainName(const QString &domainName); /** * @return The signature of the identity. * * @warning This method is not const. */ [[nodiscard]] Signature &signature(); void setSignature(const Signature &sig); /** * @return the signature with '-- \n' prepended to it if it is not * present already. * No newline in front of or after the signature is added. * @param ok if a valid bool pointer, it is set to @c true or @c false depending * on whether the signature could successfully be obtained. */ [[nodiscard]] QString signatureText(bool *ok = nullptr) const; /** * @return true if the inlined signature is html formatted * @since 4.1 */ [[nodiscard]] bool signatureIsInlinedHtml() const; /** The transport that is set for this identity. Used to link a transport with an identity. */ [[nodiscard]] QString transport() const; void setTransport(const QString &); /** The folder where sent messages from this identity will be stored by default. */ [[nodiscard]] QString fcc() const; void setFcc(const QString &); /** The folder where draft messages from this identity will be stored by default. */ [[nodiscard]] QString drafts() const; void setDrafts(const QString &); /** The folder where template messages from this identity will be stored by default. */ [[nodiscard]] QString templates() const; void setTemplates(const QString &); /** * Dictionary which should be used for spell checking * * Note that this is the localized language name (e.g. "British English"), * _not_ the language code or dictionary name! */ [[nodiscard]] QString dictionary() const; void setDictionary(const QString &); /** a X-Face header for this identity */ [[nodiscard]] QString xface() const; void setXFace(const QString &); [[nodiscard]] bool isXFaceEnabled() const; void setXFaceEnabled(bool); /** a Face header for this identity */ [[nodiscard]] QString face() const; void setFace(const QString &); [[nodiscard]] bool isFaceEnabled() const; void setFaceEnabled(bool); /** Get random properties * @param key the key of the property to get */ [[nodiscard]] QVariant property(const QString &key) const; /** Set random properties, when @p value is empty (for QStrings) or null, the property is deleted. */ void setProperty(const QString &key, const QVariant &value); static const Identity &null(); /** Returns true when the identity contains no values, all null values or only empty values */ [[nodiscard]] bool isNull() const; [[nodiscard]] static QString mimeDataType(); [[nodiscard]] static bool canDecode(const QMimeData *); void populateMimeData(QMimeData *) const; static Identity fromMimeData(const QMimeData *); /** Read configuration from config. Group must be preset (or use KConfigGroup). Called from IdentityManager. */ void readConfig(const KConfigGroup &); /** Write configuration to config. Group must be preset (or use KConfigGroup). Called from IdentityManager. */ void writeConfig(KConfigGroup &) const; /** Set whether this identity is the default identity. Since this affects all other identities, too (most notably, the old default identity), only the IdentityManager can change this. You should use
         kmkernel->identityManager()->setAsDefault( name_of_default )
         
instead. */ void setIsDefault(bool flag); /** * Set the uiod * @param aUoid the uoid to set */ void setUoid(uint aUoid); protected: /** during migration when it failed it can be a string => not a qlonglong akonadi::id => fix it*/ [[nodiscard]] QString verifyAkonadiId(const QString &str) const; /** @return true if the signature was specified directly */ [[nodiscard]] bool signatureIsInline() const; /** inline signature */ [[nodiscard]] QString signatureInlineText() const; void setSignatureInlineText(const QString &); /** Inline or signature from a file */ [[nodiscard]] bool useSignatureFile() const; Signature mSignature; bool mIsDefault = false; QHash mPropertiesMap; }; } #ifndef UNITY_CMAKE_SUPPORT Q_DECLARE_METATYPE(KIdentityManagementCore::Identity) #endif diff --git a/client/identity/identitydialog.cpp b/client/identity/identitydialog.cpp index f8e5865..54ad125 100644 --- a/client/identity/identitydialog.cpp +++ b/client/identity/identitydialog.cpp @@ -1,620 +1,606 @@ /* identitydialog.cpp This file is part of KMail, the KDE mail client. SPDX-FileCopyrightText: 2002 Marc Mutz SPDX-FileCopyrightText: 2014-2023 Laurent Montel SPDX-License-Identifier: GPL-2.0-only */ #include "identitydialog.h" #include "identitymanager.h" #include "addressvalidationjob.h" #include "kleo_util.h" #include #include // other KMail headers: #include #include // other kdepim headers: #include "identity/identity.h" #include "identity/signatureconfigurator.h" #include // libkleopatra: #include #include #include #include // gpgme++ #include // other KDE headers: #include #include #include #include #include // Qt headers: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // other headers: #include #include #include namespace KMail { class KeySelectionCombo : public Kleo::KeySelectionCombo { Q_OBJECT public: enum KeyType { SigningKey, EncryptionKey, }; explicit KeySelectionCombo(KeyType keyType, GpgME::Protocol protocol, QWidget *parent); ~KeySelectionCombo() override; void setIdentity(const QString &name, const QString &email); void init() override; private: void onCustomItemSelected(const QVariant &type); QString mEmail; QString mName; const KeyType mKeyType; const GpgME::Protocol mProtocol; }; class KeyGenerationJob : public QGpgME::Job { Q_OBJECT public: explicit KeyGenerationJob(const QString &name, const QString &email, KeySelectionCombo *parent); ~KeyGenerationJob() override; void slotCancel() override; void start(); private: void keyGenerated(const GpgME::KeyGenerationResult &result); const QString mName; const QString mEmail; QGpgME::Job *mJob = nullptr; }; KeyGenerationJob::KeyGenerationJob(const QString &name, const QString &email, KeySelectionCombo *parent) : QGpgME::Job(parent) , mName(name) , mEmail(email) { } KeyGenerationJob::~KeyGenerationJob() = default; void KeyGenerationJob::slotCancel() { if (mJob) { mJob->slotCancel(); } } void KeyGenerationJob::start() { auto job = new Kleo::DefaultKeyGenerationJob(this); connect(job, &Kleo::DefaultKeyGenerationJob::result, this, &KeyGenerationJob::keyGenerated); job->start(mEmail, mName); mJob = job; } void KeyGenerationJob::keyGenerated(const GpgME::KeyGenerationResult &result) { mJob = nullptr; if (result.error()) { KMessageBox::error(qobject_cast(parent()), i18n("Error while generating new key pair: %1", QString::fromUtf8(result.error().asString())), i18n("Key Generation Error")); Q_EMIT done(); return; } auto combo = qobject_cast(parent()); combo->setDefaultKey(QLatin1String(result.fingerprint())); connect(combo, &KeySelectionCombo::keyListingFinished, this, &KeyGenerationJob::done); combo->refreshKeys(); } KeySelectionCombo::KeySelectionCombo(KeyType keyType, GpgME::Protocol protocol, QWidget *parent) : Kleo::KeySelectionCombo(parent) , mKeyType(keyType) , mProtocol(protocol) { } KeySelectionCombo::~KeySelectionCombo() = default; void KeySelectionCombo::setIdentity(const QString &name, const QString &email) { mName = name; mEmail = email; setIdFilter(email); } void KeySelectionCombo::init() { Kleo::KeySelectionCombo::init(); std::shared_ptr keyFilter(new Kleo::DefaultKeyFilter); keyFilter->setIsOpenPGP(mProtocol == GpgME::OpenPGP ? Kleo::DefaultKeyFilter::Set : Kleo::DefaultKeyFilter::NotSet); if (mKeyType == SigningKey) { keyFilter->setCanSign(Kleo::DefaultKeyFilter::Set); keyFilter->setHasSecret(Kleo::DefaultKeyFilter::Set); } else { keyFilter->setCanEncrypt(Kleo::DefaultKeyFilter::Set); } setKeyFilter(keyFilter); prependCustomItem(QIcon(), i18n("No key"), QStringLiteral("no-key")); if (mProtocol == GpgME::OpenPGP) { appendCustomItem(QIcon::fromTheme(QStringLiteral("password-generate")), i18n("Generate a new key pair"), QStringLiteral("generate-new-key")); } connect(this, &KeySelectionCombo::customItemSelected, this, &KeySelectionCombo::onCustomItemSelected); } void KeySelectionCombo::onCustomItemSelected(const QVariant &type) { if (type == QLatin1String("no-key")) { return; } else if (type == QLatin1String("generate-new-key")) { auto job = new KeyGenerationJob(mName, mEmail, this); auto dlg = new Kleo::ProgressDialog(job, i18n("Generating new key pair..."), parentWidget()); dlg->setModal(true); setEnabled(false); connect(job, &KeyGenerationJob::done, this, [this]() { setEnabled(true); }); job->start(); } } IdentityDialog::IdentityDialog(QWidget *parent) : QDialog(parent) { setWindowTitle(i18nc("@title:window", "Edit Identity")); auto mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins({}); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &IdentityDialog::slotAccepted); connect(buttonBox, &QDialogButtonBox::rejected, this, &IdentityDialog::reject); // // Tab Widget: General // auto page = new QWidget(this); mainLayout->addWidget(page); auto buttonBoxLayout = new QVBoxLayout; buttonBoxLayout->setContentsMargins(style()->pixelMetric(QStyle::PM_LayoutLeftMargin), style()->pixelMetric(QStyle::PM_LayoutTopMargin), style()->pixelMetric(QStyle::PM_LayoutRightMargin), style()->pixelMetric(QStyle::PM_LayoutBottomMargin)); buttonBoxLayout->addWidget(buttonBox); mainLayout->addLayout(buttonBoxLayout); auto vlay = new QVBoxLayout(page); vlay->setContentsMargins({}); mTabWidget = new QTabWidget(page); mTabWidget->tabBar()->setExpanding(true); mTabWidget->setDocumentMode(true); mTabWidget->setObjectName(QStringLiteral("config-identity-tab")); vlay->addWidget(mTabWidget); auto tab = new QWidget(mTabWidget); mTabWidget->addTab(tab, i18nc("@title:tab General identity settings.", "General")); auto formLayout = new QFormLayout(tab); // "Name" line edit and label: mNameEdit = new QLineEdit(tab); KLineEditEventHandler::catchReturnKey(mNameEdit); auto label = new QLabel(i18n("&Your name:"), tab); formLayout->addRow(label, mNameEdit); label->setBuddy(mNameEdit); QString msg = i18n( "

Your name

" "

This field should contain your name as you would like " "it to appear in the email header that is sent out;

" "

if you leave this blank your real name will not " "appear, only the email address.

"); label->setWhatsThis(msg); mNameEdit->setWhatsThis(msg); // "Organization" line edit and label: mOrganizationEdit = new QLineEdit(tab); KLineEditEventHandler::catchReturnKey(mOrganizationEdit); label = new QLabel(i18n("Organi&zation:"), tab); formLayout->addRow(label, mOrganizationEdit); label->setBuddy(mOrganizationEdit); msg = i18n( "

Organization

" "

This field should have the name of your organization " "if you would like it to be shown in the email header that " "is sent out.

" "

It is safe (and normal) to leave this blank.

"); label->setWhatsThis(msg); mOrganizationEdit->setWhatsThis(msg); // "Dictionary" combo box and label: mDictionaryCombo = new Sonnet::DictionaryComboBox(tab); label = new QLabel(i18n("D&ictionary:"), tab); label->setBuddy(mDictionaryCombo); formLayout->addRow(label, mDictionaryCombo); // "Email Address" line edit and label: // (row 3: spacer) mEmailEdit = new QLineEdit(tab); mEmailEdit->setEnabled(false); KLineEditEventHandler::catchReturnKey(mEmailEdit); label = new QLabel(i18n("&Email address:"), tab); formLayout->addRow(label, mEmailEdit); label->setBuddy(mEmailEdit); msg = i18n( "

Email address

" "

This field should have your full email address.

" "

This address is the primary one, used for all outgoing mail. " "If you have more than one address, either create a new identity, " "or add additional alias addresses in the field below.

" "

If you leave this blank, or get it wrong, people " "will have trouble replying to you.

"); label->setWhatsThis(msg); mEmailEdit->setWhatsThis(msg); auto emailValidator = new KEmailValidator(this); mEmailEdit->setValidator(emailValidator); // // Tab Widget: Security // mCryptographyTab = new QWidget(mTabWidget); mTabWidget->addTab(mCryptographyTab, i18nc("@title:tab", "Security")); formLayout = new QFormLayout(mCryptographyTab); // "OpenPGP Signature Key" requester and label: mPGPSigningKeyRequester = new KeySelectionCombo(KeySelectionCombo::SigningKey, GpgME::OpenPGP, mCryptographyTab); mPGPSigningKeyRequester->setObjectName("PGP Signing Key Requester"); msg = i18n( "

The OpenPGP key you choose here will be used " "to digitally sign messages. You can also use GnuPG keys.

" "

You can leave this blank, but KMail will not be able " "to digitally sign emails using OpenPGP; " "normal mail functions will not be affected.

" "

You can find out more about keys at https://www.gnupg.org

"); label = new QLabel(i18n("OpenPGP signing key:"), mCryptographyTab); label->setBuddy(mPGPSigningKeyRequester); mPGPSigningKeyRequester->setWhatsThis(msg); label->setWhatsThis(msg); auto vbox = new QVBoxLayout; mPGPSameKey = new QCheckBox(i18n("Use same key for encryption and signing")); vbox->addWidget(mPGPSigningKeyRequester); vbox->addWidget(mPGPSameKey); formLayout->addRow(label, vbox); connect(mPGPSameKey, &QCheckBox::toggled, this, [=](bool checked) { mPGPEncryptionKeyRequester->setVisible(!checked); formLayout->labelForField(mPGPEncryptionKeyRequester)->setVisible(!checked); const auto label = qobject_cast(formLayout->labelForField(vbox)); if (checked) { label->setText(i18n("OpenPGP key:")); const auto key = mPGPSigningKeyRequester->currentKey(); if (!key.isBad()) { mPGPEncryptionKeyRequester->setCurrentKey(key); } else if (mPGPSigningKeyRequester->currentData() == QLatin1String("no-key")) { mPGPEncryptionKeyRequester->setCurrentIndex(mPGPSigningKeyRequester->currentIndex()); } } else { label->setText(i18n("OpenPGP signing key:")); } }); connect(mPGPSigningKeyRequester, &KeySelectionCombo::currentKeyChanged, this, [&](const GpgME::Key &key) { if (mPGPSameKey->isChecked()) { mPGPEncryptionKeyRequester->setCurrentKey(key); } }); connect(mPGPSigningKeyRequester, &KeySelectionCombo::customItemSelected, this, [&](const QVariant &type) { if (mPGPSameKey->isChecked() && type == QLatin1String("no-key")) { mPGPEncryptionKeyRequester->setCurrentIndex(mPGPSigningKeyRequester->currentIndex()); } }); connect(mPGPSigningKeyRequester, &KeySelectionCombo::keyListingFinished, this, [this] { slotKeyListingFinished(mPGPSigningKeyRequester); }); // "OpenPGP Encryption Key" requester and label: mPGPEncryptionKeyRequester = new KeySelectionCombo(KeySelectionCombo::EncryptionKey, GpgME::OpenPGP, mCryptographyTab); msg = i18n( "

The OpenPGP key you choose here will be used " "to encrypt messages to yourself and for the \"Attach My Public Key\" " "feature in the composer. You can also use GnuPG keys.

" "

You can leave this blank, but KMail will not be able " "to encrypt copies of outgoing messages to you using OpenPGP; " "normal mail functions will not be affected.

" "

You can find out more about keys at https://www.gnupg.org

"); label = new QLabel(i18n("OpenPGP encryption key:"), mCryptographyTab); label->setBuddy(mPGPEncryptionKeyRequester); label->setWhatsThis(msg); mPGPEncryptionKeyRequester->setWhatsThis(msg); formLayout->addRow(label, mPGPEncryptionKeyRequester); // "S/MIME Signature Key" requester and label: mSMIMESigningKeyRequester = new KeySelectionCombo(KeySelectionCombo::SigningKey, GpgME::CMS, mCryptographyTab); mSMIMESigningKeyRequester->setObjectName("SMIME Signing Key Requester"); msg = i18n( "

The S/MIME (X.509) certificate you choose here will be used " "to digitally sign messages.

" "

You can leave this blank, but KMail will not be able " "to digitally sign emails using S/MIME; " "normal mail functions will not be affected.

"); label = new QLabel(i18n("S/MIME signing certificate:"), mCryptographyTab); label->setBuddy(mSMIMESigningKeyRequester); mSMIMESigningKeyRequester->setWhatsThis(msg); label->setWhatsThis(msg); formLayout->addRow(label, mSMIMESigningKeyRequester); connect(mSMIMESigningKeyRequester, &KeySelectionCombo::keyListingFinished, this, [this] { slotKeyListingFinished(mSMIMESigningKeyRequester); }); const QGpgME::Protocol *smimeProtocol = QGpgME::smime(); label->setEnabled(smimeProtocol); mSMIMESigningKeyRequester->setEnabled(smimeProtocol); // "S/MIME Encryption Key" requester and label: mSMIMEEncryptionKeyRequester = new KeySelectionCombo(KeySelectionCombo::EncryptionKey, GpgME::CMS, mCryptographyTab); mSMIMEEncryptionKeyRequester->setObjectName("SMIME Encryption Key Requester"); msg = i18n( "

The S/MIME certificate you choose here will be used " "to encrypt messages to yourself and for the \"Attach My Certificate\" " "feature in the composer.

" "

You can leave this blank, but KMail will not be able " "to encrypt copies of outgoing messages to you using S/MIME; " "normal mail functions will not be affected.

"); label = new QLabel(i18n("S/MIME encryption certificate:"), mCryptographyTab); label->setBuddy(mSMIMEEncryptionKeyRequester); mSMIMEEncryptionKeyRequester->setWhatsThis(msg); connect(mSMIMEEncryptionKeyRequester, &KeySelectionCombo::keyListingFinished, this, [this] { slotKeyListingFinished(mSMIMEEncryptionKeyRequester); }); label->setWhatsThis(msg); formLayout->addRow(label, mSMIMEEncryptionKeyRequester); label->setEnabled(smimeProtocol); mSMIMEEncryptionKeyRequester->setEnabled(smimeProtocol); - // "Preferred Crypto Message Format" combobox and label: - mPreferredCryptoMessageFormat = new QComboBox(mCryptographyTab); - QStringList l; - l << Kleo::cryptoMessageFormatToLabel(Kleo::AutoFormat) << Kleo::cryptoMessageFormatToLabel(Kleo::InlineOpenPGPFormat) - << Kleo::cryptoMessageFormatToLabel(Kleo::OpenPGPMIMEFormat) << Kleo::cryptoMessageFormatToLabel(Kleo::SMIMEFormat) - << Kleo::cryptoMessageFormatToLabel(Kleo::SMIMEOpaqueFormat); - mPreferredCryptoMessageFormat->addItems(l); - label = new QLabel(i18nc("preferred format of encrypted messages", "Preferred format:"), mCryptographyTab); - label->setBuddy(mPreferredCryptoMessageFormat); - - formLayout->addRow(label, mPreferredCryptoMessageFormat); - mWarnNotEncrypt = new QCheckBox(i18n("Warn when trying to send unencrypted messages")); formLayout->addRow(QString(), mWarnNotEncrypt); // // Tab Widget: Signature // mSignatureConfigurator = new KIdentityManagementWidgets::SignatureConfigurator(mTabWidget); mTabWidget->addTab(mSignatureConfigurator, i18n("Signature")); } IdentityDialog::~IdentityDialog() = default; void IdentityDialog::slotAccepted() { // Validate email addresses const QString email = mEmailEdit->text().trimmed(); if (email.isEmpty()) { KMessageBox::error(this, i18n("You must provide an email for this identity."), i18nc("@title:window", "Empty Email Address")); return; } if (!KEmailAddress::isValidSimpleAddress(email)) { const QString errorMsg(KEmailAddress::simpleEmailAddressErrorMsg()); KMessageBox::error(this, errorMsg, i18n("Invalid Email Address")); return; } const GpgME::Key &pgpSigningKey = mPGPSigningKeyRequester->currentKey(); const GpgME::Key &pgpEncryptionKey = mPGPEncryptionKeyRequester->currentKey(); const GpgME::Key &smimeSigningKey = mSMIMESigningKeyRequester->currentKey(); const GpgME::Key &smimeEncryptionKey = mSMIMEEncryptionKeyRequester->currentKey(); QString msg; bool err = false; if (!keyMatchesEmailAddress(pgpSigningKey, email)) { msg = i18n( "One of the configured OpenPGP signing keys does not contain " "any user ID with the configured email address for this " "identity (%1).\n" "This might result in warning messages on the receiving side " "when trying to verify signatures made with this configuration.", email); err = true; } else if (!keyMatchesEmailAddress(pgpEncryptionKey, email)) { msg = i18n( "One of the configured OpenPGP encryption keys does not contain " "any user ID with the configured email address for this " "identity (%1).", email); err = true; } else if (!keyMatchesEmailAddress(smimeSigningKey, email)) { msg = i18n( "One of the configured S/MIME signing certificates does not contain " "the configured email address for this " "identity (%1).\n" "This might result in warning messages on the receiving side " "when trying to verify signatures made with this configuration.", email); err = true; } else if (!keyMatchesEmailAddress(smimeEncryptionKey, email)) { msg = i18n( "One of the configured S/MIME encryption certificates does not contain " "the configured email address for this " "identity (%1).", email); err = true; } if (err && KMessageBox::warningContinueCancel(this, msg, i18nc("@title:window", "Email Address Not Found in Key/Certificates"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), QStringLiteral("warn_email_not_in_certificate")) != KMessageBox::Continue) { return; } accept(); } bool IdentityDialog::keyMatchesEmailAddress(const GpgME::Key &key, const QString &email_) { if (key.isNull()) { return true; } const QString email = email_.trimmed().toLower(); const auto uids = key.userIDs(); for (const auto &uid : uids) { QString em = QString::fromUtf8(uid.email() ? uid.email() : uid.id()); if (em.isEmpty()) { continue; } if (em[0] == QLatin1Char('<')) { em = em.mid(1, em.length() - 2); } if (em.toLower() == email) { return true; } } return false; } void IdentityDialog::setIdentity(KIdentityManagementCore::Identity &ident) { setWindowTitle(i18nc("@title:window", "Edit Identity \"%1\"", ident.identityName())); // "General" tab: mNameEdit->setText(ident.fullName()); mOrganizationEdit->setText(ident.organization()); mEmailEdit->setText(ident.primaryEmailAddress()); mDictionaryCombo->setCurrentByDictionaryName(ident.dictionary()); // "Cryptography" tab: mPGPSigningKeyRequester->setDefaultKey(QLatin1String(ident.pgpSigningKey())); mPGPEncryptionKeyRequester->setDefaultKey(QLatin1String(ident.pgpEncryptionKey())); mPGPSameKey->setChecked(ident.pgpSigningKey() == ident.pgpEncryptionKey()); mSMIMESigningKeyRequester->setDefaultKey(QLatin1String(ident.smimeSigningKey())); mSMIMEEncryptionKeyRequester->setDefaultKey(QLatin1String(ident.smimeEncryptionKey())); - mPreferredCryptoMessageFormat->setCurrentIndex(format2cb(Kleo::stringToCryptoMessageFormat(ident.preferredCryptoMessageFormat()))); mWarnNotEncrypt->setChecked(ident.warnNotEncrypt()); // "Signature" tab: mSignatureConfigurator->setImageLocation(ident); mSignatureConfigurator->setSignature(ident.signature()); // set the configured email address as initial query of the key // requesters: const QString name = mNameEdit->text().trimmed(); const QString email = mEmailEdit->text().trimmed(); mPGPEncryptionKeyRequester->setIdentity(name, email); mPGPSigningKeyRequester->setIdentity(name, email); mSMIMEEncryptionKeyRequester->setIdentity(name, email); mSMIMESigningKeyRequester->setIdentity(name, email); } void IdentityDialog::updateIdentity(KIdentityManagementCore::Identity &ident) { // "General" tab: ident.setFullName(mNameEdit->text()); ident.setOrganization(mOrganizationEdit->text()); QString email = mEmailEdit->text().trimmed(); ident.setPrimaryEmailAddress(email); // "Cryptography" tab: ident.setPGPSigningKey(mPGPSigningKeyRequester->currentKey().primaryFingerprint()); ident.setPGPEncryptionKey(mPGPEncryptionKeyRequester->currentKey().primaryFingerprint()); ident.setSMIMESigningKey(mSMIMESigningKeyRequester->currentKey().primaryFingerprint()); ident.setSMIMEEncryptionKey(mSMIMEEncryptionKeyRequester->currentKey().primaryFingerprint()); - ident.setPreferredCryptoMessageFormat(QLatin1String(Kleo::cryptoMessageFormatToString(cb2format(mPreferredCryptoMessageFormat->currentIndex())))); ident.setEncryptionOverride(true); ident.setWarnNotEncrypt(mWarnNotEncrypt->isChecked()); ident.setWarnNotEncrypt(mWarnNotEncrypt->isChecked()); // "Advanced" tab: ident.setDictionary(mDictionaryCombo->currentDictionaryName()); // "Signature" tab: ident.setSignature(mSignatureConfigurator->signature()); } void IdentityDialog::slotKeyListingFinished(KeySelectionCombo *combo) { mInitialLoadingFinished << combo; if (mInitialLoadingFinished.count() == 2) { Q_EMIT keyListingFinished(); } } } #include "identitydialog.moc" #include "moc_identitydialog.cpp" diff --git a/client/identity/identitydialog.h b/client/identity/identitydialog.h index 94a2553..6f9d240 100644 --- a/client/identity/identitydialog.h +++ b/client/identity/identitydialog.h @@ -1,92 +1,91 @@ /* identitydialog.h This file is part of KMail, the KDE mail client. SPDX-FileCopyrightText: 2002 Marc Mutz SPDX-License-Identifier: GPL-2.0-only */ #pragma once #include class QCheckBox; class KEditListWidget; class QComboBox; class QGroupBox; class KJob; class QLineEdit; class QPushButton; class QTabWidget; namespace GpgME { class Key; } namespace KIdentityManagementCore { class Identity; } namespace KIdentityManagementWidgets { class SignatureConfigurator; } namespace Sonnet { class DictionaryComboBox; } namespace KMail { class IdentityFolderRequester; class IdentityInvalidFolder; class KeySelectionCombo; class IdentityDialog : public QDialog { Q_OBJECT public: explicit IdentityDialog(QWidget *parent = nullptr); ~IdentityDialog() override; void setIdentity(/*_not_ const*/ KIdentityManagementCore::Identity &ident); void updateIdentity(KIdentityManagementCore::Identity &ident); Q_SIGNALS: void keyListingFinished(); private: // copy default templates to identity templates void slotAccepted(); void slotKeyListingFinished(KeySelectionCombo *combo); [[nodiscard]] bool keyMatchesEmailAddress(const GpgME::Key &key, const QString &email); [[nodiscard]] bool checkFolderExists(const QString &folder); QTabWidget *mTabWidget = nullptr; // "general" tab: QLineEdit *mNameEdit = nullptr; QLineEdit *mOrganizationEdit = nullptr; QLineEdit *mEmailEdit = nullptr; Sonnet::DictionaryComboBox *mDictionaryCombo = nullptr; // "cryptography" tab: QWidget *mCryptographyTab = nullptr; KeySelectionCombo *mPGPSigningKeyRequester = nullptr; KeySelectionCombo *mPGPEncryptionKeyRequester = nullptr; KeySelectionCombo *mSMIMESigningKeyRequester = nullptr; KeySelectionCombo *mSMIMEEncryptionKeyRequester = nullptr; - QComboBox *mPreferredCryptoMessageFormat = nullptr; QCheckBox *mPGPSameKey = nullptr; QCheckBox *mWarnNotEncrypt = nullptr; QSet mInitialLoadingFinished; // "signature" tab: KIdentityManagementWidgets::SignatureConfigurator *mSignatureConfigurator = nullptr; }; } // namespace KMail