diff options
author | Damien Caliste <dcaliste@free.fr> | 2018-12-05 10:41:10 +0100 |
---|---|---|
committer | Damien Caliste <dcaliste@free.fr> | 2018-12-13 20:17:49 +0000 |
commit | 3dc8e6f79caf1c8c108700be0f03df914e97821e (patch) | |
tree | 45713dde22d1403b28d694848d9b04d1ec8496f9 | |
parent | 2e987658ec7876ac082958130de25c7baea072fb (diff) |
Exclude parts containing signature data from attachment list
The signature data of PGP or S/MIME standards requires to be checked
on the undecoded data of another part of the email. This other part
is available internally through the undecoded() method, but is not
available outside QMF. There is thus no point to propose the signature
data as an attachment that may become visible to the user.
This patch remove the signature data of these two protocols from the
list of attachment, as it was done for the calendar data for instance.
It also updates and extends the tests of the findAttachmentLocations()
method.
Since imap plugin is using findAttachmentLocations() to decide to retrieve
parts or full message, a modification was required to ensure that
signature data are properly parsed in case of full message download.
Change-Id: If0da27ce06d78b15a44c40bfb409f84635a3a8f6
Reviewed-by: Christopher Adams <chris.adams@jollamobile.com>
Reviewed-by: Matthew Vogt <matthew.vogt@qinetic.com.au>
-rw-r--r-- | src/libraries/qmfclient/qmailmessage.cpp | 14 | ||||
-rw-r--r-- | src/plugins/messageservices/imap/imapprotocol.cpp | 4 | ||||
-rw-r--r-- | tests/tst_qmailmessage/tst_qmailmessage.cpp | 207 |
3 files changed, 129 insertions, 96 deletions
diff --git a/src/libraries/qmfclient/qmailmessage.cpp b/src/libraries/qmfclient/qmailmessage.cpp index f021833a..cd8ca4b1 100644 --- a/src/libraries/qmfclient/qmailmessage.cpp +++ b/src/libraries/qmfclient/qmailmessage.cpp @@ -1162,10 +1162,15 @@ namespace findAttachments { QMailMessageContentType contentType = part.contentType(); - bool isText = (contentType.matches("text", "plain") - || contentType.matches("text", "html")); + // Excluded text content-types. + bool excludedText = (contentType.matches("text", "plain") + || contentType.matches("text", "html") + || contentType.matches("text", "calendar")); - bool isCalendar = contentType.matches("text", "calendar"); + // Excluded application content-types even when + // explicitly marked as attachment. + bool excludedApp = (contentType.matches("application", "pgp-signature") + || contentType.matches("application", "pkcs7-signature")); bool isInLine = (!part.contentDisposition().isNull()) && (part.contentDisposition().type() == QMailMessageContentDisposition::Inline); @@ -1177,7 +1182,8 @@ namespace findAttachments // Attached messages are considered as attachments even if content disposition // is inline instead of attachment, but only if they aren't text/plain nor text/html - if (isRFC822 || isAttachment || (isInLine && !isText && !isCalendar)) { + if (isRFC822 || (isAttachment && !excludedApp) + || (isInLine && !excludedText && !excludedApp)) { if (found) { *found << part.location(); } diff --git a/src/plugins/messageservices/imap/imapprotocol.cpp b/src/plugins/messageservices/imap/imapprotocol.cpp index 6de98d68..630b16ed 100644 --- a/src/plugins/messageservices/imap/imapprotocol.cpp +++ b/src/plugins/messageservices/imap/imapprotocol.cpp @@ -3804,8 +3804,9 @@ QByteArray ImapProtocol::quoteString(const QByteArray& input) void ImapProtocol::createMail(const QString &uid, const QDateTime &timeStamp, int size, uint flags, const QString &detachedFile, const QStringList& structure) { - QMailMessage mail = QMailMessage::fromSkeletonRfc2822File( detachedFile ); + QMailMessage mail; if ( !structure.isEmpty() ) { + mail = QMailMessage::fromSkeletonRfc2822File( detachedFile ); bool wellFormed = setMessageContentFromStructure( structure, &mail ); if (wellFormed && (mail.multipartType() != QMailMessage::MultipartNone)) { @@ -3817,6 +3818,7 @@ void ImapProtocol::createMail(const QString &uid, const QDateTime &timeStamp, in mail.setStatus( QMailMessage::New, true ); } else { // No structure - we're fetching the body of a message we already know about + mail = QMailMessage::fromRfc2822File( detachedFile ); mail.setStatus( QMailMessage::ContentAvailable, true ); } diff --git a/tests/tst_qmailmessage/tst_qmailmessage.cpp b/tests/tst_qmailmessage/tst_qmailmessage.cpp index 57645075..b6ac9f7b 100644 --- a/tests/tst_qmailmessage/tst_qmailmessage.cpp +++ b/tests/tst_qmailmessage/tst_qmailmessage.cpp @@ -127,8 +127,8 @@ private slots: void multiMultipart(); + void attachments_data(); void attachments(); - void recursiveAttachments(); void copyAndAssign(); @@ -1473,107 +1473,132 @@ void tst_QMailMessage::multiMultipart() } } -void tst_QMailMessage::attachments() +Q_DECLARE_METATYPE(QMailMessageContentDisposition::DispositionType) +typedef QPair<QByteArray, QMailMessageContentDisposition::DispositionType> PartDefinition; +void tst_QMailMessage::attachments_data() { - QByteArray data; - QByteArray type; - - QMailMessagePart p1; - type = "text/plain; charset=UTF-8"; - data = "P1: This is a plain text part."; - p1.setBody(QMailMessageBody::fromData(data, QMailMessageContentType(type), - QMailMessageBody::EightBit, - QMailMessageBody::RequiresEncoding)); - - QMailMessagePart p2; - type = "text/calendar; charset=UTF-8"; - data = "BEGIN:VCALENDAR\nEND:VCALENDAR"; - p2.setBody(QMailMessageBody::fromData(data, QMailMessageContentType(type), - QMailMessageBody::EightBit, - QMailMessageBody::RequiresEncoding)); - - QMailMessagePart p3; - type = "application/octet-stream; name=\"attach.pdf\""; - data = "abcdef"; - p3.setBody(QMailMessageBody::fromData(data, QMailMessageContentType(type), - QMailMessageBody::Base64, - QMailMessageBody::AlreadyEncoded)); - p3.setContentDisposition(QMailMessageContentDisposition::Attachment); - - QMailMessage m; - m.setTo(QMailAddress("someone@example.net")); - m.setFrom(QMailAddress("someone@example.net")); - m.setSubject("multipart/mixed with attachment"); - - m.setMultipartType(QMailMessagePartContainer::MultipartMixed); - m.appendPart(p1); - m.appendPart(p2); - m.appendPart(p3); - QCOMPARE(m.contentType().toString().toLower(), - QByteArray("Content-Type: multipart/mixed").toLower()); - QCOMPARE(m.transferEncoding(), QMailMessageBody::NoEncoding); - QCOMPARE(m.partCount(), uint(3)); - for (uint i = 0; i < m.partCount(); ++i) - QCOMPARE( m.partAt(i).partNumber(), int(i) ); - - QList<QMailMessagePart::Location> indices = m.findAttachmentLocations(); - QCOMPARE(indices.size(), 1); - QCOMPARE(indices.at(0).toString(false), QStringLiteral("3")); + QTest::addColumn<QList<PartDefinition>>("structure"); + QTest::addColumn<QStringList>("attachments"); + + QTest::newRow("simple text") + << (QList<PartDefinition>() + << PartDefinition("text/plain; charset=UTF-8", + QMailMessageContentDisposition::Inline)) + << QStringList(); + + QTest::newRow("multipart/alternative text-HTML") + << (QList<PartDefinition>() + << PartDefinition("multipart/alternative", + QMailMessageContentDisposition::None) + << PartDefinition("text/plain; charset=UTF-8", + QMailMessageContentDisposition::Inline) + << PartDefinition("text/html; charset=UTF-8", + QMailMessageContentDisposition::Inline)) + << QStringList(); + + QTest::newRow("multipart/mixed with calendar") + << (QList<PartDefinition>() + << PartDefinition("multipart/mixed", + QMailMessageContentDisposition::None) + << PartDefinition("text/plain; charset=UTF-8", + QMailMessageContentDisposition::Inline) + << PartDefinition("text/calendar; charset=UTF-8", + QMailMessageContentDisposition::Inline) + << PartDefinition("application/octet-stream; name=\"attach.pdf\"", + QMailMessageContentDisposition::Attachment)) + << (QStringList() << "3"); + + QTest::newRow("multipart/mixed with text attachment") + << (QList<PartDefinition>() + << PartDefinition("multipart/mixed", + QMailMessageContentDisposition::None) + << PartDefinition("text/plain; charset=UTF-8", + QMailMessageContentDisposition::Inline) + << PartDefinition("text/plain; charset=UTF-8", + QMailMessageContentDisposition::Attachment)) + << (QStringList() << "2"); + + QTest::newRow("multipart/alternative recursive") + << (QList<PartDefinition>() + << PartDefinition("multipart/alternative", + QMailMessageContentDisposition::None) + << PartDefinition("text/plain; charset=UTF-8", + QMailMessageContentDisposition::Inline) + << PartDefinition("multipart/mixed", + QMailMessageContentDisposition::None) + << PartDefinition("text/html; charset=UTF-8", + QMailMessageContentDisposition::Inline) + << PartDefinition("application/octet-stream; name=\"attach.pdf\"", + QMailMessageContentDisposition::Attachment)) + << (QStringList() << "2.2"); + + QTest::newRow("multipart/signed PGP") + << (QList<PartDefinition>() + << PartDefinition("multipart/signed", + QMailMessageContentDisposition::None) + << PartDefinition("text/plain; charset=UTF-8", + QMailMessageContentDisposition::Inline) + << PartDefinition("application/pgp-signature", + QMailMessageContentDisposition::Inline)) + << QStringList(); + + QTest::newRow("multipart/signed S/MIME") + << (QList<PartDefinition>() + << PartDefinition("multipart/signed", + QMailMessageContentDisposition::None) + << PartDefinition("text/plain; charset=UTF-8", + QMailMessageContentDisposition::Inline) + << PartDefinition("application/pkcs7-signature", + QMailMessageContentDisposition::Attachment)) + << QStringList(); } -void tst_QMailMessage::recursiveAttachments() +void tst_QMailMessage::attachments() { - QByteArray data; - QByteArray type; - - QMailMessagePart p1; - type = "text/plain; charset=UTF-8"; - data = "P1: This is a plain text part."; - p1.setBody(QMailMessageBody::fromData(data, QMailMessageContentType(type), - QMailMessageBody::EightBit, - QMailMessageBody::RequiresEncoding)); - - QMailMessagePart p3; - type = "text/html; charset=UTF-8"; - data = "<html></html>"; - p3.setBody(QMailMessageBody::fromData(data, QMailMessageContentType(type), - QMailMessageBody::EightBit, - QMailMessageBody::RequiresEncoding)); - - QMailMessagePart p4; - type = "application/octet-stream; name=\"attach.pdf\""; - data = "abcdef"; - p4.setBody(QMailMessageBody::fromData(data, QMailMessageContentType(type), - QMailMessageBody::Base64, - QMailMessageBody::AlreadyEncoded)); - p4.setContentDisposition(QMailMessageContentDisposition::Attachment); - - QMailMessagePart p2; - p2.setMultipartType(QMailMessagePartContainer::MultipartMixed); - p2.appendPart(p3); - p2.appendPart(p4); + QFETCH(QList<PartDefinition>, structure); + QFETCH(QStringList, attachments); QMailMessage m; m.setTo(QMailAddress("someone@example.net")); m.setFrom(QMailAddress("someone@example.net")); - m.setSubject("multipart/alternative with attachment in mixed"); + m.setSubject("multipart/mixed with attachment"); - m.setMultipartType(QMailMessagePartContainer::MultipartAlternative); - m.appendPart(p1); - m.appendPart(p2); - QCOMPARE(m.contentType().toString().toLower(), - QByteArray("Content-Type: multipart/alternative").toLower()); - QCOMPARE(m.transferEncoding(), QMailMessageBody::NoEncoding); - QCOMPARE(m.partCount(), uint(2)); - for (uint i = 0; i < m.partCount(); ++i) - QCOMPARE( m.partAt(i).partNumber(), int(i) ); - QCOMPARE(m.partAt(1).partCount(), uint(2)); - for (uint i = 0; i < m.partAt(1).partCount(); ++i) - QCOMPARE( m.partAt(1).partAt(i).partNumber(), int(i) ); + if (!structure[0].first.startsWith("multipart")) { + m.setBody(QMailMessageBody::fromData(QStringLiteral("some content"), + QMailMessageContentType(structure[0].first), + QMailMessageBody::QuotedPrintable)); + m.setContentDisposition(structure[0].second); + } else { + QList<PartDefinition>::ConstIterator it = structure.constBegin(); + m.setBody(QMailMessageBody::fromData(QString(), + QMailMessageContentType(it->first), + QMailMessageBody::NoEncoding)); + m.setContentDisposition(it->second); + QMailMessagePartContainer *lastContainer = &m; + for (it++; it != structure.constEnd(); it++) { + QMailMessagePart part; + if (it->first.startsWith("multipart")) { + part.setBody(QMailMessageBody::fromData(QString(), + QMailMessageContentType(it->first), + QMailMessageBody::NoEncoding)); + part.setContentDisposition(it->second); + lastContainer->appendPart(part); + lastContainer = &lastContainer->partAt(lastContainer->partCount() - 1); + } else { + part.setBody(QMailMessageBody::fromData(QStringLiteral("some content"), + QMailMessageContentType(it->first), + QMailMessageBody::QuotedPrintable)); + part.setContentDisposition(it->second); + lastContainer->appendPart(part); + } + } + } QList<QMailMessagePart::Location> indices = m.findAttachmentLocations(); - QCOMPARE(indices.size(), 1); - QCOMPARE(indices.at(0).toString(false), QStringLiteral("2.2")); + QCOMPARE(indices.size(), attachments.size()); + for (int i = 0; i < attachments.size(); i++) { + QCOMPARE(indices.at(i).toString(false), attachments[i]); + } } void tst_QMailMessage::copyAndAssign() |