aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2013-07-11 16:06:26 +0000
committerVincent Richard <[email protected]>2013-07-11 16:06:26 +0000
commitb886cd48649c09561417b378b9c1f932d6e72dd8 (patch)
tree8417a5de917a1b82a5ce7b67bb6e5abbb4bb8207
parentUpdate example to test STATUS command. (diff)
downloadvmime-b886cd48649c09561417b378b9c1f932d6e72dd8.tar.gz
vmime-b886cd48649c09561417b378b9c1f932d6e72dd8.zip
Refactored the way embedded objects are referenced in MHTML.
-rw-r--r--examples/example3.cpp7
-rw-r--r--src/htmlTextPart.cpp115
-rw-r--r--tests/parser/htmlTextPartTest.cpp3
-rw-r--r--vmime/htmlTextPart.hpp71
4 files changed, 133 insertions, 63 deletions
diff --git a/examples/example3.cpp b/examples/example3.cpp
index 038f3ba6..31e26534 100644
--- a/examples/example3.cpp
+++ b/examples/example3.cpp
@@ -86,12 +86,13 @@ int main()
vmime::create <vmime::streamContentHandler>
(fileReader->getInputStream(), imageFile->getLength());
- const vmime::string cid = textPart.addObject(imageCts,
- vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
+ vmime::ref <const vmime::htmlTextPart::embeddedObject> obj = textPart.addObject
+ (imageCts, vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
// -- message text
textPart.setText(vmime::create <vmime::stringContentHandler>
- (vmime::string("This is the <b>HTML text</b>.<br/><img src=\"") + cid + vmime::string("\"/>")));
+ (vmime::string("This is the <b>HTML text</b>.<br/>"
+ "<img src=\"") + obj->getReferenceId() + vmime::string("\"/>")));
textPart.setPlainText(vmime::create <vmime::stringContentHandler>
("This is the plain text (without HTML formatting)."));
diff --git a/src/htmlTextPart.cpp b/src/htmlTextPart.cpp
index f0b07d9d..ebb6587c 100644
--- a/src/htmlTextPart.cpp
+++ b/src/htmlTextPart.cpp
@@ -162,7 +162,8 @@ void htmlTextPart::findEmbeddedParts(const bodyPart& part,
}
-void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id)
+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
@@ -183,7 +184,7 @@ void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id)
m_objects.push_back(vmime::create <embeddedObject>
(part.getBody()->getContents()->clone().dynamicCast <contentHandler>(),
- part.getBody()->getEncoding(), id, type));
+ part.getBody()->getEncoding(), id, type, refType));
}
@@ -235,7 +236,7 @@ void htmlTextPart::parse(ref <const bodyPart> message, ref <const bodyPart> pare
{
// This part is referenced in the HTML text.
// Add it to the embedded object list.
- addEmbeddedObject(**p, mid.getId());
+ addEmbeddedObject(**p, mid.getId(), embeddedObject::REFERENCED_BY_ID);
}
}
@@ -251,7 +252,7 @@ void htmlTextPart::parse(ref <const bodyPart> message, ref <const bodyPart> pare
{
// This part is referenced in the HTML text.
// Add it to the embedded object list.
- addEmbeddedObject(**p, locStr);
+ addEmbeddedObject(**p, locStr, embeddedObject::REFERENCED_BY_LOCATION);
}
}
@@ -353,7 +354,7 @@ void htmlTextPart::setCharset(const charset& ch)
}
-const ref <const contentHandler> htmlTextPart::getPlainText() const
+ref <const contentHandler> htmlTextPart::getPlainText() const
{
return m_plainText;
}
@@ -383,20 +384,18 @@ size_t htmlTextPart::getObjectCount() const
}
-const ref <const htmlTextPart::embeddedObject> htmlTextPart::getObjectAt(const size_t pos) const
+ref <const htmlTextPart::embeddedObject> htmlTextPart::getObjectAt(const size_t pos) const
{
return m_objects[pos];
}
-const ref <const htmlTextPart::embeddedObject> htmlTextPart::findObject(const string& id_) const
+ref <const htmlTextPart::embeddedObject> htmlTextPart::findObject(const string& id) const
{
- const string id = cleanId(id_);
-
for (std::vector <ref <embeddedObject> >::const_iterator o = m_objects.begin() ;
o != m_objects.end() ; ++o)
{
- if ((*o)->getId() == id)
+ if ((*o)->matchesId(id))
return *o;
}
@@ -404,14 +403,12 @@ const ref <const htmlTextPart::embeddedObject> htmlTextPart::findObject(const st
}
-bool htmlTextPart::hasObject(const string& id_) const
+bool htmlTextPart::hasObject(const string& id) const
{
- const string id = cleanId(id_);
-
for (std::vector <ref <embeddedObject> >::const_iterator o = m_objects.begin() ;
o != m_objects.end() ; ++o)
{
- if ((*o)->getId() == id)
+ if ((*o)->matchesId(id))
return true;
}
@@ -419,49 +416,35 @@ bool htmlTextPart::hasObject(const string& id_) const
}
-const string htmlTextPart::addObject(ref <contentHandler> data,
- const vmime::encoding& enc, const mediaType& type)
+ref <const htmlTextPart::embeddedObject> htmlTextPart::addObject
+ (ref <contentHandler> data, const vmime::encoding& enc, const mediaType& type)
{
const messageId mid(messageId::generateId());
- const string id = mid.getId();
- m_objects.push_back(vmime::create <embeddedObject>(data, enc, id, type));
+ ref <embeddedObject> obj = vmime::create <embeddedObject>
+ (data, enc, mid.getId(), type, embeddedObject::REFERENCED_BY_ID);
- return "CID:" + id;
+ m_objects.push_back(obj);
+
+ return obj;
}
-const string htmlTextPart::addObject(ref <contentHandler> data, const mediaType& type)
+ref <const htmlTextPart::embeddedObject> htmlTextPart::addObject
+ (ref <contentHandler> data, const mediaType& type)
{
return addObject(data, encoding::decide(data), type);
}
-const string htmlTextPart::addObject(const string& data, const mediaType& type)
+ref <const htmlTextPart::embeddedObject> htmlTextPart::addObject
+ (const string& data, const mediaType& type)
{
ref <stringContentHandler> cts = vmime::create <stringContentHandler>(data);
return addObject(cts, encoding::decide(cts), type);
}
-// static
-const string htmlTextPart::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] == ':')
- {
- return id.substr(4);
- }
- else
- {
- return id;
- }
-}
-
-
//
// htmlTextPart::embeddedObject
@@ -469,35 +452,77 @@ const string htmlTextPart::cleanId(const string& id)
htmlTextPart::embeddedObject::embeddedObject
(ref <contentHandler> data, const encoding& enc,
- const string& id, const mediaType& type)
+ const string& id, const mediaType& type, const ReferenceType refType)
: m_data(data->clone().dynamicCast <contentHandler>()),
- m_encoding(enc), m_id(id), m_type(type)
+ m_encoding(enc), m_id(id), m_type(type), m_refType(refType)
{
}
-const ref <const contentHandler> htmlTextPart::embeddedObject::getData() const
+ref <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 mediaType& htmlTextPart::embeddedObject::getType() const
+const string htmlTextPart::embeddedObject::getReferenceId() const
+{
+ if (m_refType == REFERENCED_BY_ID)
+ return string("CID:") + m_id;
+ else
+ return m_id;
+}
+
+
+const mediaType htmlTextPart::embeddedObject::getType() const
{
return m_type;
}
+htmlTextPart::embeddedObject::ReferenceType htmlTextPart::embeddedObject::getReferenceType() const
+{
+ return m_refType;
+}
+
+
+bool htmlTextPart::embeddedObject::matchesId(const string& id) const
+{
+ if (m_refType == REFERENCED_BY_ID)
+ return m_id == cleanId(id);
+ else
+ return m_id == id;
+}
+
+
+// static
+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] == ':')
+ {
+ return id.substr(4);
+ }
+ else
+ {
+ return id;
+ }
+}
+
+
} // vmime
diff --git a/tests/parser/htmlTextPartTest.cpp b/tests/parser/htmlTextPartTest.cpp
index 732fcd8c..0eb7bbaf 100644
--- a/tests/parser/htmlTextPartTest.cpp
+++ b/tests/parser/htmlTextPartTest.cpp
@@ -157,12 +157,14 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest)
obj = htmlPart.findObject("image1@test");
+ VASSERT_EQ("ref-type1", vmime::htmlTextPart::embeddedObject::REFERENCED_BY_ID, obj->getReferenceType());
VASSERT_EQ("id-obj1", "image1@test", obj->getId());
VASSERT_EQ("data-obj1", "Image1", extractContent(obj->getData()));
VASSERT_EQ("type-obj1", "image/png", obj->getType().generate());
obj = htmlPart.findObject("image2@test");
+ VASSERT_EQ("ref-type2", vmime::htmlTextPart::embeddedObject::REFERENCED_BY_ID, obj->getReferenceType());
VASSERT_EQ("id-obj2", "image2@test", obj->getId());
VASSERT_EQ("data-obj2", "Image2", extractContent(obj->getData()));
VASSERT_EQ("type-obj2", "image/jpeg", obj->getType().generate());
@@ -223,6 +225,7 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest)
obj = htmlPart.findObject("http://www.vmime.org/test/image1.png");
+ VASSERT_EQ("ref-type", vmime::htmlTextPart::embeddedObject::REFERENCED_BY_LOCATION, obj->getReferenceType());
VASSERT_EQ("id-obj", "http://www.vmime.org/test/image1.png", obj->getId());
VASSERT_EQ("data-obj", "Image1", extractContent(obj->getData()));
VASSERT_EQ("type-obj", "image/png", obj->getType().generate());
diff --git a/vmime/htmlTextPart.hpp b/vmime/htmlTextPart.hpp
index 170c0546..77060565 100644
--- a/vmime/htmlTextPart.hpp
+++ b/vmime/htmlTextPart.hpp
@@ -51,7 +51,7 @@ public:
const charset& getCharset() const;
void setCharset(const charset& ch);
- const ref <const contentHandler> getPlainText() const;
+ ref <const contentHandler> getPlainText() const;
void setPlainText(ref <contentHandler> plainText);
const ref <const contentHandler> getText() const;
@@ -63,41 +63,84 @@ public:
{
public:
+ /** The ways embedded objects can be referenced. */
+ enum ReferenceType
+ {
+ REFERENCED_BY_ID, /**< Referenced by Content-Id. */
+ REFERENCED_BY_LOCATION /**< Referenced by Content-Location. */
+ };
+
+ /** Constructs an embedded object.
+ *
+ * @param data content of the object
+ * @param enc encoding of the data
+ * @param id object identifier
+ * @param type object content type
+ * @param refType reference type
+ * @return a reference to a new embedded object
+ */
embeddedObject(ref <contentHandler> data, const encoding& enc,
- const string& id, const mediaType& type);
+ const string& id, const mediaType& type,
+ const ReferenceType refType);
/** Return data stored in this embedded object.
*
* @return stored data
*/
- const ref <const contentHandler> getData() const;
+ ref <const contentHandler> getData() const;
/** Return the encoding used for data in this
* embedded object.
*
* @return data encoding
*/
- const vmime::encoding& getEncoding() const;
+ const vmime::encoding getEncoding() const;
- /** Return the identifier of this embedded object.
+ /** Returns the identifier of this embedded object (either a
+ * unique ID or a location).
*
* @return object identifier
*/
- const string& getId() const;
+ const string getId() const;
+
+ /** Return the identifier used to reference this embedded object
+ * in a text document (for example, you can use the result as
+ * the "src" attribute of an &lt;img> tag).
+ *
+ * @return object reference identifier
+ */
+ const string getReferenceId() const;
/** Return the content type of data stored in
* this embedded object.
*
* @return data type
*/
- const mediaType& getType() const;
+ const mediaType getType() const;
+
+ /** Returns the way this object is referenced.
+ *
+ * @return reference type (see ReferenceType enum)
+ */
+ ReferenceType getReferenceType() const;
+
+ /** Returns whether this object matches the specified identifier.
+ *
+ * @param id identifier to test
+ * @return true if the specified identifier references this
+ * object, or false otherwise
+ */
+ bool matchesId(const string& id) const;
private:
+ static const string cleanId(const string& id);
+
ref <contentHandler> m_data;
encoding m_encoding;
string m_id;
mediaType m_type;
+ ReferenceType m_refType;
};
@@ -115,7 +158,7 @@ public:
* @param id object identifier
* @return embedded object with the specified identifier
*/
- const ref <const embeddedObject> findObject(const string& id) const;
+ ref <const embeddedObject> findObject(const string& id) const;
/** Return the number of embedded objects.
*
@@ -128,7 +171,7 @@ public:
* @param pos position of the embedded object
* @return embedded object at position 'pos'
*/
- const ref <const embeddedObject> getObjectAt(const size_t pos) const;
+ ref <const embeddedObject> getObjectAt(const size_t pos) const;
/** Embed an object and returns a string which identifies it.
* The returned identifier is suitable for use in the 'src' attribute
@@ -142,7 +185,7 @@ public:
* @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);
+ ref <const embeddedObject> addObject(const string& data, const mediaType& type);
/** Embed an object and returns a string which identifies it.
* The returned identifier is suitable for use in the 'src' attribute
@@ -153,7 +196,7 @@ public:
* @return an unique object identifier used to identify the new
* object among all other embedded objects
*/
- const string addObject(ref <contentHandler> data, const mediaType& type);
+ ref <const embeddedObject> addObject(ref <contentHandler> data, const mediaType& type);
/** Embed an object and returns a string which identifies it.
* The returned identifier is suitable for use in the 'src' attribute
@@ -165,7 +208,7 @@ public:
* @return an unique object identifier used to identify the new
* object among all other embedded objects
*/
- const string addObject(ref <contentHandler> data, const encoding& enc, const mediaType& type);
+ ref <const embeddedObject> addObject(ref <contentHandler> data, const encoding& enc, const mediaType& type);
size_t getPartCount() const;
@@ -182,11 +225,9 @@ private:
std::vector <ref <embeddedObject> > m_objects;
void findEmbeddedParts(const bodyPart& part, std::vector <ref <const bodyPart> >& cidParts, std::vector <ref <const bodyPart> >& locParts);
- void addEmbeddedObject(const bodyPart& part, const string& id);
+ void addEmbeddedObject(const bodyPart& part, const string& id, const embeddedObject::ReferenceType refType);
bool findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart);
-
- static const string cleanId(const string& id);
};