14 #include "composer/keyresolver.h"
15 #include "composer/nearexpirychecker.h"
16 #include "contactpreference/savecontactpreferencejob.h"
18 #include "utils/kleo_util.h"
19 #include <KCursorSaver>
21 #include <KEmailAddress>
23 #include <Libkleo/Algorithm>
24 #include <Libkleo/Compliance>
26 #include <Libkleo/Formatting>
27 #include <Libkleo/KeySelectionDialog>
29 #include <QGpgME/KeyListJob>
30 #include <QGpgME/Protocol>
32 #include <gpgme++/key.h>
33 #include <gpgme++/keylistresult.h>
35 #include "messagecomposer_debug.h"
36 #include <Akonadi/ContactSearchJob>
37 #include <KLocalizedString>
38 #include <KMessageBox>
40 #include <MessageCore/AutocryptRecipient>
41 #include <MessageCore/AutocryptStorage>
59 static inline bool EmptyKeyList(
const Kleo::KeyApprovalDialog::Item &item)
61 return item.keys.empty();
64 static inline QString ItemDotAddress(
const Kleo::KeyResolver::Item &item)
69 static bool keyIsCompliant(
const GpgME::Key &key)
71 return (key.keyListMode() & GpgME::Validate)
72 && Kleo::Formatting::uidsHaveFullValidity(key)
73 && Kleo::Formatting::isKeyDeVs(key);
76 static inline bool ApprovalNeeded(
const Kleo::KeyResolver::Item &item)
78 bool approvalNeeded = item.pref == Kleo::NeverEncrypt || item.keys.empty();
79 if (!approvalNeeded && Kleo::DeVSCompliance::isCompliant()) {
80 approvalNeeded = !Kleo::all_of(item.keys, &keyIsCompliant);
82 return approvalNeeded;
85 static inline Kleo::KeyResolver::Item CopyKeysAndEncryptionPreferences(
const Kleo::KeyResolver::Item &oldItem,
const Kleo::KeyApprovalDialog::Item &newItem)
87 return Kleo::KeyResolver::Item(oldItem.address, newItem.keys, newItem.pref, oldItem.signPref, oldItem.format);
90 static bool ValidOpenPGPEncryptionKey(
const GpgME::Key &key)
92 if (key.protocol() != GpgME::OpenPGP) {
95 if (key.isRevoked()) {
96 qCWarning(MESSAGECOMPOSER_LOG) <<
"is revoked";
98 if (key.isExpired()) {
99 qCWarning(MESSAGECOMPOSER_LOG) <<
"is expired";
101 if (key.isDisabled()) {
102 qCWarning(MESSAGECOMPOSER_LOG) <<
"is disabled";
104 if (!key.canEncrypt()) {
105 qCWarning(MESSAGECOMPOSER_LOG) <<
"can't encrypt";
107 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canEncrypt()) {
113 static bool ValidTrustedOpenPGPEncryptionKey(
const GpgME::Key &key)
115 if (!ValidOpenPGPEncryptionKey(key)) {
118 const std::vector<GpgME::UserID> uids = key.userIDs();
119 auto end(uids.end());
120 for (
auto it = uids.begin(); it != end; ++it) {
121 if (!it->isRevoked() && it->validity() >= GpgME::UserID::Marginal) {
123 }
else if (it->isRevoked()) {
124 qCWarning(MESSAGECOMPOSER_LOG) <<
"a userid is revoked";
126 qCWarning(MESSAGECOMPOSER_LOG) <<
"bad validity" << int(it->validity());
132 static bool ValidSMIMEEncryptionKey(
const GpgME::Key &key)
134 if (key.protocol() != GpgME::CMS) {
137 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canEncrypt()) {
143 static bool ValidTrustedSMIMEEncryptionKey(
const GpgME::Key &key)
145 if (!ValidSMIMEEncryptionKey(key)) {
151 static inline bool ValidTrustedEncryptionKey(
const GpgME::Key &key)
153 switch (key.protocol()) {
155 return ValidTrustedOpenPGPEncryptionKey(key);
157 return ValidTrustedSMIMEEncryptionKey(key);
163 static inline bool ValidEncryptionKey(
const GpgME::Key &key)
165 switch (key.protocol()) {
167 return ValidOpenPGPEncryptionKey(key);
169 return ValidSMIMEEncryptionKey(key);
175 static inline bool ValidSigningKey(
const GpgME::Key &key)
177 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canSign()) {
180 return key.hasSecret();
183 static inline bool ValidOpenPGPSigningKey(
const GpgME::Key &key)
185 return key.protocol() == GpgME::OpenPGP && ValidSigningKey(key);
188 static inline bool ValidSMIMESigningKey(
const GpgME::Key &key)
190 return key.protocol() == GpgME::CMS && ValidSigningKey(key);
193 static inline bool NotValidTrustedOpenPGPEncryptionKey(
const GpgME::Key &key)
195 return !ValidTrustedOpenPGPEncryptionKey(key);
198 static inline bool NotValidTrustedSMIMEEncryptionKey(
const GpgME::Key &key)
200 return !ValidTrustedSMIMEEncryptionKey(key);
203 static inline bool NotValidTrustedEncryptionKey(
const GpgME::Key &key)
205 return !ValidTrustedEncryptionKey(key);
208 static inline bool NotValidEncryptionKey(
const GpgME::Key &key)
210 return !ValidEncryptionKey(key);
213 static inline bool NotValidOpenPGPSigningKey(
const GpgME::Key &key)
215 return !ValidOpenPGPSigningKey(key);
218 static inline bool NotValidSMIMESigningKey(
const GpgME::Key &key)
220 return !ValidSMIMESigningKey(key);
225 struct ByTrustScore {
226 static int score(
const GpgME::UserID &uid)
228 return uid.isRevoked() || uid.isInvalid() ? -1 : uid.validity();
231 bool operator()(
const GpgME::UserID &lhs,
const GpgME::UserID &rhs)
const
233 return score(lhs) < score(rhs);
238 static std::vector<GpgME::UserID> matchingUIDs(
const std::vector<GpgME::UserID> &uids,
const QString &address)
244 std::vector<GpgME::UserID> result;
245 result.reserve(uids.size());
247 for (
auto it = uids.begin(), end = uids.end(); it != end; ++it) {
249 if (
const char *email = it->email()) {
251 result.push_back(*it);
258 static GpgME::UserID findBestMatchUID(
const GpgME::Key &key,
const QString &address)
260 const std::vector<GpgME::UserID> all = key.userIDs();
264 const std::vector<GpgME::UserID> matching = matchingUIDs(all,
address.toLower());
265 const std::vector<GpgME::UserID> &v = matching.empty() ? all : matching;
266 return *std::max_element(v.begin(), v.end(), ByTrustScore());
269 static QStringList keysAsStrings(
const std::vector<GpgME::Key> &keys)
273 for (
auto it = keys.begin(); it != keys.end(); ++it) {
274 assert(!(*it).userID(0).isNull());
275 const auto userID = (*it).userID(0);
288 static std::vector<GpgME::Key> trustedOrConfirmed(
const std::vector<GpgME::Key> &keys,
const QString &address,
bool &canceled)
291 std::vector<GpgME::Key> fishies;
292 std::vector<GpgME::Key> ickies;
293 std::vector<GpgME::Key> rewookies;
294 auto it = keys.begin();
295 const auto end = keys.end();
296 for (; it !=
end; ++it) {
297 const GpgME::Key &key = *it;
298 assert(ValidEncryptionKey(key));
299 const GpgME::UserID uid = findBestMatchUID(key, address);
300 if (uid.isRevoked()) {
301 rewookies.push_back(key);
303 if (!uid.isRevoked() && uid.validity() == GpgME::UserID::Marginal) {
304 fishies.push_back(key);
306 if (!uid.isRevoked() && uid.validity() < GpgME::UserID::Never) {
307 ickies.push_back(key);
311 if (fishies.empty() && ickies.empty() && rewookies.empty()) {
317 "One or more of your configured OpenPGP encryption "
318 "keys or S/MIME certificates is not fully trusted "
321 "One or more of the OpenPGP encryption keys or S/MIME "
322 "certificates for recipient \"%1\" is not fully trusted "
326 if (!fishies.empty()) {
328 msg +=
i18n(
"\nThe following keys are only marginally trusted: \n");
331 if (!ickies.empty()) {
332 msg +=
i18n(
"\nThe following keys or certificates have unknown trust level: \n");
335 if (!rewookies.empty()) {
336 msg +=
i18n(
"\nThe following keys or certificates are <b>revoked</b>: \n");
342 i18n(
"Not Fully Trusted Encryption Keys"),
345 QStringLiteral(
"not fully trusted encryption key warning"))
346 == KMessageBox::Continue) {
356 struct IsNotForFormat :
public std::unary_function<GpgME::Key, bool> {
357 IsNotForFormat(Kleo::CryptoMessageFormat f)
362 bool operator()(
const GpgME::Key &key)
const
364 return (isOpenPGP(format) && key.protocol() != GpgME::OpenPGP) || (isSMIME(format) && key.protocol() != GpgME::CMS);
367 const Kleo::CryptoMessageFormat format;
370 struct IsForFormat : std::unary_function<GpgME::Key, bool> {
371 explicit IsForFormat(Kleo::CryptoMessageFormat f)
372 : protocol(isOpenPGP(f) ? GpgME::OpenPGP
373 : isSMIME(f) ? GpgME::CMS
378 bool operator()(
const GpgME::Key &key)
const
380 return key.protocol() == protocol;
383 const GpgME::Protocol protocol;
387 class Kleo::KeyResolver::SigningPreferenceCounter :
public std::unary_function<Kleo::KeyResolver::Item, void>
390 SigningPreferenceCounter() =
default;
392 void operator()(
const Kleo::KeyResolver::Item &item);
393 #define make_int_accessor(x) \
394 unsigned int num##x() const \
398 make_int_accessor(UnknownSigningPreference) make_int_accessor(NeverSign) make_int_accessor(AlwaysSign) make_int_accessor(AlwaysSignIfPossible)
399 make_int_accessor(AlwaysAskForSigning) make_int_accessor(AskSigningWheneverPossible) make_int_accessor(Total)
400 #undef make_int_accessor
401 private :
unsigned int mTotal = 0;
402 unsigned int mUnknownSigningPreference = 0;
403 unsigned int mNeverSign = 0;
404 unsigned int mAlwaysSign = 0;
405 unsigned int mAlwaysSignIfPossible = 0;
406 unsigned int mAlwaysAskForSigning = 0;
407 unsigned int mAskSigningWheneverPossible = 0;
410 void Kleo::KeyResolver::SigningPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
412 switch (item.signPref) {
417 CASE(UnknownSigningPreference);
420 CASE(AlwaysSignIfPossible);
421 CASE(AlwaysAskForSigning);
422 CASE(AskSigningWheneverPossible);
428 class Kleo::KeyResolver::EncryptionPreferenceCounter :
public std::unary_function<Item, void>
433 EncryptionPreferenceCounter(
const Kleo::KeyResolver *kr, EncryptionPreference defaultPreference)
435 , mDefaultPreference(defaultPreference)
439 void operator()(
Item &item);
441 template<
typename Container>
442 void process(Container &c)
444 *
this = std::for_each(c.begin(), c.end(), *
this);
447 #define make_int_accessor(x) \
448 unsigned int num##x() const \
452 make_int_accessor(NoKey) make_int_accessor(NeverEncrypt) make_int_accessor(UnknownPreference) make_int_accessor(AlwaysEncrypt)
453 make_int_accessor(AlwaysEncryptIfPossible) make_int_accessor(AlwaysAskForEncryption) make_int_accessor(AskWheneverPossible) make_int_accessor(Total)
454 #undef make_int_accessor
455 private : EncryptionPreference mDefaultPreference;
456 unsigned int mTotal = 0;
457 unsigned int mNoKey = 0;
458 unsigned int mNeverEncrypt = 0;
459 unsigned int mUnknownPreference = 0;
460 unsigned int mAlwaysEncrypt = 0;
461 unsigned int mAlwaysEncryptIfPossible = 0;
462 unsigned int mAlwaysAskForEncryption = 0;
463 unsigned int mAskWheneverPossible = 0;
466 void Kleo::KeyResolver::EncryptionPreferenceCounter::operator()(
Item &item)
470 item.keys = _this->getEncryptionKeys(item.address,
true);
472 if (item.keys.empty()) {
477 switch (!item.pref ? mDefaultPreference : item.pref) {
483 CASE(UnknownPreference);
485 CASE(AlwaysEncryptIfPossible);
486 CASE(AlwaysAskForEncryption);
487 CASE(AskWheneverPossible);
495 class FormatPreferenceCounterBase :
public std::unary_function<Kleo::KeyResolver::Item, void>
498 FormatPreferenceCounterBase() =
default;
500 #define make_int_accessor(x) \
501 unsigned int num##x() const \
505 make_int_accessor(Total) make_int_accessor(InlineOpenPGP) make_int_accessor(OpenPGPMIME) make_int_accessor(SMIME) make_int_accessor(SMIMEOpaque)
506 #undef make_int_accessor
508 Q_REQUIRED_RESULT
unsigned int numOf(Kleo::CryptoMessageFormat f)
const
512 case Kleo::x##Format: \
525 unsigned int mTotal = 0;
526 unsigned int mInlineOpenPGP = 0;
527 unsigned int mOpenPGPMIME = 0;
528 unsigned int mSMIME = 0;
529 unsigned int mSMIMEOpaque = 0;
532 class EncryptionFormatPreferenceCounter :
public FormatPreferenceCounterBase
535 EncryptionFormatPreferenceCounter()
536 : FormatPreferenceCounterBase()
540 void operator()(
const Kleo::KeyResolver::Item &item);
543 class SigningFormatPreferenceCounter :
public FormatPreferenceCounterBase
546 SigningFormatPreferenceCounter()
547 : FormatPreferenceCounterBase()
551 void operator()(
const Kleo::KeyResolver::Item &item);
555 if (item.format & Kleo::x##Format) { \
558 void EncryptionFormatPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
560 if (item.format & (Kleo::InlineOpenPGPFormat | Kleo::OpenPGPMIMEFormat)
561 && std::any_of(item.keys.begin(),
563 ValidTrustedOpenPGPEncryptionKey)) {
567 if (item.format & (Kleo::SMIMEFormat | Kleo::SMIMEOpaqueFormat)
568 && std::any_of(item.keys.begin(),
570 ValidTrustedSMIMEEncryptionKey)) {
577 void SigningFormatPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
602 std::vector<Kleo::KeyResolver::SplitInfo> splitInfos;
603 std::vector<GpgME::Key> signKeys;
606 struct Q_DECL_HIDDEN Kleo::KeyResolver::KeyResolverPrivate {
607 bool mAkonadiLookupEnabled =
true;
608 bool mAutocryptEnabled =
false;
609 std::set<QByteArray> alreadyWarnedFingerprints;
611 std::vector<GpgME::Key> mOpenPGPSigningKeys;
612 std::vector<GpgME::Key> mSMIMESigningKeys;
614 std::vector<GpgME::Key> mOpenPGPEncryptToSelfKeys;
615 std::vector<GpgME::Key> mSMIMEEncryptToSelfKeys;
617 std::vector<Item> mPrimaryEncryptionKeys;
618 std::vector<Item> mSecondaryEncryptionKeys;
620 std::map<CryptoMessageFormat, FormatInfo> mFormatInfoMap;
623 using ContactPreferencesMap = std::map<QString, MessageComposer::ContactPreference>;
624 ContactPreferencesMap mContactPreferencesMap;
625 std::map<QByteArray, QString> mAutocryptMap;
629 Kleo::KeyResolver::KeyResolver(
bool encToSelf,
634 : d(new KeyResolverPrivate)
635 , mEncryptToSelf(encToSelf)
636 , mShowApprovalDialog(showApproval)
637 , mOpportunisticEncyption(oppEncryption)
638 , mCryptoMessageFormats(f)
640 d->nearExpiryChecker = nearExpiryChecker;
643 Kleo::KeyResolver::~KeyResolver() =
default;
647 if (!encryptToSelf()) {
651 std::vector<GpgME::Key> keys = lookup(fingerprints);
652 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mOpenPGPEncryptToSelfKeys),
653 NotValidTrustedOpenPGPEncryptionKey);
654 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mSMIMEEncryptToSelfKeys),
655 NotValidTrustedSMIMEEncryptionKey);
657 if (d->mOpenPGPEncryptToSelfKeys.size() + d->mSMIMEEncryptToSelfKeys.size() < keys.size()) {
660 "One or more of your configured OpenPGP encryption "
661 "keys or S/MIME certificates is not usable for "
662 "encryption. Please reconfigure your encryption keys "
663 "and certificates for this identity in the identity "
664 "configuration dialog.\n"
665 "If you choose to continue, and the keys are needed "
666 "later on, you will be prompted to specify the keys "
670 i18n(
"Unusable Encryption Keys"),
673 QStringLiteral(
"unusable own encryption key warning"))
674 == KMessageBox::Continue
680 std::vector<GpgME::Key>::const_iterator end(d->mOpenPGPEncryptToSelfKeys.end());
682 for (
auto it = d->mOpenPGPEncryptToSelfKeys.begin(); it != end; ++it) {
683 d->nearExpiryChecker->checkOwnKey(*it);
685 std::vector<GpgME::Key>::const_iterator end2(d->mSMIMEEncryptToSelfKeys.end());
686 for (
auto it = d->mSMIMEEncryptToSelfKeys.begin(); it != end2; ++it) {
687 d->nearExpiryChecker->checkOwnKey(*it);
695 std::vector<GpgME::Key> keys = lookup(fingerprints,
true);
696 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mOpenPGPSigningKeys), NotValidOpenPGPSigningKey);
697 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mSMIMESigningKeys), NotValidSMIMESigningKey);
699 if (d->mOpenPGPSigningKeys.size() + d->mSMIMESigningKeys.size() < keys.size()) {
702 "One or more of your configured OpenPGP signing keys "
703 "or S/MIME signing certificates is not usable for "
704 "signing. Please reconfigure your signing keys "
705 "and certificates for this identity in the identity "
706 "configuration dialog.\n"
707 "If you choose to continue, and the keys are needed "
708 "later on, you will be prompted to specify the keys "
712 i18n(
"Unusable Signing Keys"),
715 QStringLiteral(
"unusable signing key warning"))
716 == KMessageBox::Continue
723 for (
auto it = d->mOpenPGPSigningKeys.begin(), total = d->mOpenPGPSigningKeys.end(); it != total; ++it) {
724 d->nearExpiryChecker->checkOwnSigningKey(*it);
727 for (
auto it = d->mSMIMESigningKeys.begin(), total = d->mSMIMESigningKeys.end(); it != total; ++it) {
728 d->nearExpiryChecker->checkOwnSigningKey(*it);
736 d->mPrimaryEncryptionKeys = getEncryptionItems(addresses);
741 d->mSecondaryEncryptionKeys = getEncryptionItems(addresses);
744 std::vector<Kleo::KeyResolver::Item> Kleo::KeyResolver::getEncryptionItems(
const QStringList &addresses)
746 std::vector<Item> items;
747 items.reserve(addresses.
size());
751 const auto pref = lookupContactPreferences(addr);
753 items.emplace_back(*it,
754 pref.encryptionPreference,
755 pref.signingPreference,
756 pref.cryptoMessageFormat);
761 static Kleo::Action action(
bool doit,
bool ask,
bool donot,
bool requested)
763 if (requested && !donot) {
766 if (doit && !ask && !donot) {
769 if (!doit && ask && !donot) {
772 if (!doit && !ask && donot) {
773 return requested ? Kleo::Conflict : Kleo::DontDoIt;
775 if (!doit && !ask && !donot) {
776 return Kleo::DontDoIt;
778 return Kleo::Conflict;
783 if (signingRequested && d->mOpenPGPSigningKeys.empty() && d->mSMIMESigningKeys.empty()) {
787 SigningPreferenceCounter count;
788 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
789 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
791 unsigned int sign = count.numAlwaysSign();
792 unsigned int ask = count.numAlwaysAskForSigning();
793 const unsigned int dontSign = count.numNeverSign();
794 if (signingPossible()) {
795 sign += count.numAlwaysSignIfPossible();
796 ask += count.numAskSigningWheneverPossible();
799 return action(sign, ask, dontSign, signingRequested);
802 bool Kleo::KeyResolver::signingPossible()
const
804 return !d->mOpenPGPSigningKeys.empty() || !d->mSMIMESigningKeys.empty();
809 if (d->mPrimaryEncryptionKeys.empty() && d->mSecondaryEncryptionKeys.empty()) {
813 if (encryptionRequested && encryptToSelf() && d->mOpenPGPEncryptToSelfKeys.empty() && d->mSMIMEEncryptToSelfKeys.empty()) {
817 if (!encryptionRequested && !mOpportunisticEncyption) {
821 EncryptionPreferenceCounter count(
nullptr, UnknownPreference);
822 count.process(d->mPrimaryEncryptionKeys);
823 count.process(d->mSecondaryEncryptionKeys);
824 if (!count.numAlwaysEncrypt()
825 && !count.numAlwaysAskForEncryption()
826 && !count.numAlwaysEncryptIfPossible() && !count.numAskWheneverPossible()) {
831 EncryptionPreferenceCounter count(
this, mOpportunisticEncyption ? AskWheneverPossible : UnknownPreference);
832 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
833 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
835 unsigned int encrypt = count.numAlwaysEncrypt();
836 unsigned int ask = count.numAlwaysAskForEncryption();
837 const unsigned int dontEncrypt = count.numNeverEncrypt() + count.numNoKey();
838 if (encryptionPossible()) {
839 encrypt += count.numAlwaysEncryptIfPossible();
840 ask += count.numAskWheneverPossible();
843 const Action act = action(encrypt, ask, dontEncrypt, encryptionRequested);
846 d->mPrimaryEncryptionKeys.begin(),
847 d->mPrimaryEncryptionKeys.end(),
848 std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EncryptionPreferenceCounter(
this, UnknownPreference)))
849 .numAlwaysAskForEncryption()) {
852 return AskOpportunistic;
856 bool Kleo::KeyResolver::encryptionPossible()
const
858 return std::none_of(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), EmptyKeyList)
859 && std::none_of(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EmptyKeyList);
864 if (!encryptionRequested && !signingRequested) {
868 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.emplace_back(allRecipients());
872 Kleo::Result result = Kleo::Ok;
873 if (encryptionRequested) {
874 bool finalySendUnencrypted =
false;
875 result = resolveEncryptionKeys(signingRequested, finalySendUnencrypted);
876 if (finalySendUnencrypted) {
877 encryptionRequested =
false;
880 if (result != Kleo::Ok) {
883 if (encryptionRequested) {
884 result = resolveSigningKeysForEncryption();
886 result = resolveSigningKeysForSigningOnly();
887 if (result == Kleo::Failure) {
888 signingRequested =
false;
895 Kleo::Result Kleo::KeyResolver::resolveEncryptionKeys(
bool signingRequested,
bool &finalySendUnencrypted)
900 qCDebug(MESSAGECOMPOSER_LOG) <<
"resolving enc keys" << d->mPrimaryEncryptionKeys.size();
901 for (
auto it = d->mPrimaryEncryptionKeys.begin(); it != d->mPrimaryEncryptionKeys.end(); ++it) {
902 qCDebug(MESSAGECOMPOSER_LOG) <<
"checking primary:" << it->address;
906 it->keys = getEncryptionKeys(it->address,
false);
907 qCDebug(MESSAGECOMPOSER_LOG) <<
"got # keys:" << it->keys.size();
908 if (it->keys.empty()) {
909 return Kleo::Canceled;
912 const auto pref = lookupContactPreferences(addr);
913 it->pref = pref.encryptionPreference;
914 it->signPref = pref.signingPreference;
915 it->format = pref.cryptoMessageFormat;
916 qCDebug(MESSAGECOMPOSER_LOG) <<
"set key data:" << int(it->pref) << int(it->signPref) << int(it->format);
919 for (
auto it = d->mSecondaryEncryptionKeys.begin(), total = d->mSecondaryEncryptionKeys.end(); it != total; ++it) {
923 it->keys = getEncryptionKeys(it->address,
false);
924 if (it->keys.empty()) {
925 return Kleo::Canceled;
928 const auto pref = lookupContactPreferences(addr);
929 it->pref = pref.encryptionPreference;
930 it->signPref = pref.signingPreference;
931 it->format = pref.cryptoMessageFormat;
936 const Kleo::Result res = showKeyApprovalDialog(finalySendUnencrypted);
937 if (res != Kleo::Ok) {
948 const EncryptionFormatPreferenceCounter primaryCount =
949 std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), EncryptionFormatPreferenceCounter());
951 CryptoMessageFormat commonFormat = AutoFormat;
952 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
953 if (!(concreteCryptoMessageFormats[i] & mCryptoMessageFormats)) {
956 if (signingRequested && signingKeysFor(concreteCryptoMessageFormats[i]).empty()) {
959 if (encryptToSelf() && encryptToSelfKeysFor(concreteCryptoMessageFormats[i]).empty()) {
962 if (primaryCount.numOf(concreteCryptoMessageFormats[i]) == primaryCount.numTotal()) {
963 commonFormat = concreteCryptoMessageFormats[i];
967 qCDebug(MESSAGECOMPOSER_LOG) <<
"got commonFormat for primary recipients:" << int(commonFormat);
968 if (commonFormat != AutoFormat) {
969 addKeys(d->mPrimaryEncryptionKeys, commonFormat);
971 addKeys(d->mPrimaryEncryptionKeys);
974 collapseAllSplitInfos();
979 const EncryptionFormatPreferenceCounter secondaryCount =
980 std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EncryptionFormatPreferenceCounter());
982 if (commonFormat != AutoFormat && secondaryCount.numOf(commonFormat) == secondaryCount.numTotal()) {
983 addKeys(d->mSecondaryEncryptionKeys, commonFormat);
985 addKeys(d->mSecondaryEncryptionKeys);
990 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
991 const std::vector<SplitInfo> si_list = encryptionItems(concreteCryptoMessageFormats[i]);
992 for (
auto sit = si_list.begin(), total = si_list.end(); sit != total; ++sit) {
993 for (
auto kit = sit->keys.begin(); kit != sit->keys.end(); ++kit) {
994 d->nearExpiryChecker->checkKey(*kit);
1001 if (!encryptToSelf()) {
1007 qCDebug(MESSAGECOMPOSER_LOG) <<
"sizes of encryption items:" << encryptionItems(InlineOpenPGPFormat).size() << encryptionItems(OpenPGPMIMEFormat).size()
1008 << encryptionItems(SMIMEFormat).size() << encryptionItems(SMIMEOpaqueFormat).size();
1009 if (!encryptionItems(InlineOpenPGPFormat).empty() || !encryptionItems(OpenPGPMIMEFormat).empty()) {
1011 if (d->mOpenPGPEncryptToSelfKeys.empty()) {
1013 "Examination of recipient's encryption preferences "
1014 "yielded that the message should be encrypted using "
1015 "OpenPGP, at least for some recipients;\n"
1016 "however, you have not configured valid trusted "
1017 "OpenPGP encryption keys for this identity.\n"
1018 "You may continue without encrypting to yourself, "
1019 "but be aware that you will not be able to read your "
1020 "own messages if you do so.");
1023 i18n(
"Unusable Encryption Keys"),
1026 QStringLiteral(
"encrypt-to-self will fail warning"))
1027 == KMessageBox::Cancel) {
1028 return Kleo::Canceled;
1032 addToAllSplitInfos(d->mOpenPGPEncryptToSelfKeys, InlineOpenPGPFormat | OpenPGPMIMEFormat);
1037 if (!encryptionItems(SMIMEFormat).empty() || !encryptionItems(SMIMEOpaqueFormat).empty()) {
1039 if (d->mSMIMEEncryptToSelfKeys.empty()) {
1042 "Examination of recipient's encryption preferences "
1043 "yielded that the message should be encrypted using "
1044 "S/MIME, at least for some recipients;\n"
1045 "however, you have not configured valid "
1046 "S/MIME encryption certificates for this identity.\n"
1047 "You may continue without encrypting to yourself, "
1048 "but be aware that you will not be able to read your "
1049 "own messages if you do so.");
1052 i18n(
"Unusable Encryption Keys"),
1055 QStringLiteral(
"encrypt-to-self will fail warning"))
1056 == KMessageBox::Cancel) {
1057 return Kleo::Canceled;
1061 addToAllSplitInfos(d->mSMIMEEncryptToSelfKeys, SMIMEFormat | SMIMEOpaqueFormat);
1070 Kleo::Result Kleo::KeyResolver::resolveSigningKeysForEncryption()
1072 if ((!encryptionItems(InlineOpenPGPFormat).empty() || !encryptionItems(OpenPGPMIMEFormat).empty()) && d->mOpenPGPSigningKeys.empty()) {
1074 "Examination of recipient's signing preferences "
1075 "yielded that the message should be signed using "
1076 "OpenPGP, at least for some recipients;\n"
1077 "however, you have not configured valid "
1078 "OpenPGP signing certificates for this identity.");
1081 i18n(
"Unusable Signing Keys"),
1084 QStringLiteral(
"signing will fail warning"))
1085 == KMessageBox::Cancel) {
1086 return Kleo::Canceled;
1090 if ((!encryptionItems(SMIMEFormat).empty() || !encryptionItems(SMIMEOpaqueFormat).empty()) && d->mSMIMESigningKeys.empty()) {
1092 "Examination of recipient's signing preferences "
1093 "yielded that the message should be signed using "
1094 "S/MIME, at least for some recipients;\n"
1095 "however, you have not configured valid "
1096 "S/MIME signing certificates for this identity.");
1099 i18n(
"Unusable Signing Keys"),
1102 QStringLiteral(
"signing will fail warning"))
1103 == KMessageBox::Cancel) {
1104 return Kleo::Canceled;
1112 for (
auto it = d->mFormatInfoMap.begin(); it != d->mFormatInfoMap.end(); ++it) {
1113 if (!it->second.splitInfos.empty()) {
1115 it->second.signKeys = signingKeysFor(it->first);
1123 Kleo::Result Kleo::KeyResolver::resolveSigningKeysForSigningOnly()
1129 SigningFormatPreferenceCounter count;
1130 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
1131 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
1135 CryptoMessageFormat commonFormat = AutoFormat;
1137 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1138 const auto res = concreteCryptoMessageFormats[i];
1139 if (!(mCryptoMessageFormats & res)) {
1142 if (signingKeysFor(res).empty()) {
1145 if (count.numOf(res) == count.numTotal()) {
1151 if (commonFormat != AutoFormat) {
1153 FormatInfo &fi = d->mFormatInfoMap[commonFormat];
1154 fi.signKeys = signingKeysFor(commonFormat);
1155 fi.splitInfos.resize(1);
1156 fi.splitInfos.front() = SplitInfo(allRecipients());
1162 "Examination of recipient's signing preferences "
1163 "showed no common type of signature matching your "
1164 "available signing keys.\n"
1165 "Send message without signing?");
1167 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.emplace_back(allRecipients());
1168 return Kleo::Failure;
1170 return Kleo::Canceled;
1173 std::vector<GpgME::Key> Kleo::KeyResolver::signingKeysFor(CryptoMessageFormat f)
const
1176 return d->mOpenPGPSigningKeys;
1179 return d->mSMIMESigningKeys;
1184 std::vector<GpgME::Key> Kleo::KeyResolver::encryptToSelfKeysFor(CryptoMessageFormat f)
const
1187 return d->mOpenPGPEncryptToSelfKeys;
1190 return d->mSMIMEEncryptToSelfKeys;
1195 QStringList Kleo::KeyResolver::allRecipients()
const
1198 std::transform(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), std::back_inserter(result), ItemDotAddress);
1199 std::transform(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), std::back_inserter(result), ItemDotAddress);
1203 void Kleo::KeyResolver::collapseAllSplitInfos()
1206 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1207 auto pos = d->mFormatInfoMap.find(concreteCryptoMessageFormats[i]);
1208 if (pos == d->mFormatInfoMap.end()) {
1211 std::vector<SplitInfo> &v = pos->second.splitInfos;
1215 SplitInfo &si = v.front();
1216 for (
auto it = v.begin() + 1; it != v.end(); ++it) {
1217 si.keys.insert(si.keys.end(), it->keys.begin(), it->keys.end());
1218 std::copy(it->recipients.begin(), it->recipients.end(), std::back_inserter(si.recipients));
1225 void Kleo::KeyResolver::addToAllSplitInfos(
const std::vector<GpgME::Key> &keys,
unsigned int f)
1228 if (!f || keys.empty()) {
1231 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1232 if (!(f & concreteCryptoMessageFormats[i])) {
1235 auto pos = d->mFormatInfoMap.find(concreteCryptoMessageFormats[i]);
1236 if (pos == d->mFormatInfoMap.end()) {
1239 std::vector<SplitInfo> &v = pos->second.splitInfos;
1240 for (
auto it = v.begin(); it != v.end(); ++it) {
1241 it->keys.insert(it->keys.end(), keys.begin(), keys.end());
1247 void Kleo::KeyResolver::dump()
const
1250 if (d->mFormatInfoMap.empty()) {
1251 qCDebug(MESSAGECOMPOSER_LOG) <<
"Keyresolver: Format info empty";
1253 for (
auto it = d->mFormatInfoMap.begin(); it != d->mFormatInfoMap.end(); ++it) {
1254 qCDebug(MESSAGECOMPOSER_LOG) <<
"Format info for " << Kleo::cryptoMessageFormatToString(it->first) <<
": Signing keys: ";
1255 for (
auto sit = it->second.signKeys.begin(); sit != it->second.signKeys.end(); ++sit) {
1256 qCDebug(MESSAGECOMPOSER_LOG) <<
" " << sit->shortKeyID() <<
" ";
1259 for (
auto sit = it->second.splitInfos.begin(), sitEnd = it->second.splitInfos.end(); sit != sitEnd; ++sit, ++i) {
1260 qCDebug(MESSAGECOMPOSER_LOG) <<
" SplitInfo #" << i <<
" encryption keys: ";
1261 for (
auto kit = sit->keys.begin(), sitEnd = sit->keys.end(); kit != sitEnd; ++kit) {
1262 qCDebug(MESSAGECOMPOSER_LOG) <<
" " << kit->shortKeyID();
1264 qCDebug(MESSAGECOMPOSER_LOG) <<
" SplitInfo #" << i <<
" recipients: " << qPrintable(sit->recipients.join(
QLatin1String(
", ")));
1270 Kleo::Result Kleo::KeyResolver::showKeyApprovalDialog(
bool &finalySendUnencrypted)
1272 const bool showKeysForApproval = showApprovalDialog() || std::any_of(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), ApprovalNeeded)
1273 || std::any_of(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), ApprovalNeeded);
1275 if (!showKeysForApproval) {
1279 std::vector<Kleo::KeyApprovalDialog::Item> items;
1280 items.reserve(d->mPrimaryEncryptionKeys.size() + d->mSecondaryEncryptionKeys.size());
1281 std::copy(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), std::back_inserter(items));
1282 std::copy(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), std::back_inserter(items));
1284 std::vector<GpgME::Key> senderKeys;
1285 senderKeys.reserve(d->mOpenPGPEncryptToSelfKeys.size() + d->mSMIMEEncryptToSelfKeys.size());
1286 std::copy(d->mOpenPGPEncryptToSelfKeys.begin(), d->mOpenPGPEncryptToSelfKeys.end(), std::back_inserter(senderKeys));
1287 std::copy(d->mSMIMEEncryptToSelfKeys.begin(), d->mSMIMEEncryptToSelfKeys.end(), std::back_inserter(senderKeys));
1295 return Kleo::Canceled;
1298 items = dlg->items();
1299 senderKeys = dlg->senderKeys();
1300 const bool prefsChanged = dlg->preferencesChanged();
1304 for (uint i = 0, total = items.size(); i < total; ++i) {
1305 auto pref = lookupContactPreferences(items[i].address);
1306 pref.encryptionPreference = items[i].pref;
1307 pref.pgpKeyFingerprints.clear();
1308 pref.smimeCertFingerprints.clear();
1309 const std::vector<GpgME::Key> &keys = items[i].keys;
1310 for (
auto it = keys.begin(), end = keys.end(); it != end; ++it) {
1311 if (it->protocol() == GpgME::OpenPGP) {
1312 if (
const char *fpr = it->primaryFingerprint()) {
1315 }
else if (it->protocol() == GpgME::CMS) {
1316 if (
const char *fpr = it->primaryFingerprint()) {
1321 saveContactPreference(items[i].address, pref);
1327 if (encryptToSelf() && senderKeys.empty()) {
1329 "You did not select an encryption key for yourself "
1330 "(encrypt to self). You will not be able to decrypt "
1331 "your own message if you encrypt it.");
1333 return Kleo::Canceled;
1335 mEncryptToSelf =
false;
1340 const unsigned int emptyListCount = std::count_if(items.begin(), items.end(), EmptyKeyList);
1344 if (items.size() == emptyListCount) {
1345 const QString msg = (d->mPrimaryEncryptionKeys.size() + d->mSecondaryEncryptionKeys.size() == 1)
1347 "You did not select an encryption key for the "
1348 "recipient of this message; therefore, the message "
1349 "will not be encrypted.")
1351 "You did not select an encryption key for any of the "
1352 "recipients of this message; therefore, the message "
1353 "will not be encrypted.");
1355 return Kleo::Canceled;
1357 finalySendUnencrypted =
true;
1358 }
else if (emptyListCount > 0) {
1360 "You did not select an encryption key for one of "
1361 "the recipients: this person will not be able to "
1362 "decrypt the message if you encrypt it.")
1364 "You did not select encryption keys for some of "
1365 "the recipients: these persons will not be able to "
1366 "decrypt the message if you encrypt it.");
1369 return Kleo::Canceled;
1373 std::transform(d->mPrimaryEncryptionKeys.begin(),
1374 d->mPrimaryEncryptionKeys.end(),
1376 d->mPrimaryEncryptionKeys.begin(),
1377 CopyKeysAndEncryptionPreferences);
1378 std::transform(d->mSecondaryEncryptionKeys.begin(),
1379 d->mSecondaryEncryptionKeys.end(),
1380 items.begin() + d->mPrimaryEncryptionKeys.size(),
1381 d->mSecondaryEncryptionKeys.begin(),
1382 CopyKeysAndEncryptionPreferences);
1384 d->mOpenPGPEncryptToSelfKeys.clear();
1385 d->mSMIMEEncryptToSelfKeys.clear();
1387 std::remove_copy_if(senderKeys.begin(),
1389 std::back_inserter(d->mOpenPGPEncryptToSelfKeys),
1390 NotValidTrustedOpenPGPEncryptionKey);
1391 std::remove_copy_if(senderKeys.begin(),
1393 std::back_inserter(d->mSMIMEEncryptToSelfKeys),
1394 NotValidTrustedSMIMEEncryptionKey);
1402 auto it = d->mFormatInfoMap.find(f);
1403 return it != d->mFormatInfoMap.end() ? it->second.splitInfos : std::vector<SplitInfo>();
1408 d->mAutocryptEnabled = autocryptEnabled;
1411 std::map<QByteArray, QString> Kleo::KeyResolver::useAutocrypt()
const
1413 return d->mAutocryptMap;
1418 d->mAkonadiLookupEnabled = akonadiLoopkupEnabled;
1424 auto it = d->mFormatInfoMap.find(f);
1425 return it != d->mFormatInfoMap.end() ? it->second.signKeys : std::vector<GpgME::Key>();
1434 std::vector<GpgME::Key> Kleo::KeyResolver::selectKeys(
const QString &person,
const QString &msg,
const std::vector<GpgME::Key> &selectedKeys)
const
1436 const bool opgp = containsOpenPGP(mCryptoMessageFormats);
1437 const bool x509 = containsSMIME(mCryptoMessageFormats);
1440 i18n(
"Encryption Key Selection"),
1444 Kleo::KeySelectionDialog::ValidEncryptionKeys & ~(opgp ? 0 : Kleo::KeySelectionDialog::OpenPGPKeys) & ~(x509 ? 0 : Kleo::KeySelectionDialog::SMIMEKeys),
1453 std::vector<GpgME::Key> keys = dlg->selectedKeys();
1454 keys.erase(std::remove_if(keys.begin(), keys.end(), NotValidEncryptionKey), keys.end());
1455 if (!keys.empty() && dlg->rememberSelection()) {
1456 setKeysForAddress(person, dlg->pgpKeyFingerprints(), dlg->smimeFingerprints());
1463 std::vector<GpgME::Key> Kleo::KeyResolver::getEncryptionKeys(
const QString &person,
bool quiet)
const
1468 const QStringList fingerprints = keysForAddress(address);
1470 if (!fingerprints.
empty()) {
1471 qCDebug(MESSAGECOMPOSER_LOG) <<
"Using encryption keys 0x" << fingerprints.
join(
QLatin1String(
", 0x")) <<
"for" << person;
1472 std::vector<GpgME::Key> keys = lookup(fingerprints);
1473 if (!keys.empty()) {
1475 if (std::any_of(keys.begin(), keys.end(),
1476 NotValidTrustedEncryptionKey)) {
1480 keys = selectKeys(person,
1481 i18nc(
"if in your language something like "
1482 "'certificate(s)' is not possible please "
1483 "use the plural in the translation",
1484 "There is a problem with the "
1485 "encryption certificate(s) for \"%1\".\n\n"
1486 "Please re-select the certificate(s) which should "
1487 "be used for this recipient.",
1491 bool canceled =
false;
1492 keys = trustedOrConfirmed(keys, address, canceled);
1497 if (!keys.empty()) {
1505 std::vector<GpgME::Key> matchingKeys = lookup(
QStringList(address));
1506 matchingKeys.erase(std::remove_if(matchingKeys.begin(), matchingKeys.end(), NotValidEncryptionKey), matchingKeys.end());
1508 if (matchingKeys.empty() && d->mAutocryptEnabled) {
1509 qCDebug(MESSAGECOMPOSER_LOG) <<
"Search in Autocrypt storage a key for " <<
address;
1510 const auto storage = MessageCore::AutocryptStorage::self();
1511 const auto recipient = storage->getRecipient(
address.toUtf8());
1513 const auto key = recipient->gpgKey();
1514 if (!key.isNull() && ValidEncryptionKey(key)) {
1515 qCDebug(MESSAGECOMPOSER_LOG) <<
"Found an valid autocrypt key.";
1516 matchingKeys.push_back(key);
1518 const auto gossipKey = recipient->gossipKey();
1519 if (!gossipKey.isNull() && ValidEncryptionKey(gossipKey)) {
1520 qCDebug(MESSAGECOMPOSER_LOG) <<
"Found an valid autocrypt gossip key.";
1521 matchingKeys.push_back(gossipKey);
1526 if (matchingKeys.size() == 1) {
1527 if (recipient->prefer_encrypt()) {
1528 d->mContactPreferencesMap[
address].encryptionPreference = AlwaysEncryptIfPossible;
1530 d->mAutocryptMap[matchingKeys[0].primaryFingerprint()] =
address;
1531 return matchingKeys;
1538 bool canceled =
false;
1540 matchingKeys = trustedOrConfirmed(matchingKeys, address, canceled);
1545 if (quiet || matchingKeys.size() == 1) {
1546 return matchingKeys;
1552 return trustedOrConfirmed(selectKeys(person,
1553 matchingKeys.empty() ?
i18nc(
"if in your language something like "
1554 "'certificate(s)' is not possible please "
1555 "use the plural in the translation",
1556 "<qt>No valid and trusted encryption certificate was "
1557 "found for \"%1\".<br/><br/>"
1558 "Select the certificate(s) which should "
1559 "be used for this recipient. If there is no suitable certificate in the list "
1560 "you can also search for external certificates by clicking the button: "
1561 "search for external certificates.</qt>",
1563 :
i18nc(
"if in your language something like "
1564 "'certificate(s)' is not possible please "
1565 "use the plural in the translation",
1566 "More than one certificate matches \"%1\".\n\n"
1567 "Select the certificate(s) which should "
1568 "be used for this recipient.",
1577 std::vector<GpgME::Key> Kleo::KeyResolver::lookup(
const QStringList &patterns,
bool secret)
const
1579 if (patterns.
empty()) {
1582 qCDebug(MESSAGECOMPOSER_LOG) <<
"( \"" << patterns.
join(
QLatin1String(
"\", \"")) <<
"\"," << secret <<
")";
1583 std::vector<GpgME::Key> result;
1584 if (mCryptoMessageFormats & (InlineOpenPGPFormat | OpenPGPMIMEFormat)) {
1585 if (
const QGpgME::Protocol *p = QGpgME::openpgp()) {
1586 std::unique_ptr<QGpgME::KeyListJob> job(p->keyListJob(
false,
false,
true));
1588 std::vector<GpgME::Key> keys;
1589 job->exec(patterns, secret, keys);
1590 result.insert(result.end(), keys.begin(), keys.end());
1594 if (mCryptoMessageFormats & (SMIMEFormat | SMIMEOpaqueFormat)) {
1595 if (
const QGpgME::Protocol *p = QGpgME::smime()) {
1596 std::unique_ptr<QGpgME::KeyListJob> job(p->keyListJob(
false,
false,
true));
1598 std::vector<GpgME::Key> keys;
1599 job->exec(patterns, secret, keys);
1600 result.insert(result.end(), keys.begin(), keys.end());
1604 qCDebug(MESSAGECOMPOSER_LOG) <<
" returned" << result.size() <<
"keys";
1608 void Kleo::KeyResolver::addKeys(
const std::vector<Item> &items, CryptoMessageFormat f)
1611 for (
auto it = items.begin(); it != items.end(); ++it) {
1613 std::remove_copy_if(it->keys.begin(), it->keys.end(), std::back_inserter(si.keys), IsNotForFormat(f));
1615 if (si.keys.empty()) {
1616 qCWarning(MESSAGECOMPOSER_LOG) <<
"Kleo::KeyResolver::addKeys(): Fix EncryptionFormatPreferenceCounter."
1617 <<
"It detected a common format, but the list of such keys for recipient \"" << it->address <<
"\" is empty!";
1619 d->mFormatInfoMap[f].splitInfos.push_back(si);
1624 void Kleo::KeyResolver::addKeys(
const std::vector<Item> &items)
1627 for (
auto it = items.begin(); it != items.end(); ++it) {
1629 CryptoMessageFormat f = AutoFormat;
1630 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1631 const CryptoMessageFormat fmt = concreteCryptoMessageFormats[i];
1632 if ((fmt & it->format) && std::any_of(it->keys.begin(), it->keys.end(), IsForFormat(fmt))) {
1637 if (f == AutoFormat) {
1638 qCWarning(MESSAGECOMPOSER_LOG) <<
"Something went wrong. Didn't find a format for \"" << it->address <<
"\"";
1640 std::remove_copy_if(it->keys.begin(), it->keys.end(), std::back_inserter(si.keys), IsNotForFormat(f));
1642 d->mFormatInfoMap[f].splitInfos.push_back(si);
1647 MessageComposer::ContactPreference Kleo::KeyResolver::lookupContactPreferences(
const QString &address)
const
1649 const auto it = d->mContactPreferencesMap.find(address);
1650 if (it != d->mContactPreferencesMap.end()) {
1654 MessageComposer::ContactPreference pref;
1656 if (!d->mAkonadiLookupEnabled) {
1666 if (!res.isEmpty()) {
1668 pref.fillFromAddressee(addr);
1671 d->mContactPreferencesMap.insert(std::make_pair(address, pref));
1676 void Kleo::KeyResolver::saveContactPreference(
const QString &email,
const MessageComposer::ContactPreference &pref)
const
1678 d->mContactPreferencesMap.insert(std::make_pair(email, pref));
1679 auto saveContactPreferencesJob =
new MessageComposer::SaveContactPreferenceJob(email, pref);
1680 saveContactPreferencesJob->start();
1689 const auto pref = lookupContactPreferences(addr);
1690 return pref.pgpKeyFingerprints + pref.smimeCertFingerprints;
1693 void Kleo::KeyResolver::setKeysForAddress(
const QString &address,
const QStringList &pgpKeyFingerprints,
const QStringList &smimeCertFingerprints)
const
1699 auto pref = lookupContactPreferences(addr);
1700 pref.pgpKeyFingerprints = pgpKeyFingerprints;
1701 pref.smimeCertFingerprints = smimeCertFingerprints;
1702 saveContactPreference(addr, pref);
1705 bool Kleo::KeyResolver::encryptToSelf()
const
1707 return mEncryptToSelf;
1710 bool Kleo::KeyResolver::showApprovalDialog()
const
1712 return mShowApprovalDialog;