Refactoring (see ChangeLog).

This commit is contained in:
Vincent Richard 2004-10-21 15:05:47 +00:00
parent 6f7f1674f7
commit 2949fb51f1
183 changed files with 6505 additions and 5365 deletions

View File

@ -1,7 +1,46 @@
VERSION 0.5.2-CVS
VERSION 0.6.0-cvs
=================
2004-10-21 Vincent Richard <vincent@vincent-richard.net>
* A _LOT_ of cleaning/refactoring in VMime code:
- got rid of field types (only using field names now).
- removed iterators on 'header', 'text', 'addressList', 'mailboxGroup',
'propertySet' and 'bodyPart': use access functions instead (iterators
made the code difficult to understand). You can always use standard
iterators on the container returned by getFieldList(), and so on.
- migrated to get/set convention for accessors (most of time, just add
'get' or 'set' before method name, depending on what it does).
- dropped 'comp_t' typedef on 'datetime' (useless).
- moved a lot of code from header (.hpp) to implementation files (.cpp).
- made all objects cloneable and copiable at the 'component' level:
methods component::clone() and component::copyFrom().
- made a 'typeAdapter' to allow using fondamental/no-vmime types in
header field and parameter values.
- implicit 'operator=' on header fields to set value is not allowed
anymore: use setValue() instead or you will get a std::bad_cast
exception.
- 'textParameter' renamed to 'defaultParameter'.
- vmime::makeWordsFromText() is now vmime::text::newFromString().
- changed a lot of return type value from reference to pointer, to
to avoid confusion.
2004-10-05 Vincent Richard <vincent@vincent-richard.net>
* added clone() method on 'component' object.
2004-09-09 Vincent Richard <vincent@vincent-richard.net>
* IMAPFolder.cpp: fixed rename(): folder name is now updated.

View File

@ -28,26 +28,18 @@ import string
libvmime_sources = [
'address.cpp', 'address.hpp',
'addressList.cpp', 'addressList.hpp',
'addressListField.cpp', 'addressListField.hpp',
'attachment.hpp',
'base.cpp', 'base.hpp',
'body.cpp', 'body.hpp',
'bodyPart.cpp', 'bodyPart.hpp',
'charset.cpp', 'charset.hpp',
'charsetParameter.cpp', 'charsetParameter.hpp',
'component.cpp', 'component.hpp',
'constants.cpp', 'constants.hpp',
'contentDispositionField.cpp', 'contentDispositionField.hpp',
'contentEncodingField.cpp', 'contentEncodingField.hpp',
'contentHandler.cpp', 'contentHandler.hpp',
'contentTypeField.cpp', 'contentTypeField.hpp',
'dateField.cpp', 'dateField.hpp',
'dateParameter.cpp', 'dateParameter.hpp',
'dateTime.cpp', 'dateTime.hpp',
'defaultAttachment.cpp', 'defaultAttachment.hpp',
'defaultField.cpp', 'defaultField.hpp',
'defaultParameter.cpp', 'defaultParameter.hpp',
'defaultParameterizedHeaderField.cpp', 'defaultParameterizedHeaderField.hpp',
'disposition.cpp', 'disposition.hpp',
'encoder.cpp', 'encoder.hpp',
'encoder7bit.cpp', 'encoder7bit.hpp',
@ -61,6 +53,8 @@ libvmime_sources = [
'encoding.cpp', 'encoding.hpp',
'exception.hpp',
'fileAttachment.cpp', 'fileAttachment.hpp',
'genericField.hpp',
'genericParameter.hpp',
'header.cpp', 'header.hpp',
'headerFieldFactory.cpp', 'headerFieldFactory.hpp',
'headerField.cpp', 'headerField.hpp',
@ -69,12 +63,10 @@ libvmime_sources = [
'mailboxField.cpp', 'mailboxField.hpp',
'mailboxGroup.cpp', 'mailboxGroup.hpp',
'mailboxList.cpp', 'mailboxList.hpp',
'mailboxListField.cpp', 'mailboxListField.hpp',
'mediaType.cpp', 'mediaType.hpp',
'messageBuilder.cpp', 'messageBuilder.hpp',
'message.cpp', 'message.hpp',
'messageId.cpp', 'messageId.hpp',
'messageIdField.cpp', 'messageIdField.hpp',
'messageParser.cpp', 'messageParser.hpp',
'options.cpp', 'options.hpp',
'parameter.cpp', 'parameter.hpp',
@ -84,12 +76,13 @@ libvmime_sources = [
'plainTextPart.cpp', 'plainTextPart.hpp',
'platformDependant.cpp', 'platformDependant.hpp',
'propertySet.cpp', 'propertySet.hpp',
'relayField.cpp', 'relayField.hpp',
'relay.cpp', 'relay.hpp',
'standardFields.hpp',
'standardParams.hpp',
'text.cpp', 'text.hpp',
'textField.cpp', 'textField.hpp',
'textParameter.cpp', 'textParameter.hpp',
'textPartFactory.cpp', 'textPartFactory.hpp',
'textPart.hpp',
'typeAdapter.hpp',
'types.hpp',
'word.cpp', 'word.hpp',
'vmime',
@ -100,7 +93,8 @@ libvmime_sources = [
'utility/singleton.cpp', 'utility/singleton.hpp',
'utility/smartPtr.hpp',
'utility/stream.cpp', 'utility/stream.hpp',
'utility/stringProxy.cpp', 'utility/stringProxy.hpp'
'utility/stringProxy.cpp', 'utility/stringProxy.hpp',
'utility/stringUtils.cpp', 'utility/stringUtils.hpp'
]
libvmime_examples_sources = [

View File

@ -1 +1 @@
0.5.2
0.6.0

View File

@ -257,7 +257,7 @@ public:
gmt.tm_isdst = -1;
// Calculate the difference (in seconds)
const vmime::datetime::comp_t diff = ::std::mktime(&local) - ::std::mktime(&gmt);
const int diff = ::std::mktime(&local) - ::std::mktime(&gmt);
// Return the date
return vmime::datetime(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,

View File

@ -45,14 +45,24 @@ int main()
vmime::messageBuilder mb;
// Fill in the basic fields
mb.expeditor() = vmime::mailbox("me@somewhere.com");
mb.recipients().append(vmime::mailbox("you@elsewhere.com"));
mb.blindCopyRecipients().append(vmime::mailbox("you-bcc@nowhere.com"));
mb.subject() = vmime::text("My first message generated with vmime::messageBuilder");
mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
vmime::addressList to;
to.appendAddress(new vmime::mailbox("you@elsewhere.com"));
mb.setRecipients(to);
vmime::addressList bcc;
bcc.appendAddress(new vmime::mailbox("you-bcc@nowhere.com"));
mb.setBlindCopyRecipients(bcc);
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
// Message body
mb.textPart().text() = "I'm writing this short text to test message construction " \
"using the vmime::messageBuilder component.";
mb.getTextPart()->setText(vmime::contentHandler(
"I'm writing this short text to test message construction " \
"using the vmime::messageBuilder component."));
// Construction
vmime::message* msg = mb.construct();
@ -61,7 +71,7 @@ int main()
std::cout << "Generated message:" << std::endl;
std::cout << "==================" << std::endl;
vmime::outputStreamAdapter out(std::cout);
vmime::utility::outputStreamAdapter out(std::cout);
msg->generate(out);
// Destruction
@ -77,7 +87,7 @@ int main()
catch (std::exception& e)
{
std::cout << "std::exception: " << e.what() << std::endl;
throw;
//throw;
}
std::cout << std::endl;

View File

@ -45,14 +45,24 @@ int main()
vmime::messageBuilder mb;
// Fill in the basic fields
mb.expeditor() = vmime::mailbox("me@somewhere.com");
mb.recipients().append(vmime::mailbox("you@elsewhere.com"));
mb.blindCopyRecipients().append(vmime::mailbox("you-bcc@nowhere.com"));
mb.subject() = vmime::text("My first message generated with vmime::messageBuilder");
mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
vmime::addressList to;
to.appendAddress(new vmime::mailbox("you@elsewhere.com"));
mb.setRecipients(to);
vmime::addressList bcc;
bcc.appendAddress(new vmime::mailbox("you-bcc@nowhere.com"));
mb.setBlindCopyRecipients(bcc);
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
// Message body
mb.textPart().text() = "I'm writing this short text to test message construction " \
"with attachment, using the vmime::messageBuilder component.";
mb.getTextPart()->setText(vmime::contentHandler(
"I'm writing this short text to test message construction " \
"with attachment, using the vmime::messageBuilder component."));
// Adding an attachment
vmime::fileAttachment* a = new vmime::fileAttachment
@ -62,8 +72,8 @@ int main()
vmime::text("My first attachment") // description
);
a->fileInfo().setFilename("example2.cpp");
a->fileInfo().setCreationDate(vmime::datetime("30 Apr 2003 14:30:00 +0200"));
a->getFileInfo().setFilename("example2.cpp");
a->getFileInfo().setCreationDate(vmime::datetime("30 Apr 2003 14:30:00 +0200"));
mb.attach(a);

View File

@ -45,10 +45,19 @@ int main()
vmime::messageBuilder mb;
// Fill in the basic fields
mb.expeditor() = vmime::mailbox("me@somewhere.com");
mb.recipients().append(vmime::mailbox("you@elsewhere.com"));
mb.blindCopyRecipients().append(vmime::mailbox("you-bcc@nowhere.com"));
mb.subject() = vmime::text("My first message generated with vmime::messageBuilder");
mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
vmime::addressList to;
to.appendAddress(new vmime::mailbox("you@elsewhere.com"));
mb.setRecipients(to);
vmime::addressList bcc;
bcc.appendAddress(new vmime::mailbox("you-bcc@nowhere.com"));
mb.setBlindCopyRecipients(bcc);
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
// Set the content-type to "text/html"
mb.constructTextPart(vmime::mediaType
@ -56,16 +65,16 @@ int main()
// Fill in the text part: the message is available in two formats: HTML and plain text.
// HTML text part also includes an inline image (embedded into the message).
vmime::htmlTextPart& textPart = dynamic_cast<vmime::htmlTextPart&>(mb.textPart());
vmime::htmlTextPart& textPart = dynamic_cast<vmime::htmlTextPart&>(*mb.getTextPart());
// -- embed an image (the returned "CID" (content identifier) is used to reference
// -- the image into HTML content).
vmime::string cid = textPart.embeddedObjects.add("<...IMAGE DATA...>",
vmime::string cid = textPart.addObject("<...IMAGE DATA...>",
vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
// -- message text
textPart.text() = vmime::string("This is the <b>HTML text</b>.<br/><img src=\"") + cid + vmime::string("\"/>");
textPart.plainText() = vmime::string("This is the plain text (without HTML formatting).");
textPart.setText(vmime::contentHandler(vmime::string("This is the <b>HTML text</b>.<br/><img src=\"") + cid + vmime::string("\"/>")));
textPart.setPlainText(vmime::contentHandler(vmime::string("This is the plain text (without HTML formatting).")));
// Construction
vmime::message* msg = mb.construct();

View File

@ -44,28 +44,28 @@ int main()
vmime::messageParser mp("<...MIME message content...>");
// Enumerate text parts
for (std::vector <vmime::textPart*>::const_iterator i = mp.textParts().begin() ;
i != mp.textParts().end() ; ++i)
for (int i = 0 ; i < mp.getTextPartCount() ; ++i)
{
const vmime::textPart& part = **i;
const vmime::textPart& part = *mp.getTextPartAt(i);
// Output content-type of the part
std::cout << part.type().generate() << std::endl;
std::cout << part.getType().generate() << std::endl;
// text/html
if (part.type().subType() == vmime::mediaTypes::TEXT_HTML)
if (part.getType().getSubType() == vmime::mediaTypes::TEXT_HTML)
{
const vmime::htmlTextPart& hp = dynamic_cast<const vmime::htmlTextPart&>(part);
// HTML text is in "hp.text()"
// Corresponding plain text is in "hp.plainText()"
// HTML text is in "hp.getText()"
// Corresponding plain text is in "hp.getPlainText()"
// Enumerate embedded objects (eg. images)
for (vmime::htmlTextPart::const_iterator i = hp.embeddedObjects.begin() ;
i != hp.embeddedObjects.end() ; ++i)
for (int j = 0 ; j < hp.getObjectCount() ; ++j)
{
// Identifier (content-id or content-location) is in "(*i).id()"
// Object data is in "(*i).data()"
const vmime::htmlTextPart::embeddedObject& obj = *hp.getObjectAt(j);
// Identifier (content-id or content-location) is in "obj.getId()"
// Object data is in "obj.getData()"
}
}
// text/plain
@ -73,7 +73,7 @@ int main()
{
const vmime::textPart& tp = dynamic_cast<const vmime::textPart&>(part);
// Text is in "tp.text()"
// Text is in "tp.getText()"
}
}
}

View File

@ -45,12 +45,13 @@ int main()
vmime::messageParser mp("<...MIME message content...>");
// Enumerate attachments
for (std::vector <vmime::attachment*>::const_iterator i = mp.attachments().begin() ;
i != mp.attachments().end() ; ++i)
for (int i = 0 ; i < mp.getAttachmentCount() ; ++i)
{
// Media type (content type) is in "(*i).type()"
// Description is in "(*i).description()"
// Data is in "(*i).data()"
const vmime::attachment& att = *mp.getAttachmentAt(i);
// Media type (content type) is in "att.getType()"
// Description is in "att.getDescription()"
// Data is in "att.getData()"
}
}
// VMime exception

View File

@ -49,19 +49,19 @@ class my_auth : public vmime::messaging::authenticator
void printStructure(const vmime::messaging::structure& s, int level = 0)
{
for (int i = 1 ; i <= s.count() ; ++i)
for (int i = 1 ; i <= s.getCount() ; ++i)
{
const vmime::messaging::part& part = s[i];
for (int j = 0 ; j < level * 2 ; ++j)
std::cout << " ";
std::cout << part.number() << ". "
<< part.type().generate()
<< " [" << part.size() << " byte(s)]"
std::cout << part.getNumber() << ". "
<< part.getType().generate()
<< " [" << part.getSize() << " byte(s)]"
<< std::endl;
printStructure(part.structure(), level + 1);
printStructure(part.getStructure(), level + 1);
}
}
@ -76,22 +76,23 @@ int main()
// Test the new enumeration system for encoders
//
#if 0
#if 1
vmime::encoderFactory* ef = vmime::encoderFactory::getInstance();
std::cout << "Available encoders:" << std::endl;
for (vmime::encoderFactory::iterator it = ef->begin() ;
it != ef->end() ; ++it)
for (int i = 0 ; i < ef->getEncoderCount() ; ++i)
{
std::cout << " * " << (*it).name() << std::endl;
const vmime::encoderFactory::registeredEncoder& enc = *ef->getEncoderAt(i);
vmime::encoder* e = (*it).create();
std::cout << " * " << enc.getName() << std::endl;
std::vector <vmime::string> props = e->availableProperties();
vmime::encoder* e = enc.create();
for (std::vector <vmime::string>::const_iterator it2 = props.begin() ; it2 != props.end() ; ++it2)
std::cout << " - " << *it2 << std::endl;
std::vector <vmime::string> props = e->getAvailableProperties();
for (std::vector <vmime::string>::const_iterator it = props.begin() ; it != props.end() ; ++it)
std::cout << " - " << *it << std::endl;
delete (e);
}
@ -108,21 +109,22 @@ int main()
std::cout << "Available messaging services:" << std::endl;
for (vmime::messaging::serviceFactory::const_iterator it = sf->begin() ;
it != sf->end() ; ++it)
for (int i = 0 ; i < sf->getServiceCount() ; ++i)
{
std::cout << " * " << (*it).name() << " (" << (*it).infos().defaultPort() << ")" << std::endl;
const vmime::messaging::serviceFactory::registeredService& serv = *sf->getServiceAt(i);
std::vector <vmime::string> props = (*it).infos().availableProperties();
std::cout << " * " << serv.getName() << " (" << serv.getInfos().getDefaultPort() << ")" << std::endl;
for (std::vector <vmime::string>::const_iterator it2 = props.begin() ; it2 != props.end() ; ++it2)
std::cout << " - " << (*it).infos().propertyPrefix() + *it2 << std::endl;
std::vector <vmime::string> props = serv.getInfos().getAvailableProperties();
for (std::vector <vmime::string>::const_iterator it = props.begin() ; it != props.end() ; ++it)
std::cout << " - " << serv.getInfos().getPropertyPrefix() + *it << std::endl;
}
#endif
vmime::messaging::session sess;
sess.properties()["store.protocol"] = "imap";
sess.properties()["transport.protocol"] = "smtp";
sess.getProperties()["store.protocol"] = "imap";
sess.getProperties()["transport.protocol"] = "smtp";
my_auth auth;
@ -136,12 +138,12 @@ int main()
// Transport protocol configuration
vmime::messaging::transport* tr = sess.getTransport();
//sess.properties()[tr->infos().propertyPrefix() + "auth.username"] = "username";
//sess.properties()[tr->infos().propertyPrefix() + "auth.password"] = "password";
//sess.getProperties()[tr->getInfos().getPropertyPrefix() + "auth.username"] = "username";
//sess.getProperties()[tr->getInfos().getPropertyPrefix() + "auth.password"] = "password";
sess.properties()[tr->infos().propertyPrefix() + "server.address"] = "smtp.mydomain.com";
sess.getProperties()[tr->getInfos().getPropertyPrefix() + "server.address"] = "smtp.mydomain.com";
//sess.properties()[tr->infos().propertyPrefix() + "options.need-authentification"] = true;
//sess.getProperties()[tr->getInfos().getPropertyPrefix() + "options.need-authentification"] = true;
// Connection
tr->connect();
@ -151,8 +153,8 @@ int main()
// Recipients list
vmime::mailboxList to;
to.append(vmime::mailbox("you@somewhere.com"));
to.append(vmime::mailbox("somebody.else@anywhere.com"));
to.appendMailbox(new vmime::mailbox("you@somewhere.com"));
to.appendMailbox(new vmime::mailbox("somebody.else@anywhere.com"));
std::istringstream iss("[MESSAGE DATA: HEADER + BODY]");
tr->send(from, to, iss);
@ -176,15 +178,15 @@ int main()
vmime::messaging::store* st = sess.getStore(&auth);
// Store protocol configuration
//sess.properties()[st->infos().propertyPrefix() + "auth.username"] = "username";
//sess.properties()[st->infos().propertyPrefix() + "auth.password"] = "password";
//sess.getProperties()[st->getInfos().getPropertyPrefix() + "auth.username"] = "username";
//sess.getProperties()[st->getInfos().getPropertyPrefix() + "auth.password"] = "password";
sess.properties()[st->infos().propertyPrefix() + "server.address"] = "imap.mydomain.com";
//sess.properties()[st->infos().propertyPrefix() + "server.port"] = 110;
//sess.properties()[st->infos().propertyPrefix() + "server.socket-factory"] = "default";
sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.address"] = "imap.mydomain.com";
//sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.port"] = 110;
//sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.socket-factory"] = "default";
//sess.properties()[st->infos().propertyPrefix() + "options.apop"] = false;
//sess.properties()[st->infos().propertyPrefix() + "options.apop.fallback"] = true;
//sess.getProperties()[st->getInfos().getPropertyPrefix() + "options.apop"] = false;
//sess.getProperties()[st->getInfos().getPropertyPrefix() + "options.apop.fallback"] = true;
// Connection
st->connect();
@ -205,7 +207,7 @@ int main()
// To retrieve the whole message
std::ostringstream oss;
vmime::outputStreamAdapter out(oss);
vmime::utility::outputStreamAdapter out(oss);
m->extract(out);
@ -223,55 +225,55 @@ int main()
std::cout << "STRUCTURE:" << std::endl;
std::cout << "==========" << std::endl;
printStructure(m->structure());
printStructure(m->getStructure());
std::cout << std::endl;
std::cout << "Size = " << m->size() << " byte(s)" << std::endl;
std::cout << "UID = " << m->uniqueId() << std::endl;
std::cout << "Size = " << m->getSize() << " byte(s)" << std::endl;
std::cout << "UID = " << m->getUniqueId() << std::endl;
std::cout << std::endl;
std::cout << "ENVELOPE:" << std::endl;
std::cout << "=========" << std::endl;
try { std::cout << m->header().fields.From().generate() << std::endl; } catch (...) { }
try { std::cout << m->header().fields.To().generate() << std::endl; } catch (...) { }
try { std::cout << m->header().fields.Date().generate() << std::endl; } catch (...) { }
try { std::cout << m->header().fields.Subject().generate() << std::endl; } catch (...) { }
try { std::cout << m->getHeader().From().generate() << std::endl; } catch (...) { }
try { std::cout << m->getHeader().To().generate() << std::endl; } catch (...) { }
try { std::cout << m->getHeader().Date().generate() << std::endl; } catch (...) { }
try { std::cout << m->getHeader().Subject().generate() << std::endl; } catch (...) { }
std::cout << std::endl;
std::cout << "FULL HEADER:" << std::endl;
std::cout << "============" << std::endl;
std::cout << m->header().generate() << std::endl;
std::cout << m->getHeader().generate() << std::endl;
std::cout << std::endl;
std::cout << "=========================================================" << std::endl;
vmime::outputStreamAdapter out2(std::cout);
m->extractPart(m->structure()[1][2][1], out2, NULL); //, 0, 10);
vmime::utility::outputStreamAdapter out2(std::cout);
m->extractPart(m->getStructure()[1][2][1], out2, NULL); //, 0, 10);
std::cout << "=========================================================" << std::endl;
std::cout << std::endl;
std::cout << "=========================================================" << std::endl;
m->fetchPartHeader(m->structure()[1][2][1]);
m->fetchPartHeader(m->getStructure()[1][2][1]);
std::cout << m->structure()[1][2][1].header().generate() << std::endl;
std::cout << m->getStructure()[1][2][1].getHeader().generate() << std::endl;
std::cout << "=========================================================" << std::endl;
// Flags manipulation
std::cout << "Flags = " << m->flags() << std::endl;
std::cout << "Flags = " << m->getFlags() << std::endl;
m->setFlags(vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_ADD);
std::cout << "Flags = " << m->flags() << std::endl;
std::cout << "Flags = " << m->getFlags() << std::endl;
m->setFlags(vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_REMOVE);
std::cout << "Flags = " << m->flags() << std::endl;
std::cout << "Flags = " << m->getFlags() << std::endl;
f->setMessageFlags(m->number(), m->number(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_ADD);
std::cout << "Flags = " << m->flags() << std::endl;
f->setMessageFlags(m->number(), m->number(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_REMOVE);
std::cout << "Flags = " << m->flags() << std::endl;
f->setMessageFlags(m->getNumber(), m->getNumber(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_ADD);
std::cout << "Flags = " << m->getFlags() << std::endl;
f->setMessageFlags(m->getNumber(), m->getNumber(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_REMOVE);
std::cout << "Flags = " << m->getFlags() << std::endl;
std::cout << "=========================================================" << std::endl;
@ -312,7 +314,7 @@ int main()
if (!g->exists())
g->create(vmime::messaging::folder::TYPE_CONTAINS_MESSAGES);
f->copyMessages(g->fullPath());
f->copyMessages(g->getFullPath());
delete (g);
}

View File

@ -191,11 +191,4 @@ address* address::parseNext(const string& buffer, const string::size_type positi
}
address& address::operator=(const address& addr)
{
copyFrom(addr);
return (*this);
}
} // vmime

View File

@ -45,33 +45,13 @@ protected:
public:
/** Copy data from another object to this object.
* Both objects must be the same type.
*
* @param addr other object
*/
address& operator=(const address& addr);
/** Duplicate this object.
*
* @return a copy of this object
*/
virtual address* clone() const = 0;
/** Copy data from another object to this object.
* Both objects must be the same type.
*
* @param addr other object
*/
virtual void copyFrom(const address& addr) = 0;
/** Check whether this address is empty (no mailboxes specified
* if this is a mailboxGroup -or- no email specified if this is
* a mailbox).
*
* @return true if this address is empty
*/
virtual const bool empty() const = 0;
virtual const bool isEmpty() const = 0;
/** Test whether this is object is a mailboxGroup.
*
@ -79,6 +59,8 @@ public:
*/
virtual const bool isGroup() const = 0;
virtual address* clone() const = 0;
protected:
/** Parse an address from an input buffer.

View File

@ -19,6 +19,8 @@
#include "addressList.hpp"
#include "parserHelpers.hpp"
#include "exception.hpp"
#include "mailboxList.hpp"
namespace vmime
@ -30,23 +32,23 @@ addressList::addressList()
}
addressList::addressList(const class addressList& addressList)
addressList::addressList(const addressList& addrList)
: component()
{
copyFrom(addressList);
copyFrom(addrList);
}
addressList::~addressList()
{
clear();
removeAllAddresses();
}
void addressList::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
clear();
removeAllAddresses();
string::size_type pos = position;
@ -69,11 +71,11 @@ void addressList::generate(utility::outputStream& os, const string::size_type ma
if (!m_list.empty())
{
string::size_type pos = curLinePos;
const_iterator i = m_list.begin();
std::vector <address*>::const_iterator i = m_list.begin();
for ( ; ; )
{
(*i).generate(os, maxLineLength - 2, pos, &pos);
(*i)->generate(os, maxLineLength - 2, pos, &pos);
if (++i != m_list.end())
{
@ -92,97 +94,158 @@ void addressList::generate(utility::outputStream& os, const string::size_type ma
}
/** Return the number of addresses in the list.
*
* @return number of addresses in the list
*/
const std::vector <address*>::size_type addressList::size() const
void addressList::copyFrom(const component& other)
{
return (m_list.size());
const addressList& addrList = dynamic_cast <const addressList&>(other);
removeAllAddresses();
for (std::vector <address*>::const_iterator it = addrList.m_list.begin() ;
it != addrList.m_list.end() ; ++it)
{
m_list.push_back(static_cast <address*>((*it)->clone()));
}
}
/** Return the number of addresses in the list.
*
* @return number of addresses in the list
*/
const std::vector <address*>::size_type addressList::count() const
addressList& addressList::operator=(const addressList& other)
{
return (m_list.size());
copyFrom(other);
return (*this);
}
/** Test whether the list is empty.
*
* @return true if the list is empty, false otherwise
*/
const bool addressList::empty() const
addressList& addressList::operator=(const mailboxList& other)
{
return (m_list.empty());
copyFrom(other);
return (*this);
}
/** Append an address to the list.
*
* @param addr the address to add
*/
void addressList::append(const address& addr)
addressList* addressList::clone() const
{
m_list.push_back(addr.clone());
return new addressList(*this);
}
/** Insert an address at the specified position in the list.
*
* @param it position of the new address
* @param addr the address to insert
*/
void addressList::insert(const iterator it, const address& addr)
void addressList::appendAddress(address* addr)
{
m_list.insert(it.m_iterator, addr.clone());
m_list.push_back(addr);
}
/** Remove the address at the specified position.
*
* @param it position of the address to remove
*/
void addressList::erase(const iterator it)
void addressList::insertAddressBefore(address* beforeAddress, address* addr)
{
delete (*it.m_iterator);
m_list.erase(it.m_iterator);
const std::vector <address*>::iterator it = std::find
(m_list.begin(), m_list.end(), beforeAddress);
if (it == m_list.end())
throw exceptions::no_such_address();
m_list.insert(it, addr);
}
/** Remove all the addresses from the list.
*/
void addressList::insertAddressBefore(const int pos, address* addr)
{
m_list.insert(m_list.begin() + pos, addr);
}
void addressList::clear()
void addressList::insertAddressAfter(address* afterAddress, address* addr)
{
const std::vector <address*>::iterator it = std::find
(m_list.begin(), m_list.end(), afterAddress);
if (it == m_list.end())
throw exceptions::no_such_address();
m_list.insert(it + 1, addr);
}
void addressList::insertAddressAfter(const int pos, address* addr)
{
m_list.insert(m_list.begin() + pos + 1, addr);
}
void addressList::removeAddress(address* addr)
{
const std::vector <address*>::iterator it = std::find
(m_list.begin(), m_list.end(), addr);
if (it == m_list.end())
throw exceptions::no_such_address();
delete (*it);
m_list.erase(it);
}
void addressList::removeAddress(const int pos)
{
const std::vector <address*>::iterator it = m_list.begin() + pos;
delete (*it);
m_list.erase(it);
}
void addressList::removeAllAddresses()
{
free_container(m_list);
}
void addressList::copyFrom(const addressList& source)
const int addressList::getAddressCount() const
{
clear();
for (std::vector <address*>::const_iterator i = source.m_list.begin() ; i != source.m_list.end() ; ++i)
m_list.push_back((*i)->clone());
return (m_list.size());
}
addressList& addressList::operator=(const addressList& source)
const bool addressList::isEmpty() const
{
copyFrom(source);
return (*this);
return (m_list.empty());
}
address* addressList::getAddressAt(const int pos)
{
return (m_list[pos]);
}
const address* const addressList::getAddressAt(const int pos) const
{
return (m_list[pos]);
}
const std::vector <const address*> addressList::getAddressList() const
{
std::vector <const address*> list;
list.reserve(m_list.size());
for (std::vector <address*>::const_iterator it = m_list.begin() ;
it != m_list.end() ; ++it)
{
list.push_back(*it);
}
return (list);
}
const std::vector <address*> addressList::getAddressList()
{
return (m_list);
}
} // vmime

View File

@ -31,106 +31,124 @@ namespace vmime
{
class mailboxList;
/** A list of addresses.
*/
class addressList : public component
{
friend class addressListField;
friend class mailboxListField;
public:
addressList();
addressList(const class addressList& addressList);
addressList(const addressList& addrList);
~addressList();
public:
addressList& operator=(const addressList& source);
addressList* clone() const;
void copyFrom(const component& other);
addressList& operator=(const addressList& other);
addressList& operator=(const mailboxList& other);
// Address iterator
class const_iterator;
class iterator
{
friend class addressList;
friend class const_iterator;
/** Add a address at the end of the list.
*
* @param addr address to append
*/
void appendAddress(address* addr);
public:
/** Insert a new address before the specified address.
*
* @param beforeAddress address before which the new address will be inserted
* @param addr address to insert
* @throw exceptions::no_such_address if the address is not in the list
*/
void insertAddressBefore(address* beforeAddress, address* addr);
iterator(std::vector <address*>::iterator it) : m_iterator(it) { }
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
/** Insert a new address before the specified position.
*
* @param pos position at which to insert the new address (0 to insert at
* the beginning of the list)
* @param addr address to insert
*/
void insertAddressBefore(const int pos, address* addr);
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
/** Insert a new address after the specified address.
*
* @param afterAddress address after which the new address will be inserted
* @param addr address to insert
* @throw exceptions::no_such_address if the address is not in the list
*/
void insertAddressAfter(address* afterAddress, address* addr);
address& operator*() const { return (**m_iterator); }
address* operator->() const { return (*m_iterator); }
/** Insert a new address after the specified position.
*
* @param pos position of the address before the new address
* @param addr address to insert
*/
void insertAddressAfter(const int pos, address* addr);
iterator& operator++() { ++m_iterator; return (*this); }
iterator& operator++(int) { ++m_iterator; return (*this); }
/** Remove the specified address from the list.
*
* @param addr address to remove
* @throw exceptions::no_such_address if the address is not in the list
*/
void removeAddress(address* addr);
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
/** Remove the address at the specified position.
*
* @param pos position of the address to remove
*/
void removeAddress(const int pos);
private:
/** Remove all addresses from the list.
*/
void removeAllAddresses();
std::vector <address*>::iterator m_iterator;
};
/** Return the number of addresses in the list.
*
* @return number of addresses
*/
const int getAddressCount() const;
class const_iterator
{
friend class addressList;
/** Tests whether the list of addresses is empty.
*
* @return true if there is no address, false otherwise
*/
const bool isEmpty() const;
public:
/** Return the address at the specified position.
*
* @param pos position
* @return address at position 'pos'
*/
address* getAddressAt(const int pos);
const_iterator(std::vector <address*>::const_iterator it) : m_iterator(it) { }
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
/** Return the address at the specified position.
*
* @param pos position
* @return address at position 'pos'
*/
const address* const getAddressAt(const int pos) const;
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
/** Return the address list.
*
* @return list of addresses
*/
const std::vector <const address*> getAddressList() const;
const address& operator*() const { return (**m_iterator); }
const address* operator->() const { return (*m_iterator); }
/** Return the address list.
*
* @return list of addresses
*/
const std::vector <address*> getAddressList();
const_iterator& operator++() { ++m_iterator; return (*this); }
const_iterator& operator++(int) { ++m_iterator; return (*this); }
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
private:
std::vector <address*>::const_iterator m_iterator;
};
iterator begin() { return (m_list.begin()); }
iterator end() { return (m_list.end()); }
const_iterator begin() const { return (const_iterator(m_list.begin())); }
const_iterator end() const { return (const_iterator(m_list.end())); }
const std::vector <address*>::size_type size() const;
const std::vector <address*>::size_type count() const;
const bool empty() const;
const address& operator[](const std::vector <address*>::size_type x) const { return (*m_list[x]); }
address& operator[](const std::vector <address*>::size_type x) { return (*m_list[x]); }
virtual void append(const address& addr);
virtual void insert(const iterator it, const address& addr);
void erase(const iterator it);
void clear();
protected:
private:
std::vector <address*> m_list;
void copyFrom(const addressList& source);
public:
using component::parse;

View File

@ -1,67 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "addressListField.hpp"
namespace vmime
{
addressListField::addressListField()
{
}
void addressListField::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
m_list.parse(buffer, position, end, newPosition);
}
void addressListField::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
string::size_type pos = curLinePos;
headerField::generate(os, maxLineLength, pos, &pos);
m_list.generate(os, maxLineLength, pos, newLinePos);
}
addressListField& addressListField::operator=(const addressList& list)
{
m_list.copyFrom(list);
return (*this);
}
void addressListField::copyFrom(const headerField& field)
{
const addressListField& source = dynamic_cast<const addressListField&>(field);
m_list = source.m_list;
headerField::copyFrom(field);
}
} // vmime

View File

@ -1,70 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_ADDRESSLISTFIELD_HPP_INCLUDED
#define VMIME_ADDRESSLISTFIELD_HPP_INCLUDED
#include "base.hpp"
#include "component.hpp"
#include "headerFieldFactory.hpp"
#include "addressList.hpp"
namespace vmime
{
class addressListField : public headerField
{
friend class headerFieldFactory::registerer <addressListField>;
protected:
addressListField();
public:
void copyFrom(const headerField& field);
addressListField& operator=(const addressList& list);
const addressList& value() const { return (m_list); }
addressList& value() { return (m_list); }
protected:
addressList m_list;
public:
using headerField::parse;
using headerField::generate;
// Component parsing & assembling
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
};
} // vmime
#endif // VMIME_ADDRESSLISTFIELD_HPP_INCLUDED

View File

@ -47,27 +47,25 @@ public:
virtual ~attachment() { }
virtual attachment& operator=(const attachment& attach) = 0;
/** Return the media type of this attachment.
* @return content type of the attachment
*/
virtual const mediaType& type() const = 0;
virtual const mediaType& getType() const = 0;
/** Return the description of this attachment.
* @return attachment description
*/
virtual const text& description() const = 0;
virtual const text& getDescription() const = 0;
/** Return the data contained in this attachment.
* @return attachment data
*/
virtual const contentHandler& data() const = 0;
virtual const contentHandler& getData() const = 0;
/** Return the encoding used for this attachment.
* @return attachment data encoding
*/
virtual const class encoding& encoding() const = 0;
virtual const encoding& getEncoding() const = 0;
/** Generate the attachment in the specified body part.
* @param parent body part in which to generate the attachment

View File

@ -30,6 +30,8 @@
#include "parserHelpers.hpp"
#include "utility/stringUtils.hpp"
// For initializing
#include "encoderFactory.hpp"
#include "headerFieldFactory.hpp"
@ -75,17 +77,17 @@ const string libversion() { return (VMIME_VERSION " (" __DATE__ " " __TIME__ ")"
// New line sequence to be used when folding header fields.
const string NEW_LINE_SEQUENCE("\r\n ");
const string::size_type NEW_LINE_SEQUENCE_LENGTH(1); // space
const string NEW_LINE_SEQUENCE = "\r\n ";
const string::size_type NEW_LINE_SEQUENCE_LENGTH = 1; // space
/** The CR-LF sequence.
*/
const string CRLF("\r\n");
const string CRLF = "\r\n";
/** The current MIME version supported by VMime.
*/
const string MIME_VERSION("1.0");
const string MIME_VERSION = "1.0";
// Line length limits
@ -96,147 +98,6 @@ namespace lineLengthLimits
/** Test two strings for equality (case insensitive).
* WARNING: use this with ASCII-only strings.
*
* @param s1 first string
* @param s2 second string (must be in lower-case!)
* @param n length of the second string
* @return true if the two strings compare equally, false otherwise
*/
bool isStringEqualNoCase(const string& s1, const char* s2, const string::size_type n)
{
// 'n' is the number of characters to compare
// 's2' must be in lowercase letters only
if (s1.length() < n)
return (false);
bool equal = true;
for (string::size_type i = 0 ; equal && i < n ; ++i)
equal = (std::tolower(s1[i], std::locale()) == s2[i]);
return (equal);
}
/** Test two strings for equality (case insensitive).
* WARNING: use this with ASCII-only strings.
*
* @param s1 first string
* @param s2 second string
* @return true if the two strings compare equally, false otherwise
*/
bool isStringEqualNoCase(const string& s1, const string& s2)
{
if (s1.length() != s2.length())
return (false);
bool equal = true;
const string::const_iterator end = s1.end();
for (string::const_iterator i = s1.begin(), j = s2.begin(); i != end ; ++i, ++j)
equal = (std::tolower(*i, std::locale()) == std::tolower(*j, std::locale()));
return (equal);
}
/** Test two strings for equality (case insensitive).
* WARNING: use this with ASCII-only strings.
*
* @param begin start position of the first string
* @param end end position of the first string
* @param s second string (must be in lower-case!)
* @param n length of the second string
* @return true if the two strings compare equally, false otherwise
*/
bool isStringEqualNoCase(const string::const_iterator begin, const string::const_iterator end,
const char* s, const string::size_type n)
{
if ((string::size_type)(end - begin) < n)
return (false);
bool equal = true;
char* c = const_cast<char*>(s);
string::size_type r = n;
for (string::const_iterator i = begin ; equal && r && *c ; ++i, ++c, --r)
equal = (std::tolower(*i, std::locale()) == *c);
return (r == 0 && equal);
}
/** Transform all the characters in a string to lower-case.
* WARNING: use this with ASCII-only strings.
*
* @param str the string to transform
* @return a new string in lower-case
*/
const string toLower(const string& str)
{
string out(str);
const string::iterator end = out.end();
for (string::iterator i = out.begin() ; i != end ; ++i)
*i = std::tolower(*i, std::locale());
return (out);
}
/** Strip the space characters (SPC, TAB, CR, LF) at the beginning
* and at the end of the specified string.
*
* @param str string in which to strip spaces
* @return a new string with space characters removed
*/
const string trim(const string& str)
{
string::const_iterator b = str.begin();
string::const_iterator e = str.end();
if (b != e)
{
for ( ; b != e && isspace(*b) ; ++b);
for ( ; e != b && isspace(*(e - 1)) ; --e);
}
return (string(b, e));
}
/** Return the number of 7-bit US-ASCII characters in a string.
*
* @param begin start position
* @param end end position
* @return number of ASCII characters
*/
string::size_type countASCIIchars
(const string::const_iterator begin, const string::const_iterator end)
{
string::size_type count = 0;
for (string::const_iterator i = begin ; i != end ; ++i)
{
if (isascii(*i))
{
if (*i != '=' || *(i + 1) != '?') // To avoid bad behaviour...
++count;
}
}
return (count);
}
/** Encode and fold text in respect to RFC-2047.
*
* @param os output stream
@ -252,14 +113,15 @@ void encodeAndFoldText(utility::outputStream& os, const text& in, const string::
{
string::size_type curLineLength = firstLineOffset;
for (text::const_iterator wi = in.begin() ; wi != in.end() ; ++wi)
for (int wi = 0 ; wi < in.getWordCount() ; ++wi)
{
const word& w = *wi;
const string& buffer = w.buffer();
const word& w = *in.getWordAt(wi);
const string& buffer = w.getBuffer();
// Calculate the number of ASCII chars to check whether encoding is needed
// and _which_ encoding to use.
const string::size_type asciiCount = countASCIIchars(buffer.begin(), buffer.end());
const string::size_type asciiCount =
stringUtils::countASCIIchars(buffer.begin(), buffer.end());
bool noEncoding = (flags & encodeAndFoldFlags::forceNoEncoding) ||
(!(flags & encodeAndFoldFlags::forceEncoding) && asciiCount == buffer.length());
@ -305,7 +167,7 @@ void encodeAndFoldText(utility::outputStream& os, const text& in, const string::
// we write the full line no matter of the max line length...
if (!newLine && p != end && lastWSpos == end &&
wi != in.begin() && curLineStart == buffer.begin())
wi != 0 && curLineStart == buffer.begin())
{
// Here, we are continuing on the line of previous encoded
// word, but there is not even enough space to put the
@ -359,7 +221,7 @@ void encodeAndFoldText(utility::outputStream& os, const text& in, const string::
// last white-space.
#if 1
if (curLineLength != 1 && wi != in.begin())
if (curLineLength != 1 && wi != 0)
os << " "; // Separate from previous word
#endif
@ -419,7 +281,7 @@ void encodeAndFoldText(utility::outputStream& os, const text& in, const string::
const string::size_type asciiPercent = (100 * asciiCount) / buffer.length();
const string::value_type encoding = (asciiPercent <= 40) ? 'B' : 'Q';
string wordStart("=?" + w.charset().name() + "?" + encoding + "?");
string wordStart("=?" + w.getCharset().getName() + "?" + encoding + "?");
string wordEnd("?=");
const string::size_type minWordLength = wordStart.length() + wordEnd.length();
@ -465,7 +327,7 @@ void encodeAndFoldText(utility::outputStream& os, const text& in, const string::
if (encoding == 'Q')
{
theEncoder->properties()["rfc2047"] = true;
theEncoder->getProperties()["rfc2047"] = true;
// In the case of Quoted-Printable encoding, we cannot simply encode input
// buffer line by line. So, we encode the whole buffer and we will fold it
@ -480,7 +342,7 @@ void encodeAndFoldText(utility::outputStream& os, const text& in, const string::
}
#if 1
if (curLineLength != 1 && wi != in.begin())
if (curLineLength != 1 && wi != 0)
{
os << " "; // Separate from previous word
++curLineLength;
@ -585,7 +447,7 @@ void decodeAndUnfoldText(const string::const_iterator& inStart, const string::co
// NOTE: See RFC-2047, Pages 11-12 for knowing about handling
// of white-spaces between encoded words.
out.clear();
out.removeAllWords();
string::const_iterator p = inStart;
const string::const_iterator end = inEnd;
@ -608,14 +470,14 @@ void decodeAndUnfoldText(const string::const_iterator& inStart, const string::co
if (textEnd != prevPos)
{
if (out.size() && prevWordCharset == defaultCharset)
if (!out.isEmpty() && prevWordCharset == defaultCharset)
{
out.back().buffer() += string(prevPos, textEnd);
out.getWordAt(out.getWordCount() - 1)->getBuffer() += string(prevPos, textEnd);
}
else
{
prevWordCharset = defaultCharset;
out.append(word(string(prevPos, textEnd), defaultCharset));
out.appendWord(new word(string(prevPos, textEnd), defaultCharset));
prevIsEncoded = false;
}
}
@ -670,7 +532,7 @@ void decodeAndUnfoldText(const string::const_iterator& inStart, const string::co
else if (*encPos == 'Q' || *encPos == 'q')
{
theEncoder = new encoderQP;
theEncoder->properties()["rfc2047"] = true;
theEncoder->getProperties()["rfc2047"] = true;
}
if (theEncoder)
@ -698,13 +560,16 @@ void decodeAndUnfoldText(const string::const_iterator& inStart, const string::co
if (p != wordPos) // if not empty
{
if (out.size() && prevWordCharset == defaultCharset)
if (!out.isEmpty() && prevWordCharset == defaultCharset)
{
out.back().buffer() += string(prevPos, wordPos);
out.getWordAt(out.getWordCount() - 1)->
getBuffer() += string(prevPos, wordPos);
}
else
{
out.append(word(string(prevPos, wordPos), defaultCharset));
out.appendWord(new word
(string(prevPos, wordPos), defaultCharset));
prevWordCharset = defaultCharset;
}
}
@ -713,14 +578,15 @@ void decodeAndUnfoldText(const string::const_iterator& inStart, const string::co
// Append this fresh decoded word to output text
charset thisCharset(string(charsetPos, charsetEnd));
if (out.size() && prevWordCharset == thisCharset)
if (!out.isEmpty() && prevWordCharset == thisCharset)
{
out.back().buffer() += decodedBuffer;
out.getWordAt(out.getWordCount() - 1)->
getBuffer() += decodedBuffer;
}
else
{
prevWordCharset = thisCharset;
out.append(word(decodedBuffer, thisCharset));
out.appendWord(new word(decodedBuffer, thisCharset));
}
// This word has been decoded: we can advance in the input buffer
@ -753,90 +619,6 @@ void decodeAndUnfoldText(const string& in, text& out)
}
/** This function can be used to make several encoded words from a text.
* All the characters in the text must be in the same specified charset.
*
* <p>Eg: giving:</p>
* <pre> &lt;iso-8859-1> "Linux dans un t'el'ephone mobile"
* ("=?iso-8859-1?Q?Linux_dans_un_t=E9l=E9phone_mobile?=")
* </pre><p>it will return:</p>
* <pre> &lt:us-ascii> "Linux dans un "
* &lt;iso-8859-1> "t'el'ephone "
* &lt;us-ascii> "mobile"
* ("Linux dans un =?iso-8859-1?Q?t=E9l=E9phone_?= mobile")
* </pre>
*
* @param in input string
* @param ch input charset
* @param out output text
*/
void makeWordsFromText(const string& in, const charset& ch, text& out)
{
const string::const_iterator end = in.end();
string::const_iterator p = in.begin();
string::const_iterator start = in.begin();
bool is8bit = false; // is the current word 8-bit?
bool prevIs8bit = false; // is previous word 8-bit?
unsigned int count = 0; // total number of words
out.clear();
for ( ; ; )
{
if (p == end || isspace(*p))
{
if (p != end)
++p;
if (is8bit)
{
if (prevIs8bit)
{
// No need to create a new encoded word, just append
// the current word to the previous one.
out.back().buffer() += string(start, p);
}
else
{
out.append(word(string(start, p), ch));
prevIs8bit = true;
++count;
}
}
else
{
if (count && !prevIs8bit)
{
out.back().buffer() += string(start, p);
}
else
{
out.append(word(string(start, p), charset(charsets::US_ASCII)));
prevIs8bit = false;
++count;
}
}
if (p == end)
break;
is8bit = false;
start = p;
}
else if (!isascii(*p))
{
is8bit = true;
++p;
}
else
{
++p;
}
}
}
//
// V-Mime Initializer

View File

@ -79,39 +79,6 @@ namespace vmime
}
//
// Some helpful functions
//
bool isStringEqualNoCase(const string& s1, const char* s2, const string::size_type n);
bool isStringEqualNoCase(const string& s1, const string& s2);
bool isStringEqualNoCase(const string::const_iterator begin, const string::const_iterator end, const char* s, const string::size_type n);
const string toLower(const string& str);
const string trim(const string& str);
template <class TYPE>
const string toString(const TYPE& value)
{
std::ostringstream oss;
oss << value;
return (oss.str());
}
template <class TYPE>
const TYPE fromString(const string& value)
{
TYPE ret;
std::istringstream iss(value);
iss >> ret;
return (ret);
}
// Free the pointer elements in a STL container and empty the container
template <class CONTAINER>
@ -125,14 +92,10 @@ namespace vmime
// Field contents encoding (RFC-2047 and folding)
string::size_type countASCIIchars(const string::const_iterator begin, const string::const_iterator end);
void encodeAndFoldText(utility::outputStream& os, const text& in, const string::size_type maxLineLength, const string::size_type firstLineOffset, string::size_type* lastLineLength, const int flags);
void decodeAndUnfoldText(const string& in, text& out);
void decodeAndUnfoldText(const string::const_iterator& inStart, const string::const_iterator& inEnd, text& out);
void makeWordsFromText(const string& in, const charset& ch, text& out);
//
// Some constants
@ -210,6 +173,9 @@ namespace vmime
// Mime version
extern const string MIME_VERSION;
/** Utility classes. */
namespace utility { }
} // vmime

View File

@ -23,7 +23,6 @@
#include "options.hpp"
#include "contentTypeField.hpp"
#include "contentEncodingField.hpp"
#include "utility/random.hpp"
@ -34,16 +33,28 @@ namespace vmime
{
body::body(bodyPart& part)
: parts(*this), m_part(part), m_header(part.header())
body::body()
: m_part(NULL), m_header(NULL)
{
}
body::body(bodyPart* parentPart)
: m_part(parentPart), m_header(parentPart != NULL ? parentPart->getHeader() : NULL)
{
}
body::~body()
{
removeAllParts();
}
void body::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
parts.clear();
removeAllParts();
// Check whether the body is a MIME-multipart
bool isMultipart = false;
@ -52,15 +63,15 @@ void body::parse(const string& buffer, const string::size_type position,
try
{
const contentTypeField& ctf = dynamic_cast <contentTypeField&>
(m_header.fields.find(headerField::ContentType));
(*m_header->findField(fields::CONTENT_TYPE));
if (ctf.value().type() == mediaTypes::MULTIPART)
if (ctf.getValue().getType() == mediaTypes::MULTIPART)
{
isMultipart = true;
try
{
boundary = ctf.boundary();
boundary = ctf.getBoundary();
}
catch (exceptions::no_such_parameter&)
{
@ -170,13 +181,17 @@ void body::parse(const string& buffer, const string::size_type position,
throw;
}
parts.m_parts.push_back(part);
part->m_parent = m_part;
m_parts.push_back(part);
}
partStart = pos;
pos = buffer.find(boundarySep, partStart);
}
m_contents.setData("");
if (partStart < end)
m_epilogText = string(buffer.begin() + partStart, buffer.begin() + end);
}
@ -184,7 +199,7 @@ void body::parse(const string& buffer, const string::size_type position,
else
{
// Extract the (encoded) contents
m_contents.set(buffer, position, end, encoding());
m_contents.setData(buffer, position, end, getEncoding());
}
if (newPosition)
@ -196,32 +211,39 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
const string::size_type /* curLinePos */, string::size_type* newLinePos) const
{
// MIME-Multipart
if (parts.size() != 0)
if (getPartCount() != 0)
{
string boundary;
try
if (m_header == NULL)
{
contentTypeField& ctf = dynamic_cast<contentTypeField&>
(m_header.fields.find(headerField::ContentType));
boundary = generateRandomBoundaryString();
}
else
{
try
{
contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*m_header->findField(fields::CONTENT_TYPE));
boundary = ctf.boundary();
}
catch (exceptions::no_such_field&)
{
// Warning: no content-type and no boundary string specified!
boundary = generateRandomBoundaryString();
}
catch (exceptions::no_such_parameter&)
{
// Warning: no boundary string specified!
boundary = generateRandomBoundaryString();
boundary = ctf.getBoundary();
}
catch (exceptions::no_such_field&)
{
// Warning: no content-type and no boundary string specified!
boundary = generateRandomBoundaryString();
}
catch (exceptions::no_such_parameter&)
{
// Warning: no boundary string specified!
boundary = generateRandomBoundaryString();
}
}
const string& prologText =
m_prologText.empty()
? (isRootPart()
? options::getInstance()->multipart.prologText()
? options::getInstance()->multipart.getPrologText()
: NULL_STRING
)
: m_prologText;
@ -229,14 +251,14 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
const string& epilogText =
m_epilogText.empty()
? (isRootPart()
? options::getInstance()->multipart.epilogText()
? options::getInstance()->multipart.getEpilogText()
: NULL_STRING
)
: m_epilogText;
if (!prologText.empty())
{
encodeAndFoldText(os, text(word(prologText, charset())), maxLineLength, 0,
encodeAndFoldText(os, text(word(prologText, getCharset())), maxLineLength, 0,
NULL, encodeAndFoldFlags::forceNoEncoding | encodeAndFoldFlags::noNewLineSequence);
os << CRLF;
@ -244,12 +266,11 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
os << "--" << boundary;
for (std::vector <bodyPart*>::const_iterator
p = parts.m_parts.begin() ; p != parts.m_parts.end() ; ++p)
for (int p = 0 ; p < getPartCount() ; ++p)
{
os << CRLF;
(*p)->generate(os, maxLineLength, 0);
getPartAt(p)->generate(os, maxLineLength, 0);
os << CRLF << "--" << boundary;
}
@ -258,7 +279,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
if (!epilogText.empty())
{
encodeAndFoldText(os, text(word(epilogText, charset())), maxLineLength, 0,
encodeAndFoldText(os, text(word(epilogText, getCharset())), maxLineLength, 0,
NULL, encodeAndFoldFlags::forceNoEncoding | encodeAndFoldFlags::noNewLineSequence);
os << CRLF;
@ -271,7 +292,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
else
{
// Generate the contents
m_contents.generate(os, encoding(), maxLineLength);
m_contents.generate(os, getEncoding(), maxLineLength);
}
}
@ -316,7 +337,7 @@ const string body::generateRandomBoundaryString()
boundary[1] = '_';
// Generate a string of random characters
unsigned int r = utility::random::time();
unsigned int r = utility::random::getTime();
unsigned int m = sizeof(unsigned int);
for (size_t i = 2 ; i < (sizeof(boundary) / sizeof(boundary[0]) - 1) ; ++i)
@ -326,7 +347,7 @@ const string body::generateRandomBoundaryString()
if (--m == 0)
{
r = utility::random::next();
r = utility::random::getNext();
m = sizeof(unsigned int);
}
}
@ -363,12 +384,14 @@ const bool body::isValidBoundary(const string& boundary)
// Quick-access functions
//
const mediaType body::contentType() const
const mediaType body::getContentType() const
{
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>(m_header.fields.find(headerField::ContentType));
return (ctf.value());
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*m_header->findField(fields::CONTENT_TYPE));
return (ctf.getValue());
}
catch (exceptions::no_such_field&)
{
@ -378,12 +401,14 @@ const mediaType body::contentType() const
}
const class charset body::charset() const
const charset body::getCharset() const
{
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>(m_header.fields.find(headerField::ContentType));
const class charset& cs = ctf.charset();
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*m_header->findField(fields::CONTENT_TYPE));
const class charset& cs = ctf.getCharset();
return (cs);
}
@ -400,12 +425,14 @@ const class charset body::charset() const
}
const class encoding body::encoding() const
const encoding body::getEncoding() const
{
try
{
const contentEncodingField& cef = m_header.fields.ContentTransferEncoding();
return (cef.value());
const contentEncodingField& cef = dynamic_cast<contentEncodingField&>
(*m_header->findField(fields::CONTENT_TRANSFER_ENCODING));
return (cef.getValue());
}
catch (exceptions::no_such_field&)
{
@ -417,126 +444,259 @@ const class encoding body::encoding() const
const bool body::isRootPart() const
{
return (m_part.parent() == NULL);
return (m_part == NULL || m_part->getParentPart() == NULL);
}
body& body::operator=(const body& b)
body* body::clone() const
{
m_prologText = b.m_prologText;
m_epilogText = b.m_epilogText;
body* bdy = new body(NULL);
m_contents = b.m_contents;
bdy->copyFrom(*this);
parts = b.parts;
return (bdy);
}
void body::copyFrom(const component& other)
{
const body& bdy = dynamic_cast <const body&>(other);
m_prologText = bdy.m_prologText;
m_epilogText = bdy.m_epilogText;
m_contents = bdy.m_contents;
removeAllParts();
for (int p = 0 ; p < bdy.getPartCount() ; ++p)
{
bodyPart* part = bdy.getPartAt(p)->clone();
part->m_parent = m_part;
m_parts.push_back(part);
}
}
body& body::operator=(const body& other)
{
copyFrom(other);
return (*this);
}
/////////////////////
// Parts container //
/////////////////////
body::partsContainer::partsContainer(class body& body)
: m_body(body)
const string& body::getPrologText() const
{
return (m_prologText);
}
// Part insertion
void body::partsContainer::append(bodyPart* part)
void body::setPrologText(const string& prologText)
{
part->m_parent = &(m_body.m_part);
m_prologText = prologText;
}
m_parts.push_back(part);
// Check whether we have a boundary string
try
const string& body::getEpilogText() const
{
return (m_epilogText);
}
void body::setEpilogText(const string& epilogText)
{
m_epilogText = epilogText;
}
const contentHandler& body::getContents() const
{
return (m_contents);
}
contentHandler& body::getContents()
{
return (m_contents);
}
void body::setContents(const contentHandler& contents)
{
m_contents = contents;
}
void body::initNewPart(bodyPart* part)
{
part->m_parent = m_part;
if (m_header != NULL)
{
contentTypeField& ctf = dynamic_cast<contentTypeField&>
(m_body.m_header.fields.find(headerField::ContentType));
// Check whether we have a boundary string
try
{
const string boundary = ctf.boundary();
contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*m_header->findField(fields::CONTENT_TYPE));
if (boundary.empty() || !isValidBoundary(boundary))
throw exceptions::no_such_parameter("boundary"); // to generate a new one
try
{
const string boundary = ctf.getBoundary();
if (boundary.empty() || !isValidBoundary(boundary))
ctf.setBoundary(generateRandomBoundaryString());
}
catch (exceptions::no_such_parameter&)
{
// No "boundary" parameter: generate a random one.
ctf.setBoundary(generateRandomBoundaryString());
}
if (ctf.getValue().getType() != mediaTypes::MULTIPART)
{
// Warning: multi-part body but the Content-Type is
// not specified as "multipart/..."
}
}
catch (exceptions::no_such_parameter&)
catch (exceptions::no_such_field&)
{
// No "boundary" parameter: generate a random one.
ctf.boundary() = generateRandomBoundaryString();
}
// No "Content-Type" field: create a new one and generate
// a random boundary string.
contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*m_header->getField(fields::CONTENT_TYPE));
if (ctf.value().type() != mediaTypes::MULTIPART)
{
// Warning: multi-part body but the Content-Type is
// not specified as "multipart/..."
ctf.setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED));
ctf.setBoundary(generateRandomBoundaryString());
}
}
catch (exceptions::no_such_field&)
{
// No "Content-Type" field: create a new one and generate
// a random boundary string.
contentTypeField& ctf = dynamic_cast<contentTypeField&>
(m_body.m_header.fields.get(headerField::ContentType));
ctf.value() = mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED);
ctf.boundary() = generateRandomBoundaryString();
}
}
void body::partsContainer::insert(const iterator it, bodyPart* part)
void body::appendPart(bodyPart* part)
{
part->m_parent = &(m_body.m_part);
initNewPart(part);
m_parts.insert(it.m_iterator, part);
m_parts.push_back(part);
}
// Part removing
void body::partsContainer::remove(const iterator it)
void body::insertPartBefore(bodyPart* beforePart, bodyPart* part)
{
delete (*it.m_iterator);
m_parts.erase(it.m_iterator);
initNewPart(part);
const std::vector <bodyPart*>::iterator it = std::find
(m_parts.begin(), m_parts.end(), beforePart);
if (it == m_parts.end())
throw exceptions::no_such_part();
m_parts.insert(it, part);
}
void body::partsContainer::clear()
void body::insertPartBefore(const int pos, bodyPart* part)
{
initNewPart(part);
m_parts.insert(m_parts.begin() + pos, part);
}
void body::insertPartAfter(bodyPart* afterPart, bodyPart* part)
{
initNewPart(part);
const std::vector <bodyPart*>::iterator it = std::find
(m_parts.begin(), m_parts.end(), afterPart);
if (it == m_parts.end())
throw exceptions::no_such_part();
m_parts.insert(it + 1, part);
}
void body::insertPartAfter(const int pos, bodyPart* part)
{
initNewPart(part);
m_parts.insert(m_parts.begin() + pos + 1, part);
}
void body::removePart(bodyPart* part)
{
const std::vector <bodyPart*>::iterator it = std::find
(m_parts.begin(), m_parts.end(), part);
if (it == m_parts.end())
throw exceptions::no_such_part();
delete (*it);
m_parts.erase(it);
}
void body::removePart(const int pos)
{
delete (m_parts[pos]);
m_parts.erase(m_parts.begin() + pos);
}
void body::removeAllParts()
{
free_container(m_parts);
}
body::partsContainer::~partsContainer()
const int body::getPartCount() const
{
clear();
return (m_parts.size());
}
body::partsContainer& body::partsContainer::operator=(const partsContainer& c)
const bool body::isEmpty() const
{
std::vector <bodyPart*> parts;
return (m_parts.size() == 0);
}
for (std::vector <bodyPart*>::const_iterator it = c.m_parts.begin() ; it != c.m_parts.end() ; ++it)
bodyPart* body::getPartAt(const int pos)
{
return (m_parts[pos]);
}
const bodyPart* const body::getPartAt(const int pos) const
{
return (m_parts[pos]);
}
const std::vector <const bodyPart*> body::getPartList() const
{
std::vector <const bodyPart*> list;
list.reserve(m_parts.size());
for (std::vector <bodyPart*>::const_iterator it = m_parts.begin() ;
it != m_parts.end() ; ++it)
{
bodyPart* p = (*it)->clone();
p->m_parent = &(m_body.m_part);
parts.push_back(p);
list.push_back(*it);
}
for (std::vector <bodyPart*>::iterator it = m_parts.begin() ; it != m_parts.end() ; ++it)
delete (*it);
return (list);
}
m_parts.resize(parts.size());
std::copy(parts.begin(), parts.end(), m_parts.begin());
return (*this);
const std::vector <bodyPart*> body::getPartList()
{
return (m_parts);
}

View File

@ -47,176 +47,206 @@ class body : public component
{
friend class bodyPart;
protected:
private:
body(bodyPart& part);
body(bodyPart* parentPart);
public:
// A sub-class for part manipulation
class partsContainer
{
friend class body;
body();
~body();
protected:
/** Add a part at the end of the list.
*
* @param part part to append
*/
void appendPart(bodyPart* part);
partsContainer(class body& body);
~partsContainer();
/** Insert a new part before the specified part.
*
* @param beforePart part before which the new part will be inserted
* @param part part to insert
* @throw exceptions::no_such_part if the part is not in the list
*/
void insertPartBefore(bodyPart* beforePart, bodyPart* part);
public:
/** Insert a new part before the specified position.
*
* @param pos position at which to insert the new part (0 to insert at
* the beginning of the list)
* @param part part to insert
*/
void insertPartBefore(const int pos, bodyPart* part);
// Part iterator
class const_iterator;
/** Insert a new part after the specified part.
*
* @param afterPart part after which the new part will be inserted
* @param part part to insert
* @throw exceptions::no_such_part if the part is not in the list
*/
void insertPartAfter(bodyPart* afterPart, bodyPart* part);
class iterator
{
friend class body::partsContainer::const_iterator;
friend class body::partsContainer;
/** Insert a new part after the specified position.
*
* @param pos position of the part before the new part
* @param part part to insert
*/
void insertPartAfter(const int pos, bodyPart* part);
public:
/** Remove the specified part from the list.
*
* @param part part to remove
* @throw exceptions::no_such_part if the part is not in the list
*/
void removePart(bodyPart* part);
typedef std::vector <bodyPart*>::iterator::difference_type difference_type;
/** Remove the part at the specified position.
*
* @param pos position of the part to remove
*/
void removePart(const int pos);
iterator(std::vector <bodyPart*>::iterator it) : m_iterator(it) { }
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
/** Remove all parts from the list.
*/
void removeAllParts();
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
/** Return the number of parts in the list.
*
* @return number of parts
*/
const int getPartCount() const;
bodyPart& operator*() const { return (**m_iterator); }
bodyPart* operator->() const { return (*m_iterator); }
/** Tests whether the list of parts is empty.
*
* @return true if there is no part, false otherwise
*/
const bool isEmpty() const;
iterator& operator++() { ++m_iterator; return (*this); }
iterator operator++(int) { iterator i(*this); ++m_iterator; return (i); }
/** Return the part at the specified position.
*
* @param pos position
* @return part at position 'pos'
*/
bodyPart* getPartAt(const int pos);
iterator& operator--() { --m_iterator; return (*this); }
iterator operator--(int) { iterator i(*this); --m_iterator; return (i); }
/** Return the part at the specified position.
*
* @param pos position
* @return part at position 'pos'
*/
const bodyPart* const getPartAt(const int pos) const;
iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
/** Return the part list.
*
* @return list of parts
*/
const std::vector <const bodyPart*> getPartList() const;
iterator operator-(difference_type x) const { return iterator(m_iterator - x); }
/** Return the part list.
*
* @return list of parts
*/
const std::vector <bodyPart*> getPartList();
bodyPart& operator[](difference_type n) const { return *(m_iterator[n]); }
/** Return the prolog text.
*
* @return prolog text
*/
const string& getPrologText() const;
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
/** Set the prolog text.
*
* @param prologText new prolog text
*/
void setPrologText(const string& prologText);
protected:
/** Return the epilog text.
*
* @return epilog text
*/
const string& getEpilogText() const;
std::vector <bodyPart*>::iterator m_iterator;
};
/** Set the epilog text.
*
* @param epilogText new epilog text
*/
void setEpilogText(const string& epilogText);
class const_iterator
{
public:
/** Return a read-only reference to body contents.
*
* @return read-only body contents
*/
const contentHandler& getContents() const;
typedef std::vector <bodyPart*>::const_iterator::difference_type difference_type;
/** Return a modifiable reference to body contents.
*
* @return body contents
*/
contentHandler& getContents();
const_iterator(std::vector <bodyPart*>::const_iterator it) : m_iterator(it) { }
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
/** Set the body contents.
*
* @param contents new body contents
*/
void setContents(const contentHandler& contents);
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
/** Return the media type of the data contained in the body contents.
* This is a shortcut for getHeader()->ContentType()->getValue()
* on the parent part.
*
* @return media type of body contents
*/
const mediaType getContentType() const;
const bodyPart& operator*() const { return (**m_iterator); }
const bodyPart* operator->() const { return (*m_iterator); }
/** Return the charset of the data contained in the body contents.
* This is a shortcut for getHeader()->ContentType()->getCharset()
* on the parent part.
*
* @return charset of body contents
*/
const charset getCharset() const;
const_iterator& operator++() { ++m_iterator; return (*this); }
const_iterator operator++(int) { const_iterator i(*this); ++m_iterator; return (i); }
/** Return the encoding used to encode the body contents.
* This is a shortcut for getHeader()->ContentTransferEncoding()->getValue()
* on the parent part.
*
* @return encoding of body contents
*/
const encoding getEncoding() const;
const_iterator& operator--() { --m_iterator; return (*this); }
const_iterator operator--(int) { const_iterator i(*this); --m_iterator; return (i); }
const_iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
const_iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
const_iterator operator-(difference_type x) const { return const_iterator(m_iterator - x); }
const bodyPart& operator[](difference_type n) const { return *(m_iterator[n]); }
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
protected:
std::vector <bodyPart*>::const_iterator m_iterator;
};
public:
iterator begin() { return (m_parts.begin()); }
iterator end() { return (m_parts.end()); }
const_iterator begin() const { return (const_iterator(m_parts.begin())); }
const_iterator end() const { return (const_iterator(m_parts.end())); }
const bodyPart& operator[](const std::vector <bodyPart*>::size_type x) const { return (*m_parts[x]); }
bodyPart& operator[](const std::vector <bodyPart*>::size_type x) { return (*m_parts[x]); }
// Part insertion
void append(bodyPart* part);
void insert(const iterator it, bodyPart* part);
// Part removing
void remove(const iterator it);
void clear();
// Part count
const size_t count() const { return (m_parts.size()); }
const size_t size() const { return (m_parts.size()); }
bodyPart& front() { return (*m_parts.front()); }
const bodyPart& front() const { return (*m_parts.front()); }
bodyPart& back() { return (*m_parts.back()); }
const bodyPart& back() const { return (*m_parts.back()); }
partsContainer& operator=(const partsContainer& c);
protected:
body& m_body;
std::vector <bodyPart*> m_parts;
} parts;
typedef partsContainer::iterator iterator;
typedef partsContainer::const_iterator const_iterator;
const string& prologText() const { return (m_prologText); }
string& prologText() { return (m_prologText); }
const string& epilogText() const { return (m_epilogText); }
string& epilogText() { return (m_epilogText); }
const contentHandler& contents() const { return (m_contents); }
contentHandler& contents() { return (m_contents); }
// Quick-access functions
const mediaType contentType() const;
const class charset charset() const;
const class encoding encoding() const;
// Boundary string functions
/** Generate a new random boundary string.
*
* @return randomly generated boundary string
*/
static const string generateRandomBoundaryString();
/** Test a boundary string for validity (as defined in RFC #1521, page 19).
*
* @param boundary boundary string to test
* @return true if the boundary string is valid, false otherwise
*/
static const bool isValidBoundary(const string& boundary);
body& operator=(const body& b);
body* clone() const;
void copyFrom(const component& other);
body& operator=(const body& other);
protected:
private:
string m_prologText;
string m_epilogText;
contentHandler m_contents;
bodyPart& m_part;
header& m_header;
bodyPart* m_part;
header* m_header;
std::vector <bodyPart*> m_parts;
const bool isRootPart() const;
void initNewPart(bodyPart* part);
public:
using component::parse;

View File

@ -25,7 +25,7 @@ namespace vmime
bodyPart::bodyPart()
: m_body(*this), m_parent(NULL)
: m_body(this), m_parent(NULL)
{
}
@ -64,12 +64,59 @@ bodyPart* bodyPart::clone() const
bodyPart* p = new bodyPart;
p->m_parent = NULL;
p->m_header = m_header;
p->m_body = m_body;
p->m_header.copyFrom(m_header);
p->m_body.copyFrom(m_body);
return (p);
}
void bodyPart::copyFrom(const component& other)
{
const bodyPart& bp = dynamic_cast <const bodyPart&>(other);
m_header = bp.m_header;
m_body = bp.m_body;
}
bodyPart& bodyPart::operator=(const bodyPart& other)
{
copyFrom(other);
return (*this);
}
const header* bodyPart::getHeader() const
{
return (&m_header);
}
header* bodyPart::getHeader()
{
return (&m_header);
}
const body* bodyPart::getBody() const
{
return (&m_body);
}
body* bodyPart::getBody()
{
return (&m_body);
}
bodyPart* bodyPart::getParentPart() const
{
return (m_parent);
}
} // vmime

View File

@ -37,24 +37,28 @@ namespace vmime
class bodyPart : public component
{
friend class body;
public:
bodyPart();
const class header& header() const { return (m_header); }
class header& header() { return (m_header); }
const header* getHeader() const;
header* getHeader();
const class body& body() const { return (m_body); }
class body& body() { return (m_body); }
const body* getBody() const;
body* getBody();
bodyPart* parent() const { return (m_parent); }
bodyPart* getParentPart() const;
bodyPart* clone() const;
void copyFrom(const component& other);
bodyPart& operator=(const bodyPart& other);
protected:
private:
class header m_header;
class body m_body;
header m_header;
body m_body;
bodyPart* m_parent;
@ -66,11 +70,6 @@ public:
// Component parsing & assembling
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
// This is here because of a bug in g++ < 3.4
friend class body;
friend class body::partsContainer;
};

View File

@ -21,6 +21,8 @@
#include "exception.hpp"
#include "platformDependant.hpp"
#include "utility/stringUtils.hpp"
extern "C"
{
@ -72,20 +74,11 @@ void charset::generate(utility::outputStream& os, const string::size_type /* max
}
/** Convert the contents of an input stream in a specified charset
* to another charset and write the result to an output stream.
*
* @param in input stream to read data from
* @param out output stream to write the converted data
* @param source input charset
* @param dest output charset
*/
void charset::convert(utility::inputStream& in, utility::outputStream& out,
const charset& source, const charset& dest)
{
// Get an iconv descriptor
const iconv_t cd = iconv_open(dest.name().c_str(), source.name().c_str());
const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str());
if (cd != (iconv_t) -1)
{
@ -158,20 +151,11 @@ void charset::convert(utility::inputStream& in, utility::outputStream& out,
}
/** Convert a string buffer in a specified charset to a string
* buffer in another charset.
*
* @param in input buffer
* @param out output buffer
* @param from input charset
* @param to output charset
*/
template <class STRINGF, class STRINGT>
void charset::iconvert(const STRINGF& in, STRINGT& out, const charset& from, const charset& to)
{
// Get an iconv descriptor
const iconv_t cd = iconv_open(to.name().c_str(), from.name().c_str());
const iconv_t cd = iconv_open(to.getName().c_str(), from.getName().c_str());
typedef typename STRINGF::value_type ivt;
typedef typename STRINGT::value_type ovt;
@ -218,28 +202,12 @@ void charset::iconvert(const STRINGF& in, STRINGT& out, const charset& from, con
#if VMIME_WIDE_CHAR_SUPPORT
/** Convert a string buffer in the specified charset to a wide-char
* string buffer.
*
* @param in input buffer
* @param out output buffer
* @param ch input charset
*/
void charset::decode(const string& in, wstring& out, const charset& ch)
{
iconvert(in, out, ch, charset("WCHAR_T"));
}
/** Convert a wide-char string buffer to a string buffer in the
* specified charset.
*
* @param in input buffer
* @param out output buffer
* @param ch output charset
*/
void charset::encode(const wstring& in, string& out, const charset& ch)
{
iconvert(in, out, charset("WCHAR_T"), ch);
@ -248,37 +216,21 @@ void charset::encode(const wstring& in, string& out, const charset& ch)
#endif
/** Convert a string buffer from one charset to another charset.
*
* @param in input buffer
* @param out output buffer
* @param source input charset
* @param dest output charset
*/
void charset::convert(const string& in, string& out, const charset& source, const charset& dest)
{
iconvert(in, out, source, dest);
}
/** Returns the default charset used on the system.
*
* This function simply calls <code>platformDependantHandler::getLocaleCharset()</code>
* and is provided for convenience.
*
* @return system default charset
*/
const charset charset::getLocaleCharset()
{
return (platformDependant::getHandler()->getLocaleCharset());
}
charset& charset::operator=(const charset& source)
charset& charset::operator=(const charset& other)
{
m_name = source.m_name;
copyFrom(other);
return (*this);
}
@ -292,7 +244,7 @@ charset& charset::operator=(const string& name)
const bool charset::operator==(const charset& value) const
{
return (isStringEqualNoCase(m_name, value.m_name));
return (stringUtils::isStringEqualNoCase(m_name, value.m_name));
}
@ -302,4 +254,22 @@ const bool charset::operator!=(const charset& value) const
}
charset* charset::clone() const
{
return new charset(m_name);
}
const string& charset::getName() const
{
return (m_name);
}
void charset::copyFrom(const component& other)
{
m_name = dynamic_cast <const charset&>(other).m_name;
}
} // vmime

View File

@ -41,28 +41,74 @@ public:
public:
const string name() const { return (m_name); }
/** Return the ISO name of the charset.
*
* @return charset name
*/
const string& getName() const;
charset& operator=(const charset& source);
charset& operator=(const charset& other);
charset& operator=(const string& name);
const bool operator==(const charset& value) const;
const bool operator!=(const charset& value) const;
/** Returns the default charset used on the system.
*
* This function simply calls <code>platformDependantHandler::getLocaleCharset()</code>
* and is provided for convenience.
*
* @return system default charset
*/
static const charset getLocaleCharset();
#if VMIME_WIDE_CHAR_SUPPORT
/** Convert a string buffer in the specified charset to a wide-char
* string buffer.
*
* @param in input buffer
* @param out output buffer
* @param ch input charset
*/
static void decode(const string& in, wstring& out, const charset& ch);
/** Convert a wide-char string buffer to a string buffer in the
* specified charset.
*
* @param in input buffer
* @param out output buffer
* @param ch output charset
*/
static void encode(const wstring& in, string& out, const charset& ch);
#endif
// In-memory conversion
/** Convert a string buffer from one charset to another
* charset (in-memory conversion)
*
* \deprecated Use the new convert() method, which takes
* an outputStream parameter.
*
* @param in input buffer
* @param out output buffer
* @param source input charset
* @param dest output charset
*/
static void convert(const string& in, string& out, const charset& source, const charset& dest);
// Stream conversion
/** Convert the contents of an input stream in a specified charset
* to another charset and write the result to an output stream.
*
* @param in input stream to read data from
* @param out output stream to write the converted data
* @param source input charset
* @param dest output charset
*/
static void convert(utility::inputStream& in, utility::outputStream& out, const charset& source, const charset& dest);
protected:
charset* clone() const;
void copyFrom(const component& other);
private:
string m_name;

View File

@ -1,50 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "charsetParameter.hpp"
#include "parserHelpers.hpp"
namespace vmime
{
void charsetParameter::parseValue(const string& buffer, const string::size_type position,
const string::size_type end)
{
m_value.parse(buffer, position, end);
}
const string charsetParameter::generateValue() const
{
return (m_value.name());
}
void charsetParameter::copyFrom(const parameter& param)
{
const charsetParameter& source = dynamic_cast<const charsetParameter&>(param);
m_value = source.m_value;
defaultParameter::copyFrom(param);
}
} // vmime

View File

@ -1,55 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_CHARSETPARAMETER_HPP_INCLUDED
#define VMIME_CHARSETPARAMETER_HPP_INCLUDED
#include "defaultParameter.hpp"
#include "charset.hpp"
namespace vmime
{
class charsetParameter : public defaultParameter
{
protected:
charset m_value;
public:
void copyFrom(const parameter& param);
const charset& value() const { return (m_value); }
charset& value() { return (m_value); }
protected:
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
const string generateValue() const;
};
} // vmime
#endif // VMIME_CHARSETPARAMETER_HPP_INCLUDED

View File

@ -18,6 +18,7 @@
//
#include "component.hpp"
#include "base.hpp"
#include <sstream>
@ -26,6 +27,11 @@ namespace vmime
{
component::~component()
{
}
void component::parse(const string& buffer)
{
parse(buffer, 0, buffer.length(), NULL);

View File

@ -34,11 +34,9 @@ namespace vmime
class component
{
protected:
public:
virtual ~component() {}
protected:
virtual ~component();
/** Parse RFC-822/MIME data for this component.
*
@ -55,8 +53,6 @@ protected:
*/
virtual void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL) = 0;
public:
/** Generate RFC-2822/MIME data for this component.
*
* \deprecated Use the new generate() method, which takes an outputStream parameter.
@ -65,7 +61,7 @@ public:
* @param curLinePos length of the current line in the output buffer
* @return generated data
*/
virtual const string generate(const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0) const;
const string generate(const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0) const;
/** Generate RFC-2822/MIME data for this component.
*
@ -75,6 +71,21 @@ public:
* @param newLinePos will receive the new line position (length of the last line written)
*/
virtual void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const = 0;
/** Clone this component.
*
* @return a copy of this component
*/
virtual component* clone() const = 0;
/** Replace data in this component by data in other component.
* Both components must be of the same type.
*
* @throw std::bad_cast_exception if the components are not
* of the same (dynamic) type
* @param other other component to copy data from
*/
virtual void copyFrom(const component& other) = 0;
};

View File

@ -148,4 +148,34 @@ namespace charsets
}
// Fields
namespace fields
{
const string::value_type* const RECEIVED = "Received";
const string::value_type* const FROM = "From";
const string::value_type* const SENDER = "Sender";
const string::value_type* const REPLY_TO = "Reply-To";
const string::value_type* const TO = "To";
const string::value_type* const CC = "Cc";
const string::value_type* const BCC = "Bcc";
const string::value_type* const DATE = "Date";
const string::value_type* const SUBJECT = "Subject";
const string::value_type* const ORGANIZATION = "Organization";
const string::value_type* const USER_AGENT = "User-Agent";
const string::value_type* const DELIVERED_TO = "Delivered-To";
const string::value_type* const RETURN_PATH = "Return-Path";
const string::value_type* const MIME_VERSION = "Mime-Version";
const string::value_type* const MESSAGE_ID = "Message-Id";
const string::value_type* const CONTENT_TYPE = "Content-Type";
const string::value_type* const CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
const string::value_type* const CONTENT_DESCRIPTION = "Content-Description";
const string::value_type* const CONTENT_DISPOSITION = "Content-Disposition";
const string::value_type* const CONTENT_ID = "Content-Id";
const string::value_type* const CONTENT_LOCATION = "Content-Location";
const string::value_type* const X_MAILER = "X-Mailer";
const string::value_type* const X_PRIORITY = "X-Priority";
}
} // vmime

View File

@ -28,7 +28,7 @@
namespace vmime
{
// Media types (predefined types)
/** Constants for media types. */
namespace mediaTypes
{
// Types
@ -67,7 +67,7 @@ namespace vmime
}
// Encoding types
/** Constants for encoding types. */
namespace encodingTypes
{
extern const string::value_type* const SEVEN_BIT;
@ -79,7 +79,7 @@ namespace vmime
}
// Disposition types (RFC-2183)
/** Constants for disposition types (RFC-2183). */
namespace dispositionTypes
{
extern const string::value_type* const INLINE;
@ -87,7 +87,7 @@ namespace vmime
}
// Charsets
/** Constants for charsets. */
namespace charsets
{
extern const string::value_type* const ISO8859_1;
@ -150,6 +150,35 @@ namespace vmime
extern const string::value_type* const WINDOWS_1257;
extern const string::value_type* const WINDOWS_1258;
}
/** Constants for standard field names. */
namespace fields
{
extern const string::value_type* const RECEIVED;
extern const string::value_type* const FROM;
extern const string::value_type* const SENDER;
extern const string::value_type* const REPLY_TO;
extern const string::value_type* const TO;
extern const string::value_type* const CC;
extern const string::value_type* const BCC;
extern const string::value_type* const DATE;
extern const string::value_type* const SUBJECT;
extern const string::value_type* const ORGANIZATION;
extern const string::value_type* const USER_AGENT;
extern const string::value_type* const DELIVERED_TO;
extern const string::value_type* const RETURN_PATH;
extern const string::value_type* const MIME_VERSION;
extern const string::value_type* const MESSAGE_ID;
extern const string::value_type* const CONTENT_TYPE;
extern const string::value_type* const CONTENT_TRANSFER_ENCODING;
extern const string::value_type* const CONTENT_DESCRIPTION;
extern const string::value_type* const CONTENT_DISPOSITION;
extern const string::value_type* const CONTENT_ID;
extern const string::value_type* const CONTENT_LOCATION;
extern const string::value_type* const X_MAILER;
extern const string::value_type* const X_PRIORITY;
}
}

View File

@ -20,6 +20,8 @@
#include "contentDispositionField.hpp"
#include "exception.hpp"
#include "standardParams.hpp"
namespace vmime
{
@ -30,32 +32,69 @@ contentDispositionField::contentDispositionField()
}
void contentDispositionField::parseValue(const string& buffer, const string::size_type position,
const string::size_type end)
contentDispositionField::contentDispositionField(contentDispositionField&)
: headerField(), parameterizedHeaderField(), genericField <disposition>()
{
m_value.parse(buffer, position, end);
}
const string contentDispositionField::generateValue() const
const datetime& contentDispositionField::getCreationDate() const
{
return (m_value.generate());
return (dynamic_cast <const dateParameter&>(*findParameter("creation-date")).getValue());
}
contentDispositionField& contentDispositionField::operator=(const disposition& type)
void contentDispositionField::setCreationDate(const datetime& creationDate)
{
m_value = type;
return (*this);
dynamic_cast <dateParameter&>(*getParameter("creation-date")).setValue(creationDate);
}
void contentDispositionField::copyFrom(const headerField& field)
const datetime& contentDispositionField::getModificationDate() const
{
const contentDispositionField& source = dynamic_cast<const contentDispositionField&>(field);
m_value = source.m_value;
return (dynamic_cast <const dateParameter&>(*findParameter("modification-date")).getValue());
}
parameterizedHeaderField::copyFrom(field);
void contentDispositionField::setModificationDate(const datetime& modificationDate)
{
dynamic_cast <dateParameter&>(*getParameter("modification-date")).setValue(modificationDate);
}
const datetime& contentDispositionField::getReadDate() const
{
return (dynamic_cast <const dateParameter&>(*findParameter("read-date")).getValue());
}
void contentDispositionField::setReadDate(const datetime& readDate)
{
dynamic_cast <dateParameter&>(*getParameter("read-date")).setValue(readDate);
}
const string contentDispositionField::getFilename() const
{
return (dynamic_cast <const defaultParameter&>(*findParameter("filename")).getValue());
}
void contentDispositionField::setFilename(const string& filename)
{
dynamic_cast <defaultParameter&>(*getParameter("filename")).setValue(filename);
}
const string contentDispositionField::getSize() const
{
return (dynamic_cast <const defaultParameter&>(*findParameter("size")).getValue());
}
void contentDispositionField::setSize(const string& size)
{
dynamic_cast <defaultParameter&>(*getParameter("size")).setValue(size);
}

View File

@ -22,54 +22,41 @@
#include "parameterizedHeaderField.hpp"
#include "disposition.hpp"
#include "genericField.hpp"
#include "dateParameter.hpp"
#include "textParameter.hpp"
#include "disposition.hpp"
#include "dateTime.hpp"
namespace vmime
{
class contentDispositionField : public parameterizedHeaderField
class contentDispositionField : public parameterizedHeaderField, public genericField <disposition>
{
friend class headerFieldFactory::registerer <contentDispositionField>;
protected:
contentDispositionField();
contentDispositionField(contentDispositionField&);
public:
void copyFrom(const headerField& field);
const datetime& getCreationDate() const;
void setCreationDate(const datetime& creationDate);
contentDispositionField& operator=(const disposition& type);
const datetime& getModificationDate() const;
void setModificationDate(const datetime& modificationDate);
const disposition& value() const { return (m_value); }
disposition& value() { return (m_value); }
const datetime& getReadDate() const;
void setReadDate(const datetime& readDate);
const datetime& creationDate() const { return (dynamic_cast<const dateParameter&>(parameters.find("creation-date")).value()); }
datetime& creationDate() { return (dynamic_cast<dateParameter&>(parameters.get("creation-date")).value()); }
const string getFilename() const;
void setFilename(const string& filename);
const datetime& modificationDate() const { return (dynamic_cast<const dateParameter&>(parameters.find("modification-date")).value()); }
datetime& modificationDate() { return (dynamic_cast<dateParameter&>(parameters.get("modification-date")).value()); }
const datetime& readDate() const { return (dynamic_cast<const dateParameter&>(parameters.find("read-date")).value()); }
datetime& readDate() { return (dynamic_cast<dateParameter&>(parameters.get("read-date")).value()); }
const string& filename() const { return (dynamic_cast<const textParameter&>(parameters.find("filename")).value()); }
string& filename() { return (dynamic_cast<textParameter&>(parameters.get("filename")).value()); }
const string& size() const { return (dynamic_cast<const textParameter&>(parameters.find("size")).value()); }
string& size() { return (dynamic_cast<textParameter&>(parameters.get("size")).value()); }
protected:
disposition m_value;
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
const string generateValue() const;
const string getSize() const;
void setSize(const string& size);
};

View File

@ -1,62 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "contentEncodingField.hpp"
#include "exception.hpp"
namespace vmime
{
contentEncodingField::contentEncodingField()
{
}
void contentEncodingField::parseValue(const string& buffer, const string::size_type position,
const string::size_type end)
{
m_value.parse(buffer, position, end);
}
const string contentEncodingField::generateValue() const
{
return (m_value.generate());
}
contentEncodingField& contentEncodingField::operator=(const encoding& type)
{
m_value = type;
return (*this);
}
void contentEncodingField::copyFrom(const headerField& field)
{
const contentEncodingField& source = dynamic_cast<const contentEncodingField&>(field);
m_value = source.m_value;
parameterizedHeaderField::copyFrom(field);
}
} // vmime

View File

@ -1,61 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_CONTENTENCODINGFIELD_HPP_INCLUDED
#define VMIME_CONTENTENCODINGFIELD_HPP_INCLUDED
#include "defaultParameterizedHeaderField.hpp"
#include "encoding.hpp"
namespace vmime
{
class contentEncodingField : public parameterizedHeaderField
{
friend class headerFieldFactory::registerer <contentEncodingField>;
protected:
contentEncodingField();
public:
void copyFrom(const headerField& field);
contentEncodingField& operator=(const encoding& type);
const encoding& value() const { return (m_value); }
encoding& value() { return (m_value); }
protected:
encoding m_value;
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
const string generateValue() const;
};
} // vmime
#endif // VMIME_CONTENTENCODINGFIELD_HPP_INCLUDED

View File

@ -69,7 +69,7 @@ contentHandler& contentHandler::operator=(const contentHandler& cts)
}
void contentHandler::set(const utility::stringProxy& str, const vmime::encoding& enc)
void contentHandler::setData(const utility::stringProxy& str, const vmime::encoding& enc)
{
m_type = TYPE_STRING;
m_encoding = enc;
@ -81,7 +81,7 @@ void contentHandler::set(const utility::stringProxy& str, const vmime::encoding&
}
void contentHandler::set(const string& buffer, const vmime::encoding& enc)
void contentHandler::setData(const string& buffer, const vmime::encoding& enc)
{
m_type = TYPE_STRING;
m_encoding = enc;
@ -93,7 +93,7 @@ void contentHandler::set(const string& buffer, const vmime::encoding& enc)
}
void contentHandler::set(const string& buffer, const string::size_type start,
void contentHandler::setData(const string& buffer, const string::size_type start,
const string::size_type end, const vmime::encoding& enc)
{
m_type = TYPE_STRING;
@ -106,7 +106,7 @@ void contentHandler::set(const string& buffer, const string::size_type start,
}
void contentHandler::set(utility::inputStream* const is, const string::size_type length,
void contentHandler::setData(utility::inputStream* const is, const utility::stream::size_type length,
const bool own, const vmime::encoding& enc)
{
m_type = TYPE_STREAM;
@ -131,7 +131,7 @@ void contentHandler::set(utility::inputStream* const is, const string::size_type
contentHandler& contentHandler::operator=(const string& buffer)
{
set(buffer, NO_ENCODING);
setData(buffer, NO_ENCODING);
return (*this);
}
@ -154,7 +154,7 @@ void contentHandler::generate(utility::outputStream& os, const vmime::encoding&
utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
theEncoder->properties()["maxlinelength"] = maxLineLength;
theEncoder->getProperties()["maxlinelength"] = maxLineLength;
switch (m_type)
{
@ -234,7 +234,7 @@ void contentHandler::generate(utility::outputStream& os, const vmime::encoding&
else
{
utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
theEncoder->properties()["maxlinelength"] = maxLineLength;
theEncoder->getProperties()["maxlinelength"] = maxLineLength;
// Encode the contents
switch (m_type)
@ -335,7 +335,7 @@ void contentHandler::extract(utility::outputStream& os) const
}
const string::size_type contentHandler::length() const
const string::size_type contentHandler::getLength() const
{
switch (m_type)
{
@ -348,7 +348,7 @@ const string::size_type contentHandler::length() const
}
const bool contentHandler::empty() const
const bool contentHandler::isEmpty() const
{
return (m_type == TYPE_NONE);
}
@ -360,7 +360,7 @@ const bool contentHandler::isEncoded() const
}
const vmime::encoding& contentHandler::encoding() const
const vmime::encoding& contentHandler::getEncoding() const
{
return (m_encoding);
}

View File

@ -62,10 +62,10 @@ public:
//
// The 'length' parameter is optional (user-defined). You can pass 0 if you want,
// VMime does not make use of it.
void set(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING);
void set(const string& buffer, const vmime::encoding& enc = NO_ENCODING);
void set(const string& buffer, const string::size_type start, const string::size_type end, const vmime::encoding& enc = NO_ENCODING);
void set(utility::inputStream* const is, const utility::stream::size_type length, const bool own, const vmime::encoding& enc = NO_ENCODING);
void setData(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING);
void setData(const string& buffer, const vmime::encoding& enc = NO_ENCODING);
void setData(const string& buffer, const string::size_type start, const string::size_type end, const vmime::encoding& enc = NO_ENCODING);
void setData(utility::inputStream* const is, const utility::stream::size_type length, const bool own, const vmime::encoding& enc = NO_ENCODING);
// For compatibility
contentHandler& operator=(const string& buffer);
@ -82,16 +82,16 @@ public:
// Returns the actual length of the data. WARNING: this can return 0 if no
// length was specified when setting data of this object.
const string::size_type length() const;
const string::size_type getLength() const;
// Returns 'true' if the data managed by this object is encoded.
const bool isEncoded() const;
// Returns the encoding used for the data (or "binary" if not encoded).
const vmime::encoding& encoding() const;
const vmime::encoding& getEncoding() const;
// Returns 'true' if there is no data set.
const bool empty() const;
const bool isEmpty() const;
private:

View File

@ -20,6 +20,8 @@
#include "contentTypeField.hpp"
#include "exception.hpp"
#include "standardParams.hpp"
namespace vmime
{
@ -30,32 +32,33 @@ contentTypeField::contentTypeField()
}
void contentTypeField::parseValue(const string& buffer,
const string::size_type position, const string::size_type end)
contentTypeField::contentTypeField(contentTypeField&)
: headerField(), parameterizedHeaderField(), genericField <mediaType>()
{
m_value.parse(buffer, position, end);
}
const string contentTypeField::generateValue() const
const string contentTypeField::getBoundary() const
{
return (m_value.generate());
return (dynamic_cast <const defaultParameter&>(*findParameter("boundary")).getValue());
}
contentTypeField& contentTypeField::operator=(const mediaType& type)
void contentTypeField::setBoundary(const string& boundary)
{
m_value = type;
return (*this);
dynamic_cast <defaultParameter&>(*getParameter("boundary")).setValue(boundary);
}
void contentTypeField::copyFrom(const headerField& field)
const charset& contentTypeField::getCharset() const
{
const contentTypeField& source = dynamic_cast<const contentTypeField&>(field);
m_value = source.m_value;
return (dynamic_cast <const charsetParameter&>(*findParameter("charset")).getValue());
}
parameterizedHeaderField::copyFrom(field);
void contentTypeField::setCharset(const charset& ch)
{
dynamic_cast <charsetParameter&>(*getParameter("charset")).setValue(ch);
}

View File

@ -22,47 +22,32 @@
#include "parameterizedHeaderField.hpp"
#include "genericField.hpp"
#include "mediaType.hpp"
#include "charset.hpp"
#include "textParameter.hpp"
#include "charsetParameter.hpp"
namespace vmime
{
class contentTypeField : public parameterizedHeaderField
class contentTypeField : public parameterizedHeaderField, public genericField <mediaType>
{
friend class headerFieldFactory::registerer <contentTypeField>;
protected:
contentTypeField();
contentTypeField(contentTypeField&);
public:
void copyFrom(const headerField& field);
const string getBoundary() const;
void setBoundary(const string& boundary);
contentTypeField& operator=(const mediaType& type);
const mediaType& value() const { return (m_value); }
mediaType& value() { return (m_value); }
const string& boundary() const { return (dynamic_cast<const textParameter&>(parameters.find("boundary")).value()); }
string& boundary() { return (dynamic_cast<textParameter&>(parameters.get("boundary")).value()); }
const class charset& charset() const { return (dynamic_cast<const charsetParameter&>(parameters.find("charset")).value()); }
class charset& charset() { return (dynamic_cast<charsetParameter&>(parameters.get("charset")).value()); }
protected:
mediaType m_value;
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
const string generateValue() const;
const charset& getCharset() const;
void setCharset(const charset& ch);
};

View File

@ -1,66 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "dateField.hpp"
namespace vmime
{
dateField::dateField()
{
}
void dateField::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
m_datetime.parse(buffer, position, end, newPosition);
}
void dateField::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
string::size_type pos = curLinePos;
headerField::generate(os, maxLineLength, pos, &pos);
m_datetime.generate(os, maxLineLength, pos, newLinePos);
}
dateField& dateField::operator=(const class datetime& datetime)
{
m_datetime = datetime;
return (*this);
}
void dateField::copyFrom(const headerField& field)
{
const dateField& source = dynamic_cast<const dateField&>(field);
m_datetime = source.m_datetime;
headerField::copyFrom(field);
}
} // vmime

View File

@ -1,70 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_DATEFIELD_HPP_INCLUDED
#define VMIME_DATEFIELD_HPP_INCLUDED
#include "base.hpp"
#include "component.hpp"
#include "headerFieldFactory.hpp"
#include "dateTime.hpp"
namespace vmime
{
class dateField : public headerField
{
friend class headerFieldFactory::registerer <dateField>;
protected:
dateField();
public:
void copyFrom(const headerField& field);
dateField& operator=(const class datetime& datetime);
const datetime& value() const { return (m_datetime); }
datetime& value() { return (m_datetime); }
protected:
datetime m_datetime;
public:
using headerField::parse;
using headerField::generate;
// Component parsing & assembling
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
};
} // vmime
#endif // VMIME_DATEFIELD_HPP_INCLUDED

View File

@ -1,50 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "dateParameter.hpp"
#include "parserHelpers.hpp"
namespace vmime
{
void dateParameter::parseValue(const string& buffer, const string::size_type position,
const string::size_type end)
{
m_value.parse(buffer, position, end);
}
const string dateParameter::generateValue() const
{
return (m_value.generate());
}
void dateParameter::copyFrom(const parameter& param)
{
const dateParameter& source = dynamic_cast<const dateParameter&>(param);
m_value = source.m_value;
defaultParameter::copyFrom(param);
}
} // vmime

View File

@ -86,7 +86,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p))
{
// Month day
comp_t day = 0;
int day = 0;
do
{
@ -221,7 +221,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p))
{
// Year
comp_t year = 0;
int year = 0;
do
{
@ -249,7 +249,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p))
{
// Hour
comp_t hour = 0;
int hour = 0;
do
{
@ -271,7 +271,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p))
{
// Minute
comp_t minute = 0;
int minute = 0;
do
{
@ -293,7 +293,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p))
{
// Second
comp_t second = 0;
int second = 0;
do
{
@ -342,7 +342,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
++p;
// Zone offset (in hour/minutes)
comp_t offset = 0;
int offset = 0;
do
{
@ -351,8 +351,8 @@ void datetime::parse(const string& buffer, const string::size_type position,
}
while (p < pend && isdigit(*p));
const comp_t hourOff = offset / 100;
const comp_t minOff = offset % 100;
const int hourOff = offset / 100;
const int minOff = offset % 100;
if (sign == '+')
m_zone = hourOff * 60 + minOff;
@ -538,13 +538,13 @@ void datetime::generate(utility::outputStream& os, const string::size_type /* ma
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
const comp_t z = ((m_zone < 0) ? -m_zone : m_zone);
const comp_t zh = z / 60;
const comp_t zm = z % 60;
const int z = ((m_zone < 0) ? -m_zone : m_zone);
const int zh = z / 60;
const int zm = z % 60;
std::ostringstream oss;
oss << dayNames[dayOfWeek(m_year, m_month, m_day)] << ", "
<< m_day << " " << monthNames[month() - 1] << " " << year()
<< m_day << " " << monthNames[m_month - 1] << " " << m_year
<< " " << std::setfill('0') << std::setw(2) << m_hour << ":"
<< std::setfill('0') << std::setw(2) << m_minute << ":"
<< std::setfill('0') << std::setw(2) << m_second
@ -566,16 +566,16 @@ datetime::datetime()
}
datetime::datetime(const comp_t year, const comp_t month, const comp_t day)
datetime::datetime(const int year, const int month, const int day)
: m_year(year), m_month(month), m_day(day),
m_hour(0), m_minute(0), m_second(0), m_zone(0)
{
}
datetime::datetime(const comp_t year, const comp_t month, const comp_t day,
const comp_t hour, const comp_t minute, const comp_t second,
const comp_t zone)
datetime::datetime(const int year, const int month, const int day,
const int hour, const int minute, const int second,
const int zone)
: m_year(year), m_month(month), m_day(day),
m_hour(hour), m_minute(minute), m_second(second), m_zone(zone)
{
@ -600,8 +600,10 @@ datetime::~datetime()
}
void datetime::copyFrom(const datetime& d)
void datetime::copyFrom(const component& other)
{
const datetime& d = dynamic_cast <const datetime&>(other);
m_year = d.m_year;
m_month = d.m_month;
m_day = d.m_day;
@ -612,9 +614,9 @@ void datetime::copyFrom(const datetime& d)
}
datetime& datetime::operator=(const datetime& d)
datetime& datetime::operator=(const datetime& other)
{
copyFrom(d);
copyFrom(other);
return (*this);
}
@ -626,7 +628,7 @@ datetime& datetime::operator=(const string& s)
}
void datetime::getTime(comp_t& hour, comp_t& minute, comp_t& second, comp_t& zone) const
void datetime::getTime(int& hour, int& minute, int& second, int& zone) const
{
hour = m_hour;
minute = m_minute;
@ -635,7 +637,7 @@ void datetime::getTime(comp_t& hour, comp_t& minute, comp_t& second, comp_t& zon
}
void datetime::getTime(comp_t& hour, comp_t& minute, comp_t& second) const
void datetime::getTime(int& hour, int& minute, int& second) const
{
hour = m_hour;
minute = m_minute;
@ -643,7 +645,7 @@ void datetime::getTime(comp_t& hour, comp_t& minute, comp_t& second) const
}
void datetime::getDate(comp_t& year, comp_t& month, comp_t& day) const
void datetime::getDate(int& year, int& month, int& day) const
{
year = m_year;
month = m_month;
@ -651,8 +653,8 @@ void datetime::getDate(comp_t& year, comp_t& month, comp_t& day) const
}
void datetime::setTime(const comp_t hour, const comp_t minute,
const comp_t second, const comp_t zone)
void datetime::setTime(const int hour, const int minute,
const int second, const int zone)
{
m_hour = hour;
m_minute = minute;
@ -661,7 +663,7 @@ void datetime::setTime(const comp_t hour, const comp_t minute,
}
void datetime::setDate(const comp_t year, const comp_t month, const comp_t day)
void datetime::setDate(const int year, const int month, const int day)
{
m_year = year;
m_month = month;
@ -669,10 +671,10 @@ void datetime::setDate(const comp_t year, const comp_t month, const comp_t day)
}
const datetime::comp_t datetime::dayOfWeek(const comp_t year, const comp_t month, const comp_t day)
const int datetime::dayOfWeek(const int year, const int month, const int day)
{
comp_t y = year;
comp_t m = month;
int y = year;
int m = month;
// From RFC-3339 - Appendix B. Day of the Week
@ -686,7 +688,7 @@ const datetime::comp_t datetime::dayOfWeek(const comp_t year, const comp_t month
}
// Split by century
const comp_t cent = y / 100;
const int cent = y / 100;
y %= 100;
return (((26 * m - 2) / 10 + day + y + (y >> 2) + (cent >> 2) + 5 * cent) % 7);
@ -699,4 +701,27 @@ const datetime datetime::now()
}
datetime* datetime::clone() const
{
return new datetime(*this);
}
const int datetime::getYear() const { return (m_year); }
const int datetime::getMonth() const { return (m_month); }
const int datetime::getDay() const { return (m_day); }
const int datetime::getHour() const { return (m_hour); }
const int datetime::getMinute() const { return (m_minute); }
const int datetime::getSecond() const { return (m_second); }
const int datetime::getZone() const { return (m_zone); }
void datetime::setYear(const int year) { m_year = year; }
void datetime::setMonth(const int month) { m_month = std::min(std::max(month, 1), 12); }
void datetime::setDay(const int day) { m_day = day; }
void datetime::setHour(const int hour) { m_hour = hour; }
void datetime::setMinute(const int minute) { m_minute = minute; }
void datetime::setSecond(const int second) { m_second = second; }
void datetime::setZone(const int zone) { m_zone = zone; }
} // vmime

View File

@ -36,13 +36,10 @@ class datetime : public component
{
public:
// Data type for a date/time component
typedef int comp_t;
// Constructors
datetime();
datetime(const comp_t year, const comp_t month, const comp_t day);
datetime(const comp_t year, const comp_t month, const comp_t day, const comp_t hour, const comp_t minute, const comp_t second, const comp_t zone = GMT);
datetime(const int year, const int month, const int day);
datetime(const int year, const int month, const int day, const int hour, const int minute, const int second, const int zone = GMT);
datetime(const datetime& d);
datetime(const string& date);
@ -172,58 +169,60 @@ public:
SAT = 6
};
protected:
private:
// Date components
comp_t m_year;
comp_t m_month;
comp_t m_day;
int m_year;
int m_month;
int m_day;
// Time components
comp_t m_hour;
comp_t m_minute;
comp_t m_second;
comp_t m_zone;
int m_hour;
int m_minute;
int m_second;
int m_zone;
public:
// Get
const comp_t year() const { return (m_year); }
const comp_t month() const { return (m_month); }
const comp_t day() const { return (m_day); }
const comp_t hour() const { return (m_hour); }
const comp_t minute() const { return (m_minute); }
const comp_t second() const { return (m_second); }
const comp_t zone() const { return (m_zone); }
const int getYear() const;
const int getMonth() const;
const int getDay() const;
const int getHour() const;
const int getMinute() const;
const int getSecond() const;
const int getZone() const;
void getTime(comp_t& hour, comp_t& minute, comp_t& second, comp_t& zone) const;
void getTime(comp_t& hour, comp_t& minute, comp_t& second) const;
void getDate(comp_t& year, comp_t& month, comp_t& day) const;
void getTime(int& hour, int& minute, int& second, int& zone) const;
void getTime(int& hour, int& minute, int& second) const;
void getDate(int& year, int& month, int& day) const;
// Set
comp_t& year() { return (m_year); }
comp_t& month() { return (m_month); }
comp_t& day() { return (m_day); }
comp_t& hour() { return (m_hour); }
comp_t& minute() { return (m_minute); }
comp_t& second() { return (m_second); }
comp_t& zone() { return (m_zone); }
void setYear(const int year);
void setMonth(const int month);
void setDay(const int day);
void setHour(const int hour);
void setMinute(const int minute);
void setSecond(const int second);
void setZone(const int zone);
void setTime(const comp_t hour = 0, const comp_t minute = 0, const comp_t second = 0, const comp_t zone = GMT);
void setDate(const comp_t year, const comp_t month, const comp_t day);
void setTime(const int hour = 0, const int minute = 0, const int second = 0, const int zone = GMT);
void setDate(const int year, const int month, const int day);
// Assignment
datetime& operator=(const datetime& d);
datetime& operator=(const datetime& other);
datetime& operator=(const string& s);
void copyFrom(const datetime& d);
void copyFrom(const component& other);
datetime* clone() const;
// Current date and time
static const datetime now();
protected:
private:
static const comp_t dayOfWeek(const comp_t year, const comp_t month, const comp_t day);
static const int dayOfWeek(const int year, const int month, const int day);
public:

View File

@ -31,7 +31,7 @@ defaultAttachment::defaultAttachment()
defaultAttachment::defaultAttachment(const contentHandler& data,
const class encoding& enc, const mediaType& type, const text& desc)
const encoding& enc, const mediaType& type, const text& desc)
: m_type(type), m_desc(desc), m_data(data), m_encoding(enc)
{
}
@ -51,15 +51,12 @@ defaultAttachment::defaultAttachment(const defaultAttachment& attach)
}
attachment& defaultAttachment::operator=(const attachment& attach)
defaultAttachment& defaultAttachment::operator=(const defaultAttachment& attach)
{
const defaultAttachment& att =
dynamic_cast <const defaultAttachment&>(attach);
m_type = att.m_type;
m_desc = att.m_desc;
m_data = att.m_data;
m_encoding = att.m_encoding;
m_type = attach.m_type;
m_desc = attach.m_desc;
m_data = attach.m_data;
m_encoding = attach.m_encoding;
return (*this);
}
@ -69,7 +66,7 @@ void defaultAttachment::generateIn(bodyPart& parent) const
{
// Create and append a new part for this attachment
bodyPart* part = new bodyPart;
parent.body().parts.append(part);
parent.getBody()->appendPart(part);
generatePart(*part);
}
@ -78,13 +75,37 @@ void defaultAttachment::generateIn(bodyPart& parent) const
void defaultAttachment::generatePart(bodyPart& part) const
{
// Set header fields
part.header().fields.ContentType() = m_type;
if (!m_desc.empty()) part.header().fields.ContentDescription() = m_desc;
part.header().fields.ContentTransferEncoding() = m_encoding;
part.header().fields.ContentDisposition() = disposition(dispositionTypes::ATTACHMENT);
part.getHeader()->ContentType().setValue(m_type);
if (!m_desc.isEmpty()) part.getHeader()->ContentDescription().setValue(m_desc);
part.getHeader()->ContentTransferEncoding().setValue(m_encoding);
part.getHeader()->ContentDisposition().setValue(disposition(dispositionTypes::ATTACHMENT));
// Set contents
part.body().contents() = m_data;
part.getBody()->getContents() = m_data;
}
const mediaType& defaultAttachment::getType() const
{
return (m_type);
}
const text& defaultAttachment::getDescription() const
{
return (m_desc);
}
const contentHandler& defaultAttachment::getData() const
{
return (m_data);
}
const encoding& defaultAttachment::getEncoding() const
{
return (m_encoding);
}

View File

@ -38,27 +38,31 @@ protected:
public:
defaultAttachment(const contentHandler& data, const class encoding& enc, const mediaType& type, const text& desc = NULL_TEXT);
defaultAttachment(const contentHandler& data, const encoding& enc, const mediaType& type, const text& desc = NULL_TEXT);
defaultAttachment(const contentHandler& data, const mediaType& type, const text& desc = NULL_TEXT);
defaultAttachment(const defaultAttachment& attach);
attachment& operator=(const attachment& attach);
defaultAttachment& operator=(const defaultAttachment& attach);
const mediaType& type() const { return (m_type); }
const text& description() const { return (m_desc); }
const contentHandler& data() const { return (m_data); }
const class encoding& encoding() const { return (m_encoding); }
const mediaType& getType() const;
const text& getDescription() const;
const contentHandler& getData() const;
const encoding& getEncoding() const;
protected:
mediaType m_type; // Media type (eg. "application/octet-stream")
text m_desc; // Description (eg. "The image you requested")
contentHandler m_data; // Attachment data (eg. the file contents)
class encoding m_encoding; // Encoding
encoding m_encoding; // Encoding
private:
// No need to override "generateIn", use "generatePart" instead (see below).
void generateIn(bodyPart& parent) const;
protected:
virtual void generatePart(bodyPart& part) const;
};

View File

@ -1,71 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "defaultField.hpp"
#include "text.hpp"
namespace vmime
{
defaultField::defaultField()
{
}
void defaultField::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
m_text = string(buffer.begin() + position, buffer.begin() + end);
if (newPosition)
*newPosition = end;
}
void defaultField::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
string::size_type pos = curLinePos;
headerField::generate(os, maxLineLength, pos, &pos);
encodeAndFoldText(os, vmime::text(word(m_text, charset())), maxLineLength,
pos, newLinePos, encodeAndFoldFlags::forceNoEncoding);
}
defaultField& defaultField::operator=(const string& text)
{
m_text = text;
return (*this);
}
void defaultField::copyFrom(const headerField& field)
{
const defaultField& source = dynamic_cast<const defaultField&>(field);
m_text = source.m_text;
headerField::copyFrom(field);
}
} // vmime

View File

@ -1,70 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_DEFAULTFIELD_HPP_INCLUDED
#define VMIME_DEFAULTFIELD_HPP_INCLUDED
#include "base.hpp"
#include "component.hpp"
#include "headerFieldFactory.hpp"
namespace vmime
{
class defaultField : public headerField
{
friend class headerFieldFactory;
friend class headerFieldFactory::registerer <defaultField>;
protected:
defaultField();
public:
void copyFrom(const headerField& field);
defaultField& operator=(const string& text);
const string& value() const { return (m_text); }
string& value() { return (m_text); }
protected:
string m_text;
public:
using headerField::parse;
using headerField::generate;
// Component parsing & assembling
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
};
} // vmime
#endif // VMIME_DEFAULTFIELD_HPP_INCLUDED

View File

@ -1,117 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "defaultParameter.hpp"
namespace vmime
{
void defaultParameter::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
parseValue(buffer, position, end);
if (newPosition)
*newPosition = end;
}
void defaultParameter::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
string::size_type pos = curLinePos;
const string value = quotedValue();
pos += m_name.length() + value.length() + 2;
if (pos > maxLineLength)
{
os << NEW_LINE_SEQUENCE;
pos = NEW_LINE_SEQUENCE_LENGTH;
}
os << m_name << "=" << value;
if (newLinePos)
*newLinePos = pos;
}
const string defaultParameter::quotedValue() const
{
const string value(generateValue());
std::ostringstream ss;
string::const_iterator start = value.begin();
bool quoted = false;
for (string::const_iterator i = value.begin() ; i != value.end() ; ++i)
{
switch (*i)
{
// Characters that need to be quoted _and_ escaped
case '"':
case '\\':
ss << string(start, i) << "\\" << *i;
start = i + 1;
quoted = true;
break;
// Other characters that need quoting
case ' ':
case '\t':
case '(':
case ')':
case '<':
case '>':
case '@':
case ',':
case ';':
case ':':
case '/':
case '[':
case ']':
case '?':
case '=':
quoted = true;
break;
}
}
if (start != value.end())
ss << string(start, value.end());
return (quoted ? ("\"" + ss.str() + "\"") : (ss.str()));
}
void defaultParameter::copyFrom(const parameter& param)
{
parameter::copyFrom(param);
}
} // vmime

View File

@ -1,55 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_DEFAULTPARAMETER_HPP_INCLUDED
#define VMIME_DEFAULTPARAMETER_HPP_INCLUDED
#include "parameter.hpp"
namespace vmime
{
class defaultParameter : public parameter
{
protected:
void copyFrom(const parameter& param);
virtual void parseValue(const string& buffer, const string::size_type position, const string::size_type end) = 0;
virtual const string generateValue() const = 0;
private:
const string quotedValue() const;
// No need to override these in class that derive from "defaultParameter".
// "defaultParameter" provides a default handling for value parsing/building.
// Instead, you must define two functions: "parseValue" and "generateValue" (see above).
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
};
} // vmime
#endif // VMIME_DEFAULTPARAMETER_HPP_INCLUDED

View File

@ -1,62 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "defaultParameterizedHeaderField.hpp"
namespace vmime
{
defaultParameterizedHeaderField::defaultParameterizedHeaderField()
{
}
void defaultParameterizedHeaderField::parseValue(const string& buffer,
const string::size_type position, const string::size_type end)
{
m_value = string(buffer.begin() + position, buffer.begin() + end);
}
const string defaultParameterizedHeaderField::generateValue() const
{
return (m_value);
}
void defaultParameterizedHeaderField::copyFrom(const headerField& field)
{
const defaultParameterizedHeaderField& source = dynamic_cast
<const defaultParameterizedHeaderField&>(field);
m_value = source.m_value;
parameterizedHeaderField::copyFrom(field);
}
defaultParameterizedHeaderField& defaultParameterizedHeaderField::operator=(const string& value)
{
m_value = value;
return (*this);
}
} // vmime

View File

@ -1,63 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_DEFAULTPARAMETERIZEDHEADERFIELD_HPP_INCLUDED
#define VMIME_DEFAULTPARAMETERIZEDHEADERFIELD_HPP_INCLUDED
#include "parameterizedHeaderField.hpp"
#include "base.hpp"
namespace vmime
{
class defaultParameterizedHeaderField : public parameterizedHeaderField
{
friend class headerFieldFactory::registerer <defaultParameterizedHeaderField>;
protected:
defaultParameterizedHeaderField();
public:
void copyFrom(const headerField& field);
defaultParameterizedHeaderField& operator=(const string& value);
const string& value() const { return (m_value); }
string& value() { return (m_value); }
protected:
string m_value;
protected:
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
const string generateValue() const;
};
} // vmime
#endif // VMIME_DEFAULTPARAMETERIZEDHEADERFIELD_HPP_INCLUDED

View File

@ -18,6 +18,7 @@
//
#include "disposition.hpp"
#include "utility/stringUtils.hpp"
namespace vmime
@ -31,7 +32,7 @@ disposition::disposition()
disposition::disposition(const string& name)
: m_name(toLower(name))
: m_name(stringUtils::toLower(name))
{
}
@ -45,7 +46,7 @@ disposition::disposition(const disposition& type)
void disposition::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
m_name = toLower(string(buffer.begin() + position, buffer.begin() + end));
m_name = stringUtils::toLower(string(buffer.begin() + position, buffer.begin() + end));
if (newPosition)
*newPosition = end;
@ -62,23 +63,16 @@ void disposition::generate(utility::outputStream& os, const string::size_type /*
}
disposition& disposition::operator=(const disposition& source)
{
m_name = source.m_name;
return (*this);
}
disposition& disposition::operator=(const string& name)
{
m_name = toLower(name);
m_name = stringUtils::toLower(name);
return (*this);
}
const bool disposition::operator==(const disposition& value) const
{
return (toLower(m_name) == value.m_name);
return (stringUtils::toLower(m_name) == value.m_name);
}
@ -88,4 +82,37 @@ const bool disposition::operator!=(const disposition& value) const
}
disposition* disposition::clone() const
{
return new disposition(*this);
}
void disposition::copyFrom(const component& other)
{
const disposition& d = dynamic_cast <const disposition&>(other);
m_name = d.m_name;
}
disposition& disposition::operator=(const disposition& other)
{
copyFrom(other);
return (*this);
}
const string& disposition::getName() const
{
return (m_name);
}
void disposition::setName(const string& name)
{
m_name = name;
}
} // vmime

View File

@ -40,20 +40,32 @@ public:
disposition(const string& name);
disposition(const disposition& disp);
public:
const string& name() const { return (m_name); }
string& name() { return (m_name); }
/** Return the disposition type.
* See the constants in vmime::dispositionTypes.
*
* @return name of the encoding (eg. "inline")
*/
const string& getName() const;
/** Set the disposition type.
* See the constants in vmime::dispositionTypes.
*
* @param name name of the encoding
*/
void setName(const string& name);
disposition* clone() const;
void copyFrom(const component& other);
disposition& operator=(const disposition& other);
public:
disposition& operator=(const disposition& source);
disposition& operator=(const string& name);
const bool operator==(const disposition& value) const;
const bool operator!=(const disposition& value) const;
protected:
private:
string m_name;

View File

@ -35,31 +35,31 @@ encoder::~encoder()
}
const propertySet& encoder::properties() const
const propertySet& encoder::getProperties() const
{
return (m_props);
}
propertySet& encoder::properties()
propertySet& encoder::getProperties()
{
return (m_props);
}
const propertySet& encoder::results() const
const propertySet& encoder::getResults() const
{
return (m_results);
}
propertySet& encoder::results()
propertySet& encoder::getResults()
{
return (m_results);
}
const std::vector <string> encoder::availableProperties() const
const std::vector <string> encoder::getAvailableProperties() const
{
std::vector <string> list;
return (list);

View File

@ -57,30 +57,30 @@ public:
*
* @return properties of the encoder
*/
const propertySet& properties() const;
const propertySet& getProperties() const;
/** Return the properties of the encoder.
*
* @return properties of the encoder
*/
propertySet& properties();
propertySet& getProperties();
/** Return a list of property names that can be set for
* this encoder.
*
* @return list of property names
*/
virtual const std::vector <string> availableProperties() const;
virtual const std::vector <string> getAvailableProperties() const;
/** Return the results returned by this encoder.
*
* @return results returned by the encoder
*/
const propertySet& results() const;
const propertySet& getResults() const;
protected:
propertySet& results();
propertySet& getResults();
private:

View File

@ -30,9 +30,9 @@ encoderB64::encoderB64()
}
const std::vector <string> encoderB64::availableProperties() const
const std::vector <string> encoderB64::getAvailableProperties() const
{
std::vector <string> list(encoder::availableProperties());
std::vector <string> list(encoder::getAvailableProperties());
list.push_back("maxlinelength");
@ -70,7 +70,7 @@ const utility::stream::size_type encoderB64::encode(utility::inputStream& in, ut
{
in.reset(); // may not work...
const int propMaxLineLength = properties().get <int>("maxlinelength", -1);
const int propMaxLineLength = getProperties().getProperty <int>("maxlinelength", -1);
const bool cutLines = (propMaxLineLength != -1);
const int maxLineLength = std::min(propMaxLineLength, 76);

View File

@ -40,7 +40,7 @@ public:
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
const std::vector <string> availableProperties() const;
const std::vector <string> getAvailableProperties() const;
protected:

View File

@ -46,24 +46,58 @@ encoderFactory::encoderFactory()
encoderFactory::~encoderFactory()
{
for (NameMap::iterator it = m_nameMap.begin() ; it != m_nameMap.end() ; ++it)
delete ((*it).second);
for (std::vector <registeredEncoder*>::const_iterator it = m_encoders.begin() ;
it != m_encoders.end() ; ++it)
{
delete (*it);
}
}
encoder* encoderFactory::create(const string& name)
{
NameMap::const_iterator pos = m_nameMap.find(toLower(name));
return (getEncoderByName(name)->create());
}
if (pos != m_nameMap.end())
const encoderFactory::registeredEncoder* encoderFactory::getEncoderByName(const string& name) const
{
const string lcName(stringUtils::toLower(name));
for (std::vector <registeredEncoder*>::const_iterator it = m_encoders.begin() ;
it != m_encoders.end() ; ++it)
{
return ((*pos).second)->create();
if ((*it)->getName() == lcName)
return (*it);
}
else
throw exceptions::no_encoder_available();
}
const int encoderFactory::getEncoderCount() const
{
return (m_encoders.size());
}
const encoderFactory::registeredEncoder* encoderFactory::getEncoderAt(const int pos) const
{
return (m_encoders[pos]);
}
const std::vector <const encoderFactory::registeredEncoder*> encoderFactory::getEncoderList() const
{
std::vector <const registeredEncoder*> res;
for (std::vector <registeredEncoder*>::const_iterator it = m_encoders.begin() ;
it != m_encoders.end() ; ++it)
{
throw exceptions::no_encoder_available();
return (NULL);
res.push_back(*it);
}
return (res);
}

View File

@ -23,6 +23,7 @@
#include "encoder.hpp"
#include "utility/singleton.hpp"
#include "utility/stringUtils.hpp"
namespace vmime
@ -43,6 +44,7 @@ private:
public:
/** Information about a registered encoder. */
class registeredEncoder
{
friend class encoderFactory;
@ -53,9 +55,9 @@ public:
public:
virtual encoder* create() = 0;
virtual encoder* create() const = 0;
virtual const string& name() const = 0;
virtual const string& getName() const = 0;
};
private:
@ -71,12 +73,12 @@ private:
public:
encoder* create()
encoder* create() const
{
return new E;
}
const string& name() const
const string& getName() const
{
return (m_name);
}
@ -87,93 +89,56 @@ private:
};
typedef std::map <string, registeredEncoder*> NameMap;
NameMap m_nameMap;
std::vector <registeredEncoder*> m_encoders;
public:
/** Register a new encoder by its encoding name.
*
* @param name encoding name
*/
template <class E>
void registerName(const string& name)
{
const string _name = toLower(name);
m_nameMap.insert(NameMap::value_type(_name,
new registeredEncoderImpl <E>(_name)));
m_encoders.push_back(new registeredEncoderImpl <E>(stringUtils::toLower(name)));
}
/** Create a new encoder instance from an encoding name.
*
* @param name encoding name (eg. "base64")
* @return a new encoder instance for the specified encoding
* @throw exceptions::no_encoder_available if no encoder is registered
* for this encoding
*/
encoder* create(const string& name);
const registeredEncoder& operator[](const string& name) const;
/** Return information about a registered encoder.
*
* @param name encoding name
* @return information about this encoder
* @throw exceptions::no_encoder_available if no encoder is registered
* for this encoding
*/
const registeredEncoder* getEncoderByName(const string& name) const;
/** Return the number of registered encoders.
*
* @return number of registered encoders
*/
const int getEncoderCount() const;
class iterator;
/** Return the registered encoder at the specified position.
*
* @param pos position of the registered encoder to return
* @return registered encoder at the specified position
*/
const registeredEncoder* getEncoderAt(const int pos) const;
class const_iterator
{
friend class encoderFactory;
public:
const_iterator() { }
const_iterator(const const_iterator& it) : m_it(it.m_it) { }
const_iterator(const iterator& it) : m_it(it.m_it) { }
const_iterator& operator=(const const_iterator& it) { m_it = it.m_it; return (*this); }
const registeredEncoder& operator*() const { return (*(*m_it).second); }
const registeredEncoder* operator->() const { return ((*m_it).second); }
const_iterator& operator++() { ++m_it; return (*this); }
const_iterator operator++(int) { return (m_it++); }
const_iterator& operator--() { --m_it; return (*this); }
const_iterator operator--(int) { return (m_it--); }
const bool operator==(const const_iterator& it) const { return (m_it == it.m_it); }
const bool operator!=(const const_iterator& it) const { return (m_it != it.m_it); }
private:
const_iterator(const NameMap::const_iterator it) : m_it(it) { }
NameMap::const_iterator m_it;
};
class iterator
{
friend class encoderFactory;
friend class encoderFactory::const_iterator;
public:
iterator() { }
iterator(const iterator& it) : m_it(it.m_it) { }
iterator& operator=(const iterator& it) { m_it = it.m_it; return (*this); }
registeredEncoder& operator*() const { return (*(*m_it).second); }
registeredEncoder* operator->() const { return ((*m_it).second); }
iterator& operator++() { ++m_it; return (*this); }
iterator operator++(int) { return (m_it++); }
iterator& operator--() { --m_it; return (*this); }
iterator operator--(int) { return (m_it--); }
const bool operator==(const iterator& it) const { return (m_it == it.m_it); }
const bool operator!=(const iterator& it) const { return (m_it != it.m_it); }
private:
iterator(const NameMap::iterator it) : m_it(it) { }
NameMap::iterator m_it;
};
iterator begin() { return iterator(m_nameMap.begin()); }
iterator end() { return iterator(m_nameMap.end()); }
const_iterator begin() const { return const_iterator(m_nameMap.begin()); }
const_iterator end() const { return const_iterator(m_nameMap.end()); }
/** Return a list of all registered encoders.
*
* @return list of registered encoders
*/
const std::vector <const registeredEncoder*> getEncoderList() const;
};

View File

@ -30,9 +30,9 @@ encoderQP::encoderQP()
}
const std::vector <string> encoderQP::availableProperties() const
const std::vector <string> encoderQP::getAvailableProperties() const
{
std::vector <string> list(encoder::availableProperties());
std::vector <string> list(encoder::getAvailableProperties());
list.push_back("maxlinelength");
@ -84,10 +84,10 @@ const utility::stream::size_type encoderQP::encode(utility::inputStream& in, uti
in.reset(); // may not work...
const string::size_type propMaxLineLength =
properties().get <string::size_type>("maxlinelength", (string::size_type) -1);
getProperties().getProperty <string::size_type>("maxlinelength", (string::size_type) -1);
const bool rfc2047 = properties().get <bool>("rfc2047", false);
const bool text = properties().get <bool>("text", false); // binary mode by default
const bool rfc2047 = getProperties().getProperty <bool>("rfc2047", false);
const bool text = getProperties().getProperty <bool>("text", false); // binary mode by default
const bool cutLines = (propMaxLineLength != (string::size_type) -1);
const string::size_type maxLineLength = std::min(propMaxLineLength, (string::size_type) 74);
@ -279,7 +279,7 @@ const utility::stream::size_type encoderQP::decode(utility::inputStream& in, uti
in.reset(); // may not work...
// Process the data
const bool rfc2047 = properties().get <bool>("rfc2047", false);
const bool rfc2047 = getProperties().getProperty <bool>("rfc2047", false);
char buffer[16384];
int bufferLength = 0;

View File

@ -40,7 +40,7 @@ public:
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
const std::vector <string> availableProperties() const;
const std::vector <string> getAvailableProperties() const;
protected:

View File

@ -27,15 +27,15 @@ namespace vmime
encoderUUE::encoderUUE()
{
properties()["mode"] = 644;
properties()["filename"] = "no_name";
properties()["maxlinelength"] = 46;
getProperties()["mode"] = 644;
getProperties()["filename"] = "no_name";
getProperties()["maxlinelength"] = 46;
}
const std::vector <string> encoderUUE::availableProperties() const
const std::vector <string> encoderUUE::getAvailableProperties() const
{
std::vector <string> list(encoder::availableProperties());
std::vector <string> list(encoder::getAvailableProperties());
list.push_back("maxlinelength");
@ -63,11 +63,11 @@ const utility::stream::size_type encoderUUE::encode(utility::inputStream& in, ut
{
in.reset(); // may not work...
const string propFilename = properties().get <string>("filename", "");
const string propMode = properties().get <string>("mode", "644");
const string propFilename = getProperties().getProperty <string>("filename", "");
const string propMode = getProperties().getProperty <string>("mode", "644");
const string::size_type maxLineLength =
std::min(properties().get <string::size_type>("maxlinelength", 46),
std::min(getProperties().getProperty <string::size_type>("maxlinelength", 46),
static_cast <string::size_type>(46));
utility::stream::size_type total = 0;
@ -206,7 +206,7 @@ const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, ut
while (*p && !isspace(*p)) ++p;
results()["mode"] = string(modeStart, p);
getResults()["mode"] = string(modeStart, p);
while (*p && isspace(*p)) ++p;
@ -214,13 +214,13 @@ const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, ut
while (*p && !(*p == '\r' || *p == '\n')) ++p;
results()["filename"] = string(filenameStart, p);
getResults()["filename"] = string(filenameStart, p);
}
// No filename or mode specified
else
{
results()["filename"] = "untitled";
results()["mode"] = 644;
getResults()["filename"] = "untitled";
getResults()["mode"] = 644;
}
continue;

View File

@ -40,7 +40,7 @@ public:
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
const std::vector <string> availableProperties() const;
const std::vector <string> getAvailableProperties() const;
};

View File

@ -35,7 +35,7 @@ encoding::encoding()
encoding::encoding(const string& name)
: m_name(toLower(name))
: m_name(stringUtils::toLower(name))
{
}
@ -49,7 +49,7 @@ encoding::encoding(const encoding& enc)
void encoding::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
m_name = toLower(string(buffer.begin() + position, buffer.begin() + end));
m_name = stringUtils::toLower(string(buffer.begin() + position, buffer.begin() + end));
if (newPosition)
*newPosition = end;
@ -72,23 +72,23 @@ encoder* encoding::getEncoder() const
}
encoding& encoding::operator=(const encoding& source)
encoding& encoding::operator=(const encoding& other)
{
m_name = source.m_name;
copyFrom(other);
return (*this);
}
encoding& encoding::operator=(const string& name)
{
m_name = toLower(name);
m_name = stringUtils::toLower(name);
return (*this);
}
const bool encoding::operator==(const encoding& value) const
{
return (toLower(m_name) == value.m_name);
return (stringUtils::toLower(m_name) == value.m_name);
}
@ -154,8 +154,35 @@ const encoding encoding::decide
const encoding encoding::decide(const contentHandler& /* data */)
{
// TODO: a better solution to do that?
return (encoding(encodingTypes::BASE64));
}
encoding* encoding::clone() const
{
return new encoding(*this);
}
void encoding::copyFrom(const component& other)
{
const encoding& e = dynamic_cast <const encoding&>(other);
m_name = e.m_name;
}
const string& encoding::getName() const
{
return (m_name);
}
void encoding::setName(const string& name)
{
m_name = name;
}
} // vmime

View File

@ -46,27 +46,56 @@ public:
public:
const string& name() const { return (m_name); }
string& name() { return (m_name); }
/** Return the name of the encoding.
* See the constants in vmime::encodingTypes.
*
* @return name of the encoding (eg. "quoted-printable")
*/
const string& getName() const;
public:
/** Set the name of the encoding.
* See the constants in vmime::encodingTypes.
*
* @param name name of the encoding
*/
void setName(const string& name);
encoding& operator=(const encoding& source);
encoding& operator=(const encoding& other);
encoding& operator=(const string& name);
const bool operator==(const encoding& value) const;
const bool operator!=(const encoding& value) const;
// Decide which encoding to use based on the data
/** Decide which encoding to use based on the specified data.
*
* \deprecated Use the new decide() method which takes a contentHandler parameter.
*
* @param begin start iterator in buffer
* @param end end iterator in buffer
* @return suitable encoding for specified data
*/
static const encoding decide(const string::const_iterator begin, const string::const_iterator end);
/** Decide which encoding to use based on the specified data.
*
* @param data data used to determine encoding
* @return suitable encoding for specified data
*/
static const encoding decide(const contentHandler& data);
public:
encoding* clone() const;
void copyFrom(const component& other);
// Obtain an encoder/decoder for the current encoding type
/** Use encoderFactory to obtain an encoder/decoder object
* for the current encoding type.
*
* @throw exceptions::no_encoder_available if no encoder
* is registered for the encoding
* @return a new encoder object for the encoding type
*/
encoder* getEncoder() const;
protected:
private:
string m_name;

View File

@ -45,6 +45,8 @@ public:
};
/** List of all VMime exceptions. */
namespace exceptions
{
@ -95,6 +97,33 @@ public:
};
class no_such_part : public vmime::exception
{
public:
no_such_part() : exception("Part not found.") {}
~no_such_part() throw() {}
};
class no_such_mailbox : public vmime::exception
{
public:
no_such_mailbox() : exception("Mailbox not found.") {}
~no_such_mailbox() throw() {}
};
class no_such_address : public vmime::exception
{
public:
no_such_address() : exception("Address not found.") {}
~no_such_address() throw() {}
};
class open_file_error : public vmime::exception
{
public:

View File

@ -40,7 +40,7 @@ fileAttachment::fileAttachment(const string& filename, const mediaType& type, co
fileAttachment::fileAttachment(const string& filename, const mediaType& type,
const class encoding& enc, const text& desc)
const encoding& enc, const text& desc)
{
m_type = type;
m_desc = desc;
@ -62,7 +62,7 @@ void fileAttachment::setData(const string& filename)
throw exceptions::open_file_error();
}
m_data.set(new utility::inputStreamPointerAdapter(file, true), 0, true);
m_data.setData(new utility::inputStreamPointerAdapter(file, true), 0, true);
}
@ -70,16 +70,29 @@ void fileAttachment::generatePart(bodyPart& part) const
{
defaultAttachment::generatePart(part);
contentDispositionField& cdf = part.header().fields.ContentDisposition();
contentDispositionField& cdf = part.getHeader()->ContentDisposition();
if (m_fileInfo.hasSize()) cdf.size() = toString(m_fileInfo.getSize());
if (m_fileInfo.hasFilename()) cdf.filename() = m_fileInfo.getFilename();
if (m_fileInfo.hasCreationDate()) cdf.creationDate() = m_fileInfo.getCreationDate();
if (m_fileInfo.hasModificationDate()) cdf.modificationDate() = m_fileInfo.getModificationDate();
if (m_fileInfo.hasReadDate()) cdf.readDate() = m_fileInfo.getReadDate();
if (m_fileInfo.hasSize()) cdf.setSize(stringUtils::toString(m_fileInfo.getSize()));
if (m_fileInfo.hasFilename()) cdf.setFilename(m_fileInfo.getFilename());
if (m_fileInfo.hasCreationDate()) cdf.setCreationDate(m_fileInfo.getCreationDate());
if (m_fileInfo.hasModificationDate()) cdf.setModificationDate(m_fileInfo.getModificationDate());
if (m_fileInfo.hasReadDate()) cdf.setReadDate(m_fileInfo.getReadDate());
}
const fileAttachment::fileInfo& fileAttachment::getFileInfo() const
{
return (m_fileInfo);
}
fileAttachment::fileInfo& fileAttachment::getFileInfo()
{
return (m_fileInfo);
}
//
// fileAttachment::fileInfo
//

View File

@ -33,7 +33,7 @@ class fileAttachment : public defaultAttachment
public:
fileAttachment(const string& filename, const mediaType& type, const text& desc = NULL_TEXT);
fileAttachment(const string& filename, const mediaType& type, const class encoding& enc, const text& desc = NULL_TEXT);
fileAttachment(const string& filename, const mediaType& type, const encoding& enc, const text& desc = NULL_TEXT);
class fileInfo
{
@ -71,14 +71,14 @@ public:
datetime* m_readDate;
};
const class fileInfo& fileInfo() const { return (m_fileInfo); }
class fileInfo& fileInfo() { return (m_fileInfo); }
const fileInfo& getFileInfo() const;
fileInfo& getFileInfo();
protected:
private:
void setData(const string& filename);
class fileInfo m_fileInfo;
fileInfo m_fileInfo;
void generatePart(bodyPart& part) const;
};

91
src/genericField.hpp Normal file
View File

@ -0,0 +1,91 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_GENERICFIELD_HPP_INCLUDED
#define VMIME_GENERICFIELD_HPP_INCLUDED
#include "headerField.hpp"
#include "headerFieldFactory.hpp"
#include "typeAdapter.hpp"
namespace vmime
{
/** Generic implementation for headerField.
*/
template <class VALUE_TYPE>
class genericField : virtual public headerField
{
friend class headerFieldFactory::registerer <genericField <VALUE_TYPE> >;
protected:
genericField() { }
public:
genericField <VALUE_TYPE>& operator=(const genericField <VALUE_TYPE>& other)
{
copyFrom(other);
return (*this);
}
const VALUE_TYPE& getValue() const
{
return (m_value);
}
VALUE_TYPE& getValue()
{
return (m_value);
}
template <class TYPE>
void setValue(const TYPE& value)
{
m_value = value;
}
void setValue(const component& value)
{
const VALUE_TYPE& v = dynamic_cast <const VALUE_TYPE&>(value);
m_value = v;
}
private:
VALUE_TYPE m_value;
};
template <>
class genericField <string> : public genericField <typeAdapter <string> >
{
};
} // vmime
#endif // VMIME_GENERICFIELD_HPP_INCLUDED

91
src/genericParameter.hpp Normal file
View File

@ -0,0 +1,91 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_GENERICPARAMETER_HPP_INCLUDED
#define VMIME_GENERICPARAMETER_HPP_INCLUDED
#include "parameter.hpp"
#include "parameterFactory.hpp"
#include "typeAdapter.hpp"
namespace vmime
{
/** Generic implementation for parameter.
*/
template <class VALUE_TYPE>
class genericParameter : public parameter
{
friend class parameterFactory::registerer <genericParameter <VALUE_TYPE> >;
protected:
genericParameter() { }
public:
genericParameter <VALUE_TYPE>& operator=(const genericParameter <VALUE_TYPE>& other)
{
copyFrom(other);
return (*this);
}
const VALUE_TYPE& getValue() const
{
return (m_value);
}
VALUE_TYPE& getValue()
{
return (m_value);
}
template <class TYPE>
void setValue(const TYPE& value)
{
m_value = value;
}
void setValue(const component& value)
{
const VALUE_TYPE& v = dynamic_cast <const VALUE_TYPE&>(value);
m_value = v;
}
private:
VALUE_TYPE m_value;
};
template <>
class genericParameter <string> : public genericParameter <typeAdapter <string> >
{
};
} // vmime
#endif // VMIME_GENERICPARAMETER_HPP_INCLUDED

View File

@ -32,6 +32,7 @@ header::header()
header::~header()
{
removeAllFields();
}
@ -59,7 +60,7 @@ void header::parse(const string& buffer, const string::size_type position,
{
string::size_type pos = position;
fields.clear();
removeAllFields();
while (pos < end)
{
@ -181,8 +182,8 @@ void header::parse(const string& buffer, const string::size_type position,
}
// Add a new field to list
fields.m_fields.push_back(headerFieldFactory::getInstance()->
create(headerField::nameToType(name), name, contents));
m_fields.push_back(headerFieldFactory::getInstance()->
create(name, contents));
}
}
else
@ -220,8 +221,8 @@ void header::generate(utility::outputStream& os, const string::size_type maxLine
const string::size_type /* curLinePos */, string::size_type* newLinePos) const
{
// Generate the fields
for (std::vector <headerField*>::const_iterator
it = fields.m_fields.begin() ; it != fields.m_fields.end() ; ++it)
for (std::vector <headerField*>::const_iterator it = m_fields.begin() ;
it != m_fields.end() ; ++it)
{
(*it)->generate(os, maxLineLength);
os << CRLF;
@ -232,93 +233,91 @@ void header::generate(utility::outputStream& os, const string::size_type maxLine
}
header& header::operator=(const header& h)
header* header::clone() const
{
fields = h.fields;
header* hdr = new header();
try
{
hdr->m_fields.reserve(m_fields.size());
for (std::vector <headerField*>::const_iterator it = m_fields.begin() ;
it != m_fields.end() ; ++it)
{
hdr->m_fields.push_back((*it)->clone());
}
}
catch (std::exception&)
{
free_container(hdr->m_fields);
delete (hdr);
throw;
}
return (hdr);
}
void header::copyFrom(const component& other)
{
const header& h = dynamic_cast <const header&>(other);
std::vector <headerField*> fields;
try
{
fields.reserve(h.m_fields.size());
for (std::vector <headerField*>::const_iterator it = h.m_fields.begin() ;
it != h.m_fields.end() ; ++it)
{
fields.push_back((*it)->clone());
}
free_container(m_fields);
m_fields.resize(fields.size());
std::copy(fields.begin(), fields.end(), m_fields.begin());
}
catch (std::exception&)
{
free_container(fields);
throw;
}
}
header& header::operator=(const header& other)
{
copyFrom(other);
return (*this);
}
//////////////////////
// Fields container //
//////////////////////
header::fieldsContainer::fieldsContainer()
const bool header::hasField(const string& fieldName) const
{
}
const string name = stringUtils::toLower(fieldName);
header::fieldsContainer::~fieldsContainer()
{
for (std::vector <headerField*>::iterator i = m_fields.begin() ; i != m_fields.end() ; ++i)
delete (*i);
}
// Checks whether (at least) one field with this type/name exists
const bool header::fieldsContainer::has(const headerField::Types fieldType) const
{
std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end();
for ( ; pos != end && (*pos)->type() != fieldType ; ++pos);
for ( ; pos != end && stringUtils::toLower((*pos)->getName()) != name ; ++pos);
return (pos != end);
}
const bool header::fieldsContainer::has(const string& fieldName) const
headerField* header::findField(const string& fieldName) const
{
headerField::Types type = headerField::nameToType(fieldName);
if (type != headerField::Custom) return (has(type));
const string name = toLower(fieldName);
std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end();
for ( ; pos != end && toLower((*pos)->name()) != name ; ++pos);
return (pos != end);
}
headerField& header::fieldsContainer::find(const headerField::Types fieldType) const
{
// Find the first field that matches the specified type
std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end();
for ( ; pos != end && (*pos)->type() != fieldType ; ++pos);
// No field with this type can be found
if (pos == end)
{
throw exceptions::no_such_field();
}
// Else, return a reference to the existing field
else
{
return (**pos);
}
}
headerField& header::fieldsContainer::find(const string& fieldName) const
{
headerField::Types type = headerField::nameToType(fieldName);
if (type != headerField::Custom) return (find(type));
const string name = toLower(fieldName);
const string name = stringUtils::toLower(fieldName);
// Find the first field that matches the specified name
std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end();
for ( ; pos != end && toLower((*pos)->name()) != name ; ++pos);
for ( ; pos != end && stringUtils::toLower((*pos)->getName()) != name ; ++pos);
// No field with this name can be found
if (pos == end)
@ -328,34 +327,14 @@ headerField& header::fieldsContainer::find(const string& fieldName) const
// Else, return a reference to the existing field
else
{
return (**pos);
return (*pos);
}
}
std::vector <headerField*> header::fieldsContainer::findAllByType(const headerField::Types fieldType)
std::vector <headerField*> header::findAllFields(const string& fieldName)
{
std::vector <headerField*> result;
std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end();
for ( ; pos != end ; ++pos)
{
// Add the header if it matches the specified type
if ((*pos)->type() == fieldType)
{
result.push_back(*pos);
}
}
return result;
}
std::vector <headerField*> header::fieldsContainer::findAllByName(const string& fieldName)
{
const string name = toLower(fieldName);
const string name = stringUtils::toLower(fieldName);
std::vector <headerField*> result;
@ -365,7 +344,7 @@ std::vector <headerField*> header::fieldsContainer::findAllByName(const string&
for ( ; pos != end ; ++pos)
{
// Add the header if it matches the specified type
if (toLower((*pos)->name()) == name)
if (stringUtils::toLower((*pos)->getName()) == name)
{
result.push_back(*pos);
}
@ -375,116 +354,157 @@ std::vector <headerField*> header::fieldsContainer::findAllByName(const string&
}
headerField& header::fieldsContainer::get(const headerField::Types fieldType)
headerField* header::getField(const string& fieldName)
{
// Find the first field that matches the specified type
std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end();
for ( ; pos != end && (*pos)->type() != fieldType ; ++pos);
// If no field with this type can be found, create a new one
if (pos == end)
{
headerField* field = headerFieldFactory::getInstance()->create(fieldType);
insertSorted(field);
// Return a reference to the new field
return (*field);
}
// Else, return a reference to the existing field
else
{
return (**pos);
}
}
headerField& header::fieldsContainer::get(const string& fieldName)
{
headerField::Types type = headerField::nameToType(fieldName);
if (type != headerField::Custom) return (get(type));
const string name = toLower(fieldName);
const string name = stringUtils::toLower(fieldName);
// Find the first field that matches the specified name
std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end();
for ( ; pos != end && toLower((*pos)->name()) != name ; ++pos);
for ( ; pos != end && stringUtils::toLower((*pos)->getName()) != name ; ++pos);
// If no field with this name can be found, create a new one
if (pos == end)
{
headerField* field = headerFieldFactory::getInstance()->create(fieldName);
insertSorted(field);
try
{
appendField(field);
}
catch (std::exception&)
{
delete (field);
throw;
}
// Return a reference to the new field
return (*field);
return (field);
}
// Else, return a reference to the existing field
else
{
return (**pos);
return (*pos);
}
}
void header::fieldsContainer::insertSorted(headerField* field)
void header::appendField(headerField* field)
{
const headerField::Types type = field->type();
std::vector <headerField*>::iterator i;
for (i = m_fields.begin() ; (i != m_fields.end()) && ((*i)->type() < type) ; ++i);
m_fields.insert(i, field);
m_fields.push_back(field);
}
// Field insertion
void header::fieldsContainer::append(const headerField& field)
void header::insertFieldBefore(headerField* beforeField, headerField* field)
{
m_fields.push_back(field.clone());
const std::vector <headerField*>::iterator it = std::find
(m_fields.begin(), m_fields.end(), beforeField);
if (it == m_fields.end())
throw exceptions::no_such_field();
m_fields.insert(it, field);
}
void header::fieldsContainer::insert(const iterator it, const headerField& field)
void header::insertFieldBefore(const int pos, headerField* field)
{
m_fields.insert(it.m_iterator, field.clone());
m_fields.insert(m_fields.begin() + pos, field);
}
// Field removing
void header::fieldsContainer::remove(const iterator it)
void header::insertFieldAfter(headerField* afterField, headerField* field)
{
delete (*it.m_iterator);
m_fields.erase(it.m_iterator);
const std::vector <headerField*>::iterator it = std::find
(m_fields.begin(), m_fields.end(), afterField);
if (it == m_fields.end())
throw exceptions::no_such_field();
m_fields.insert(it + 1, field);
}
void header::fieldsContainer::clear()
void header::insertFieldAfter(const int pos, headerField* field)
{
for (std::vector <headerField*>::iterator it = m_fields.begin() ; it != m_fields.end() ; ++it)
delete (*it);
m_fields.clear();
m_fields.insert(m_fields.begin() + pos + 1, field);
}
header::fieldsContainer& header::fieldsContainer::operator=(const fieldsContainer& c)
void header::removeField(headerField* field)
{
std::vector <headerField*> fields;
const std::vector <headerField*>::iterator it = std::find
(m_fields.begin(), m_fields.end(), field);
for (std::vector <headerField*>::const_iterator it = c.m_fields.begin() ; it != c.m_fields.end() ; ++it)
fields.push_back((*it)->clone());
if (it == m_fields.end())
throw exceptions::no_such_field();
for (std::vector <headerField*>::iterator it = m_fields.begin() ; it != m_fields.end() ; ++it)
delete (*it);
delete (*it);
m_fields.resize(fields.size());
std::copy(fields.begin(), fields.end(), m_fields.begin());
m_fields.erase(it);
}
return (*this);
void header::removeField(const int pos)
{
const std::vector <headerField*>::iterator it = m_fields.begin() + pos;
delete (*it);
m_fields.erase(it);
}
void header::removeAllFields()
{
free_container(m_fields);
}
const int header::getFieldCount() const
{
return (m_fields.size());
}
const bool header::isEmpty() const
{
return (m_fields.empty());
}
headerField* header::getFieldAt(const int pos)
{
return (m_fields[pos]);
}
const headerField* const header::getFieldAt(const int pos) const
{
return (m_fields[pos]);
}
const std::vector <const headerField*> header::getFieldList() const
{
std::vector <const headerField*> list;
list.reserve(m_fields.size());
for (std::vector <headerField*>::const_iterator it = m_fields.begin() ;
it != m_fields.end() ; ++it)
{
list.push_back(*it);
}
return (list);
}
const std::vector <headerField*> header::getFieldList()
{
return (m_fields);
}

View File

@ -28,16 +28,12 @@
#include "headerField.hpp"
#include "headerFieldFactory.hpp"
#include "addressListField.hpp"
#include "mailboxListField.hpp"
#include "mailboxField.hpp"
#include "textField.hpp"
#include "dateField.hpp"
#include "contentTypeField.hpp"
#include "contentEncodingField.hpp"
#include "defaultField.hpp"
#include "contentDispositionField.hpp"
#include "messageIdField.hpp"
#include "standardFields.hpp"
#include "standardParams.hpp"
namespace vmime
@ -61,196 +57,166 @@ public:
header();
~header();
// A sub-class for field manipulation
class fieldsContainer
{
friend class header;
#define FIELD_ACCESS(methodName, fieldName, type) \
type& methodName() { return dynamic_cast <type&> \
(*getField(fields::fieldName)); } \
const type& methodName() const { return dynamic_cast <const type&> \
(*findField(fields::fieldName)); }
protected:
FIELD_ACCESS(From, FROM, mailboxField)
FIELD_ACCESS(Sender, SENDER, mailboxField)
FIELD_ACCESS(ReplyTo, REPLY_TO, mailboxField)
FIELD_ACCESS(DeliveredTo, DELIVERED_TO, mailboxField)
fieldsContainer();
~fieldsContainer();
FIELD_ACCESS(To, TO, addressListField)
FIELD_ACCESS(Cc, CC, addressListField)
FIELD_ACCESS(Bcc, BCC, addressListField)
FIELD_ACCESS(Date, DATE, dateField)
FIELD_ACCESS(Subject, SUBJECT, textField)
FIELD_ACCESS(Organization, ORGANIZATION, textField)
FIELD_ACCESS(UserAgent, USER_AGENT, textField)
public:
FIELD_ACCESS(ContentType, CONTENT_TYPE, contentTypeField)
FIELD_ACCESS(ContentDescription, CONTENT_DESCRIPTION, textField)
FIELD_ACCESS(ContentTransferEncoding, CONTENT_TRANSFER_ENCODING, contentEncodingField)
FIELD_ACCESS(MimeVersion, MIME_VERSION, defaultField)
FIELD_ACCESS(ContentDisposition, CONTENT_DISPOSITION, contentDispositionField)
FIELD_ACCESS(ContentId, CONTENT_ID, messageIdField)
FIELD_ACCESS(MessageId, MESSAGE_ID, messageIdField)
FIELD_ACCESS(ContentLocation, CONTENT_LOCATION, defaultField)
// Field access
mailboxField& From() { return (dynamic_cast<mailboxField&>(get(headerField::From))); }
mailboxField& Sender() { return (dynamic_cast<mailboxField&>(get(headerField::Sender))); }
mailboxField& ReplyTo() { return (dynamic_cast<mailboxField&>(get(headerField::ReplyTo))); }
mailboxField& DeliveredTo() { return (dynamic_cast<mailboxField&>(get(headerField::DeliveredTo))); }
addressListField& To() { return (dynamic_cast<addressListField&>(get(headerField::To))); }
addressListField& Cc() { return (dynamic_cast<addressListField&>(get(headerField::Cc))); }
addressListField& Bcc() { return (dynamic_cast<addressListField&>(get(headerField::Bcc))); }
dateField& Date() { return (dynamic_cast<dateField&>(get(headerField::Date))); }
textField& Subject() { return (dynamic_cast<textField&>(get(headerField::Subject))); }
textField& Organization() { return (dynamic_cast<textField&>(get(headerField::Organization))); }
textField& UserAgent() { return (dynamic_cast<textField&>(get(headerField::UserAgent))); }
contentTypeField& ContentType() { return (dynamic_cast<contentTypeField&>(get(headerField::ContentType))); }
textField& ContentDescription() { return (dynamic_cast<textField&>(get(headerField::ContentDescription))); }
contentEncodingField& ContentTransferEncoding() { return (dynamic_cast<contentEncodingField&>(get(headerField::ContentTransferEncoding))); }
defaultField& MimeVersion() { return (dynamic_cast<defaultField&>(get(headerField::MimeVersion))); }
contentDispositionField& ContentDisposition() { return (dynamic_cast<contentDispositionField&>(get(headerField::ContentDisposition))); }
messageIdField& ContentId() { return (dynamic_cast<messageIdField&>(get(headerField::ContentId))); }
messageIdField& MessageId() { return (dynamic_cast<messageIdField&>(get(headerField::MessageId))); }
defaultField& ContentLocation() { return (dynamic_cast<defaultField&>(get(headerField::ContentLocation))); }
#undef FIELD_ACCESS
const mailboxField& From() const { return (dynamic_cast<mailboxField&>(find(headerField::From))); }
const mailboxField& Sender() const { return (dynamic_cast<mailboxField&>(find(headerField::Sender))); }
const mailboxField& ReplyTo() const { return (dynamic_cast<mailboxField&>(find(headerField::ReplyTo))); }
const mailboxField& DeliveredTo() const { return (dynamic_cast<mailboxField&>(find(headerField::DeliveredTo))); }
const addressListField& To() const { return (dynamic_cast<addressListField&>(find(headerField::To))); }
const addressListField& Cc() const { return (dynamic_cast<addressListField&>(find(headerField::Cc))); }
const addressListField& Bcc() const { return (dynamic_cast<addressListField&>(find(headerField::Bcc))); }
const dateField& Date() const { return (dynamic_cast<dateField&>(find(headerField::Date))); }
const textField& Subject() const { return (dynamic_cast<textField&>(find(headerField::Subject))); }
const textField& Organization() const { return (dynamic_cast<textField&>(find(headerField::Organization))); }
const textField& UserAgent() const { return (dynamic_cast<textField&>(find(headerField::UserAgent))); }
const contentTypeField& ContentType() const { return (dynamic_cast<contentTypeField&>(find(headerField::ContentType))); }
const textField& ContentDescription() const { return (dynamic_cast<textField&>(find(headerField::ContentDescription))); }
const contentEncodingField& ContentTransferEncoding() const { return (dynamic_cast<contentEncodingField&>(find(headerField::ContentTransferEncoding))); }
const defaultField& MimeVersion() const { return (dynamic_cast<defaultField&>(find(headerField::MimeVersion))); }
const contentDispositionField& ContentDisposition() const { return (dynamic_cast<contentDispositionField&>(find(headerField::ContentDisposition))); }
const messageIdField& ContentId() const { return (dynamic_cast<messageIdField&>(find(headerField::ContentId))); }
const messageIdField& MessageId() const { return (dynamic_cast<messageIdField&>(find(headerField::MessageId))); }
const defaultField& ContentLocation() const { return (dynamic_cast<defaultField&>(find(headerField::ContentLocation))); }
/** Checks whether (at least) one field with this name exists.
*
* @return true if at least one field with the specified name
* exists, or false otherwise
*/
const bool hasField(const string& fieldName) const;
// Checks whether (at least) one field with this type/name exists
const bool has(const headerField::Types fieldType) const;
const bool has(const string& fieldName) const;
/** Find the first field that matches the specified name.
* If no field is found, an exception is thrown.
*
* @throw exceptions::no_such_field if no field with this name exists
* @return first field with the specified name
*/
headerField* findField(const string& fieldName) const;
// Find the first field that matches the specified type/name.
// If no field is found, an exception is thrown.
headerField& find(const headerField::Types fieldType) const;
headerField& find(const string& fieldName) const;
/** Find all fields that match the specified name.
* If no field is found, an empty vector is returned.
*
* @return list of fields with the specified name
*/
std::vector <headerField*> findAllFields(const string& fieldName);
// Find all fields that matche the specified type/name.
// If no field is found, an empty vector is returned.
std::vector <headerField*> findAllByType(const headerField::Types fieldType);
std::vector <headerField*> findAllByName(const string& fieldName);
/** Find the first field that matches the specified name.
* If no field is found, one will be created and inserted into
* the header.
*
* @return first field with the specified name or a new field
* if no field is found
*/
headerField* getField(const string& fieldName);
// Find the first field that matches the specified type/name.
// If no field is found, one will be created.
headerField& get(const headerField::Types fieldType);
headerField& get(const string& fieldName);
/** Add a field at the end of the list.
*
* @param field field to append
*/
void appendField(headerField* field);
// Field iterator
class const_iterator;
/** Insert a new field before the specified field.
*
* @param beforeField field before which the new field will be inserted
* @param field field to insert
* @throw exceptions::no_such_field if the field is not in the list
*/
void insertFieldBefore(headerField* beforeField, headerField* field);
class iterator
{
friend class header::fieldsContainer::const_iterator;
friend class header::fieldsContainer;
/** Insert a new field before the specified position.
*
* @param pos position at which to insert the new field (0 to insert at
* the beginning of the list)
* @param field field to insert
*/
void insertFieldBefore(const int pos, headerField* field);
public:
/** Insert a new field after the specified field.
*
* @param afterField field after which the new field will be inserted
* @param field field to insert
* @throw exceptions::no_such_field if the field is not in the list
*/
void insertFieldAfter(headerField* afterField, headerField* field);
typedef std::vector <headerField*>::iterator::difference_type difference_type;
/** Insert a new field after the specified position.
*
* @param pos position of the field before the new field
* @param field field to insert
*/
void insertFieldAfter(const int pos, headerField* field);
iterator(std::vector <headerField*>::iterator it) : m_iterator(it) { }
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
/** Remove the specified field from the list.
*
* @param field field to remove
* @throw exceptions::no_such_field if the field is not in the list
*/
void removeField(headerField* field);
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
/** Remove the field at the specified position.
*
* @param pos position of the field to remove
*/
void removeField(const int pos);
headerField& operator*() const { return (**m_iterator); }
headerField* operator->() const { return (*m_iterator); }
/** Remove all fields from the list.
*/
void removeAllFields();
iterator& operator++() { ++m_iterator; return (*this); }
iterator operator++(int) { iterator i(*this); ++m_iterator; return (i); }
/** Return the number of fields in the list.
*
* @return number of fields
*/
const int getFieldCount() const;
iterator& operator--() { --m_iterator; return (*this); }
iterator operator--(int) { iterator i(*this); --m_iterator; return (i); }
/** Tests whether the list of fields is empty.
*
* @return true if there is no field, false otherwise
*/
const bool isEmpty() const;
iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
/** Return the field at the specified position.
*
* @param pos position
* @return field at position 'pos'
*/
headerField* getFieldAt(const int pos);
iterator operator-(difference_type x) const { return iterator(m_iterator - x); }
/** Return the field at the specified position.
*
* @param pos position
* @return field at position 'pos'
*/
const headerField* const getFieldAt(const int pos) const;
headerField& operator[](difference_type n) const { return *(m_iterator[n]); }
/** Return the field list.
*
* @return list of fields
*/
const std::vector <const headerField*> getFieldList() const;
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
/** Return the field list.
*
* @return list of fields
*/
const std::vector <headerField*> getFieldList();
protected:
header* clone() const;
void copyFrom(const component& other);
header& operator=(const header& other);
std::vector <headerField*>::iterator m_iterator;
};
private:
class const_iterator
{
public:
typedef std::vector <headerField*>::const_iterator::difference_type difference_type;
const_iterator(std::vector <headerField*>::const_iterator it) : m_iterator(it) { }
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
const headerField& operator*() const { return (**m_iterator); }
const headerField* operator->() const { return (*m_iterator); }
const_iterator& operator++() { ++m_iterator; return (*this); }
const_iterator operator++(int) { const_iterator i(*this); ++m_iterator; return (i); }
const_iterator& operator--() { --m_iterator; return (*this); }
const_iterator operator--(int) { const_iterator i(*this); --m_iterator; return (i); }
const_iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
const_iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
const_iterator operator-(difference_type x) const { return const_iterator(m_iterator - x); }
const headerField& operator[](difference_type n) const { return *(m_iterator[n]); }
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
protected:
std::vector <headerField*>::const_iterator m_iterator;
};
public:
iterator begin() { return (m_fields.begin()); }
iterator end() { return (m_fields.end()); }
const_iterator begin() const { return (const_iterator(m_fields.begin())); }
const_iterator end() const { return (const_iterator(m_fields.end())); }
// Field insertion
void append(const headerField& field);
void insert(const iterator it, const headerField& field);
// Field removing
void remove(const iterator it);
void clear();
// Field count
const std::vector <headerField*>::size_type count() const { return (m_fields.size()); }
const std::vector <headerField*>::size_type size() const { return (m_fields.size()); }
const bool empty() const { return (m_fields.empty()); }
headerField& front() { return (*m_fields.front()); }
const headerField& front() const { return (*m_fields.front()); }
headerField& back() { return (*m_fields.back()); }
const headerField& back() const { return (*m_fields.back()); }
fieldsContainer& operator=(const fieldsContainer& c);
protected:
void insertSorted(headerField* field);
std::vector <headerField*> m_fields;
} fields;
typedef fieldsContainer::iterator iterator;
typedef fieldsContainer::const_iterator const_iterator;
header& operator=(const header& h);
std::vector <headerField*> m_fields;
public:

View File

@ -26,13 +26,13 @@ namespace vmime
headerField::headerField()
: m_type(Custom), m_name("Undefined")
: m_name("X-Undefined")
{
}
headerField::headerField(const string& fieldName)
: m_type(Custom), m_name(fieldName)
: m_name(fieldName)
{
}
@ -44,12 +44,7 @@ headerField::~headerField()
headerField* headerField::clone() const
{
headerField* field = NULL;
if (m_type == Custom)
field = headerFieldFactory::getInstance()->create(m_name);
else
field = headerFieldFactory::getInstance()->create(m_type);
headerField* field = headerFieldFactory::getInstance()->create(m_name);
field->copyFrom(*this);
@ -57,209 +52,46 @@ headerField* headerField::clone() const
}
const bool headerField::operator<(const headerField& field) const
void headerField::copyFrom(const component& other)
{
return (m_type < field.m_type);
const headerField& hf = dynamic_cast <const headerField&>(other);
getValue().copyFrom(hf.getValue());
}
headerField& headerField::operator=(const headerField& field)
headerField& headerField::operator=(const headerField& other)
{
copyFrom(field);
copyFrom(other);
return (*this);
}
void headerField::copyFrom(const headerField& field)
void headerField::parse(const string& buffer, const string::size_type position, const string::size_type end,
string::size_type* newPosition)
{
m_type = field.m_type;
m_name = field.m_name;
getValue().parse(buffer, position, end, newPosition);
}
void headerField::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
void headerField::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
if (m_type == Custom)
{
os << m_name + ": ";
os << m_name + ": ";
if (newLinePos)
*newLinePos = curLinePos + m_name.length() + 2;
}
else
{
const string name = typeToName(m_type);
os << name + ": ";
if (newLinePos)
*newLinePos = curLinePos + name.length() + 2;
}
getValue().generate(os, maxLineLength, curLinePos + m_name.length() + 2, newLinePos);
}
/** Return the field type corresponding to the specified name.
*
* @param name field name
* @return field type (see headerField::Types) or headerField::custom
* if this is a custom field
*/
const headerField::Types headerField::nameToType(const string& name)
const string headerField::getName() const
{
switch (name[0])
{
case 'B':
case 'b':
{
if (isStringEqualNoCase(name, "bcc", 3)) return (Bcc);
break;
}
case 'C':
case 'c':
{
if (isStringEqualNoCase(name, "cc", 2)) return (Cc);
else if (isStringEqualNoCase(name, "content-type", 12)) return (ContentType);
else if (isStringEqualNoCase(name, "content-transfer-encoding", 25)) return (ContentTransferEncoding);
else if (isStringEqualNoCase(name, "content-description", 19)) return (ContentDescription);
else if (isStringEqualNoCase(name, "content-disposition", 19)) return (ContentDisposition);
else if (isStringEqualNoCase(name, "content-id", 10)) return (ContentId);
else if (isStringEqualNoCase(name, "content-location", 16)) return (ContentLocation);
break;
}
case 'd':
case 'D':
{
if (isStringEqualNoCase(name, "date", 4)) return (Date);
else if (isStringEqualNoCase(name, "delivered-to", 12)) return (DeliveredTo);
break;
}
case 'f':
case 'F':
{
if (isStringEqualNoCase(name, "from", 4)) return (From);
break;
}
case 'm':
case 'M':
{
if (isStringEqualNoCase(name, "mime-version", 12)) return (MimeVersion);
else if (isStringEqualNoCase(name, "message-id", 10)) return (MessageId);
break;
}
case 'o':
case 'O':
{
if (isStringEqualNoCase(name, "organization", 12)) return (Organization);
break;
}
case 'r':
case 'R':
{
if (isStringEqualNoCase(name, "received", 8)) return (Received);
else if (isStringEqualNoCase(name, "reply-to", 8)) return (ReplyTo);
else if (isStringEqualNoCase(name, "return-path", 11)) return (ReturnPath);
break;
}
case 's':
case 'S':
{
if (isStringEqualNoCase(name, "sender", 6)) return (Sender);
else if (isStringEqualNoCase(name, "subject", 7)) return (Subject);
break;
}
case 't':
case 'T':
{
if (isStringEqualNoCase(name, "to", 2)) return (To);
break;
}
case 'u':
case 'U':
{
if (isStringEqualNoCase(name, "user-agent", 10)) return (UserAgent);
break;
}
}
return (Custom);
return (m_name);
}
/** Return the name for the specified field type.
* Eg: returns "From" for headerField::From.
*
* @param type field type
* @return name for the specified field type
*/
const string headerField::typeToName(const Types type)
{
switch (type)
{
case From: return "From";
case Sender: return "Sender";
case To: return "To";
case Cc: return "Cc";
case Bcc: return "Bcc";
case Date: return "Date";
case Received: return "Received";
case Subject: return "Subject";
case ReplyTo: return "Reply-To";
case Organization: return "Organization";
case DeliveredTo: return "Delivered-To";
case UserAgent: return "User-Agent";
case ReturnPath: return "Return-Path";
case ContentType: return "Content-Type";
case ContentTransferEncoding: return "Content-Transfer-Encoding";
case ContentDescription: return "Content-Description";
case MimeVersion: return "Mime-Version";
case ContentDisposition: return "Content-Disposition";
case ContentId: return "Content-Id";
case MessageId: return "Message-Id";
case ContentLocation: return "Content-Location";
case Custom:
case Last:
return "?";
};
return "?";
}
/** Return the type of this field.
*
* @return field type (see headerField::Types)
*/
const headerField::Types headerField::type() const
{
return (m_type);
}
/** Return the name of this field.
*
* @return field name
*/
const string headerField::name() const
{
return ((m_type == Custom) ? m_name : typeToName(m_type));
}
/** Check whether this field is a custom field.
*
* @return true if the field is a custom field, false otherwise
*/
const bool headerField::isCustom() const
{
return (m_type == Custom);
return (m_name.length() > 2 && m_name[0] == 'X' && m_name[1] == '-');
}

View File

@ -45,65 +45,53 @@ public:
~headerField();
public:
headerField* clone() const;
void copyFrom(const component& other);
headerField& operator=(const headerField& other);
// Header field types (in the order in which they will appear
// in the message header)
enum Types
{
Received, // Relay
From, // Expeditor
Sender, // Sender
ReplyTo, // Reply-To
To, // Recipient(s)
Cc, // Carbon copy recipient(s)
Bcc, // Blind carbon-copy recipient(s)
Date, // Date sent
Subject, // Subject
Organization, // Organization
UserAgent, // User agent
DeliveredTo, // Delivered-To
ReturnPath, // Return-Path
MimeVersion, // Mime-Version
MessageId, // Message-Id
ContentType, // Content-Type
ContentTransferEncoding, // Content-Transfer-Encoding
ContentDescription, // Content-Description
ContentDisposition, // Content-Disposition
ContentId, // Content-Id
ContentLocation, // Content-Location
Custom, // Unknown or custom field (eg. X-Priority, X-Mailer, etc.)
Last
};
protected:
Types m_type;
string m_name; // In case of custom field
public:
const bool operator<(const headerField& field) const;
const Types type() const;
const string name() const;
/** Return the name of this field.
*
* @return field name
*/
const string getName() const;
/** Check whether this field is a custom (non-standard) field.
* Custom fields have a name beginning with "X-".
*
* @return true if the field is a custom field, false otherwise
*/
const bool isCustom() const;
virtual void copyFrom(const headerField& field);
headerField& operator=(const headerField& field);
headerField* clone() const;
/** Return the read-only value object attached to this field.
*
* @return read-only value object
*/
virtual const component& getValue() const = 0;
static const Types nameToType(const string& name);
static const string typeToName(const Types type);
/** Return the value object attached to this field.
*
* @return value object
*/
virtual component& getValue() = 0;
/** Set the value of this field.
*
* @throw std::bad_cast_exception if the value type is
* incompatible with the header field type
* @param value value object
*/
virtual void setValue(const component& value) = 0;
// Component assembling
using component::parse;
using component::generate;
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
private:
string m_name;
};

View File

@ -20,21 +20,11 @@
#include "headerFieldFactory.hpp"
#include "exception.hpp"
#include "defaultField.hpp"
#include "standardFields.hpp"
#include "mailboxField.hpp"
#include "addressListField.hpp"
#include "addressListField.hpp"
#include "addressListField.hpp"
#include "mailboxField.hpp"
#include "dateField.hpp"
#include "relayField.hpp"
#include "textField.hpp"
#include "mailboxField.hpp"
#include "contentTypeField.hpp"
#include "contentEncodingField.hpp"
#include "contentDispositionField.hpp"
#include "messageIdField.hpp"
namespace vmime
@ -43,28 +33,28 @@ namespace vmime
headerFieldFactory::headerFieldFactory()
{
// Register some default field types
registerType <mailboxField>(headerField::From);
registerType <addressListField>(headerField::To);
registerType <addressListField>(headerField::Cc);
registerType <addressListField>(headerField::Bcc);
registerType <mailboxField>(headerField::Sender);
registerType <dateField>(headerField::Date);
registerType <relayField>(headerField::Received);
registerType <textField>(headerField::Subject);
registerType <mailboxField>(headerField::ReplyTo);
registerType <mailboxField>(headerField::DeliveredTo);
registerType <textField>(headerField::Organization);
registerType <textField>(headerField::UserAgent);
registerType <mailboxField>(headerField::ReturnPath);
registerType <contentTypeField>(headerField::ContentType);
registerType <contentEncodingField>(headerField::ContentTransferEncoding);
registerType <textField>(headerField::ContentDescription);
registerType <defaultField>(headerField::MimeVersion);
registerType <contentDispositionField>(headerField::ContentDisposition);
registerType <messageIdField>(headerField::ContentId);
registerType <messageIdField>(headerField::MessageId);
registerType <defaultField>(headerField::ContentLocation);
// Register some default fields
registerName <mailboxField>(vmime::fields::FROM);
registerName <addressListField>(vmime::fields::TO);
registerName <addressListField>(vmime::fields::CC);
registerName <addressListField>(vmime::fields::BCC);
registerName <mailboxField>(vmime::fields::SENDER);
registerName <dateField>(vmime::fields::DATE);
registerName <relayField>(vmime::fields::RECEIVED);
registerName <textField>(vmime::fields::SUBJECT);
registerName <mailboxField>(vmime::fields::REPLY_TO);
registerName <mailboxField>(vmime::fields::DELIVERED_TO);
registerName <textField>(vmime::fields::ORGANIZATION);
registerName <textField>(vmime::fields::USER_AGENT);
registerName <mailboxField>(vmime::fields::RETURN_PATH);
registerName <contentTypeField>(vmime::fields::CONTENT_TYPE);
registerName <contentEncodingField>(vmime::fields::CONTENT_TRANSFER_ENCODING);
registerName <textField>(vmime::fields::CONTENT_DESCRIPTION);
registerName <defaultField>(vmime::fields::MIME_VERSION);
registerName <contentDispositionField>(vmime::fields::CONTENT_DISPOSITION);
registerName <messageIdField>(vmime::fields::CONTENT_ID);
registerName <messageIdField>(vmime::fields::MESSAGE_ID);
registerName <defaultField>(vmime::fields::CONTENT_LOCATION);
}
@ -76,63 +66,24 @@ headerFieldFactory::~headerFieldFactory()
headerField* headerFieldFactory::create
(const string& name, const string& body)
{
const headerField::Types type = headerField::nameToType(name);
NameMap::const_iterator pos = m_nameMap.find(stringUtils::toLower(name));
headerField* field = NULL;
if (type != headerField::Custom)
if (pos != m_nameMap.end())
{
return (create(type, name, body));
field = ((*pos).second)();
}
else
{
NameMap::const_iterator pos = m_nameMap.find(toLower(name));
headerField* field = NULL;
if (pos != m_nameMap.end())
{
field = ((*pos).second)();
}
else
{
field = new defaultField;
}
field->m_type = headerField::Custom;
field->m_name = name;
if (body != NULL_STRING)
field->parse(body);
return (field);
field = registerer <defaultField>::creator();
}
}
field->m_name = name;
headerField* headerFieldFactory::create(const headerField::Types type,
const string& name, const string& body)
{
if (type == headerField::Custom)
{
return (create(name, body));
}
else
{
TypeMap::const_iterator pos = m_typeMap.find(type);
if (body != NULL_STRING)
field->parse(body);
if (pos != m_typeMap.end())
{
headerField* field = ((*pos).second)();
field->m_type = type;
if (name != NULL_STRING) field->m_name = name;
if (body != NULL_STRING) field->parse(body);
return (field);
}
else
{
throw exceptions::bad_field_type();
}
}
return (field);
}

View File

@ -23,6 +23,7 @@
#include "headerField.hpp"
#include "utility/singleton.hpp"
#include "utility/stringUtils.hpp"
namespace vmime
@ -40,10 +41,8 @@ protected:
typedef headerField* (*AllocFunc)(void);
typedef std::map <string, AllocFunc> NameMap;
typedef std::map <headerField::Types, AllocFunc> TypeMap;
NameMap m_nameMap;
TypeMap m_typeMap;
public:
@ -63,19 +62,10 @@ public:
template <class T>
void registerName(const string& name)
{
m_nameMap.insert(NameMap::value_type(toLower(name), &registerer<T>::creator));
m_nameMap.insert(NameMap::value_type(stringUtils::toLower(name), &registerer<T>::creator));
}
headerField* create(const string& name, const string& body = NULL_STRING);
headerField* create(const headerField::Types type, const string& name = NULL_STRING, const string& body = NULL_STRING);
protected:
template <class T>
void registerType(const headerField::Types type)
{
m_typeMap.insert(TypeMap::value_type(type, &registerer<T>::creator));
}
};

View File

@ -27,10 +27,11 @@ namespace vmime
htmlTextPart::~htmlTextPart()
{
free_container(m_objects);
}
const mediaType htmlTextPart::type() const
const mediaType htmlTextPart::getType() const
{
return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML));
}
@ -38,26 +39,26 @@ const mediaType htmlTextPart::type() const
const int htmlTextPart::getPartCount() const
{
return (m_plainText.empty() ? 1 : 2);
return (m_plainText.isEmpty() ? 1 : 2);
}
void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
{
// Plain text
if (!m_plainText.empty())
if (!m_plainText.isEmpty())
{
// -- Create a new part
bodyPart* part = new bodyPart();
parent.body().parts.append(part);
parent.getBody()->appendPart(part);
// -- Set header fields
part->header().fields.ContentType() = mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
part->header().fields.ContentType().charset() = m_charset;
part->header().fields.ContentTransferEncoding() = encoding(encodingTypes::QUOTED_PRINTABLE);
part->getHeader()->ContentType().setValue(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN));
part->getHeader()->ContentType().setCharset(m_charset);
part->getHeader()->ContentTransferEncoding().setValue(encoding(encodingTypes::QUOTED_PRINTABLE));
// -- Set contents
part->body().contents() = m_plainText;
part->getBody()->setContents(m_plainText);
}
// HTML text
@ -65,51 +66,51 @@ void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
bodyPart* htmlPart = new bodyPart();
// -- Set header fields
htmlPart->header().fields.ContentType() = mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML);
htmlPart->header().fields.ContentType().charset() = m_charset;
htmlPart->header().fields.ContentTransferEncoding() = encoding(encodingTypes::QUOTED_PRINTABLE);
htmlPart->getHeader()->ContentType().setValue(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML));
htmlPart->getHeader()->ContentType().setCharset(m_charset);
htmlPart->getHeader()->ContentTransferEncoding().setValue(encoding(encodingTypes::QUOTED_PRINTABLE));
// -- Set contents
htmlPart->body().contents() = m_text;
htmlPart->getBody()->setContents(m_text);
// Handle the case we have embedded objects
if (!embeddedObjects.empty())
if (!m_objects.empty())
{
// Create a "multipart/related" body part
bodyPart* relPart = new bodyPart();
parent.body().parts.append(relPart);
parent.getBody()->appendPart(relPart);
relPart->header().fields.ContentType() = mediaType
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED);
relPart->getHeader()->ContentType().
setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED));
// Add the HTML part into this part
relPart->body().parts.append(htmlPart);
relPart->getBody()->appendPart(htmlPart);
// Also add images into this part
for (embeddedObjectsContainer::const_iterator i = embeddedObjects.begin() ;
i != embeddedObjects.end() ; ++i)
// Also add objects into this part
for (std::vector <embeddedObject*>::const_iterator it = m_objects.begin() ;
it != m_objects.end() ; ++it)
{
bodyPart* objPart = new bodyPart();
relPart->body().parts.append(objPart);
relPart->getBody()->appendPart(objPart);
string id = (*i).id();
string id = (*it)->getId();
if (id.substr(0, 4) == "CID:")
id = id.substr(4);
objPart->header().fields.ContentType() = (*i).type();
objPart->header().fields.ContentId() = messageId("<" + id + ">");
objPart->header().fields.ContentDisposition() = disposition(dispositionTypes::INLINE);
objPart->header().fields.ContentTransferEncoding() = (*i).encoding();
objPart->getHeader()->ContentType().setValue((*it)->getType());
objPart->getHeader()->ContentId().setValue(messageId("<" + id + ">"));
objPart->getHeader()->ContentDisposition().setValue(disposition(dispositionTypes::INLINE));
objPart->getHeader()->ContentTransferEncoding().setValue((*it)->getEncoding());
//encoding(encodingTypes::BASE64);
objPart->body().contents() = (*i).data();
objPart->getBody()->setContents((*it)->getData());
}
}
else
{
// Add the HTML part into the parent part
parent.body().parts.append(htmlPart);
parent.getBody()->appendPart(htmlPart);
}
}
@ -117,12 +118,14 @@ void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
void htmlTextPart::findEmbeddedParts(const bodyPart& part,
std::vector <const bodyPart*>& cidParts, std::vector <const bodyPart*>& locParts)
{
for (body::const_iterator p = part.body().parts.begin() ; p != part.body().parts.end() ; ++p)
for (int i = 0 ; i < part.getBody()->getPartCount() ; ++i)
{
const bodyPart& p = *part.getBody()->getPartAt(i);
try
{
dynamic_cast<messageIdField&>((*p).header().fields.find(headerField::ContentId));
cidParts.push_back(&(*p));
dynamic_cast<messageIdField&>(*p.getHeader()->findField(fields::CONTENT_ID));
cidParts.push_back(&p);
}
catch (exceptions::no_such_field)
{
@ -130,8 +133,8 @@ void htmlTextPart::findEmbeddedParts(const bodyPart& part,
// Maybe there is a "Content-Location" field...
try
{
dynamic_cast<messageIdField&>((*p).header().fields.find(headerField::ContentId));
locParts.push_back(&(*p));
dynamic_cast<messageIdField&>(*p.getHeader()->findField(fields::CONTENT_ID));
locParts.push_back(&p);
}
catch (exceptions::no_such_field)
{
@ -140,7 +143,7 @@ void htmlTextPart::findEmbeddedParts(const bodyPart& part,
}
}
findEmbeddedParts((*p), cidParts, locParts);
findEmbeddedParts(p, cidParts, locParts);
}
}
@ -152,17 +155,17 @@ void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id)
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(part.header().fields.find(headerField::ContentType));
(*part.getHeader()->findField(fields::CONTENT_TYPE));
type = ctf.value();
type = ctf.getValue();
}
catch (exceptions::no_such_field)
{
// No "Content-type" field: assume "application/octet-stream".
}
embeddedObjects.m_list.push_back(new embeddedObject
(part.body().contents(), part.body().encoding(), id, type));
m_objects.push_back(new embeddedObject
(part.getBody()->getContents(), part.getBody()->getEncoding(), id, type));
}
@ -178,18 +181,18 @@ void htmlTextPart::parse(const bodyPart& message, const bodyPart& parent, const
std::ostringstream oss;
utility::outputStreamAdapter adapter(oss);
textPart.body().contents().extract(adapter);
textPart.getBody()->getContents().extract(adapter);
const string data = oss.str();
m_text = textPart.body().contents();
m_text = textPart.getBody()->getContents();
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(textPart.header().fields.find(headerField::ContentType));
(*textPart.getHeader()->findField(fields::CONTENT_TYPE));
m_charset = ctf.charset();
m_charset = ctf.getCharset();
}
catch (exceptions::no_such_field)
{
@ -205,28 +208,28 @@ void htmlTextPart::parse(const bodyPart& message, const bodyPart& parent, const
for (std::vector <const bodyPart*>::const_iterator p = cidParts.begin() ; p != cidParts.end() ; ++p)
{
const messageIdField& midField = dynamic_cast<messageIdField&>
((**p).header().fields.find(headerField::ContentId));
(*(*p)->getHeader()->findField(fields::CONTENT_ID));
const string searchFor("CID:" + midField.value().id());
const string searchFor("CID:" + midField.getValue().getId());
if (data.find(searchFor) != string::npos)
{
// This part is referenced in the HTML text.
// Add it to the embedded object list.
addEmbeddedObject(**p, "CID:" + midField.value().id());
addEmbeddedObject(**p, "CID:" + midField.getValue().getId());
}
}
for (std::vector <const bodyPart*>::const_iterator p = locParts.begin() ; p != locParts.end() ; ++p)
{
const defaultField& locField = dynamic_cast<defaultField&>
((**p).header().fields.find(headerField::ContentLocation));
(*(*p)->getHeader()->findField(fields::CONTENT_LOCATION));
if (data.find(locField.value()) != string::npos)
if (data.find(locField.getValue()) != string::npos)
{
// This part is referenced in the HTML text.
// Add it to the embedded object list.
addEmbeddedObject(**p, locField.value());
addEmbeddedObject(**p, locField.getValue());
}
}
@ -241,17 +244,19 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(part.header().fields.find(headerField::ContentType));
(*part.getHeader()->findField(fields::CONTENT_TYPE));
if (ctf.value().type() == mediaTypes::MULTIPART &&
ctf.value().subType() == mediaTypes::MULTIPART_ALTERNATIVE)
if (ctf.getValue().getType() == mediaTypes::MULTIPART &&
ctf.getValue().getSubType() == mediaTypes::MULTIPART_ALTERNATIVE)
{
bodyPart const* foundPart = NULL;
for (body::const_iterator p = part.body().parts.begin() ; !foundPart && p != part.body().parts.end() ; ++p)
for (int i = 0 ; i < part.getBody()->getPartCount() ; ++i)
{
if (&(*p) == &parent || // if "text/html" is in "multipart/related"
&(*p) == &textPart) // if not...
const bodyPart* p = part.getBody()->getPartAt(i);
if (p == &parent || // if "text/html" is in "multipart/related"
p == &textPart) // if not...
{
foundPart = &(*p);
}
@ -262,18 +267,19 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
bool found = false;
// Now, search for the alternative plain text part
for (body::const_iterator p = part.body().parts.begin() ;
!found && p != part.body().parts.end() ; ++p)
for (int i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i)
{
const bodyPart& p = *part.getBody()->getPartAt(i);
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
((*p).header().fields.find(headerField::ContentType));
(*p.getHeader()->findField(fields::CONTENT_TYPE));
if (ctf.value().type() == mediaTypes::TEXT &&
ctf.value().subType() == mediaTypes::TEXT_PLAIN)
if (ctf.getValue().getType() == mediaTypes::TEXT &&
ctf.getValue().getSubType() == mediaTypes::TEXT_PLAIN)
{
m_plainText = (*p).body().contents();
m_plainText = p.getBody()->getContents();
found = true;
}
}
@ -297,44 +303,82 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
bool found = false;
for (body::const_iterator p = part.body().parts.begin() ; !found && p != part.body().parts.end() ; ++p)
for (int i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i)
{
found = findPlainTextPart(*p, parent, textPart);
found = findPlainTextPart(*part.getBody()->getPartAt(i), parent, textPart);
}
return (found);
}
////////////////////////////////
// Embedded objects container //
////////////////////////////////
htmlTextPart::embeddedObjectsContainer::~embeddedObjectsContainer()
const charset& htmlTextPart::getCharset() const
{
free_container(m_list);
return (m_charset);
}
const htmlTextPart::embeddedObject& htmlTextPart::embeddedObjectsContainer::find(const string& id) const
void htmlTextPart::setCharset(const charset& ch)
{
for (std::vector <embeddedObject*>::const_iterator o = m_list.begin() ; o != m_list.end() ; ++o)
m_charset = ch;
}
const contentHandler& htmlTextPart::getPlainText() const
{
return (m_plainText);
}
void htmlTextPart::setPlainText(const contentHandler& plainText)
{
m_plainText = plainText;
}
const contentHandler& htmlTextPart::getText() const
{
return (m_text);
}
void htmlTextPart::setText(const contentHandler& text)
{
m_text = text;
}
const int htmlTextPart::getObjectCount() const
{
return (m_objects.size());
}
const htmlTextPart::embeddedObject* htmlTextPart::getObjectAt(const int pos) const
{
return (m_objects[pos]);
}
const htmlTextPart::embeddedObject* htmlTextPart::findObject(const string& id) const
{
for (std::vector <embeddedObject*>::const_iterator o = m_objects.begin() ;
o != m_objects.end() ; ++o)
{
if ((**o).id() == id)
return (**o);
if ((*o)->getId() == id)
return (*o);
}
throw exceptions::no_object_found();
}
const bool htmlTextPart::embeddedObjectsContainer::has(const string& id) const
const bool htmlTextPart::hasObject(const string& id) const
{
for (std::vector <embeddedObject*>::const_iterator o = m_list.begin() ; o != m_list.end() ; ++o)
for (std::vector <embeddedObject*>::const_iterator o = m_objects.begin() ;
o != m_objects.end() ; ++o)
{
if ((**o).id() == id)
if ((*o)->getId() == id)
return (true);
}
@ -342,29 +386,64 @@ const bool htmlTextPart::embeddedObjectsContainer::has(const string& id) const
}
const string htmlTextPart::embeddedObjectsContainer::add
(const contentHandler& data, const vmime::encoding& enc, const mediaType& type)
const string htmlTextPart::addObject(const contentHandler& data,
const vmime::encoding& enc, const mediaType& type)
{
const messageId mid(messageId::generateId());
const string id = "CID:" + mid.id();
const string id = "CID:" + mid.getId();
m_list.push_back(new embeddedObject(data, enc, id, type));
m_objects.push_back(new embeddedObject(data, enc, id, type));
return (id);
}
const string htmlTextPart::embeddedObjectsContainer::add
(const contentHandler& data, const mediaType& type)
const string htmlTextPart::addObject(const contentHandler& data, const mediaType& type)
{
return (add(data, encoding::decide(data), type));
return (addObject(data, encoding::decide(data), type));
}
const string htmlTextPart::embeddedObjectsContainer::add
(const string& data, const mediaType& type)
const string htmlTextPart::addObject(const string& data, const mediaType& type)
{
return (add(contentHandler(data), encoding::decide(data), type));
return (addObject(contentHandler(data), encoding::decide(data), type));
}
//
// htmlTextPart::embeddedObject
//
htmlTextPart::embeddedObject::embeddedObject
(const contentHandler& data, const encoding& enc,
const string& id, const mediaType& type)
: m_data(data), m_encoding(enc), m_id(id), m_type(type)
{
}
const contentHandler& htmlTextPart::embeddedObject::getData() const
{
return (m_data);
}
const vmime::encoding& htmlTextPart::embeddedObject::getEncoding() const
{
return (m_encoding);
}
const string& htmlTextPart::embeddedObject::getId() const
{
return (m_id);
}
const mediaType& htmlTextPart::embeddedObject::getType() const
{
return (m_type);
}

View File

@ -32,6 +32,9 @@ namespace vmime
{
/** Text part of type 'text/html'.
*/
class htmlTextPart : public textPart
{
protected:
@ -40,127 +43,128 @@ protected:
public:
const mediaType type() const;
const mediaType getType() const;
const vmime::charset& charset() const { return (m_charset); }
vmime::charset& charset() { return (m_charset); }
const charset& getCharset() const;
void setCharset(const charset& ch);
const contentHandler& plainText() const { return (m_plainText); }
contentHandler& plainText() { return (m_plainText); }
const contentHandler& getPlainText() const;
void setPlainText(const contentHandler& plainText);
const contentHandler& text() const { return (m_text); }
contentHandler& text() { return (m_text); }
const contentHandler& getText() const;
void setText(const contentHandler& text);
// Embedded object (eg. image for <IMG> tag)
/** Embedded object (eg: image for <IMG> tag).
*/
class embeddedObject
{
public:
embeddedObject(const contentHandler& data, const vmime::encoding& enc,
const string& id, const mediaType& type)
: m_data(data), m_encoding(enc), m_id(id), m_type(type)
{
}
embeddedObject(const contentHandler& data, const encoding& enc,
const string& id, const mediaType& type);
public:
/** Return data stored in this embedded object.
*
* @return stored data
*/
const contentHandler& getData() const;
const contentHandler& data() const { return (m_data); }
const vmime::encoding& encoding() const { return (m_encoding); }
const string& id() const { return (m_id); }
const mediaType& type() const { return (m_type); }
/** Return the encoding used for data in this
* embedded object.
*
* @return data encoding
*/
const vmime::encoding& getEncoding() const;
/** Return the identifier of this embedded object.
*
* @return object identifier
*/
const string& getId() const;
/** Return the content type of data stored in
* this embedded object.
*
* @return data type
*/
const mediaType& getType() const;
private:
contentHandler m_data;
vmime::encoding m_encoding;
encoding m_encoding;
string m_id;
mediaType m_type;
};
// Embedded objects container
class embeddedObjectsContainer
{
friend class htmlTextPart;
protected:
/** Test the existence of an embedded object given its identifier.
*
* @param id object identifier
* @return true if an object with this identifier exists,
* false otherwise
*/
const bool hasObject(const string& id) const;
~embeddedObjectsContainer();
/** Return the embedded object with the specified identifier.
*
* @throw exceptions::no_object_found() if no object has been found
* @param id object identifier
* @return embedded object with the specified identifier
*/
const embeddedObject* findObject(const string& id) const;
public:
/** Return the number of embedded objects.
*
* @return number of embedded objects
*/
const int getObjectCount() const;
// Test the existence/get an embedded object given its identifier.
const bool has(const string& id) const;
const embeddedObject& find(const string& id) const;
/** Return the embedded object at the specified position.
*
* @param pos position of the embedded object
* @return embedded object at position 'pos'
*/
const embeddedObject* getObjectAt(const int pos) const;
// Embed an object and returns a string which identifies it.
const string add(const string& data, const mediaType& type);
const string add(const contentHandler& data, const mediaType& type);
const string add(const contentHandler& data, const encoding& enc, const mediaType& type);
/** Embed an object and returns a string which identifies it.
*
* \deprecated Use the addObject() methods which take a 'contentHandler'
* parameter type instead.
*
* @param data object data
* @param type data type
* @return an unique object identifier used to identify the new
* object among all other embedded objects
*/
const string addObject(const string& data, const mediaType& type);
// Embedded objects enumerator
class const_iterator
{
public:
/** Embed an object and returns a string which identifies it.
*
* @param data object data
* @param type data type
* @return an unique object identifier used to identify the new
* object among all other embedded objects
*/
const string addObject(const contentHandler& data, const mediaType& type);
typedef std::vector <embeddedObject*>::const_iterator::difference_type difference_type;
/** Embed an object and returns a string which identifies it.
*
* @param data object data
* @param enc data encoding
* @param type data type
* @return an unique object identifier used to identify the new
* object among all other embedded objects
*/
const string addObject(const contentHandler& data, const encoding& enc, const mediaType& type);
const_iterator(std::vector <embeddedObject*>::const_iterator it) : m_iterator(it) { }
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
const embeddedObject& operator*() const { return (**m_iterator); }
const embeddedObject* operator->() const { return (*m_iterator); }
const_iterator& operator++() { ++m_iterator; return (*this); }
const_iterator operator++(int) { const_iterator i(*this); ++m_iterator; return (i); }
const_iterator& operator--() { --m_iterator; return (*this); }
const_iterator operator--(int) { const_iterator i(*this); --m_iterator; return (i); }
const_iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
const_iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
const_iterator operator-(difference_type x) const { return const_iterator(m_iterator - x); }
const embeddedObject& operator[](difference_type n) const { return *(m_iterator[n]); }
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
protected:
std::vector <embeddedObject*>::const_iterator m_iterator;
};
public:
const_iterator begin() const { return (const_iterator(m_list.begin())); }
const_iterator end() const { return (const_iterator(m_list.end())); }
// Object count
const std::vector <embeddedObject*>::size_type count() const { return (m_list.size()); }
const std::vector <embeddedObject*>::size_type size() const { return (m_list.size()); }
const bool empty() const { return (m_list.empty()); }
embeddedObject& front() { return (*m_list.front()); }
const embeddedObject& front() const { return (*m_list.front()); }
embeddedObject& back() { return (*m_list.back()); }
const embeddedObject& back() const { return (*m_list.back()); }
protected:
std::vector <embeddedObject*> m_list;
} embeddedObjects;
typedef embeddedObjectsContainer::const_iterator const_iterator;
protected:
private:
contentHandler m_plainText;
contentHandler m_text;
vmime::charset m_charset;
charset m_charset;
std::vector <embeddedObject*> m_objects;
void findEmbeddedParts(const bodyPart& part, std::vector <const bodyPart*>& cidParts, std::vector <const bodyPart*>& locParts);
void addEmbeddedObject(const bodyPart& part, const string& id);
@ -170,7 +174,7 @@ protected:
const int getPartCount() const;
void generateIn(bodyPart& message, bodyPart& parent) const;
virtual void parse(const bodyPart& message, const bodyPart& parent, const bodyPart& textPart);
void parse(const bodyPart& message, const bodyPart& parent, const bodyPart& textPart);
};

View File

@ -30,8 +30,8 @@ mailbox::mailbox()
}
mailbox::mailbox(const class mailbox& mailbox)
: address(), m_name(mailbox.m_name), m_email(mailbox.m_email)
mailbox::mailbox(const mailbox& mbox)
: address(), m_name(mbox.m_name), m_email(mbox.m_email)
{
}
@ -305,7 +305,7 @@ void mailbox::parse(const string& buffer, const string::size_type position,
if (address.empty() && !name.empty())
{
m_email = name;
m_name.clear();
m_name.removeAllWords();
}
else
{
@ -321,7 +321,7 @@ void mailbox::parse(const string& buffer, const string::size_type position,
void mailbox::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
if (m_name.empty())
if (m_name.isEmpty())
{
bool newLine = false;
@ -352,11 +352,11 @@ void mailbox::generate(utility::outputStream& os, const string::size_type maxLin
// and/or contain the special chars.
bool forceEncode = false;
for (text::const_iterator w = m_name.begin() ; !forceEncode && w != m_name.end() ; ++w)
for (int w = 0 ; !forceEncode && w != m_name.getWordCount() ; ++w)
{
if ((*w).charset() == charset(charsets::US_ASCII))
if (m_name.getWordAt(w)->getCharset() == charset(charsets::US_ASCII))
{
const string& buffer = (*w).buffer();
const string& buffer = m_name.getWordAt(w)->getBuffer();
for (string::const_iterator c = buffer.begin() ;
!forceEncode && c != buffer.end() ; ++c)
@ -423,22 +423,29 @@ const bool mailbox::operator!=(const class mailbox& mailbox) const
}
void mailbox::copyFrom(const address& addr)
void mailbox::copyFrom(const component& other)
{
const mailbox& source = dynamic_cast<const mailbox&>(addr);
const mailbox& source = dynamic_cast <const mailbox&>(other);
m_name = source.m_name;
m_email = source.m_email;
}
address* mailbox::clone() const
mailbox& mailbox::operator=(const mailbox& other)
{
copyFrom(other);
return (*this);
}
mailbox* mailbox::clone() const
{
return new mailbox(*this);
}
const bool mailbox::empty() const
const bool mailbox::isEmpty() const
{
return (m_email.empty());
}
@ -446,7 +453,7 @@ const bool mailbox::empty() const
void mailbox::clear()
{
m_name.clear();
m_name.removeAllWords();
m_email.clear();
}
@ -457,4 +464,28 @@ const bool mailbox::isGroup() const
}
const text& mailbox::getName() const
{
return (m_name);
}
void mailbox::setName(const text& name)
{
m_name = name;
}
const string& mailbox::getEmail() const
{
return (m_email);
}
void mailbox::setEmail(const string& email)
{
m_email = email;
}
} // vmime

View File

@ -40,7 +40,7 @@ class mailbox : public address
public:
mailbox();
mailbox(const class mailbox& mailbox);
mailbox(const mailbox& mbox);
mailbox(const string& email);
mailbox(const text& name, const string& email);
@ -48,35 +48,36 @@ public:
*
* @return full name of the mailbox
*/
const text& name() const { return (m_name); }
const text& getName() const;
/** Return the full name of the mailbox (empty if not specified).
/** Set the full name of the mailbox.
*
* @return full name of the mailbox
*/
text& name() { return (m_name); }
void setName(const text& name);
/** Return the email of the mailbox.
*
* @return email of the mailbox
*/
const string& email() const { return (m_email); }
const string& getEmail() const;
/** Return the email of the mailbox.
/** Set the email of the mailbox.
*
* @return email of the mailbox
*/
string& email() { return (m_email); }
void setEmail(const string& email);
// Comparison
const bool operator==(const class mailbox& mailbox) const;
const bool operator!=(const class mailbox& mailbox) const;
// Assignment
void copyFrom(const address& addr);
address* clone() const;
void copyFrom(const component& other);
mailbox* clone() const;
mailbox& operator=(const mailbox& other);
const bool empty() const;
const bool isEmpty() const;
void clear();

View File

@ -30,10 +30,16 @@ mailboxField::mailboxField()
}
mailboxField::mailboxField(const mailboxField&)
: headerField(), genericField <mailbox>()
{
}
void mailboxField::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
m_mailbox.clear();
getValue().clear();
// Here, we cannot simply call "m_mailbox.parse()" because it
// may have more than one address specified (even if this field
@ -48,13 +54,13 @@ void mailboxField::parse(const string& buffer, const string::size_type position,
// mailbox of the group
mailboxGroup* group = static_cast <mailboxGroup*>(parsedAddress);
if (!group->empty())
m_mailbox = *(group->begin());
if (!group->isEmpty())
getValue() = *(group->getMailboxAt(0));
}
else
{
// Parse only if it is a mailbox
m_mailbox = *static_cast <mailbox*>(parsedAddress);
getValue() = *static_cast <mailbox*>(parsedAddress);
}
}
@ -65,31 +71,4 @@ void mailboxField::parse(const string& buffer, const string::size_type position,
}
void mailboxField::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
string::size_type pos = curLinePos;
headerField::generate(os, maxLineLength, pos, &pos);
m_mailbox.generate(os, maxLineLength, pos, newLinePos);
}
mailboxField& mailboxField::operator=(const class mailbox& mailbox)
{
m_mailbox = mailbox;
return (*this);
}
void mailboxField::copyFrom(const headerField& field)
{
const mailboxField& source = dynamic_cast<const mailboxField&>(field);
m_mailbox = source.m_mailbox;
headerField::copyFrom(field);
}
} // vmime

View File

@ -21,10 +21,7 @@
#define VMIME_MAILBOXFIELD_HPP_INCLUDED
#include "base.hpp"
#include "component.hpp"
#include "headerFieldFactory.hpp"
#include "genericField.hpp"
#include "mailbox.hpp"
@ -32,35 +29,18 @@ namespace vmime
{
class mailboxField : public headerField
class mailboxField : public genericField <mailbox>
{
friend class headerFieldFactory::registerer <mailboxField>;
protected:
mailboxField();
mailboxField(const mailboxField&);
public:
void copyFrom(const headerField& field);
mailboxField& operator=(const class mailbox& mailbox);
const mailbox& value() const { return (m_mailbox); }
mailbox& value() { return (m_mailbox); }
protected:
mailbox m_mailbox;
public:
using headerField::parse;
using headerField::generate;
// Component parsing & assembling
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
};

View File

@ -19,6 +19,7 @@
#include "mailboxGroup.hpp"
#include "parserHelpers.hpp"
#include "exception.hpp"
namespace vmime
@ -30,10 +31,10 @@ mailboxGroup::mailboxGroup()
}
mailboxGroup::mailboxGroup(const class mailboxGroup& mailboxGroup)
mailboxGroup::mailboxGroup(const mailboxGroup& mboxGroup)
: address()
{
copyFrom(mailboxGroup);
copyFrom(mboxGroup);
}
@ -45,7 +46,7 @@ mailboxGroup::mailboxGroup(const text& name)
mailboxGroup::~mailboxGroup()
{
clear();
removeAllMailboxes();
}
@ -85,10 +86,9 @@ void mailboxGroup::parse(const string& buffer, const string::size_type position,
// Sub-groups are not allowed in mailbox groups: so, we add all
// the contents of the sub-group into this group...
for (mailboxGroup::const_iterator
it = group->begin() ; it != group->end() ; ++it)
for (int i = 0 ; i < group->getMailboxCount() ; ++i)
{
m_list.push_back(static_cast <mailbox*>((*it).clone()));
m_list.push_back(group->getMailboxAt(i)->clone());
}
delete (parsedAddress);
@ -119,11 +119,11 @@ void mailboxGroup::generate(utility::outputStream& os, const string::size_type m
// and/or contain the special chars.
bool forceEncode = false;
for (text::const_iterator w = m_name.begin() ; !forceEncode && w != m_name.end() ; ++w)
for (int w = 0 ; !forceEncode && w < m_name.getWordCount() ; ++w)
{
if ((*w).charset() == charset(charsets::US_ASCII))
if (m_name.getWordAt(w)->getCharset() == charset(charsets::US_ASCII))
{
const string& buffer = (*w).buffer();
const string& buffer = m_name.getWordAt(w)->getBuffer();
for (string::const_iterator c = buffer.begin() ;
!forceEncode && c != buffer.end() ; ++c)
@ -158,7 +158,8 @@ void mailboxGroup::generate(utility::outputStream& os, const string::size_type m
os << ":";
++pos;
for (const_iterator it = m_list.begin() ; it != m_list.end() ; ++it)
for (std::vector <mailbox*>::const_iterator it = m_list.begin() ;
it != m_list.end() ; ++it)
{
if (it != m_list.begin())
{
@ -171,7 +172,7 @@ void mailboxGroup::generate(utility::outputStream& os, const string::size_type m
++pos;
}
(*it).generate(os, maxLineLength - 2, pos, &pos);
(*it)->generate(os, maxLineLength - 2, pos, &pos);
}
os << ";";
@ -182,49 +183,44 @@ void mailboxGroup::generate(utility::outputStream& os, const string::size_type m
}
address* mailboxGroup::clone() const
void mailboxGroup::copyFrom(const component& other)
{
const mailboxGroup& source = dynamic_cast <const mailboxGroup&>(other);
m_name = source.m_name;
removeAllMailboxes();
for (std::vector <mailbox*>::const_iterator it = source.m_list.begin() ;
it != source.m_list.end() ; ++it)
{
m_list.push_back((*it)->clone());
}
}
mailboxGroup* mailboxGroup::clone() const
{
return new mailboxGroup(*this);
}
// Mailbox insertion
void mailboxGroup::append(const mailbox& field)
mailboxGroup& mailboxGroup::operator=(const component& other)
{
m_list.push_back(static_cast<mailbox*>(field.clone()));
copyFrom(other);
return (*this);
}
void mailboxGroup::insert(const iterator it, const mailbox& field)
const text& mailboxGroup::getName() const
{
m_list.insert(it.m_iterator, static_cast<mailbox*>(field.clone()));
return (m_name);
}
// Mailbox removing
void mailboxGroup::erase(const iterator it)
void mailboxGroup::setName(const text& name)
{
delete (*it.m_iterator);
m_list.erase(it.m_iterator);
}
void mailboxGroup::clear()
{
free_container(m_list);
}
void mailboxGroup::copyFrom(const address& addr)
{
const mailboxGroup& source = dynamic_cast<const mailboxGroup&>(addr);
m_name = source.m_name;
clear();
for (std::vector <mailbox*>::const_iterator i = source.m_list.begin() ; i != source.m_list.end() ; ++i)
m_list.push_back(static_cast<mailbox*>((*i)->clone()));
m_name = name;
}
@ -234,4 +230,122 @@ const bool mailboxGroup::isGroup() const
}
const bool mailboxGroup::isEmpty() const
{
return (m_list.empty());
}
void mailboxGroup::appendMailbox(mailbox* mbox)
{
m_list.push_back(mbox);
}
void mailboxGroup::insertMailboxBefore(mailbox* beforeMailbox, mailbox* mbox)
{
const std::vector <mailbox*>::iterator it = std::find
(m_list.begin(), m_list.end(), beforeMailbox);
if (it == m_list.end())
throw exceptions::no_such_mailbox();
m_list.insert(it, mbox);
}
void mailboxGroup::insertMailboxBefore(const int pos, mailbox* mbox)
{
m_list.insert(m_list.begin() + pos, mbox);
}
void mailboxGroup::insertMailboxAfter(mailbox* afterMailbox, mailbox* mbox)
{
const std::vector <mailbox*>::iterator it = std::find
(m_list.begin(), m_list.end(), afterMailbox);
if (it == m_list.end())
throw exceptions::no_such_mailbox();
m_list.insert(it + 1, mbox);
}
void mailboxGroup::insertMailboxAfter(const int pos, mailbox* mbox)
{
m_list.insert(m_list.begin() + pos + 1, mbox);
}
void mailboxGroup::removeMailbox(mailbox* mbox)
{
const std::vector <mailbox*>::iterator it = std::find
(m_list.begin(), m_list.end(), mbox);
if (it == m_list.end())
throw exceptions::no_such_mailbox();
delete (*it);
m_list.erase(it);
}
void mailboxGroup::removeMailbox(const int pos)
{
const std::vector <mailbox*>::iterator it = m_list.begin() + pos;
delete (*it);
m_list.erase(it);
}
void mailboxGroup::removeAllMailboxes()
{
free_container(m_list);
}
const int mailboxGroup::getMailboxCount() const
{
return (m_list.size());
}
mailbox* mailboxGroup::getMailboxAt(const int pos)
{
return (m_list[pos]);
}
const mailbox* const mailboxGroup::getMailboxAt(const int pos) const
{
return (m_list[pos]);
}
const std::vector <const mailbox*> mailboxGroup::getMailboxList() const
{
std::vector <const mailbox*> list;
list.reserve(m_list.size());
for (std::vector <mailbox*>::const_iterator it = m_list.begin() ;
it != m_list.end() ; ++it)
{
list.push_back(*it);
}
return (list);
}
const std::vector <mailbox*> mailboxGroup::getMailboxList()
{
return (m_list);
}
} // vmime

View File

@ -38,102 +38,123 @@ class mailboxGroup : public address
public:
mailboxGroup();
mailboxGroup(const class mailboxGroup& mailboxGroup);
mailboxGroup(const mailboxGroup& mboxGroup);
mailboxGroup(const text& name);
~mailboxGroup();
// Properties set/get
const text& name() const { return (m_name); }
text& name() { return (m_name); }
// Assignment
void copyFrom(const address& addr);
address* clone() const;
void copyFrom(const component& other);
mailboxGroup* clone() const;
mailboxGroup& operator=(const component& other);
public:
/** Return the name of the group.
*
* @return group name
*/
const text& getName() const;
// Mailbox iterator
class const_iterator;
/** Set the name of the group.
*
* @param name group name
*/
void setName(const text& name);
class iterator
{
friend class mailboxGroup;
friend class const_iterator;
/** Add a mailbox at the end of the list.
*
* @param mbox mailbox to append
*/
void appendMailbox(mailbox* mbox);
public:
/** Insert a new mailbox before the specified mailbox.
*
* @param beforeMailbox mailbox before which the new mailbox will be inserted
* @param mbox mailbox to insert
* @throw exceptions::no_such_mailbox if the mailbox is not in the list
*/
void insertMailboxBefore(mailbox* beforeMailbox, mailbox* mbox);
iterator(std::vector <mailbox*>::iterator it) : m_iterator(it) { }
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
/** Insert a new mailbox before the specified position.
*
* @param pos position at which to insert the new mailbox (0 to insert at
* the beginning of the list)
* @param mbox mailbox to insert
*/
void insertMailboxBefore(const int pos, mailbox* mbox);
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
/** Insert a new mailbox after the specified mailbox.
*
* @param afterMailbox mailbox after which the new mailbox will be inserted
* @param mbox mailbox to insert
* @throw exceptions::no_such_mailbox if the mailbox is not in the list
*/
void insertMailboxAfter(mailbox* afterMailbox, mailbox* mbox);
mailbox& operator*() const { return (**m_iterator); }
mailbox* operator->() const { return (*m_iterator); }
/** Insert a new mailbox after the specified position.
*
* @param pos position of the mailbox before the new mailbox
* @param mbox mailbox to insert
*/
void insertMailboxAfter(const int pos, mailbox* mbox);
iterator& operator++() { ++m_iterator; return (*this); }
iterator& operator++(int) { ++m_iterator; return (*this); }
/** Remove the specified mailbox from the list.
*
* @param mbox mailbox to remove
* @throw exceptions::no_such_mailbox if the mailbox is not in the list
*/
void removeMailbox(mailbox* mbox);
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
/** Remove the mailbox at the specified position.
*
* @param pos position of the mailbox to remove
*/
void removeMailbox(const int pos);
private:
/** Remove all mailboxes from the list.
*/
void removeAllMailboxes();
std::vector <mailbox*>::iterator m_iterator;
};
/** Return the number of mailboxes in the list.
*
* @return number of mailboxes
*/
const int getMailboxCount() const;
class const_iterator
{
friend class mailboxGroup;
/** Tests whether the list of mailboxes is empty.
*
* @return true if there is no mailbox, false otherwise
*/
const bool isEmpty() const;
public:
/** Return the mailbox at the specified position.
*
* @param pos position
* @return mailbox at position 'pos'
*/
mailbox* getMailboxAt(const int pos);
const_iterator(std::vector <mailbox*>::const_iterator it) : m_iterator(it) { }
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
/** Return the mailbox at the specified position.
*
* @param pos position
* @return mailbox at position 'pos'
*/
const mailbox* const getMailboxAt(const int pos) const;
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
const mailbox& operator*() const { return (**m_iterator); }
const mailbox* operator->() const { return (*m_iterator); }
const_iterator& operator++() { ++m_iterator; return (*this); }
const_iterator& operator++(int) { ++m_iterator; return (*this); }
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
private:
std::vector <mailbox*>::const_iterator m_iterator;
};
iterator begin() { return (m_list.begin()); }
iterator end() { return (m_list.end()); }
const_iterator begin() const { return (const_iterator(m_list.begin())); }
const_iterator end() const { return (const_iterator(m_list.end())); }
const std::vector <mailbox*>::size_type size() const { return (m_list.size()); }
const std::vector <mailbox*>::size_type count() const { return (m_list.size()); }
const bool empty() const { return (m_list.empty()); }
const mailbox& operator[](const std::vector <mailbox*>::size_type x) const { return (*m_list[x]); }
mailbox& operator[](const std::vector <mailbox*>::size_type x) { return (*m_list[x]); }
// Mailbox insertion
virtual void append(const mailbox& field);
virtual void insert(const iterator it, const mailbox& field);
// Mailbox removing
void erase(const iterator it);
void clear();
/** Return the mailbox list.
*
* @return list of mailboxes
*/
const std::vector <const mailbox*> getMailboxList() const;
/** Return the mailbox list.
*
* @return list of mailboxes
*/
const std::vector <mailbox*> getMailboxList();
const bool isGroup() const;
protected:
private:
text m_name;
std::vector <mailbox*> m_list;

View File

@ -18,28 +18,150 @@
//
#include "mailboxList.hpp"
#include "exception.hpp"
namespace vmime
{
// Address insertion
void mailboxList::append(const address& addr)
mailboxList::mailboxList()
{
// Ensure this is a "mailbox" object
const mailbox& mb = dynamic_cast<const mailbox&>(addr);
m_list.push_back(mb.clone());
}
void mailboxList::insert(const iterator it, const address& addr)
mailboxList::mailboxList(const mailboxList& mboxList)
: addressList(mboxList)
{
// Ensure this is a "mailbox" object
const mailbox& mb = dynamic_cast<const mailbox&>(addr);
}
m_list.insert(it.m_iterator, mb.clone());
void mailboxList::appendMailbox(mailbox* mbox)
{
addressList::appendAddress(mbox);
}
void mailboxList::insertMailboxBefore(mailbox* beforeMailbox, mailbox* mbox)
{
try
{
addressList::insertAddressBefore(beforeMailbox, mbox);
}
catch (exceptions::no_such_address&)
{
throw exceptions::no_such_mailbox();
}
}
void mailboxList::insertMailboxBefore(const int pos, mailbox* mbox)
{
addressList::insertAddressBefore(pos, mbox);
}
void mailboxList::insertMailboxAfter(mailbox* afterMailbox, mailbox* mbox)
{
try
{
addressList::insertAddressAfter(afterMailbox, mbox);
}
catch (exceptions::no_such_address&)
{
throw exceptions::no_such_mailbox();
}
}
void mailboxList::insertMailboxAfter(const int pos, mailbox* mbox)
{
addressList::insertAddressAfter(pos, mbox);
}
void mailboxList::removeMailbox(mailbox* mbox)
{
try
{
addressList::removeAddress(mbox);
}
catch (exceptions::no_such_address&)
{
throw exceptions::no_such_mailbox();
}
}
void mailboxList::removeMailbox(const int pos)
{
addressList::removeAddress(pos);
}
void mailboxList::removeAllMailboxes()
{
addressList::removeAllAddresses();
}
const int mailboxList::getMailboxCount() const
{
return (addressList::getAddressCount());
}
const bool mailboxList::isEmpty() const
{
return (addressList::isEmpty());
}
mailbox* mailboxList::getMailboxAt(const int pos)
{
return static_cast <mailbox*>(addressList::getAddressAt(pos));
}
const mailbox* const mailboxList::getMailboxAt(const int pos) const
{
return static_cast <const mailbox*>(addressList::getAddressAt(pos));
}
const std::vector <const mailbox*> mailboxList::getMailboxList() const
{
const std::vector <const address*> addrList = addressList::getAddressList();
std::vector <const mailbox*> res;
for (std::vector <const address*>::const_iterator it = addrList.begin() ;
it != addrList.end() ; ++it)
{
const mailbox* mbox = dynamic_cast <const mailbox*>(*it);
if (mbox != NULL)
res.push_back(mbox);
}
return (res);
}
const std::vector <mailbox*> mailboxList::getMailboxList()
{
const std::vector <address*> addrList = addressList::getAddressList();
std::vector <mailbox*> res;
for (std::vector <address*>::const_iterator it = addrList.begin() ;
it != addrList.end() ; ++it)
{
mailbox* mbox = dynamic_cast <mailbox*>(*it);
if (mbox != NULL)
res.push_back(mbox);
}
return (res);
}

View File

@ -32,92 +32,109 @@ namespace vmime
/** A list of mailboxes (basic type).
*/
class mailboxList : public addressList
class mailboxList : protected addressList
{
friend class mailboxGroup;
public:
//
// The following functions have the same name and work *exactly* like
// the ones in "addressList", except we don't accept anything other
// than objects of type "mailbox" (instead of a generic "address").
//
// This prevents user from inserting mailbox groups where it is not
// allowed by the RFC.
//
// This class works exactly like 'addressList' except it prevents user
// from inserting mailbox groups where it is not allowed by the RFC.
// Address iterator
class const_iterator;
mailboxList();
mailboxList(const mailboxList& mboxList);
class iterator
{
friend class mailboxList;
friend class const_iterator;
/** Add a mailbox at the end of the list.
*
* @param mbox mailbox to append
*/
void appendMailbox(mailbox* mbox);
protected:
/** Insert a new mailbox before the specified mailbox.
*
* @param beforeMailbox mailbox before which the new mailbox will be inserted
* @param mbox mailbox to insert
* @throw exceptions::no_such_mailbox if the mailbox is not in the list
*/
void insertMailboxBefore(mailbox* beforeMailbox, mailbox* mbox);
iterator(std::vector <address*>::iterator it) : m_iterator(it) { }
/** Insert a new mailbox before the specified position.
*
* @param pos position at which to insert the new mailbox (0 to insert at
* the beginning of the list)
* @param mbox mailbox to insert
*/
void insertMailboxBefore(const int pos, mailbox* mbox);
public:
/** Insert a new mailbox after the specified mailbox.
*
* @param afterMailbox mailbox after which the new mailbox will be inserted
* @param mbox mailbox to insert
* @throw exceptions::no_such_mailbox if the mailbox is not in the list
*/
void insertMailboxAfter(mailbox* afterMailbox, mailbox* mbox);
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
/** Insert a new mailbox after the specified position.
*
* @param pos position of the mailbox before the new mailbox
* @param mbox mailbox to insert
*/
void insertMailboxAfter(const int pos, mailbox* mbox);
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
/** Remove the specified mailbox from the list.
*
* @param mbox mailbox to remove
* @throw exceptions::no_such_mailbox if the mailbox is not in the list
*/
void removeMailbox(mailbox* mbox);
mailbox& operator*() const { return static_cast<mailbox&>(**m_iterator); }
mailbox* operator->() const { return static_cast<mailbox*>(*m_iterator); }
/** Remove the mailbox at the specified position.
*
* @param pos position of the mailbox to remove
*/
void removeMailbox(const int pos);
iterator& operator++() { ++m_iterator; return (*this); }
iterator& operator++(int) { ++m_iterator; return (*this); }
/** Remove all mailboxes from the list.
*/
void removeAllMailboxes();
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
/** Return the number of mailboxes in the list.
*
* @return number of mailboxes
*/
const int getMailboxCount() const;
private:
/** Tests whether the list of mailboxes is empty.
*
* @return true if there is no mailbox, false otherwise
*/
const bool isEmpty() const;
std::vector <address*>::iterator m_iterator;
};
/** Return the mailbox at the specified position.
*
* @param pos position
* @return mailbox at position 'pos'
*/
mailbox* getMailboxAt(const int pos);
class const_iterator
{
friend class mailboxList;
/** Return the mailbox at the specified position.
*
* @param pos position
* @return mailbox at position 'pos'
*/
const mailbox* const getMailboxAt(const int pos) const;
protected:
/** Return the mailbox list.
*
* @return list of mailboxes
*/
const std::vector <const mailbox*> getMailboxList() const;
const_iterator(std::vector <address*>::const_iterator it) : m_iterator(it) { }
public:
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
const mailbox& operator*() const { return static_cast<const mailbox&>(**m_iterator); }
const mailbox* operator->() const { return static_cast<const mailbox*>(*m_iterator); }
const_iterator& operator++() { ++m_iterator; return (*this); }
const_iterator& operator++(int) { ++m_iterator; return (*this); }
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
private:
std::vector <address*>::const_iterator m_iterator;
};
iterator begin() { return (m_list.begin()); }
iterator end() { return (m_list.end()); }
const_iterator begin() const { return (const_iterator(m_list.begin())); }
const_iterator end() const { return (const_iterator(m_list.end())); }
// Address insertion
void append(const address& addr);
void insert(const iterator it, const address& addr);
/** Return the mailbox list.
*
* @return list of mailboxes
*/
const std::vector <mailbox*> getMailboxList();
};

View File

@ -1,60 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "mailboxListField.hpp"
namespace vmime
{
mailboxListField::mailboxListField()
{
}
void mailboxListField::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
m_list.parse(buffer, position, end, newPosition);
}
void mailboxListField::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
string::size_type pos = curLinePos;
headerField::generate(os, maxLineLength, pos, &pos);
m_list.generate(os, maxLineLength, pos, newLinePos);
}
void mailboxListField::copyFrom(const headerField& field)
{
const mailboxListField& source = dynamic_cast<const mailboxListField&>(field);
m_list = source.m_list;
headerField::copyFrom(field);
}
} // vmime

View File

@ -1,68 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_MAILBOXLISTFIELD_HPP_INCLUDED
#define VMIME_MAILBOXLISTFIELD_HPP_INCLUDED
#include "base.hpp"
#include "component.hpp"
#include "headerFieldFactory.hpp"
#include "mailboxList.hpp"
namespace vmime
{
class mailboxListField : public headerField
{
friend class headerFieldFactory::registerer <mailboxListField>;
protected:
mailboxListField();
public:
void copyFrom(const headerField& field);
const mailboxList& value() const { return (m_list); }
mailboxList& value() { return (m_list); }
protected:
mailboxList m_list;
public:
using headerField::parse;
using headerField::generate;
// Component parsing & assembling
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
};
} // vmime
#endif // VMIME_MAILBOXLISTFIELD_HPP_INCLUDED

View File

@ -38,8 +38,8 @@ mediaType::mediaType(const string& type)
mediaType::mediaType(const string& type, const string& subType)
: m_type(stringUtils::toLower(type)), m_subType(stringUtils::toLower(subType))
{
set(type, subType);
}
@ -55,8 +55,8 @@ void mediaType::parse(const string& buffer, const string::size_type position,
while (p < pend && *p != '/') ++p;
m_type = toLower(string(buffer.begin() + typeStart,
buffer.begin() + position + (p - pstart)));
m_type = stringUtils::toLower(string(buffer.begin() + typeStart,
buffer.begin() + position + (p - pstart)));
if (p < pend)
{
@ -64,8 +64,8 @@ void mediaType::parse(const string& buffer, const string::size_type position,
++p;
// Extract the sub-type
m_subType = toLower(string(buffer.begin() + position + (p - pstart),
buffer.begin() + end));
m_subType = stringUtils::toLower(string(buffer.begin() + position + (p - pstart),
buffer.begin() + end));
}
if (newPosition)
@ -76,7 +76,7 @@ void mediaType::parse(const string& buffer, const string::size_type position,
void mediaType::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
const string value = toLower(m_type) + "/" + toLower(m_subType);
const string value = m_type + "/" + m_subType;
if (curLinePos + value.length() > maxLineLength)
{
@ -108,15 +108,6 @@ const bool mediaType::operator!=(const mediaType& type) const
}
mediaType& mediaType::operator=(const mediaType& type)
{
m_type = type.m_type;
m_subType = type.m_subType;
return (*this);
}
mediaType& mediaType::operator=(const string& type)
{
parse(type);
@ -124,4 +115,56 @@ mediaType& mediaType::operator=(const string& type)
}
mediaType* mediaType::clone() const
{
return new mediaType(m_type, m_subType);
}
void mediaType::copyFrom(const component& other)
{
const mediaType& mt = dynamic_cast <const mediaType&>(other);
m_type = mt.m_type;
m_subType = mt.m_subType;
}
mediaType& mediaType::operator=(const mediaType& other)
{
copyFrom(other);
return (*this);
}
const string& mediaType::getType() const
{
return (m_type);
}
void mediaType::setType(const string& type)
{
m_type = stringUtils::toLower(type);
}
const string& mediaType::getSubType() const
{
return (m_subType);
}
void mediaType::setSubType(const string& subType)
{
m_subType = stringUtils::toLower(subType);
}
void mediaType::setFromString(const string& type)
{
parse(type);
}
} // vmime

View File

@ -21,6 +21,7 @@
#define VMIME_MEDIATYPE_HPP_INCLUDED
#include "base.hpp"
#include "component.hpp"
@ -44,17 +45,46 @@ public:
const bool operator==(const mediaType& type) const;
const bool operator!=(const mediaType& type) const;
mediaType& operator=(const mediaType& type);
mediaType& operator=(const string& type);
const string& type() const { return (m_type); };
string& type() { return (m_type); }
mediaType* clone() const;
void copyFrom(const component& other);
mediaType& operator=(const mediaType& other);
const string& subType() const { return (m_subType); };
string& subType() { return (m_subType); }
/** Return the media type.
* See the constants in vmime::mediaTypes.
*
* @return media type
*/
const string& getType() const;
void set(const string& type) { parse(type); }
void set(const string& type, const string& subType) { m_type = type; m_subType = subType; }
/** Set the media type.
* See the constants in vmime::mediaTypes.
*
* @param type media type
*/
void setType(const string& type);
/** Return the media subtype.
* See the constants in vmime::mediaTypes.
*
* @return media subtype
*/
const string& getSubType() const;
/** Set the media subtype.
* See the constants in vmime::mediaTypes.
*
* @param subType media subtype
*/
void setSubType(const string& subType);
/** Set the media type and subtype from a string
* in the form "type/subtype" (eg: "image/jpeg").
*
* @param type media type and subtype
*/
void setFromString(const string& type);
protected:

View File

@ -48,28 +48,28 @@ message* messageBuilder::construct() const
message* msg = new message;
// Generate the header fields
msg->header().fields.Subject() = m_subject;
msg->getHeader()->Subject().setValue(m_subject);
if (m_from.empty())
if (m_from.isEmpty())
throw exceptions::no_expeditor();
if (m_to.empty() || (*m_to.begin()).empty())
if (m_to.isEmpty() || m_to.getAddressAt(0)->isEmpty())
throw exceptions::no_recipient();
msg->header().fields.From() = m_from;
msg->header().fields.To() = m_to;
msg->getHeader()->From().setValue(m_from);
msg->getHeader()->To().setValue(m_to);
if (!m_cc.empty())
msg->header().fields.Cc() = m_cc;
if (!m_cc.isEmpty())
msg->getHeader()->Cc().setValue(m_cc);
if (!m_bcc.empty())
msg->header().fields.Bcc() = m_bcc;
if (!m_bcc.isEmpty())
msg->getHeader()->Bcc().setValue(m_bcc);
// Add a "Date" field
msg->header().fields.Date() = datetime::now();
msg->getHeader()->Date().setValue(datetime::now());
// Add a "Mime-Version" header field
msg->header().fields.MimeVersion().value() = MIME_VERSION;
msg->getHeader()->MimeVersion().setValue(string(MIME_VERSION));
// If there is one or more attachments (or other parts that are
// not "text/...") and if there is more than one parts for the
@ -92,15 +92,15 @@ message* messageBuilder::construct() const
if (!m_attach.empty() && m_textPart->getPartCount() > 1)
{
// Set parent part (message) to "multipart/mixed"
msg->header().fields.ContentType() = mediaType
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED);
msg->getHeader()->ContentType().setValue
(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED));
// Create a sub-part "multipart/alternative" for text parts
bodyPart* subPart = new bodyPart;
msg->body().parts.append(subPart);
msg->getBody()->appendPart(subPart);
subPart->header().fields.ContentType() = mediaType
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE);
subPart->getHeader()->ContentType().setValue
(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE));
// Generate the text parts into this sub-part (normally, this
// sub-part will have the "multipart/alternative" content-type...)
@ -114,21 +114,22 @@ message* messageBuilder::construct() const
// If any attachment, set message content-type to "multipart/mixed"
if (!m_attach.empty())
{
msg->header().fields.ContentType() = mediaType
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED);
msg->getHeader()->ContentType().setValue
(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED));
}
// Else, set it to "multipart/alternative" if there are more than one text part.
else if (m_textPart->getPartCount() > 1)
{
msg->header().fields.ContentType() = mediaType
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE);
msg->getHeader()->ContentType().setValue
(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE));
}
}
// Generate the attachments
if (!m_attach.empty())
{
for (std::vector <attachment*>::const_iterator a = m_attach.begin() ; a != m_attach.end() ; ++a)
for (std::vector <attachment*>::const_iterator a = m_attach.begin() ;
a != m_attach.end() ; ++a)
{
(*a)->generateIn(*msg);
}
@ -136,19 +137,22 @@ message* messageBuilder::construct() const
// If there is only one part in the message, move it into the message
// (hence, the message will not be multipart...)
if (msg->body().parts.size() == 1)
if (msg->getBody()->getPartCount() == 1)
{
const bodyPart& part = msg->body().parts.front();
const bodyPart& part = *msg->getBody()->getPartAt(0);
// First, copy (and replace) the header fields
const header::fieldsContainer& hdr = part.header().fields;
const std::vector <const headerField*> fields = part.getHeader()->getFieldList();
for (header::const_iterator f = hdr.begin() ; f != hdr.end() ; ++f)
msg->header().fields.get((*f).name()) = *f;
for (std::vector <const headerField*>::const_iterator it = fields.begin() ;
it != fields.end() ; ++it)
{
*(msg->getHeader()->getField((*it)->getName())) = **it;
}
// Second, copy the body contents and sub-parts (this also remove
// the body part we are copying...)
msg->body() = part.body();
msg->getBody()->copyFrom(*part.getBody());
}
return (msg);
@ -163,7 +167,7 @@ void messageBuilder::attach(attachment* attach)
void messageBuilder::constructTextPart(const mediaType& type)
{
class textPart* part = NULL;
textPart* part = NULL;
try
{
@ -179,9 +183,117 @@ void messageBuilder::constructTextPart(const mediaType& type)
}
class textPart& messageBuilder::textPart()
textPart* messageBuilder::getTextPart()
{
return (*m_textPart);
return (m_textPart);
}
const mailbox& messageBuilder::getExpeditor() const
{
return (m_from);
}
void messageBuilder::setExpeditor(const mailbox& expeditor)
{
m_from = expeditor;
}
const addressList& messageBuilder::getRecipients() const
{
return (m_to);
}
void messageBuilder::setRecipients(const addressList& recipients)
{
m_to = recipients;
}
const addressList& messageBuilder::getCopyRecipients() const
{
return (m_cc);
}
void messageBuilder::setCopyRecipients(const addressList& cc)
{
m_cc = cc;
}
const addressList& messageBuilder::getBlindCopyRecipients() const
{
return (m_bcc);
}
void messageBuilder::setBlindCopyRecipients(const addressList& bcc)
{
m_bcc = bcc;
}
const text& messageBuilder::getSubject() const
{
return (m_subject);
}
void messageBuilder::setSubject(const text& subject)
{
m_subject = subject;
}
void messageBuilder::removeAttachment(const int pos)
{
delete (m_attach[pos]);
m_attach.erase(m_attach.begin() + pos);
}
const attachment* messageBuilder::getAttachmentAt(const int pos) const
{
return (m_attach[pos]);
}
attachment* messageBuilder::getAttachmentAt(const int pos)
{
return (m_attach[pos]);
}
const int messageBuilder::getAttachmentCount() const
{
return (m_attach.size());
}
const std::vector <const attachment*> messageBuilder::getAttachmentList() const
{
std::vector <const attachment*> res;
res.reserve(m_attach.size());
for (std::vector <attachment*>::const_iterator it = m_attach.begin() ;
it != m_attach.end() ; ++it)
{
res.push_back(*it);
}
return (res);
}
const std::vector <attachment*> messageBuilder::getAttachmentList()
{
return (m_attach);
}

View File

@ -49,35 +49,130 @@ public:
public:
// Expeditor and recipients
const mailbox& expeditor() const { return (m_from); }
mailbox& expeditor() { return (m_from); }
/** Return the expeditor of the message (From:).
*
* @return expeditor of the message
*/
const mailbox& getExpeditor() const;
const addressList& recipients() const { return (m_to); }
addressList& recipients() { return (m_to); }
/** Set the expeditor of the message (From:).
*
* @param expeditor expeditor of the message
*/
void setExpeditor(const mailbox& expeditor);
const addressList& copyRecipients() const { return (m_cc); }
addressList& copyRecipients() { return (m_cc); }
/** Return the recipients of the message (To:).
*
* return recipients of the message
*/
const addressList& getRecipients() const;
const addressList& blindCopyRecipients() const { return (m_bcc); }
addressList& blindCopyRecipients() { return (m_bcc); }
/** Set the recipients of the message (To:).
*
* @param recipients list of recipients
*/
void setRecipients(const addressList& recipients);
// Subject
const text& subject() const { return (m_subject); }
text& subject() { return (m_subject); }
/** Return the copy recipients of the message (Cc:).
*
* @return copy recipients of the message
*/
const addressList& getCopyRecipients() const;
// Attachements
/** Set the copy recipients of the message (Cc:).
*
* @param cc list of copy recipients
*/
void setCopyRecipients(const addressList& cc);
/** Return the blind-copy recipients of the message (Bcc:).
*
* @return blind-copy recipients of the message
*/
const addressList& getBlindCopyRecipients() const;
/** Set the blind-copy recipients of the message (Bcc:).
*
* @param bcc list of blind-copy recipients
*/
void setBlindCopyRecipients(const addressList& bcc);
/** Return the subject of the message.
*
* @return subject of the message
*/
const text& getSubject() const;
/** Set the subject of the message.
*
* @param subject message subject
*/
void setSubject(const text& subject);
/** Attach a new object to the message.
*
* @param attach new attachment
*/
void attach(attachment* attach);
const std::vector <attachment*>& attachments() const { return (m_attach); }
// Text parts
/** Remove the attachment at the specified position.
*
* @param pos position of the attachment to remove
*/
void removeAttachment(const int pos);
/** Return the attachment at the specified position.
*
* @param pos position of the attachment
* @return attachment at the specified position
*/
const attachment* getAttachmentAt(const int pos) const;
/** Return the attachment at the specified position.
*
* @param pos position of the attachment
* @return attachment at the specified position
*/
attachment* getAttachmentAt(const int pos);
/** Return the number of attachments in the message.
*
* @return number of attachments
*/
const int getAttachmentCount() const;
/** Return the list of attachments.
*
* @return list of attachments
*/
const std::vector <const attachment*> getAttachmentList() const;
/** Return the list of attachments.
*
* @return list of attachments
*/
const std::vector <attachment*> getAttachmentList();
/** Change the type of the text part and construct a new part.
*
* @param type media type of the text part
*/
void constructTextPart(const mediaType& type);
class textPart& textPart();
// Construction
/** Return the text part of the message.
*
* @return text part of the message
*/
textPart* getTextPart();
/** Construct a new message based on the information specified
* in this object.
*
* @return a new message
*/
message* construct() const;
protected:
private:
mailbox m_from;
@ -87,7 +182,7 @@ protected:
text m_subject;
class textPart* m_textPart;
textPart* m_textPart;
std::vector <attachment*> m_attach;
};

View File

@ -127,7 +127,7 @@ void messageId::parse(const string& buffer, const string::size_type position,
}
const string messageId::id() const
const string messageId::getId() const
{
return (m_left + '@' + m_right);
}
@ -143,14 +143,6 @@ void messageId::generate(utility::outputStream& os, const string::size_type /* m
}
messageId& messageId::operator=(const messageId& source)
{
m_left = source.m_left;
m_right = source.m_right;
return (*this);
}
messageId& messageId::operator=(const string& id)
{
parse(id);
@ -164,12 +156,12 @@ messageId messageId::generateId()
left << "vmime";
left << '.';
left << std::hex << utility::random::time();
left << std::hex << utility::random::getTime();
left << '.';
left << std::hex << utility::random::process();
left << std::hex << utility::random::getProcess();
left << '.';
left << std::hex << utility::random::next();
left << std::hex << utility::random::next();
left << std::hex << utility::random::getNext();
left << std::hex << utility::random::getNext();
return (messageId(left.str(), platformDependant::getHandler()->getHostName()));
}
@ -181,4 +173,56 @@ const bool messageId::operator==(const messageId& mid) const
}
const bool messageId::operator!=(const messageId& mid) const
{
return !(*this == mid);
}
messageId* messageId::clone() const
{
return new messageId(*this);
}
void messageId::copyFrom(const component& other)
{
const messageId& mid = dynamic_cast <const messageId&>(other);
m_left = mid.m_left;
m_right = mid.m_right;
}
messageId& messageId::operator=(const messageId& other)
{
copyFrom(other);
return (*this);
}
const string& messageId::getLeft() const
{
return (m_left);
}
void messageId::setLeft(const string& left)
{
m_left = left;
}
const string& messageId::getRight() const
{
return (m_right);
}
void messageId::setRight(const string& right)
{
m_right = right;
}
} // vmime

View File

@ -43,24 +43,55 @@ public:
public:
const string& left() const { return (m_left); }
string& left() { return (m_left); }
/** Return the left part of the message identifier.
*
* @return left part of message identifier
*/
const string& getLeft() const;
const string& right() const { return (m_right); }
string& right() { return (m_right); }
/** Set the left part of the message identifier.
*
* @param left left part of message identifier
*/
void setLeft(const string& left);
/** Return the right part of the message identifier.
*
* @return right part of message identifier
*/
const string& getRight() const;
/** Set the right part of the message identifier.
*
* @param right right part of message identifier
*/
void setRight(const string& right);
public:
messageId& operator=(const messageId& source);
messageId& operator=(const string& id);
const bool operator==(const messageId& mid) const;
const bool operator!=(const messageId& mid) const;
/** Generate a random message identifier.
*
* @return randomly created message identifier
*/
static messageId generateId();
const string id() const;
/** Return the message identifier constructed by using
* the right part and the left part, separated by
* a '@' character.
*
* @return full message identifier
*/
const string getId() const;
protected:
messageId* clone() const;
void copyFrom(const component& other);
messageId& operator=(const messageId& other);
private:
string m_left;
string m_right;

View File

@ -1,66 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "messageIdField.hpp"
namespace vmime
{
messageIdField::messageIdField()
{
}
void messageIdField::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
m_id.parse(buffer, position, end, newPosition);
}
void messageIdField::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
string::size_type pos = curLinePos;
headerField::generate(os, maxLineLength, pos, &pos);
m_id.generate(os, maxLineLength, pos, newLinePos);
}
messageIdField& messageIdField::operator=(const messageId& mid)
{
m_id = mid;
return (*this);
}
void messageIdField::copyFrom(const headerField& field)
{
const messageIdField& source = dynamic_cast<const messageIdField&>(field);
m_id = source.m_id;
headerField::copyFrom(field);
}
} // vmime

View File

@ -1,70 +0,0 @@
//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_MESSAGEIDFIELD_HPP_INCLUDED
#define VMIME_MESSAGEIDFIELD_HPP_INCLUDED
#include "base.hpp"
#include "component.hpp"
#include "headerFieldFactory.hpp"
#include "messageId.hpp"
namespace vmime
{
class messageIdField : public headerField
{
friend class headerFieldFactory::registerer <messageIdField>;
protected:
messageIdField();
public:
void copyFrom(const headerField& field);
messageIdField& operator=(const messageId& mid);
const messageId& value() const { return (m_id); }
messageId& value() { return (m_id); }
protected:
messageId m_id;
public:
using headerField::parse;
using headerField::generate;
// Component parsing & assembling
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
};
} // vmime
#endif // VMIME_MESSAGEIDFIELD_HPP_INCLUDED

View File

@ -22,8 +22,6 @@
#include "defaultAttachment.hpp"
#include "textPartFactory.hpp"
#include "relayField.hpp"
namespace vmime
{
@ -60,28 +58,36 @@ messageParser::~messageParser()
void messageParser::parse(const message& msg)
{
// Header fields (if field is present, copy its value, else do nothing)
#define TRY_FIELD(x) try { x; } catch (exceptions::no_such_field) { }
TRY_FIELD(m_from = dynamic_cast<mailboxField&>(msg.header().fields.find(headerField::From)).value());
#define TRY_FIELD(var, type, name) \
try { var = dynamic_cast<type&>(*msg.getHeader()->findField(name)).getValue(); } \
catch (exceptions::no_such_field) { }
TRY_FIELD(m_to = dynamic_cast<addressListField&>(msg.header().fields.find(headerField::To)).value());
TRY_FIELD(m_cc = dynamic_cast<addressListField&>(msg.header().fields.find(headerField::Cc)).value());
TRY_FIELD(m_bcc = dynamic_cast<addressListField&>(msg.header().fields.find(headerField::Bcc)).value());
TRY_FIELD(m_from, mailboxField, fields::FROM);
TRY_FIELD(m_to, addressListField, fields::TO);
TRY_FIELD(m_cc, addressListField, fields::CC);
TRY_FIELD(m_bcc, addressListField, fields::BCC);
TRY_FIELD(m_subject, textField, fields::SUBJECT);
TRY_FIELD(m_subject = dynamic_cast<textField&>(msg.header().fields.find(headerField::Subject)).value());
#undef TRY_FIELD
// Date
try
{
vmime::relayField& recv = static_cast<vmime::relayField&>(msg.header().fields.find(headerField::Received));
m_date = recv.date();
vmime::relayField& recv = dynamic_cast <vmime::relayField&>
(*msg.getHeader()->findField(fields::RECEIVED));
m_date = recv.getValue().getDate();
}
catch (vmime::exceptions::no_such_field&)
{
try
{
vmime::dateField& date = static_cast<vmime::dateField&>(msg.header().fields.find(headerField::Date));
m_date = date.value();
vmime::dateField& date = dynamic_cast <vmime::dateField&>
(*msg.getHeader()->findField(fields::DATE));
m_date = date.getValue();
}
catch (vmime::exceptions::no_such_field&)
{
@ -100,10 +106,11 @@ void messageParser::parse(const message& msg)
void messageParser::findAttachments(const bodyPart& part)
{
// We simply search for parts that are not "Content-disposition: inline".
for (body::const_iterator p = part.body().parts.begin() ; p != part.body().parts.end() ; ++p)
for (int i = 0 ; i < part.getBody()->getPartCount() ; ++i)
{
const header& hdr = (*p).header();
const body& bdy = (*p).body();
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;
@ -112,9 +119,9 @@ void messageParser::findAttachments(const bodyPart& part)
try
{
const contentDispositionField& cdf = dynamic_cast<contentDispositionField&>
(hdr.fields.find(headerField::ContentDisposition));
(*hdr.findField(fields::CONTENT_DISPOSITION));
if (cdf.value().name() != dispositionTypes::INLINE)
if (cdf.getValue().getName() != dispositionTypes::INLINE)
{
contentDispField = &cdf;
isAttachment = true;
@ -129,9 +136,9 @@ void messageParser::findAttachments(const bodyPart& part)
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(hdr.fields.find(headerField::ContentType));
(*hdr.findField(fields::CONTENT_TYPE));
type = ctf.value();
type = ctf.getValue();
}
catch (exceptions::no_such_field)
{
@ -140,8 +147,11 @@ void messageParser::findAttachments(const bodyPart& part)
mediaTypes::APPLICATION_OCTET_STREAM);
}
if (type.type() != mediaTypes::TEXT && type.type() != mediaTypes::MULTIPART)
if (type.getType() != mediaTypes::TEXT &&
type.getType() != mediaTypes::MULTIPART)
{
isAttachment = true;
}
}
if (isAttachment)
@ -152,9 +162,9 @@ void messageParser::findAttachments(const bodyPart& part)
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(hdr.fields.find(headerField::ContentType));
(*hdr.findField(fields::CONTENT_TYPE));
type = ctf.value();
type = ctf.getValue();
}
catch (exceptions::no_such_field)
{
@ -169,9 +179,9 @@ void messageParser::findAttachments(const bodyPart& part)
try
{
const textField& cd = dynamic_cast<textField&>
(hdr.fields.find(headerField::ContentDescription));
(*hdr.findField(fields::CONTENT_DESCRIPTION));
description = cd.value();
description = cd.getValue();
}
catch (exceptions::no_such_field)
{
@ -180,12 +190,12 @@ void messageParser::findAttachments(const bodyPart& part)
// Construct the attachment object
attachment* attach = new defaultAttachment
(bdy.contents(), bdy.encoding(), type, description);
(bdy.getContents(), bdy.getEncoding(), type, description);
if (contentDispField != NULL)
{
m_attachInfo.insert(std::map <attachment*, contentDispositionField*>::
value_type(attach, static_cast <contentDispositionField*>
value_type(attach, dynamic_cast <contentDispositionField*>
(contentDispField->clone())));
}
@ -194,8 +204,8 @@ void messageParser::findAttachments(const bodyPart& part)
}
// Try to find attachments in sub-parts
if (bdy.parts.size())
findAttachments(*p);
if (bdy.getPartCount())
findAttachments(p);
}
}
@ -204,7 +214,7 @@ void messageParser::findTextParts(const bodyPart& msg, const bodyPart& part)
{
// Handle the case in which the message is not multipart: if the body part is
// "text/*", take this part.
if (part.body().parts.count() == 0)
if (part.getBody()->getPartCount() == 0)
{
mediaType type(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
bool accept = false;
@ -212,11 +222,11 @@ void messageParser::findTextParts(const bodyPart& msg, const bodyPart& part)
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(msg.header().fields.find(headerField::ContentType));
(*msg.getHeader()->findField(fields::CONTENT_TYPE));
if (ctf.value().type() == mediaTypes::TEXT)
if (ctf.getValue().getType() == mediaTypes::TEXT)
{
type = ctf.value();
type = ctf.getValue();
accept = true;
}
}
@ -251,17 +261,18 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part)
std::vector <const bodyPart*> textParts;
for (body::const_iterator p = part.body().parts.begin() ;
p != part.body().parts.end() ; ++p)
for (int i = 0 ; i < part.getBody()->getPartCount() ; ++i)
{
const bodyPart& p = *part.getBody()->getPartAt(i);
try
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
((*p).header().fields.find(headerField::ContentType));
(*p.getHeader()->findField(fields::CONTENT_TYPE));
if (ctf.value().type() == mediaTypes::TEXT)
if (ctf.getValue().getType() == mediaTypes::TEXT)
{
textParts.push_back(&(*p));
textParts.push_back(&p);
}
}
catch (exceptions::no_such_field)
@ -273,14 +284,15 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part)
if (textParts.size())
{
// Okay. So we have found at least one text part
for (std::vector <const bodyPart*>::const_iterator p = textParts.begin() ; p != textParts.end() ; ++p)
for (std::vector <const bodyPart*>::const_iterator p = textParts.begin() ;
p != textParts.end() ; ++p)
{
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
((*p)->header().fields.find(headerField::ContentType));
(*(*p)->getHeader()->findField(fields::CONTENT_TYPE));
try
{
textPart* textPart = textPartFactory::getInstance()->create(ctf.value());
textPart* textPart = textPartFactory::getInstance()->create(ctf.getValue());
textPart->parse(msg, part, **p);
m_textParts.push_back(textPart);
@ -298,10 +310,9 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part)
{
bool found = false;
for (body::const_iterator p = part.body().parts.begin() ;
!found && p != part.body().parts.end() ; ++p)
for (int i = 0 ; !found && (i < part.getBody()->getPartCount()) ; ++i)
{
found = findSubTextParts(msg, *p);
found = findSubTextParts(msg, *part.getBody()->getPartAt(i));
}
return found;
@ -309,13 +320,105 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part)
}
const contentDispositionField* messageParser::attachmentInfo(attachment* a) const
const contentDispositionField* messageParser::getAttachmentInfo(const attachment* a) const
{
std::map <attachment*, contentDispositionField*>::const_iterator
it = m_attachInfo.find(a);
it = m_attachInfo.find(const_cast <attachment*>(a));
return (it != m_attachInfo.end() ? (*it).second : NULL);
}
const mailbox& messageParser::getExpeditor() const
{
return (m_from);
}
const addressList& messageParser::getRecipients() const
{
return (m_to);
}
const addressList& messageParser::getCopyRecipients() const
{
return (m_cc);
}
const addressList& messageParser::getBlindCopyRecipients() const
{
return (m_bcc);
}
const text& messageParser::getSubject() const
{
return (m_subject);
}
const datetime& messageParser::getDate() const
{
return (m_date);
}
const std::vector <const attachment*> messageParser::getAttachmentList() const
{
std::vector <const attachment*> res;
res.reserve(m_attach.size());
for (std::vector <attachment*>::const_iterator it = m_attach.begin() ;
it != m_attach.end() ; ++it)
{
res.push_back(*it);
}
return (res);
}
const int messageParser::getAttachmentCount() const
{
return (m_attach.size());
}
const attachment* messageParser::getAttachmentAt(const int pos) const
{
return (m_attach[pos]);
}
const std::vector <const textPart*> messageParser::getTextPartList() const
{
std::vector <const textPart*> res;
res.reserve(m_textParts.size());
for (std::vector <textPart*>::const_iterator it = m_textParts.begin() ;
it != m_textParts.end() ; ++it)
{
res.push_back(*it);
}
return (res);
}
const int messageParser::getTextPartCount() const
{
return (m_textParts.size());
}
const textPart* messageParser::getTextPartAt(const int pos) const
{
return (m_textParts[pos]);
}
} // vmime

View File

@ -46,27 +46,88 @@ public:
public:
// Expeditor and recipients
const mailbox& expeditor() const { return (m_from); }
/** Return the expeditor of the message (From:).
*
* @return expeditor of the message
*/
const mailbox& getExpeditor() const;
const addressList& recipients() const { return (m_to); }
const addressList& copyRecipients() const { return (m_cc); }
const addressList& blindCopyRecipients() const { return (m_bcc); }
/** Return the recipients of the message (To:).
*
* return recipients of the message
*/
const addressList& getRecipients() const;
// Subject
const text& subject() const { return (m_subject); }
/** Return the copy recipients of the message (Cc:).
*
* @return copy recipients of the message
*/
const addressList& getCopyRecipients() const;
// Date
const datetime& date() const { return (m_date); }
/** Return the blind-copy recipients of the message (Bcc:).
*
* @return blind-copy recipients of the message
*/
const addressList& getBlindCopyRecipients() const;
// Attachments
const std::vector <attachment*>& attachments() const { return (m_attach); }
const contentDispositionField* attachmentInfo(attachment* a) const;
/** Return the subject of the message.
*
* @return subject of the message
*/
const text& getSubject() const;
// Text parts
const std::vector <textPart*>& textParts() const { return (m_textParts); }
/** Return the date of the message.
*
* @return date of the message
*/
const datetime& getDate() const;
protected:
/** Return the number of attachments in the message.
*
* @return number of attachments
*/
const int getAttachmentCount() const;
/** Return the attachment at the specified position.
*
* @param pos position of the attachment
* @return attachment at position 'pos'
*/
const attachment* getAttachmentAt(const int pos) const;
/** Return the attachments of the message.
*
* @return list of attachments in the message
*/
const std::vector <const attachment*> getAttachmentList() const;
/** Return information about the specified attachment.
*
* @param a attachment to retrieve information about
* @return information about the specified attachment
*/
const contentDispositionField* getAttachmentInfo(const attachment* a) const;
/** Return the text parts of the message.
*
* @return list of text parts in the message
*/
const std::vector <const textPart*> getTextPartList() const;
/** Return the number of text parts in the message.
*
* @return number of text parts
*/
const int getTextPartCount() const;
/** Return the text part at the specified position.
*
* @param pos position of the text part
* @return text part at position 'pos'
*/
const textPart* getTextPartAt(const int pos) const;
private:
mailbox m_from;

View File

@ -59,24 +59,24 @@ void IMAPConnection::connect()
m_state = STATE_NONE;
m_hierarchySeparator = '\0';
const string address = m_store->session().properties()[m_store->infos().propertyPrefix() + "server.address"];
const port_t port = m_store->session().properties().get(m_store->infos().propertyPrefix() + "server.port", m_store->infos().defaultPort());
const string address = m_store->getSession()->getProperties()[m_store->getInfos().getPropertyPrefix() + "server.address"];
const port_t port = m_store->getSession()->getProperties().getProperty(m_store->getInfos().getPropertyPrefix() + "server.port", m_store->getInfos().getDefaultPort());
// Create the time-out handler
if (session().properties().exists
(m_store->infos().propertyPrefix() + "timeout.factory"))
if (m_store->getSession()->getProperties().hasProperty
(m_store->getInfos().getPropertyPrefix() + "timeout.factory"))
{
timeoutHandlerFactory* tof = platformDependant::getHandler()->
getTimeoutHandlerFactory(session().properties()
[m_store->infos().propertyPrefix() + "timeout.factory"]);
getTimeoutHandlerFactory(m_store->getSession()->getProperties()
[m_store->getInfos().getPropertyPrefix() + "timeout.factory"]);
m_timeoutHandler = tof->create();
}
// Create and connect the socket
socketFactory* sf = platformDependant::getHandler()->getSocketFactory
(m_store->session().properties().get
(m_store->infos().propertyPrefix() + "server.socket-factory", string("default")));
(m_store->getSession()->getProperties().getProperty
(m_store->getInfos().getPropertyPrefix() + "server.socket-factory", string("default")));
m_socket = sf->create();
m_socket->connect(address, port);
@ -109,8 +109,8 @@ void IMAPConnection::connect()
// TODO: other authentication methods
send(true, "LOGIN " + IMAPUtils::quoteString(auth.username())
+ " " + IMAPUtils::quoteString(auth.password()), true);
send(true, "LOGIN " + IMAPUtils::quoteString(auth.getUsername())
+ " " + IMAPUtils::quoteString(auth.getPassword()), true);
utility::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());

Some files were not shown because too many files have changed in this diff Show More