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");
325 if (!ickies.empty()) {
326 msg +=
i18n(
"\nThe following keys or certificates have unknown trust level: \n");
329 if (!rewookies.empty()) {
330 msg +=
i18n(
"\nThe following keys or certificates are <b>revoked</b>: \n");
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;
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);
726 d->mPrimaryEncryptionKeys = getEncryptionItems(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;
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();
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);
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 return Kleo::Canceled;
1349 finalySendUnencrypted =
true;
1350 }
else if (emptyListCount > 0) {
1352 "You did not select an encryption key for one of "
1353 "the recipients: this person will not be able to "
1354 "decrypt the message if you encrypt it.")
1356 "You did not select encryption keys for some of "
1357 "the recipients: these persons will not be able to "
1358 "decrypt the message if you encrypt it.");
1362 return Kleo::Canceled;
1366 std::transform(d->mPrimaryEncryptionKeys.begin(),
1367 d->mPrimaryEncryptionKeys.end(),
1369 d->mPrimaryEncryptionKeys.begin(),
1370 CopyKeysAndEncryptionPreferences);
1371 std::transform(d->mSecondaryEncryptionKeys.begin(),
1372 d->mSecondaryEncryptionKeys.end(),
1373 items.begin() + d->mPrimaryEncryptionKeys.size(),
1374 d->mSecondaryEncryptionKeys.begin(),
1375 CopyKeysAndEncryptionPreferences);
1377 d->mOpenPGPEncryptToSelfKeys.clear();
1378 d->mSMIMEEncryptToSelfKeys.clear();
1380 std::remove_copy_if(senderKeys.begin(),
1382 std::back_inserter(d->mOpenPGPEncryptToSelfKeys),
1383 NotValidTrustedOpenPGPEncryptionKey);
1384 std::remove_copy_if(senderKeys.begin(),
1386 std::back_inserter(d->mSMIMEEncryptToSelfKeys),
1387 NotValidTrustedSMIMEEncryptionKey);
1395 auto it = d->mFormatInfoMap.find(f);
1396 return it != d->mFormatInfoMap.end() ? it->second.splitInfos : std::vector<SplitInfo>();
1401 d->mAutocryptEnabled = autocryptEnabled;
1404std::map<QByteArray, QString> Kleo::KeyResolver::useAutocrypt()
const
1406 return d->mAutocryptMap;
1411 d->mAkonadiLookupEnabled = akonadiLoopkupEnabled;
1417 auto it = d->mFormatInfoMap.find(f);
1418 return it != d->mFormatInfoMap.end() ? it->second.signKeys : std::vector<GpgME::Key>();
1427std::vector<GpgME::Key> Kleo::KeyResolver::selectKeys(
const QString &person,
const QString &msg,
const std::vector<GpgME::Key> &selectedKeys)
const
1429 const bool opgp = containsOpenPGP(mCryptoMessageFormats);
1430 const bool x509 = containsSMIME(mCryptoMessageFormats);
1433 i18n(
"Encryption Key Selection"),
1437 Kleo::KeySelectionDialog::ValidEncryptionKeys & ~(opgp ? 0 :
Kleo::KeySelectionDialog::OpenPGPKeys) & ~(x509 ? 0 :
Kleo::KeySelectionDialog::SMIMEKeys),
1446 std::vector<GpgME::Key> keys = dlg->selectedKeys();
1447 keys.erase(std::remove_if(keys.begin(), keys.end(), NotValidEncryptionKey), keys.end());
1448 if (!keys.empty() && dlg->rememberSelection()) {
1449 setKeysForAddress(person, dlg->pgpKeyFingerprints(), dlg->smimeFingerprints());
1456std::vector<GpgME::Key> Kleo::KeyResolver::getEncryptionKeys(
const QString &person,
bool quiet)
const
1461 const QStringList fingerprints = keysForAddress(address);
1463 if (!fingerprints.
empty()) {
1464 qCDebug(MESSAGECOMPOSER_LOG) <<
"Using encryption keys 0x" << fingerprints.
join(
QLatin1StringView(
", 0x")) <<
"for" << person;
1465 std::vector<GpgME::Key> keys = lookup(fingerprints);
1466 if (!keys.empty()) {
1468 if (std::any_of(keys.begin(), keys.end(),
1469 NotValidTrustedEncryptionKey)) {
1473 keys = selectKeys(person,
1474 i18nc(
"if in your language something like "
1475 "'certificate(s)' is not possible please "
1476 "use the plural in the translation",
1477 "There is a problem with the "
1478 "encryption certificate(s) for \"%1\".\n\n"
1479 "Please re-select the certificate(s) which should "
1480 "be used for this recipient.",
1484 bool canceled =
false;
1485 keys = trustedOrConfirmed(keys, address, canceled);
1490 if (!keys.empty()) {
1498 std::vector<GpgME::Key> matchingKeys = lookup(
QStringList(address));
1499 matchingKeys.erase(std::remove_if(matchingKeys.begin(), matchingKeys.end(), NotValidEncryptionKey), matchingKeys.end());
1501 if (matchingKeys.empty() && d->mAutocryptEnabled) {
1502 qCDebug(MESSAGECOMPOSER_LOG) <<
"Search in Autocrypt storage a key for " <<
address;
1503 const auto storage = MessageCore::AutocryptStorage::self();
1504 const auto recipient = storage->getRecipient(
address.toUtf8());
1506 const auto key = recipient->gpgKey();
1507 if (!key.isNull() && ValidEncryptionKey(key)) {
1508 qCDebug(MESSAGECOMPOSER_LOG) <<
"Found an valid autocrypt key.";
1509 matchingKeys.push_back(key);
1511 const auto gossipKey = recipient->gossipKey();
1512 if (!gossipKey.isNull() && ValidEncryptionKey(gossipKey)) {
1513 qCDebug(MESSAGECOMPOSER_LOG) <<
"Found an valid autocrypt gossip key.";
1514 matchingKeys.push_back(gossipKey);
1519 if (matchingKeys.size() == 1) {
1520 if (recipient->prefer_encrypt()) {
1521 d->mContactPreferencesMap[
address].encryptionPreference = AlwaysEncryptIfPossible;
1523 d->mAutocryptMap[matchingKeys[0].primaryFingerprint()] =
address;
1524 return matchingKeys;
1531 bool canceled =
false;
1533 matchingKeys = trustedOrConfirmed(matchingKeys, address, canceled);
1538 if (quiet || matchingKeys.size() == 1) {
1539 return matchingKeys;
1545 return trustedOrConfirmed(selectKeys(person,
1546 matchingKeys.empty() ?
i18nc(
"if in your language something like "
1547 "'certificate(s)' is not possible please "
1548 "use the plural in the translation",
1549 "<qt>No valid and trusted encryption certificate was "
1550 "found for \"%1\".<br/><br/>"
1551 "Select the certificate(s) which should "
1552 "be used for this recipient. If there is no suitable certificate in the list "
1553 "you can also search for external certificates by clicking the button: "
1554 "search for external certificates.</qt>",
1556 :
i18nc(
"if in your language something like "
1557 "'certificate(s)' is not possible please "
1558 "use the plural in the translation",
1559 "More than one certificate matches \"%1\".\n\n"
1560 "Select the certificate(s) which should "
1561 "be used for this recipient.",
1562 person.toHtmlEscaped()),
1570std::vector<GpgME::Key> Kleo::KeyResolver::lookup(
const QStringList &patterns,
bool secret)
const
1572 if (patterns.
empty()) {
1575 qCDebug(MESSAGECOMPOSER_LOG) <<
"( \"" << patterns.
join(
QLatin1StringView(
"\", \"")) <<
"\"," << secret <<
")";
1576 std::vector<GpgME::Key> result;
1577 if (mCryptoMessageFormats & (InlineOpenPGPFormat | OpenPGPMIMEFormat)) {
1578 if (
const QGpgME::Protocol *p = QGpgME::openpgp()) {
1579 std::unique_ptr<QGpgME::KeyListJob> job(p->keyListJob(
false,
false,
true));
1581 std::vector<GpgME::Key> keys;
1582 job->exec(patterns, secret, keys);
1583 result.insert(result.end(), keys.begin(), keys.end());
1587 if (mCryptoMessageFormats & (SMIMEFormat | SMIMEOpaqueFormat)) {
1588 if (
const QGpgME::Protocol *p = QGpgME::smime()) {
1589 std::unique_ptr<QGpgME::KeyListJob> job(p->keyListJob(
false,
false,
true));
1591 std::vector<GpgME::Key> keys;
1592 job->exec(patterns, secret, keys);
1593 result.insert(result.end(), keys.begin(), keys.end());
1597 qCDebug(MESSAGECOMPOSER_LOG) <<
" returned" << result.size() <<
"keys";
1601void Kleo::KeyResolver::addKeys(
const std::vector<Item> &items, CryptoMessageFormat f)
1604 for (
auto it = items.begin(); it != items.end(); ++it) {
1606 std::remove_copy_if(it->keys.begin(), it->keys.end(), std::back_inserter(si.keys), IsNotForFormat(f));
1608 if (si.keys.empty()) {
1609 qCWarning(MESSAGECOMPOSER_LOG) <<
"Kleo::KeyResolver::addKeys(): Fix EncryptionFormatPreferenceCounter."
1610 <<
"It detected a common format, but the list of such keys for recipient \"" << it->address <<
"\" is empty!";
1612 d->mFormatInfoMap[f].splitInfos.push_back(si);
1617void Kleo::KeyResolver::addKeys(
const std::vector<Item> &items)
1620 for (
auto it = items.begin(); it != items.end(); ++it) {
1622 CryptoMessageFormat f = AutoFormat;
1623 for (
unsigned int i = 0; i < numConcreteCryptoMessageFormats; ++i) {
1624 const CryptoMessageFormat fmt = concreteCryptoMessageFormats[i];
1625 if ((fmt & it->format) && std::any_of(it->keys.begin(), it->keys.end(), IsForFormat(fmt))) {
1630 if (f == AutoFormat) {
1631 qCWarning(MESSAGECOMPOSER_LOG) <<
"Something went wrong. Didn't find a format for \"" << it->address <<
"\"";
1633 std::remove_copy_if(it->keys.begin(), it->keys.end(), std::back_inserter(si.keys), IsNotForFormat(f));
1635 d->mFormatInfoMap[f].splitInfos.push_back(si);
1640MessageComposer::ContactPreference Kleo::KeyResolver::lookupContactPreferences(
const QString &address)
const
1642 const auto it = d->mContactPreferencesMap.find(address);
1643 if (it != d->mContactPreferencesMap.end()) {
1647 MessageComposer::ContactPreference pref;
1649 if (!d->mAkonadiLookupEnabled) {
1659 if (!res.isEmpty()) {
1661 pref.fillFromAddressee(addr);
1664 const_cast<KeyResolver *
>(
this)->setContactPreferences(address, pref);
1671 d->mContactPreferencesMap.insert(std::make_pair(address, pref));
1674void Kleo::KeyResolver::saveContactPreference(
const QString &email,
const MessageComposer::ContactPreference &pref)
const
1676 d->mContactPreferencesMap.insert(std::make_pair(email, pref));
1677 auto saveContactPreferencesJob =
new MessageComposer::SaveContactPreferenceJob(email, pref);
1678 saveContactPreferencesJob->start();
1687 const auto pref = lookupContactPreferences(addr);
1688 return pref.pgpKeyFingerprints + pref.smimeCertFingerprints;
1691void Kleo::KeyResolver::setKeysForAddress(
const QString &address,
const QStringList &pgpKeyFingerprints,
const QStringList &smimeCertFingerprints)
const
1697 auto pref = lookupContactPreferences(addr);
1698 pref.pgpKeyFingerprints = pgpKeyFingerprints;
1699 pref.smimeCertFingerprints = smimeCertFingerprints;
1700 saveContactPreference(addr, pref);
1703bool Kleo::KeyResolver::encryptToSelf()
const
1705 return mEncryptToSelf;
1708bool Kleo::KeyResolver::showApprovalDialog()
const
1710 return mShowApprovalDialog;
Kleo::Result setEncryptToSelfKeys(const QStringList &fingerprints)
Set the fingerprints of keys to be used for encrypting to self.
std::vector< SplitInfo > encryptionItems(CryptoMessageFormat f) const
void setPrimaryRecipients(const QStringList &addresses)
Set the list of primary (To/CC) recipient addresses.
void setAkonadiLookupEnabled(bool akonadiLookupEnabled)
Disable ContactSearchJob in KeyResolver.
void setContactPreferences(const QString &address, const MessageComposer::ContactPreference &preference)
Sets crypto preferences for given email address.
std::vector< GpgME::Key > signingKeys(CryptoMessageFormat f) const
Kleo::Result setSigningKeys(const QStringList &fingerprints)
Set the fingerprints of keys to be used for signing.
Action checkSigningPreferences(bool signingRequested) const
Determine whether to sign or not, depending on the per-recipient signing preferences,...
Action checkEncryptionPreferences(bool encryptionRequested) const
Determine whether to encrypt or not, depending on the per-recipient encryption preferences,...
void setSecondaryRecipients(const QStringList &addresses)
Set the list of secondary (BCC) recipient addresses.
void setAutocryptEnabled(bool autocryptEnabled)
If Autocrypt keys are used to find valid PGP Keys.
Kleo::Result resolveAllKeys(bool &signingRequested, bool &encryptionRequested)
Queries the user for missing keys and displays a key approval dialog if needed.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
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)
const QList< QKeySequence > & end()
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 simplified() const const
QString toHtmlEscaped() const const
QString toLower() const const
QString join(QChar separator) const const