aboutsummaryrefslogtreecommitdiffstats
path: root/src/vmime/htmlTextPart.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vmime/htmlTextPart.cpp')
-rw-r--r--src/vmime/htmlTextPart.cpp364
1 files changed, 208 insertions, 156 deletions
diff --git a/src/vmime/htmlTextPart.cpp b/src/vmime/htmlTextPart.cpp
index bda33cc0..a30023c6 100644
--- a/src/vmime/htmlTextPart.cpp
+++ b/src/vmime/htmlTextPart.cpp
@@ -1,6 +1,6 @@
//
// VMime library (http://www.vmime.org)
-// Copyright (C) 2002-2013 Vincent Richard <[email protected]>
+// Copyright (C) 2002 Vincent Richard <[email protected]>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
@@ -34,47 +34,52 @@
#include "vmime/utility/outputStreamAdapter.hpp"
-namespace vmime
-{
+namespace vmime {
htmlTextPart::htmlTextPart()
: m_plainText(make_shared <emptyContentHandler>()),
- m_text(make_shared <emptyContentHandler>())
-{
+ m_text(make_shared <emptyContentHandler>()) {
+
}
-htmlTextPart::~htmlTextPart()
-{
+htmlTextPart::~htmlTextPart() {
+
}
-const mediaType htmlTextPart::getType() const
-{
+const mediaType htmlTextPart::getType() const {
+
return mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML);
}
-size_t htmlTextPart::getPartCount() const
-{
- return (m_plainText->isEmpty() ? 1 : 2);
+size_t htmlTextPart::getPartCount() const {
+
+ return m_plainText->isEmpty() ? 1 : 2;
}
-void htmlTextPart::generateIn(const shared_ptr <bodyPart>& /* message */, const shared_ptr <bodyPart>& parent) const
-{
+void htmlTextPart::generateIn(
+ const shared_ptr <bodyPart>& /* message */,
+ const shared_ptr <bodyPart>& parent
+) const {
+
// Plain text
- if (!m_plainText->isEmpty())
- {
+ if (!m_plainText->isEmpty()) {
+
// -- Create a new part
shared_ptr <bodyPart> part = make_shared <bodyPart>();
parent->getBody()->appendPart(part);
// -- Set contents
- part->getBody()->setContents(m_plainText,
- mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN), m_charset,
- encoding::decide(m_plainText, m_charset, encoding::USAGE_TEXT));
+ part->getBody()->setContents(
+ m_plainText,
+ mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN),
+ m_charset,
+ encoding::decide(m_plainText, m_charset, encoding::USAGE_TEXT)
+ );
}
// HTML text
@@ -82,27 +87,31 @@ void htmlTextPart::generateIn(const shared_ptr <bodyPart>& /* message */, const
shared_ptr <bodyPart> htmlPart = make_shared <bodyPart>();
// -- Set contents
- htmlPart->getBody()->setContents(m_text,
- mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML), m_charset,
- encoding::decide(m_text, m_charset, encoding::USAGE_TEXT));
+ htmlPart->getBody()->setContents(
+ m_text,
+ mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML),
+ m_charset,
+ encoding::decide(m_text, m_charset, encoding::USAGE_TEXT)
+ );
// Handle the case we have embedded objects
- if (!m_objects.empty())
- {
+ if (!m_objects.empty()) {
+
// Create a "multipart/related" body part
shared_ptr <bodyPart> relPart = make_shared <bodyPart>();
parent->getBody()->appendPart(relPart);
- relPart->getHeader()->ContentType()->
- setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED));
+ relPart->getHeader()->ContentType()->setValue(
+ mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED)
+ );
// Add the HTML part into this part
relPart->getBody()->appendPart(htmlPart);
// Also add objects into this part
for (std::vector <shared_ptr <embeddedObject> >::const_iterator it = m_objects.begin() ;
- it != m_objects.end() ; ++it)
- {
+ it != m_objects.end() ; ++it) {
+
shared_ptr <bodyPart> objPart = make_shared <bodyPart>();
relPart->getBody()->appendPart(objPart);
@@ -112,8 +121,8 @@ void htmlTextPart::generateIn(const shared_ptr <bodyPart>& /* message */, const
(id[0] == 'c' || id[0] == 'C') &&
(id[1] == 'i' || id[1] == 'I') &&
(id[2] == 'd' || id[2] == 'D') &&
- id[3] == ':')
- {
+ id[3] == ':') {
+
id = id.substr(4);
}
@@ -125,38 +134,46 @@ void htmlTextPart::generateIn(const shared_ptr <bodyPart>& /* message */, const
objPart->getBody()->setContents((*it)->getData()->clone());
}
- }
- else
- {
+
+ } else {
+
// Add the HTML part into the parent part
parent->getBody()->appendPart(htmlPart);
}
}
-void htmlTextPart::findEmbeddedParts(const bodyPart& part,
- std::vector <shared_ptr <const bodyPart> >& cidParts, std::vector <shared_ptr <const bodyPart> >& locParts)
-{
- for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i)
- {
+void htmlTextPart::findEmbeddedParts(
+ const bodyPart& part,
+ std::vector <shared_ptr <const bodyPart> >& cidParts,
+ std::vector <shared_ptr <const bodyPart> >& locParts
+) {
+
+ for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) {
+
shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i);
// For a part to be an embedded object, it must have either a
// Content-Id field or a Content-Location field.
- if (p->getHeader()->hasField(fields::CONTENT_ID))
+ if (p->getHeader()->hasField(fields::CONTENT_ID)) {
cidParts.push_back(p);
+ }
- if (p->getHeader()->hasField(fields::CONTENT_LOCATION))
+ if (p->getHeader()->hasField(fields::CONTENT_LOCATION)) {
locParts.push_back(p);
+ }
findEmbeddedParts(*p, cidParts, locParts);
}
}
-void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id,
- const embeddedObject::ReferenceType refType)
-{
+void htmlTextPart::addEmbeddedObject(
+ const bodyPart& part,
+ const string& id,
+ const embeddedObject::ReferenceType refType
+) {
+
// The object may already exists. This can happen if an object is
// identified by both a Content-Id and a Content-Location. In this
// case, there will be two embedded objects with two different IDs
@@ -167,23 +184,33 @@ void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id,
shared_ptr <const headerField> ctf =
part.getHeader()->findField(fields::CONTENT_TYPE);
- if (ctf)
- {
+ if (ctf) {
+
type = *ctf->getValue <mediaType>();
- }
- else
- {
+
+ } else {
+
// No "Content-type" field: assume "application/octet-stream".
}
- m_objects.push_back(make_shared <embeddedObject>
- (vmime::clone(part.getBody()->getContents()),
- part.getBody()->getEncoding(), id, type, refType));
+ m_objects.push_back(
+ make_shared <embeddedObject>(
+ vmime::clone(part.getBody()->getContents()),
+ part.getBody()->getEncoding(),
+ id,
+ type,
+ refType
+ )
+ );
}
-void htmlTextPart::parse(const shared_ptr <const bodyPart>& message, const shared_ptr <const bodyPart>& parent, const shared_ptr <const bodyPart>& textPart)
-{
+void htmlTextPart::parse(
+ const shared_ptr <const bodyPart>& message,
+ const shared_ptr <const bodyPart>& parent,
+ const shared_ptr <const bodyPart>& textPart
+) {
+
// Search for possible embedded objects in the _whole_ message.
std::vector <shared_ptr <const bodyPart> > cidParts;
std::vector <shared_ptr <const bodyPart> > locParts;
@@ -204,39 +231,42 @@ void htmlTextPart::parse(const shared_ptr <const bodyPart>& message, const share
shared_ptr <const contentTypeField> ctf =
textPart->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
- if (ctf && ctf->hasCharset())
+ if (ctf && ctf->hasCharset()) {
m_charset = ctf->getCharset();
- else
+ } else {
m_charset = charset();
+ }
// Extract embedded objects. The algorithm is quite simple: for each previously
// found inline part, we check if its CID/Location is contained in the HTML text.
- for (std::vector <shared_ptr <const bodyPart> >::const_iterator p = cidParts.begin() ; p != cidParts.end() ; ++p)
- {
+ for (std::vector <shared_ptr <const bodyPart> >::const_iterator p = cidParts.begin() ;
+ p != cidParts.end() ; ++p) {
+
const shared_ptr <const headerField> midField =
(*p)->getHeader()->findField(fields::CONTENT_ID);
const messageId mid = *midField->getValue <messageId>();
if (data.find("CID:" + mid.getId()) != string::npos ||
- data.find("cid:" + mid.getId()) != string::npos)
- {
+ data.find("cid:" + mid.getId()) != string::npos) {
+
// This part is referenced in the HTML text.
// Add it to the embedded object list.
addEmbeddedObject(**p, mid.getId(), embeddedObject::REFERENCED_BY_ID);
}
}
- for (std::vector <shared_ptr <const bodyPart> >::const_iterator p = locParts.begin() ; p != locParts.end() ; ++p)
- {
+ for (std::vector <shared_ptr <const bodyPart> >::const_iterator p = locParts.begin() ;
+ p != locParts.end() ; ++p) {
+
const shared_ptr <const headerField> locField =
(*p)->getHeader()->findField(fields::CONTENT_LOCATION);
const text loc = *locField->getValue <text>();
const string locStr = loc.getWholeBuffer();
- if (data.find(locStr) != string::npos)
- {
+ if (data.find(locStr) != string::npos) {
+
// This part is referenced in the HTML text.
// Add it to the embedded object list.
addEmbeddedObject(**p, locStr, embeddedObject::REFERENCED_BY_LOCATION);
@@ -244,65 +274,68 @@ void htmlTextPart::parse(const shared_ptr <const bodyPart>& message, const share
}
// Extract plain text, if any.
- if (!findPlainTextPart(*message, *parent, *textPart))
- {
+ if (!findPlainTextPart(*message, *parent, *textPart)) {
+
m_plainText = make_shared <emptyContentHandler>();
}
}
-bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart)
-{
+bool htmlTextPart::findPlainTextPart(
+ const bodyPart& part,
+ const bodyPart& parent,
+ const bodyPart& textPart
+) {
+
// We search for the nearest "multipart/alternative" part.
const shared_ptr <const headerField> ctf =
part.getHeader()->findField(fields::CONTENT_TYPE);
- if (ctf)
- {
+ if (ctf) {
+
const mediaType type = *ctf->getValue <mediaType>();
if (type.getType() == mediaTypes::MULTIPART &&
- type.getSubType() == mediaTypes::MULTIPART_ALTERNATIVE)
- {
+ type.getSubType() == mediaTypes::MULTIPART_ALTERNATIVE) {
+
shared_ptr <const bodyPart> foundPart;
- for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i)
- {
+ for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) {
+
const shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i);
if (p.get() == &parent || // if "text/html" is in "multipart/related"
- p.get() == &textPart) // if not...
- {
+ p.get() == &textPart) { // if not...
+
foundPart = p;
}
}
- if (foundPart)
- {
+ if (foundPart) {
+
bool found = false;
// Now, search for the alternative plain text part
- for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i)
- {
+ for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i) {
+
const shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i);
const shared_ptr <const headerField> ctf =
p->getHeader()->findField(fields::CONTENT_TYPE);
- if (ctf)
- {
+ if (ctf) {
const mediaType type = *ctf->getValue <mediaType>();
if (type.getType() == mediaTypes::TEXT &&
- type.getSubType() == mediaTypes::TEXT_PLAIN)
- {
+ type.getSubType() == mediaTypes::TEXT_PLAIN) {
+
m_plainText = p->getBody()->getContents()->clone();
found = true;
}
- }
- else
- {
+
+ } else {
+
// No "Content-type" field.
}
}
@@ -313,16 +346,16 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
return found;
}
}
- }
- else
- {
+
+ } else {
+
// No "Content-type" field.
}
bool found = false;
- for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i)
- {
+ for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i) {
+
found = findPlainTextPart(*part.getBody()->getPartAt(i), parent, textPart);
}
@@ -330,50 +363,50 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
}
-const charset& htmlTextPart::getCharset() const
-{
+const charset& htmlTextPart::getCharset() const {
+
return m_charset;
}
-void htmlTextPart::setCharset(const charset& ch)
-{
+void htmlTextPart::setCharset(const charset& ch) {
+
m_charset = ch;
}
-shared_ptr <const contentHandler> htmlTextPart::getPlainText() const
-{
+shared_ptr <const contentHandler> htmlTextPart::getPlainText() const {
+
return m_plainText;
}
-void htmlTextPart::setPlainText(const shared_ptr <contentHandler>& plainText)
-{
+void htmlTextPart::setPlainText(const shared_ptr <contentHandler>& plainText) {
+
m_plainText = plainText->clone();
}
-const shared_ptr <const contentHandler> htmlTextPart::getText() const
-{
+const shared_ptr <const contentHandler> htmlTextPart::getText() const {
+
return m_text;
}
-void htmlTextPart::setText(const shared_ptr <contentHandler>& text)
-{
+void htmlTextPart::setText(const shared_ptr <contentHandler>& text) {
+
m_text = text->clone();
}
-size_t htmlTextPart::getObjectCount() const
-{
+size_t htmlTextPart::getObjectCount() const {
+
return m_objects.size();
}
-shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::getObjectAt(const size_t pos) const
-{
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::getObjectAt(const size_t pos) const {
+
return m_objects[pos];
}
@@ -381,36 +414,42 @@ shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::getObjectAt(const
shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::findObject(const string& id) const
{
for (std::vector <shared_ptr <embeddedObject> >::const_iterator o = m_objects.begin() ;
- o != m_objects.end() ; ++o)
- {
- if ((*o)->matchesId(id))
+ o != m_objects.end() ; ++o) {
+
+ if ((*o)->matchesId(id)) {
return *o;
+ }
}
return null;
}
-bool htmlTextPart::hasObject(const string& id) const
-{
+bool htmlTextPart::hasObject(const string& id) const {
+
for (std::vector <shared_ptr <embeddedObject> >::const_iterator o = m_objects.begin() ;
- o != m_objects.end() ; ++o)
- {
- if ((*o)->matchesId(id))
+ o != m_objects.end() ; ++o) {
+
+ if ((*o)->matchesId(id)) {
return true;
+ }
}
return false;
}
-shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject
- (const shared_ptr <contentHandler>& data, const vmime::encoding& enc, const mediaType& type)
-{
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject(
+ const shared_ptr <contentHandler>& data,
+ const vmime::encoding& enc,
+ const mediaType& type
+) {
+
const messageId mid(messageId::generateId());
- shared_ptr <embeddedObject> obj = make_shared <embeddedObject>
- (data, enc, mid.getId(), type, embeddedObject::REFERENCED_BY_ID);
+ shared_ptr <embeddedObject> obj = make_shared <embeddedObject>(
+ data, enc, mid.getId(), type, embeddedObject::REFERENCED_BY_ID
+ );
m_objects.push_back(obj);
@@ -418,16 +457,20 @@ shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject
}
-shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject
- (const shared_ptr <contentHandler>& data, const mediaType& type)
-{
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject(
+ const shared_ptr <contentHandler>& data,
+ const mediaType& type
+) {
+
return addObject(data, encoding::decide(data), type);
}
-shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject
- (const string& data, const mediaType& type)
-{
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject(
+ const string& data,
+ const mediaType& type
+) {
+
shared_ptr <stringContentHandler> cts = make_shared <stringContentHandler>(data);
return addObject(cts, encoding::decide(cts), type);
}
@@ -438,76 +481,85 @@ shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject
// htmlTextPart::embeddedObject
//
-htmlTextPart::embeddedObject::embeddedObject
- (const shared_ptr <contentHandler>& data, const encoding& enc,
- const string& id, const mediaType& type, const ReferenceType refType)
+htmlTextPart::embeddedObject::embeddedObject(
+ const shared_ptr <contentHandler>& data,
+ const encoding& enc,
+ const string& id,
+ const mediaType& type,
+ const ReferenceType refType
+)
: m_data(vmime::clone(data)),
- m_encoding(enc), m_id(id), m_type(type), m_refType(refType)
-{
+ m_encoding(enc),
+ m_id(id),
+ m_type(type),
+ m_refType(refType) {
+
}
-shared_ptr <const contentHandler> htmlTextPart::embeddedObject::getData() const
-{
+shared_ptr <const contentHandler> htmlTextPart::embeddedObject::getData() const {
+
return m_data;
}
-const vmime::encoding htmlTextPart::embeddedObject::getEncoding() const
-{
+const vmime::encoding htmlTextPart::embeddedObject::getEncoding() const {
+
return m_encoding;
}
-const string htmlTextPart::embeddedObject::getId() const
-{
+const string htmlTextPart::embeddedObject::getId() const {
+
return m_id;
}
-const string htmlTextPart::embeddedObject::getReferenceId() const
-{
- if (m_refType == REFERENCED_BY_ID)
+const string htmlTextPart::embeddedObject::getReferenceId() const {
+
+ if (m_refType == REFERENCED_BY_ID) {
return string("cid:") + m_id;
- else
+ } else {
return m_id;
+ }
}
-const mediaType htmlTextPart::embeddedObject::getType() const
-{
+const mediaType htmlTextPart::embeddedObject::getType() const {
+
return m_type;
}
-htmlTextPart::embeddedObject::ReferenceType htmlTextPart::embeddedObject::getReferenceType() const
-{
+htmlTextPart::embeddedObject::ReferenceType htmlTextPart::embeddedObject::getReferenceType() const {
+
return m_refType;
}
-bool htmlTextPart::embeddedObject::matchesId(const string& id) const
-{
- if (m_refType == REFERENCED_BY_ID)
+bool htmlTextPart::embeddedObject::matchesId(const string& id) const {
+
+ if (m_refType == REFERENCED_BY_ID) {
return m_id == cleanId(id);
- else
+ } else {
return m_id == id;
+ }
}
// static
-const string htmlTextPart::embeddedObject::cleanId(const string& id)
-{
+const string htmlTextPart::embeddedObject::cleanId(const string& id) {
+
if (id.length() >= 4 &&
(id[0] == 'c' || id[0] == 'C') &&
(id[1] == 'i' || id[1] == 'I') &&
(id[2] == 'd' || id[2] == 'D') &&
- id[3] == ':')
- {
+ id[3] == ':') {
+
return id.substr(4);
- }
- else
- {
+
+ } else {
+
return id;
}
}