aboutsummaryrefslogtreecommitdiffstats
path: root/src/attachmentHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/attachmentHelper.cpp')
-rw-r--r--src/attachmentHelper.cpp201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/attachmentHelper.cpp b/src/attachmentHelper.cpp
new file mode 100644
index 00000000..0388ae7c
--- /dev/null
+++ b/src/attachmentHelper.cpp
@@ -0,0 +1,201 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "vmime/attachmentHelper.hpp"
+
+#include "vmime/bodyPartAttachment.hpp"
+
+
+namespace vmime
+{
+
+
+// static
+const bool attachmentHelper::isBodyPartAnAttachment(ref <const bodyPart> part)
+{
+ try
+ {
+ const contentDispositionField& cdf = dynamic_cast<contentDispositionField&>
+ (*part->getHeader()->findField(fields::CONTENT_DISPOSITION));
+
+ if (cdf.getValue().getName() != contentDispositionTypes::INLINE)
+ return true;
+ }
+ catch (exceptions::no_such_field)
+ {
+ // No "Content-disposition" field: assume "attachment" if
+ // type is not "text/..." or "multipart/...".
+ mediaType type;
+
+ try
+ {
+ const contentTypeField& ctf = dynamic_cast<contentTypeField&>
+ (*part->getHeader()->findField(fields::CONTENT_TYPE));
+
+ type = ctf.getValue();
+ }
+ catch (exceptions::no_such_field)
+ {
+ // 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)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// static
+ref <const attachment>
+ attachmentHelper::getBodyPartAttachment(ref <const bodyPart> part)
+{
+ if (!isBodyPartAnAttachment(part))
+ return NULL;
+
+ return vmime::create <bodyPartAttachment>(part);
+}
+
+
+// static
+const std::vector <ref <const attachment> >
+ attachmentHelper::findAttachmentsInMessage(ref <const message> msg)
+{
+ return findAttachmentsInBodyPart(msg);
+}
+
+
+// static
+const std::vector <ref <const attachment> >
+ attachmentHelper::findAttachmentsInBodyPart(ref <const bodyPart> part)
+{
+ std::vector <ref <const attachment> > atts;
+
+ // Test this part
+ if (isBodyPartAnAttachment(part))
+ {
+ atts.push_back(getBodyPartAttachment(part));
+ }
+ // Find in sub-parts
+ else
+ {
+ ref <const body> bdy = part->getBody();
+
+ for (int i = 0 ; i < bdy->getPartCount() ; ++i)
+ {
+ std::vector <ref <const attachment> > partAtts =
+ findAttachmentsInBodyPart(bdy->getPartAt(i));
+
+ for (unsigned int j = 0 ; j < partAtts.size() ; ++i)
+ atts.push_back(partAtts[j]);
+ }
+ }
+
+ return atts;
+}
+
+
+// static
+void attachmentHelper::addAttachment(ref <message> msg, ref <attachment> att)
+{
+ // We simply search for a "multipart/mixed" part. If no one exists,
+ // create it in the root part. This (very simple) algorithm should
+ // work in the most cases.
+
+ vmime::mediaType mpMixed(vmime::mediaTypes::MULTIPART,
+ vmime::mediaTypes::MULTIPART_MIXED);
+
+ ref <bodyPart> part = findBodyPart(msg, mpMixed);
+
+ if (part == NULL) // create it
+ {
+ // Create a new container part for the parts that were in
+ // the root part of the message
+ ref <bodyPart> container = vmime::create <bodyPart>();
+
+ try
+ {
+ container->getHeader()->ContentType()->
+ setValue(msg->getHeader()->ContentType()->getValue());
+ }
+ catch (exceptions::no_such_field&)
+ {
+ // Ignore
+ }
+
+ msg->getHeader()->removeAllFields(vmime::fields::CONTENT_DISPOSITION);
+ msg->getHeader()->removeAllFields(vmime::fields::CONTENT_TRANSFER_ENCODING);
+
+ // Move parts from the root part to this new part
+ const std::vector <ref <bodyPart> > partList =
+ msg->getBody()->getPartList();
+
+ msg->getBody()->removeAllParts();
+
+ for (unsigned int i = 0 ; i < partList.size() ; ++i)
+ container->getBody()->appendPart(partList[i]);
+
+ // Set the root part to 'multipart/mixed'
+ msg->getHeader()->ContentType()->setValue(mpMixed);
+
+ msg->getBody()->appendPart(container);
+
+ part = msg;
+ }
+
+ // Generate the attachment part
+ att->generateIn(*part);
+}
+
+
+// static
+ref <bodyPart> attachmentHelper::findBodyPart
+ (ref <bodyPart> part, const mediaType& type)
+{
+ if (part->getBody()->getContentType() == type)
+ return part;
+
+ // Try in sub-parts
+ ref <body> bdy = part->getBody();
+
+ for (int i = 0 ; i < bdy->getPartCount() ; ++i)
+ {
+ ref <bodyPart> found =
+ findBodyPart(bdy->getPartAt(i), type);
+
+ if (found != NULL)
+ return found;
+ }
+
+ return NULL;
+}
+
+
+} // vmime
+