summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--framework/domain/mimetreeparser/interface.cpp262
-rw-r--r--framework/domain/mimetreeparser/interface.h22
-rw-r--r--framework/domain/mimetreeparser/interface_p.h2
-rw-r--r--framework/domain/mimetreeparser/tests/interfacetest.cpp44
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
169class KeyPrivate
170{
171public:
172 Key *q;
173 GpgME::Key mKey;
174};
175
176Key::Key()
177 :d(std::unique_ptr<KeyPrivate>(new KeyPrivate))
178{
179 d->q = this;
180}
181
182
183Key::Key(KeyPrivate *d_ptr)
184 :d(std::unique_ptr<KeyPrivate>(d_ptr))
185{
186 d->q = this;
187}
188
189Key::~Key()
190{
191
192}
193
194QString Key::keyid() const
195{
196 return d->mKey.keyID();
197}
198
199QString 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
205QString Key::email() const
206{
207 return d->mKey.userID(0).email();
208}
209
210QString Key::comment() const
211{
212 return d->mKey.userID(0).comment();
213}
214
215class SignaturePrivate
216{
217public:
218 Signature *q;
219 GpgME::Signature mSignature;
220 Key::Ptr mKey;
221};
222
223Signature::Signature()
224 :d(std::unique_ptr<SignaturePrivate>(new SignaturePrivate))
225{
226 d->q = this;
227}
228
229
230Signature::Signature(SignaturePrivate *d_ptr)
231 :d(std::unique_ptr<SignaturePrivate>(d_ptr))
232{
233 d->q = this;
234
235}
236
237Signature::~Signature()
238{
239
240}
241
242QDateTime Signature::creationDateTime() const
243{
244 QDateTime dt;
245 dt.setTime_t(d->mSignature.creationTime());
246 return dt;
247}
248
249QDateTime Signature::expirationDateTime() const
250{
251 QDateTime dt;
252 dt.setTime_t(d->mSignature.expirationTime());
253 return dt;
254}
255
256bool Signature::neverExpires() const
257{
258 return d->mSignature.neverExpires();
259}
260
261Key::Ptr Signature::key() const
262{
263 return d->mKey;
264}
265
266class EncryptionPrivate
267{
268public:
269 Encryption *q;
270 std::vector<Key::Ptr> mRecipients;
271};
272
273Encryption::Encryption(EncryptionPrivate *d_ptr)
274 :d(std::unique_ptr<EncryptionPrivate>(d_ptr))
275{
276 d->q = this;
277}
278
279Encryption::Encryption()
280 :d(std::unique_ptr<EncryptionPrivate>(new EncryptionPrivate))
281{
282 d->q = this;
283}
284
285Encryption::~Encryption()
286{
287
288}
289
290std::vector<Key::Ptr> Encryption::recipients() const
291{
292 return d->mRecipients;
293}
165 294
166class PartPrivate 295class 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
367Encryption::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
236void PartPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& part) 401void 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
241void PartPrivate::setEncryptions(const QVector< Encryption::Ptr >& encs) 406void 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
411QVector<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
246void PartPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& part) 452void 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
362void ContentPrivate::appendEncryption(const MimeTreeParser::EncryptedMessagePart::Ptr& enc) 568void 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
367void ContentPrivate::appendSignature(const MimeTreeParser::SignedMessagePart::Ptr& sig) 573void 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
641class SignaturePrivate
642{
643public:
644 Signature *q;
645};
646
647Signature::Signature()
648 :d(std::unique_ptr<SignaturePrivate>(new SignaturePrivate))
649{
650 d->q = this;
651}
652
653
654Signature::Signature(SignaturePrivate *d_ptr)
655 :d(std::unique_ptr<SignaturePrivate>(d_ptr))
656{
657 d->q = this;
658}
659
660Signature::~Signature()
661{
662
663}
664
665
666class EncryptionPrivate
667{
668public:
669 Encryption *q;
670};
671
672Encryption::Encryption(EncryptionPrivate *d_ptr)
673 :d(std::unique_ptr<EncryptionPrivate>(d_ptr))
674{
675 d->q = this;
676}
677
678Encryption::Encryption()
679 :d(std::unique_ptr<EncryptionPrivate>(new EncryptionPrivate))
680{
681 d->q = this;
682}
683
684Encryption::~Encryption()
685{
686
687}
688
689ParserPrivate::ParserPrivate(Parser* parser) 847ParserPrivate::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;
53class EncryptionError; 53class EncryptionError;
54 54
55class Key; 55class Key;
56class KeyPrivate;
56class Signature; 57class Signature;
57class SignaturePrivate; 58class SignaturePrivate;
58class Encryption; 59class Encryption;
@@ -262,10 +263,9 @@ public:
262 263
263 EncryptionError error() const; 264 EncryptionError error() const;
264private: 265private:
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>();
281private: 281private:
282 std::unique_ptr<EncapsulatedPartPrivate> d; 282 std::unique_ptr<EncapsulatedPartPrivate> d;
283}; 283};
284 284
285class EncryptionError 285class EncryptionError
@@ -291,6 +291,12 @@ public:
291 291
292class Key 292class Key
293{ 293{
294public:
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;
316private:
317 std::unique_ptr<KeyPrivate> d;
310}; 318};
311 319
312class Signature 320class 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;
343private: 351private:
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"));