summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamien Caliste <dcaliste@free.fr>2018-12-05 10:41:10 +0100
committerDamien Caliste <dcaliste@free.fr>2018-12-13 20:17:49 +0000
commit3dc8e6f79caf1c8c108700be0f03df914e97821e (patch)
tree45713dde22d1403b28d694848d9b04d1ec8496f9
parent2e987658ec7876ac082958130de25c7baea072fb (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.cpp14
-rw-r--r--src/plugins/messageservices/imap/imapprotocol.cpp4
-rw-r--r--tests/tst_qmailmessage/tst_qmailmessage.cpp207
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()