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