diff options
-rw-r--r-- | framework/domain/mimetreeparser/interface.cpp | 262 | ||||
-rw-r--r-- | framework/domain/mimetreeparser/interface.h | 22 | ||||
-rw-r--r-- | framework/domain/mimetreeparser/interface_p.h | 2 | ||||
-rw-r--r-- | framework/domain/mimetreeparser/tests/interfacetest.cpp | 44 |
4 files changed, 270 insertions, 60 deletions
diff --git a/framework/domain/mimetreeparser/interface.cpp b/framework/domain/mimetreeparser/interface.cpp index ceb8caf3..0bcbfec4 100644 --- a/framework/domain/mimetreeparser/interface.cpp +++ b/framework/domain/mimetreeparser/interface.cpp | |||
@@ -23,6 +23,10 @@ | |||
23 | #include "stringhtmlwriter.h" | 23 | #include "stringhtmlwriter.h" |
24 | #include "objecttreesource.h" | 24 | #include "objecttreesource.h" |
25 | 25 | ||
26 | #include <Libkleo/KeyListJob> | ||
27 | #include <gpgme++/key.h> | ||
28 | #include <gpgme++/keylistresult.h> | ||
29 | |||
26 | #include <KMime/Content> | 30 | #include <KMime/Content> |
27 | #include <MimeTreeParser/ObjectTreeParser> | 31 | #include <MimeTreeParser/ObjectTreeParser> |
28 | #include <MimeTreeParser/MessagePart> | 32 | #include <MimeTreeParser/MessagePart> |
@@ -162,6 +166,131 @@ QByteArray MailMime::decodedContent() const | |||
162 | return d->mNode->decodedContent(); | 166 | return d->mNode->decodedContent(); |
163 | } | 167 | } |
164 | 168 | ||
169 | class KeyPrivate | ||
170 | { | ||
171 | public: | ||
172 | Key *q; | ||
173 | GpgME::Key mKey; | ||
174 | }; | ||
175 | |||
176 | Key::Key() | ||
177 | :d(std::unique_ptr<KeyPrivate>(new KeyPrivate)) | ||
178 | { | ||
179 | d->q = this; | ||
180 | } | ||
181 | |||
182 | |||
183 | Key::Key(KeyPrivate *d_ptr) | ||
184 | :d(std::unique_ptr<KeyPrivate>(d_ptr)) | ||
185 | { | ||
186 | d->q = this; | ||
187 | } | ||
188 | |||
189 | Key::~Key() | ||
190 | { | ||
191 | |||
192 | } | ||
193 | |||
194 | QString Key::keyid() const | ||
195 | { | ||
196 | return d->mKey.keyID(); | ||
197 | } | ||
198 | |||
199 | QString Key::name() const | ||
200 | { | ||
201 | //FIXME: is this the correct way to get the primary UID? | ||
202 | return d->mKey.userID(0).name(); | ||
203 | } | ||
204 | |||
205 | QString Key::email() const | ||
206 | { | ||
207 | return d->mKey.userID(0).email(); | ||
208 | } | ||
209 | |||
210 | QString Key::comment() const | ||
211 | { | ||
212 | return d->mKey.userID(0).comment(); | ||
213 | } | ||
214 | |||
215 | class SignaturePrivate | ||
216 | { | ||
217 | public: | ||
218 | Signature *q; | ||
219 | GpgME::Signature mSignature; | ||
220 | Key::Ptr mKey; | ||
221 | }; | ||
222 | |||
223 | Signature::Signature() | ||
224 | :d(std::unique_ptr<SignaturePrivate>(new SignaturePrivate)) | ||
225 | { | ||
226 | d->q = this; | ||
227 | } | ||
228 | |||
229 | |||
230 | Signature::Signature(SignaturePrivate *d_ptr) | ||
231 | :d(std::unique_ptr<SignaturePrivate>(d_ptr)) | ||
232 | { | ||
233 | d->q = this; | ||
234 | |||
235 | } | ||
236 | |||
237 | Signature::~Signature() | ||
238 | { | ||
239 | |||
240 | } | ||
241 | |||
242 | QDateTime Signature::creationDateTime() const | ||
243 | { | ||
244 | QDateTime dt; | ||
245 | dt.setTime_t(d->mSignature.creationTime()); | ||
246 | return dt; | ||
247 | } | ||
248 | |||
249 | QDateTime Signature::expirationDateTime() const | ||
250 | { | ||
251 | QDateTime dt; | ||
252 | dt.setTime_t(d->mSignature.expirationTime()); | ||
253 | return dt; | ||
254 | } | ||
255 | |||
256 | bool Signature::neverExpires() const | ||
257 | { | ||
258 | return d->mSignature.neverExpires(); | ||
259 | } | ||
260 | |||
261 | Key::Ptr Signature::key() const | ||
262 | { | ||
263 | return d->mKey; | ||
264 | } | ||
265 | |||
266 | class EncryptionPrivate | ||
267 | { | ||
268 | public: | ||
269 | Encryption *q; | ||
270 | std::vector<Key::Ptr> mRecipients; | ||
271 | }; | ||
272 | |||
273 | Encryption::Encryption(EncryptionPrivate *d_ptr) | ||
274 | :d(std::unique_ptr<EncryptionPrivate>(d_ptr)) | ||
275 | { | ||
276 | d->q = this; | ||
277 | } | ||
278 | |||
279 | Encryption::Encryption() | ||
280 | :d(std::unique_ptr<EncryptionPrivate>(new EncryptionPrivate)) | ||
281 | { | ||
282 | d->q = this; | ||
283 | } | ||
284 | |||
285 | Encryption::~Encryption() | ||
286 | { | ||
287 | |||
288 | } | ||
289 | |||
290 | std::vector<Key::Ptr> Encryption::recipients() const | ||
291 | { | ||
292 | return d->mRecipients; | ||
293 | } | ||
165 | 294 | ||
166 | class PartPrivate | 295 | class PartPrivate |
167 | { | 296 | { |
@@ -179,7 +308,9 @@ public: | |||
179 | void createMailMime(const MimeTreeParser::AlternativeMessagePart::Ptr &part); | 308 | void createMailMime(const MimeTreeParser::AlternativeMessagePart::Ptr &part); |
180 | void createMailMime(const MimeTreeParser::HtmlMessagePart::Ptr &part); | 309 | void createMailMime(const MimeTreeParser::HtmlMessagePart::Ptr &part); |
181 | 310 | ||
311 | static Encryption::Ptr createEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part); | ||
182 | void appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr &part); | 312 | void appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr &part); |
313 | static QVector<Signature::Ptr> createSignature(const MimeTreeParser::SignedMessagePart::Ptr& part); | ||
183 | void appendSignature(const MimeTreeParser::SignedMessagePart::Ptr &part); | 314 | void appendSignature(const MimeTreeParser::SignedMessagePart::Ptr &part); |
184 | 315 | ||
185 | void setSignatures(const QVector<Signature::Ptr> &sigs); | 316 | void setSignatures(const QVector<Signature::Ptr> &sigs); |
@@ -233,9 +364,43 @@ void PartPrivate::appendSubPart(Part::Ptr subpart) | |||
233 | mSubParts.append(subpart); | 364 | mSubParts.append(subpart); |
234 | } | 365 | } |
235 | 366 | ||
367 | Encryption::Ptr PartPrivate::createEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) | ||
368 | { | ||
369 | Kleo::KeyListJob *job = part->mCryptoProto->keyListJob(false); // local, no sigs | ||
370 | if (!job) { | ||
371 | qWarning() << "The Crypto backend does not support listing keys. "; | ||
372 | return Encryption::Ptr(); | ||
373 | } | ||
374 | |||
375 | auto encpriv = new EncryptionPrivate(); | ||
376 | foreach(const auto &recipient, part->mDecryptRecipients) { | ||
377 | std::vector<GpgME::Key> found_keys; | ||
378 | const auto &keyid = recipient.keyID(); | ||
379 | GpgME::KeyListResult res = job->exec(QStringList(QLatin1String(keyid)), false, found_keys); | ||
380 | if (res.error()) { | ||
381 | qWarning() << "Error while searching key for Fingerprint: " << keyid; | ||
382 | continue; | ||
383 | } | ||
384 | if (found_keys.size() > 1) { | ||
385 | // Should not Happen | ||
386 | qWarning() << "Oops: Found more then one Key for Fingerprint: " << keyid; | ||
387 | } | ||
388 | if (found_keys.size() != 1) { | ||
389 | // Should not Happen at this point | ||
390 | qWarning() << "Oops: Found no Key for Fingerprint: " << keyid; | ||
391 | } else { | ||
392 | auto key = found_keys[0]; | ||
393 | auto keypriv = new KeyPrivate; | ||
394 | keypriv->mKey = key; | ||
395 | encpriv->mRecipients.push_back(Key::Ptr(new Key(keypriv))); | ||
396 | } | ||
397 | } | ||
398 | return Encryption::Ptr(new Encryption(encpriv)); | ||
399 | } | ||
400 | |||
236 | void PartPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) | 401 | void PartPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) |
237 | { | 402 | { |
238 | mEncryptions.append(Encryption::Ptr(new Encryption)); | 403 | mEncryptions.append(createEncryption(part)); |
239 | } | 404 | } |
240 | 405 | ||
241 | void PartPrivate::setEncryptions(const QVector< Encryption::Ptr >& encs) | 406 | void PartPrivate::setEncryptions(const QVector< Encryption::Ptr >& encs) |
@@ -243,9 +408,50 @@ void PartPrivate::setEncryptions(const QVector< Encryption::Ptr >& encs) | |||
243 | mEncryptions = encs; | 408 | mEncryptions = encs; |
244 | } | 409 | } |
245 | 410 | ||
411 | QVector<Signature::Ptr> PartPrivate::createSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) | ||
412 | { | ||
413 | QVector<Signature::Ptr> sigs; | ||
414 | Kleo::KeyListJob *job = part->mCryptoProto->keyListJob(false); // local, no sigs | ||
415 | if (!job) { | ||
416 | qWarning() << "The Crypto backend does not support listing keys. "; | ||
417 | return sigs; | ||
418 | } | ||
419 | |||
420 | foreach(const auto &sig, part->mSignatures) { | ||
421 | auto sigpriv = new SignaturePrivate(); | ||
422 | sigpriv->mSignature = sig; | ||
423 | auto signature = std::make_shared<Signature>(sigpriv); | ||
424 | sigs.append(signature); | ||
425 | |||
426 | std::vector<GpgME::Key> found_keys; | ||
427 | const auto &keyid = sig.fingerprint(); | ||
428 | GpgME::KeyListResult res = job->exec(QStringList(QLatin1String(keyid)), false, found_keys); | ||
429 | if (res.error()) { | ||
430 | qWarning() << "Error while searching key for Fingerprint: " << keyid; | ||
431 | continue; | ||
432 | } | ||
433 | if (found_keys.size() > 1) { | ||
434 | // Should not Happen | ||
435 | qWarning() << "Oops: Found more then one Key for Fingerprint: " << keyid; | ||
436 | continue; | ||
437 | } | ||
438 | if (found_keys.size() != 1) { | ||
439 | // Should not Happen at this point | ||
440 | qWarning() << "Oops: Found no Key for Fingerprint: " << keyid; | ||
441 | continue; | ||
442 | } else { | ||
443 | auto key = found_keys[0]; | ||
444 | auto keypriv = new KeyPrivate; | ||
445 | keypriv->mKey = key; | ||
446 | sigpriv->mKey = Key::Ptr(new Key(keypriv)); | ||
447 | } | ||
448 | } | ||
449 | return sigs; | ||
450 | } | ||
451 | |||
246 | void PartPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) | 452 | void PartPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) |
247 | { | 453 | { |
248 | mSignatures.append(Signature::Ptr(new Signature)); | 454 | mSignatures.append(createSignature(part)); |
249 | } | 455 | } |
250 | 456 | ||
251 | 457 | ||
@@ -361,12 +567,12 @@ public: | |||
361 | 567 | ||
362 | void ContentPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& enc) | 568 | void ContentPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& enc) |
363 | { | 569 | { |
364 | mEncryptions.append(Encryption::Ptr(new Encryption)); | 570 | mEncryptions.append(PartPrivate::createEncryption(enc)); |
365 | } | 571 | } |
366 | 572 | ||
367 | void ContentPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& sig) | 573 | void ContentPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& sig) |
368 | { | 574 | { |
369 | mSignatures.append(Signature::Ptr(new Signature)); | 575 | mSignatures.append(PartPrivate::createSignature(sig)); |
370 | } | 576 | } |
371 | 577 | ||
372 | 578 | ||
@@ -638,54 +844,6 @@ PartPrivate* SinglePart::reachParentD() const | |||
638 | return Part::d.get(); | 844 | return Part::d.get(); |
639 | } | 845 | } |
640 | 846 | ||
641 | class SignaturePrivate | ||
642 | { | ||
643 | public: | ||
644 | Signature *q; | ||
645 | }; | ||
646 | |||
647 | Signature::Signature() | ||
648 | :d(std::unique_ptr<SignaturePrivate>(new SignaturePrivate)) | ||
649 | { | ||
650 | d->q = this; | ||
651 | } | ||
652 | |||
653 | |||
654 | Signature::Signature(SignaturePrivate *d_ptr) | ||
655 | :d(std::unique_ptr<SignaturePrivate>(d_ptr)) | ||
656 | { | ||
657 | d->q = this; | ||
658 | } | ||
659 | |||
660 | Signature::~Signature() | ||
661 | { | ||
662 | |||
663 | } | ||
664 | |||
665 | |||
666 | class EncryptionPrivate | ||
667 | { | ||
668 | public: | ||
669 | Encryption *q; | ||
670 | }; | ||
671 | |||
672 | Encryption::Encryption(EncryptionPrivate *d_ptr) | ||
673 | :d(std::unique_ptr<EncryptionPrivate>(d_ptr)) | ||
674 | { | ||
675 | d->q = this; | ||
676 | } | ||
677 | |||
678 | Encryption::Encryption() | ||
679 | :d(std::unique_ptr<EncryptionPrivate>(new EncryptionPrivate)) | ||
680 | { | ||
681 | d->q = this; | ||
682 | } | ||
683 | |||
684 | Encryption::~Encryption() | ||
685 | { | ||
686 | |||
687 | } | ||
688 | |||
689 | ParserPrivate::ParserPrivate(Parser* parser) | 847 | ParserPrivate::ParserPrivate(Parser* parser) |
690 | : q(parser) | 848 | : q(parser) |
691 | , mNodeHelper(std::make_shared<MimeTreeParser::NodeHelper>()) | 849 | , mNodeHelper(std::make_shared<MimeTreeParser::NodeHelper>()) |
diff --git a/framework/domain/mimetreeparser/interface.h b/framework/domain/mimetreeparser/interface.h index f88271af..3ff29d5d 100644 --- a/framework/domain/mimetreeparser/interface.h +++ b/framework/domain/mimetreeparser/interface.h | |||
@@ -53,6 +53,7 @@ class CertContentPrivate; | |||
53 | class EncryptionError; | 53 | class EncryptionError; |
54 | 54 | ||
55 | class Key; | 55 | class Key; |
56 | class KeyPrivate; | ||
56 | class Signature; | 57 | class Signature; |
57 | class SignaturePrivate; | 58 | class SignaturePrivate; |
58 | class Encryption; | 59 | class Encryption; |
@@ -262,10 +263,9 @@ public: | |||
262 | 263 | ||
263 | EncryptionError error() const; | 264 | EncryptionError error() const; |
264 | private: | 265 | private: |
265 | std::unique_ptr<EncryptionPartPrivate> d; | 266 | std::unique_ptr<EncryptionPartPrivate> d; |
266 | }; | 267 | }; |
267 | 268 | ||
268 | |||
269 | /* | 269 | /* |
270 | * we want to request complete headers like: | 270 | * we want to request complete headers like: |
271 | * from/to... | 271 | * from/to... |
@@ -279,7 +279,7 @@ public: | |||
279 | 279 | ||
280 | //template <class T> QByteArray header<T>(); | 280 | //template <class T> QByteArray header<T>(); |
281 | private: | 281 | private: |
282 | std::unique_ptr<EncapsulatedPartPrivate> d; | 282 | std::unique_ptr<EncapsulatedPartPrivate> d; |
283 | }; | 283 | }; |
284 | 284 | ||
285 | class EncryptionError | 285 | class EncryptionError |
@@ -291,6 +291,12 @@ public: | |||
291 | 291 | ||
292 | class Key | 292 | class Key |
293 | { | 293 | { |
294 | public: | ||
295 | typedef std::shared_ptr<Key> Ptr; | ||
296 | Key(); | ||
297 | Key(KeyPrivate *); | ||
298 | ~Key(); | ||
299 | |||
294 | QString keyid() const; | 300 | QString keyid() const; |
295 | QString name() const; | 301 | QString name() const; |
296 | QString email() const; | 302 | QString email() const; |
@@ -305,8 +311,10 @@ class Key | |||
305 | bool isInvalid() const; | 311 | bool isInvalid() const; |
306 | bool isExpired() const; | 312 | bool isExpired() const; |
307 | 313 | ||
308 | std::vector<Key> subkeys(); | 314 | std::vector<Key::Ptr> subkeys(); |
309 | Key parentkey() const; | 315 | Key parentkey() const; |
316 | private: | ||
317 | std::unique_ptr<KeyPrivate> d; | ||
310 | }; | 318 | }; |
311 | 319 | ||
312 | class Signature | 320 | class Signature |
@@ -317,9 +325,9 @@ public: | |||
317 | Signature(SignaturePrivate *); | 325 | Signature(SignaturePrivate *); |
318 | ~Signature(); | 326 | ~Signature(); |
319 | 327 | ||
320 | Key key() const; | 328 | Key::Ptr key() const; |
321 | QDateTime creationDateTime() const; | 329 | QDateTime creationDateTime() const; |
322 | QDateTime expirationTime() const; | 330 | QDateTime expirationDateTime() const; |
323 | bool neverExpires() const; | 331 | bool neverExpires() const; |
324 | 332 | ||
325 | //template <> StatusObject<SignatureVerificationResult> verify() const; | 333 | //template <> StatusObject<SignatureVerificationResult> verify() const; |
@@ -339,7 +347,7 @@ public: | |||
339 | Encryption(); | 347 | Encryption(); |
340 | Encryption(EncryptionPrivate *); | 348 | Encryption(EncryptionPrivate *); |
341 | ~Encryption(); | 349 | ~Encryption(); |
342 | std::vector<Key> recipients() const; | 350 | std::vector<Key::Ptr> recipients() const; |
343 | private: | 351 | private: |
344 | std::unique_ptr<EncryptionPrivate> d; | 352 | std::unique_ptr<EncryptionPrivate> d; |
345 | }; | 353 | }; |
diff --git a/framework/domain/mimetreeparser/interface_p.h b/framework/domain/mimetreeparser/interface_p.h index 55d1a5cc..8fab221a 100644 --- a/framework/domain/mimetreeparser/interface_p.h +++ b/framework/domain/mimetreeparser/interface_p.h | |||
@@ -53,4 +53,4 @@ public: | |||
53 | std::shared_ptr<MimeTreeParser::NodeHelper> mNodeHelper; | 53 | std::shared_ptr<MimeTreeParser::NodeHelper> mNodeHelper; |
54 | QString mHtml; | 54 | QString mHtml; |
55 | QMap<QByteArray, QUrl> mEmbeddedPartMap; | 55 | QMap<QByteArray, QUrl> mEmbeddedPartMap; |
56 | }; \ No newline at end of file | 56 | }; |
diff --git a/framework/domain/mimetreeparser/tests/interfacetest.cpp b/framework/domain/mimetreeparser/tests/interfacetest.cpp index ab6316ac..3ae32a4a 100644 --- a/framework/domain/mimetreeparser/tests/interfacetest.cpp +++ b/framework/domain/mimetreeparser/tests/interfacetest.cpp | |||
@@ -224,6 +224,50 @@ private slots: | |||
224 | QCOMPARE(contentAttachmentList.size(), 0); | 224 | QCOMPARE(contentAttachmentList.size(), 0); |
225 | } | 225 | } |
226 | 226 | ||
227 | void testEncryptionBlock() | ||
228 | { | ||
229 | Parser parser(readMailFromFile("openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox")); | ||
230 | auto contentPartList = parser.collectContentParts(); | ||
231 | auto contentPart = contentPartList[0]; | ||
232 | auto contentList = contentPart->content("plaintext"); | ||
233 | QCOMPARE(contentList.size(), 1); | ||
234 | QCOMPARE(contentList[0]->encryptions().size(), 1); | ||
235 | auto enc = contentList[0]->encryptions()[0]; | ||
236 | QCOMPARE((int) enc->recipients().size(), 2); | ||
237 | |||
238 | auto r = enc->recipients()[0]; | ||
239 | QCOMPARE(r->keyid(),QStringLiteral("14B79E26050467AA")); | ||
240 | QCOMPARE(r->name(),QStringLiteral("kdetest")); | ||
241 | QCOMPARE(r->email(),QStringLiteral("you@you.com")); | ||
242 | QCOMPARE(r->comment(),QStringLiteral("")); | ||
243 | |||
244 | r = enc->recipients()[1]; | ||
245 | QCOMPARE(r->keyid(),QStringLiteral("8D9860C58F246DE6")); | ||
246 | QCOMPARE(r->name(),QStringLiteral("unittest key")); | ||
247 | QCOMPARE(r->email(),QStringLiteral("test@kolab.org")); | ||
248 | QCOMPARE(r->comment(),QStringLiteral("no password")); | ||
249 | } | ||
250 | |||
251 | void testSignatureBlock() | ||
252 | { | ||
253 | Parser parser(readMailFromFile("openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox")); | ||
254 | auto contentPartList = parser.collectContentParts(); | ||
255 | auto contentPart = contentPartList[0]; | ||
256 | auto contentList = contentPart->content("plaintext"); | ||
257 | QCOMPARE(contentList.size(), 1); | ||
258 | QCOMPARE(contentList[0]->signatures().size(), 1); | ||
259 | auto sig = contentList[0]->signatures()[0]; | ||
260 | QCOMPARE(sig->creationDateTime(), QDateTime(QDate(2015,05,01),QTime(15,12,47))); | ||
261 | QCOMPARE(sig->expirationDateTime(), QDateTime()); | ||
262 | QCOMPARE(sig->neverExpires(), true); | ||
263 | |||
264 | auto key = sig->key(); | ||
265 | QCOMPARE(key->keyid(),QStringLiteral("8D9860C58F246DE6")); | ||
266 | QCOMPARE(key->name(),QStringLiteral("unittest key")); | ||
267 | QCOMPARE(key->email(),QStringLiteral("test@kolab.org")); | ||
268 | QCOMPARE(key->comment(),QStringLiteral("no password")); | ||
269 | } | ||
270 | |||
227 | void testRelatedAlternative() | 271 | void testRelatedAlternative() |
228 | { | 272 | { |
229 | Parser parser(readMailFromFile("cid-links.mbox")); | 273 | Parser parser(readMailFromFile("cid-links.mbox")); |