14 #include "composer/keyresolver.h"
15 #include "composer/nearexpirychecker.h"
16 #include "job/savecontactpreferencejob.h"
18 #include "utils/kleo_util.h"
19 #include <KCursorSaver>
21 #include <KEmailAddress>
23 #include <Libkleo/KeySelectionDialog>
25 #include <QGpgME/KeyListJob>
26 #include <QGpgME/Protocol>
28 #include <gpgme++/key.h>
29 #include <gpgme++/keylistresult.h>
31 #include "messagecomposer_debug.h"
32 #include <Akonadi/ContactSearchJob>
33 #include <KLocalizedString>
34 #include <KMessageBox>
36 #include <MessageCore/AutocryptRecipient>
37 #include <MessageCore/AutocryptStorage>
55 static inline bool EmptyKeyList(
const Kleo::KeyApprovalDialog::Item &item)
57 return item.keys.empty();
60 static inline QString ItemDotAddress(
const Kleo::KeyResolver::Item &item)
65 static inline bool ApprovalNeeded(
const Kleo::KeyResolver::Item &item)
67 return item.pref == Kleo::NeverEncrypt || item.keys.empty();
70 static inline Kleo::KeyResolver::Item CopyKeysAndEncryptionPreferences(
const Kleo::KeyResolver::Item &oldItem,
const Kleo::KeyApprovalDialog::Item &newItem)
72 return Kleo::KeyResolver::Item(oldItem.address, newItem.keys, newItem.pref, oldItem.signPref, oldItem.format);
75 static bool ValidOpenPGPEncryptionKey(
const GpgME::Key &key)
77 if (key.protocol() != GpgME::OpenPGP) {
80 if (key.isRevoked()) {
81 qCWarning(MESSAGECOMPOSER_LOG) <<
"is revoked";
83 if (key.isExpired()) {
84 qCWarning(MESSAGECOMPOSER_LOG) <<
"is expired";
86 if (key.isDisabled()) {
87 qCWarning(MESSAGECOMPOSER_LOG) <<
"is disabled";
89 if (!key.canEncrypt()) {
90 qCWarning(MESSAGECOMPOSER_LOG) <<
"can't encrypt";
92 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canEncrypt()) {
98 static bool ValidTrustedOpenPGPEncryptionKey(
const GpgME::Key &key)
100 if (!ValidOpenPGPEncryptionKey(key)) {
103 const std::vector<GpgME::UserID> uids = key.userIDs();
104 auto end(uids.end());
105 for (
auto it = uids.begin(); it != end; ++it) {
106 if (!it->isRevoked() && it->validity() >= GpgME::UserID::Marginal) {
108 }
else if (it->isRevoked()) {
109 qCWarning(MESSAGECOMPOSER_LOG) <<
"a userid is revoked";
111 qCWarning(MESSAGECOMPOSER_LOG) <<
"bad validity" << int(it->validity());
117 static bool ValidSMIMEEncryptionKey(
const GpgME::Key &key)
119 if (key.protocol() != GpgME::CMS) {
122 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canEncrypt()) {
128 static bool ValidTrustedSMIMEEncryptionKey(
const GpgME::Key &key)
130 if (!ValidSMIMEEncryptionKey(key)) {
136 static inline bool ValidTrustedEncryptionKey(
const GpgME::Key &key)
138 switch (key.protocol()) {
140 return ValidTrustedOpenPGPEncryptionKey(key);
142 return ValidTrustedSMIMEEncryptionKey(key);
148 static inline bool ValidEncryptionKey(
const GpgME::Key &key)
150 switch (key.protocol()) {
152 return ValidOpenPGPEncryptionKey(key);
154 return ValidSMIMEEncryptionKey(key);
160 static inline bool ValidSigningKey(
const GpgME::Key &key)
162 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canSign()) {
165 return key.hasSecret();
168 static inline bool ValidOpenPGPSigningKey(
const GpgME::Key &key)
170 return key.protocol() == GpgME::OpenPGP && ValidSigningKey(key);
173 static inline bool ValidSMIMESigningKey(
const GpgME::Key &key)
175 return key.protocol() == GpgME::CMS && ValidSigningKey(key);
178 static inline bool NotValidTrustedOpenPGPEncryptionKey(
const GpgME::Key &key)
180 return !ValidTrustedOpenPGPEncryptionKey(key);
183 static inline bool NotValidTrustedSMIMEEncryptionKey(
const GpgME::Key &key)
185 return !ValidTrustedSMIMEEncryptionKey(key);
188 static inline bool NotValidTrustedEncryptionKey(
const GpgME::Key &key)
190 return !ValidTrustedEncryptionKey(key);
193 static inline bool NotValidEncryptionKey(
const GpgME::Key &key)
195 return !ValidEncryptionKey(key);
198 static inline bool NotValidOpenPGPSigningKey(
const GpgME::Key &key)
200 return !ValidOpenPGPSigningKey(key);
203 static inline bool NotValidSMIMESigningKey(
const GpgME::Key &key)
205 return !ValidSMIMESigningKey(key);
210 struct ByTrustScore {
211 static int score(
const GpgME::UserID &uid)
213 return uid.isRevoked() || uid.isInvalid() ? -1 : uid.validity();
216 bool operator()(
const GpgME::UserID &lhs,
const GpgME::UserID &rhs)
const
218 return score(lhs) < score(rhs);
223 static std::vector<GpgME::UserID> matchingUIDs(
const std::vector<GpgME::UserID> &uids,
const QString &address)
229 std::vector<GpgME::UserID> result;
230 result.reserve(uids.size());
232 for (
auto it = uids.begin(), end = uids.end(); it != end; ++it) {
234 if (
const char *email = it->email()) {
236 result.push_back(*it);
243 static GpgME::UserID findBestMatchUID(
const GpgME::Key &key,
const QString &address)
245 const std::vector<GpgME::UserID> all = key.userIDs();
249 const std::vector<GpgME::UserID> matching = matchingUIDs(all,
address.toLower());
250 const std::vector<GpgME::UserID> &v = matching.empty() ? all : matching;
251 return *std::max_element(v.begin(), v.end(), ByTrustScore());
254 static QStringList keysAsStrings(
const std::vector<GpgME::Key> &keys)
258 for (
auto it = keys.begin(); it != keys.end(); ++it) {
259 assert(!(*it).userID(0).isNull());
260 const auto userID = (*it).userID(0);
273 static std::vector<GpgME::Key> trustedOrConfirmed(
const std::vector<GpgME::Key> &keys,
const QString &address,
bool &canceled)
276 std::vector<GpgME::Key> fishies;
277 std::vector<GpgME::Key> ickies;
278 std::vector<GpgME::Key> rewookies;
279 auto it = keys.begin();
280 const auto end = keys.end();
281 for (; it !=
end; ++it) {
282 const GpgME::Key &key = *it;
283 assert(ValidEncryptionKey(key));
284 const GpgME::UserID uid = findBestMatchUID(key, address);
285 if (uid.isRevoked()) {
286 rewookies.push_back(key);
288 if (!uid.isRevoked() && uid.validity() == GpgME::UserID::Marginal) {
289 fishies.push_back(key);
291 if (!uid.isRevoked() && uid.validity() < GpgME::UserID::Never) {
292 ickies.push_back(key);
296 if (fishies.empty() && ickies.empty() && rewookies.empty()) {
302 "One or more of your configured OpenPGP encryption "
303 "keys or S/MIME certificates is not fully trusted "
306 "One or more of the OpenPGP encryption keys or S/MIME "
307 "certificates for recipient \"%1\" is not fully trusted "
311 if (!fishies.empty()) {
313 msg +=
i18n(
"\nThe following keys are only marginally trusted: \n");
316 if (!ickies.empty()) {
317 msg +=
i18n(
"\nThe following keys or certificates have unknown trust level: \n");
320 if (!rewookies.empty()) {
321 msg +=
i18n(
"\nThe following keys or certificates are <b>revoked</b>: \n");
327 i18n(
"Not Fully Trusted Encryption Keys"),
330 QStringLiteral(
"not fully trusted encryption key warning"))
331 == KMessageBox::Continue) {
341 struct IsNotForFormat :
public std::unary_function<GpgME::Key, bool> {
342 IsNotForFormat(Kleo::CryptoMessageFormat f)
347 bool operator()(
const GpgME::Key &key)
const
349 return (isOpenPGP(format) && key.protocol() != GpgME::OpenPGP) || (isSMIME(format) && key.protocol() != GpgME::CMS);
352 const Kleo::CryptoMessageFormat format;
355 struct IsForFormat : std::unary_function<GpgME::Key, bool> {
356 explicit IsForFormat(Kleo::CryptoMessageFormat f)
357 : protocol(isOpenPGP(f) ? GpgME::OpenPGP
358 : isSMIME(f) ? GpgME::CMS
363 bool operator()(
const GpgME::Key &key)
const
365 return key.protocol() == protocol;
368 const GpgME::Protocol protocol;
372 class Kleo::KeyResolver::SigningPreferenceCounter :
public std::unary_function<Kleo::KeyResolver::Item, void>
375 SigningPreferenceCounter() =
default;
377 void operator()(
const Kleo::KeyResolver::Item &item);
378 #define make_int_accessor(x) \
379 unsigned int num##x() const \
383 make_int_accessor(UnknownSigningPreference) make_int_accessor(NeverSign) make_int_accessor(AlwaysSign) make_int_accessor(AlwaysSignIfPossible)
384 make_int_accessor(AlwaysAskForSigning) make_int_accessor(AskSigningWheneverPossible) make_int_accessor(Total)
385 #undef make_int_accessor
386 private :
unsigned int mTotal = 0;
387 unsigned int mUnknownSigningPreference = 0;
388 unsigned int mNeverSign = 0;
389 unsigned int mAlwaysSign = 0;
390 unsigned int mAlwaysSignIfPossible = 0;
391 unsigned int mAlwaysAskForSigning = 0;
392 unsigned int mAskSigningWheneverPossible = 0;
395 void Kleo::KeyResolver::SigningPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
397 switch (item.signPref) {
402 CASE(UnknownSigningPreference);
405 CASE(AlwaysSignIfPossible);
406 CASE(AlwaysAskForSigning);
407 CASE(AskSigningWheneverPossible);
413 class Kleo::KeyResolver::EncryptionPreferenceCounter :
public std::unary_function<Item, void>
418 EncryptionPreferenceCounter(
const Kleo::KeyResolver *kr, EncryptionPreference defaultPreference)
420 , mDefaultPreference(defaultPreference)
424 void operator()(
Item &item);
426 template<
typename Container>
427 void process(Container &c)
429 *
this = std::for_each(c.begin(), c.end(), *
this);
432 #define make_int_accessor(x) \
433 unsigned int num##x() const \
437 make_int_accessor(NoKey) make_int_accessor(NeverEncrypt) make_int_accessor(UnknownPreference) make_int_accessor(AlwaysEncrypt)
438 make_int_accessor(AlwaysEncryptIfPossible) make_int_accessor(AlwaysAskForEncryption) make_int_accessor(AskWheneverPossible) make_int_accessor(Total)
439 #undef make_int_accessor
440 private : EncryptionPreference mDefaultPreference;
441 unsigned int mTotal = 0;
442 unsigned int mNoKey = 0;
443 unsigned int mNeverEncrypt = 0;
444 unsigned int mUnknownPreference = 0;
445 unsigned int mAlwaysEncrypt = 0;
446 unsigned int mAlwaysEncryptIfPossible = 0;
447 unsigned int mAlwaysAskForEncryption = 0;
448 unsigned int mAskWheneverPossible = 0;
451 void Kleo::KeyResolver::EncryptionPreferenceCounter::operator()(
Item &item)
455 item.keys = _this->getEncryptionKeys(item.address,
true);
457 if (item.keys.empty()) {
462 switch (!item.pref ? mDefaultPreference : item.pref) {
468 CASE(UnknownPreference);
470 CASE(AlwaysEncryptIfPossible);
471 CASE(AlwaysAskForEncryption);
472 CASE(AskWheneverPossible);
480 class FormatPreferenceCounterBase :
public std::unary_function<Kleo::KeyResolver::Item, void>
483 FormatPreferenceCounterBase() =
default;
485 #define make_int_accessor(x) \
486 unsigned int num##x() const \
490 make_int_accessor(Total) make_int_accessor(InlineOpenPGP) make_int_accessor(OpenPGPMIME) make_int_accessor(SMIME) make_int_accessor(SMIMEOpaque)
491 #undef make_int_accessor
493 Q_REQUIRED_RESULT
unsigned int numOf(Kleo::CryptoMessageFormat f)
const
497 case Kleo::x##Format: \
510 unsigned int mTotal = 0;
511 unsigned int mInlineOpenPGP = 0;
512 unsigned int mOpenPGPMIME = 0;
513 unsigned int mSMIME = 0;
514 unsigned int mSMIMEOpaque = 0;
517 class EncryptionFormatPreferenceCounter :
public FormatPreferenceCounterBase
520 EncryptionFormatPreferenceCounter()
521 : FormatPreferenceCounterBase()
525 void operator()(
const Kleo::KeyResolver::Item &item);
528 class SigningFormatPreferenceCounter :
public FormatPreferenceCounterBase
531 SigningFormatPreferenceCounter()
532 : FormatPreferenceCounterBase()
536 void operator()(
const Kleo::KeyResolver::Item &item);
540 if (item.format & Kleo::x##Format) { \
543 void EncryptionFormatPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
545 if (item.format & (Kleo::InlineOpenPGPFormat | Kleo::OpenPGPMIMEFormat)
546 && std::any_of(item.keys.begin(),
548 ValidTrustedOpenPGPEncryptionKey)) {
552 if (item.format & (Kleo::SMIMEFormat | Kleo::SMIMEOpaqueFormat)
553 && std::any_of(item.keys.begin(),
555 ValidTrustedSMIMEEncryptionKey)) {
562 void SigningFormatPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
587 std::vector<Kleo::KeyResolver::SplitInfo> splitInfos;
588 std::vector<GpgME::Key> signKeys;
591 struct Q_DECL_HIDDEN Kleo::KeyResolver::KeyResolverPrivate {
592 bool mAkonadiLookupEnabled =
true;
593 bool mAutocryptEnabled =
false;
594 std::set<QByteArray> alreadyWarnedFingerprints;
596 std::vector<GpgME::Key> mOpenPGPSigningKeys;
597 std::vector<GpgME::Key> mSMIMESigningKeys;
599 std::vector<GpgME::Key> mOpenPGPEncryptToSelfKeys;
600 std::vector<GpgME::Key> mSMIMEEncryptToSelfKeys;
602 std::vector<Item> mPrimaryEncryptionKeys;
603 std::vector<Item> mSecondaryEncryptionKeys;
605 std::map<CryptoMessageFormat, FormatInfo> mFormatInfoMap;
608 using ContactPreferencesMap = std::map<QString, ContactPreferences>;
609 ContactPreferencesMap mContactPreferencesMap;
610 std::map<QByteArray, QString> mAutocryptMap;
614 Kleo::KeyResolver::KeyResolver(
bool encToSelf,
619 : d(new KeyResolverPrivate)
620 , mEncryptToSelf(encToSelf)
621 , mShowApprovalDialog(showApproval)
622 , mOpportunisticEncyption(oppEncryption)
623 , mCryptoMessageFormats(f)
625 d->nearExpiryChecker = nearExpiryChecker;
628 Kleo::KeyResolver::~KeyResolver() =
default;
632 if (!encryptToSelf()) {
636 std::vector<GpgME::Key> keys = lookup(fingerprints);
637 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mOpenPGPEncryptToSelfKeys),
638 NotValidTrustedOpenPGPEncryptionKey);
639 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mSMIMEEncryptToSelfKeys),
640 NotValidTrustedSMIMEEncryptionKey);
642 if (d->mOpenPGPEncryptToSelfKeys.size() + d->mSMIMEEncryptToSelfKeys.size() < keys.size()) {
645 "One or more of your configured OpenPGP encryption "
646 "keys or S/MIME certificates is not usable for "
647 "encryption. Please reconfigure your encryption keys "
648 "and certificates for this identity in the identity "
649 "configuration dialog.\n"
650 "If you choose to continue, and the keys are needed "
651 "later on, you will be prompted to specify the keys "
655 i18n(
"Unusable Encryption Keys"),
658 QStringLiteral(
"unusable own encryption key warning"))
659 == KMessageBox::Continue
665 std::vector<GpgME::Key>::const_iterator end(d->mOpenPGPEncryptToSelfKeys.end());
667 for (
auto it = d->mOpenPGPEncryptToSelfKeys.begin(); it != end; ++it) {
668 d->nearExpiryChecker->checkOwnKey(*it);
670 std::vector<GpgME::Key>::const_iterator end2(d->mSMIMEEncryptToSelfKeys.end());
671 for (
auto it = d->mSMIMEEncryptToSelfKeys.begin(); it != end2; ++it) {
672 d->nearExpiryChecker->checkOwnKey(*it);
680 std::vector<GpgME::Key> keys = lookup(fingerprints,
true);
681 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mOpenPGPSigningKeys), NotValidOpenPGPSigningKey);
682 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mSMIMESigningKeys), NotValidSMIMESigningKey);
684 if (d->mOpenPGPSigningKeys.size() + d->mSMIMESigningKeys.size() < keys.size()) {
687 "One or more of your configured OpenPGP signing keys "
688 "or S/MIME signing certificates is not usable for "
689 "signing. Please reconfigure your signing keys "
690 "and certificates for this identity in the identity "
691 "configuration dialog.\n"
692 "If you choose to continue, and the keys are needed "
693 "later on, you will be prompted to specify the keys "
697 i18n(
"Unusable Signing Keys"),
700 QStringLiteral(
"unusable signing key warning"))
701 == KMessageBox::Continue
708 for (
auto it = d->mOpenPGPSigningKeys.begin(), total = d->mOpenPGPSigningKeys.end(); it != total; ++it) {
709 d->nearExpiryChecker->checkOwnSigningKey(*it);
712 for (
auto it = d->mSMIMESigningKeys.begin(), total = d->mSMIMESigningKeys.end(); it != total; ++it) {
713 d->nearExpiryChecker->checkOwnSigningKey(*it);
721 d->mPrimaryEncryptionKeys = getEncryptionItems(addresses);
726 d->mSecondaryEncryptionKeys = getEncryptionItems(addresses);
729 std::vector<Kleo::KeyResolver::Item> Kleo::KeyResolver::getEncryptionItems(
const QStringList &addresses)
731 std::vector<Item> items;
732 items.reserve(addresses.
size());
736 const ContactPreferences pref = lookupContactPreferences(addr);
738 items.emplace_back(*it,
739 pref.encryptionPreference,
740 pref.signingPreference,
741 pref.cryptoMessageFormat);
746 static Kleo::Action action(
bool doit,
bool ask,
bool donot,
bool requested)
748 if (requested && !donot) {
751 if (doit && !ask && !donot) {
754 if (!doit && ask && !donot) {
757 if (!doit && !ask && donot) {
758 return requested ? Kleo::Conflict : Kleo::DontDoIt;
760 if (!doit && !ask && !donot) {
761 return Kleo::DontDoIt;
763 return Kleo::Conflict;
768 if (signingRequested && d->mOpenPGPSigningKeys.empty() && d->mSMIMESigningKeys.empty()) {
772 SigningPreferenceCounter count;
773 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
774 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
776 unsigned int sign = count.numAlwaysSign();
777 unsigned int ask = count.numAlwaysAskForSigning();
778 const unsigned int dontSign = count.numNeverSign();
779 if (signingPossible()) {
780 sign += count.numAlwaysSignIfPossible();
781 ask += count.numAskSigningWheneverPossible();
784 return action(sign, ask, dontSign, signingRequested);
787 bool Kleo::KeyResolver::signingPossible()
const
789 return !d->mOpenPGPSigningKeys.empty() || !d->mSMIMESigningKeys.empty();
794 if (d->mPrimaryEncryptionKeys.empty() && d->mSecondaryEncryptionKeys.empty()) {
798 if (encryptionRequested && encryptToSelf() && d->mOpenPGPEncryptToSelfKeys.empty() && d->mSMIMEEncryptToSelfKeys.empty()) {
802 if (!encryptionRequested && !mOpportunisticEncyption) {
806 EncryptionPreferenceCounter count(
nullptr, UnknownPreference);
807 count.process(d->mPrimaryEncryptionKeys);
808 count.process(d->mSecondaryEncryptionKeys);
809 if (!count.numAlwaysEncrypt()
810 && !count.numAlwaysAskForEncryption()
811 && !count.numAlwaysEncryptIfPossible() && !count.numAskWheneverPossible()) {
816 EncryptionPreferenceCounter count(
this, mOpportunisticEncyption ? AskWheneverPossible : UnknownPreference);
817 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
818 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
820 unsigned int encrypt = count.numAlwaysEncrypt();
821 unsigned int ask = count.numAlwaysAskForEncryption();
822 const unsigned int dontEncrypt = count.numNeverEncrypt() + count.numNoKey();
823 if (encryptionPossible()) {
824 encrypt += count.numAlwaysEncryptIfPossible();
825 ask += count.numAskWheneverPossible();
828 const Action act = action(encrypt, ask, dontEncrypt, encryptionRequested);
831 d->mPrimaryEncryptionKeys.begin(),
832 d->mPrimaryEncryptionKeys.end(),
833 std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EncryptionPreferenceCounter(
this, UnknownPreference)))
834 .numAlwaysAskForEncryption()) {
837 return AskOpportunistic;
841 bool Kleo::KeyResolver::encryptionPossible()
const
843 return std::none_of(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), EmptyKeyList)
844 && std::none_of(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EmptyKeyList);
849 if (!encryptionRequested && !signingRequested) {
853 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.emplace_back(allRecipients());
857 Kleo::Result result = Kleo::Ok;
858 if (encryptionRequested) {
859 bool finalySendUnencrypted =
false;
860 result = resolveEncryptionKeys(signingRequested, finalySendUnencrypted);
861 if (finalySendUnencrypted) {
862 encryptionRequested =
false;
865 if (result != Kleo::Ok) {
868 if (encryptionRequested) {
869 result = resolveSigningKeysForEncryption();
871 result = resolveSigningKeysForSigningOnly();
872 if (result == Kleo::Failure) {
873 signingRequested =
false;
880 Kleo::Result Kleo::KeyResolver::resolveEncryptionKeys(
bool signingRequested,
bool &finalySendUnencrypted)
885 qCDebug(MESSAGECOMPOSER_LOG) <<
"resolving enc keys" << d->mPrimaryEncryptionKeys.size();
886 for (
auto it = d->mPrimaryEncryptionKeys.begin(); it != d->mPrimaryEncryptionKeys.end(); ++it) {
887 qCDebug(MESSAGECOMPOSER_LOG) <<
"checking primary:" << it->address;
891 it->keys = getEncryptionKeys(it->address,
false);
892 qCDebug(MESSAGECOMPOSER_LOG) <<
"got # keys:" << it->keys.size();
893 if (it->keys.empty()) {
894 return Kleo::Canceled;
897 const ContactPreferences pref = lookupContactPreferences(addr);
898 it->pref = pref.encryptionPreference;
899 it->signPref = pref.signingPreference;
900 it->format = pref.cryptoMessageFormat;
901 qCDebug(MESSAGECOMPOSER_LOG) <<
"set key data:" << int(it->pref) << int(it->signPref) << int(it->format);
904 for (
auto it = d->mSecondaryEncryptionKeys.begin(), total = d->mSecondaryEncryptionKeys.end(); it != total; ++it) {
908 it->keys = getEncryptionKeys(it->address,
false);
909 if (it->keys.empty()) {
910 return Kleo::Canceled;
913 const ContactPreferences pref = lookupContactPreferences(addr);
914 it->pref = pref.encryptionPreference;
915 it->signPref = pref.signingPreference;
916 it->format = pref.cryptoMessageFormat;
921 const Kleo::Result res = showKeyApprovalDialog(finalySendUnencrypted);
922 if (res != Kleo::Ok) {
933 const EncryptionFormatPreferenceCounter primaryCount =
934 std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), EncryptionFormatPreferenceCounter());
936 CryptoMessageFormat commonFormat = AutoFormat;
937 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
938 if (!(concreteCryptoMessageFormats[i] & mCryptoMessageFormats)) {
941 if (signingRequested && signingKeysFor(concreteCryptoMessageFormats[i]).empty()) {
944 if (encryptToSelf() && encryptToSelfKeysFor(concreteCryptoMessageFormats[i]).empty()) {
947 if (primaryCount.numOf(concreteCryptoMessageFormats[i]) == primaryCount.numTotal()) {
948 commonFormat = concreteCryptoMessageFormats[i];
952 qCDebug(MESSAGECOMPOSER_LOG) <<
"got commonFormat for primary recipients:" << int(commonFormat);
953 if (commonFormat != AutoFormat) {
954 addKeys(d->mPrimaryEncryptionKeys, commonFormat);
956 addKeys(d->mPrimaryEncryptionKeys);
959 collapseAllSplitInfos();
964 const EncryptionFormatPreferenceCounter secondaryCount =
965 std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EncryptionFormatPreferenceCounter());
967 if (commonFormat != AutoFormat && secondaryCount.numOf(commonFormat) == secondaryCount.numTotal()) {
968 addKeys(d->mSecondaryEncryptionKeys, commonFormat);
970 addKeys(d->mSecondaryEncryptionKeys);
975 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
976 const std::vector<SplitInfo> si_list = encryptionItems(concreteCryptoMessageFormats[i]);
977 for (
auto sit = si_list.begin(), total = si_list.end(); sit != total; ++sit) {
978 for (
auto kit = sit->keys.begin(); kit != sit->keys.end(); ++kit) {
979 d->nearExpiryChecker->checkKey(*kit);
986 if (!encryptToSelf()) {
992 qCDebug(MESSAGECOMPOSER_LOG) <<
"sizes of encryption items:" << encryptionItems(InlineOpenPGPFormat).size() << encryptionItems(OpenPGPMIMEFormat).size()
993 << encryptionItems(SMIMEFormat).size() << encryptionItems(SMIMEOpaqueFormat).size();
994 if (!encryptionItems(InlineOpenPGPFormat).empty() || !encryptionItems(OpenPGPMIMEFormat).empty()) {
996 if (d->mOpenPGPEncryptToSelfKeys.empty()) {
998 "Examination of recipient's encryption preferences "
999 "yielded that the message should be encrypted using "
1000 "OpenPGP, at least for some recipients;\n"
1001 "however, you have not configured valid trusted "
1002 "OpenPGP encryption keys for this identity.\n"
1003 "You may continue without encrypting to yourself, "
1004 "but be aware that you will not be able to read your "
1005 "own messages if you do so.");
1008 i18n(
"Unusable Encryption Keys"),
1011 QStringLiteral(
"encrypt-to-self will fail warning"))
1012 == KMessageBox::Cancel) {
1013 return Kleo::Canceled;
1017 addToAllSplitInfos(d->mOpenPGPEncryptToSelfKeys, InlineOpenPGPFormat | OpenPGPMIMEFormat);
1022 if (!encryptionItems(SMIMEFormat).empty() || !encryptionItems(SMIMEOpaqueFormat).empty()) {
1024 if (d->mSMIMEEncryptToSelfKeys.empty()) {
1027 "Examination of recipient's encryption preferences "
1028 "yielded that the message should be encrypted using "
1029 "S/MIME, at least for some recipients;\n"
1030 "however, you have not configured valid "
1031 "S/MIME encryption certificates for this identity.\n"
1032 "You may continue without encrypting to yourself, "
1033 "but be aware that you will not be able to read your "
1034 "own messages if you do so.");
1037 i18n(
"Unusable Encryption Keys"),
1040 QStringLiteral(
"encrypt-to-self will fail warning"))
1041 == KMessageBox::Cancel) {
1042 return Kleo::Canceled;
1046 addToAllSplitInfos(d->mSMIMEEncryptToSelfKeys, SMIMEFormat | SMIMEOpaqueFormat);
1055 Kleo::Result Kleo::KeyResolver::resolveSigningKeysForEncryption()
1057 if ((!encryptionItems(InlineOpenPGPFormat).empty() || !encryptionItems(OpenPGPMIMEFormat).empty()) && d->mOpenPGPSigningKeys.empty()) {
1059 "Examination of recipient's signing preferences "
1060 "yielded that the message should be signed using "
1061 "OpenPGP, at least for some recipients;\n"
1062 "however, you have not configured valid "
1063 "OpenPGP signing certificates for this identity.");
1066 i18n(
"Unusable Signing Keys"),
1069 QStringLiteral(
"signing will fail warning"))
1070 == KMessageBox::Cancel) {
1071 return Kleo::Canceled;
1075 if ((!encryptionItems(SMIMEFormat).empty() || !encryptionItems(SMIMEOpaqueFormat).empty()) && d->mSMIMESigningKeys.empty()) {
1077 "Examination of recipient's signing preferences "
1078 "yielded that the message should be signed using "
1079 "S/MIME, at least for some recipients;\n"
1080 "however, you have not configured valid "
1081 "S/MIME signing certificates for this identity.");
1084 i18n(
"Unusable Signing Keys"),
1087 QStringLiteral(
"signing will fail warning"))
1088 == KMessageBox::Cancel) {
1089 return Kleo::Canceled;
1097 for (
auto it = d->mFormatInfoMap.begin(); it != d->mFormatInfoMap.end(); ++it) {
1098 if (!it->second.splitInfos.empty()) {
1100 it->second.signKeys = signingKeysFor(it->first);
1108 Kleo::Result Kleo::KeyResolver::resolveSigningKeysForSigningOnly()
1114 SigningFormatPreferenceCounter count;
1115 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
1116 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
1120 CryptoMessageFormat commonFormat = AutoFormat;
1122 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1123 const auto res = concreteCryptoMessageFormats[i];
1124 if (!(mCryptoMessageFormats & res)) {
1127 if (signingKeysFor(res).empty()) {
1130 if (count.numOf(res) == count.numTotal()) {
1136 if (commonFormat != AutoFormat) {
1138 FormatInfo &fi = d->mFormatInfoMap[commonFormat];
1139 fi.signKeys = signingKeysFor(commonFormat);
1140 fi.splitInfos.resize(1);
1141 fi.splitInfos.front() = SplitInfo(allRecipients());
1147 "Examination of recipient's signing preferences "
1148 "showed no common type of signature matching your "
1149 "available signing keys.\n"
1150 "Send message without signing?");
1152 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.emplace_back(allRecipients());
1153 return Kleo::Failure;
1155 return Kleo::Canceled;
1158 std::vector<GpgME::Key> Kleo::KeyResolver::signingKeysFor(CryptoMessageFormat f)
const
1161 return d->mOpenPGPSigningKeys;
1164 return d->mSMIMESigningKeys;
1169 std::vector<GpgME::Key> Kleo::KeyResolver::encryptToSelfKeysFor(CryptoMessageFormat f)
const
1172 return d->mOpenPGPEncryptToSelfKeys;
1175 return d->mSMIMEEncryptToSelfKeys;
1180 QStringList Kleo::KeyResolver::allRecipients()
const
1183 std::transform(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), std::back_inserter(result), ItemDotAddress);
1184 std::transform(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), std::back_inserter(result), ItemDotAddress);
1188 void Kleo::KeyResolver::collapseAllSplitInfos()
1191 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1192 auto pos = d->mFormatInfoMap.find(concreteCryptoMessageFormats[i]);
1193 if (pos == d->mFormatInfoMap.end()) {
1196 std::vector<SplitInfo> &v = pos->second.splitInfos;
1200 SplitInfo &si = v.front();
1201 for (
auto it = v.begin() + 1; it != v.end(); ++it) {
1202 si.keys.insert(si.keys.end(), it->keys.begin(), it->keys.end());
1203 std::copy(it->recipients.begin(), it->recipients.end(), std::back_inserter(si.recipients));
1210 void Kleo::KeyResolver::addToAllSplitInfos(
const std::vector<GpgME::Key> &keys,
unsigned int f)
1213 if (!f || keys.empty()) {
1216 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1217 if (!(f & concreteCryptoMessageFormats[i])) {
1220 auto pos = d->mFormatInfoMap.find(concreteCryptoMessageFormats[i]);
1221 if (pos == d->mFormatInfoMap.end()) {
1224 std::vector<SplitInfo> &v = pos->second.splitInfos;
1225 for (
auto it = v.begin(); it != v.end(); ++it) {
1226 it->keys.insert(it->keys.end(), keys.begin(), keys.end());
1232 void Kleo::KeyResolver::dump()
const
1235 if (d->mFormatInfoMap.empty()) {
1236 qCDebug(MESSAGECOMPOSER_LOG) <<
"Keyresolver: Format info empty";
1238 for (
auto it = d->mFormatInfoMap.begin(); it != d->mFormatInfoMap.end(); ++it) {
1239 qCDebug(MESSAGECOMPOSER_LOG) <<
"Format info for " << Kleo::cryptoMessageFormatToString(it->first) <<
": Signing keys: ";
1240 for (
auto sit = it->second.signKeys.begin(); sit != it->second.signKeys.end(); ++sit) {
1241 qCDebug(MESSAGECOMPOSER_LOG) <<
" " << sit->shortKeyID() <<
" ";
1244 for (
auto sit = it->second.splitInfos.begin(), sitEnd = it->second.splitInfos.end(); sit != sitEnd; ++sit, ++i) {
1245 qCDebug(MESSAGECOMPOSER_LOG) <<
" SplitInfo #" << i <<
" encryption keys: ";
1246 for (
auto kit = sit->keys.begin(), sitEnd = sit->keys.end(); kit != sitEnd; ++kit) {
1247 qCDebug(MESSAGECOMPOSER_LOG) <<
" " << kit->shortKeyID();
1249 qCDebug(MESSAGECOMPOSER_LOG) <<
" SplitInfo #" << i <<
" recipients: " << qPrintable(sit->recipients.join(
QLatin1String(
", ")));
1255 Kleo::Result Kleo::KeyResolver::showKeyApprovalDialog(
bool &finalySendUnencrypted)
1257 const bool showKeysForApproval = showApprovalDialog() || std::any_of(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), ApprovalNeeded)
1258 || std::any_of(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), ApprovalNeeded);
1260 if (!showKeysForApproval) {
1264 std::vector<Kleo::KeyApprovalDialog::Item> items;
1265 items.reserve(d->mPrimaryEncryptionKeys.size() + d->mSecondaryEncryptionKeys.size());
1266 std::copy(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), std::back_inserter(items));
1267 std::copy(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), std::back_inserter(items));
1269 std::vector<GpgME::Key> senderKeys;
1270 senderKeys.reserve(d->mOpenPGPEncryptToSelfKeys.size() + d->mSMIMEEncryptToSelfKeys.size());
1271 std::copy(d->mOpenPGPEncryptToSelfKeys.begin(), d->mOpenPGPEncryptToSelfKeys.end(), std::back_inserter(senderKeys));
1272 std::copy(d->mSMIMEEncryptToSelfKeys.begin(), d->mSMIMEEncryptToSelfKeys.end(), std::back_inserter(senderKeys));
1280 return Kleo::Canceled;
1283 items = dlg->items();
1284 senderKeys = dlg->senderKeys();
1285 const bool prefsChanged = dlg->preferencesChanged();
1289 for (uint i = 0, total = items.size(); i < total; ++i) {
1290 ContactPreferences pref = lookupContactPreferences(items[i].address);
1291 pref.encryptionPreference = items[i].pref;
1292 pref.pgpKeyFingerprints.clear();
1293 pref.smimeCertFingerprints.clear();
1294 const std::vector<GpgME::Key> &keys = items[i].keys;
1295 for (
auto it = keys.begin(), end = keys.end(); it != end; ++it) {
1296 if (it->protocol() == GpgME::OpenPGP) {
1297 if (
const char *fpr = it->primaryFingerprint()) {
1300 }
else if (it->protocol() == GpgME::CMS) {
1301 if (
const char *fpr = it->primaryFingerprint()) {
1306 saveContactPreference(items[i].address, pref);
1312 if (encryptToSelf() && senderKeys.empty()) {
1314 "You did not select an encryption key for yourself "
1315 "(encrypt to self). You will not be able to decrypt "
1316 "your own message if you encrypt it.");
1318 return Kleo::Canceled;
1320 mEncryptToSelf =
false;
1325 const unsigned int emptyListCount = std::count_if(items.begin(), items.end(), EmptyKeyList);
1329 if (items.size() == emptyListCount) {
1330 const QString msg = (d->mPrimaryEncryptionKeys.size() + d->mSecondaryEncryptionKeys.size() == 1)
1332 "You did not select an encryption key for the "
1333 "recipient of this message; therefore, the message "
1334 "will not be encrypted.")
1336 "You did not select an encryption key for any of the "
1337 "recipients of this message; therefore, the message "
1338 "will not be encrypted.");
1340 return Kleo::Canceled;
1342 finalySendUnencrypted =
true;
1343 }
else if (emptyListCount > 0) {
1345 "You did not select an encryption key for one of "
1346 "the recipients: this person will not be able to "
1347 "decrypt the message if you encrypt it.")
1349 "You did not select encryption keys for some of "
1350 "the recipients: these persons will not be able to "
1351 "decrypt the message if you encrypt it.");
1354 return Kleo::Canceled;
1358 std::transform(d->mPrimaryEncryptionKeys.begin(),
1359 d->mPrimaryEncryptionKeys.end(),
1361 d->mPrimaryEncryptionKeys.begin(),
1362 CopyKeysAndEncryptionPreferences);
1363 std::transform(d->mSecondaryEncryptionKeys.begin(),
1364 d->mSecondaryEncryptionKeys.end(),
1365 items.begin() + d->mPrimaryEncryptionKeys.size(),
1366 d->mSecondaryEncryptionKeys.begin(),
1367 CopyKeysAndEncryptionPreferences);
1369 d->mOpenPGPEncryptToSelfKeys.clear();
1370 d->mSMIMEEncryptToSelfKeys.clear();
1372 std::remove_copy_if(senderKeys.begin(),
1374 std::back_inserter(d->mOpenPGPEncryptToSelfKeys),
1375 NotValidTrustedOpenPGPEncryptionKey);
1376 std::remove_copy_if(senderKeys.begin(),
1378 std::back_inserter(d->mSMIMEEncryptToSelfKeys),
1379 NotValidTrustedSMIMEEncryptionKey);
1387 auto it = d->mFormatInfoMap.find(f);
1388 return it != d->mFormatInfoMap.end() ? it->second.splitInfos : std::vector<SplitInfo>();
1393 d->mAutocryptEnabled = autocryptEnabled;
1396 std::map<QByteArray, QString> Kleo::KeyResolver::useAutocrypt()
const
1398 return d->mAutocryptMap;
1403 d->mAkonadiLookupEnabled = akonadiLoopkupEnabled;
1409 auto it = d->mFormatInfoMap.find(f);
1410 return it != d->mFormatInfoMap.end() ? it->second.signKeys : std::vector<GpgME::Key>();
1419 std::vector<GpgME::Key> Kleo::KeyResolver::selectKeys(
const QString &person,
const QString &msg,
const std::vector<GpgME::Key> &selectedKeys)
const
1421 const bool opgp = containsOpenPGP(mCryptoMessageFormats);
1422 const bool x509 = containsSMIME(mCryptoMessageFormats);
1425 i18n(
"Encryption Key Selection"),
1429 Kleo::KeySelectionDialog::ValidEncryptionKeys & ~(opgp ? 0 : Kleo::KeySelectionDialog::OpenPGPKeys) & ~(x509 ? 0 : Kleo::KeySelectionDialog::SMIMEKeys),
1438 std::vector<GpgME::Key> keys = dlg->selectedKeys();
1439 keys.erase(std::remove_if(keys.begin(), keys.end(), NotValidEncryptionKey), keys.end());
1440 if (!keys.empty() && dlg->rememberSelection()) {
1441 setKeysForAddress(person, dlg->pgpKeyFingerprints(), dlg->smimeFingerprints());
1448 std::vector<GpgME::Key> Kleo::KeyResolver::getEncryptionKeys(
const QString &person,
bool quiet)
const
1453 const QStringList fingerprints = keysForAddress(address);
1455 if (!fingerprints.
empty()) {
1456 qCDebug(MESSAGECOMPOSER_LOG) <<
"Using encryption keys 0x" << fingerprints.
join(
QLatin1String(
", 0x")) <<
"for" << person;
1457 std::vector<GpgME::Key> keys = lookup(fingerprints);
1458 if (!keys.empty()) {
1460 if (std::any_of(keys.begin(), keys.end(),
1461 NotValidTrustedEncryptionKey)) {
1465 keys = selectKeys(person,
1466 i18nc(
"if in your language something like "
1467 "'certificate(s)' is not possible please "
1468 "use the plural in the translation",
1469 "There is a problem with the "
1470 "encryption certificate(s) for \"%1\".\n\n"
1471 "Please re-select the certificate(s) which should "
1472 "be used for this recipient.",
1476 bool canceled =
false;
1477 keys = trustedOrConfirmed(keys, address, canceled);
1482 if (!keys.empty()) {
1490 std::vector<GpgME::Key> matchingKeys = lookup(
QStringList(address));
1491 matchingKeys.erase(std::remove_if(matchingKeys.begin(), matchingKeys.end(), NotValidEncryptionKey), matchingKeys.end());
1493 if (matchingKeys.empty() && d->mAutocryptEnabled) {
1494 qCDebug(MESSAGECOMPOSER_LOG) <<
"Search in Autocrypt storage a key for " <<
address;
1495 const auto storage = MessageCore::AutocryptStorage::self();
1496 const auto recipient = storage->getRecipient(
address.toUtf8());
1498 const auto key = recipient->gpgKey();
1499 if (!key.isNull() && ValidEncryptionKey(key)) {
1500 qCDebug(MESSAGECOMPOSER_LOG) <<
"Found an valid autocrypt key.";
1501 matchingKeys.push_back(key);
1503 const auto gossipKey = recipient->gossipKey();
1504 if (!gossipKey.isNull() && ValidEncryptionKey(gossipKey)) {
1505 qCDebug(MESSAGECOMPOSER_LOG) <<
"Found an valid autocrypt gossip key.";
1506 matchingKeys.push_back(gossipKey);
1511 if (matchingKeys.size() == 1) {
1512 if (recipient->prefer_encrypt()) {
1513 d->mContactPreferencesMap[
address].encryptionPreference = AlwaysEncrypt;
1515 d->mContactPreferencesMap[
address].encryptionPreference = AlwaysEncryptIfPossible;
1517 d->mAutocryptMap[matchingKeys[0].primaryFingerprint()] =
address;
1518 return matchingKeys;
1525 bool canceled =
false;
1527 matchingKeys = trustedOrConfirmed(matchingKeys, address, canceled);
1532 if (quiet || matchingKeys.size() == 1) {
1533 return matchingKeys;
1539 return trustedOrConfirmed(selectKeys(person,
1540 matchingKeys.empty() ?
i18nc(
"if in your language something like "
1541 "'certificate(s)' is not possible please "
1542 "use the plural in the translation",
1543 "<qt>No valid and trusted encryption certificate was "
1544 "found for \"%1\".<br/><br/>"
1545 "Select the certificate(s) which should "
1546 "be used for this recipient. If there is no suitable certificate in the list "
1547 "you can also search for external certificates by clicking the button: "
1548 "search for external certificates.</qt>",
1550 :
i18nc(
"if in your language something like "
1551 "'certificate(s)' is not possible please "
1552 "use the plural in the translation",
1553 "More than one certificate matches \"%1\".\n\n"
1554 "Select the certificate(s) which should "
1555 "be used for this recipient.",
1564 std::vector<GpgME::Key> Kleo::KeyResolver::lookup(
const QStringList &patterns,
bool secret)
const
1566 if (patterns.
empty()) {
1569 qCDebug(MESSAGECOMPOSER_LOG) <<
"( \"" << patterns.
join(
QLatin1String(
"\", \"")) <<
"\"," << secret <<
")";
1570 std::vector<GpgME::Key> result;
1571 if (mCryptoMessageFormats & (InlineOpenPGPFormat | OpenPGPMIMEFormat)) {
1572 if (
const QGpgME::Protocol *p = QGpgME::openpgp()) {
1573 std::unique_ptr<QGpgME::KeyListJob> job(p->keyListJob(
false,
false,
true));
1575 std::vector<GpgME::Key> keys;
1576 job->exec(patterns, secret, keys);
1577 result.insert(result.end(), keys.begin(), keys.end());
1581 if (mCryptoMessageFormats & (SMIMEFormat | SMIMEOpaqueFormat)) {
1582 if (
const QGpgME::Protocol *p = QGpgME::smime()) {
1583 std::unique_ptr<QGpgME::KeyListJob> job(p->keyListJob(
false,
false,
true));
1585 std::vector<GpgME::Key> keys;
1586 job->exec(patterns, secret, keys);
1587 result.insert(result.end(), keys.begin(), keys.end());
1591 qCDebug(MESSAGECOMPOSER_LOG) <<
" returned" << result.size() <<
"keys";
1595 void Kleo::KeyResolver::addKeys(
const std::vector<Item> &items, CryptoMessageFormat f)
1598 for (
auto it = items.begin(); it != items.end(); ++it) {
1600 std::remove_copy_if(it->keys.begin(), it->keys.end(), std::back_inserter(si.keys), IsNotForFormat(f));
1602 if (si.keys.empty()) {
1603 qCWarning(MESSAGECOMPOSER_LOG) <<
"Kleo::KeyResolver::addKeys(): Fix EncryptionFormatPreferenceCounter."
1604 <<
"It detected a common format, but the list of such keys for recipient \"" << it->address <<
"\" is empty!";
1606 d->mFormatInfoMap[f].splitInfos.push_back(si);
1611 void Kleo::KeyResolver::addKeys(
const std::vector<Item> &items)
1614 for (
auto it = items.begin(); it != items.end(); ++it) {
1616 CryptoMessageFormat f = AutoFormat;
1617 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1618 const CryptoMessageFormat fmt = concreteCryptoMessageFormats[i];
1619 if ((fmt & it->format) && std::any_of(it->keys.begin(), it->keys.end(), IsForFormat(fmt))) {
1624 if (f == AutoFormat) {
1625 qCWarning(MESSAGECOMPOSER_LOG) <<
"Something went wrong. Didn't find a format for \"" << it->address <<
"\"";
1627 std::remove_copy_if(it->keys.begin(), it->keys.end(), std::back_inserter(si.keys), IsNotForFormat(f));
1629 d->mFormatInfoMap[f].splitInfos.push_back(si);
1634 Kleo::KeyResolver::ContactPreferences Kleo::KeyResolver::lookupContactPreferences(
const QString &address)
const
1636 const auto it = d->mContactPreferencesMap.find(address);
1637 if (it != d->mContactPreferencesMap.end()) {
1641 ContactPreferences pref;
1643 if (!d->mAkonadiLookupEnabled) {
1653 if (!res.isEmpty()) {
1655 QString encryptPref = addr.
custom(QStringLiteral(
"KADDRESSBOOK"), QStringLiteral(
"CRYPTOENCRYPTPREF"));
1656 pref.encryptionPreference = Kleo::stringToEncryptionPreference(encryptPref);
1657 QString signPref = addr.
custom(QStringLiteral(
"KADDRESSBOOK"), QStringLiteral(
"CRYPTOSIGNPREF"));
1658 pref.signingPreference = Kleo::stringToSigningPreference(signPref);
1659 QString cryptoFormats = addr.
custom(QStringLiteral(
"KADDRESSBOOK"), QStringLiteral(
"CRYPTOPROTOPREF"));
1660 pref.cryptoMessageFormat = Kleo::stringToCryptoMessageFormat(cryptoFormats);
1665 d->mContactPreferencesMap.
insert(std::make_pair(address, pref));
1670 void Kleo::KeyResolver::saveContactPreference(
const QString &email,
const ContactPreferences &pref)
const
1672 d->mContactPreferencesMap.insert(std::make_pair(email, pref));
1673 auto saveContactPreferencesJob =
new MessageComposer::SaveContactPreferenceJob(email, pref);
1674 saveContactPreferencesJob->start();
1677 Kleo::KeyResolver::ContactPreferences::ContactPreferences()
1678 : encryptionPreference(UnknownPreference)
1679 , signingPreference(UnknownSigningPreference)
1680 , cryptoMessageFormat(AutoFormat)
1690 const ContactPreferences pref = lookupContactPreferences(addr);
1691 return pref.pgpKeyFingerprints + pref.smimeCertFingerprints;
1694 void Kleo::KeyResolver::setKeysForAddress(
const QString &address,
const QStringList &pgpKeyFingerprints,
const QStringList &smimeCertFingerprints)
const
1700 ContactPreferences pref = lookupContactPreferences(addr);
1701 pref.pgpKeyFingerprints = pgpKeyFingerprints;
1702 pref.smimeCertFingerprints = smimeCertFingerprints;
1703 saveContactPreference(addr, pref);
1706 bool Kleo::KeyResolver::encryptToSelf()
const
1708 return mEncryptToSelf;
1711 bool Kleo::KeyResolver::showApprovalDialog()
const
1713 return mShowApprovalDialog;