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> 2004-09-09 Vincent Richard <vincent@vincent-richard.net>
* IMAPFolder.cpp: fixed rename(): folder name is now updated. * IMAPFolder.cpp: fixed rename(): folder name is now updated.

View File

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

View File

@ -1 +1 @@
0.5.2 0.6.0

View File

@ -257,7 +257,7 @@ public:
gmt.tm_isdst = -1; gmt.tm_isdst = -1;
// Calculate the difference (in seconds) // 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 the date
return vmime::datetime(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, 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; vmime::messageBuilder mb;
// Fill in the basic fields // Fill in the basic fields
mb.expeditor() = vmime::mailbox("me@somewhere.com"); mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
mb.recipients().append(vmime::mailbox("you@elsewhere.com"));
mb.blindCopyRecipients().append(vmime::mailbox("you-bcc@nowhere.com")); vmime::addressList to;
mb.subject() = vmime::text("My first message generated with vmime::messageBuilder"); 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 // Message body
mb.textPart().text() = "I'm writing this short text to test message construction " \ mb.getTextPart()->setText(vmime::contentHandler(
"using the vmime::messageBuilder component."; "I'm writing this short text to test message construction " \
"using the vmime::messageBuilder component."));
// Construction // Construction
vmime::message* msg = mb.construct(); vmime::message* msg = mb.construct();
@ -61,7 +71,7 @@ int main()
std::cout << "Generated message:" << std::endl; std::cout << "Generated message:" << std::endl;
std::cout << "==================" << std::endl; std::cout << "==================" << std::endl;
vmime::outputStreamAdapter out(std::cout); vmime::utility::outputStreamAdapter out(std::cout);
msg->generate(out); msg->generate(out);
// Destruction // Destruction
@ -77,7 +87,7 @@ int main()
catch (std::exception& e) catch (std::exception& e)
{ {
std::cout << "std::exception: " << e.what() << std::endl; std::cout << "std::exception: " << e.what() << std::endl;
throw; //throw;
} }
std::cout << std::endl; std::cout << std::endl;

View File

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

View File

@ -45,10 +45,19 @@ int main()
vmime::messageBuilder mb; vmime::messageBuilder mb;
// Fill in the basic fields // Fill in the basic fields
mb.expeditor() = vmime::mailbox("me@somewhere.com"); mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
mb.recipients().append(vmime::mailbox("you@elsewhere.com"));
mb.blindCopyRecipients().append(vmime::mailbox("you-bcc@nowhere.com")); vmime::addressList to;
mb.subject() = vmime::text("My first message generated with vmime::messageBuilder"); 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" // Set the content-type to "text/html"
mb.constructTextPart(vmime::mediaType 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. // 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). // 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 // -- embed an image (the returned "CID" (content identifier) is used to reference
// -- the image into HTML content). // -- 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)); vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
// -- message text // -- message text
textPart.text() = vmime::string("This is the <b>HTML text</b>.<br/><img src=\"") + cid + vmime::string("\"/>"); textPart.setText(vmime::contentHandler(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.setPlainText(vmime::contentHandler(vmime::string("This is the plain text (without HTML formatting).")));
// Construction // Construction
vmime::message* msg = mb.construct(); vmime::message* msg = mb.construct();

View File

@ -44,28 +44,28 @@ int main()
vmime::messageParser mp("<...MIME message content...>"); vmime::messageParser mp("<...MIME message content...>");
// Enumerate text parts // Enumerate text parts
for (std::vector <vmime::textPart*>::const_iterator i = mp.textParts().begin() ; for (int i = 0 ; i < mp.getTextPartCount() ; ++i)
i != mp.textParts().end() ; ++i)
{ {
const vmime::textPart& part = **i; const vmime::textPart& part = *mp.getTextPartAt(i);
// Output content-type of the part // Output content-type of the part
std::cout << part.type().generate() << std::endl; std::cout << part.getType().generate() << std::endl;
// text/html // 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); const vmime::htmlTextPart& hp = dynamic_cast<const vmime::htmlTextPart&>(part);
// HTML text is in "hp.text()" // HTML text is in "hp.getText()"
// Corresponding plain text is in "hp.plainText()" // Corresponding plain text is in "hp.getPlainText()"
// Enumerate embedded objects (eg. images) // Enumerate embedded objects (eg. images)
for (vmime::htmlTextPart::const_iterator i = hp.embeddedObjects.begin() ; for (int j = 0 ; j < hp.getObjectCount() ; ++j)
i != hp.embeddedObjects.end() ; ++i)
{ {
// Identifier (content-id or content-location) is in "(*i).id()" const vmime::htmlTextPart::embeddedObject& obj = *hp.getObjectAt(j);
// Object data is in "(*i).data()"
// Identifier (content-id or content-location) is in "obj.getId()"
// Object data is in "obj.getData()"
} }
} }
// text/plain // text/plain
@ -73,7 +73,7 @@ int main()
{ {
const vmime::textPart& tp = dynamic_cast<const vmime::textPart&>(part); 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...>"); vmime::messageParser mp("<...MIME message content...>");
// Enumerate attachments // Enumerate attachments
for (std::vector <vmime::attachment*>::const_iterator i = mp.attachments().begin() ; for (int i = 0 ; i < mp.getAttachmentCount() ; ++i)
i != mp.attachments().end() ; ++i)
{ {
// Media type (content type) is in "(*i).type()" const vmime::attachment& att = *mp.getAttachmentAt(i);
// Description is in "(*i).description()"
// Data is in "(*i).data()" // Media type (content type) is in "att.getType()"
// Description is in "att.getDescription()"
// Data is in "att.getData()"
} }
} }
// VMime exception // 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) 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]; const vmime::messaging::part& part = s[i];
for (int j = 0 ; j < level * 2 ; ++j) for (int j = 0 ; j < level * 2 ; ++j)
std::cout << " "; std::cout << " ";
std::cout << part.number() << ". " std::cout << part.getNumber() << ". "
<< part.type().generate() << part.getType().generate()
<< " [" << part.size() << " byte(s)]" << " [" << part.getSize() << " byte(s)]"
<< std::endl; << 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 // Test the new enumeration system for encoders
// //
#if 0 #if 1
vmime::encoderFactory* ef = vmime::encoderFactory::getInstance(); vmime::encoderFactory* ef = vmime::encoderFactory::getInstance();
std::cout << "Available encoders:" << std::endl; std::cout << "Available encoders:" << std::endl;
for (vmime::encoderFactory::iterator it = ef->begin() ; for (int i = 0 ; i < ef->getEncoderCount() ; ++i)
it != ef->end() ; ++it)
{ {
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::vector <vmime::string> props = e->getAvailableProperties();
std::cout << " - " << *it2 << std::endl;
for (std::vector <vmime::string>::const_iterator it = props.begin() ; it != props.end() ; ++it)
std::cout << " - " << *it << std::endl;
delete (e); delete (e);
} }
@ -108,21 +109,22 @@ int main()
std::cout << "Available messaging services:" << std::endl; std::cout << "Available messaging services:" << std::endl;
for (vmime::messaging::serviceFactory::const_iterator it = sf->begin() ; for (int i = 0 ; i < sf->getServiceCount() ; ++i)
it != sf->end() ; ++it)
{ {
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::vector <vmime::string> props = serv.getInfos().getAvailableProperties();
std::cout << " - " << (*it).infos().propertyPrefix() + *it2 << std::endl;
for (std::vector <vmime::string>::const_iterator it = props.begin() ; it != props.end() ; ++it)
std::cout << " - " << serv.getInfos().getPropertyPrefix() + *it << std::endl;
} }
#endif #endif
vmime::messaging::session sess; vmime::messaging::session sess;
sess.properties()["store.protocol"] = "imap"; sess.getProperties()["store.protocol"] = "imap";
sess.properties()["transport.protocol"] = "smtp"; sess.getProperties()["transport.protocol"] = "smtp";
my_auth auth; my_auth auth;
@ -136,12 +138,12 @@ int main()
// Transport protocol configuration // Transport protocol configuration
vmime::messaging::transport* tr = sess.getTransport(); vmime::messaging::transport* tr = sess.getTransport();
//sess.properties()[tr->infos().propertyPrefix() + "auth.username"] = "username"; //sess.getProperties()[tr->getInfos().getPropertyPrefix() + "auth.username"] = "username";
//sess.properties()[tr->infos().propertyPrefix() + "auth.password"] = "password"; //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 // Connection
tr->connect(); tr->connect();
@ -151,8 +153,8 @@ int main()
// Recipients list // Recipients list
vmime::mailboxList to; vmime::mailboxList to;
to.append(vmime::mailbox("you@somewhere.com")); to.appendMailbox(new vmime::mailbox("you@somewhere.com"));
to.append(vmime::mailbox("somebody.else@anywhere.com")); to.appendMailbox(new vmime::mailbox("somebody.else@anywhere.com"));
std::istringstream iss("[MESSAGE DATA: HEADER + BODY]"); std::istringstream iss("[MESSAGE DATA: HEADER + BODY]");
tr->send(from, to, iss); tr->send(from, to, iss);
@ -176,15 +178,15 @@ int main()
vmime::messaging::store* st = sess.getStore(&auth); vmime::messaging::store* st = sess.getStore(&auth);
// Store protocol configuration // Store protocol configuration
//sess.properties()[st->infos().propertyPrefix() + "auth.username"] = "username"; //sess.getProperties()[st->getInfos().getPropertyPrefix() + "auth.username"] = "username";
//sess.properties()[st->infos().propertyPrefix() + "auth.password"] = "password"; //sess.getProperties()[st->getInfos().getPropertyPrefix() + "auth.password"] = "password";
sess.properties()[st->infos().propertyPrefix() + "server.address"] = "imap.mydomain.com"; sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.address"] = "imap.mydomain.com";
//sess.properties()[st->infos().propertyPrefix() + "server.port"] = 110; //sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.port"] = 110;
//sess.properties()[st->infos().propertyPrefix() + "server.socket-factory"] = "default"; //sess.getProperties()[st->getInfos().getPropertyPrefix() + "server.socket-factory"] = "default";
//sess.properties()[st->infos().propertyPrefix() + "options.apop"] = false; //sess.getProperties()[st->getInfos().getPropertyPrefix() + "options.apop"] = false;
//sess.properties()[st->infos().propertyPrefix() + "options.apop.fallback"] = true; //sess.getProperties()[st->getInfos().getPropertyPrefix() + "options.apop.fallback"] = true;
// Connection // Connection
st->connect(); st->connect();
@ -205,7 +207,7 @@ int main()
// To retrieve the whole message // To retrieve the whole message
std::ostringstream oss; std::ostringstream oss;
vmime::outputStreamAdapter out(oss); vmime::utility::outputStreamAdapter out(oss);
m->extract(out); m->extract(out);
@ -223,55 +225,55 @@ int main()
std::cout << "STRUCTURE:" << std::endl; std::cout << "STRUCTURE:" << std::endl;
std::cout << "==========" << std::endl; std::cout << "==========" << std::endl;
printStructure(m->structure()); printStructure(m->getStructure());
std::cout << std::endl; std::cout << std::endl;
std::cout << "Size = " << m->size() << " byte(s)" << std::endl; std::cout << "Size = " << m->getSize() << " byte(s)" << std::endl;
std::cout << "UID = " << m->uniqueId() << std::endl; std::cout << "UID = " << m->getUniqueId() << std::endl;
std::cout << std::endl; std::cout << std::endl;
std::cout << "ENVELOPE:" << std::endl; std::cout << "ENVELOPE:" << std::endl;
std::cout << "=========" << std::endl; std::cout << "=========" << std::endl;
try { std::cout << m->header().fields.From().generate() << std::endl; } catch (...) { } try { std::cout << m->getHeader().From().generate() << std::endl; } catch (...) { }
try { std::cout << m->header().fields.To().generate() << std::endl; } catch (...) { } try { std::cout << m->getHeader().To().generate() << std::endl; } catch (...) { }
try { std::cout << m->header().fields.Date().generate() << std::endl; } catch (...) { } try { std::cout << m->getHeader().Date().generate() << std::endl; } catch (...) { }
try { std::cout << m->header().fields.Subject().generate() << std::endl; } catch (...) { } try { std::cout << m->getHeader().Subject().generate() << std::endl; } catch (...) { }
std::cout << std::endl; std::cout << std::endl;
std::cout << "FULL HEADER:" << std::endl; std::cout << "FULL HEADER:" << std::endl;
std::cout << "============" << 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;
std::cout << "=========================================================" << std::endl; std::cout << "=========================================================" << std::endl;
vmime::outputStreamAdapter out2(std::cout); vmime::utility::outputStreamAdapter out2(std::cout);
m->extractPart(m->structure()[1][2][1], out2, NULL); //, 0, 10); m->extractPart(m->getStructure()[1][2][1], out2, NULL); //, 0, 10);
std::cout << "=========================================================" << std::endl; std::cout << "=========================================================" << std::endl;
std::cout << std::endl; 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; std::cout << "=========================================================" << std::endl;
// Flags manipulation // 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); 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); 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); f->setMessageFlags(m->getNumber(), m->getNumber(), 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;
f->setMessageFlags(m->number(), m->number(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_REMOVE); f->setMessageFlags(m->getNumber(), m->getNumber(), 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;
std::cout << "=========================================================" << std::endl; std::cout << "=========================================================" << std::endl;
@ -312,7 +314,7 @@ int main()
if (!g->exists()) if (!g->exists())
g->create(vmime::messaging::folder::TYPE_CONTAINS_MESSAGES); g->create(vmime::messaging::folder::TYPE_CONTAINS_MESSAGES);
f->copyMessages(g->fullPath()); f->copyMessages(g->getFullPath());
delete (g); 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 } // vmime

View File

@ -45,33 +45,13 @@ protected:
public: 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 /** Check whether this address is empty (no mailboxes specified
* if this is a mailboxGroup -or- no email specified if this is * if this is a mailboxGroup -or- no email specified if this is
* a mailbox). * a mailbox).
* *
* @return true if this address is empty * @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. /** Test whether this is object is a mailboxGroup.
* *
@ -79,6 +59,8 @@ public:
*/ */
virtual const bool isGroup() const = 0; virtual const bool isGroup() const = 0;
virtual address* clone() const = 0;
protected: protected:
/** Parse an address from an input buffer. /** Parse an address from an input buffer.

View File

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

View File

@ -31,106 +31,124 @@ namespace vmime
{ {
class mailboxList;
/** A list of addresses. /** A list of addresses.
*/ */
class addressList : public component class addressList : public component
{ {
friend class addressListField;
friend class mailboxListField;
public: public:
addressList(); addressList();
addressList(const class addressList& addressList); addressList(const addressList& addrList);
~addressList(); ~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 /** Add a address at the end of the list.
{ *
friend class addressList; * @param addr address to append
friend class const_iterator; */
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) { } /** Insert a new address before the specified position.
iterator(const iterator& it) : m_iterator(it.m_iterator) { } *
* @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); } /** Insert a new address after the specified position.
address* operator->() const { return (*m_iterator); } *
* @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); } /** Remove the specified address from the list.
iterator& operator++(int) { ++m_iterator; return (*this); } *
* @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); } /** Remove the address at the specified position.
const bool operator!=(const iterator& it) const { return (!(*this == it)); } *
* @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 /** Tests whether the list of addresses is empty.
{ *
friend class addressList; * @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) { } /** Return the address at the specified position.
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { } *
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { } * @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); } /** Return the address list.
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); } *
* @return list of addresses
*/
const std::vector <const address*> getAddressList() const;
const address& operator*() const { return (**m_iterator); } /** Return the address list.
const address* operator->() const { return (*m_iterator); } *
* @return list of addresses
*/
const std::vector <address*> getAddressList();
const_iterator& operator++() { ++m_iterator; return (*this); } private:
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:
std::vector <address*> m_list; std::vector <address*> m_list;
void copyFrom(const addressList& source);
public: public:
using component::parse; 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() { }
virtual attachment& operator=(const attachment& attach) = 0;
/** Return the media type of this attachment. /** Return the media type of this attachment.
* @return content type of the 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 the description of this attachment.
* @return attachment description * @return attachment description
*/ */
virtual const text& description() const = 0; virtual const text& getDescription() const = 0;
/** Return the data contained in this attachment. /** Return the data contained in this attachment.
* @return attachment data * @return attachment data
*/ */
virtual const contentHandler& data() const = 0; virtual const contentHandler& getData() const = 0;
/** Return the encoding used for this attachment. /** Return the encoding used for this attachment.
* @return attachment data encoding * @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. /** Generate the attachment in the specified body part.
* @param parent body part in which to generate the attachment * @param parent body part in which to generate the attachment

View File

@ -30,6 +30,8 @@
#include "parserHelpers.hpp" #include "parserHelpers.hpp"
#include "utility/stringUtils.hpp"
// For initializing // For initializing
#include "encoderFactory.hpp" #include "encoderFactory.hpp"
#include "headerFieldFactory.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. // New line sequence to be used when folding header fields.
const string NEW_LINE_SEQUENCE("\r\n "); const string NEW_LINE_SEQUENCE = "\r\n ";
const string::size_type NEW_LINE_SEQUENCE_LENGTH(1); // space const string::size_type NEW_LINE_SEQUENCE_LENGTH = 1; // space
/** The CR-LF sequence. /** The CR-LF sequence.
*/ */
const string CRLF("\r\n"); const string CRLF = "\r\n";
/** The current MIME version supported by VMime. /** The current MIME version supported by VMime.
*/ */
const string MIME_VERSION("1.0"); const string MIME_VERSION = "1.0";
// Line length limits // 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. /** Encode and fold text in respect to RFC-2047.
* *
* @param os output stream * @param os output stream
@ -252,14 +113,15 @@ void encodeAndFoldText(utility::outputStream& os, const text& in, const string::
{ {
string::size_type curLineLength = firstLineOffset; 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 word& w = *in.getWordAt(wi);
const string& buffer = w.buffer(); const string& buffer = w.getBuffer();
// Calculate the number of ASCII chars to check whether encoding is needed // Calculate the number of ASCII chars to check whether encoding is needed
// and _which_ encoding to use. // 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) || bool noEncoding = (flags & encodeAndFoldFlags::forceNoEncoding) ||
(!(flags & encodeAndFoldFlags::forceEncoding) && asciiCount == buffer.length()); (!(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... // we write the full line no matter of the max line length...
if (!newLine && p != end && lastWSpos == end && 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 // Here, we are continuing on the line of previous encoded
// word, but there is not even enough space to put the // 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. // last white-space.
#if 1 #if 1
if (curLineLength != 1 && wi != in.begin()) if (curLineLength != 1 && wi != 0)
os << " "; // Separate from previous word os << " "; // Separate from previous word
#endif #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::size_type asciiPercent = (100 * asciiCount) / buffer.length();
const string::value_type encoding = (asciiPercent <= 40) ? 'B' : 'Q'; const string::value_type encoding = (asciiPercent <= 40) ? 'B' : 'Q';
string wordStart("=?" + w.charset().name() + "?" + encoding + "?"); string wordStart("=?" + w.getCharset().getName() + "?" + encoding + "?");
string wordEnd("?="); string wordEnd("?=");
const string::size_type minWordLength = wordStart.length() + wordEnd.length(); 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') if (encoding == 'Q')
{ {
theEncoder->properties()["rfc2047"] = true; theEncoder->getProperties()["rfc2047"] = true;
// In the case of Quoted-Printable encoding, we cannot simply encode input // 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 // 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 1
if (curLineLength != 1 && wi != in.begin()) if (curLineLength != 1 && wi != 0)
{ {
os << " "; // Separate from previous word os << " "; // Separate from previous word
++curLineLength; ++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 // NOTE: See RFC-2047, Pages 11-12 for knowing about handling
// of white-spaces between encoded words. // of white-spaces between encoded words.
out.clear(); out.removeAllWords();
string::const_iterator p = inStart; string::const_iterator p = inStart;
const string::const_iterator end = inEnd; const string::const_iterator end = inEnd;
@ -608,14 +470,14 @@ void decodeAndUnfoldText(const string::const_iterator& inStart, const string::co
if (textEnd != prevPos) 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 else
{ {
prevWordCharset = defaultCharset; prevWordCharset = defaultCharset;
out.append(word(string(prevPos, textEnd), defaultCharset)); out.appendWord(new word(string(prevPos, textEnd), defaultCharset));
prevIsEncoded = false; prevIsEncoded = false;
} }
} }
@ -670,7 +532,7 @@ void decodeAndUnfoldText(const string::const_iterator& inStart, const string::co
else if (*encPos == 'Q' || *encPos == 'q') else if (*encPos == 'Q' || *encPos == 'q')
{ {
theEncoder = new encoderQP; theEncoder = new encoderQP;
theEncoder->properties()["rfc2047"] = true; theEncoder->getProperties()["rfc2047"] = true;
} }
if (theEncoder) if (theEncoder)
@ -698,13 +560,16 @@ void decodeAndUnfoldText(const string::const_iterator& inStart, const string::co
if (p != wordPos) // if not empty 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 else
{ {
out.append(word(string(prevPos, wordPos), defaultCharset)); out.appendWord(new word
(string(prevPos, wordPos), defaultCharset));
prevWordCharset = 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 // Append this fresh decoded word to output text
charset thisCharset(string(charsetPos, charsetEnd)); 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 else
{ {
prevWordCharset = thisCharset; 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 // 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 // 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 // Free the pointer elements in a STL container and empty the container
template <class CONTAINER> template <class CONTAINER>
@ -125,14 +92,10 @@ namespace vmime
// Field contents encoding (RFC-2047 and folding) // 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 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& in, text& out);
void decodeAndUnfoldText(const string::const_iterator& inStart, const string::const_iterator& inEnd, 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 // Some constants
@ -210,6 +173,9 @@ namespace vmime
// Mime version // Mime version
extern const string MIME_VERSION; extern const string MIME_VERSION;
/** Utility classes. */
namespace utility { }
} // vmime } // vmime

View File

@ -23,7 +23,6 @@
#include "options.hpp" #include "options.hpp"
#include "contentTypeField.hpp" #include "contentTypeField.hpp"
#include "contentEncodingField.hpp"
#include "utility/random.hpp" #include "utility/random.hpp"
@ -34,16 +33,28 @@ namespace vmime
{ {
body::body(bodyPart& part) body::body()
: parts(*this), m_part(part), m_header(part.header()) : 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, void body::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition) const string::size_type end, string::size_type* newPosition)
{ {
parts.clear(); removeAllParts();
// Check whether the body is a MIME-multipart // Check whether the body is a MIME-multipart
bool isMultipart = false; bool isMultipart = false;
@ -52,15 +63,15 @@ void body::parse(const string& buffer, const string::size_type position,
try try
{ {
const contentTypeField& ctf = dynamic_cast <contentTypeField&> 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; isMultipart = true;
try try
{ {
boundary = ctf.boundary(); boundary = ctf.getBoundary();
} }
catch (exceptions::no_such_parameter&) catch (exceptions::no_such_parameter&)
{ {
@ -170,13 +181,17 @@ void body::parse(const string& buffer, const string::size_type position,
throw; throw;
} }
parts.m_parts.push_back(part); part->m_parent = m_part;
m_parts.push_back(part);
} }
partStart = pos; partStart = pos;
pos = buffer.find(boundarySep, partStart); pos = buffer.find(boundarySep, partStart);
} }
m_contents.setData("");
if (partStart < end) if (partStart < end)
m_epilogText = string(buffer.begin() + partStart, buffer.begin() + 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 else
{ {
// Extract the (encoded) contents // Extract the (encoded) contents
m_contents.set(buffer, position, end, encoding()); m_contents.setData(buffer, position, end, getEncoding());
} }
if (newPosition) 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 const string::size_type /* curLinePos */, string::size_type* newLinePos) const
{ {
// MIME-Multipart // MIME-Multipart
if (parts.size() != 0) if (getPartCount() != 0)
{ {
string boundary; string boundary;
try if (m_header == NULL)
{ {
contentTypeField& ctf = dynamic_cast<contentTypeField&> boundary = generateRandomBoundaryString();
(m_header.fields.find(headerField::ContentType)); }
else
{
try
{
contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*m_header->findField(fields::CONTENT_TYPE));
boundary = ctf.boundary(); boundary = ctf.getBoundary();
} }
catch (exceptions::no_such_field&) catch (exceptions::no_such_field&)
{ {
// Warning: no content-type and no boundary string specified! // Warning: no content-type and no boundary string specified!
boundary = generateRandomBoundaryString(); boundary = generateRandomBoundaryString();
} }
catch (exceptions::no_such_parameter&) catch (exceptions::no_such_parameter&)
{ {
// Warning: no boundary string specified! // Warning: no boundary string specified!
boundary = generateRandomBoundaryString(); boundary = generateRandomBoundaryString();
}
} }
const string& prologText = const string& prologText =
m_prologText.empty() m_prologText.empty()
? (isRootPart() ? (isRootPart()
? options::getInstance()->multipart.prologText() ? options::getInstance()->multipart.getPrologText()
: NULL_STRING : NULL_STRING
) )
: m_prologText; : m_prologText;
@ -229,14 +251,14 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
const string& epilogText = const string& epilogText =
m_epilogText.empty() m_epilogText.empty()
? (isRootPart() ? (isRootPart()
? options::getInstance()->multipart.epilogText() ? options::getInstance()->multipart.getEpilogText()
: NULL_STRING : NULL_STRING
) )
: m_epilogText; : m_epilogText;
if (!prologText.empty()) if (!prologText.empty())
{ {
encodeAndFoldText(os, text(word(prologText, charset())), maxLineLength, 0, encodeAndFoldText(os, text(word(prologText, getCharset())), maxLineLength, 0,
NULL, encodeAndFoldFlags::forceNoEncoding | encodeAndFoldFlags::noNewLineSequence); NULL, encodeAndFoldFlags::forceNoEncoding | encodeAndFoldFlags::noNewLineSequence);
os << CRLF; os << CRLF;
@ -244,12 +266,11 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
os << "--" << boundary; os << "--" << boundary;
for (std::vector <bodyPart*>::const_iterator for (int p = 0 ; p < getPartCount() ; ++p)
p = parts.m_parts.begin() ; p != parts.m_parts.end() ; ++p)
{ {
os << CRLF; os << CRLF;
(*p)->generate(os, maxLineLength, 0); getPartAt(p)->generate(os, maxLineLength, 0);
os << CRLF << "--" << boundary; os << CRLF << "--" << boundary;
} }
@ -258,7 +279,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
if (!epilogText.empty()) if (!epilogText.empty())
{ {
encodeAndFoldText(os, text(word(epilogText, charset())), maxLineLength, 0, encodeAndFoldText(os, text(word(epilogText, getCharset())), maxLineLength, 0,
NULL, encodeAndFoldFlags::forceNoEncoding | encodeAndFoldFlags::noNewLineSequence); NULL, encodeAndFoldFlags::forceNoEncoding | encodeAndFoldFlags::noNewLineSequence);
os << CRLF; os << CRLF;
@ -271,7 +292,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
else else
{ {
// Generate the contents // 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] = '_'; boundary[1] = '_';
// Generate a string of random characters // Generate a string of random characters
unsigned int r = utility::random::time(); unsigned int r = utility::random::getTime();
unsigned int m = sizeof(unsigned int); unsigned int m = sizeof(unsigned int);
for (size_t i = 2 ; i < (sizeof(boundary) / sizeof(boundary[0]) - 1) ; ++i) for (size_t i = 2 ; i < (sizeof(boundary) / sizeof(boundary[0]) - 1) ; ++i)
@ -326,7 +347,7 @@ const string body::generateRandomBoundaryString()
if (--m == 0) if (--m == 0)
{ {
r = utility::random::next(); r = utility::random::getNext();
m = sizeof(unsigned int); m = sizeof(unsigned int);
} }
} }
@ -363,12 +384,14 @@ const bool body::isValidBoundary(const string& boundary)
// Quick-access functions // Quick-access functions
// //
const mediaType body::contentType() const const mediaType body::getContentType() const
{ {
try try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&>(m_header.fields.find(headerField::ContentType)); const contentTypeField& ctf = dynamic_cast<contentTypeField&>
return (ctf.value()); (*m_header->findField(fields::CONTENT_TYPE));
return (ctf.getValue());
} }
catch (exceptions::no_such_field&) 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 try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&>(m_header.fields.find(headerField::ContentType)); const contentTypeField& ctf = dynamic_cast<contentTypeField&>
const class charset& cs = ctf.charset(); (*m_header->findField(fields::CONTENT_TYPE));
const class charset& cs = ctf.getCharset();
return (cs); return (cs);
} }
@ -400,12 +425,14 @@ const class charset body::charset() const
} }
const class encoding body::encoding() const const encoding body::getEncoding() const
{ {
try try
{ {
const contentEncodingField& cef = m_header.fields.ContentTransferEncoding(); const contentEncodingField& cef = dynamic_cast<contentEncodingField&>
return (cef.value()); (*m_header->findField(fields::CONTENT_TRANSFER_ENCODING));
return (cef.getValue());
} }
catch (exceptions::no_such_field&) catch (exceptions::no_such_field&)
{ {
@ -417,126 +444,259 @@ const class encoding body::encoding() const
const bool body::isRootPart() 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; body* bdy = new body(NULL);
m_epilogText = b.m_epilogText;
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); return (*this);
} }
///////////////////// const string& body::getPrologText() const
// Parts container //
/////////////////////
body::partsContainer::partsContainer(class body& body)
: m_body(body)
{ {
return (m_prologText);
} }
// Part insertion void body::setPrologText(const string& prologText)
void body::partsContainer::append(bodyPart* part)
{ {
part->m_parent = &(m_body.m_part); m_prologText = prologText;
}
m_parts.push_back(part);
// Check whether we have a boundary string const string& body::getEpilogText() const
try {
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&> // Check whether we have a boundary string
(m_body.m_header.fields.find(headerField::ContentType));
try try
{ {
const string boundary = ctf.boundary(); contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*m_header->findField(fields::CONTENT_TYPE));
if (boundary.empty() || !isValidBoundary(boundary)) try
throw exceptions::no_such_parameter("boundary"); // to generate a new one {
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. // No "Content-Type" field: create a new one and generate
ctf.boundary() = generateRandomBoundaryString(); // a random boundary string.
} contentTypeField& ctf = dynamic_cast<contentTypeField&>
(*m_header->getField(fields::CONTENT_TYPE));
if (ctf.value().type() != mediaTypes::MULTIPART) ctf.setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED));
{ ctf.setBoundary(generateRandomBoundaryString());
// Warning: multi-part body but the Content-Type is
// not specified as "multipart/..."
} }
} }
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::insertPartBefore(bodyPart* beforePart, bodyPart* part)
void body::partsContainer::remove(const iterator it)
{ {
delete (*it.m_iterator); initNewPart(part);
m_parts.erase(it.m_iterator);
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); 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(); list.push_back(*it);
p->m_parent = &(m_body.m_part);
parts.push_back(p);
} }
for (std::vector <bodyPart*>::iterator it = m_parts.begin() ; it != m_parts.end() ; ++it) return (list);
delete (*it); }
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; friend class bodyPart;
protected: private:
body(bodyPart& part); body(bodyPart* parentPart);
public: public:
// A sub-class for part manipulation body();
class partsContainer ~body();
{
friend class body;
protected: /** Add a part at the end of the list.
*
* @param part part to append
*/
void appendPart(bodyPart* part);
partsContainer(class body& body); /** Insert a new part before the specified part.
~partsContainer(); *
* @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 /** Insert a new part after the specified part.
class const_iterator; *
* @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 /** Insert a new part after the specified position.
{ *
friend class body::partsContainer::const_iterator; * @param pos position of the part before the new part
friend class body::partsContainer; * @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) { } /** Remove all parts from the list.
iterator(const iterator& it) : m_iterator(it.m_iterator) { } */
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); } /** Tests whether the list of parts is empty.
bodyPart* operator->() const { return (*m_iterator); } *
* @return true if there is no part, false otherwise
*/
const bool isEmpty() const;
iterator& operator++() { ++m_iterator; return (*this); } /** Return the part at the specified position.
iterator operator++(int) { iterator i(*this); ++m_iterator; return (i); } *
* @param pos position
* @return part at position 'pos'
*/
bodyPart* getPartAt(const int pos);
iterator& operator--() { --m_iterator; return (*this); } /** Return the part at the specified position.
iterator operator--(int) { iterator i(*this); --m_iterator; return (i); } *
* @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); } /** Return the part list.
iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); } *
* @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); } /** Set the prolog text.
const bool operator!=(const iterator& it) const { return (!(*this == it)); } *
* @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 /** Return a read-only reference to body contents.
{ *
public: * @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) { } /** Set the body contents.
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { } *
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { } * @param contents new body contents
*/
void setContents(const contentHandler& contents);
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); } /** Return the media type of the data contained in the body contents.
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); } * 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); } /** Return the charset of the data contained in the body contents.
const bodyPart* operator->() const { return (*m_iterator); } * 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); } /** Return the encoding used to encode the body contents.
const_iterator operator++(int) { const_iterator i(*this); ++m_iterator; return (i); } * 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); } /** Generate a new random boundary string.
const_iterator operator--(int) { const_iterator i(*this); --m_iterator; return (i); } *
* @return randomly generated boundary string
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
static const string generateRandomBoundaryString(); 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); 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_prologText;
string m_epilogText; string m_epilogText;
contentHandler m_contents; contentHandler m_contents;
bodyPart& m_part; bodyPart* m_part;
header& m_header; header* m_header;
std::vector <bodyPart*> m_parts;
const bool isRootPart() const; const bool isRootPart() const;
void initNewPart(bodyPart* part);
public: public:
using component::parse; using component::parse;

View File

@ -25,7 +25,7 @@ namespace vmime
bodyPart::bodyPart() 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; bodyPart* p = new bodyPart;
p->m_parent = NULL; 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); 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 } // vmime

View File

@ -37,24 +37,28 @@ namespace vmime
class bodyPart : public component class bodyPart : public component
{ {
friend class body;
public: public:
bodyPart(); bodyPart();
const class header& header() const { return (m_header); } const header* getHeader() const;
class header& header() { return (m_header); } header* getHeader();
const class body& body() const { return (m_body); } const body* getBody() const;
class body& body() { return (m_body); } body* getBody();
bodyPart* parent() const { return (m_parent); } bodyPart* getParentPart() const;
bodyPart* clone() const; bodyPart* clone() const;
void copyFrom(const component& other);
bodyPart& operator=(const bodyPart& other);
protected: private:
class header m_header; header m_header;
class body m_body; body m_body;
bodyPart* m_parent; bodyPart* m_parent;
@ -66,11 +70,6 @@ public:
// Component parsing & assembling // Component parsing & assembling
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL); 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; 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 "exception.hpp"
#include "platformDependant.hpp" #include "platformDependant.hpp"
#include "utility/stringUtils.hpp"
extern "C" 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, void charset::convert(utility::inputStream& in, utility::outputStream& out,
const charset& source, const charset& dest) const charset& source, const charset& dest)
{ {
// Get an iconv descriptor // 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) 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> template <class STRINGF, class STRINGT>
void charset::iconvert(const STRINGF& in, STRINGT& out, const charset& from, const charset& to) void charset::iconvert(const STRINGF& in, STRINGT& out, const charset& from, const charset& to)
{ {
// Get an iconv descriptor // 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 STRINGF::value_type ivt;
typedef typename STRINGT::value_type ovt; 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 #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) void charset::decode(const string& in, wstring& out, const charset& ch)
{ {
iconvert(in, out, ch, charset("WCHAR_T")); 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) void charset::encode(const wstring& in, string& out, const charset& ch)
{ {
iconvert(in, out, charset("WCHAR_T"), ch); iconvert(in, out, charset("WCHAR_T"), ch);
@ -248,37 +216,21 @@ void charset::encode(const wstring& in, string& out, const charset& ch)
#endif #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) void charset::convert(const string& in, string& out, const charset& source, const charset& dest)
{ {
iconvert(in, out, source, 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() const charset charset::getLocaleCharset()
{ {
return (platformDependant::getHandler()->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); return (*this);
} }
@ -292,7 +244,7 @@ charset& charset::operator=(const string& name)
const bool charset::operator==(const charset& value) const 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 } // vmime

View File

@ -41,28 +41,74 @@ public:
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); charset& operator=(const string& name);
const bool operator==(const charset& value) const; const bool operator==(const charset& value) const;
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(); static const charset getLocaleCharset();
#if VMIME_WIDE_CHAR_SUPPORT #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); 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); static void encode(const wstring& in, string& out, const charset& ch);
#endif #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); 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); 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; 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 "component.hpp"
#include "base.hpp"
#include <sstream> #include <sstream>
@ -26,6 +27,11 @@ namespace vmime
{ {
component::~component()
{
}
void component::parse(const string& buffer) void component::parse(const string& buffer)
{ {
parse(buffer, 0, buffer.length(), NULL); parse(buffer, 0, buffer.length(), NULL);

View File

@ -34,11 +34,9 @@ namespace vmime
class component class component
{ {
protected: public:
virtual ~component() {} virtual ~component();
protected:
/** Parse RFC-822/MIME data for this 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; 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. /** Generate RFC-2822/MIME data for this component.
* *
* \deprecated Use the new generate() method, which takes an outputStream parameter. * \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 * @param curLinePos length of the current line in the output buffer
* @return generated data * @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. /** 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) * @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; 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 } // vmime

View File

@ -28,7 +28,7 @@
namespace vmime namespace vmime
{ {
// Media types (predefined types) /** Constants for media types. */
namespace mediaTypes namespace mediaTypes
{ {
// Types // Types
@ -67,7 +67,7 @@ namespace vmime
} }
// Encoding types /** Constants for encoding types. */
namespace encodingTypes namespace encodingTypes
{ {
extern const string::value_type* const SEVEN_BIT; 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 namespace dispositionTypes
{ {
extern const string::value_type* const INLINE; extern const string::value_type* const INLINE;
@ -87,7 +87,7 @@ namespace vmime
} }
// Charsets /** Constants for charsets. */
namespace charsets namespace charsets
{ {
extern const string::value_type* const ISO8859_1; 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_1257;
extern const string::value_type* const WINDOWS_1258; 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 "contentDispositionField.hpp"
#include "exception.hpp" #include "exception.hpp"
#include "standardParams.hpp"
namespace vmime namespace vmime
{ {
@ -30,32 +32,69 @@ contentDispositionField::contentDispositionField()
} }
void contentDispositionField::parseValue(const string& buffer, const string::size_type position, contentDispositionField::contentDispositionField(contentDispositionField&)
const string::size_type end) : 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; dynamic_cast <dateParameter&>(*getParameter("creation-date")).setValue(creationDate);
return (*this);
} }
void contentDispositionField::copyFrom(const headerField& field) const datetime& contentDispositionField::getModificationDate() const
{ {
const contentDispositionField& source = dynamic_cast<const contentDispositionField&>(field); return (dynamic_cast <const dateParameter&>(*findParameter("modification-date")).getValue());
m_value = source.m_value; }
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 "parameterizedHeaderField.hpp"
#include "disposition.hpp" #include "genericField.hpp"
#include "dateParameter.hpp" #include "disposition.hpp"
#include "textParameter.hpp" #include "dateTime.hpp"
namespace vmime namespace vmime
{ {
class contentDispositionField : public parameterizedHeaderField class contentDispositionField : public parameterizedHeaderField, public genericField <disposition>
{ {
friend class headerFieldFactory::registerer <contentDispositionField>; friend class headerFieldFactory::registerer <contentDispositionField>;
protected: protected:
contentDispositionField(); contentDispositionField();
contentDispositionField(contentDispositionField&);
public: 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); } const datetime& getReadDate() const;
disposition& value() { return (m_value); } void setReadDate(const datetime& readDate);
const datetime& creationDate() const { return (dynamic_cast<const dateParameter&>(parameters.find("creation-date")).value()); } const string getFilename() const;
datetime& creationDate() { return (dynamic_cast<dateParameter&>(parameters.get("creation-date")).value()); } void setFilename(const string& filename);
const datetime& modificationDate() const { return (dynamic_cast<const dateParameter&>(parameters.find("modification-date")).value()); } const string getSize() const;
datetime& modificationDate() { return (dynamic_cast<dateParameter&>(parameters.get("modification-date")).value()); } void setSize(const string& size);
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;
}; };

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_type = TYPE_STRING;
m_encoding = enc; 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_type = TYPE_STRING;
m_encoding = enc; 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) const string::size_type end, const vmime::encoding& enc)
{ {
m_type = TYPE_STRING; 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) const bool own, const vmime::encoding& enc)
{ {
m_type = TYPE_STREAM; 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) contentHandler& contentHandler::operator=(const string& buffer)
{ {
set(buffer, NO_ENCODING); setData(buffer, NO_ENCODING);
return (*this); 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> theDecoder(m_encoding.getEncoder());
utility::auto_ptr <encoder> theEncoder(enc.getEncoder()); utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
theEncoder->properties()["maxlinelength"] = maxLineLength; theEncoder->getProperties()["maxlinelength"] = maxLineLength;
switch (m_type) switch (m_type)
{ {
@ -234,7 +234,7 @@ void contentHandler::generate(utility::outputStream& os, const vmime::encoding&
else else
{ {
utility::auto_ptr <encoder> theEncoder(enc.getEncoder()); utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
theEncoder->properties()["maxlinelength"] = maxLineLength; theEncoder->getProperties()["maxlinelength"] = maxLineLength;
// Encode the contents // Encode the contents
switch (m_type) 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) 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); 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); return (m_encoding);
} }

View File

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

View File

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

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)) if (p < pend && isdigit(*p))
{ {
// Month day // Month day
comp_t day = 0; int day = 0;
do do
{ {
@ -221,7 +221,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p)) if (p < pend && isdigit(*p))
{ {
// Year // Year
comp_t year = 0; int year = 0;
do do
{ {
@ -249,7 +249,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p)) if (p < pend && isdigit(*p))
{ {
// Hour // Hour
comp_t hour = 0; int hour = 0;
do do
{ {
@ -271,7 +271,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p)) if (p < pend && isdigit(*p))
{ {
// Minute // Minute
comp_t minute = 0; int minute = 0;
do do
{ {
@ -293,7 +293,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
if (p < pend && isdigit(*p)) if (p < pend && isdigit(*p))
{ {
// Second // Second
comp_t second = 0; int second = 0;
do do
{ {
@ -342,7 +342,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
++p; ++p;
// Zone offset (in hour/minutes) // Zone offset (in hour/minutes)
comp_t offset = 0; int offset = 0;
do do
{ {
@ -351,8 +351,8 @@ void datetime::parse(const string& buffer, const string::size_type position,
} }
while (p < pend && isdigit(*p)); while (p < pend && isdigit(*p));
const comp_t hourOff = offset / 100; const int hourOff = offset / 100;
const comp_t minOff = offset % 100; const int minOff = offset % 100;
if (sign == '+') if (sign == '+')
m_zone = hourOff * 60 + minOff; 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", { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
const comp_t z = ((m_zone < 0) ? -m_zone : m_zone); const int z = ((m_zone < 0) ? -m_zone : m_zone);
const comp_t zh = z / 60; const int zh = z / 60;
const comp_t zm = z % 60; const int zm = z % 60;
std::ostringstream oss; std::ostringstream oss;
oss << dayNames[dayOfWeek(m_year, m_month, m_day)] << ", " 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_hour << ":"
<< std::setfill('0') << std::setw(2) << m_minute << ":" << std::setfill('0') << std::setw(2) << m_minute << ":"
<< std::setfill('0') << std::setw(2) << m_second << 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_year(year), m_month(month), m_day(day),
m_hour(0), m_minute(0), m_second(0), m_zone(0) 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, datetime::datetime(const int year, const int month, const int day,
const comp_t hour, const comp_t minute, const comp_t second, const int hour, const int minute, const int second,
const comp_t zone) const int zone)
: m_year(year), m_month(month), m_day(day), : m_year(year), m_month(month), m_day(day),
m_hour(hour), m_minute(minute), m_second(second), m_zone(zone) 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_year = d.m_year;
m_month = d.m_month; m_month = d.m_month;
m_day = d.m_day; 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); 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; hour = m_hour;
minute = m_minute; 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; hour = m_hour;
minute = m_minute; 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; year = m_year;
month = m_month; 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, void datetime::setTime(const int hour, const int minute,
const comp_t second, const comp_t zone) const int second, const int zone)
{ {
m_hour = hour; m_hour = hour;
m_minute = minute; 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_year = year;
m_month = month; 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; int y = year;
comp_t m = month; int m = month;
// From RFC-3339 - Appendix B. Day of the Week // 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 // Split by century
const comp_t cent = y / 100; const int cent = y / 100;
y %= 100; y %= 100;
return (((26 * m - 2) / 10 + day + y + (y >> 2) + (cent >> 2) + 5 * cent) % 7); 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 } // vmime

View File

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

View File

@ -31,7 +31,7 @@ defaultAttachment::defaultAttachment()
defaultAttachment::defaultAttachment(const contentHandler& data, 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) : 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 = m_type = attach.m_type;
dynamic_cast <const defaultAttachment&>(attach); m_desc = attach.m_desc;
m_data = attach.m_data;
m_type = att.m_type; m_encoding = attach.m_encoding;
m_desc = att.m_desc;
m_data = att.m_data;
m_encoding = att.m_encoding;
return (*this); return (*this);
} }
@ -69,7 +66,7 @@ void defaultAttachment::generateIn(bodyPart& parent) const
{ {
// Create and append a new part for this attachment // Create and append a new part for this attachment
bodyPart* part = new bodyPart; bodyPart* part = new bodyPart;
parent.body().parts.append(part); parent.getBody()->appendPart(part);
generatePart(*part); generatePart(*part);
} }
@ -78,13 +75,37 @@ void defaultAttachment::generateIn(bodyPart& parent) const
void defaultAttachment::generatePart(bodyPart& part) const void defaultAttachment::generatePart(bodyPart& part) const
{ {
// Set header fields // Set header fields
part.header().fields.ContentType() = m_type; part.getHeader()->ContentType().setValue(m_type);
if (!m_desc.empty()) part.header().fields.ContentDescription() = m_desc; if (!m_desc.isEmpty()) part.getHeader()->ContentDescription().setValue(m_desc);
part.header().fields.ContentTransferEncoding() = m_encoding; part.getHeader()->ContentTransferEncoding().setValue(m_encoding);
part.header().fields.ContentDisposition() = disposition(dispositionTypes::ATTACHMENT); part.getHeader()->ContentDisposition().setValue(disposition(dispositionTypes::ATTACHMENT));
// Set contents // 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: 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 contentHandler& data, const mediaType& type, const text& desc = NULL_TEXT);
defaultAttachment(const defaultAttachment& attach); defaultAttachment(const defaultAttachment& attach);
attachment& operator=(const attachment& attach); defaultAttachment& operator=(const defaultAttachment& attach);
const mediaType& type() const { return (m_type); } const mediaType& getType() const;
const text& description() const { return (m_desc); } const text& getDescription() const;
const contentHandler& data() const { return (m_data); } const contentHandler& getData() const;
const class encoding& encoding() const { return (m_encoding); } const encoding& getEncoding() const;
protected: protected:
mediaType m_type; // Media type (eg. "application/octet-stream") mediaType m_type; // Media type (eg. "application/octet-stream")
text m_desc; // Description (eg. "The image you requested") text m_desc; // Description (eg. "The image you requested")
contentHandler m_data; // Attachment data (eg. the file contents) 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). // No need to override "generateIn", use "generatePart" instead (see below).
void generateIn(bodyPart& parent) const; void generateIn(bodyPart& parent) const;
protected:
virtual void generatePart(bodyPart& part) const; 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 "disposition.hpp"
#include "utility/stringUtils.hpp"
namespace vmime namespace vmime
@ -31,7 +32,7 @@ disposition::disposition()
disposition::disposition(const string& name) 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, void disposition::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition) 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) if (newPosition)
*newPosition = end; *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) disposition& disposition::operator=(const string& name)
{ {
m_name = toLower(name); m_name = stringUtils::toLower(name);
return (*this); return (*this);
} }
const bool disposition::operator==(const disposition& value) const 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 } // vmime

View File

@ -40,20 +40,32 @@ public:
disposition(const string& name); disposition(const string& name);
disposition(const disposition& disp); disposition(const disposition& disp);
public:
const string& name() const { return (m_name); } /** Return the disposition type.
string& name() { return (m_name); } * 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); disposition& operator=(const string& name);
const bool operator==(const disposition& value) const; const bool operator==(const disposition& value) const;
const bool operator!=(const disposition& value) const; const bool operator!=(const disposition& value) const;
protected: private:
string m_name; string m_name;

View File

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

View File

@ -57,30 +57,30 @@ public:
* *
* @return properties of the encoder * @return properties of the encoder
*/ */
const propertySet& properties() const; const propertySet& getProperties() const;
/** Return the properties of the encoder. /** Return the properties of the encoder.
* *
* @return properties of the encoder * @return properties of the encoder
*/ */
propertySet& properties(); propertySet& getProperties();
/** Return a list of property names that can be set for /** Return a list of property names that can be set for
* this encoder. * this encoder.
* *
* @return list of property names * @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 the results returned by this encoder.
* *
* @return results returned by the encoder * @return results returned by the encoder
*/ */
const propertySet& results() const; const propertySet& getResults() const;
protected: protected:
propertySet& results(); propertySet& getResults();
private: 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"); list.push_back("maxlinelength");
@ -70,7 +70,7 @@ const utility::stream::size_type encoderB64::encode(utility::inputStream& in, ut
{ {
in.reset(); // may not work... 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 bool cutLines = (propMaxLineLength != -1);
const int maxLineLength = std::min(propMaxLineLength, 76); 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 encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(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: protected:

View File

@ -46,24 +46,58 @@ encoderFactory::encoderFactory()
encoderFactory::~encoderFactory() encoderFactory::~encoderFactory()
{ {
for (NameMap::iterator it = m_nameMap.begin() ; it != m_nameMap.end() ; ++it) for (std::vector <registeredEncoder*>::const_iterator it = m_encoders.begin() ;
delete ((*it).second); it != m_encoders.end() ; ++it)
{
delete (*it);
}
} }
encoder* encoderFactory::create(const string& name) 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(); res.push_back(*it);
return (NULL);
} }
return (res);
} }

View File

@ -23,6 +23,7 @@
#include "encoder.hpp" #include "encoder.hpp"
#include "utility/singleton.hpp" #include "utility/singleton.hpp"
#include "utility/stringUtils.hpp"
namespace vmime namespace vmime
@ -43,6 +44,7 @@ private:
public: public:
/** Information about a registered encoder. */
class registeredEncoder class registeredEncoder
{ {
friend class encoderFactory; friend class encoderFactory;
@ -53,9 +55,9 @@ public:
public: public:
virtual encoder* create() = 0; virtual encoder* create() const = 0;
virtual const string& name() const = 0; virtual const string& getName() const = 0;
}; };
private: private:
@ -71,12 +73,12 @@ private:
public: public:
encoder* create() encoder* create() const
{ {
return new E; return new E;
} }
const string& name() const const string& getName() const
{ {
return (m_name); return (m_name);
} }
@ -87,93 +89,56 @@ private:
}; };
typedef std::map <string, registeredEncoder*> NameMap; std::vector <registeredEncoder*> m_encoders;
NameMap m_nameMap;
public: public:
/** Register a new encoder by its encoding name.
*
* @param name encoding name
*/
template <class E> template <class E>
void registerName(const string& name) void registerName(const string& name)
{ {
const string _name = toLower(name); m_encoders.push_back(new registeredEncoderImpl <E>(stringUtils::toLower(name)));
m_nameMap.insert(NameMap::value_type(_name,
new registeredEncoderImpl <E>(_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); 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 /** Return a list of all registered encoders.
{ *
friend class encoderFactory; * @return list of registered encoders
*/
public: const std::vector <const registeredEncoder*> getEncoderList() const;
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()); }
}; };

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

View File

@ -27,15 +27,15 @@ namespace vmime
encoderUUE::encoderUUE() encoderUUE::encoderUUE()
{ {
properties()["mode"] = 644; getProperties()["mode"] = 644;
properties()["filename"] = "no_name"; getProperties()["filename"] = "no_name";
properties()["maxlinelength"] = 46; 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"); list.push_back("maxlinelength");
@ -63,11 +63,11 @@ const utility::stream::size_type encoderUUE::encode(utility::inputStream& in, ut
{ {
in.reset(); // may not work... in.reset(); // may not work...
const string propFilename = properties().get <string>("filename", ""); const string propFilename = getProperties().getProperty <string>("filename", "");
const string propMode = properties().get <string>("mode", "644"); const string propMode = getProperties().getProperty <string>("mode", "644");
const string::size_type maxLineLength = 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)); static_cast <string::size_type>(46));
utility::stream::size_type total = 0; 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; while (*p && !isspace(*p)) ++p;
results()["mode"] = string(modeStart, p); getResults()["mode"] = string(modeStart, p);
while (*p && isspace(*p)) ++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; while (*p && !(*p == '\r' || *p == '\n')) ++p;
results()["filename"] = string(filenameStart, p); getResults()["filename"] = string(filenameStart, p);
} }
// No filename or mode specified // No filename or mode specified
else else
{ {
results()["filename"] = "untitled"; getResults()["filename"] = "untitled";
results()["mode"] = 644; getResults()["mode"] = 644;
} }
continue; 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 encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(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) 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, void encoding::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition) 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) if (newPosition)
*newPosition = end; *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); return (*this);
} }
encoding& encoding::operator=(const string& name) encoding& encoding::operator=(const string& name)
{ {
m_name = toLower(name); m_name = stringUtils::toLower(name);
return (*this); return (*this);
} }
const bool encoding::operator==(const encoding& value) const 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 */) const encoding encoding::decide(const contentHandler& /* data */)
{ {
// TODO: a better solution to do that?
return (encoding(encodingTypes::BASE64)); 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 } // vmime

View File

@ -46,27 +46,56 @@ public:
public: public:
const string& name() const { return (m_name); } /** Return the name of the encoding.
string& name() { return (m_name); } * 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); encoding& operator=(const string& name);
const bool operator==(const encoding& value) const; const bool operator==(const encoding& value) const;
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); 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); 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; encoder* getEncoder() const;
protected: private:
string m_name; string m_name;

View File

@ -45,6 +45,8 @@ public:
}; };
/** List of all VMime exceptions. */
namespace 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 class open_file_error : public vmime::exception
{ {
public: public:

View File

@ -40,7 +40,7 @@ fileAttachment::fileAttachment(const string& filename, const mediaType& type, co
fileAttachment::fileAttachment(const string& filename, const mediaType& type, 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_type = type;
m_desc = desc; m_desc = desc;
@ -62,7 +62,7 @@ void fileAttachment::setData(const string& filename)
throw exceptions::open_file_error(); 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); 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.hasSize()) cdf.setSize(stringUtils::toString(m_fileInfo.getSize()));
if (m_fileInfo.hasFilename()) cdf.filename() = m_fileInfo.getFilename(); if (m_fileInfo.hasFilename()) cdf.setFilename(m_fileInfo.getFilename());
if (m_fileInfo.hasCreationDate()) cdf.creationDate() = m_fileInfo.getCreationDate(); if (m_fileInfo.hasCreationDate()) cdf.setCreationDate(m_fileInfo.getCreationDate());
if (m_fileInfo.hasModificationDate()) cdf.modificationDate() = m_fileInfo.getModificationDate(); if (m_fileInfo.hasModificationDate()) cdf.setModificationDate(m_fileInfo.getModificationDate());
if (m_fileInfo.hasReadDate()) cdf.readDate() = m_fileInfo.getReadDate(); 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 // fileAttachment::fileInfo
// //

View File

@ -33,7 +33,7 @@ class fileAttachment : public defaultAttachment
public: public:
fileAttachment(const string& filename, const mediaType& type, const text& desc = NULL_TEXT); 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 class fileInfo
{ {
@ -71,14 +71,14 @@ public:
datetime* m_readDate; datetime* m_readDate;
}; };
const class fileInfo& fileInfo() const { return (m_fileInfo); } const fileInfo& getFileInfo() const;
class fileInfo& fileInfo() { return (m_fileInfo); } fileInfo& getFileInfo();
protected: private:
void setData(const string& filename); void setData(const string& filename);
class fileInfo m_fileInfo; fileInfo m_fileInfo;
void generatePart(bodyPart& part) const; 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() header::~header()
{ {
removeAllFields();
} }
@ -59,7 +60,7 @@ void header::parse(const string& buffer, const string::size_type position,
{ {
string::size_type pos = position; string::size_type pos = position;
fields.clear(); removeAllFields();
while (pos < end) while (pos < end)
{ {
@ -181,8 +182,8 @@ void header::parse(const string& buffer, const string::size_type position,
} }
// Add a new field to list // Add a new field to list
fields.m_fields.push_back(headerFieldFactory::getInstance()-> m_fields.push_back(headerFieldFactory::getInstance()->
create(headerField::nameToType(name), name, contents)); create(name, contents));
} }
} }
else 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 const string::size_type /* curLinePos */, string::size_type* newLinePos) const
{ {
// Generate the fields // Generate the fields
for (std::vector <headerField*>::const_iterator for (std::vector <headerField*>::const_iterator it = m_fields.begin() ;
it = fields.m_fields.begin() ; it != fields.m_fields.end() ; ++it) it != m_fields.end() ; ++it)
{ {
(*it)->generate(os, maxLineLength); (*it)->generate(os, maxLineLength);
os << CRLF; 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); return (*this);
} }
const bool header::hasField(const string& fieldName) const
//////////////////////
// Fields container //
//////////////////////
header::fieldsContainer::fieldsContainer()
{ {
} 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(); std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end(); 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); 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); const string name = stringUtils::toLower(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);
// Find the first field that matches the specified name // Find the first field that matches the specified name
std::vector <headerField*>::const_iterator pos = m_fields.begin(); std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end(); 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 // No field with this name can be found
if (pos == end) 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 a reference to the existing field
else 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; const string name = stringUtils::toLower(fieldName);
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);
std::vector <headerField*> result; std::vector <headerField*> result;
@ -365,7 +344,7 @@ std::vector <headerField*> header::fieldsContainer::findAllByName(const string&
for ( ; pos != end ; ++pos) for ( ; pos != end ; ++pos)
{ {
// Add the header if it matches the specified type // Add the header if it matches the specified type
if (toLower((*pos)->name()) == name) if (stringUtils::toLower((*pos)->getName()) == name)
{ {
result.push_back(*pos); 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 const string name = stringUtils::toLower(fieldName);
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);
// Find the first field that matches the specified name // Find the first field that matches the specified name
std::vector <headerField*>::const_iterator pos = m_fields.begin(); std::vector <headerField*>::const_iterator pos = m_fields.begin();
const std::vector <headerField*>::const_iterator end = m_fields.end(); 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 no field with this name can be found, create a new one
if (pos == end) if (pos == end)
{ {
headerField* field = headerFieldFactory::getInstance()->create(fieldName); 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 a reference to the new field
return (*field); return (field);
} }
// Else, return a reference to the existing field // Else, return a reference to the existing field
else else
{ {
return (**pos); return (*pos);
} }
} }
void header::fieldsContainer::insertSorted(headerField* field) void header::appendField(headerField* field)
{ {
const headerField::Types type = field->type(); m_fields.push_back(field);
std::vector <headerField*>::iterator i;
for (i = m_fields.begin() ; (i != m_fields.end()) && ((*i)->type() < type) ; ++i);
m_fields.insert(i, field);
} }
// Field insertion void header::insertFieldBefore(headerField* beforeField, headerField* field)
void header::fieldsContainer::append(const 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::insertFieldAfter(headerField* afterField, headerField* field)
void header::fieldsContainer::remove(const iterator it)
{ {
delete (*it.m_iterator); const std::vector <headerField*>::iterator it = std::find
m_fields.erase(it.m_iterator); (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) m_fields.insert(m_fields.begin() + pos + 1, field);
delete (*it);
m_fields.clear();
} }
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) if (it == m_fields.end())
fields.push_back((*it)->clone()); 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()); m_fields.erase(it);
std::copy(fields.begin(), fields.end(), m_fields.begin()); }
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 "headerField.hpp"
#include "headerFieldFactory.hpp" #include "headerFieldFactory.hpp"
#include "addressListField.hpp"
#include "mailboxListField.hpp"
#include "mailboxField.hpp" #include "mailboxField.hpp"
#include "textField.hpp"
#include "dateField.hpp"
#include "contentTypeField.hpp" #include "contentTypeField.hpp"
#include "contentEncodingField.hpp"
#include "defaultField.hpp"
#include "contentDispositionField.hpp" #include "contentDispositionField.hpp"
#include "messageIdField.hpp"
#include "standardFields.hpp"
#include "standardParams.hpp"
namespace vmime namespace vmime
@ -61,196 +57,166 @@ public:
header(); header();
~header(); ~header();
// A sub-class for field manipulation #define FIELD_ACCESS(methodName, fieldName, type) \
class fieldsContainer type& methodName() { return dynamic_cast <type&> \
{ (*getField(fields::fieldName)); } \
friend class header; 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(); FIELD_ACCESS(To, TO, addressListField)
~fieldsContainer(); 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 #undef 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))); }
const mailboxField& From() const { return (dynamic_cast<mailboxField&>(find(headerField::From))); } /** Checks whether (at least) one field with this name exists.
const mailboxField& Sender() const { return (dynamic_cast<mailboxField&>(find(headerField::Sender))); } *
const mailboxField& ReplyTo() const { return (dynamic_cast<mailboxField&>(find(headerField::ReplyTo))); } * @return true if at least one field with the specified name
const mailboxField& DeliveredTo() const { return (dynamic_cast<mailboxField&>(find(headerField::DeliveredTo))); } * exists, or false otherwise
const addressListField& To() const { return (dynamic_cast<addressListField&>(find(headerField::To))); } */
const addressListField& Cc() const { return (dynamic_cast<addressListField&>(find(headerField::Cc))); } const bool hasField(const string& fieldName) const;
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 type/name exists /** Find the first field that matches the specified name.
const bool has(const headerField::Types fieldType) const; * If no field is found, an exception is thrown.
const bool has(const string& fieldName) const; *
* @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. /** Find all fields that match the specified name.
// If no field is found, an exception is thrown. * If no field is found, an empty vector is returned.
headerField& find(const headerField::Types fieldType) const; *
headerField& find(const string& fieldName) const; * @return list of fields with the specified name
*/
std::vector <headerField*> findAllFields(const string& fieldName);
// Find all fields that matche the specified type/name. /** Find the first field that matches the specified name.
// If no field is found, an empty vector is returned. * If no field is found, one will be created and inserted into
std::vector <headerField*> findAllByType(const headerField::Types fieldType); * the header.
std::vector <headerField*> findAllByName(const string& fieldName); *
* @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. /** Add a field at the end of the list.
// If no field is found, one will be created. *
headerField& get(const headerField::Types fieldType); * @param field field to append
headerField& get(const string& fieldName); */
void appendField(headerField* field);
// Field iterator /** Insert a new field before the specified field.
class const_iterator; *
* @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 /** Insert a new field before the specified position.
{ *
friend class header::fieldsContainer::const_iterator; * @param pos position at which to insert the new field (0 to insert at
friend class header::fieldsContainer; * 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) { } /** Remove the specified field from the list.
iterator(const iterator& it) : m_iterator(it.m_iterator) { } *
* @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); } /** Remove all fields from the list.
headerField* operator->() const { return (*m_iterator); } */
void removeAllFields();
iterator& operator++() { ++m_iterator; return (*this); } /** Return the number of fields in the list.
iterator operator++(int) { iterator i(*this); ++m_iterator; return (i); } *
* @return number of fields
*/
const int getFieldCount() const;
iterator& operator--() { --m_iterator; return (*this); } /** Tests whether the list of fields is empty.
iterator operator--(int) { iterator i(*this); --m_iterator; return (i); } *
* @return true if there is no field, false otherwise
*/
const bool isEmpty() const;
iterator& operator+=(difference_type n) { m_iterator += n; return (*this); } /** Return the field at the specified position.
iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); } *
* @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); } /** Return the field list.
const bool operator!=(const iterator& it) const { return (!(*this == it)); } *
* @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 std::vector <headerField*> m_fields;
{
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);
public: public:

View File

@ -26,13 +26,13 @@ namespace vmime
headerField::headerField() headerField::headerField()
: m_type(Custom), m_name("Undefined") : m_name("X-Undefined")
{ {
} }
headerField::headerField(const string& fieldName) 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* headerField::clone() const
{ {
headerField* field = NULL; headerField* field = headerFieldFactory::getInstance()->create(m_name);
if (m_type == Custom)
field = headerFieldFactory::getInstance()->create(m_name);
else
field = headerFieldFactory::getInstance()->create(m_type);
field->copyFrom(*this); 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); 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; getValue().parse(buffer, position, end, newPosition);
m_name = field.m_name;
} }
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 const string::size_type curLinePos, string::size_type* newLinePos) const
{ {
if (m_type == Custom) os << m_name + ": ";
{
os << m_name + ": ";
if (newLinePos) getValue().generate(os, maxLineLength, curLinePos + m_name.length() + 2, newLinePos);
*newLinePos = curLinePos + m_name.length() + 2;
}
else
{
const string name = typeToName(m_type);
os << name + ": ";
if (newLinePos)
*newLinePos = curLinePos + name.length() + 2;
}
} }
/** Return the field type corresponding to the specified name. const string headerField::getName() const
*
* @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)
{ {
switch (name[0]) return (m_name);
{
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 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 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(); ~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 /** Return the name of this field.
// in the message header) *
enum Types * @return field name
{ */
Received, // Relay const string getName() const;
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;
/** 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; const bool isCustom() const;
virtual void copyFrom(const headerField& field); /** Return the read-only value object attached to this field.
headerField& operator=(const headerField& field); *
headerField* clone() const; * @return read-only value object
*/
virtual const component& getValue() const = 0;
static const Types nameToType(const string& name); /** Return the value object attached to this field.
static const string typeToName(const Types type); *
* @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; 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; 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 "headerFieldFactory.hpp"
#include "exception.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 "mailboxField.hpp"
#include "contentTypeField.hpp" #include "contentTypeField.hpp"
#include "contentEncodingField.hpp"
#include "contentDispositionField.hpp" #include "contentDispositionField.hpp"
#include "messageIdField.hpp"
namespace vmime namespace vmime
@ -43,28 +33,28 @@ namespace vmime
headerFieldFactory::headerFieldFactory() headerFieldFactory::headerFieldFactory()
{ {
// Register some default field types // Register some default fields
registerType <mailboxField>(headerField::From); registerName <mailboxField>(vmime::fields::FROM);
registerType <addressListField>(headerField::To); registerName <addressListField>(vmime::fields::TO);
registerType <addressListField>(headerField::Cc); registerName <addressListField>(vmime::fields::CC);
registerType <addressListField>(headerField::Bcc); registerName <addressListField>(vmime::fields::BCC);
registerType <mailboxField>(headerField::Sender); registerName <mailboxField>(vmime::fields::SENDER);
registerType <dateField>(headerField::Date); registerName <dateField>(vmime::fields::DATE);
registerType <relayField>(headerField::Received); registerName <relayField>(vmime::fields::RECEIVED);
registerType <textField>(headerField::Subject); registerName <textField>(vmime::fields::SUBJECT);
registerType <mailboxField>(headerField::ReplyTo); registerName <mailboxField>(vmime::fields::REPLY_TO);
registerType <mailboxField>(headerField::DeliveredTo); registerName <mailboxField>(vmime::fields::DELIVERED_TO);
registerType <textField>(headerField::Organization); registerName <textField>(vmime::fields::ORGANIZATION);
registerType <textField>(headerField::UserAgent); registerName <textField>(vmime::fields::USER_AGENT);
registerType <mailboxField>(headerField::ReturnPath); registerName <mailboxField>(vmime::fields::RETURN_PATH);
registerType <contentTypeField>(headerField::ContentType); registerName <contentTypeField>(vmime::fields::CONTENT_TYPE);
registerType <contentEncodingField>(headerField::ContentTransferEncoding); registerName <contentEncodingField>(vmime::fields::CONTENT_TRANSFER_ENCODING);
registerType <textField>(headerField::ContentDescription); registerName <textField>(vmime::fields::CONTENT_DESCRIPTION);
registerType <defaultField>(headerField::MimeVersion); registerName <defaultField>(vmime::fields::MIME_VERSION);
registerType <contentDispositionField>(headerField::ContentDisposition); registerName <contentDispositionField>(vmime::fields::CONTENT_DISPOSITION);
registerType <messageIdField>(headerField::ContentId); registerName <messageIdField>(vmime::fields::CONTENT_ID);
registerType <messageIdField>(headerField::MessageId); registerName <messageIdField>(vmime::fields::MESSAGE_ID);
registerType <defaultField>(headerField::ContentLocation); registerName <defaultField>(vmime::fields::CONTENT_LOCATION);
} }
@ -76,63 +66,24 @@ headerFieldFactory::~headerFieldFactory()
headerField* headerFieldFactory::create headerField* headerFieldFactory::create
(const string& name, const string& body) (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 else
{ {
NameMap::const_iterator pos = m_nameMap.find(toLower(name)); field = registerer <defaultField>::creator();
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->m_name = name;
headerField* headerFieldFactory::create(const headerField::Types type, if (body != NULL_STRING)
const string& name, const string& body) field->parse(body);
{
if (type == headerField::Custom)
{
return (create(name, body));
}
else
{
TypeMap::const_iterator pos = m_typeMap.find(type);
if (pos != m_typeMap.end()) return (field);
{
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();
}
}
} }

View File

@ -23,6 +23,7 @@
#include "headerField.hpp" #include "headerField.hpp"
#include "utility/singleton.hpp" #include "utility/singleton.hpp"
#include "utility/stringUtils.hpp"
namespace vmime namespace vmime
@ -40,10 +41,8 @@ protected:
typedef headerField* (*AllocFunc)(void); typedef headerField* (*AllocFunc)(void);
typedef std::map <string, AllocFunc> NameMap; typedef std::map <string, AllocFunc> NameMap;
typedef std::map <headerField::Types, AllocFunc> TypeMap;
NameMap m_nameMap; NameMap m_nameMap;
TypeMap m_typeMap;
public: public:
@ -63,19 +62,10 @@ public:
template <class T> template <class T>
void registerName(const string& name) 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 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() htmlTextPart::~htmlTextPart()
{ {
free_container(m_objects);
} }
const mediaType htmlTextPart::type() const const mediaType htmlTextPart::getType() const
{ {
return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML)); return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML));
} }
@ -38,26 +39,26 @@ const mediaType htmlTextPart::type() const
const int htmlTextPart::getPartCount() 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 void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
{ {
// Plain text // Plain text
if (!m_plainText.empty()) if (!m_plainText.isEmpty())
{ {
// -- Create a new part // -- Create a new part
bodyPart* part = new bodyPart(); bodyPart* part = new bodyPart();
parent.body().parts.append(part); parent.getBody()->appendPart(part);
// -- Set header fields // -- Set header fields
part->header().fields.ContentType() = mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN); part->getHeader()->ContentType().setValue(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN));
part->header().fields.ContentType().charset() = m_charset; part->getHeader()->ContentType().setCharset(m_charset);
part->header().fields.ContentTransferEncoding() = encoding(encodingTypes::QUOTED_PRINTABLE); part->getHeader()->ContentTransferEncoding().setValue(encoding(encodingTypes::QUOTED_PRINTABLE));
// -- Set contents // -- Set contents
part->body().contents() = m_plainText; part->getBody()->setContents(m_plainText);
} }
// HTML text // HTML text
@ -65,51 +66,51 @@ void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
bodyPart* htmlPart = new bodyPart(); bodyPart* htmlPart = new bodyPart();
// -- Set header fields // -- Set header fields
htmlPart->header().fields.ContentType() = mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML); htmlPart->getHeader()->ContentType().setValue(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML));
htmlPart->header().fields.ContentType().charset() = m_charset; htmlPart->getHeader()->ContentType().setCharset(m_charset);
htmlPart->header().fields.ContentTransferEncoding() = encoding(encodingTypes::QUOTED_PRINTABLE); htmlPart->getHeader()->ContentTransferEncoding().setValue(encoding(encodingTypes::QUOTED_PRINTABLE));
// -- Set contents // -- Set contents
htmlPart->body().contents() = m_text; htmlPart->getBody()->setContents(m_text);
// Handle the case we have embedded objects // Handle the case we have embedded objects
if (!embeddedObjects.empty()) if (!m_objects.empty())
{ {
// Create a "multipart/related" body part // Create a "multipart/related" body part
bodyPart* relPart = new bodyPart(); bodyPart* relPart = new bodyPart();
parent.body().parts.append(relPart); parent.getBody()->appendPart(relPart);
relPart->header().fields.ContentType() = mediaType relPart->getHeader()->ContentType().
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED); setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED));
// Add the HTML part into this part // Add the HTML part into this part
relPart->body().parts.append(htmlPart); relPart->getBody()->appendPart(htmlPart);
// Also add images into this part // Also add objects into this part
for (embeddedObjectsContainer::const_iterator i = embeddedObjects.begin() ; for (std::vector <embeddedObject*>::const_iterator it = m_objects.begin() ;
i != embeddedObjects.end() ; ++i) it != m_objects.end() ; ++it)
{ {
bodyPart* objPart = new bodyPart(); 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:") if (id.substr(0, 4) == "CID:")
id = id.substr(4); id = id.substr(4);
objPart->header().fields.ContentType() = (*i).type(); objPart->getHeader()->ContentType().setValue((*it)->getType());
objPart->header().fields.ContentId() = messageId("<" + id + ">"); objPart->getHeader()->ContentId().setValue(messageId("<" + id + ">"));
objPart->header().fields.ContentDisposition() = disposition(dispositionTypes::INLINE); objPart->getHeader()->ContentDisposition().setValue(disposition(dispositionTypes::INLINE));
objPart->header().fields.ContentTransferEncoding() = (*i).encoding(); objPart->getHeader()->ContentTransferEncoding().setValue((*it)->getEncoding());
//encoding(encodingTypes::BASE64); //encoding(encodingTypes::BASE64);
objPart->body().contents() = (*i).data(); objPart->getBody()->setContents((*it)->getData());
} }
} }
else else
{ {
// Add the HTML part into the parent part // 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, void htmlTextPart::findEmbeddedParts(const bodyPart& part,
std::vector <const bodyPart*>& cidParts, std::vector <const bodyPart*>& locParts) 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 try
{ {
dynamic_cast<messageIdField&>((*p).header().fields.find(headerField::ContentId)); dynamic_cast<messageIdField&>(*p.getHeader()->findField(fields::CONTENT_ID));
cidParts.push_back(&(*p)); cidParts.push_back(&p);
} }
catch (exceptions::no_such_field) catch (exceptions::no_such_field)
{ {
@ -130,8 +133,8 @@ void htmlTextPart::findEmbeddedParts(const bodyPart& part,
// Maybe there is a "Content-Location" field... // Maybe there is a "Content-Location" field...
try try
{ {
dynamic_cast<messageIdField&>((*p).header().fields.find(headerField::ContentId)); dynamic_cast<messageIdField&>(*p.getHeader()->findField(fields::CONTENT_ID));
locParts.push_back(&(*p)); locParts.push_back(&p);
} }
catch (exceptions::no_such_field) 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 try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&> 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) catch (exceptions::no_such_field)
{ {
// No "Content-type" field: assume "application/octet-stream". // No "Content-type" field: assume "application/octet-stream".
} }
embeddedObjects.m_list.push_back(new embeddedObject m_objects.push_back(new embeddedObject
(part.body().contents(), part.body().encoding(), id, type)); (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; std::ostringstream oss;
utility::outputStreamAdapter adapter(oss); utility::outputStreamAdapter adapter(oss);
textPart.body().contents().extract(adapter); textPart.getBody()->getContents().extract(adapter);
const string data = oss.str(); const string data = oss.str();
m_text = textPart.body().contents(); m_text = textPart.getBody()->getContents();
try try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&> 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) 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) for (std::vector <const bodyPart*>::const_iterator p = cidParts.begin() ; p != cidParts.end() ; ++p)
{ {
const messageIdField& midField = dynamic_cast<messageIdField&> 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) if (data.find(searchFor) != string::npos)
{ {
// This part is referenced in the HTML text. // This part is referenced in the HTML text.
// Add it to the embedded object list. // 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) for (std::vector <const bodyPart*>::const_iterator p = locParts.begin() ; p != locParts.end() ; ++p)
{ {
const defaultField& locField = dynamic_cast<defaultField&> 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. // This part is referenced in the HTML text.
// Add it to the embedded object list. // 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 try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&> const contentTypeField& ctf = dynamic_cast<contentTypeField&>
(part.header().fields.find(headerField::ContentType)); (*part.getHeader()->findField(fields::CONTENT_TYPE));
if (ctf.value().type() == mediaTypes::MULTIPART && if (ctf.getValue().getType() == mediaTypes::MULTIPART &&
ctf.value().subType() == mediaTypes::MULTIPART_ALTERNATIVE) ctf.getValue().getSubType() == mediaTypes::MULTIPART_ALTERNATIVE)
{ {
bodyPart const* foundPart = NULL; 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" const bodyPart* p = part.getBody()->getPartAt(i);
&(*p) == &textPart) // if not...
if (p == &parent || // if "text/html" is in "multipart/related"
p == &textPart) // if not...
{ {
foundPart = &(*p); foundPart = &(*p);
} }
@ -262,18 +267,19 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
bool found = false; bool found = false;
// Now, search for the alternative plain text part // Now, search for the alternative plain text part
for (body::const_iterator p = part.body().parts.begin() ; for (int i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i)
!found && p != part.body().parts.end() ; ++p)
{ {
const bodyPart& p = *part.getBody()->getPartAt(i);
try try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&> 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 &&
ctf.value().subType() == mediaTypes::TEXT_PLAIN) ctf.getValue().getSubType() == mediaTypes::TEXT_PLAIN)
{ {
m_plainText = (*p).body().contents(); m_plainText = p.getBody()->getContents();
found = true; found = true;
} }
} }
@ -297,44 +303,82 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
bool found = false; 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); return (found);
} }
const charset& htmlTextPart::getCharset() const
////////////////////////////////
// Embedded objects container //
////////////////////////////////
htmlTextPart::embeddedObjectsContainer::~embeddedObjectsContainer()
{ {
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) if ((*o)->getId() == id)
return (**o); return (*o);
} }
throw exceptions::no_object_found(); 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); return (true);
} }
@ -342,29 +386,64 @@ const bool htmlTextPart::embeddedObjectsContainer::has(const string& id) const
} }
const string htmlTextPart::embeddedObjectsContainer::add const string htmlTextPart::addObject(const contentHandler& data,
(const contentHandler& data, const vmime::encoding& enc, const mediaType& type) const vmime::encoding& enc, const mediaType& type)
{ {
const messageId mid(messageId::generateId()); 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); return (id);
} }
const string htmlTextPart::embeddedObjectsContainer::add const string htmlTextPart::addObject(const contentHandler& data, const mediaType& type)
(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 htmlTextPart::addObject(const string& data, const mediaType& type)
(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 class htmlTextPart : public textPart
{ {
protected: protected:
@ -40,127 +43,128 @@ protected:
public: public:
const mediaType type() const; const mediaType getType() const;
const vmime::charset& charset() const { return (m_charset); } const charset& getCharset() const;
vmime::charset& charset() { return (m_charset); } void setCharset(const charset& ch);
const contentHandler& plainText() const { return (m_plainText); } const contentHandler& getPlainText() const;
contentHandler& plainText() { return (m_plainText); } void setPlainText(const contentHandler& plainText);
const contentHandler& text() const { return (m_text); } const contentHandler& getText() const;
contentHandler& text() { return (m_text); } void setText(const contentHandler& text);
// Embedded object (eg. image for <IMG> tag) /** Embedded object (eg: image for <IMG> tag).
*/
class embeddedObject class embeddedObject
{ {
public: public:
embeddedObject(const contentHandler& data, const vmime::encoding& enc, embeddedObject(const contentHandler& data, const encoding& enc,
const string& id, const mediaType& type) const string& id, const mediaType& type);
: m_data(data), m_encoding(enc), m_id(id), m_type(type)
{
}
public: /** Return data stored in this embedded object.
*
* @return stored data
*/
const contentHandler& getData() const;
const contentHandler& data() const { return (m_data); } /** Return the encoding used for data in this
const vmime::encoding& encoding() const { return (m_encoding); } * embedded object.
const string& id() const { return (m_id); } *
const mediaType& type() const { return (m_type); } * @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: private:
contentHandler m_data; contentHandler m_data;
vmime::encoding m_encoding; encoding m_encoding;
string m_id; string m_id;
mediaType m_type; 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. /** Return the embedded object at the specified position.
const bool has(const string& id) const; *
const embeddedObject& find(const string& id) const; * @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. /** 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); * \deprecated Use the addObject() methods which take a 'contentHandler'
const string add(const contentHandler& data, const encoding& enc, const mediaType& type); * 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 /** Embed an object and returns a string which identifies it.
class const_iterator *
{ * @param data object data
public: * @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) { } private:
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:
contentHandler m_plainText; contentHandler m_plainText;
contentHandler m_text; 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 findEmbeddedParts(const bodyPart& part, std::vector <const bodyPart*>& cidParts, std::vector <const bodyPart*>& locParts);
void addEmbeddedObject(const bodyPart& part, const string& id); void addEmbeddedObject(const bodyPart& part, const string& id);
@ -170,7 +174,7 @@ protected:
const int getPartCount() const; const int getPartCount() const;
void generateIn(bodyPart& message, bodyPart& parent) 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) mailbox::mailbox(const mailbox& mbox)
: address(), m_name(mailbox.m_name), m_email(mailbox.m_email) : 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()) if (address.empty() && !name.empty())
{ {
m_email = name; m_email = name;
m_name.clear(); m_name.removeAllWords();
} }
else 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, void mailbox::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const const string::size_type curLinePos, string::size_type* newLinePos) const
{ {
if (m_name.empty()) if (m_name.isEmpty())
{ {
bool newLine = false; bool newLine = false;
@ -352,11 +352,11 @@ void mailbox::generate(utility::outputStream& os, const string::size_type maxLin
// and/or contain the special chars. // and/or contain the special chars.
bool forceEncode = false; 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() ; for (string::const_iterator c = buffer.begin() ;
!forceEncode && c != buffer.end() ; ++c) !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_name = source.m_name;
m_email = source.m_email; 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); return new mailbox(*this);
} }
const bool mailbox::empty() const const bool mailbox::isEmpty() const
{ {
return (m_email.empty()); return (m_email.empty());
} }
@ -446,7 +453,7 @@ const bool mailbox::empty() const
void mailbox::clear() void mailbox::clear()
{ {
m_name.clear(); m_name.removeAllWords();
m_email.clear(); 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 } // vmime

View File

@ -40,7 +40,7 @@ class mailbox : public address
public: public:
mailbox(); mailbox();
mailbox(const class mailbox& mailbox); mailbox(const mailbox& mbox);
mailbox(const string& email); mailbox(const string& email);
mailbox(const text& name, const string& email); mailbox(const text& name, const string& email);
@ -48,35 +48,36 @@ public:
* *
* @return full name of the mailbox * @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 * @return full name of the mailbox
*/ */
text& name() { return (m_name); } void setName(const text& name);
/** Return the email of the mailbox. /** Return the email of the mailbox.
* *
* @return 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 * @return email of the mailbox
*/ */
string& email() { return (m_email); } void setEmail(const string& email);
// Comparison // Comparison
const bool operator==(const class mailbox& mailbox) const; const bool operator==(const class mailbox& mailbox) const;
const bool operator!=(const class mailbox& mailbox) const; const bool operator!=(const class mailbox& mailbox) const;
// Assignment // Assignment
void copyFrom(const address& addr); void copyFrom(const component& other);
address* clone() const; mailbox* clone() const;
mailbox& operator=(const mailbox& other);
const bool empty() const; const bool isEmpty() const;
void clear(); 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, void mailboxField::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition) const string::size_type end, string::size_type* newPosition)
{ {
m_mailbox.clear(); getValue().clear();
// Here, we cannot simply call "m_mailbox.parse()" because it // Here, we cannot simply call "m_mailbox.parse()" because it
// may have more than one address specified (even if this field // 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 // mailbox of the group
mailboxGroup* group = static_cast <mailboxGroup*>(parsedAddress); mailboxGroup* group = static_cast <mailboxGroup*>(parsedAddress);
if (!group->empty()) if (!group->isEmpty())
m_mailbox = *(group->begin()); getValue() = *(group->getMailboxAt(0));
} }
else else
{ {
// Parse only if it is a mailbox // 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 } // vmime

View File

@ -21,10 +21,7 @@
#define VMIME_MAILBOXFIELD_HPP_INCLUDED #define VMIME_MAILBOXFIELD_HPP_INCLUDED
#include "base.hpp" #include "genericField.hpp"
#include "component.hpp"
#include "headerFieldFactory.hpp"
#include "mailbox.hpp" #include "mailbox.hpp"
@ -32,35 +29,18 @@ namespace vmime
{ {
class mailboxField : public headerField class mailboxField : public genericField <mailbox>
{ {
friend class headerFieldFactory::registerer <mailboxField>; friend class headerFieldFactory::registerer <mailboxField>;
protected: protected:
mailboxField(); mailboxField();
mailboxField(const mailboxField&);
public: 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 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 "mailboxGroup.hpp"
#include "parserHelpers.hpp" #include "parserHelpers.hpp"
#include "exception.hpp"
namespace vmime namespace vmime
@ -30,10 +31,10 @@ mailboxGroup::mailboxGroup()
} }
mailboxGroup::mailboxGroup(const class mailboxGroup& mailboxGroup) mailboxGroup::mailboxGroup(const mailboxGroup& mboxGroup)
: address() : address()
{ {
copyFrom(mailboxGroup); copyFrom(mboxGroup);
} }
@ -45,7 +46,7 @@ mailboxGroup::mailboxGroup(const text& name)
mailboxGroup::~mailboxGroup() 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 // Sub-groups are not allowed in mailbox groups: so, we add all
// the contents of the sub-group into this group... // the contents of the sub-group into this group...
for (mailboxGroup::const_iterator for (int i = 0 ; i < group->getMailboxCount() ; ++i)
it = group->begin() ; it != group->end() ; ++it)
{ {
m_list.push_back(static_cast <mailbox*>((*it).clone())); m_list.push_back(group->getMailboxAt(i)->clone());
} }
delete (parsedAddress); delete (parsedAddress);
@ -119,11 +119,11 @@ void mailboxGroup::generate(utility::outputStream& os, const string::size_type m
// and/or contain the special chars. // and/or contain the special chars.
bool forceEncode = false; 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() ; for (string::const_iterator c = buffer.begin() ;
!forceEncode && c != buffer.end() ; ++c) !forceEncode && c != buffer.end() ; ++c)
@ -158,7 +158,8 @@ void mailboxGroup::generate(utility::outputStream& os, const string::size_type m
os << ":"; os << ":";
++pos; ++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()) if (it != m_list.begin())
{ {
@ -171,7 +172,7 @@ void mailboxGroup::generate(utility::outputStream& os, const string::size_type m
++pos; ++pos;
} }
(*it).generate(os, maxLineLength - 2, pos, &pos); (*it)->generate(os, maxLineLength - 2, pos, &pos);
} }
os << ";"; 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); return new mailboxGroup(*this);
} }
// Mailbox insertion mailboxGroup& mailboxGroup::operator=(const component& other)
void mailboxGroup::append(const mailbox& field)
{ {
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::setName(const text& name)
void mailboxGroup::erase(const iterator it)
{ {
delete (*it.m_iterator); m_name = name;
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()));
} }
@ -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 } // vmime

View File

@ -38,102 +38,123 @@ class mailboxGroup : public address
public: public:
mailboxGroup(); mailboxGroup();
mailboxGroup(const class mailboxGroup& mailboxGroup); mailboxGroup(const mailboxGroup& mboxGroup);
mailboxGroup(const text& name); mailboxGroup(const text& name);
~mailboxGroup(); ~mailboxGroup();
// Properties set/get
const text& name() const { return (m_name); }
text& name() { return (m_name); }
// Assignment void copyFrom(const component& other);
void copyFrom(const address& addr); mailboxGroup* clone() const;
address* clone() const; mailboxGroup& operator=(const component& other);
public: /** Return the name of the group.
*
* @return group name
*/
const text& getName() const;
// Mailbox iterator /** Set the name of the group.
class const_iterator; *
* @param name group name
*/
void setName(const text& name);
class iterator /** Add a mailbox at the end of the list.
{ *
friend class mailboxGroup; * @param mbox mailbox to append
friend class const_iterator; */
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) { } /** Insert a new mailbox before the specified position.
iterator(const iterator& it) : m_iterator(it.m_iterator) { } *
* @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); } /** Insert a new mailbox after the specified position.
mailbox* operator->() const { return (*m_iterator); } *
* @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); } /** Remove the specified mailbox from the list.
iterator& operator++(int) { ++m_iterator; return (*this); } *
* @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); } /** Remove the mailbox at the specified position.
const bool operator!=(const iterator& it) const { return (!(*this == it)); } *
* @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 /** Tests whether the list of mailboxes is empty.
{ *
friend class mailboxGroup; * @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) { } /** Return the mailbox at the specified position.
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { } *
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { } * @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); } /** Return the mailbox list.
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); } *
* @return list of mailboxes
const mailbox& operator*() const { return (**m_iterator); } */
const mailbox* operator->() const { return (*m_iterator); } const std::vector <const mailbox*> getMailboxList() const;
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 <mailbox*> getMailboxList();
const bool isGroup() const; const bool isGroup() const;
protected: private:
text m_name; text m_name;
std::vector <mailbox*> m_list; std::vector <mailbox*> m_list;

View File

@ -18,28 +18,150 @@
// //
#include "mailboxList.hpp" #include "mailboxList.hpp"
#include "exception.hpp"
namespace vmime namespace vmime
{ {
// Address insertion mailboxList::mailboxList()
void mailboxList::append(const address& addr)
{ {
// 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). /** A list of mailboxes (basic type).
*/ */
class mailboxList : public addressList class mailboxList : protected addressList
{ {
friend class mailboxGroup; friend class mailboxGroup;
public: public:
// // This class works exactly like 'addressList' except it prevents user
// The following functions have the same name and work *exactly* like // from inserting mailbox groups where it is not allowed by the RFC.
// 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.
//
// Address iterator mailboxList();
class const_iterator; mailboxList(const mailboxList& mboxList);
class iterator /** Add a mailbox at the end of the list.
{ *
friend class mailboxList; * @param mbox mailbox to append
friend class const_iterator; */
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); } /** Remove the mailbox at the specified position.
mailbox* operator->() const { return static_cast<mailbox*>(*m_iterator); } *
* @param pos position of the mailbox to remove
*/
void removeMailbox(const int pos);
iterator& operator++() { ++m_iterator; return (*this); } /** Remove all mailboxes from the list.
iterator& operator++(int) { ++m_iterator; return (*this); } */
void removeAllMailboxes();
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); } /** Return the number of mailboxes in the list.
const bool operator!=(const iterator& it) const { return (!(*this == it)); } *
* @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 /** Return the mailbox at the specified position.
{ *
friend class mailboxList; * @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) { } /** Return the mailbox list.
*
public: * @return list of mailboxes
*/
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { } const std::vector <mailbox*> getMailboxList();
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);
}; };

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) 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; while (p < pend && *p != '/') ++p;
m_type = toLower(string(buffer.begin() + typeStart, m_type = stringUtils::toLower(string(buffer.begin() + typeStart,
buffer.begin() + position + (p - pstart))); buffer.begin() + position + (p - pstart)));
if (p < pend) if (p < pend)
{ {
@ -64,8 +64,8 @@ void mediaType::parse(const string& buffer, const string::size_type position,
++p; ++p;
// Extract the sub-type // Extract the sub-type
m_subType = toLower(string(buffer.begin() + position + (p - pstart), m_subType = stringUtils::toLower(string(buffer.begin() + position + (p - pstart),
buffer.begin() + end)); buffer.begin() + end));
} }
if (newPosition) 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, void mediaType::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const 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) 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) mediaType& mediaType::operator=(const string& type)
{ {
parse(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 } // vmime

View File

@ -21,6 +21,7 @@
#define VMIME_MEDIATYPE_HPP_INCLUDED #define VMIME_MEDIATYPE_HPP_INCLUDED
#include "base.hpp"
#include "component.hpp" #include "component.hpp"
@ -44,17 +45,46 @@ public:
const bool operator==(const mediaType& type) const; const bool operator==(const mediaType& type) const;
const bool operator!=(const mediaType& type) const; const bool operator!=(const mediaType& type) const;
mediaType& operator=(const mediaType& type);
mediaType& operator=(const string& type); mediaType& operator=(const string& type);
const string& type() const { return (m_type); }; mediaType* clone() const;
string& type() { return (m_type); } void copyFrom(const component& other);
mediaType& operator=(const mediaType& other);
const string& subType() const { return (m_subType); }; /** Return the media type.
string& subType() { return (m_subType); } * See the constants in vmime::mediaTypes.
*
* @return media type
*/
const string& getType() const;
void set(const string& type) { parse(type); } /** Set the media type.
void set(const string& type, const string& subType) { m_type = type; m_subType = subType; } * 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: protected:

View File

@ -48,28 +48,28 @@ message* messageBuilder::construct() const
message* msg = new message; message* msg = new message;
// Generate the header fields // 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(); 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(); throw exceptions::no_recipient();
msg->header().fields.From() = m_from; msg->getHeader()->From().setValue(m_from);
msg->header().fields.To() = m_to; msg->getHeader()->To().setValue(m_to);
if (!m_cc.empty()) if (!m_cc.isEmpty())
msg->header().fields.Cc() = m_cc; msg->getHeader()->Cc().setValue(m_cc);
if (!m_bcc.empty()) if (!m_bcc.isEmpty())
msg->header().fields.Bcc() = m_bcc; msg->getHeader()->Bcc().setValue(m_bcc);
// Add a "Date" field // Add a "Date" field
msg->header().fields.Date() = datetime::now(); msg->getHeader()->Date().setValue(datetime::now());
// Add a "Mime-Version" header field // 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 // If there is one or more attachments (or other parts that are
// not "text/...") and if there is more than one parts for the // 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) if (!m_attach.empty() && m_textPart->getPartCount() > 1)
{ {
// Set parent part (message) to "multipart/mixed" // Set parent part (message) to "multipart/mixed"
msg->header().fields.ContentType() = mediaType msg->getHeader()->ContentType().setValue
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED); (mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED));
// Create a sub-part "multipart/alternative" for text parts // Create a sub-part "multipart/alternative" for text parts
bodyPart* subPart = new bodyPart; bodyPart* subPart = new bodyPart;
msg->body().parts.append(subPart); msg->getBody()->appendPart(subPart);
subPart->header().fields.ContentType() = mediaType subPart->getHeader()->ContentType().setValue
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE); (mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE));
// Generate the text parts into this sub-part (normally, this // Generate the text parts into this sub-part (normally, this
// sub-part will have the "multipart/alternative" content-type...) // 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 any attachment, set message content-type to "multipart/mixed"
if (!m_attach.empty()) if (!m_attach.empty())
{ {
msg->header().fields.ContentType() = mediaType msg->getHeader()->ContentType().setValue
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED); (mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED));
} }
// Else, set it to "multipart/alternative" if there are more than one text part. // Else, set it to "multipart/alternative" if there are more than one text part.
else if (m_textPart->getPartCount() > 1) else if (m_textPart->getPartCount() > 1)
{ {
msg->header().fields.ContentType() = mediaType msg->getHeader()->ContentType().setValue
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE); (mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE));
} }
} }
// Generate the attachments // Generate the attachments
if (!m_attach.empty()) 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); (*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 // If there is only one part in the message, move it into the message
// (hence, the message will not be multipart...) // (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 // 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) for (std::vector <const headerField*>::const_iterator it = fields.begin() ;
msg->header().fields.get((*f).name()) = *f; it != fields.end() ; ++it)
{
*(msg->getHeader()->getField((*it)->getName())) = **it;
}
// Second, copy the body contents and sub-parts (this also remove // Second, copy the body contents and sub-parts (this also remove
// the body part we are copying...) // the body part we are copying...)
msg->body() = part.body(); msg->getBody()->copyFrom(*part.getBody());
} }
return (msg); return (msg);
@ -163,7 +167,7 @@ void messageBuilder::attach(attachment* attach)
void messageBuilder::constructTextPart(const mediaType& type) void messageBuilder::constructTextPart(const mediaType& type)
{ {
class textPart* part = NULL; textPart* part = NULL;
try 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: public:
// Expeditor and recipients /** Return the expeditor of the message (From:).
const mailbox& expeditor() const { return (m_from); } *
mailbox& expeditor() { return (m_from); } * @return expeditor of the message
*/
const mailbox& getExpeditor() const;
const addressList& recipients() const { return (m_to); } /** Set the expeditor of the message (From:).
addressList& recipients() { return (m_to); } *
* @param expeditor expeditor of the message
*/
void setExpeditor(const mailbox& expeditor);
const addressList& copyRecipients() const { return (m_cc); } /** Return the recipients of the message (To:).
addressList& copyRecipients() { return (m_cc); } *
* return recipients of the message
*/
const addressList& getRecipients() const;
const addressList& blindCopyRecipients() const { return (m_bcc); } /** Set the recipients of the message (To:).
addressList& blindCopyRecipients() { return (m_bcc); } *
* @param recipients list of recipients
*/
void setRecipients(const addressList& recipients);
// Subject /** Return the copy recipients of the message (Cc:).
const text& subject() const { return (m_subject); } *
text& subject() { return (m_subject); } * @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); 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); 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; message* construct() const;
protected: private:
mailbox m_from; mailbox m_from;
@ -87,7 +182,7 @@ protected:
text m_subject; text m_subject;
class textPart* m_textPart; textPart* m_textPart;
std::vector <attachment*> m_attach; 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); 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) messageId& messageId::operator=(const string& id)
{ {
parse(id); parse(id);
@ -164,12 +156,12 @@ messageId messageId::generateId()
left << "vmime"; left << "vmime";
left << '.'; left << '.';
left << std::hex << utility::random::time(); left << std::hex << utility::random::getTime();
left << '.'; left << '.';
left << std::hex << utility::random::process(); left << std::hex << utility::random::getProcess();
left << '.'; left << '.';
left << std::hex << utility::random::next(); left << std::hex << utility::random::getNext();
left << std::hex << utility::random::next(); left << std::hex << utility::random::getNext();
return (messageId(left.str(), platformDependant::getHandler()->getHostName())); 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 } // vmime

View File

@ -43,24 +43,55 @@ public:
public: public:
const string& left() const { return (m_left); } /** Return the left part of the message identifier.
string& left() { return (m_left); } *
* @return left part of message identifier
*/
const string& getLeft() const;
const string& right() const { return (m_right); } /** Set the left part of the message identifier.
string& right() { return (m_right); } *
* @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); messageId& operator=(const string& id);
const bool operator==(const messageId& mid) const; 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(); 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_left;
string m_right; 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 "defaultAttachment.hpp"
#include "textPartFactory.hpp" #include "textPartFactory.hpp"
#include "relayField.hpp"
namespace vmime namespace vmime
{ {
@ -60,28 +58,36 @@ messageParser::~messageParser()
void messageParser::parse(const message& msg) void messageParser::parse(const message& msg)
{ {
// Header fields (if field is present, copy its value, else do nothing) // Header fields (if field is present, copy its value, else do nothing)
#define TRY_FIELD(x) try { x; } catch (exceptions::no_such_field) { } #define TRY_FIELD(var, type, name) \
TRY_FIELD(m_from = dynamic_cast<mailboxField&>(msg.header().fields.find(headerField::From)).value()); 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_from, mailboxField, fields::FROM);
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_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 #undef TRY_FIELD
// Date // Date
try try
{ {
vmime::relayField& recv = static_cast<vmime::relayField&>(msg.header().fields.find(headerField::Received)); vmime::relayField& recv = dynamic_cast <vmime::relayField&>
m_date = recv.date(); (*msg.getHeader()->findField(fields::RECEIVED));
m_date = recv.getValue().getDate();
} }
catch (vmime::exceptions::no_such_field&) catch (vmime::exceptions::no_such_field&)
{ {
try try
{ {
vmime::dateField& date = static_cast<vmime::dateField&>(msg.header().fields.find(headerField::Date)); vmime::dateField& date = dynamic_cast <vmime::dateField&>
m_date = date.value(); (*msg.getHeader()->findField(fields::DATE));
m_date = date.getValue();
} }
catch (vmime::exceptions::no_such_field&) catch (vmime::exceptions::no_such_field&)
{ {
@ -100,10 +106,11 @@ void messageParser::parse(const message& msg)
void messageParser::findAttachments(const bodyPart& part) void messageParser::findAttachments(const bodyPart& part)
{ {
// We simply search for parts that are not "Content-disposition: inline". // 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 bodyPart& p = *part.getBody()->getPartAt(i);
const body& bdy = (*p).body(); const header& hdr = *p.getHeader();
const body& bdy = *p.getBody();
// Is this part an attachment? // Is this part an attachment?
bool isAttachment = false; bool isAttachment = false;
@ -112,9 +119,9 @@ void messageParser::findAttachments(const bodyPart& part)
try try
{ {
const contentDispositionField& cdf = dynamic_cast<contentDispositionField&> 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; contentDispField = &cdf;
isAttachment = true; isAttachment = true;
@ -129,9 +136,9 @@ void messageParser::findAttachments(const bodyPart& part)
try try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&> 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) catch (exceptions::no_such_field)
{ {
@ -140,8 +147,11 @@ void messageParser::findAttachments(const bodyPart& part)
mediaTypes::APPLICATION_OCTET_STREAM); mediaTypes::APPLICATION_OCTET_STREAM);
} }
if (type.type() != mediaTypes::TEXT && type.type() != mediaTypes::MULTIPART) if (type.getType() != mediaTypes::TEXT &&
type.getType() != mediaTypes::MULTIPART)
{
isAttachment = true; isAttachment = true;
}
} }
if (isAttachment) if (isAttachment)
@ -152,9 +162,9 @@ void messageParser::findAttachments(const bodyPart& part)
try try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&> 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) catch (exceptions::no_such_field)
{ {
@ -169,9 +179,9 @@ void messageParser::findAttachments(const bodyPart& part)
try try
{ {
const textField& cd = dynamic_cast<textField&> 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) catch (exceptions::no_such_field)
{ {
@ -180,12 +190,12 @@ void messageParser::findAttachments(const bodyPart& part)
// Construct the attachment object // Construct the attachment object
attachment* attach = new defaultAttachment attachment* attach = new defaultAttachment
(bdy.contents(), bdy.encoding(), type, description); (bdy.getContents(), bdy.getEncoding(), type, description);
if (contentDispField != NULL) if (contentDispField != NULL)
{ {
m_attachInfo.insert(std::map <attachment*, contentDispositionField*>:: m_attachInfo.insert(std::map <attachment*, contentDispositionField*>::
value_type(attach, static_cast <contentDispositionField*> value_type(attach, dynamic_cast <contentDispositionField*>
(contentDispField->clone()))); (contentDispField->clone())));
} }
@ -194,8 +204,8 @@ void messageParser::findAttachments(const bodyPart& part)
} }
// Try to find attachments in sub-parts // Try to find attachments in sub-parts
if (bdy.parts.size()) if (bdy.getPartCount())
findAttachments(*p); 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 // Handle the case in which the message is not multipart: if the body part is
// "text/*", take this part. // "text/*", take this part.
if (part.body().parts.count() == 0) if (part.getBody()->getPartCount() == 0)
{ {
mediaType type(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN); mediaType type(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
bool accept = false; bool accept = false;
@ -212,11 +222,11 @@ void messageParser::findTextParts(const bodyPart& msg, const bodyPart& part)
try try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&> 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; accept = true;
} }
} }
@ -251,17 +261,18 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part)
std::vector <const bodyPart*> textParts; std::vector <const bodyPart*> textParts;
for (body::const_iterator p = part.body().parts.begin() ; for (int i = 0 ; i < part.getBody()->getPartCount() ; ++i)
p != part.body().parts.end() ; ++p)
{ {
const bodyPart& p = *part.getBody()->getPartAt(i);
try try
{ {
const contentTypeField& ctf = dynamic_cast<contentTypeField&> 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) catch (exceptions::no_such_field)
@ -273,14 +284,15 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part)
if (textParts.size()) if (textParts.size())
{ {
// Okay. So we have found at least one text part // 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&> const contentTypeField& ctf = dynamic_cast<contentTypeField&>
((*p)->header().fields.find(headerField::ContentType)); (*(*p)->getHeader()->findField(fields::CONTENT_TYPE));
try try
{ {
textPart* textPart = textPartFactory::getInstance()->create(ctf.value()); textPart* textPart = textPartFactory::getInstance()->create(ctf.getValue());
textPart->parse(msg, part, **p); textPart->parse(msg, part, **p);
m_textParts.push_back(textPart); m_textParts.push_back(textPart);
@ -298,10 +310,9 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part)
{ {
bool found = false; bool found = false;
for (body::const_iterator p = part.body().parts.begin() ; for (int i = 0 ; !found && (i < part.getBody()->getPartCount()) ; ++i)
!found && p != part.body().parts.end() ; ++p)
{ {
found = findSubTextParts(msg, *p); found = findSubTextParts(msg, *part.getBody()->getPartAt(i));
} }
return found; 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 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); 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 } // vmime

View File

@ -46,27 +46,88 @@ public:
public: public:
// Expeditor and recipients /** Return the expeditor of the message (From:).
const mailbox& expeditor() const { return (m_from); } *
* @return expeditor of the message
*/
const mailbox& getExpeditor() const;
const addressList& recipients() const { return (m_to); } /** Return the recipients of the message (To:).
const addressList& copyRecipients() const { return (m_cc); } *
const addressList& blindCopyRecipients() const { return (m_bcc); } * return recipients of the message
*/
const addressList& getRecipients() const;
// Subject /** Return the copy recipients of the message (Cc:).
const text& subject() const { return (m_subject); } *
* @return copy recipients of the message
*/
const addressList& getCopyRecipients() const;
// Date /** Return the blind-copy recipients of the message (Bcc:).
const datetime& date() const { return (m_date); } *
* @return blind-copy recipients of the message
*/
const addressList& getBlindCopyRecipients() const;
// Attachments /** Return the subject of the message.
const std::vector <attachment*>& attachments() const { return (m_attach); } *
const contentDispositionField* attachmentInfo(attachment* a) const; * @return subject of the message
*/
const text& getSubject() const;
// Text parts /** Return the date of the message.
const std::vector <textPart*>& textParts() const { return (m_textParts); } *
* @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; mailbox m_from;

View File

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