Added 'attachmentHelper'.
This commit is contained in:
parent
9b31891938
commit
a4161cf09d
@ -2,6 +2,11 @@
|
||||
VERSION 0.7.2cvs
|
||||
================
|
||||
|
||||
2005-10-13 Vincent Richard <vincent@vincent-richard.net>
|
||||
|
||||
* attachmentHelper.{hpp|cpp}: the attachmentHelper allows listing all
|
||||
attachments in a message, as well as adding new attachments.
|
||||
|
||||
2005-10-06 Vincent Richard <vincent@vincent-richard.net>
|
||||
|
||||
* utility/progressionListener.{hpp|cpp}: renamed 'progressionListener'
|
||||
|
@ -76,9 +76,11 @@ libvmime_sources = [
|
||||
'address.cpp', 'address.hpp',
|
||||
'addressList.cpp', 'addressList.hpp',
|
||||
'attachment.hpp',
|
||||
'attachmentHelper.cpp', 'attachmentHelper.hpp',
|
||||
'base.cpp', 'base.hpp',
|
||||
'body.cpp', 'body.hpp',
|
||||
'bodyPart.cpp', 'bodyPart.hpp',
|
||||
'bodyPartAttachment.cpp', 'bodyPartAttachment.hpp',
|
||||
'charset.cpp', 'charset.hpp',
|
||||
'component.cpp', 'component.hpp',
|
||||
'constants.cpp', 'constants.hpp',
|
||||
@ -327,6 +329,7 @@ libvmimetest_common = [
|
||||
libvmimetest_sources = [
|
||||
'tests/testRunner.cpp',
|
||||
# ============================== Parser ==============================
|
||||
'tests/parser/attachmentHelperTest.cpp',
|
||||
'tests/parser/bodyPartTest.cpp',
|
||||
'tests/parser/datetimeTest.cpp',
|
||||
'tests/parser/dispositionTest.cpp',
|
||||
|
201
src/attachmentHelper.cpp
Normal file
201
src/attachmentHelper.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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
|
||||
|
164
src/bodyPartAttachment.cpp
Normal file
164
src/bodyPartAttachment.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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/bodyPartAttachment.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
|
||||
|
||||
bodyPartAttachment::bodyPartAttachment(ref <const bodyPart> part)
|
||||
: m_part(part)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const mediaType bodyPartAttachment::getType() const
|
||||
{
|
||||
mediaType type;
|
||||
|
||||
try
|
||||
{
|
||||
type = getContentType()->getValue();
|
||||
}
|
||||
catch (exceptions::no_such_field&)
|
||||
{
|
||||
// No "Content-type" field: assume "application/octet-stream".
|
||||
type = mediaType(mediaTypes::APPLICATION,
|
||||
mediaTypes::APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
const word bodyPartAttachment::getName() const
|
||||
{
|
||||
word name;
|
||||
|
||||
// Try the 'filename' parameter of 'Content-Disposition' field
|
||||
try
|
||||
{
|
||||
name = getContentDisposition()->getFilename();
|
||||
}
|
||||
catch (exceptions::no_such_field&)
|
||||
{
|
||||
// No 'Content-Disposition' field
|
||||
}
|
||||
catch (exceptions::no_such_parameter&)
|
||||
{
|
||||
// No 'filename' parameter
|
||||
}
|
||||
|
||||
// Try the 'name' parameter of 'Content-Type' field
|
||||
if (name.getBuffer().empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
ref <defaultParameter> prm = getContentType()->
|
||||
findParameter("name").dynamicCast <defaultParameter>();
|
||||
|
||||
if (prm != NULL)
|
||||
name = prm->getValue();
|
||||
}
|
||||
catch (exceptions::no_such_field&)
|
||||
{
|
||||
// No 'Content-Type' field
|
||||
}
|
||||
catch (exceptions::no_such_parameter&)
|
||||
{
|
||||
// No attachment name available
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
const text bodyPartAttachment::getDescription() const
|
||||
{
|
||||
text description;
|
||||
|
||||
try
|
||||
{
|
||||
const textField& cd = dynamic_cast <textField&>
|
||||
(*getHeader()->findField(fields::CONTENT_DESCRIPTION));
|
||||
|
||||
description = cd.getValue();
|
||||
}
|
||||
catch (exceptions::no_such_field&)
|
||||
{
|
||||
// No description available.
|
||||
}
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
const encoding bodyPartAttachment::getEncoding() const
|
||||
{
|
||||
return m_part->getBody()->getEncoding();
|
||||
}
|
||||
|
||||
|
||||
const ref <const contentHandler> bodyPartAttachment::getData() const
|
||||
{
|
||||
return m_part->getBody()->getContents();
|
||||
}
|
||||
|
||||
|
||||
ref <const object> bodyPartAttachment::getPart() const
|
||||
{
|
||||
return m_part;
|
||||
}
|
||||
|
||||
|
||||
ref <const header> bodyPartAttachment::getHeader() const
|
||||
{
|
||||
return m_part->getHeader();
|
||||
}
|
||||
|
||||
|
||||
ref <const contentDispositionField> bodyPartAttachment::getContentDisposition() const
|
||||
{
|
||||
return getHeader()->findField(fields::CONTENT_DISPOSITION).
|
||||
dynamicCast <const contentDispositionField>();
|
||||
}
|
||||
|
||||
|
||||
ref <const contentTypeField> bodyPartAttachment::getContentType() const
|
||||
{
|
||||
return getHeader()->findField(fields::CONTENT_TYPE).
|
||||
dynamicCast <const contentTypeField>();
|
||||
}
|
||||
|
||||
|
||||
void bodyPartAttachment::generateIn(bodyPart& /* parent */) const
|
||||
{
|
||||
// Not used
|
||||
}
|
||||
|
||||
|
||||
} // vmime
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include "vmime/messageParser.hpp"
|
||||
|
||||
#include "vmime/attachmentHelper.hpp"
|
||||
|
||||
#include "vmime/defaultAttachment.hpp"
|
||||
#include "vmime/textPartFactory.hpp"
|
||||
|
||||
@ -33,14 +35,14 @@ namespace vmime
|
||||
|
||||
messageParser::messageParser(const string& buffer)
|
||||
{
|
||||
vmime::message msg;
|
||||
msg.parse(buffer);
|
||||
ref <message> msg = vmime::create <message>();
|
||||
msg->parse(buffer);
|
||||
|
||||
parse(msg);
|
||||
}
|
||||
|
||||
|
||||
messageParser::messageParser(const message& msg)
|
||||
messageParser::messageParser(ref <const message> msg)
|
||||
{
|
||||
parse(msg);
|
||||
}
|
||||
@ -51,13 +53,13 @@ messageParser::~messageParser()
|
||||
}
|
||||
|
||||
|
||||
void messageParser::parse(const message& msg)
|
||||
void messageParser::parse(ref <const message> msg)
|
||||
{
|
||||
// Header fields (if field is present, copy its value, else do nothing)
|
||||
#ifndef VMIME_BUILDING_DOC
|
||||
|
||||
#define TRY_FIELD(var, type, name) \
|
||||
try { var = dynamic_cast<type&>(*msg.getHeader()->findField(name)).getValue(); } \
|
||||
try { var = dynamic_cast<type&>(*msg->getHeader()->findField(name)).getValue(); } \
|
||||
catch (exceptions::no_such_field) { }
|
||||
|
||||
TRY_FIELD(m_from, mailboxField, fields::FROM);
|
||||
@ -76,7 +78,7 @@ void messageParser::parse(const message& msg)
|
||||
try
|
||||
{
|
||||
vmime::relayField& recv = dynamic_cast <vmime::relayField&>
|
||||
(*msg.getHeader()->findField(fields::RECEIVED));
|
||||
(*msg->getHeader()->findField(fields::RECEIVED));
|
||||
|
||||
m_date = recv.getValue().getDate();
|
||||
}
|
||||
@ -85,7 +87,7 @@ void messageParser::parse(const message& msg)
|
||||
try
|
||||
{
|
||||
vmime::dateField& date = dynamic_cast <vmime::dateField&>
|
||||
(*msg.getHeader()->findField(fields::DATE));
|
||||
(*msg->getHeader()->findField(fields::DATE));
|
||||
|
||||
m_date = date.getValue();
|
||||
}
|
||||
@ -99,151 +101,13 @@ void messageParser::parse(const message& msg)
|
||||
findAttachments(msg);
|
||||
|
||||
// Text parts
|
||||
findTextParts(msg, msg);
|
||||
findTextParts(*msg, *msg);
|
||||
}
|
||||
|
||||
|
||||
void messageParser::findAttachments(const bodyPart& part)
|
||||
void messageParser::findAttachments(ref <const message> msg)
|
||||
{
|
||||
// We simply search for parts that are not "Content-disposition: inline".
|
||||
for (int i = 0 ; i < part.getBody()->getPartCount() ; ++i)
|
||||
{
|
||||
const bodyPart& p = *part.getBody()->getPartAt(i);
|
||||
const header& hdr = *p.getHeader();
|
||||
const body& bdy = *p.getBody();
|
||||
|
||||
// Is this part an attachment?
|
||||
bool isAttachment = false;
|
||||
const contentDispositionField* contentDispField = NULL;
|
||||
|
||||
try
|
||||
{
|
||||
const contentDispositionField& cdf = dynamic_cast<contentDispositionField&>
|
||||
(*hdr.findField(fields::CONTENT_DISPOSITION));
|
||||
|
||||
if (cdf.getValue().getName() != contentDispositionTypes::INLINE)
|
||||
{
|
||||
contentDispField = &cdf;
|
||||
isAttachment = 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&>
|
||||
(*hdr.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)
|
||||
{
|
||||
isAttachment = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAttachment)
|
||||
{
|
||||
// Determine the media type of this attachment
|
||||
const contentTypeField* contTypeField = NULL;
|
||||
mediaType type;
|
||||
|
||||
try
|
||||
{
|
||||
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
|
||||
(*hdr.findField(fields::CONTENT_TYPE));
|
||||
|
||||
type = ctf.getValue();
|
||||
|
||||
contTypeField = &ctf;
|
||||
}
|
||||
catch (exceptions::no_such_field)
|
||||
{
|
||||
// No "Content-type" field: assume "application/octet-stream".
|
||||
type = mediaType(mediaTypes::APPLICATION,
|
||||
mediaTypes::APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
|
||||
// Get the description (if available)
|
||||
text description;
|
||||
|
||||
try
|
||||
{
|
||||
const textField& cd = dynamic_cast<textField&>
|
||||
(*hdr.findField(fields::CONTENT_DESCRIPTION));
|
||||
|
||||
description = cd.getValue();
|
||||
}
|
||||
catch (exceptions::no_such_field)
|
||||
{
|
||||
// No description available.
|
||||
}
|
||||
|
||||
// Get the name/filename (if available)
|
||||
word name;
|
||||
|
||||
// -- try the 'filename' parameter of 'Content-Disposition' field
|
||||
if (contentDispField != NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
name = contentDispField->getFilename();
|
||||
}
|
||||
catch (exceptions::no_such_parameter)
|
||||
{
|
||||
// No 'filename' parameter
|
||||
}
|
||||
}
|
||||
|
||||
// -- try the 'name' parameter of 'Content-Type' field
|
||||
if (name.getBuffer().empty() && contTypeField != NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
ref <defaultParameter> prm = contTypeField->
|
||||
findParameter("name").dynamicCast <defaultParameter>();
|
||||
|
||||
if (prm != NULL)
|
||||
name = prm->getValue();
|
||||
}
|
||||
catch (exceptions::no_such_parameter)
|
||||
{
|
||||
// No attachment name available.
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the attachment object
|
||||
ref <attachment> attach = vmime::create <defaultAttachment>
|
||||
(bdy.getContents()->clone().dynamicCast <contentHandler>(),
|
||||
bdy.getEncoding(), type, description, name);
|
||||
|
||||
if (contentDispField != NULL)
|
||||
{
|
||||
m_attachInfo.insert(std::map <attachment*, ref <contentDispositionField> >::
|
||||
value_type(attach.get(), contentDispField->clone().
|
||||
dynamicCast <contentDispositionField>()));
|
||||
}
|
||||
|
||||
// Add the attachment to the list
|
||||
m_attach.push_back(attach);
|
||||
}
|
||||
|
||||
// Try to find attachments in sub-parts
|
||||
if (bdy.getPartCount())
|
||||
findAttachments(p);
|
||||
}
|
||||
m_attach = attachmentHelper::findAttachmentsInMessage(msg);
|
||||
}
|
||||
|
||||
|
||||
@ -357,15 +221,6 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part)
|
||||
}
|
||||
|
||||
|
||||
const ref <const contentDispositionField> messageParser::getAttachmentInfo(const ref <const attachment> a) const
|
||||
{
|
||||
std::map <attachment*, ref <contentDispositionField> >::const_iterator
|
||||
it = m_attachInfo.find(ref <attachment>(a.constCast <attachment>()).get());
|
||||
|
||||
return (it != m_attachInfo.end() ? (*it).second : NULL);
|
||||
}
|
||||
|
||||
|
||||
const mailbox& messageParser::getExpeditor() const
|
||||
{
|
||||
return (m_from);
|
||||
@ -404,17 +259,7 @@ const datetime& messageParser::getDate() const
|
||||
|
||||
const std::vector <ref <const attachment> > messageParser::getAttachmentList() const
|
||||
{
|
||||
std::vector <ref <const attachment> > res;
|
||||
|
||||
res.reserve(m_attach.size());
|
||||
|
||||
for (std::vector <ref <attachment> >::const_iterator it = m_attach.begin() ;
|
||||
it != m_attach.end() ; ++it)
|
||||
{
|
||||
res.push_back(*it);
|
||||
}
|
||||
|
||||
return (res);
|
||||
return m_attach;
|
||||
}
|
||||
|
||||
|
||||
|
113
tests/parser/attachmentHelperTest.cpp
Normal file
113
tests/parser/attachmentHelperTest.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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 "tests/testUtils.hpp"
|
||||
|
||||
|
||||
#define VMIME_TEST_SUITE attachmentHelperTest
|
||||
#define VMIME_TEST_SUITE_MODULE "Parser"
|
||||
|
||||
|
||||
VMIME_TEST_SUITE_BEGIN
|
||||
|
||||
VMIME_TEST_LIST_BEGIN
|
||||
VMIME_TEST(testAddAttachment1)
|
||||
VMIME_TEST(testAddAttachment2)
|
||||
// TODO: add more tests
|
||||
VMIME_TEST_LIST_END
|
||||
|
||||
|
||||
static const vmime::string getStructure(vmime::ref <vmime::bodyPart> part)
|
||||
{
|
||||
vmime::ref <vmime::body> bdy = part->getBody();
|
||||
|
||||
vmime::string res = part->getBody()->getContentType().generate();
|
||||
|
||||
if (bdy->getPartCount() == 0)
|
||||
return res;
|
||||
|
||||
res += "[";
|
||||
|
||||
for (int i = 0 ; i < bdy->getPartCount() ; ++i)
|
||||
{
|
||||
vmime::ref <vmime::bodyPart> subPart = bdy->getPartAt(i);
|
||||
|
||||
if (i != 0)
|
||||
res += ",";
|
||||
|
||||
res += getStructure(subPart);
|
||||
}
|
||||
|
||||
return res + "]";
|
||||
}
|
||||
|
||||
void testAddAttachment1()
|
||||
{
|
||||
vmime::string data =
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"The text\r\n"
|
||||
"";
|
||||
|
||||
vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
|
||||
msg->parse(data);
|
||||
|
||||
vmime::ref <vmime::attachment> att = vmime::create <vmime::defaultAttachment>
|
||||
(vmime::create <vmime::stringContentHandler>("test"),
|
||||
vmime::mediaType("image/jpeg"));
|
||||
|
||||
vmime::attachmentHelper::addAttachment(msg, att);
|
||||
|
||||
VASSERT_EQ("1", "multipart/mixed[text/plain,image/jpeg]", getStructure(msg));
|
||||
}
|
||||
|
||||
void testAddAttachment2()
|
||||
{
|
||||
vmime::string data =
|
||||
"Content-Type: multipart/mixed; boundary=\"foo\"\r\n"
|
||||
"\r\n"
|
||||
"--foo\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"The text\r\n"
|
||||
"--foo\r\n"
|
||||
"Content-Type: application/octet-stream\r\n"
|
||||
"\r\n"
|
||||
"Blah\r\n"
|
||||
"--foo--\r\n"
|
||||
"";
|
||||
|
||||
vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
|
||||
msg->parse(data);
|
||||
|
||||
vmime::ref <vmime::attachment> att = vmime::create <vmime::defaultAttachment>
|
||||
(vmime::create <vmime::stringContentHandler>("test"),
|
||||
vmime::mediaType("image/jpeg"));
|
||||
|
||||
vmime::attachmentHelper::addAttachment(msg, att);
|
||||
|
||||
VASSERT_EQ("1", "multipart/mixed[text/plain,application/octet-stream,image/jpeg]", getStructure(msg));
|
||||
}
|
||||
|
||||
VMIME_TEST_SUITE_END
|
||||
|
@ -45,6 +45,7 @@ class attachment : public object
|
||||
{
|
||||
friend class messageBuilder;
|
||||
friend class messageParser;
|
||||
friend class attachmentHelper;
|
||||
|
||||
protected:
|
||||
|
||||
|
95
vmime/attachmentHelper.hpp
Normal file
95
vmime/attachmentHelper.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef VMIME_ATTACHMENTHELPER_HPP_INCLUDED
|
||||
#define VMIME_ATTACHMENTHELPER_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
|
||||
#include "vmime/attachment.hpp"
|
||||
#include "vmime/message.hpp"
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||
#include "vmime/net/message.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
|
||||
|
||||
/** Retrieve attachment information from message parts.
|
||||
*/
|
||||
class attachmentHelper
|
||||
{
|
||||
public:
|
||||
|
||||
/** Test whether a body part is an attachment.
|
||||
*
|
||||
* @param part message part to test
|
||||
* @return true if the part is an attachment, false otherwise
|
||||
*/
|
||||
static const bool isBodyPartAnAttachment(ref <const bodyPart> part);
|
||||
|
||||
/** 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
|
||||
* @return a list of attachments found
|
||||
*/
|
||||
static ref <const attachment>
|
||||
getBodyPartAttachment(ref <const bodyPart> part);
|
||||
|
||||
/** Find all attachments contained in the specified message.
|
||||
* This is simply a recursive call to getBodyPartAttachment().
|
||||
*
|
||||
* @param msg message in which to search
|
||||
* @return a list of attachments found
|
||||
*/
|
||||
static const std::vector <ref <const attachment> >
|
||||
findAttachmentsInMessage(ref <const message> msg);
|
||||
|
||||
/** Add an attachment to the specified message.
|
||||
*
|
||||
* @param msg message into which to add the attachment
|
||||
* @param att attachment to add
|
||||
*/
|
||||
static void addAttachment(ref <message> msg, ref <attachment> att);
|
||||
|
||||
protected:
|
||||
|
||||
static const std::vector <ref <const attachment> >
|
||||
findAttachmentsInBodyPart(ref <const bodyPart> part);
|
||||
|
||||
static ref <bodyPart> findBodyPart
|
||||
(ref <bodyPart> part, const mediaType& type);
|
||||
};
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_ATTACHMENTHELPER_HPP_INCLUDED
|
||||
|
73
vmime/bodyPartAttachment.hpp
Normal file
73
vmime/bodyPartAttachment.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef VMIME_BODYPARTATTACHMENT_HPP_INCLUDED
|
||||
#define VMIME_BODYPARTATTACHMENT_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/attachment.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
|
||||
|
||||
/** An attachment related to a local body part.
|
||||
*/
|
||||
class bodyPartAttachment : public attachment
|
||||
{
|
||||
friend class creator;
|
||||
|
||||
protected:
|
||||
|
||||
bodyPartAttachment(ref <const bodyPart> part);
|
||||
|
||||
public:
|
||||
|
||||
const mediaType getType() const;
|
||||
const word getName() const;
|
||||
const text getDescription() const;
|
||||
const encoding getEncoding() const;
|
||||
|
||||
const ref <const contentHandler> getData() const;
|
||||
|
||||
ref <const object> getPart() const;
|
||||
ref <const header> getHeader() const;
|
||||
|
||||
private:
|
||||
|
||||
void generateIn(bodyPart& parent) const;
|
||||
|
||||
ref <const contentDispositionField> getContentDisposition() const;
|
||||
ref <const contentTypeField> getContentType() const;
|
||||
|
||||
|
||||
ref <const bodyPart> m_part;
|
||||
};
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_BODYPARTATTACHMENT_HPP_INCLUDED
|
||||
|
@ -45,7 +45,7 @@ class messageParser
|
||||
public:
|
||||
|
||||
messageParser(const string& buffer);
|
||||
messageParser(const message& msg);
|
||||
messageParser(ref <const message> msg);
|
||||
~messageParser();
|
||||
|
||||
public:
|
||||
@ -105,13 +105,6 @@ public:
|
||||
*/
|
||||
const std::vector <ref <const attachment> > getAttachmentList() const;
|
||||
|
||||
/** Return information about the specified attachment.
|
||||
*
|
||||
* @param a attachment to retrieve information about
|
||||
* @return information about the specified attachment
|
||||
*/
|
||||
const ref <const contentDispositionField> getAttachmentInfo(const ref <const attachment> a) const;
|
||||
|
||||
/** Return the text parts of the message.
|
||||
*
|
||||
* @return list of text parts in the message
|
||||
@ -143,14 +136,13 @@ private:
|
||||
|
||||
datetime m_date;
|
||||
|
||||
std::vector <ref <attachment> > m_attach;
|
||||
std::map <attachment*, ref <contentDispositionField> > m_attachInfo;
|
||||
std::vector <ref <const attachment> > m_attach;
|
||||
|
||||
std::vector <ref <textPart> > m_textParts;
|
||||
|
||||
void parse(const message& msg);
|
||||
void parse(ref <const message> msg);
|
||||
|
||||
void findAttachments(const bodyPart& part);
|
||||
void findAttachments(ref <const message> msg);
|
||||
|
||||
void findTextParts(const bodyPart& msg, const bodyPart& part);
|
||||
bool findSubTextParts(const bodyPart& msg, const bodyPart& part);
|
||||
|
@ -77,6 +77,8 @@
|
||||
#include "vmime/plainTextPart.hpp"
|
||||
#include "vmime/htmlTextPart.hpp"
|
||||
|
||||
#include "vmime/attachmentHelper.hpp"
|
||||
|
||||
// MDN
|
||||
#include "vmime/mdn/MDNHelper.hpp"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user