diff options
author | Vincent Richard <[email protected]> | 2013-07-11 16:06:26 +0000 |
---|---|---|
committer | Vincent Richard <[email protected]> | 2013-07-11 16:06:26 +0000 |
commit | b886cd48649c09561417b378b9c1f932d6e72dd8 (patch) | |
tree | 8417a5de917a1b82a5ce7b67bb6e5abbb4bb8207 | |
parent | Update example to test STATUS command. (diff) | |
download | vmime-b886cd48649c09561417b378b9c1f932d6e72dd8.tar.gz vmime-b886cd48649c09561417b378b9c1f932d6e72dd8.zip |
Refactored the way embedded objects are referenced in MHTML.
-rw-r--r-- | examples/example3.cpp | 7 | ||||
-rw-r--r-- | src/htmlTextPart.cpp | 115 | ||||
-rw-r--r-- | tests/parser/htmlTextPartTest.cpp | 3 | ||||
-rw-r--r-- | vmime/htmlTextPart.hpp | 71 |
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 <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); }; |