diff options
author | Damien Caliste <dcaliste@free.fr> | 2018-09-05 09:46:12 +0200 |
---|---|---|
committer | Pekka Vuorela <pvuorela@iki.fi> | 2018-09-11 09:11:08 +0000 |
commit | fdf7f8085330303801f25b222e7876452ac602ec (patch) | |
tree | 606b7640d4ab972163fef6a68ae350e4e1b1a286 | |
parent | 100331a6b73b97337ae59f40694162eed9201572 (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.cpp | 63 | ||||
-rw-r--r-- | src/libraries/qmfclient/qmailmessage.h | 2 | ||||
-rw-r--r-- | src/libraries/qmfmessageserver/qmailmessageclassifier.cpp | 31 | ||||
-rw-r--r-- | src/plugins/messageservices/imap/imapstrategy.cpp | 9 | ||||
-rw-r--r-- | src/plugins/messageservices/imap/imapstructure.cpp | 4 | ||||
-rw-r--r-- | src/tools/messageserver/servicehandler.cpp | 4 |
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 << ∂ } 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; } |