14#include "composer/keyresolver.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>
25#include <Libkleo/ExpiryChecker>
26#include <Libkleo/KeySelectionDialog>
28#include <QGpgME/KeyListJob>
29#include <QGpgME/Protocol>
31#include <gpgme++/key.h>
32#include <gpgme++/keylistresult.h>
34#include "messagecomposer_debug.h"
35#include <Akonadi/ContactSearchJob>
36#include <KLocalizedString>
39#include <MessageCore/AutocryptRecipient>
40#include <MessageCore/AutocryptStorage>
58static inline bool EmptyKeyList(
const Kleo::KeyApprovalDialog::Item &item)
60 return item.keys.empty();
63static inline QString ItemDotAddress(
const Kleo::KeyResolver::Item &item)
68static inline bool ApprovalNeeded(
const Kleo::KeyResolver::Item &item)
70 bool approvalNeeded = item.pref == Kleo::NeverEncrypt || item.keys.empty();
71 if (!approvalNeeded && Kleo::DeVSCompliance::isCompliant()) {
72 approvalNeeded = !Kleo::all_of(item.keys, &Kleo::DeVSCompliance::keyIsCompliant);
74 return approvalNeeded;
77static inline Kleo::KeyResolver::Item CopyKeysAndEncryptionPreferences(
const Kleo::KeyResolver::Item &oldItem,
const Kleo::KeyApprovalDialog::Item &newItem)
79 return Kleo::KeyResolver::Item(oldItem.address, newItem.keys, newItem.pref, oldItem.signPref, oldItem.format);
82static bool ValidOpenPGPEncryptionKey(
const GpgME::Key &key)
84 if (key.protocol() != GpgME::OpenPGP) {
87 if (key.isRevoked()) {
88 qCWarning(MESSAGECOMPOSER_LOG) <<
"is revoked";
90 if (key.isExpired()) {
91 qCWarning(MESSAGECOMPOSER_LOG) <<
"is expired";
93 if (key.isDisabled()) {
94 qCWarning(MESSAGECOMPOSER_LOG) <<
"is disabled";
96 if (!key.canEncrypt()) {
97 qCWarning(MESSAGECOMPOSER_LOG) <<
"can't encrypt";
99 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canEncrypt()) {
105static bool ValidTrustedOpenPGPEncryptionKey(
const GpgME::Key &key)
107 if (!ValidOpenPGPEncryptionKey(key)) {
110 const std::vector<GpgME::UserID> uids = key.userIDs();
111 auto end(uids.end());
112 for (
auto it = uids.begin(); it != end; ++it) {
113 if (!it->isRevoked() && it->validity() >= GpgME::UserID::Marginal) {
115 }
else if (it->isRevoked()) {
116 qCWarning(MESSAGECOMPOSER_LOG) <<
"a userid is revoked";
118 qCWarning(MESSAGECOMPOSER_LOG) <<
"bad validity" << int(it->validity());
124static bool ValidSMIMEEncryptionKey(
const GpgME::Key &key)
126 if (key.protocol() != GpgME::CMS) {
129 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canEncrypt()) {
135static bool ValidTrustedSMIMEEncryptionKey(
const GpgME::Key &key)
137 if (!ValidSMIMEEncryptionKey(key)) {
143static inline bool ValidTrustedEncryptionKey(
const GpgME::Key &key)
145 switch (key.protocol()) {
147 return ValidTrustedOpenPGPEncryptionKey(key);
149 return ValidTrustedSMIMEEncryptionKey(key);
155static inline bool ValidEncryptionKey(
const GpgME::Key &key)
157 switch (key.protocol()) {
159 return ValidOpenPGPEncryptionKey(key);
161 return ValidSMIMEEncryptionKey(key);
167static inline bool ValidSigningKey(
const GpgME::Key &key)
169 if (key.isRevoked() || key.isExpired() || key.isDisabled() || !key.canSign()) {
172 return key.hasSecret();
175static inline bool ValidOpenPGPSigningKey(
const GpgME::Key &key)
177 return key.protocol() == GpgME::OpenPGP && ValidSigningKey(key);
180static inline bool ValidSMIMESigningKey(
const GpgME::Key &key)
182 return key.protocol() == GpgME::CMS && ValidSigningKey(key);
185static inline bool NotValidTrustedOpenPGPEncryptionKey(
const GpgME::Key &key)
187 return !ValidTrustedOpenPGPEncryptionKey(key);
190static inline bool NotValidTrustedSMIMEEncryptionKey(
const GpgME::Key &key)
192 return !ValidTrustedSMIMEEncryptionKey(key);
195static inline bool NotValidTrustedEncryptionKey(
const GpgME::Key &key)
197 return !ValidTrustedEncryptionKey(key);
200static inline bool NotValidEncryptionKey(
const GpgME::Key &key)
202 return !ValidEncryptionKey(key);
205static inline bool NotValidOpenPGPSigningKey(
const GpgME::Key &key)
207 return !ValidOpenPGPSigningKey(key);
210static inline bool NotValidSMIMESigningKey(
const GpgME::Key &key)
212 return !ValidSMIMESigningKey(key);
218 static int score(
const GpgME::UserID &uid)
220 return uid.isRevoked() || uid.isInvalid() ? -1 : uid.validity();
223 bool operator()(
const GpgME::UserID &lhs,
const GpgME::UserID &rhs)
const
225 return score(lhs) < score(rhs);
230static std::vector<GpgME::UserID> matchingUIDs(
const std::vector<GpgME::UserID> &uids,
const QString &address)
236 std::vector<GpgME::UserID> result;
237 result.reserve(uids.size());
239 for (
auto it = uids.begin(), end = uids.end(); it != end; ++it) {
241 if (
const char *email = it->email()) {
243 result.push_back(*it);
250static GpgME::UserID findBestMatchUID(
const GpgME::Key &key,
const QString &address)
252 const std::vector<GpgME::UserID> all = key.userIDs();
256 const std::vector<GpgME::UserID> matching = matchingUIDs(all,
address.toLower());
257 const std::vector<GpgME::UserID> &v = matching.empty() ? all : matching;
258 return *std::max_element(v.begin(), v.end(), ByTrustScore());
261static QStringList keysAsStrings(
const std::vector<GpgME::Key> &keys)
265 for (
auto it = keys.begin(); it != keys.end(); ++it) {
266 assert(!(*it).userID(0).isNull());
267 const auto userID = (*it).userID(0);
280static std::vector<GpgME::Key> trustedOrConfirmed(
const std::vector<GpgME::Key> &keys,
const QString &address,
bool &canceled)
283 std::vector<GpgME::Key> fishies;
284 std::vector<GpgME::Key> ickies;
285 std::vector<GpgME::Key> rewookies;
286 auto it = keys.begin();
287 const auto end = keys.end();
288 for (; it !=
end; ++it) {
289 const GpgME::Key &key = *it;
290 assert(ValidEncryptionKey(key));
291 const GpgME::UserID uid = findBestMatchUID(key, address);
292 if (uid.isRevoked()) {
293 rewookies.push_back(key);
295 if (!uid.isRevoked()) {
296 if (uid.validity() == GpgME::UserID::Marginal) {
297 fishies.push_back(key);
299 if (uid.validity() < GpgME::UserID::Never) {
300 ickies.push_back(key);
305 if (fishies.empty() && ickies.empty() && rewookies.empty()) {
311 "One or more of your configured OpenPGP encryption "
312 "keys or S/MIME certificates is not fully trusted "
315 "One or more of the OpenPGP encryption keys or S/MIME "
316 "certificates for recipient \"%1\" is not fully trusted "
320 if (!fishies.empty()) {
322 msg += i18n(
"\nThe following keys are only marginally trusted: \n");
323 msg += keysAsStrings(fishies).join(QLatin1Char(
','));
325 if (!ickies.empty()) {
326 msg += i18n(
"\nThe following keys or certificates have unknown trust level: \n");
327 msg += keysAsStrings(ickies).join(QLatin1Char(
','));
329 if (!rewookies.empty()) {
330 msg += i18n(
"\nThe following keys or certificates are <b>revoked</b>: \n");
331 msg += keysAsStrings(rewookies).join(QLatin1Char(
','));
336 i18nc(
"@title:window",
"Not Fully Trusted Encryption Keys"),
339 QStringLiteral(
"not fully trusted encryption key warning"))
350struct IsNotForFormat :
public std::function<bool(GpgME::Key)> {
351 IsNotForFormat(Kleo::CryptoMessageFormat f)
356 bool operator()(
const GpgME::Key &key)
const
358 return (isOpenPGP(format) && key.protocol() != GpgME::OpenPGP) || (isSMIME(format) && key.protocol() != GpgME::CMS);
361 const Kleo::CryptoMessageFormat format;
364struct IsForFormat : std::function<bool(GpgME::Key)> {
365 explicit IsForFormat(Kleo::CryptoMessageFormat f)
366 : protocol(isOpenPGP(f) ? GpgME::OpenPGP
367 : isSMIME(f) ? GpgME::CMS
372 bool operator()(
const GpgME::Key &key)
const
374 return key.protocol() == protocol;
377 const GpgME::Protocol protocol;
381class Kleo::KeyResolver::SigningPreferenceCounter :
public std::function<void(Kleo::KeyResolver::Item)>
384 SigningPreferenceCounter() =
default;
386 void operator()(
const Kleo::KeyResolver::Item &item);
387#define make_int_accessor(x) \
388 unsigned int num##x() const \
392 make_int_accessor(UnknownSigningPreference) make_int_accessor(NeverSign) make_int_accessor(AlwaysSign) make_int_accessor(AlwaysSignIfPossible)
393 make_int_accessor(AlwaysAskForSigning) make_int_accessor(AskSigningWheneverPossible) make_int_accessor(Total)
394#undef make_int_accessor
395 private :
unsigned int mTotal = 0;
396 unsigned int mUnknownSigningPreference = 0;
397 unsigned int mNeverSign = 0;
398 unsigned int mAlwaysSign = 0;
399 unsigned int mAlwaysSignIfPossible = 0;
400 unsigned int mAlwaysAskForSigning = 0;
401 unsigned int mAskSigningWheneverPossible = 0;
404void Kleo::KeyResolver::SigningPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
406 switch (item.signPref) {
411 CASE(UnknownSigningPreference);
414 CASE(AlwaysSignIfPossible);
415 CASE(AlwaysAskForSigning);
416 CASE(AskSigningWheneverPossible);
422class Kleo::KeyResolver::EncryptionPreferenceCounter :
public std::function<void(Item)>
427 EncryptionPreferenceCounter(
const Kleo::KeyResolver *kr, EncryptionPreference defaultPreference)
429 , mDefaultPreference(defaultPreference)
433 void operator()(
Item &item);
435 template<
typename Container>
436 void process(Container &c)
438 *
this = std::for_each(c.begin(), c.end(), *
this);
441#define make_int_accessor(x) \
442 unsigned int num##x() const \
446 make_int_accessor(NoKey) make_int_accessor(NeverEncrypt) make_int_accessor(UnknownPreference) make_int_accessor(AlwaysEncrypt)
447 make_int_accessor(AlwaysEncryptIfPossible) make_int_accessor(AlwaysAskForEncryption) make_int_accessor(AskWheneverPossible) make_int_accessor(Total)
448#undef make_int_accessor
449 private : EncryptionPreference mDefaultPreference;
450 unsigned int mTotal = 0;
451 unsigned int mNoKey = 0;
452 unsigned int mNeverEncrypt = 0;
453 unsigned int mUnknownPreference = 0;
454 unsigned int mAlwaysEncrypt = 0;
455 unsigned int mAlwaysEncryptIfPossible = 0;
456 unsigned int mAlwaysAskForEncryption = 0;
457 unsigned int mAskWheneverPossible = 0;
460void Kleo::KeyResolver::EncryptionPreferenceCounter::operator()(
Item &item)
464 item.keys = _this->getEncryptionKeys(item.address,
true);
466 if (item.keys.empty()) {
471 switch (!item.pref ? mDefaultPreference : item.pref) {
477 CASE(UnknownPreference);
479 CASE(AlwaysEncryptIfPossible);
480 CASE(AlwaysAskForEncryption);
481 CASE(AskWheneverPossible);
489class FormatPreferenceCounterBase :
public std::function<void(Kleo::KeyResolver::Item)>
492 FormatPreferenceCounterBase() =
default;
494#define make_int_accessor(x) \
495 unsigned int num##x() const \
499 make_int_accessor(Total) make_int_accessor(InlineOpenPGP) make_int_accessor(OpenPGPMIME) make_int_accessor(SMIME) make_int_accessor(SMIMEOpaque)
500#undef make_int_accessor
502 [[nodiscard]]
unsigned int numOf(Kleo::CryptoMessageFormat f)
const
506 case Kleo::x##Format: \
519 unsigned int mTotal = 0;
520 unsigned int mInlineOpenPGP = 0;
521 unsigned int mOpenPGPMIME = 0;
522 unsigned int mSMIME = 0;
523 unsigned int mSMIMEOpaque = 0;
526class EncryptionFormatPreferenceCounter :
public FormatPreferenceCounterBase
529 EncryptionFormatPreferenceCounter()
530 : FormatPreferenceCounterBase()
534 void operator()(
const Kleo::KeyResolver::Item &item);
537class SigningFormatPreferenceCounter :
public FormatPreferenceCounterBase
540 SigningFormatPreferenceCounter()
541 : FormatPreferenceCounterBase()
545 void operator()(
const Kleo::KeyResolver::Item &item);
549 if (item.format & Kleo::x##Format) { \
552void EncryptionFormatPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
554 if (item.format & (Kleo::InlineOpenPGPFormat | Kleo::OpenPGPMIMEFormat)
555 && std::any_of(item.keys.begin(),
557 ValidTrustedOpenPGPEncryptionKey)) {
561 if (item.format & (Kleo::SMIMEFormat | Kleo::SMIMEOpaqueFormat)
562 && std::any_of(item.keys.begin(),
564 ValidTrustedSMIMEEncryptionKey)) {
571void SigningFormatPreferenceCounter::operator()(
const Kleo::KeyResolver::Item &item)
596 std::vector<Kleo::KeyResolver::SplitInfo> splitInfos;
597 std::vector<GpgME::Key> signKeys;
600struct Q_DECL_HIDDEN
Kleo::KeyResolver::KeyResolverPrivate {
601 bool mAkonadiLookupEnabled =
true;
602 bool mAutocryptEnabled =
false;
603 std::set<QByteArray> alreadyWarnedFingerprints;
605 std::vector<GpgME::Key> mOpenPGPSigningKeys;
606 std::vector<GpgME::Key> mSMIMESigningKeys;
608 std::vector<GpgME::Key> mOpenPGPEncryptToSelfKeys;
609 std::vector<GpgME::Key> mSMIMEEncryptToSelfKeys;
611 std::vector<Item> mPrimaryEncryptionKeys;
612 std::vector<Item> mSecondaryEncryptionKeys;
614 std::map<CryptoMessageFormat, FormatInfo> mFormatInfoMap;
617 using ContactPreferencesMap = std::map<QString, MessageComposer::ContactPreference>;
618 ContactPreferencesMap mContactPreferencesMap;
619 std::map<QByteArray, QString> mAutocryptMap;
620 std::shared_ptr<Kleo::ExpiryChecker> expiryChecker;
623Kleo::KeyResolver::KeyResolver(
bool encToSelf,
bool showApproval,
bool oppEncryption,
unsigned int f,
const std::shared_ptr<Kleo::ExpiryChecker> &expiryChecker)
624 : d(new KeyResolverPrivate)
625 , mEncryptToSelf(encToSelf)
626 , mShowApprovalDialog(showApproval)
627 , mOpportunisticEncyption(oppEncryption)
628 , mCryptoMessageFormats(f)
630 d->expiryChecker = expiryChecker;
633Kleo::KeyResolver::~KeyResolver() =
default;
635Kleo::Result Kleo::KeyResolver::setEncryptToSelfKeys(
const QStringList &fingerprints)
637 if (!encryptToSelf()) {
641 std::vector<GpgME::Key> keys = lookup(fingerprints);
642 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mOpenPGPEncryptToSelfKeys),
643 NotValidTrustedOpenPGPEncryptionKey);
644 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mSMIMEEncryptToSelfKeys),
645 NotValidTrustedSMIMEEncryptionKey);
647 if (d->mOpenPGPEncryptToSelfKeys.size() + d->mSMIMEEncryptToSelfKeys.size() < keys.size()) {
650 "One or more of your configured OpenPGP encryption "
651 "keys or S/MIME certificates is not usable for "
652 "encryption. Please reconfigure your encryption keys "
653 "and certificates for this identity in the identity "
654 "configuration dialog.\n"
655 "If you choose to continue, and the keys are needed "
656 "later on, you will be prompted to specify the keys "
660 i18nc(
"@title:window",
"Unusable Encryption Keys"),
663 QStringLiteral(
"unusable own encryption key warning"))
670 std::vector<GpgME::Key>::const_iterator
end(d->mOpenPGPEncryptToSelfKeys.end());
672 for (
auto it = d->mOpenPGPEncryptToSelfKeys.begin(); it != end; ++it) {
673 d->expiryChecker->checkKey(*it, Kleo::ExpiryChecker::OwnEncryptionKey);
675 std::vector<GpgME::Key>::const_iterator end2(d->mSMIMEEncryptToSelfKeys.end());
676 for (
auto it = d->mSMIMEEncryptToSelfKeys.begin(); it != end2; ++it) {
677 d->expiryChecker->checkKey(*it, Kleo::ExpiryChecker::OwnEncryptionKey);
685 std::vector<GpgME::Key> keys = lookup(fingerprints,
true);
686 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mOpenPGPSigningKeys), NotValidOpenPGPSigningKey);
687 std::remove_copy_if(keys.begin(), keys.end(), std::back_inserter(d->mSMIMESigningKeys), NotValidSMIMESigningKey);
689 if (d->mOpenPGPSigningKeys.size() + d->mSMIMESigningKeys.size() < keys.size()) {
692 "One or more of your configured OpenPGP signing keys "
693 "or S/MIME signing certificates is not usable for "
694 "signing. Please reconfigure your signing keys "
695 "and certificates for this identity in the identity "
696 "configuration dialog.\n"
697 "If you choose to continue, and the keys are needed "
698 "later on, you will be prompted to specify the keys "
702 i18nc(
"@title:window",
"Unusable Signing Keys"),
705 QStringLiteral(
"unusable signing key warning"))
713 for (
auto it = d->mOpenPGPSigningKeys.begin(), total = d->mOpenPGPSigningKeys.end(); it != total; ++it) {
714 d->expiryChecker->checkKey(*it, Kleo::ExpiryChecker::OwnSigningKey);
717 for (
auto it = d->mSMIMESigningKeys.begin(), total = d->mSMIMESigningKeys.end(); it != total; ++it) {
718 d->expiryChecker->checkKey(*it, Kleo::ExpiryChecker::OwnSigningKey);
724void Kleo::KeyResolver::setPrimaryRecipients(
const QStringList &addresses)
726 d->mPrimaryEncryptionKeys = getEncryptionItems(addresses);
729void Kleo::KeyResolver::setSecondaryRecipients(
const QStringList &addresses)
731 d->mSecondaryEncryptionKeys = getEncryptionItems(addresses);
734std::vector<Kleo::KeyResolver::Item> Kleo::KeyResolver::getEncryptionItems(
const QStringList &addresses)
736 std::vector<Item> items;
737 items.reserve(addresses.
size());
741 const auto pref = lookupContactPreferences(addr);
743 items.emplace_back(*it,
744 pref.encryptionPreference,
745 pref.signingPreference,
746 pref.cryptoMessageFormat);
751static Kleo::Action action(
bool doit,
bool ask,
bool donot,
bool requested)
753 if (requested && !donot) {
756 if (doit && !ask && !donot) {
759 if (!doit && ask && !donot) {
762 if (!doit && !ask && donot) {
763 return requested ? Kleo::Conflict : Kleo::DontDoIt;
765 if (!doit && !ask && !donot) {
766 return Kleo::DontDoIt;
768 return Kleo::Conflict;
771Kleo::Action Kleo::KeyResolver::checkSigningPreferences(
bool signingRequested)
const
773 if (signingRequested && d->mOpenPGPSigningKeys.empty() && d->mSMIMESigningKeys.empty()) {
777 SigningPreferenceCounter count;
778 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
779 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
781 unsigned int sign = count.numAlwaysSign();
782 unsigned int ask = count.numAlwaysAskForSigning();
783 const unsigned int dontSign = count.numNeverSign();
784 if (signingPossible()) {
785 sign += count.numAlwaysSignIfPossible();
786 ask += count.numAskSigningWheneverPossible();
789 return action(sign, ask, dontSign, signingRequested);
792bool Kleo::KeyResolver::signingPossible()
const
794 return !d->mOpenPGPSigningKeys.empty() || !d->mSMIMESigningKeys.empty();
797Kleo::Action Kleo::KeyResolver::checkEncryptionPreferences(
bool encryptionRequested)
const
799 if (d->mPrimaryEncryptionKeys.empty() && d->mSecondaryEncryptionKeys.empty()) {
803 if (encryptionRequested && encryptToSelf() && d->mOpenPGPEncryptToSelfKeys.empty() && d->mSMIMEEncryptToSelfKeys.empty()) {
807 if (!encryptionRequested && !mOpportunisticEncyption) {
811 EncryptionPreferenceCounter count(
nullptr, UnknownPreference);
812 count.process(d->mPrimaryEncryptionKeys);
813 count.process(d->mSecondaryEncryptionKeys);
814 if (!count.numAlwaysEncrypt()
815 && !count.numAlwaysAskForEncryption()
816 && !count.numAlwaysEncryptIfPossible() && !count.numAskWheneverPossible()) {
821 EncryptionPreferenceCounter count(
this, mOpportunisticEncyption ? AskWheneverPossible : UnknownPreference);
822 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
823 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
825 unsigned int encrypt = count.numAlwaysEncrypt();
826 unsigned int ask = count.numAlwaysAskForEncryption();
827 const unsigned int dontEncrypt = count.numNeverEncrypt() + count.numNoKey();
828 if (encryptionPossible()) {
829 encrypt += count.numAlwaysEncryptIfPossible();
830 ask += count.numAskWheneverPossible();
833 const Action act = action(encrypt, ask, dontEncrypt, encryptionRequested);
836 d->mPrimaryEncryptionKeys.begin(),
837 d->mPrimaryEncryptionKeys.end(),
838 std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EncryptionPreferenceCounter(
this, UnknownPreference)))
839 .numAlwaysAskForEncryption()) {
842 return AskOpportunistic;
846bool Kleo::KeyResolver::encryptionPossible()
const
848 return std::none_of(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), EmptyKeyList)
849 && std::none_of(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EmptyKeyList);
852Kleo::Result Kleo::KeyResolver::resolveAllKeys(
bool &signingRequested,
bool &encryptionRequested)
854 if (!encryptionRequested && !signingRequested) {
858 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.emplace_back(allRecipients());
862 Kleo::Result result = Kleo::Ok;
863 if (encryptionRequested) {
864 bool finalySendUnencrypted =
false;
865 result = resolveEncryptionKeys(signingRequested, finalySendUnencrypted);
866 if (finalySendUnencrypted) {
867 encryptionRequested =
false;
870 if (result != Kleo::Ok) {
873 if (encryptionRequested) {
874 result = resolveSigningKeysForEncryption();
876 result = resolveSigningKeysForSigningOnly();
877 if (result == Kleo::Failure) {
878 signingRequested =
false;
885Kleo::Result Kleo::KeyResolver::resolveEncryptionKeys(
bool signingRequested,
bool &finalySendUnencrypted)
890 qCDebug(MESSAGECOMPOSER_LOG) <<
"resolving enc keys" << d->mPrimaryEncryptionKeys.size();
891 for (
auto it = d->mPrimaryEncryptionKeys.begin(); it != d->mPrimaryEncryptionKeys.end(); ++it) {
892 qCDebug(MESSAGECOMPOSER_LOG) <<
"checking primary:" << it->address;
896 it->keys = getEncryptionKeys(it->address,
false);
897 qCDebug(MESSAGECOMPOSER_LOG) <<
"got # keys:" << it->keys.size();
898 if (it->keys.empty()) {
899 return Kleo::Canceled;
902 const auto pref = lookupContactPreferences(addr);
903 it->pref = pref.encryptionPreference;
904 it->signPref = pref.signingPreference;
905 it->format = pref.cryptoMessageFormat;
906 qCDebug(MESSAGECOMPOSER_LOG) <<
"set key data:" << int(it->pref) << int(it->signPref) << int(it->format);
909 for (
auto it = d->mSecondaryEncryptionKeys.begin(), total = d->mSecondaryEncryptionKeys.end(); it != total; ++it) {
913 it->keys = getEncryptionKeys(it->address,
false);
914 if (it->keys.empty()) {
915 return Kleo::Canceled;
918 const auto pref = lookupContactPreferences(addr);
919 it->pref = pref.encryptionPreference;
920 it->signPref = pref.signingPreference;
921 it->format = pref.cryptoMessageFormat;
926 const Kleo::Result res = showKeyApprovalDialog(finalySendUnencrypted);
927 if (res != Kleo::Ok) {
938 const EncryptionFormatPreferenceCounter primaryCount =
939 std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), EncryptionFormatPreferenceCounter());
941 CryptoMessageFormat commonFormat = AutoFormat;
942 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
943 if (!(concreteCryptoMessageFormats[i] & mCryptoMessageFormats)) {
946 if (signingRequested && signingKeysFor(concreteCryptoMessageFormats[i]).empty()) {
949 if (encryptToSelf() && encryptToSelfKeysFor(concreteCryptoMessageFormats[i]).empty()) {
952 if (primaryCount.numOf(concreteCryptoMessageFormats[i]) == primaryCount.numTotal()) {
953 commonFormat = concreteCryptoMessageFormats[i];
957 qCDebug(MESSAGECOMPOSER_LOG) <<
"got commonFormat for primary recipients:" << int(commonFormat);
958 if (commonFormat != AutoFormat) {
959 addKeys(d->mPrimaryEncryptionKeys, commonFormat);
961 addKeys(d->mPrimaryEncryptionKeys);
964 collapseAllSplitInfos();
969 const EncryptionFormatPreferenceCounter secondaryCount =
970 std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), EncryptionFormatPreferenceCounter());
972 if (commonFormat != AutoFormat && secondaryCount.numOf(commonFormat) == secondaryCount.numTotal()) {
973 addKeys(d->mSecondaryEncryptionKeys, commonFormat);
975 addKeys(d->mSecondaryEncryptionKeys);
980 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
981 const std::vector<SplitInfo> si_list = encryptionItems(concreteCryptoMessageFormats[i]);
982 for (
auto sit = si_list.begin(), total = si_list.end(); sit != total; ++sit) {
983 for (
auto kit = sit->keys.begin(); kit != sit->keys.end(); ++kit) {
984 d->expiryChecker->checkKey(*kit, Kleo::ExpiryChecker::EncryptionKey);
991 if (!encryptToSelf()) {
997 qCDebug(MESSAGECOMPOSER_LOG) <<
"sizes of encryption items:" << encryptionItems(InlineOpenPGPFormat).size() << encryptionItems(OpenPGPMIMEFormat).size()
998 << encryptionItems(SMIMEFormat).size() << encryptionItems(SMIMEOpaqueFormat).size();
999 if (!encryptionItems(InlineOpenPGPFormat).empty() || !encryptionItems(OpenPGPMIMEFormat).empty()) {
1001 if (d->mOpenPGPEncryptToSelfKeys.empty()) {
1003 "Examination of recipient's encryption preferences "
1004 "yielded that the message should be encrypted using "
1005 "OpenPGP, at least for some recipients;\n"
1006 "however, you have not configured valid trusted "
1007 "OpenPGP encryption keys for this identity.\n"
1008 "You may continue without encrypting to yourself, "
1009 "but be aware that you will not be able to read your "
1010 "own messages if you do so.");
1013 i18nc(
"@title:window",
"Unusable Encryption Keys"),
1016 QStringLiteral(
"encrypt-to-self will fail warning"))
1018 return Kleo::Canceled;
1022 addToAllSplitInfos(d->mOpenPGPEncryptToSelfKeys, InlineOpenPGPFormat | OpenPGPMIMEFormat);
1027 if (!encryptionItems(SMIMEFormat).empty() || !encryptionItems(SMIMEOpaqueFormat).empty()) {
1029 if (d->mSMIMEEncryptToSelfKeys.empty()) {
1032 "Examination of recipient's encryption preferences "
1033 "yielded that the message should be encrypted using "
1034 "S/MIME, at least for some recipients;\n"
1035 "however, you have not configured valid "
1036 "S/MIME encryption certificates for this identity.\n"
1037 "You may continue without encrypting to yourself, "
1038 "but be aware that you will not be able to read your "
1039 "own messages if you do so.");
1042 i18nc(
"@title:window",
"Unusable Encryption Keys"),
1045 QStringLiteral(
"encrypt-to-self will fail warning"))
1047 return Kleo::Canceled;
1051 addToAllSplitInfos(d->mSMIMEEncryptToSelfKeys, SMIMEFormat | SMIMEOpaqueFormat);
1060Kleo::Result Kleo::KeyResolver::resolveSigningKeysForEncryption()
1062 if ((!encryptionItems(InlineOpenPGPFormat).empty() || !encryptionItems(OpenPGPMIMEFormat).empty()) && d->mOpenPGPSigningKeys.empty()) {
1064 "Examination of recipient's signing preferences "
1065 "yielded that the message should be signed using "
1066 "OpenPGP, at least for some recipients;\n"
1067 "however, you have not configured valid "
1068 "OpenPGP signing certificates for this identity.");
1071 i18nc(
"@title:window",
"Unusable Signing Keys"),
1074 QStringLiteral(
"signing will fail warning"))
1076 return Kleo::Canceled;
1080 if ((!encryptionItems(SMIMEFormat).empty() || !encryptionItems(SMIMEOpaqueFormat).empty()) && d->mSMIMESigningKeys.empty()) {
1082 "Examination of recipient's signing preferences "
1083 "yielded that the message should be signed using "
1084 "S/MIME, at least for some recipients;\n"
1085 "however, you have not configured valid "
1086 "S/MIME signing certificates for this identity.");
1089 i18nc(
"@title:window",
"Unusable Signing Keys"),
1092 QStringLiteral(
"signing will fail warning"))
1094 return Kleo::Canceled;
1102 for (
auto it = d->mFormatInfoMap.begin(); it != d->mFormatInfoMap.end(); ++it) {
1103 if (!it->second.splitInfos.empty()) {
1105 it->second.signKeys = signingKeysFor(it->first);
1113Kleo::Result Kleo::KeyResolver::resolveSigningKeysForSigningOnly()
1119 SigningFormatPreferenceCounter count;
1120 count = std::for_each(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), count);
1121 count = std::for_each(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), count);
1125 CryptoMessageFormat commonFormat = AutoFormat;
1127 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1128 const auto res = concreteCryptoMessageFormats[i];
1129 if (!(mCryptoMessageFormats & res)) {
1132 if (signingKeysFor(res).empty()) {
1135 if (count.numOf(res) == count.numTotal()) {
1141 if (commonFormat != AutoFormat) {
1143 FormatInfo &fi = d->mFormatInfoMap[commonFormat];
1144 fi.signKeys = signingKeysFor(commonFormat);
1145 fi.splitInfos.resize(1);
1146 fi.splitInfos.front() = SplitInfo(allRecipients());
1152 "Examination of recipient's signing preferences "
1153 "showed no common type of signature matching your "
1154 "available signing keys.\n"
1155 "Send message without signing?");
1157 d->mFormatInfoMap[OpenPGPMIMEFormat].splitInfos.emplace_back(allRecipients());
1158 return Kleo::Failure;
1160 return Kleo::Canceled;
1163std::vector<GpgME::Key> Kleo::KeyResolver::signingKeysFor(CryptoMessageFormat f)
const
1166 return d->mOpenPGPSigningKeys;
1169 return d->mSMIMESigningKeys;
1174std::vector<GpgME::Key> Kleo::KeyResolver::encryptToSelfKeysFor(CryptoMessageFormat f)
const
1177 return d->mOpenPGPEncryptToSelfKeys;
1180 return d->mSMIMEEncryptToSelfKeys;
1185QStringList Kleo::KeyResolver::allRecipients()
const
1188 std::transform(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), std::back_inserter(result), ItemDotAddress);
1189 std::transform(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), std::back_inserter(result), ItemDotAddress);
1193void Kleo::KeyResolver::collapseAllSplitInfos()
1196 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1197 auto pos = d->mFormatInfoMap.find(concreteCryptoMessageFormats[i]);
1198 if (pos == d->mFormatInfoMap.end()) {
1201 std::vector<SplitInfo> &v = pos->second.splitInfos;
1205 SplitInfo &si = v.front();
1206 for (
auto it = v.begin() + 1; it != v.end(); ++it) {
1207 si.keys.insert(si.keys.end(), it->keys.begin(), it->keys.end());
1208 std::copy(it->recipients.begin(), it->recipients.end(), std::back_inserter(si.recipients));
1215void Kleo::KeyResolver::addToAllSplitInfos(
const std::vector<GpgME::Key> &keys,
unsigned int f)
1218 if (!f || keys.empty()) {
1221 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1222 if (!(f & concreteCryptoMessageFormats[i])) {
1225 auto pos = d->mFormatInfoMap.find(concreteCryptoMessageFormats[i]);
1226 if (pos == d->mFormatInfoMap.end()) {
1229 std::vector<SplitInfo> &v = pos->second.splitInfos;
1230 for (
auto it = v.begin(); it != v.end(); ++it) {
1231 it->keys.insert(it->keys.end(), keys.begin(), keys.end());
1237void Kleo::KeyResolver::dump()
const
1240 if (d->mFormatInfoMap.empty()) {
1241 qCDebug(MESSAGECOMPOSER_LOG) <<
"Keyresolver: Format info empty";
1243 for (
auto it = d->mFormatInfoMap.begin(); it != d->mFormatInfoMap.end(); ++it) {
1244 qCDebug(MESSAGECOMPOSER_LOG) <<
"Format info for " << Kleo::cryptoMessageFormatToString(it->first) <<
": Signing keys: ";
1245 for (
auto sit = it->second.signKeys.begin(); sit != it->second.signKeys.end(); ++sit) {
1246 qCDebug(MESSAGECOMPOSER_LOG) <<
" " << sit->shortKeyID() <<
" ";
1249 for (
auto sit = it->second.splitInfos.begin(), sitEnd = it->second.splitInfos.end(); sit != sitEnd; ++sit, ++i) {
1250 qCDebug(MESSAGECOMPOSER_LOG) <<
" SplitInfo #" << i <<
" encryption keys: ";
1251 for (
auto kit = sit->keys.begin(), sitEnd = sit->keys.end(); kit != sitEnd; ++kit) {
1252 qCDebug(MESSAGECOMPOSER_LOG) <<
" " << kit->shortKeyID();
1254 qCDebug(MESSAGECOMPOSER_LOG) <<
" SplitInfo #" << i <<
" recipients: " << qPrintable(sit->recipients.join(
QLatin1StringView(
", ")));
1260Kleo::Result Kleo::KeyResolver::showKeyApprovalDialog(
bool &finalySendUnencrypted)
1262 const bool showKeysForApproval = showApprovalDialog() || std::any_of(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), ApprovalNeeded)
1263 || std::any_of(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), ApprovalNeeded);
1265 if (!showKeysForApproval) {
1269 std::vector<Kleo::KeyApprovalDialog::Item> items;
1270 items.reserve(d->mPrimaryEncryptionKeys.size() + d->mSecondaryEncryptionKeys.size());
1271 std::copy(d->mPrimaryEncryptionKeys.begin(), d->mPrimaryEncryptionKeys.end(), std::back_inserter(items));
1272 std::copy(d->mSecondaryEncryptionKeys.begin(), d->mSecondaryEncryptionKeys.end(), std::back_inserter(items));
1274 std::vector<GpgME::Key> senderKeys;
1275 senderKeys.reserve(d->mOpenPGPEncryptToSelfKeys.size() + d->mSMIMEEncryptToSelfKeys.size());
1276 std::copy(d->mOpenPGPEncryptToSelfKeys.begin(), d->mOpenPGPEncryptToSelfKeys.end(), std::back_inserter(senderKeys));
1277 std::copy(d->mSMIMEEncryptToSelfKeys.begin(), d->mSMIMEEncryptToSelfKeys.end(), std::back_inserter(senderKeys));
1285 return Kleo::Canceled;
1288 items = dlg->items();
1289 senderKeys = dlg->senderKeys();
1290 const bool prefsChanged = dlg->preferencesChanged();
1294 for (uint i = 0, total = items.size(); i < total; ++i) {
1295 auto pref = lookupContactPreferences(items[i].address);
1296 pref.encryptionPreference = items[i].pref;
1297 pref.pgpKeyFingerprints.clear();
1298 pref.smimeCertFingerprints.clear();
1299 const std::vector<GpgME::Key> &keys = items[i].keys;
1300 for (
auto it = keys.begin(), end = keys.end(); it != end; ++it) {
1301 if (it->protocol() == GpgME::OpenPGP) {
1302 if (
const char *fpr = it->primaryFingerprint()) {
1305 }
else if (it->protocol() == GpgME::CMS) {
1306 if (
const char *fpr = it->primaryFingerprint()) {
1311 saveContactPreference(items[i].address, pref);
1317 if (encryptToSelf() && senderKeys.empty()) {
1319 "You did not select an encryption key for yourself "
1320 "(encrypt to self). You will not be able to decrypt "
1321 "your own message if you encrypt it.");
1324 return Kleo::Canceled;
1326 mEncryptToSelf =
false;
1331 const unsigned int emptyListCount = std::count_if(items.begin(), items.end(), EmptyKeyList);
1335 if (items.size() == emptyListCount) {
1336 const QString msg = (d->mPrimaryEncryptionKeys.size() + d->mSecondaryEncryptionKeys.size() == 1)
1338 "You did not select an encryption key for the "
1339 "recipient of this message; therefore, the message "
1340 "will not be encrypted.")
1342 "You did not select an encryption key for any of the "
1343 "recipients of this message; therefore, the message "
1344 "will not be encrypted.");
1347 i18nc(
"@title:window",
"Missing Key Warning"),
1350 return Kleo::Canceled;
1352 finalySendUnencrypted =
true;
1353 }
else if (emptyListCount > 0) {
1355 "You did not select an encryption key for one of "
1356 "the recipients: this person will not be able to "
1357 "decrypt the message if you encrypt it.")
1359 "You did not select encryption keys for some of "
1360 "the recipients: these persons will not be able to "
1361 "decrypt the message if you encrypt it.");
1365 return Kleo::Canceled;
1369 std::transform(d->mPrimaryEncryptionKeys.begin(),
1370 d->mPrimaryEncryptionKeys.end(),
1372 d->mPrimaryEncryptionKeys.begin(),
1373 CopyKeysAndEncryptionPreferences);
1374 std::transform(d->mSecondaryEncryptionKeys.begin(),
1375 d->mSecondaryEncryptionKeys.end(),
1376 items.begin() + d->mPrimaryEncryptionKeys.size(),
1377 d->mSecondaryEncryptionKeys.begin(),
1378 CopyKeysAndEncryptionPreferences);
1380 d->mOpenPGPEncryptToSelfKeys.clear();
1381 d->mSMIMEEncryptToSelfKeys.clear();
1383 std::remove_copy_if(senderKeys.begin(),
1385 std::back_inserter(d->mOpenPGPEncryptToSelfKeys),
1386 NotValidTrustedOpenPGPEncryptionKey);
1387 std::remove_copy_if(senderKeys.begin(),
1389 std::back_inserter(d->mSMIMEEncryptToSelfKeys),
1390 NotValidTrustedSMIMEEncryptionKey);
1395std::vector<Kleo::KeyResolver::SplitInfo> Kleo::KeyResolver::encryptionItems(Kleo::CryptoMessageFormat f)
const
1398 auto it = d->mFormatInfoMap.find(f);
1399 return it != d->mFormatInfoMap.end() ? it->second.splitInfos : std::vector<SplitInfo>();
1402void Kleo::KeyResolver::setAutocryptEnabled(
bool autocryptEnabled)
1404 d->mAutocryptEnabled = autocryptEnabled;
1407std::map<QByteArray, QString> Kleo::KeyResolver::useAutocrypt()
const
1409 return d->mAutocryptMap;
1412void Kleo::KeyResolver::setAkonadiLookupEnabled(
bool akonadiLoopkupEnabled)
1414 d->mAkonadiLookupEnabled = akonadiLoopkupEnabled;
1417std::vector<GpgME::Key> Kleo::KeyResolver::signingKeys(CryptoMessageFormat f)
const
1420 auto it = d->mFormatInfoMap.find(f);
1421 return it != d->mFormatInfoMap.end() ? it->second.signKeys : std::vector<GpgME::Key>();
1430std::vector<GpgME::Key> Kleo::KeyResolver::selectKeys(
const QString &person,
const QString &msg,
const std::vector<GpgME::Key> &selectedKeys)
const
1432 const bool opgp = containsOpenPGP(mCryptoMessageFormats);
1433 const bool x509 = containsSMIME(mCryptoMessageFormats);
1436 i18n(
"Encryption Key Selection"),
1440 Kleo::KeySelectionDialog::ValidEncryptionKeys & ~(opgp ? 0 : Kleo::KeySelectionDialog::OpenPGPKeys) & ~(x509 ? 0 : Kleo::KeySelectionDialog::SMIMEKeys),
1449 std::vector<GpgME::Key> keys = dlg->selectedKeys();
1450 keys.erase(std::remove_if(keys.begin(), keys.end(), NotValidEncryptionKey), keys.end());
1451 if (!keys.empty() && dlg->rememberSelection()) {
1452 setKeysForAddress(person, dlg->pgpKeyFingerprints(), dlg->smimeFingerprints());
1459std::vector<GpgME::Key> Kleo::KeyResolver::getEncryptionKeys(
const QString &person,
bool quiet)
const
1464 const QStringList fingerprints = keysForAddress(address);
1466 if (!fingerprints.
empty()) {
1467 qCDebug(MESSAGECOMPOSER_LOG) <<
"Using encryption keys 0x" << fingerprints.
join(
QLatin1StringView(
", 0x")) <<
"for" << person;
1468 std::vector<GpgME::Key> keys = lookup(fingerprints);
1469 if (!keys.empty()) {
1471 if (std::any_of(keys.begin(), keys.end(),
1472 NotValidTrustedEncryptionKey)) {
1476 keys = selectKeys(person,
1477 i18nc(
"if in your language something like "
1478 "'certificate(s)' is not possible please "
1479 "use the plural in the translation",
1480 "There is a problem with the "
1481 "encryption certificate(s) for \"%1\".\n\n"
1482 "Please re-select the certificate(s) which should "
1483 "be used for this recipient.",
1487 bool canceled =
false;
1488 keys = trustedOrConfirmed(keys, address, canceled);
1493 if (!keys.empty()) {
1501 std::vector<GpgME::Key> matchingKeys = lookup(
QStringList(address));
1502 matchingKeys.erase(std::remove_if(matchingKeys.begin(), matchingKeys.end(), NotValidEncryptionKey), matchingKeys.end());
1504 if (matchingKeys.empty() && d->mAutocryptEnabled) {
1505 qCDebug(MESSAGECOMPOSER_LOG) <<
"Search in Autocrypt storage a key for " <<
address;
1506 const auto storage = MessageCore::AutocryptStorage::self();
1507 const auto recipient = storage->getRecipient(
address.toUtf8());
1509 const auto key = recipient->gpgKey();
1510 if (!key.isNull() && ValidEncryptionKey(key)) {
1511 qCDebug(MESSAGECOMPOSER_LOG) <<
"Found an valid autocrypt key.";
1512 matchingKeys.push_back(key);
1514 const auto gossipKey = recipient->gossipKey();
1515 if (!gossipKey.isNull() && ValidEncryptionKey(gossipKey)) {
1516 qCDebug(MESSAGECOMPOSER_LOG) <<
"Found an valid autocrypt gossip key.";
1517 matchingKeys.push_back(gossipKey);
1522 if (matchingKeys.size() == 1) {
1523 if (recipient->prefer_encrypt()) {
1524 d->mContactPreferencesMap[
address].encryptionPreference = AlwaysEncryptIfPossible;
1526 d->mAutocryptMap[matchingKeys[0].primaryFingerprint()] =
address;
1527 return matchingKeys;
1534 bool canceled =
false;
1536 matchingKeys = trustedOrConfirmed(matchingKeys, address, canceled);
1541 if (quiet || matchingKeys.size() == 1) {
1542 return matchingKeys;
1548 return trustedOrConfirmed(selectKeys(person,
1549 matchingKeys.empty() ?
i18nc(
"if in your language something like "
1550 "'certificate(s)' is not possible please "
1551 "use the plural in the translation",
1552 "<qt>No valid and trusted encryption certificate was "
1553 "found for \"%1\".<br/><br/>"
1554 "Select the certificate(s) which should "
1555 "be used for this recipient. If there is no suitable certificate in the list "
1556 "you can also search for external certificates by clicking the button: "
1557 "search for external certificates.</qt>",
1559 :
i18nc(
"if in your language something like "
1560 "'certificate(s)' is not possible please "
1561 "use the plural in the translation",
1562 "More than one certificate matches \"%1\".\n\n"
1563 "Select the certificate(s) which should "
1564 "be used for this recipient.",
1573std::vector<GpgME::Key> Kleo::KeyResolver::lookup(
const QStringList &patterns,
bool secret)
const
1575 if (patterns.
empty()) {
1578 qCDebug(MESSAGECOMPOSER_LOG) <<
"( \"" << patterns.
join(
QLatin1StringView(
"\", \"")) <<
"\"," << secret <<
")";
1579 std::vector<GpgME::Key> result;
1580 if (mCryptoMessageFormats & (InlineOpenPGPFormat | OpenPGPMIMEFormat)) {
1581 if (
const QGpgME::Protocol *p = QGpgME::openpgp()) {
1582 std::unique_ptr<QGpgME::KeyListJob> job(p->keyListJob(
false,
false,
true));
1584 std::vector<GpgME::Key> keys;
1585 job->exec(patterns, secret, keys);
1586 result.insert(result.end(), keys.begin(), keys.end());
1590 if (mCryptoMessageFormats & (SMIMEFormat | SMIMEOpaqueFormat)) {
1591 if (
const QGpgME::Protocol *p = QGpgME::smime()) {
1592 std::unique_ptr<QGpgME::KeyListJob> job(p->keyListJob(
false,
false,
true));
1594 std::vector<GpgME::Key> keys;
1595 job->exec(patterns, secret, keys);
1596 result.insert(result.end(), keys.begin(), keys.end());
1600 qCDebug(MESSAGECOMPOSER_LOG) <<
" returned" << result.size() <<
"keys";
1604void Kleo::KeyResolver::addKeys(
const std::vector<Item> &items, CryptoMessageFormat f)
1607 for (
auto it = items.begin(); it != items.end(); ++it) {
1609 std::remove_copy_if(it->keys.begin(), it->keys.end(), std::back_inserter(si.keys), IsNotForFormat(f));
1611 if (si.keys.empty()) {
1612 qCWarning(MESSAGECOMPOSER_LOG) <<
"Kleo::KeyResolver::addKeys(): Fix EncryptionFormatPreferenceCounter."
1613 <<
"It detected a common format, but the list of such keys for recipient \"" << it->address <<
"\" is empty!";
1615 d->mFormatInfoMap[f].splitInfos.push_back(si);
1620void Kleo::KeyResolver::addKeys(
const std::vector<Item> &items)
1623 for (
auto it = items.begin(); it != items.end(); ++it) {
1625 CryptoMessageFormat f = AutoFormat;
1626 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1627 const CryptoMessageFormat fmt = concreteCryptoMessageFormats[i];
1628 if ((fmt & it->format) && std::any_of(it->keys.begin(), it->keys.end(), IsForFormat(fmt))) {
1633 if (f == AutoFormat) {
1634 qCWarning(MESSAGECOMPOSER_LOG) <<
"Something went wrong. Didn't find a format for \"" << it->address <<
"\"";
1636 std::remove_copy_if(it->keys.begin(), it->keys.end(), std::back_inserter(si.keys), IsNotForFormat(f));
1638 d->mFormatInfoMap[f].splitInfos.push_back(si);
1643MessageComposer::ContactPreference Kleo::KeyResolver::lookupContactPreferences(
const QString &address)
const
1645 const auto it = d->mContactPreferencesMap.find(address);
1646 if (it != d->mContactPreferencesMap.end()) {
1650 MessageComposer::ContactPreference pref;
1652 if (!d->mAkonadiLookupEnabled) {
1662 if (!res.isEmpty()) {
1664 pref.fillFromAddressee(addr);
1667 const_cast<KeyResolver *
>(
this)->setContactPreferences(address, pref);
1672void Kleo::KeyResolver::setContactPreferences(
const QString &address,
const MessageComposer::ContactPreference &pref)
1674 d->mContactPreferencesMap.insert(std::make_pair(address, pref));
1677void Kleo::KeyResolver::saveContactPreference(
const QString &email,
const MessageComposer::ContactPreference &pref)
const
1679 d->mContactPreferencesMap.insert(std::make_pair(email, pref));
1680 auto saveContactPreferencesJob =
new MessageComposer::SaveContactPreferenceJob(email, pref);
1681 saveContactPreferencesJob->start();
1690 const auto pref = lookupContactPreferences(addr);
1691 return pref.pgpKeyFingerprints + pref.smimeCertFingerprints;
1694void Kleo::KeyResolver::setKeysForAddress(
const QString &address,
const QStringList &pgpKeyFingerprints,
const QStringList &smimeCertFingerprints)
const
1700 auto pref = lookupContactPreferences(addr);
1701 pref.pgpKeyFingerprints = pgpKeyFingerprints;
1702 pref.smimeCertFingerprints = smimeCertFingerprints;
1703 saveContactPreference(addr, pref);
1706bool Kleo::KeyResolver::encryptToSelf()
const
1708 return mEncryptToSelf;
1711bool Kleo::KeyResolver::showApprovalDialog()
const
1713 return mShowApprovalDialog;
KeyResolver(bool encrypt, bool sign, GpgME::Protocol protocol=GpgME::UnknownProtocol, bool allowMixed=true)
void setSigningKeys(const QStringList &fingerprints)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
PostalAddress address(const QVariant &location)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
void append(QList< T > &&value)
const_iterator constBegin() const const
const_iterator constEnd() const const
void reserve(qsizetype size)
qsizetype size() const const
const QChar at(qsizetype position) const const
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QString toHtmlEscaped() const const
QString toLower() const const
QString join(QChar separator) const const