diff options
-rw-r--r-- | framework/src/domain/composercontroller.cpp | 32 | ||||
-rw-r--r-- | framework/src/domain/composercontroller.h | 7 | ||||
-rw-r--r-- | framework/src/domain/mime/mailcrypto.cpp | 99 | ||||
-rw-r--r-- | framework/src/domain/mime/mailcrypto.h | 23 | ||||
-rw-r--r-- | framework/src/domain/mime/mailtemplates.cpp | 4 | ||||
-rw-r--r-- | framework/src/domain/mime/mailtemplates.h | 4 | ||||
-rw-r--r-- | framework/src/domain/mime/tests/mailtemplatetest.cpp | 50 |
7 files changed, 100 insertions, 119 deletions
diff --git a/framework/src/domain/composercontroller.cpp b/framework/src/domain/composercontroller.cpp index a71e66f9..fc436003 100644 --- a/framework/src/domain/composercontroller.cpp +++ b/framework/src/domain/composercontroller.cpp | |||
@@ -36,7 +36,7 @@ | |||
36 | #include "mime/mailcrypto.h" | 36 | #include "mime/mailcrypto.h" |
37 | #include "async.h" | 37 | #include "async.h" |
38 | 38 | ||
39 | std::vector<GpgME::Key> &operator+=(std::vector<GpgME::Key> &list, const std::vector<GpgME::Key> &add) | 39 | std::vector<MailCrypto::Key> &operator+=(std::vector<MailCrypto::Key> &list, const std::vector<MailCrypto::Key> &add) |
40 | { | 40 | { |
41 | list.insert(std::end(list), std::begin(add), std::end(add)); | 41 | list.insert(std::end(list), std::begin(add), std::end(add)); |
42 | return list; | 42 | return list; |
@@ -133,16 +133,16 @@ public: | |||
133 | mb.fromUnicodeString(addressee); | 133 | mb.fromUnicodeString(addressee); |
134 | 134 | ||
135 | SinkLog() << "Searching key for: " << mb.address(); | 135 | SinkLog() << "Searching key for: " << mb.address(); |
136 | asyncRun<std::vector<GpgME::Key>>(this, | 136 | asyncRun<std::vector<MailCrypto::Key>>(this, |
137 | [mb] { | 137 | [mb] { |
138 | return MailCrypto::findKeys(QStringList{} << mb.address(), false, false); | 138 | return MailCrypto::findKeys(QStringList{} << mb.address(), false, false); |
139 | }, | 139 | }, |
140 | [this, addressee, id](const std::vector<GpgME::Key> &keys) { | 140 | [this, addressee, id](const std::vector<MailCrypto::Key> &keys) { |
141 | if (!keys.empty()) { | 141 | if (!keys.empty()) { |
142 | if (keys.size() > 1) { | 142 | if (keys.size() > 1) { |
143 | SinkWarning() << "Found more than one key, encrypting to all of them."; | 143 | SinkWarning() << "Found more than one key, encrypting to all of them."; |
144 | } | 144 | } |
145 | SinkLog() << "Found key: " << keys.front().primaryFingerprint(); | 145 | SinkLog() << "Found key: " << keys.front(); |
146 | setValue(id, "keyFound", true); | 146 | setValue(id, "keyFound", true); |
147 | setValue(id, "key", QVariant::fromValue(keys)); | 147 | setValue(id, "key", QVariant::fromValue(keys)); |
148 | mMissingKeys.remove(id); | 148 | mMissingKeys.remove(id); |
@@ -227,10 +227,10 @@ void ComposerController::findPersonalKey() | |||
227 | { | 227 | { |
228 | auto identity = getIdentity(); | 228 | auto identity = getIdentity(); |
229 | SinkLog() << "Looking for personal key for: " << identity.address(); | 229 | SinkLog() << "Looking for personal key for: " << identity.address(); |
230 | asyncRun<std::vector<GpgME::Key>>(this, [=] { | 230 | asyncRun<std::vector<MailCrypto::Key>>(this, [=] { |
231 | return MailCrypto::findKeys(QStringList{} << identity.address(), true); | 231 | return MailCrypto::findKeys(QStringList{} << identity.address(), true); |
232 | }, | 232 | }, |
233 | [this](const std::vector<GpgME::Key> &keys) { | 233 | [this](const std::vector<MailCrypto::Key> &keys) { |
234 | if (keys.empty()) { | 234 | if (keys.empty()) { |
235 | SinkWarning() << "Failed to find a personal key."; | 235 | SinkWarning() << "Failed to find a personal key."; |
236 | } else if (keys.size() > 1) { | 236 | } else if (keys.size() > 1) { |
@@ -419,23 +419,23 @@ void ComposerController::recordForAutocompletion(const QByteArray &addrSpec, con | |||
419 | } | 419 | } |
420 | } | 420 | } |
421 | 421 | ||
422 | std::vector<GpgME::Key> ComposerController::getRecipientKeys() | 422 | std::vector<MailCrypto::Key> ComposerController::getRecipientKeys() |
423 | { | 423 | { |
424 | std::vector<GpgME::Key> keys; | 424 | std::vector<MailCrypto::Key> keys; |
425 | { | 425 | { |
426 | const auto list = toController()->getList<std::vector<GpgME::Key>>("key"); | 426 | const auto list = toController()->getList<std::vector<MailCrypto::Key>>("key"); |
427 | for (const auto &l: list) { | 427 | for (const auto &l: list) { |
428 | keys.insert(std::end(keys), std::begin(l), std::end(l)); | 428 | keys.insert(std::end(keys), std::begin(l), std::end(l)); |
429 | } | 429 | } |
430 | } | 430 | } |
431 | { | 431 | { |
432 | const auto list = ccController()->getList<std::vector<GpgME::Key>>("key"); | 432 | const auto list = ccController()->getList<std::vector<MailCrypto::Key>>("key"); |
433 | for (const auto &l: list) { | 433 | for (const auto &l: list) { |
434 | keys.insert(std::end(keys), std::begin(l), std::end(l)); | 434 | keys.insert(std::end(keys), std::begin(l), std::end(l)); |
435 | } | 435 | } |
436 | } | 436 | } |
437 | { | 437 | { |
438 | const auto list = bccController()->getList<std::vector<GpgME::Key>>("key"); | 438 | const auto list = bccController()->getList<std::vector<MailCrypto::Key>>("key"); |
439 | for (const auto &l: list) { | 439 | for (const auto &l: list) { |
440 | keys.insert(std::end(keys), std::begin(l), std::end(l)); | 440 | keys.insert(std::end(keys), std::begin(l), std::end(l)); |
441 | } | 441 | } |
@@ -463,17 +463,17 @@ KMime::Message::Ptr ComposerController::assembleMessage() | |||
463 | }; | 463 | }; |
464 | }); | 464 | }); |
465 | 465 | ||
466 | GpgME::Key attachedKey; | 466 | MailCrypto::Key attachedKey; |
467 | std::vector<GpgME::Key> signingKeys; | 467 | std::vector<MailCrypto::Key> signingKeys; |
468 | if (getSign()) { | 468 | if (getSign()) { |
469 | signingKeys = getPersonalKeys().value<std::vector<GpgME::Key>>(); | 469 | signingKeys = getPersonalKeys().value<std::vector<MailCrypto::Key>>(); |
470 | Q_ASSERT(!signingKeys.empty()); | 470 | Q_ASSERT(!signingKeys.empty()); |
471 | attachedKey = signingKeys[0]; | 471 | attachedKey = signingKeys[0]; |
472 | } | 472 | } |
473 | std::vector<GpgME::Key> encryptionKeys; | 473 | std::vector<MailCrypto::Key> encryptionKeys; |
474 | if (getEncrypt()) { | 474 | if (getEncrypt()) { |
475 | //Encrypt to self so we can read the sent message | 475 | //Encrypt to self so we can read the sent message |
476 | auto personalKeys = getPersonalKeys().value<std::vector<GpgME::Key>>(); | 476 | auto personalKeys = getPersonalKeys().value<std::vector<MailCrypto::Key>>(); |
477 | 477 | ||
478 | attachedKey = personalKeys[0]; | 478 | attachedKey = personalKeys[0]; |
479 | 479 | ||
diff --git a/framework/src/domain/composercontroller.h b/framework/src/domain/composercontroller.h index ac83dfd3..17271dce 100644 --- a/framework/src/domain/composercontroller.h +++ b/framework/src/domain/composercontroller.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <QStandardItemModel> | 26 | #include <QStandardItemModel> |
27 | #include <sink/applicationdomaintype.h> | 27 | #include <sink/applicationdomaintype.h> |
28 | #include <KMime/Message> | 28 | #include <KMime/Message> |
29 | #include <gpgme++/key.h> | 29 | #include <mime/mailcrypto.h> |
30 | 30 | ||
31 | #include "completer.h" | 31 | #include "completer.h" |
32 | #include "selector.h" | 32 | #include "selector.h" |
@@ -39,7 +39,6 @@ inline bool operator !=(const KMime::Types::Mailbox &l, const KMime::Types::Mail | |||
39 | 39 | ||
40 | Q_DECLARE_METATYPE(KMime::Types::Mailbox); | 40 | Q_DECLARE_METATYPE(KMime::Types::Mailbox); |
41 | 41 | ||
42 | Q_DECLARE_METATYPE(GpgME::Key); | ||
43 | 42 | ||
44 | namespace KMime { | 43 | namespace KMime { |
45 | class Message; | 44 | class Message; |
@@ -66,7 +65,7 @@ class ComposerController : public Kube::Controller | |||
66 | KUBE_CONTROLLER_PROPERTY(KMime::Message::Ptr, ExistingMessage, existingMessage) | 65 | KUBE_CONTROLLER_PROPERTY(KMime::Message::Ptr, ExistingMessage, existingMessage) |
67 | KUBE_CONTROLLER_PROPERTY(Sink::ApplicationDomain::Mail, ExistingMail, existingMail) | 66 | KUBE_CONTROLLER_PROPERTY(Sink::ApplicationDomain::Mail, ExistingMail, existingMail) |
68 | 67 | ||
69 | KUBE_CONTROLLER_PROPERTY(/*std::vector<GpgME::Key>*/QVariant, PersonalKeys, personalKeys) | 68 | KUBE_CONTROLLER_PROPERTY(/*std::vector<MailCrypto::Key>*/QVariant, PersonalKeys, personalKeys) |
70 | KUBE_CONTROLLER_PROPERTY(bool, FoundPersonalKeys, foundPersonalKeys) | 69 | KUBE_CONTROLLER_PROPERTY(bool, FoundPersonalKeys, foundPersonalKeys) |
71 | 70 | ||
72 | KUBE_CONTROLLER_LISTCONTROLLER(to) | 71 | KUBE_CONTROLLER_LISTCONTROLLER(to) |
@@ -110,7 +109,7 @@ private: | |||
110 | void setMessage(const QSharedPointer<KMime::Message> &msg); | 109 | void setMessage(const QSharedPointer<KMime::Message> &msg); |
111 | void addAttachmentPart(KMime::Content *partToAttach); | 110 | void addAttachmentPart(KMime::Content *partToAttach); |
112 | KMime::Message::Ptr assembleMessage(); | 111 | KMime::Message::Ptr assembleMessage(); |
113 | std::vector<GpgME::Key> getRecipientKeys(); | 112 | std::vector<MailCrypto::Key> getRecipientKeys(); |
114 | 113 | ||
115 | QScopedPointer<Completer> mRecipientCompleter; | 114 | QScopedPointer<Completer> mRecipientCompleter; |
116 | QScopedPointer<Selector> mIdentitySelector; | 115 | QScopedPointer<Selector> mIdentitySelector; |
diff --git a/framework/src/domain/mime/mailcrypto.cpp b/framework/src/domain/mime/mailcrypto.cpp index da1b82c7..a7f3772a 100644 --- a/framework/src/domain/mime/mailcrypto.cpp +++ b/framework/src/domain/mime/mailcrypto.cpp | |||
@@ -44,6 +44,21 @@ | |||
44 | #include <future> | 44 | #include <future> |
45 | #include <utility> | 45 | #include <utility> |
46 | 46 | ||
47 | using namespace MailCrypto; | ||
48 | |||
49 | QDebug operator<< (QDebug d, const MailCrypto::Key &key) | ||
50 | { | ||
51 | d << key.key.primaryFingerprint(); | ||
52 | return d; | ||
53 | } | ||
54 | |||
55 | static std::vector<GpgME::Key> toGpgME(const std::vector<Key> keys) | ||
56 | { | ||
57 | std::vector<GpgME::Key> list; | ||
58 | std::transform(keys.begin(), keys.end(), std::back_inserter(list), [] (const Key &key) { return key.key; }); | ||
59 | return list; | ||
60 | } | ||
61 | |||
47 | // replace simple LFs by CRLFs for all MIME supporting CryptPlugs | 62 | // replace simple LFs by CRLFs for all MIME supporting CryptPlugs |
48 | // according to RfC 2633, 3.1.1 Canonicalization | 63 | // according to RfC 2633, 3.1.1 Canonicalization |
49 | static QByteArray canonicalizeContent(KMime::Content *content) | 64 | static QByteArray canonicalizeContent(KMime::Content *content) |
@@ -112,7 +127,7 @@ static QByteArray canonicalizeContent(KMime::Content *content) | |||
112 | /** | 127 | /** |
113 | * Get the given `key` in the armor format. | 128 | * Get the given `key` in the armor format. |
114 | */ | 129 | */ |
115 | Expected<GpgME::Error, QByteArray> exportPublicKey(const GpgME::Key &key) | 130 | Expected<Error, QByteArray> exportPublicKey(const Key &key) |
116 | { | 131 | { |
117 | // Not using the Qt API because it apparently blocks (the `result` signal is never | 132 | // Not using the Qt API because it apparently blocks (the `result` signal is never |
118 | // triggered) | 133 | // triggered) |
@@ -122,11 +137,11 @@ Expected<GpgME::Error, QByteArray> exportPublicKey(const GpgME::Key &key) | |||
122 | QGpgME::QByteArrayDataProvider dp; | 137 | QGpgME::QByteArrayDataProvider dp; |
123 | GpgME::Data data(&dp); | 138 | GpgME::Data data(&dp); |
124 | 139 | ||
125 | qDebug() << "Exporting public key:" << key.shortKeyID(); | 140 | qDebug() << "Exporting public key:" << key.key.shortKeyID(); |
126 | auto error = ctx->exportPublicKeys(key.keyID(), data); | 141 | auto error = ctx->exportPublicKeys(key.key.keyID(), data); |
127 | 142 | ||
128 | if (error.code()) { | 143 | if (error.code()) { |
129 | return makeUnexpected(error); | 144 | return makeUnexpected(Error{error}); |
130 | } | 145 | } |
131 | 146 | ||
132 | return dp.data(); | 147 | return dp.data(); |
@@ -143,14 +158,14 @@ Expected<GpgME::Error, QByteArray> exportPublicKey(const GpgME::Key &key) | |||
143 | * | 158 | * |
144 | * Used by the `createSignedEmail` and `createEncryptedEmail` functions. | 159 | * Used by the `createSignedEmail` and `createEncryptedEmail` functions. |
145 | */ | 160 | */ |
146 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 161 | Expected<Error, std::unique_ptr<KMime::Content>> |
147 | appendPublicKey(std::unique_ptr<KMime::Content> msg, const GpgME::Key &key) | 162 | appendPublicKey(std::unique_ptr<KMime::Content> msg, const Key &key) |
148 | { | 163 | { |
149 | const auto publicKeyExportResult = exportPublicKey(key); | 164 | const auto publicKeyExportResult = exportPublicKey(key); |
150 | 165 | ||
151 | if (!publicKeyExportResult) { | 166 | if (!publicKeyExportResult) { |
152 | // "Could not export public key" | 167 | // "Could not export public key" |
153 | return makeUnexpected(publicKeyExportResult.error()); | 168 | return makeUnexpected(Error{publicKeyExportResult.error()}); |
154 | } | 169 | } |
155 | 170 | ||
156 | const auto publicKeyData = publicKeyExportResult.value(); | 171 | const auto publicKeyData = publicKeyExportResult.value(); |
@@ -163,7 +178,7 @@ appendPublicKey(std::unique_ptr<KMime::Content> msg, const GpgME::Key &key) | |||
163 | { | 178 | { |
164 | keyAttachment->contentType()->setMimeType("application/pgp-keys"); | 179 | keyAttachment->contentType()->setMimeType("application/pgp-keys"); |
165 | keyAttachment->contentDisposition()->setDisposition(KMime::Headers::CDattachment); | 180 | keyAttachment->contentDisposition()->setDisposition(KMime::Headers::CDattachment); |
166 | keyAttachment->contentDisposition()->setFilename(QString("0x") + key.shortKeyID() + ".asc"); | 181 | keyAttachment->contentDisposition()->setFilename(QString("0x") + key.key.shortKeyID() + ".asc"); |
167 | keyAttachment->setBody(publicKeyData); | 182 | keyAttachment->setBody(publicKeyData); |
168 | } | 183 | } |
169 | 184 | ||
@@ -177,39 +192,39 @@ appendPublicKey(std::unique_ptr<KMime::Content> msg, const GpgME::Key &key) | |||
177 | return result; | 192 | return result; |
178 | } | 193 | } |
179 | 194 | ||
180 | Expected<GpgME::Error, QByteArray> encrypt(const QByteArray &content, const std::vector<GpgME::Key> &encryptionKeys) | 195 | Expected<Error, QByteArray> encrypt(const QByteArray &content, const std::vector<Key> &encryptionKeys) |
181 | { | 196 | { |
182 | QByteArray resultData; | 197 | QByteArray resultData; |
183 | 198 | ||
184 | const QGpgME::Protocol *const proto = QGpgME::openpgp(); | 199 | const QGpgME::Protocol *const proto = QGpgME::openpgp(); |
185 | std::unique_ptr<QGpgME::EncryptJob> job(proto->encryptJob(/* armor = */ true)); | 200 | std::unique_ptr<QGpgME::EncryptJob> job(proto->encryptJob(/* armor = */ true)); |
186 | const auto result = job->exec(encryptionKeys, content, /* alwaysTrust = */ true, resultData); | 201 | const auto result = job->exec(toGpgME(encryptionKeys), content, /* alwaysTrust = */ true, resultData); |
187 | 202 | ||
188 | if (result.error().code()) { | 203 | if (result.error().code()) { |
189 | qWarning() << "Encryption failed:" << result.error().asString(); | 204 | qWarning() << "Encryption failed:" << result.error().asString(); |
190 | return makeUnexpected(result.error()); | 205 | return makeUnexpected(Error{result.error()}); |
191 | } | 206 | } |
192 | 207 | ||
193 | return resultData; | 208 | return resultData; |
194 | } | 209 | } |
195 | 210 | ||
196 | Expected<GpgME::Error, QByteArray> signAndEncrypt(const QByteArray &content, | 211 | Expected<Error, QByteArray> signAndEncrypt(const QByteArray &content, |
197 | const std::vector<GpgME::Key> &signingKeys, const std::vector<GpgME::Key> &encryptionKeys) | 212 | const std::vector<Key> &signingKeys, const std::vector<Key> &encryptionKeys) |
198 | { | 213 | { |
199 | QByteArray resultData; | 214 | QByteArray resultData; |
200 | 215 | ||
201 | const QGpgME::Protocol *const proto = QGpgME::openpgp(); | 216 | const QGpgME::Protocol *const proto = QGpgME::openpgp(); |
202 | std::unique_ptr<QGpgME::SignEncryptJob> job(proto->signEncryptJob(/* armor = */ true)); | 217 | std::unique_ptr<QGpgME::SignEncryptJob> job(proto->signEncryptJob(/* armor = */ true)); |
203 | const auto result = job->exec(signingKeys, encryptionKeys, content, /* alwaysTrust = */ true, resultData); | 218 | const auto result = job->exec(toGpgME(signingKeys), toGpgME(encryptionKeys), content, /* alwaysTrust = */ true, resultData); |
204 | 219 | ||
205 | if (result.first.error().code()) { | 220 | if (result.first.error().code()) { |
206 | qWarning() << "Signing failed:" << result.first.error().asString(); | 221 | qWarning() << "Signing failed:" << result.first.error().asString(); |
207 | return makeUnexpected(result.first.error()); | 222 | return makeUnexpected(Error{result.first.error()}); |
208 | } | 223 | } |
209 | 224 | ||
210 | if (result.second.error().code()) { | 225 | if (result.second.error().code()) { |
211 | qWarning() << "Encryption failed:" << result.second.error().asString(); | 226 | qWarning() << "Encryption failed:" << result.second.error().asString(); |
212 | return makeUnexpected(result.second.error()); | 227 | return makeUnexpected(Error{result.second.error()}); |
213 | } | 228 | } |
214 | 229 | ||
215 | return resultData; | 230 | return resultData; |
@@ -276,9 +291,9 @@ std::unique_ptr<KMime::Content> createEncryptedPart(QByteArray encryptedData) | |||
276 | * - `application/pgp-keys` (the public key as attachment, which is the first of the | 291 | * - `application/pgp-keys` (the public key as attachment, which is the first of the |
277 | * `signingKeys`) | 292 | * `signingKeys`) |
278 | */ | 293 | */ |
279 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 294 | Expected<Error, std::unique_ptr<KMime::Content>> |
280 | createEncryptedEmail(KMime::Content *content, const std::vector<GpgME::Key> &encryptionKeys, | 295 | createEncryptedEmail(KMime::Content *content, const std::vector<Key> &encryptionKeys, |
281 | const GpgME::Key &attachedKey, const std::vector<GpgME::Key> &signingKeys = {}) | 296 | const Key &attachedKey, const std::vector<Key> &signingKeys = {}) |
282 | { | 297 | { |
283 | auto contentToEncrypt = canonicalizeContent(content); | 298 | auto contentToEncrypt = canonicalizeContent(content); |
284 | 299 | ||
@@ -287,7 +302,7 @@ createEncryptedEmail(KMime::Content *content, const std::vector<GpgME::Key> &enc | |||
287 | signAndEncrypt(contentToEncrypt, signingKeys, encryptionKeys); | 302 | signAndEncrypt(contentToEncrypt, signingKeys, encryptionKeys); |
288 | 303 | ||
289 | if (!encryptionResult) { | 304 | if (!encryptionResult) { |
290 | return makeUnexpected(encryptionResult.error()); | 305 | return makeUnexpected(Error{encryptionResult.error()}); |
291 | } | 306 | } |
292 | 307 | ||
293 | auto encryptedPart = createEncryptedPart(encryptionResult.value()); | 308 | auto encryptedPart = createEncryptedPart(encryptionResult.value()); |
@@ -305,18 +320,18 @@ createEncryptedEmail(KMime::Content *content, const std::vector<GpgME::Key> &enc | |||
305 | * Sign the given content and returns the signing data and the algorithm used | 320 | * Sign the given content and returns the signing data and the algorithm used |
306 | * for integrity check in the "pgp-<algorithm>" format. | 321 | * for integrity check in the "pgp-<algorithm>" format. |
307 | */ | 322 | */ |
308 | Expected<GpgME::Error, std::pair<QByteArray, QString>> | 323 | Expected<Error, std::pair<QByteArray, QString>> |
309 | sign(const QByteArray &content, const std::vector<GpgME::Key> &signingKeys) | 324 | sign(const QByteArray &content, const std::vector<Key> &signingKeys) |
310 | { | 325 | { |
311 | QByteArray resultData; | 326 | QByteArray resultData; |
312 | 327 | ||
313 | const QGpgME::Protocol *const proto = QGpgME::openpgp(); | 328 | const QGpgME::Protocol *const proto = QGpgME::openpgp(); |
314 | std::unique_ptr<QGpgME::SignJob> job(proto->signJob(/* armor = */ true)); | 329 | std::unique_ptr<QGpgME::SignJob> job(proto->signJob(/* armor = */ true)); |
315 | const auto result = job->exec(signingKeys, content, GpgME::Detached, resultData); | 330 | const auto result = job->exec(toGpgME(signingKeys), content, GpgME::Detached, resultData); |
316 | 331 | ||
317 | if (result.error().code()) { | 332 | if (result.error().code()) { |
318 | qWarning() << "Signing failed:" << result.error().asString(); | 333 | qWarning() << "Signing failed:" << result.error().asString(); |
319 | return makeUnexpected(result.error()); | 334 | return makeUnexpected(Error{result.error()}); |
320 | } | 335 | } |
321 | 336 | ||
322 | auto algo = result.createdSignature(0).hashAlgorithmAsString(); | 337 | auto algo = result.createdSignature(0).hashAlgorithmAsString(); |
@@ -380,9 +395,9 @@ std::unique_ptr<KMime::Content> createSignedPart( | |||
380 | * - `application/pgp-keys` (the public key as attachment, which is the first of the | 395 | * - `application/pgp-keys` (the public key as attachment, which is the first of the |
381 | * `signingKeys`) | 396 | * `signingKeys`) |
382 | */ | 397 | */ |
383 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 398 | Expected<Error, std::unique_ptr<KMime::Content>> |
384 | createSignedEmail(std::unique_ptr<KMime::Content> content, | 399 | createSignedEmail(std::unique_ptr<KMime::Content> content, |
385 | const std::vector<GpgME::Key> &signingKeys, const GpgME::Key &attachedKey) | 400 | const std::vector<Key> &signingKeys, const Key &attachedKey) |
386 | { | 401 | { |
387 | Q_ASSERT(!signingKeys.empty()); | 402 | Q_ASSERT(!signingKeys.empty()); |
388 | 403 | ||
@@ -391,7 +406,7 @@ createSignedEmail(std::unique_ptr<KMime::Content> content, | |||
391 | auto signingResult = sign(contentToSign, signingKeys); | 406 | auto signingResult = sign(contentToSign, signingKeys); |
392 | 407 | ||
393 | if (!signingResult) { | 408 | if (!signingResult) { |
394 | return makeUnexpected(signingResult.error()); | 409 | return makeUnexpected(Error{signingResult.error()}); |
395 | } | 410 | } |
396 | 411 | ||
397 | QByteArray signingData; | 412 | QByteArray signingData; |
@@ -409,9 +424,9 @@ createSignedEmail(std::unique_ptr<KMime::Content> content, | |||
409 | return publicKeyAppendResult; | 424 | return publicKeyAppendResult; |
410 | } | 425 | } |
411 | 426 | ||
412 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 427 | Expected<Error, std::unique_ptr<KMime::Content>> |
413 | MailCrypto::processCrypto(std::unique_ptr<KMime::Content> content, const std::vector<GpgME::Key> &signingKeys, | 428 | MailCrypto::processCrypto(std::unique_ptr<KMime::Content> content, const std::vector<Key> &signingKeys, |
414 | const std::vector<GpgME::Key> &encryptionKeys, const GpgME::Key &attachedKey) | 429 | const std::vector<Key> &encryptionKeys, const Key &attachedKey) |
415 | { | 430 | { |
416 | if (!encryptionKeys.empty()) { | 431 | if (!encryptionKeys.empty()) { |
417 | return createEncryptedEmail(content.release(), encryptionKeys, attachedKey, signingKeys); | 432 | return createEncryptedEmail(content.release(), encryptionKeys, attachedKey, signingKeys); |
@@ -423,12 +438,12 @@ MailCrypto::processCrypto(std::unique_ptr<KMime::Content> content, const std::ve | |||
423 | } | 438 | } |
424 | } | 439 | } |
425 | 440 | ||
426 | void MailCrypto::importKeys(const std::vector<GpgME::Key> &keys) | 441 | void MailCrypto::importKeys(const std::vector<Key> &keys) |
427 | { | 442 | { |
428 | const QGpgME::Protocol *const backend = QGpgME::openpgp(); | 443 | const QGpgME::Protocol *const backend = QGpgME::openpgp(); |
429 | Q_ASSERT(backend); | 444 | Q_ASSERT(backend); |
430 | auto *job = backend->importFromKeyserverJob(); | 445 | auto *job = backend->importFromKeyserverJob(); |
431 | job->exec(keys); | 446 | job->exec(toGpgME(keys)); |
432 | } | 447 | } |
433 | 448 | ||
434 | MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey) | 449 | MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey) |
@@ -439,7 +454,7 @@ MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey) | |||
439 | return {result.numConsidered(), result.numImported(), result.numUnchanged()}; | 454 | return {result.numConsidered(), result.numImported(), result.numUnchanged()}; |
440 | } | 455 | } |
441 | 456 | ||
442 | static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnly, int keyListMode, std::vector<GpgME::Key> &keys) | 457 | static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnly, int keyListMode, std::vector<Key> &keys) |
443 | { | 458 | { |
444 | QByteArrayList list; | 459 | QByteArrayList list; |
445 | std::transform(patterns.constBegin(), patterns.constEnd(), std::back_inserter(list), [] (const QString &s) { return s.toUtf8(); }); | 460 | std::transform(patterns.constBegin(), patterns.constEnd(), std::back_inserter(list), [] (const QString &s) { return s.toUtf8(); }); |
@@ -456,7 +471,7 @@ static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnl | |||
456 | 471 | ||
457 | GpgME::Error err; | 472 | GpgME::Error err; |
458 | do { | 473 | do { |
459 | keys.push_back( ctx->nextKey(err)); | 474 | keys.push_back( Key{ctx->nextKey(err)}); |
460 | } while ( !err ); | 475 | } while ( !err ); |
461 | 476 | ||
462 | keys.pop_back(); | 477 | keys.pop_back(); |
@@ -466,21 +481,21 @@ static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnl | |||
466 | return result; | 481 | return result; |
467 | } | 482 | } |
468 | 483 | ||
469 | std::vector<GpgME::Key> MailCrypto::findKeys(const QStringList &filter, bool findPrivate, bool remote) | 484 | std::vector<Key> MailCrypto::findKeys(const QStringList &filter, bool findPrivate, bool remote) |
470 | { | 485 | { |
471 | std::vector<GpgME::Key> keys; | 486 | std::vector<Key> keys; |
472 | GpgME::KeyListResult res = listKeys(filter, findPrivate, remote ? GpgME::Extern : GpgME::Local, keys); | 487 | GpgME::KeyListResult res = listKeys(filter, findPrivate, remote ? GpgME::Extern : GpgME::Local, keys); |
473 | if (res.error()) { | 488 | if (res.error()) { |
474 | qWarning() << "Failed to lookup keys: " << res.error().asString(); | 489 | qWarning() << "Failed to lookup keys: " << res.error().asString(); |
475 | return keys; | 490 | return {}; |
476 | } | 491 | } |
477 | qWarning() << "got keys:" << keys.size(); | 492 | qWarning() << "got keys:" << keys.size(); |
478 | 493 | ||
479 | for (std::vector< GpgME::Key >::iterator i = keys.begin(); i != keys.end(); ++i) { | 494 | for (auto i = keys.begin(); i != keys.end(); ++i) { |
480 | qWarning() << "key isnull:" << i->isNull() << "isexpired:" << i->isExpired(); | 495 | qWarning() << "key isnull:" << i->key.isNull() << "isexpired:" << i->key.isExpired(); |
481 | qWarning() << "key numuserIds:" << i->numUserIDs(); | 496 | qWarning() << "key numuserIds:" << i->key.numUserIDs(); |
482 | for (uint k = 0; k < i->numUserIDs(); ++k) { | 497 | for (uint k = 0; k < i->key.numUserIDs(); ++k) { |
483 | qWarning() << "userIDs:" << i->userID(k).email(); | 498 | qWarning() << "userIDs:" << i->key.userID(k).email(); |
484 | } | 499 | } |
485 | } | 500 | } |
486 | 501 | ||
diff --git a/framework/src/domain/mime/mailcrypto.h b/framework/src/domain/mime/mailcrypto.h index 9e317b43..c9247859 100644 --- a/framework/src/domain/mime/mailcrypto.h +++ b/framework/src/domain/mime/mailcrypto.h | |||
@@ -25,19 +25,28 @@ | |||
25 | #include <gpgme++/key.h> | 25 | #include <gpgme++/key.h> |
26 | 26 | ||
27 | #include <QByteArray> | 27 | #include <QByteArray> |
28 | #include <QVariant> | ||
28 | 29 | ||
29 | #include <functional> | 30 | #include <functional> |
30 | #include <memory> | 31 | #include <memory> |
31 | 32 | ||
32 | namespace MailCrypto { | 33 | namespace MailCrypto { |
33 | 34 | ||
34 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 35 | struct Key { |
35 | processCrypto(std::unique_ptr<KMime::Content> content, const std::vector<GpgME::Key> &signingKeys, | 36 | GpgME::Key key; |
36 | const std::vector<GpgME::Key> &encryptionKeys, const GpgME::Key &attachedKey); | 37 | }; |
38 | |||
39 | struct Error { | ||
40 | GpgME::Error key; | ||
41 | }; | ||
37 | 42 | ||
38 | std::vector<GpgME::Key> findKeys(const QStringList &filter, bool findPrivate = false, bool remote = false); | 43 | Expected<Error, std::unique_ptr<KMime::Content>> |
44 | processCrypto(std::unique_ptr<KMime::Content> content, const std::vector<Key> &signingKeys, | ||
45 | const std::vector<Key> &encryptionKeys, const Key &attachedKey); | ||
39 | 46 | ||
40 | void importKeys(const std::vector<GpgME::Key> &keys); | 47 | std::vector<Key> findKeys(const QStringList &filter, bool findPrivate = false, bool remote = false); |
48 | |||
49 | void importKeys(const std::vector<Key> &keys); | ||
41 | 50 | ||
42 | struct ImportResult { | 51 | struct ImportResult { |
43 | int considered; | 52 | int considered; |
@@ -48,3 +57,7 @@ struct ImportResult { | |||
48 | ImportResult importKey(const QByteArray &key); | 57 | ImportResult importKey(const QByteArray &key); |
49 | 58 | ||
50 | }; // namespace MailCrypto | 59 | }; // namespace MailCrypto |
60 | |||
61 | Q_DECLARE_METATYPE(MailCrypto::Key); | ||
62 | |||
63 | QDebug operator<< (QDebug d, const MailCrypto::Key &); | ||
diff --git a/framework/src/domain/mime/mailtemplates.cpp b/framework/src/domain/mime/mailtemplates.cpp index a614da1a..ac2b2b72 100644 --- a/framework/src/domain/mime/mailtemplates.cpp +++ b/framework/src/domain/mime/mailtemplates.cpp | |||
@@ -1027,8 +1027,8 @@ static KMime::Types::Mailbox::List stringListToMailboxes(const QStringList &list | |||
1027 | KMime::Message::Ptr MailTemplates::createMessage(KMime::Message::Ptr existingMessage, | 1027 | KMime::Message::Ptr MailTemplates::createMessage(KMime::Message::Ptr existingMessage, |
1028 | const QStringList &to, const QStringList &cc, const QStringList &bcc, | 1028 | const QStringList &to, const QStringList &cc, const QStringList &bcc, |
1029 | const KMime::Types::Mailbox &from, const QString &subject, const QString &body, bool htmlBody, | 1029 | const KMime::Types::Mailbox &from, const QString &subject, const QString &body, bool htmlBody, |
1030 | const QList<Attachment> &attachments, const std::vector<GpgME::Key> &signingKeys, | 1030 | const QList<Attachment> &attachments, const std::vector<MailCrypto::Key> &signingKeys, |
1031 | const std::vector<GpgME::Key> &encryptionKeys, const GpgME::Key &attachedKey) | 1031 | const std::vector<MailCrypto::Key> &encryptionKeys, const MailCrypto::Key &attachedKey) |
1032 | { | 1032 | { |
1033 | auto mail = existingMessage; | 1033 | auto mail = existingMessage; |
1034 | if (!mail) { | 1034 | if (!mail) { |
diff --git a/framework/src/domain/mime/mailtemplates.h b/framework/src/domain/mime/mailtemplates.h index 154b76a2..a894d120 100644 --- a/framework/src/domain/mime/mailtemplates.h +++ b/framework/src/domain/mime/mailtemplates.h | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <QByteArray> | 22 | #include <QByteArray> |
23 | #include <KMime/Message> | 23 | #include <KMime/Message> |
24 | #include <functional> | 24 | #include <functional> |
25 | #include <gpgme++/key.h> | 25 | #include <mailcrypto.h> |
26 | 26 | ||
27 | struct Attachment { | 27 | struct Attachment { |
28 | QString name; | 28 | QString name; |
@@ -38,5 +38,5 @@ namespace MailTemplates | |||
38 | void forward(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback); | 38 | void forward(const KMime::Message::Ptr &origMsg, const std::function<void(const KMime::Message::Ptr &result)> &callback); |
39 | QString plaintextContent(const KMime::Message::Ptr &origMsg); | 39 | QString plaintextContent(const KMime::Message::Ptr &origMsg); |
40 | QString body(const KMime::Message::Ptr &msg, bool &isHtml); | 40 | QString body(const KMime::Message::Ptr &msg, bool &isHtml); |
41 | KMime::Message::Ptr createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, bool htmlBody, const QList<Attachment> &attachments, const std::vector<GpgME::Key> &signingKeys = {}, const std::vector<GpgME::Key> &encryptionKeys = {}, const GpgME::Key &attachedKey = {}); | 41 | KMime::Message::Ptr createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, bool htmlBody, const QList<Attachment> &attachments, const std::vector<MailCrypto::Key> &signingKeys = {}, const std::vector<MailCrypto::Key> &encryptionKeys = {}, const MailCrypto::Key &attachedKey = {}); |
42 | }; | 42 | }; |
diff --git a/framework/src/domain/mime/tests/mailtemplatetest.cpp b/framework/src/domain/mime/tests/mailtemplatetest.cpp index d07b704d..75debd75 100644 --- a/framework/src/domain/mime/tests/mailtemplatetest.cpp +++ b/framework/src/domain/mime/tests/mailtemplatetest.cpp | |||
@@ -6,10 +6,6 @@ | |||
6 | #include <QDir> | 6 | #include <QDir> |
7 | #include <QtWebEngine> | 7 | #include <QtWebEngine> |
8 | 8 | ||
9 | #include <QGpgME/KeyListJob> | ||
10 | #include <QGpgME/Protocol> | ||
11 | #include <gpgme++/key.h> | ||
12 | #include <gpgme++/keylistresult.h> | ||
13 | 9 | ||
14 | #include "mailtemplates.h" | 10 | #include "mailtemplates.h" |
15 | #include "mailcrypto.h" | 11 | #include "mailcrypto.h" |
@@ -24,45 +20,6 @@ static KMime::Content *getSubpart(KMime::Content *msg, const QByteArray &mimeTyp | |||
24 | return nullptr; | 20 | return nullptr; |
25 | } | 21 | } |
26 | 22 | ||
27 | static std::vector< GpgME::Key, std::allocator< GpgME::Key > > getKeys(bool smime = false) | ||
28 | { | ||
29 | QGpgME::KeyListJob *job = nullptr; | ||
30 | |||
31 | if (smime) { | ||
32 | const QGpgME::Protocol *const backend = QGpgME::smime(); | ||
33 | Q_ASSERT(backend); | ||
34 | job = backend->keyListJob(/* remote = */ false); | ||
35 | } else { | ||
36 | const QGpgME::Protocol *const backend = QGpgME::openpgp(); | ||
37 | Q_ASSERT(backend); | ||
38 | job = backend->keyListJob(/* remote = */ false); | ||
39 | } | ||
40 | Q_ASSERT(job); | ||
41 | |||
42 | std::vector< GpgME::Key > keys; | ||
43 | GpgME::KeyListResult res = job->exec(QStringList(), /* secretOnly = */ true, keys); | ||
44 | |||
45 | if (!smime) { | ||
46 | Q_ASSERT(keys.size() == 3); | ||
47 | } | ||
48 | |||
49 | Q_ASSERT(!res.error()); | ||
50 | |||
51 | /* | ||
52 | qDebug() << "got private keys:" << keys.size(); | ||
53 | |||
54 | for (std::vector< GpgME::Key >::iterator i = keys.begin(); i != keys.end(); ++i) { | ||
55 | qDebug() << "key isnull:" << i->isNull() << "isexpired:" << i->isExpired(); | ||
56 | qDebug() << "key numuserIds:" << i->numUserIDs(); | ||
57 | for (uint k = 0; k < i->numUserIDs(); ++k) { | ||
58 | qDebug() << "userIDs:" << i->userID(k).email(); | ||
59 | } | ||
60 | } | ||
61 | */ | ||
62 | |||
63 | return keys; | ||
64 | } | ||
65 | |||
66 | static QByteArray readMailFromFile(const QString &mailFile) | 23 | static QByteArray readMailFromFile(const QString &mailFile) |
67 | { | 24 | { |
68 | Q_ASSERT(!QString::fromLatin1(MAIL_DATA_DIR).isEmpty()); | 25 | Q_ASSERT(!QString::fromLatin1(MAIL_DATA_DIR).isEmpty()); |
@@ -399,8 +356,7 @@ private slots: | |||
399 | QString body = "body"; | 356 | QString body = "body"; |
400 | QList<Attachment> attachments; | 357 | QList<Attachment> attachments; |
401 | 358 | ||
402 | std::vector<GpgME::Key> keys = getKeys(); | 359 | auto keys = MailCrypto::findKeys({}, true, false); |
403 | |||
404 | auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, false, attachments, keys, {}, keys[0]); | 360 | auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, false, attachments, keys, {}, keys[0]); |
405 | 361 | ||
406 | QVERIFY(result); | 362 | QVERIFY(result); |
@@ -442,9 +398,7 @@ private slots: | |||
442 | QString body = "body"; | 398 | QString body = "body"; |
443 | QList<Attachment> attachments = {{"name", "filename", "mimetype", true, "inlineAttachment"}, {"name", "filename", "mimetype", false, "nonInlineAttachment"}}; | 399 | QList<Attachment> attachments = {{"name", "filename", "mimetype", true, "inlineAttachment"}, {"name", "filename", "mimetype", false, "nonInlineAttachment"}}; |
444 | 400 | ||
445 | std::vector<GpgME::Key> keys = getKeys(); | 401 | auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, false, attachments, MailCrypto::findKeys({}, true, false)); |
446 | |||
447 | auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, false, attachments, keys); | ||
448 | 402 | ||
449 | QVERIFY(result); | 403 | QVERIFY(result); |
450 | QCOMPARE(result->subject()->asUnicodeString(), subject); | 404 | QCOMPARE(result->subject()->asUnicodeString(), subject); |