summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamien Caliste <dcaliste@free.fr>2018-09-05 09:46:12 +0200
committerPekka Vuorela <pvuorela@iki.fi>2018-09-11 09:11:08 +0000
commitfdf7f8085330303801f25b222e7876452ac602ec (patch)
tree606b7640d4ab972163fef6a68ae350e4e1b1a286
parent100331a6b73b97337ae59f40694162eed9201572 (diff)
Introduce a new function to test content type content
Create a new function to ensure that content type matching is always done case insensitive. Originally the comparison was done after a toLower(), but forgetting this, like in src/libraries/qmfclient/qmailmessage.cpp#6252, can create bugs. Change-Id: Ia93e068e5374c346c94c2afe4de768d3833b4a9a Reviewed-by: Pekka Vuorela <pvuorela@iki.fi>
-rw-r--r--src/libraries/qmfclient/qmailmessage.cpp63
-rw-r--r--src/libraries/qmfclient/qmailmessage.h2
-rw-r--r--src/libraries/qmfmessageserver/qmailmessageclassifier.cpp31
-rw-r--r--src/plugins/messageservices/imap/imapstrategy.cpp9
-rw-r--r--src/plugins/messageservices/imap/imapstructure.cpp4
-rw-r--r--src/tools/messageserver/servicehandler.cpp4
6 files changed, 50 insertions, 63 deletions
diff --git a/src/libraries/qmfclient/qmailmessage.cpp b/src/libraries/qmfclient/qmailmessage.cpp
index 867d0aa2..98108179 100644
--- a/src/libraries/qmfclient/qmailmessage.cpp
+++ b/src/libraries/qmfclient/qmailmessage.cpp
@@ -917,11 +917,7 @@ namespace findBody
bool inMultipartNone(const QMailMessagePartContainer &container, Context &ctx)
{
- if (!ctx.contentType.isEmpty()
- && ctx.contentType != container.contentType().type().toLower())
- return false;
- if (!ctx.contentSubtype.isEmpty()
- && ctx.contentSubtype != container.contentType().subType().toLower())
+ if (!container.contentType().matches(ctx.contentType, ctx.contentSubtype))
return false;
ctx.found = const_cast<QMailMessagePartContainer*>(&container);
return true;
@@ -932,12 +928,7 @@ namespace findBody
if (part.contentDisposition().type() == QMailMessageContentDisposition::Attachment)
return false;
- if (!ctx.contentType.isEmpty()
- && ctx.contentType != part.contentType().type().toLower())
- return false;
-
- if (!ctx.contentSubtype.isEmpty()
- && ctx.contentSubtype != part.contentType().subType().toLower())
+ if (!part.contentType().matches(ctx.contentType, ctx.contentSubtype))
return false;
ctx.found = const_cast<QMailMessagePart*> (&part);
@@ -1012,7 +1003,7 @@ namespace findBody
for (int i = (int)container.partCount() - 1; i >= 0; i--) {
if (i != bodyPart) {
const QMailMessagePart &part = container.partAt(i);
- if (imageContentType == part.contentType().type().toLower()) {
+ if (part.contentType().matches(imageContentType)) {
ctx.htmlImageLoc << part.location();
ctx.htmlImageParts << &part;
} else if (!part.contentID().isEmpty()) {
@@ -1166,8 +1157,8 @@ namespace findAttachments
{
QMailMessageContentType contentType = part.contentType();
- bool isText = (contentType.type().toLower() == "text") &&
- ((contentType.subType().toLower() == "plain") || (contentType.subType().toLower() == "html"));
+ bool isText = (contentType.matches("text", "plain")
+ || contentType.matches("text", "html"));
bool isCalendar = (contentType.type().toLower() == "text") &&
(contentType.subType().toLower() == "calendar");
@@ -1178,8 +1169,7 @@ namespace findAttachments
bool isAttachment = (!part.contentDisposition().isNull()) &&
(part.contentDisposition().type() == QMailMessageContentDisposition::Attachment);
- bool isRFC822 = (contentType.type().toLower() == "message") &&
- (contentType.subType().toLower() == "rfc822");
+ bool isRFC822 = contentType.matches("message", "rfc822");
// 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
@@ -1272,18 +1262,17 @@ namespace findAttachments
const QMailMessagePart &part = container.partAt(i);
// Skip parts of the message body
- const QString contentType = QString::fromLatin1(part.contentType().content()).toLower();
switch (i) {
case 0:
- if (contentType == QLatin1String("text/plain")) {
+ if (part.contentType().matches("text", "plain")) {
firstPartIsTextPlain = true;
continue;
- } else if (contentType == QLatin1String("text/html")) {
+ } else if (part.contentType().matches("text", "html")) {
continue;
}
break;
case 1:
- if (firstPartIsTextPlain && contentType == QLatin1String("text/html")) {
+ if (firstPartIsTextPlain && part.contentType().matches("text", "html")) {
continue;
}
break;
@@ -2688,6 +2677,15 @@ void QMailMessageContentType::setCharset(const QByteArray& charset)
setParameter("charset", charset);
}
+/*!
+ Allow to test if the content type matches a specific "type / subtype" string.
+*/
+bool QMailMessageContentType::matches(const QByteArray& primary, const QByteArray& sub) const
+{
+ // Content type is not encoded, we can use qstricmp directly.
+ return ((primary.isEmpty() || qstricmp(type(), primary) == 0)
+ && (sub.isEmpty() || qstricmp(subType(), sub) == 0));
+}
/*!
\class QMailMessageContentDisposition
@@ -3179,9 +3177,7 @@ QMailMessageBodyPrivate::QMailMessageBodyPrivate()
void QMailMessageBodyPrivate::ensureCharsetExist()
{
- if (_type.type().toLower() != "text"
- || (_type.subType().toLower() != "plain"
- && _type.subType().toLower() != "html")) {
+ if (!_type.matches("text", "plain") && !_type.matches("text", "html")) {
QByteArray best(QMailCodec::bestCompatibleCharset(_type.charset(), true));
if (!best.isEmpty()) {
_type.setCharset(best);
@@ -4037,7 +4033,7 @@ void QMailMessagePartContainerPrivate::defaultContentType(const QMailMessagePart
{
// Note that the default is 'message/rfc822' when the parent is 'multipart/digest'
QMailMessageContentType parentType = parent->contentType();
- if (parentType.content().toLower() == "multipart/digest")
+ if (parentType.matches("multipart", "digest"))
{
type.setType("message");
type.setSubType("rfc822");
@@ -4211,7 +4207,7 @@ void QMailMessagePartContainerPrivate::setBody(const QMailMessageBody& body, QMa
setBodyProperties(body.contentType(), body.transferEncoding());
// Multipart messages do not have their own bodies
- if (body.contentType().type().toLower() != "multipart") {
+ if (!body.contentType().matches("multipart")) {
_body = body;
_hasBody = !_body.isEmpty();
}
@@ -6104,14 +6100,10 @@ QString QMailMessagePart::displayName() const
if (id.isEmpty())
id = contentID();
- if (id.isEmpty()) {
- bool isRFC822 = (contentType().type().toLower() == "message") &&
- (contentType().subType().toLower() == "rfc822");
- if (isRFC822) {
- // TODO don't load entire body into memory
- QMailMessage msg = QMailMessage::fromRfc2822(body().data(QMailMessageBody::Decoded));
- id = msg.subject();
- }
+ if (id.isEmpty() && contentType().matches("message", "rfc822")) {
+ // TODO don't load entire body into memory
+ QMailMessage msg = QMailMessage::fromRfc2822(body().data(QMailMessageBody::Decoded));
+ id = msg.subject();
}
if (id.isEmpty()) {
@@ -6243,7 +6235,7 @@ static QString partFileName(const QMailMessagePart &part)
// Application/octet-stream is a fallback for the case when mimetype
// is unknown by MUA, so it's treated exceptionally here, so the original
// attachment name is preserved
- if (part.contentType().content() != QByteArray("application/octet-stream")) {
+ if (!part.contentType().matches("application", "octet-stream")) {
// If possible, create the file with a useful filename extension
QString existing;
int index = fileName.lastIndexOf('.');
@@ -8472,8 +8464,7 @@ bool QMailMessage::hasCalendarInvitation() const
}
} else {
const QMailMessageContentType &ct(part->contentType());
- if ((ct.type().toLower() == "text") &&
- (ct.subType().toLower() == "calendar") &&
+ if (ct.matches("text", "calendar") &&
(ct.parameter("method").toLower() == "request")) {
return true;
}
diff --git a/src/libraries/qmfclient/qmailmessage.h b/src/libraries/qmfclient/qmailmessage.h
index 1f57dbfb..6d73f75a 100644
--- a/src/libraries/qmfclient/qmailmessage.h
+++ b/src/libraries/qmfclient/qmailmessage.h
@@ -146,6 +146,8 @@ public:
QByteArray charset() const;
void setCharset(const QByteArray& charset);
+ bool matches(const QByteArray& primary, const QByteArray& sub = QByteArray()) const;
+
private:
// Don't allow the Id to be changed
void setId(const QByteArray& text);
diff --git a/src/libraries/qmfmessageserver/qmailmessageclassifier.cpp b/src/libraries/qmfmessageserver/qmailmessageclassifier.cpp
index a4060382..eed1b888 100644
--- a/src/libraries/qmfmessageserver/qmailmessageclassifier.cpp
+++ b/src/libraries/qmfmessageserver/qmailmessageclassifier.cpp
@@ -87,26 +87,21 @@ QMailMessageClassifier::~QMailMessageClassifier()
static QMailMessage::ContentType fromContentType(const QMailMessageContentType& contentType)
{
- QByteArray type(contentType.type().toLower());
- QByteArray subtype(contentType.subType().toLower());
-
QMailMessage::ContentType content = QMailMessage::UnknownContent;
- if (type == "text") {
- if (subtype == "html") {
- content = QMailMessage::HtmlContent;
- } else if (subtype == "plain") {
- content = QMailMessage::PlainTextContent;
- } else if (subtype == "x-vcard") {
- content = QMailMessage::VCardContent;
- } else if (subtype == "x-vcalendar") {
- content = QMailMessage::VCalendarContent;
- }
- } else if (contentType.type().toLower() == "image") {
+ if (contentType.matches("text", "html")) {
+ content = QMailMessage::HtmlContent;
+ } else if (contentType.matches("text", "plain")) {
+ content = QMailMessage::PlainTextContent;
+ } else if (contentType.matches("text", "x-vcard")) {
+ content = QMailMessage::VCardContent;
+ } else if (contentType.matches("text", "x-vcalendar")) {
+ content = QMailMessage::VCalendarContent;
+ } else if (contentType.matches("image")) {
content = QMailMessage::ImageContent;
- } else if (contentType.type().toLower() == "audio") {
+ } else if (contentType.matches("audio")) {
content = QMailMessage::AudioContent;
- } else if (contentType.type().toLower() == "video") {
+ } else if (contentType.matches("video")) {
content = QMailMessage::VideoContent;
}
@@ -183,7 +178,7 @@ bool QMailMessageClassifier::classifyMessage(QMailMessage& message)
if (multipartType == QMailMessagePartContainer::MultipartNone) {
content = fromContentType(contentType);
if (content == QMailMessage::UnknownContent) {
- if (contentType.type().toLower() == "text") {
+ if (contentType.matches("text")) {
// Assume some type of richer-than-plain text
content = QMailMessage::RichTextContent;
}
@@ -202,7 +197,7 @@ bool QMailMessageClassifier::classifyMessage(QMailMessage& message)
if (multipartType == QMailMessagePartContainer::MultipartNone) {
content = fromContentType(contentType);
if (content == QMailMessage::UnknownContent) {
- if (contentType.type().toLower() == "text") {
+ if (contentType.matches("text")) {
// Assume some type of richer-than-plain text
content = QMailMessage::RichTextContent;
}
diff --git a/src/plugins/messageservices/imap/imapstrategy.cpp b/src/plugins/messageservices/imap/imapstrategy.cpp
index 7f0be8e1..aa05258a 100644
--- a/src/plugins/messageservices/imap/imapstrategy.cpp
+++ b/src/plugins/messageservices/imap/imapstrategy.cpp
@@ -1531,7 +1531,7 @@ void ImapFetchSelectedMessagesStrategy::metaDataAnalysis(ImapStrategyContextBase
}
ImapConfiguration imapCfg(context->config());
- QString preferred(imapCfg.preferredTextSubtype().toLower());
+ QByteArray preferred(imapCfg.preferredTextSubtype().toLatin1());
// Iterate over all parts, looking for the preferred body,
// download that first giving preference over all other parts
@@ -1544,8 +1544,7 @@ void ImapFetchSelectedMessagesStrategy::metaDataAnalysis(ImapStrategyContextBase
if ((part.partCount() == 0)
&& (!part.partialContentAvailable())
&& (disposition.size() > 0)
- && (contentType.type().toLower() == "text")
- && (contentType.subType().toLower() == preferred)) {
+ && (contentType.matches("text", preferred))) {
// There is a preferred text sub-part to retrieve.
// The preferred text part has priority over other parts so,
// we put it directly into the main completion list.
@@ -1612,7 +1611,7 @@ void ImapFetchSelectedMessagesStrategy::prepareCompletionList(
completionList.append(message.id());
} else {
const QMailMessageContentType contentType(message.contentType());
- if (contentType.type().toLower() == "text") {
+ if (contentType.matches("text")) {
// It is a text part. So, we can retrieve the first
// portion of it.
QMailMessagePart::Location location;
@@ -1637,7 +1636,7 @@ void ImapFetchSelectedMessagesStrategy::prepareCompletionList(
completionSectionList.append(qMakePair(it->first, (uint)0));
bytesLeft -= it->second;
++partsToRetrieve;
- } else if (part.contentType().type().toLower() == "text") {
+ } else if (part.contentType().matches("text")) {
// Text parts can be downloaded partially.
completionSectionList.append(qMakePair(it->first, (uint)bytesLeft));
bytesLeft = 0;
diff --git a/src/plugins/messageservices/imap/imapstructure.cpp b/src/plugins/messageservices/imap/imapstructure.cpp
index a962d089..acfa832e 100644
--- a/src/plugins/messageservices/imap/imapstructure.cpp
+++ b/src/plugins/messageservices/imap/imapstructure.cpp
@@ -364,10 +364,10 @@ void setPartFromDescription(const QStringList &details, QMailMessagePart *part)
int next = 7;
const QMailMessageContentType &type(part->contentType());
- if (type.type().toUpper() == "TEXT") {
+ if (type.matches("text")) {
// The following field is the part's line count
++next;
- } else if ((type.type().toUpper() == "MESSAGE") && (type.subType().toUpper() == "RFC822")) {
+ } else if (type.matches("message", "rfc822")) {
// For parts of type 'message/rfc822', there are three extra fields here...
next += 3;
}
diff --git a/src/tools/messageserver/servicehandler.cpp b/src/tools/messageserver/servicehandler.cpp
index 86cc5810..06fdb13e 100644
--- a/src/tools/messageserver/servicehandler.cpp
+++ b/src/tools/messageserver/servicehandler.cpp
@@ -366,7 +366,7 @@ struct TextPartSearcher
bool operator()(const QMailMessagePart &part)
{
- if (part.contentType().type().toLower() == "text") {
+ if (part.contentType().matches("text")) {
if (part.body().data().contains(text, Qt::CaseInsensitive)) {
return false;
}
@@ -381,7 +381,7 @@ bool messageBodyContainsText(const QMailMessage &message, const QString& text)
{
// Search only messages or message parts that are of type 'text/*'
if (message.hasBody()) {
- if (message.contentType().type().toLower() == "text") {
+ if (message.contentType().matches("text")) {
if (message.body().data().contains(text, Qt::CaseInsensitive))
return true;
}