From def04e4ba5b838bba3786c1ddb28ed5094f99a98 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Tue, 7 Sep 2010 10:46:24 +0000 Subject: [PATCH] Added an option to recognize inline objects as attachments. --- src/attachmentHelper.cpp | 96 +++++++++++++++++++++----------------- vmime/attachmentHelper.hpp | 39 ++++++++++++---- 2 files changed, 83 insertions(+), 52 deletions(-) diff --git a/src/attachmentHelper.cpp b/src/attachmentHelper.cpp index 65e8c88b..c23ee950 100644 --- a/src/attachmentHelper.cpp +++ b/src/attachmentHelper.cpp @@ -36,7 +36,8 @@ namespace vmime // static -bool attachmentHelper::isBodyPartAnAttachment(ref part) +bool attachmentHelper::isBodyPartAnAttachment + (ref part, const unsigned int options) { try { @@ -49,54 +50,63 @@ bool attachmentHelper::isBodyPartAnAttachment(ref part) if (disp.getName() != contentDispositionTypes::INLINE) return true; - // If the Content-Disposition is 'inline' and there is no - // Content-Id or Content-Location field, it may be an attachment - if (!part->getHeader()->hasField(vmime::fields::CONTENT_ID) && - !part->getHeader()->hasField(vmime::fields::CONTENT_LOCATION)) + if ((options & INLINE_OBJECTS) == 0) { - // If this is the root part, it might not be an attachment - if (part->getParentPart() == NULL) - return false; + // If the Content-Disposition is 'inline' and there is no + // Content-Id or Content-Location field, it may be an attachment + if (!part->getHeader()->hasField(vmime::fields::CONTENT_ID) && + !part->getHeader()->hasField(vmime::fields::CONTENT_LOCATION)) + { + // If this is the root part, it might not be an attachment + if (part->getParentPart() == NULL) + return false; - return true; + return true; + } + + return false; } } catch (exceptions::no_such_field&) { - // No "Content-disposition" field: assume "attachment" if - // type is not "text/..." or "multipart/...". - mediaType type; + // Will try using Content-Type + } - try - { - const contentTypeField& ctf = dynamic_cast - (*part->getHeader()->findField(fields::CONTENT_TYPE)); + // Assume "attachment" if type is not "text/..." or "multipart/...". + mediaType type; - type = *ctf.getValue().dynamicCast (); - } - catch (exceptions::no_such_field&) - { - // If this is the root part and no Content-Type field is present, - // then this may not be a MIME message, so do not assume it is - // an attachment - if (part->getParentPart() == NULL) - return false; + try + { + const contentTypeField& ctf = dynamic_cast + (*part->getHeader()->findField(fields::CONTENT_TYPE)); - // No "Content-type" field: assume "application/octet-stream". - type = mediaType(mediaTypes::APPLICATION, - mediaTypes::APPLICATION_OCTET_STREAM); - } + type = *ctf.getValue().dynamicCast (); + } + catch (exceptions::no_such_field&) + { + // If this is the root part and no Content-Type field is present, + // then this may not be a MIME message, so do not assume it is + // an attachment + if (part->getParentPart() == NULL) + return false; - if (type.getType() != mediaTypes::TEXT && - type.getType() != mediaTypes::MULTIPART) + // No "Content-type" field: assume "application/octet-stream". + type = mediaType(mediaTypes::APPLICATION, + mediaTypes::APPLICATION_OCTET_STREAM); + } + + if (type.getType() != mediaTypes::TEXT && + type.getType() != mediaTypes::MULTIPART) + { + if ((options & INLINE_OBJECTS) == 0) { // If a "Content-Id" field is present, it might be an // embedded object (MHTML messages) if (part->getHeader()->hasField(vmime::fields::CONTENT_ID)) return false; - - return true; } + + return true; } return false; @@ -104,10 +114,10 @@ bool attachmentHelper::isBodyPartAnAttachment(ref part) // static -ref - attachmentHelper::getBodyPartAttachment(ref part) +ref attachmentHelper::getBodyPartAttachment + (ref part, const unsigned int options) { - if (!isBodyPartAnAttachment(part)) + if (!isBodyPartAnAttachment(part, options)) return NULL; mediaType type; @@ -140,22 +150,24 @@ ref // static const std::vector > - attachmentHelper::findAttachmentsInMessage(ref msg) + attachmentHelper::findAttachmentsInMessage + (ref msg, const unsigned int options) { - return findAttachmentsInBodyPart(msg); + return findAttachmentsInBodyPart(msg, options); } // static const std::vector > - attachmentHelper::findAttachmentsInBodyPart(ref part) + attachmentHelper::findAttachmentsInBodyPart + (ref part, const unsigned int options) { std::vector > atts; // Test this part - if (isBodyPartAnAttachment(part)) + if (isBodyPartAnAttachment(part, options)) { - atts.push_back(getBodyPartAttachment(part)); + atts.push_back(getBodyPartAttachment(part, options)); } // Find in sub-parts else @@ -165,7 +177,7 @@ const std::vector > for (int i = 0 ; i < bdy->getPartCount() ; ++i) { std::vector > partAtts = - findAttachmentsInBodyPart(bdy->getPartAt(i)); + findAttachmentsInBodyPart(bdy->getPartAt(i), options); std::copy(partAtts.begin(), partAtts.end(), std::back_inserter(atts)); } diff --git a/vmime/attachmentHelper.hpp b/vmime/attachmentHelper.hpp index 3ce86c83..a3833672 100644 --- a/vmime/attachmentHelper.hpp +++ b/vmime/attachmentHelper.hpp @@ -30,10 +30,6 @@ #include "vmime/attachment.hpp" #include "vmime/message.hpp" -#if VMIME_HAVE_MESSAGING_FEATURES - #include "vmime/net/message.hpp" -#endif - namespace vmime { @@ -45,31 +41,57 @@ class attachmentHelper { public: + /** Options for use with the following functions: + * findAttachmentsInMessage, + * getBodyPartAttachment, + * and isBodyPartAnAttachment. + */ + enum FindOptions + { + INLINE_OBJECTS = (1 << 0) /**< Recognize and return inline objects. The aim is to + consider MHTML objects (parts with a "Content-Id" or + a "Content-Location", such as inline images) as attachments. */ + }; + /** Test whether a body part is an attachment. * * @param part message part to test + * @param options search options (see FindOptions) * @return true if the part is an attachment, false otherwise */ - static bool isBodyPartAnAttachment(ref part); + static bool isBodyPartAnAttachment(ref part, const unsigned int options = 0); /** Return attachment information in the specified body part. * If the specified body part does not contain attachment * information (ie. is not an attachment), NULL is returned. * * @param part message part in which to search + * @param options search options (see FindOptions) * @return attachment found in the part, or NULL */ static ref - getBodyPartAttachment(ref part); + getBodyPartAttachment(ref part, const unsigned int options = 0); + + /** Find all attachments contained in the specified part + * and all its children parts. + * This is simply a recursive call to getBodyPartAttachment(). + * + * @param part part in which to search + * @param options search options (see FindOptions) + * @return a list of attachments found + */ + static const std::vector > + findAttachmentsInBodyPart(ref part, const unsigned int options = 0); /** Find all attachments contained in the specified message. * This is simply a recursive call to getBodyPartAttachment(). * * @param msg message in which to search + * @param options search options (see FindOptions) * @return a list of attachments found */ static const std::vector > - findAttachmentsInMessage(ref msg); + findAttachmentsInMessage(ref msg, const unsigned int options = 0); /** Add an attachment to the specified message. * @@ -87,9 +109,6 @@ public: protected: - static const std::vector > - findAttachmentsInBodyPart(ref part); - static ref findBodyPart (ref part, const mediaType& type); };