diff options
Diffstat (limited to 'src')
35 files changed, 701 insertions, 840 deletions
diff --git a/src/addressList.cpp b/src/addressList.cpp index 09e36cd6..db3eabf7 100644 --- a/src/addressList.cpp +++ b/src/addressList.cpp @@ -37,7 +37,7 @@ addressList::addressList() addressList::addressList(const addressList& addrList) - : component() + : headerFieldValue() { copyFrom(addrList); } diff --git a/src/attachmentHelper.cpp b/src/attachmentHelper.cpp index 82e19f3f..9c080472 100644 --- a/src/attachmentHelper.cpp +++ b/src/attachmentHelper.cpp @@ -24,6 +24,7 @@ #include "vmime/attachmentHelper.hpp" #include "vmime/bodyPartAttachment.hpp" +#include "vmime/disposition.hpp" namespace vmime @@ -38,10 +39,13 @@ const bool attachmentHelper::isBodyPartAnAttachment(ref <const bodyPart> part) const contentDispositionField& cdf = dynamic_cast<contentDispositionField&> (*part->getHeader()->findField(fields::CONTENT_DISPOSITION)); - if (cdf.getValue().getName() != contentDispositionTypes::INLINE) + const contentDisposition disp = *cdf.getValue() + .dynamicCast <const contentDisposition>(); + + if (disp.getName() != contentDispositionTypes::INLINE) return true; } - catch (exceptions::no_such_field) + catch (exceptions::no_such_field&) { // No "Content-disposition" field: assume "attachment" if // type is not "text/..." or "multipart/...". @@ -52,9 +56,9 @@ const bool attachmentHelper::isBodyPartAnAttachment(ref <const bodyPart> part) const contentTypeField& ctf = dynamic_cast<contentTypeField&> (*part->getHeader()->findField(fields::CONTENT_TYPE)); - type = ctf.getValue(); + type = *ctf.getValue().dynamicCast <const mediaType>(); } - catch (exceptions::no_such_field) + catch (exceptions::no_such_field&) { // No "Content-type" field: assume "application/octet-stream". type = mediaType(mediaTypes::APPLICATION, diff --git a/src/base.cpp b/src/base.cpp index 70651cbe..8170a9b8 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -39,7 +39,6 @@ // For initializing #include "vmime/encoderFactory.hpp" #include "vmime/headerFieldFactory.hpp" -#include "vmime/parameterFactory.hpp" #include "vmime/textPartFactory.hpp" #include "vmime/options.hpp" @@ -143,7 +142,6 @@ public: encoderFactory::getInstance(); headerFieldFactory::getInstance(); - parameterFactory::getInstance(); textPartFactory::getInstance(); #if VMIME_HAVE_MESSAGING_FEATURES diff --git a/src/body.cpp b/src/body.cpp index e2fcf0ad..cee72d0a 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -27,6 +27,7 @@ #include "vmime/options.hpp" #include "vmime/contentTypeField.hpp" +#include "vmime/text.hpp" #include "vmime/utility/random.hpp" @@ -65,7 +66,9 @@ void body::parse(const string& buffer, const string::size_type position, const ref <const contentTypeField> ctf = m_header->findField(fields::CONTENT_TYPE).dynamicCast <contentTypeField>(); - if (ctf->getValue().getType() == mediaTypes::MULTIPART) + const mediaType type = *ctf->getValue().dynamicCast <const mediaType>(); + + if (type.getType() == mediaTypes::MULTIPART) { isMultipart = true; @@ -388,7 +391,7 @@ const mediaType body::getContentType() const ref <const contentTypeField> ctf = m_header->findField(fields::CONTENT_TYPE).dynamicCast <const contentTypeField>(); - return (ctf->getValue()); + return (*ctf->getValue().dynamicCast <const mediaType>()); } catch (exceptions::no_such_field&) { @@ -424,10 +427,10 @@ const encoding body::getEncoding() const { try { - const ref <const contentEncodingField> cef = - m_header->findField(fields::CONTENT_TRANSFER_ENCODING).dynamicCast <contentEncodingField>(); + const ref <const headerField> cef = + m_header->findField(fields::CONTENT_TRANSFER_ENCODING); - return (cef->getValue()); + return (*cef->getValue().dynamicCast <const encoding>()); } catch (exceptions::no_such_field&) { @@ -550,7 +553,7 @@ void body::initNewPart(ref <bodyPart> part) ctf->setBoundary(generateRandomBoundaryString()); } - if (ctf->getValue().getType() != mediaTypes::MULTIPART) + if (ctf->getValue().dynamicCast <const mediaType>()->getType() != mediaTypes::MULTIPART) { // Warning: multi-part body but the Content-Type is // not specified as "multipart/..." diff --git a/src/bodyPartAttachment.cpp b/src/bodyPartAttachment.cpp index adf605d3..c40b84b2 100644 --- a/src/bodyPartAttachment.cpp +++ b/src/bodyPartAttachment.cpp @@ -40,7 +40,7 @@ const mediaType bodyPartAttachment::getType() const try { - type = getContentType()->getValue(); + type = *getContentType()->getValue().dynamicCast <const mediaType>(); } catch (exceptions::no_such_field&) { @@ -76,8 +76,7 @@ const word bodyPartAttachment::getName() const { try { - ref <defaultParameter> prm = getContentType()-> - findParameter("name").dynamicCast <defaultParameter>(); + ref <parameter> prm = getContentType()->findParameter("name"); if (prm != NULL) name = prm->getValue(); @@ -102,10 +101,10 @@ const text bodyPartAttachment::getDescription() const try { - const textField& cd = dynamic_cast <textField&> - (*getHeader()->findField(fields::CONTENT_DESCRIPTION)); + ref <const headerField> cd = + getHeader()->findField(fields::CONTENT_DESCRIPTION); - description = cd.getValue(); + description = *cd->getValue().dynamicCast <const text>(); } catch (exceptions::no_such_field&) { diff --git a/src/contentDisposition.cpp b/src/contentDisposition.cpp index b906b2da..7f17dd37 100644 --- a/src/contentDisposition.cpp +++ b/src/contentDisposition.cpp @@ -42,7 +42,7 @@ contentDisposition::contentDisposition(const string& name) contentDisposition::contentDisposition(const contentDisposition& type) - : component(), m_name(type.m_name) + : headerFieldValue(), m_name(type.m_name) { } diff --git a/src/contentDispositionField.cpp b/src/contentDispositionField.cpp index cf033ff0..f364785b 100644 --- a/src/contentDispositionField.cpp +++ b/src/contentDispositionField.cpp @@ -24,8 +24,6 @@ #include "vmime/contentDispositionField.hpp" #include "vmime/exception.hpp" -#include "vmime/standardParams.hpp" - namespace vmime { @@ -37,68 +35,68 @@ contentDispositionField::contentDispositionField() contentDispositionField::contentDispositionField(contentDispositionField&) - : headerField(), parameterizedHeaderField(), genericField <contentDisposition>() + : headerField(), parameterizedHeaderField() { } -const datetime& contentDispositionField::getCreationDate() const +const datetime contentDispositionField::getCreationDate() const { - return (dynamic_cast <const dateParameter&>(*findParameter("creation-date")).getValue()); + return findParameter("creation-date")->getValueAs <datetime>(); } void contentDispositionField::setCreationDate(const datetime& creationDate) { - dynamic_cast <dateParameter&>(*getParameter("creation-date")).setValue(creationDate); + getParameter("creation-date")->setValue(creationDate); } -const datetime& contentDispositionField::getModificationDate() const +const datetime contentDispositionField::getModificationDate() const { - return (dynamic_cast <const dateParameter&>(*findParameter("modification-date")).getValue()); + return findParameter("modification-date")->getValueAs <datetime>(); } void contentDispositionField::setModificationDate(const datetime& modificationDate) { - dynamic_cast <dateParameter&>(*getParameter("modification-date")).setValue(modificationDate); + getParameter("modification-date")->setValue(modificationDate); } -const datetime& contentDispositionField::getReadDate() const +const datetime contentDispositionField::getReadDate() const { - return (dynamic_cast <const dateParameter&>(*findParameter("read-date")).getValue()); + return findParameter("read-date")->getValueAs <datetime>(); } void contentDispositionField::setReadDate(const datetime& readDate) { - dynamic_cast <dateParameter&>(*getParameter("read-date")).setValue(readDate); + getParameter("read-date")->setValue(readDate); } const word contentDispositionField::getFilename() const { - return (dynamic_cast <const defaultParameter&>(*findParameter("filename")).getValue()); + return findParameter("filename")->getValue(); } void contentDispositionField::setFilename(const word& filename) { - dynamic_cast <defaultParameter&>(*getParameter("filename")).setValue(filename); + getParameter("filename")->setValue(filename); } const string contentDispositionField::getSize() const { - return (dynamic_cast <const defaultParameter&>(*findParameter("size")).getValue().getBuffer()); + return findParameter("size")->getValue().getBuffer(); } void contentDispositionField::setSize(const string& size) { - dynamic_cast <defaultParameter&>(*getParameter("size")).setValue(word(size)); + getParameter("size")->setValue(word(size, vmime::charsets::US_ASCII)); } diff --git a/src/contentTypeField.cpp b/src/contentTypeField.cpp index 1b46ffc3..852f9961 100644 --- a/src/contentTypeField.cpp +++ b/src/contentTypeField.cpp @@ -24,8 +24,6 @@ #include "vmime/contentTypeField.hpp" #include "vmime/exception.hpp" -#include "vmime/standardParams.hpp" - namespace vmime { @@ -37,45 +35,46 @@ contentTypeField::contentTypeField() contentTypeField::contentTypeField(contentTypeField&) - : headerField(), parameterizedHeaderField(), genericField <mediaType>() + : headerField(), parameterizedHeaderField() { } const string contentTypeField::getBoundary() const { - return (dynamic_cast <const defaultParameter&>(*findParameter("boundary")).getValue().getBuffer()); + return findParameter("boundary")->getValue().getBuffer(); } void contentTypeField::setBoundary(const string& boundary) { - dynamic_cast <defaultParameter&>(*getParameter("boundary")).setValue(word(boundary)); + getParameter("boundary")->setValue(word(boundary, vmime::charsets::US_ASCII)); } -const charset& contentTypeField::getCharset() const +const charset contentTypeField::getCharset() const { - return (dynamic_cast <const charsetParameter&>(*findParameter("charset")).getValue()); + return findParameter("charset")->getValueAs <charset>(); } void contentTypeField::setCharset(const charset& ch) { - dynamic_cast <charsetParameter&>(*getParameter("charset")).setValue(ch); + getParameter("charset")->setValue(ch); } const string contentTypeField::getReportType() const { - return (dynamic_cast <const defaultParameter&>(*findParameter("report-type")).getValue().getBuffer()); + return findParameter("report-type")->getValue().getBuffer(); } void contentTypeField::setReportType(const string& reportType) { - dynamic_cast <defaultParameter&>(*getParameter("report-type")).setValue(word(reportType)); + getParameter("report-type")->setValue(word(reportType, vmime::charsets::US_ASCII)); } } // vmime + diff --git a/src/dateTime.cpp b/src/dateTime.cpp index 36aafe2a..ea965805 100644 --- a/src/dateTime.cpp +++ b/src/dateTime.cpp @@ -640,7 +640,7 @@ datetime::datetime(const int year, const int month, const int day, datetime::datetime(const datetime& d) - : component(), m_year(d.m_year), m_month(d.m_month), m_day(d.m_day), + : headerFieldValue(), m_year(d.m_year), m_month(d.m_month), m_day(d.m_day), m_hour(d.m_hour), m_minute(d.m_minute), m_second(d.m_second), m_zone(d.m_zone) { } diff --git a/src/defaultAttachment.cpp b/src/defaultAttachment.cpp index 909dca10..463bc89c 100644 --- a/src/defaultAttachment.cpp +++ b/src/defaultAttachment.cpp @@ -22,6 +22,8 @@ // #include "vmime/defaultAttachment.hpp" + +#include "vmime/contentDisposition.hpp" #include "vmime/encoding.hpp" diff --git a/src/defaultParameter.cpp b/src/defaultParameter.cpp deleted file mode 100644 index 2cb8c156..00000000 --- a/src/defaultParameter.cpp +++ /dev/null @@ -1,437 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2005 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 -// 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., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/defaultParameter.hpp" -#include "vmime/parserHelpers.hpp" - - -namespace vmime -{ - - -defaultParameter::defaultParameter() - : m_value(vmime::create <word>()) -{ -} - - -defaultParameter& defaultParameter::operator=(const defaultParameter& other) -{ - copyFrom(other); - return (*this); -} - - -const ref <const component> defaultParameter::getValueImp() const -{ - return (m_value); -} - - -const ref <component> defaultParameter::getValueImp() -{ - return (m_value); -} - - -const word& defaultParameter::getValue() const -{ - return (*m_value); -} - - -word& defaultParameter::getValue() -{ - return (*m_value); -} - - -void defaultParameter::setValue(const word& value) -{ - *m_value = value; -} - - -void defaultParameter::setValue(const component& value) -{ - const word& v = dynamic_cast <const word&>(value); - *m_value = v; -} - - -void defaultParameter::parse(const string& buffer, const string::size_type position, - const string::size_type end, string::size_type* newPosition) -{ - m_value = vmime::create <word> - (string(buffer.begin() + position, buffer.begin() + end), - charset(charsets::US_ASCII)); - - if (newPosition) - *newPosition = end; -} - - -void defaultParameter::parse(const std::vector <valueChunk>& chunks) -{ - bool foundCharsetChunk = false; - - charset ch(charsets::US_ASCII); - std::ostringstream value; - - for (std::vector <valueChunk>::size_type i = 0 ; i < chunks.size() ; ++i) - { - const valueChunk& chunk = chunks[i]; - - // Decode following data - if (chunk.encoded) - { - const string::size_type len = chunk.data.length(); - string::size_type pos = 0; - - // If this is the first encoded chunk, extract charset - // and language information - if (!foundCharsetChunk) - { - // Eg. "us-ascii'en'This%20is%20even%20more%20" - string::size_type q = chunk.data.find_first_of('\''); - - if (q != string::npos) - { - const string chs = chunk.data.substr(0, q); - - if (!chs.empty()) - ch = charset(chs); - - ++q; - pos = q; - } - - q = chunk.data.find_first_of('\'', pos); - - if (q != string::npos) - { - // Ignore language - ++q; - pos = q; - } - - foundCharsetChunk = true; - } - - for (string::size_type i = pos ; i < len ; ++i) - { - const string::value_type c = chunk.data[i]; - - if (c == '%' && i + 2 < len) - { - string::value_type v = 0; - - // First char - switch (chunk.data[i + 1]) - { - case 'a': case 'A': v += 10; break; - case 'b': case 'B': v += 11; break; - case 'c': case 'C': v += 12; break; - case 'd': case 'D': v += 13; break; - case 'e': case 'E': v += 14; break; - case 'f': case 'F': v += 15; break; - default: // assume 0-9 - - v += (chunk.data[i + 1] - '0'); - break; - } - - v *= 16; - - // Second char - switch (chunk.data[i + 2]) - { - case 'a': case 'A': v += 10; break; - case 'b': case 'B': v += 11; break; - case 'c': case 'C': v += 12; break; - case 'd': case 'D': v += 13; break; - case 'e': case 'E': v += 14; break; - case 'f': case 'F': v += 15; break; - default: // assume 0-9 - - v += (chunk.data[i + 2] - '0'); - break; - } - - value << v; - - i += 2; // skip next 2 chars - } - else - { - value << c; - } - } - } - // Simply copy data, as it is not encoded - else - { - value << chunk.data; - } - } - - m_value = vmime::create <word>(value.str(), ch); -} - - -void defaultParameter::generate(utility::outputStream& os, const string::size_type maxLineLength, - const string::size_type curLinePos, string::size_type* newLinePos) const -{ - const string& name = getName(); - const string& value = m_value->getBuffer(); - - // For compatibility with implementations that do not understand RFC-2231, - // also generate a normal "7bit/us-ascii" parameter - string::size_type pos = curLinePos; - - if (pos + name.length() + 10 + value.length() > maxLineLength) - { - os << NEW_LINE_SEQUENCE; - pos = NEW_LINE_SEQUENCE_LENGTH; - } - - bool needQuoting = false; - string::size_type valueLength = 0; - - for (string::size_type i = 0 ; (i < value.length()) && (pos + valueLength < maxLineLength - 4) ; ++i, ++valueLength) - { - switch (value[i]) - { - // Characters that need to be quoted _and_ escaped - case '"': - case '\\': - // Other characters that need quoting - case ' ': - case '\t': - case '(': - case ')': - case '<': - case '>': - case '@': - case ',': - case ';': - case ':': - case '/': - case '[': - case ']': - case '?': - case '=': - - needQuoting = true; - break; - } - } - - const bool cutValue = (valueLength != value.length()); // has the value been cut? - - if (needQuoting) - { - os << name << "=\""; - pos += name.length() + 2; - } - else - { - os << name << "="; - pos += name.length() + 1; - } - - bool extended = false; - - for (string::size_type i = 0 ; (i < value.length()) && (pos < maxLineLength - 4) ; ++i) - { - const char_t c = value[i]; - - if (/* needQuoting && */ (c == '"' || c == '\\')) // 'needQuoting' is implicit - { - os << '\\' << value[i]; // escape 'x' with '\x' - pos += 2; - } - else if (parserHelpers::isAscii(c)) - { - os << value[i]; - ++pos; - } - else - { - extended = true; - } - } - - if (needQuoting) - { - os << '"'; - ++pos; - } - - // Also generate an extended parameter if the value contains 8-bit characters - // or is too long for a single line - if (extended || cutValue) - { - os << ';'; - ++pos; - - /* RFC-2231 - * ======== - * - * Content-Type: message/external-body; access-type=URL; - * URL*0="ftp://"; - * URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" - * - * Content-Type: application/x-stuff; - * title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A - * - * Content-Type: application/x-stuff; - * title*0*=us-ascii'en'This%20is%20even%20more%20 - * title*1*=%2A%2A%2Afun%2A%2A%2A%20 - * title*2="isn't it!" - */ - - // Check whether there is enough space for the first section: - // parameter name, section identifier, charset and separators - // + at least 5 characters for the value - const string::size_type firstSectionLength = - name.length() + 4 /* *0*= */ + 2 /* '' */ - + m_value->getCharset().getName().length(); - - if (pos + firstSectionLength + 5 >= maxLineLength) - { - os << NEW_LINE_SEQUENCE; - pos = NEW_LINE_SEQUENCE_LENGTH; - } - - // Split text into multiple sections that fit on one line - int sectionCount = 0; - std::vector <string> sectionText; - - string currentSection; - string::size_type currentSectionLength = firstSectionLength; - - for (string::size_type i = 0 ; i < value.length() ; ++i) - { - // Check whether we should start a new line (taking into - // account the next character will be encoded = worst case) - if (currentSectionLength + 3 >= maxLineLength) - { - sectionText.push_back(currentSection); - sectionCount++; - - currentSection.clear(); - currentSectionLength = NEW_LINE_SEQUENCE_LENGTH - + name.length() + 6; - } - - // Output next character - const char_t c = value[i]; - bool encode = false; - - switch (c) - { - // special characters - case ' ': - case '\t': - case '\r': - case '\n': - case '"': - case ';': - case ',': - - encode = true; - break; - - default: - - encode = (!parserHelpers::isPrint(c) || - !parserHelpers::isAscii(c)); - - break; - } - - if (encode) // need encoding - { - const int h1 = static_cast <unsigned char>(c) / 16; - const int h2 = static_cast <unsigned char>(c) % 16; - - currentSection += '%'; - currentSection += "0123456789ABCDEF"[h1]; - currentSection += "0123456789ABCDEF"[h2]; - - pos += 3; - currentSectionLength += 3; - } - else - { - currentSection += value[i]; - - ++pos; - ++currentSectionLength; - } - } - - if (!currentSection.empty()) - { - sectionText.push_back(currentSection); - sectionCount++; - } - - // Output sections - for (int sectionNumber = 0 ; sectionNumber < sectionCount ; ++sectionNumber) - { - os << name; - - if (sectionCount != 1) // no section specifier when only a single one - { - os << '*'; - os << sectionNumber; - } - - os << "*="; - - if (sectionNumber == 0) - { - os << m_value->getCharset().getName(); - os << '\'' << /* No language */ '\''; - } - - os << sectionText[sectionNumber]; - - if (sectionNumber + 1 < sectionCount) - { - os << ';'; - os << NEW_LINE_SEQUENCE; - pos = NEW_LINE_SEQUENCE_LENGTH; - } - } - } - - if (newLinePos) - *newLinePos = pos; -} - - - -} // vmime diff --git a/src/encoding.cpp b/src/encoding.cpp index 4465021d..f2b40ed0 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -45,7 +45,7 @@ encoding::encoding(const string& name) encoding::encoding(const encoding& enc) - : component(), m_name(enc.m_name) + : headerFieldValue(), m_name(enc.m_name) { } diff --git a/src/fileAttachment.cpp b/src/fileAttachment.cpp index 584ba12a..785e0b8e 100644 --- a/src/fileAttachment.cpp +++ b/src/fileAttachment.cpp @@ -29,6 +29,8 @@ #include "vmime/streamContentHandler.hpp" +#include "vmime/contentDispositionField.hpp" + namespace vmime { @@ -78,7 +80,8 @@ void fileAttachment::generatePart(bodyPart& part) const { defaultAttachment::generatePart(part); - ref <contentDispositionField> cdf = part.getHeader()->ContentDisposition(); + ref <contentDispositionField> cdf = part.getHeader()->ContentDisposition(). + dynamicCast <contentDispositionField>(); if (m_fileInfo.hasSize()) cdf->setSize(utility::stringUtils::toString(m_fileInfo.getSize())); if (m_fileInfo.hasFilename()) cdf->setFilename(m_fileInfo.getFilename()); diff --git a/src/headerField.cpp b/src/headerField.cpp index 87524fbf..13b6ae4f 100644 --- a/src/headerField.cpp +++ b/src/headerField.cpp @@ -62,7 +62,7 @@ void headerField::copyFrom(const component& other) { const headerField& hf = dynamic_cast <const headerField&>(other); - getValue().copyFrom(hf.getValue()); + m_value->copyFrom(*hf.m_value); } @@ -227,7 +227,7 @@ ref <headerField> headerField::parseNext(const string& buffer, const string::siz void headerField::parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition) { - getValue().parse(buffer, position, end, newPosition); + m_value->parse(buffer, position, end, newPosition); } @@ -236,13 +236,19 @@ void headerField::generate(utility::outputStream& os, const string::size_type ma { os << m_name + ": "; - getValue().generate(os, maxLineLength, curLinePos + m_name.length() + 2, newLinePos); + m_value->generate(os, maxLineLength, curLinePos + m_name.length() + 2, newLinePos); } const string headerField::getName() const { - return (m_name); + return m_name; +} + + +void headerField::setName(const string& name) +{ + m_name = name; } @@ -256,12 +262,43 @@ const std::vector <ref <const component> > headerField::getChildComponents() con { std::vector <ref <const component> > list; - list.push_back(getValueImp()); + list.push_back(m_value); return (list); } +ref <const headerFieldValue> headerField::getValue() const +{ + return m_value; +} + + +ref <headerFieldValue> headerField::getValue() +{ + return m_value; +} + + +void headerField::setValue(ref <headerFieldValue> value) +{ + if (value != NULL) + m_value = value; +} + + +void headerField::setValueConst(ref <const headerFieldValue> value) +{ + m_value = value->clone().dynamicCast <headerFieldValue>(); +} + + +void headerField::setValue(const headerFieldValue& value) +{ + m_value = value.clone().dynamicCast <headerFieldValue>(); +} + + void headerField::setValue(const string& value) { parse(value); diff --git a/src/headerFieldFactory.cpp b/src/headerFieldFactory.cpp index 98a6f300..61782c2b 100644 --- a/src/headerFieldFactory.cpp +++ b/src/headerFieldFactory.cpp @@ -24,11 +24,18 @@ #include "vmime/headerFieldFactory.hpp" #include "vmime/exception.hpp" -#include "vmime/standardFields.hpp" +#include "vmime/mailboxList.hpp" +#include "vmime/dateTime.hpp" +#include "vmime/text.hpp" +#include "vmime/path.hpp" +#include "vmime/relay.hpp" +#include "vmime/encoding.hpp" +#include "vmime/disposition.hpp" +#include "vmime/messageIdSequence.hpp" -#include "vmime/mailboxField.hpp" #include "vmime/contentTypeField.hpp" #include "vmime/contentDispositionField.hpp" +#include "vmime/mailboxField.hpp" namespace vmime @@ -37,34 +44,44 @@ namespace vmime headerFieldFactory::headerFieldFactory() { - // Register some default fields - registerName <mailboxField>(vmime::fields::FROM); - registerName <addressListField>(vmime::fields::TO); - registerName <addressListField>(vmime::fields::CC); - registerName <addressListField>(vmime::fields::BCC); - registerName <mailboxField>(vmime::fields::SENDER); - registerName <dateField>(vmime::fields::DATE); - registerName <relayField>(vmime::fields::RECEIVED); - registerName <textField>(vmime::fields::SUBJECT); - registerName <mailboxField>(vmime::fields::REPLY_TO); - registerName <mailboxField>(vmime::fields::DELIVERED_TO); - registerName <textField>(vmime::fields::ORGANIZATION); - registerName <textField>(vmime::fields::USER_AGENT); - registerName <pathField>(vmime::fields::RETURN_PATH); - registerName <contentTypeField>(vmime::fields::CONTENT_TYPE); - registerName <contentEncodingField>(vmime::fields::CONTENT_TRANSFER_ENCODING); - registerName <textField>(vmime::fields::CONTENT_DESCRIPTION); - registerName <defaultField>(vmime::fields::MIME_VERSION); - registerName <contentDispositionField>(vmime::fields::CONTENT_DISPOSITION); - registerName <messageIdField>(vmime::fields::CONTENT_ID); - registerName <messageIdField>(vmime::fields::MESSAGE_ID); - registerName <defaultField>(vmime::fields::CONTENT_LOCATION); - registerName <messageIdSequenceField>(vmime::fields::IN_REPLY_TO); - registerName <messageIdSequenceField>(vmime::fields::REFERENCES); - - registerName <messageIdField>(vmime::fields::ORIGINAL_MESSAGE_ID); - registerName <dispositionField>(vmime::fields::DISPOSITION); - registerName <mailboxListField>(vmime::fields::DISPOSITION_NOTIFICATION_TO); + // Register parameterized fields + registerField <contentTypeField>(vmime::fields::CONTENT_TYPE); + registerField <parameterizedHeaderField>(vmime::fields::CONTENT_TRANSFER_ENCODING); + registerField <contentDispositionField>(vmime::fields::CONTENT_DISPOSITION); + + registerField <mailboxField>(vmime::fields::FROM); + registerField <mailboxField>(vmime::fields::SENDER); + registerField <mailboxField>(vmime::fields::REPLY_TO); + registerField <mailboxField>(vmime::fields::DELIVERED_TO); + + // Register standard field values + registerFieldValue <mailbox>(vmime::fields::FROM); + registerFieldValue <addressList>(vmime::fields::TO); + registerFieldValue <addressList>(vmime::fields::CC); + registerFieldValue <addressList>(vmime::fields::BCC); + registerFieldValue <mailbox>(vmime::fields::SENDER); + registerFieldValue <datetime>(vmime::fields::DATE); + registerFieldValue <relay>(vmime::fields::RECEIVED); + registerFieldValue <text>(vmime::fields::SUBJECT); + registerFieldValue <mailbox>(vmime::fields::REPLY_TO); + registerFieldValue <mailbox>(vmime::fields::DELIVERED_TO); + registerFieldValue <text>(vmime::fields::ORGANIZATION); + registerFieldValue <text>(vmime::fields::USER_AGENT); + registerFieldValue <path>(vmime::fields::RETURN_PATH); + registerFieldValue <mediaType>(vmime::fields::CONTENT_TYPE); + registerFieldValue <encoding>(vmime::fields::CONTENT_TRANSFER_ENCODING); + registerFieldValue <text>(vmime::fields::CONTENT_DESCRIPTION); + registerFieldValue <text>(vmime::fields::MIME_VERSION); + registerFieldValue <contentDisposition>(vmime::fields::CONTENT_DISPOSITION); + registerFieldValue <messageId>(vmime::fields::CONTENT_ID); + registerFieldValue <messageId>(vmime::fields::MESSAGE_ID); + registerFieldValue <text>(vmime::fields::CONTENT_LOCATION); + registerFieldValue <messageIdSequence>(vmime::fields::IN_REPLY_TO); + registerFieldValue <messageIdSequence>(vmime::fields::REFERENCES); + + registerFieldValue <messageId>(vmime::fields::ORIGINAL_MESSAGE_ID); + registerFieldValue <disposition>(vmime::fields::DISPOSITION); + registerFieldValue <mailboxList>(vmime::fields::DISPOSITION_NOTIFICATION_TO); } @@ -87,21 +104,35 @@ ref <headerField> headerFieldFactory::create ref <headerField> field = NULL; if (pos != m_nameMap.end()) - { field = ((*pos).second)(); - } else - { - field = registerer <defaultField>::creator(); - } + field = registerer <headerField, headerField>::creator(); - field->m_name = name; + field->setName(name); + field->setValue(createValue(name)); if (body != NULL_STRING) field->parse(body); - return (field); + return field; +} + + +ref <headerFieldValue> headerFieldFactory::createValue(const string& fieldName) +{ + ValueMap::const_iterator pos = m_valueMap.find + (utility::stringUtils::toLower(fieldName)); + + ref <headerFieldValue> value = NULL; + + if (pos != m_valueMap.end()) + value = ((*pos).second)(); + else + value = registerer <headerFieldValue, text>::creator(); + + return value; } } // vmime + diff --git a/src/htmlTextPart.cpp b/src/htmlTextPart.cpp index 7d1f6896..b2cb3523 100644 --- a/src/htmlTextPart.cpp +++ b/src/htmlTextPart.cpp @@ -24,6 +24,10 @@ #include "vmime/htmlTextPart.hpp" #include "vmime/exception.hpp" +#include "vmime/contentTypeField.hpp" +#include "vmime/contentDisposition.hpp" +#include "vmime/text.hpp" + #include "vmime/emptyContentHandler.hpp" #include "vmime/stringContentHandler.hpp" @@ -66,8 +70,9 @@ void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const parent.getBody()->appendPart(part); // -- Set header fields - part->getHeader()->ContentType()->setValue(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); - part->getHeader()->ContentType()->setCharset(m_charset); + part->getHeader()->ContentType()->setValue + (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); + part->getHeader()->ContentType().dynamicCast <contentTypeField>()->setCharset(m_charset); part->getHeader()->ContentTransferEncoding()->setValue(encoding(encodingTypes::QUOTED_PRINTABLE)); // -- Set contents @@ -80,7 +85,7 @@ void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const // -- Set header fields htmlPart->getHeader()->ContentType()->setValue(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML)); - htmlPart->getHeader()->ContentType()->setCharset(m_charset); + htmlPart->getHeader()->ContentType().dynamicCast <contentTypeField>()->setCharset(m_charset); htmlPart->getHeader()->ContentTransferEncoding()->setValue(encoding(encodingTypes::QUOTED_PRINTABLE)); // -- Set contents @@ -167,8 +172,8 @@ void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id) try { - const ref <const contentTypeField> ctf = part.getHeader()->ContentType(); - type = ctf->getValue(); + const ref <const headerField> ctf = part.getHeader()->ContentType(); + type = *ctf->getValue().dynamicCast <const mediaType>(); } catch (exceptions::no_such_field) { @@ -219,29 +224,34 @@ void htmlTextPart::parse(const bodyPart& message, const bodyPart& parent, const // found inline part, we check if its CID/Location is contained in the HTML text. for (std::vector <ref <const bodyPart> >::const_iterator p = cidParts.begin() ; p != cidParts.end() ; ++p) { - const ref <const messageIdField> midField = - (*p)->getHeader()->findField(fields::CONTENT_ID).dynamicCast <messageIdField>(); + const ref <const headerField> midField = + (*p)->getHeader()->findField(fields::CONTENT_ID); + + const messageId mid = *midField->getValue().dynamicCast <const messageId>(); - const string searchFor("CID:" + midField->getValue().getId()); + const string searchFor("CID:" + mid.getId()); if (data.find(searchFor) != string::npos) { // This part is referenced in the HTML text. // Add it to the embedded object list. - addEmbeddedObject(**p, "CID:" + midField->getValue().getId()); + addEmbeddedObject(**p, "CID:" + mid.getId()); } } for (std::vector <ref <const bodyPart> >::const_iterator p = locParts.begin() ; p != locParts.end() ; ++p) { - const ref <const defaultField> locField = - (*p)->getHeader()->findField(fields::CONTENT_LOCATION).dynamicCast <defaultField>(); + const ref <const headerField> locField = + (*p)->getHeader()->findField(fields::CONTENT_LOCATION); + + const text loc = *locField->getValue().dynamicCast <const text>(); + const string locStr = loc.getWholeBuffer(); - if (data.find(locField->getValue()) != 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, locField->getValue()); + addEmbeddedObject(**p, locStr); } } @@ -258,11 +268,13 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren // We search for the nearest "multipart/alternative" part. try { - const ref <const contentTypeField> ctf = - part.getHeader()->findField(fields::CONTENT_TYPE).dynamicCast <contentTypeField>(); + const ref <const headerField> ctf = + part.getHeader()->findField(fields::CONTENT_TYPE); + + const mediaType type = *ctf->getValue().dynamicCast <const mediaType>(); - if (ctf->getValue().getType() == mediaTypes::MULTIPART && - ctf->getValue().getSubType() == mediaTypes::MULTIPART_ALTERNATIVE) + if (type.getType() == mediaTypes::MULTIPART && + type.getSubType() == mediaTypes::MULTIPART_ALTERNATIVE) { ref <const bodyPart> foundPart = NULL; @@ -288,11 +300,13 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren try { - const ref <const contentTypeField> ctf = - p->getHeader()->findField(fields::CONTENT_TYPE).dynamicCast <contentTypeField>(); + const ref <const headerField> ctf = + p->getHeader()->findField(fields::CONTENT_TYPE); + + const mediaType type = *ctf->getValue().dynamicCast <const mediaType>(); - if (ctf->getValue().getType() == mediaTypes::TEXT && - ctf->getValue().getSubType() == mediaTypes::TEXT_PLAIN) + if (type.getType() == mediaTypes::TEXT && + type.getSubType() == mediaTypes::TEXT_PLAIN) { m_plainText = p->getBody()->getContents()->clone(); found = true; diff --git a/src/mailboxField.cpp b/src/mailboxField.cpp index bab461be..188fa17b 100644 --- a/src/mailboxField.cpp +++ b/src/mailboxField.cpp @@ -25,6 +25,9 @@ #include "vmime/mailboxGroup.hpp" +#ifndef VMIME_BUILDING_DOC + + namespace vmime { @@ -35,7 +38,7 @@ mailboxField::mailboxField() mailboxField::mailboxField(const mailboxField&) - : headerField(), genericField <mailbox>() + : headerField() { } @@ -43,7 +46,7 @@ mailboxField::mailboxField(const mailboxField&) void mailboxField::parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition) { - getValue().clear(); + ref <mailbox> mbox = vmime::create <mailbox>(); // Here, we cannot simply call "m_mailbox.parse()" because it // may have more than one address specified (even if this field @@ -59,16 +62,18 @@ void mailboxField::parse(const string& buffer, const string::size_type position, ref <mailboxGroup> group = parsedAddress.staticCast <mailboxGroup>(); if (!group->isEmpty()) - getValue() = *(group->getMailboxAt(0)); + mbox = group->getMailboxAt(0); } else { // Parse only if it is a mailbox - getValue() = *parsedAddress.staticCast <mailbox>(); + mbox = parsedAddress.staticCast <mailbox>(); } } - getValue().setParsedBounds(position, end); + mbox->setParsedBounds(position, end); + + setValue(mbox); setParsedBounds(position, end); @@ -78,3 +83,7 @@ void mailboxField::parse(const string& buffer, const string::size_type position, } // vmime + + +#endif // VMIME_BUILDING_DOC + diff --git a/src/mailboxList.cpp b/src/mailboxList.cpp index 4ff0b885..6e43059f 100644 --- a/src/mailboxList.cpp +++ b/src/mailboxList.cpp @@ -35,7 +35,7 @@ mailboxList::mailboxList() mailboxList::mailboxList(const mailboxList& mboxList) - : component(), m_list(mboxList.m_list) + : headerFieldValue(), m_list(mboxList.m_list) { } diff --git a/src/mdn/MDNHelper.cpp b/src/mdn/MDNHelper.cpp index b79b8713..a140a7a4 100644 --- a/src/mdn/MDNHelper.cpp +++ b/src/mdn/MDNHelper.cpp @@ -22,6 +22,11 @@ #include "vmime/exception.hpp" #include "vmime/stringContentHandler.hpp" +#include "vmime/contentTypeField.hpp" + +#include "vmime/path.hpp" +#include "vmime/dateTime.hpp" + namespace vmime { namespace mdn { @@ -52,7 +57,8 @@ const std::vector <sendableMDNInfos> MDNHelper::getPossibleMDNs(const ref <const if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) { - const mailboxList& dnto = hdr->DispositionNotificationTo()->getValue(); + const mailboxList& dnto = *hdr->DispositionNotificationTo()->getValue() + .dynamicCast <const mailboxList>(); for (int i = 0 ; i < dnto.getMailboxCount() ; ++i) result.push_back(sendableMDNInfos(msg, *dnto.getMailboxAt(i))); @@ -72,10 +78,13 @@ const bool MDNHelper::isMDN(const ref <const message> msg) // and its value is "disposition-notification" if (hdr->hasField(fields::CONTENT_TYPE)) { - const contentTypeField& ctf = *(hdr->ContentType()); + const contentTypeField& ctf = *(hdr->ContentType() + .dynamicCast <const contentTypeField>()); + + const mediaType type = *ctf.getValue().dynamicCast <const mediaType>(); - if (ctf.getValue().getType() == vmime::mediaTypes::MULTIPART && - ctf.getValue().getSubType() == vmime::mediaTypes::MULTIPART_REPORT) + if (type.getType() == vmime::mediaTypes::MULTIPART && + type.getSubType() == vmime::mediaTypes::MULTIPART_REPORT) { if (ctf.hasParameter("report-type") && ctf.getReportType() == "disposition-notification") @@ -104,26 +113,29 @@ const bool MDNHelper::needConfirmation(const ref <const message> msg) // No "Return-Path" field if (!hdr->hasField(fields::RETURN_PATH)) - return (true); + return true; // More than one address in Disposition-Notification-To if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) { - const mailboxList& dnto = hdr->DispositionNotificationTo()->getValue(); + const mailboxList& dnto = *hdr->DispositionNotificationTo()->getValue() + .dynamicCast <const mailboxList>(); if (dnto.getMailboxCount() > 1) - return (true); + return true; + else if (dnto.getMailboxCount() == 0) + return false; // Return-Path != Disposition-Notification-To const mailbox& mbox = *dnto.getMailboxAt(0); - const path& rp = hdr->ReturnPath()->getValue(); + const path& rp = *hdr->ReturnPath()->getValue().dynamicCast <const path>(); if (mbox.getEmail() != rp.getLocalPart() + "@" + rp.getDomain()) - return (true); + return true; } // User confirmation not needed - return (false); + return false; } @@ -143,13 +155,17 @@ ref <message> MDNHelper::buildMDN(const sendableMDNInfos& mdnInfos, hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::MULTIPART, vmime::mediaTypes::MULTIPART_REPORT)); - hdr->ContentType()->setReportType("disosition-notification"); + hdr->ContentType().dynamicCast <contentTypeField>()->setReportType("disposition-notification"); hdr->Disposition()->setValue(dispo); - hdr->To()->getValue().appendAddress(vmime::create <mailbox>(mdnInfos.getRecipient())); - hdr->From()->getValue() = expeditor; - hdr->Subject()->getValue().appendWord(vmime::create <word>("Disposition notification")); + addressList to; + to.appendAddress(vmime::create <mailbox>(mdnInfos.getRecipient())); + hdr->To()->setValue(to); + + hdr->From()->setValue(expeditor); + + hdr->Subject()->setValue(vmime::text(word("Disposition notification"))); hdr->Date()->setValue(datetime::now()); hdr->MimeVersion()->setValue(string(SUPPORTED_MIME_VERSION)); @@ -174,7 +190,7 @@ ref <bodyPart> MDNHelper::createFirstMDNPart(const sendableMDNInfos& /* mdnInfos hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_PLAIN)); - hdr->ContentType()->setCharset(ch); + hdr->ContentType().dynamicCast <contentTypeField>()->setCharset(ch); // Body part->getBody()->setContents(vmime::create <stringContentHandler>(text)); @@ -233,9 +249,8 @@ ref <bodyPart> MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdnInfos, ruaText += reportingUAProducts[i]; } - ref <defaultField> rua = - (headerFieldFactory::getInstance()->create - (vmime::fields::REPORTING_UA)).dynamicCast <defaultField>(); + ref <headerField> rua = headerFieldFactory::getInstance()-> + create(vmime::fields::REPORTING_UA); rua->setValue(ruaText); @@ -243,16 +258,15 @@ ref <bodyPart> MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdnInfos, } // -- Final-Recipient - ref <defaultField> fr = - (headerFieldFactory::getInstance()-> - create(vmime::fields::FINAL_RECIPIENT)).dynamicCast <defaultField>(); + ref <headerField> fr = headerFieldFactory::getInstance()-> + create(vmime::fields::FINAL_RECIPIENT); fr->setValue("rfc822; " + mdnInfos.getRecipient().getEmail()); // -- Original-Message-ID if (mdnInfos.getMessage()->getHeader()->hasField(vmime::fields::MESSAGE_ID)) { - fields.OriginalMessageId()->setValue + fields.OriginalMessageId()->setValueConst (mdnInfos.getMessage()->getHeader()->MessageId()->getValue()); } diff --git a/src/mdn/receivedMDNInfos.cpp b/src/mdn/receivedMDNInfos.cpp index dea54a0b..3578931e 100644 --- a/src/mdn/receivedMDNInfos.cpp +++ b/src/mdn/receivedMDNInfos.cpp @@ -82,7 +82,8 @@ void receivedMDNInfos::extract() if (!part->getHeader()->hasField(fields::CONTENT_TYPE)) continue; - const mediaType& type = part->getHeader()->ContentType()->getValue(); + const mediaType& type = *part->getHeader()->ContentType()-> + getValue().dynamicCast <const mediaType>(); // Extract from second part (message/disposition-notification) if (type.getType() == vmime::mediaTypes::MESSAGE && @@ -97,10 +98,10 @@ void receivedMDNInfos::extract() header fields; fields.parse(oss.str()); - try { m_omid = fields.OriginalMessageId()->getValue(); } + try { m_omid = *fields.OriginalMessageId()->getValue().dynamicCast <const messageId>(); } catch (exceptions::no_such_field&) { /* Ignore */ } - try { m_disp = fields.Disposition()->getValue(); } + try { m_disp = *fields.Disposition()->getValue().dynamicCast <const disposition>(); } catch (exceptions::no_such_field&) { /* Ignore */ } } } diff --git a/src/messageBuilder.cpp b/src/messageBuilder.cpp index 5768ca3c..429cbd0a 100644 --- a/src/messageBuilder.cpp +++ b/src/messageBuilder.cpp @@ -23,6 +23,7 @@ #include "vmime/messageBuilder.hpp" +#include "vmime/dateTime.hpp" #include "vmime/textPartFactory.hpp" diff --git a/src/messageId.cpp b/src/messageId.cpp index b9ef32fd..705d987c 100644 --- a/src/messageId.cpp +++ b/src/messageId.cpp @@ -43,7 +43,7 @@ messageId::messageId(const string& id) messageId::messageId(const messageId& mid) - : component(), m_left(mid.m_left), m_right(mid.m_right) + : headerFieldValue(), m_left(mid.m_left), m_right(mid.m_right) { } diff --git a/src/messageIdSequence.cpp b/src/messageIdSequence.cpp index 877d4f8c..1be754c2 100644 --- a/src/messageIdSequence.cpp +++ b/src/messageIdSequence.cpp @@ -44,7 +44,7 @@ messageIdSequence::~messageIdSequence() messageIdSequence::messageIdSequence(const messageIdSequence& midSeq) - : component() + : headerFieldValue() { copyFrom(midSeq); } diff --git a/src/messageParser.cpp b/src/messageParser.cpp index 4a96cf10..8f1c1610 100644 --- a/src/messageParser.cpp +++ b/src/messageParser.cpp @@ -28,6 +28,9 @@ #include "vmime/defaultAttachment.hpp" #include "vmime/textPartFactory.hpp" +#include "vmime/relay.hpp" +#include "vmime/contentTypeField.hpp" + namespace vmime { @@ -59,16 +62,16 @@ void messageParser::parse(ref <const message> msg) #ifndef VMIME_BUILDING_DOC #define TRY_FIELD(var, type, name) \ - try { var = dynamic_cast<type&>(*msg->getHeader()->findField(name)).getValue(); } \ + try { var = *msg->getHeader()->findField(name)->getValue().dynamicCast <type>(); } \ catch (exceptions::no_such_field) { } - TRY_FIELD(m_from, mailboxField, fields::FROM); + TRY_FIELD(m_from, mailbox, fields::FROM); - TRY_FIELD(m_to, addressListField, fields::TO); - TRY_FIELD(m_cc, addressListField, fields::CC); - TRY_FIELD(m_bcc, addressListField, fields::BCC); + TRY_FIELD(m_to, addressList, fields::TO); + TRY_FIELD(m_cc, addressList, fields::CC); + TRY_FIELD(m_bcc, addressList, fields::BCC); - TRY_FIELD(m_subject, textField, fields::SUBJECT); + TRY_FIELD(m_subject, text, fields::SUBJECT); #undef TRY_FIELD @@ -77,19 +80,15 @@ void messageParser::parse(ref <const message> msg) // Date try { - vmime::relayField& recv = dynamic_cast <vmime::relayField&> - (*msg->getHeader()->findField(fields::RECEIVED)); - - m_date = recv.getValue().getDate(); + const headerField& recv = *msg->getHeader()->findField(fields::RECEIVED); + m_date = recv.getValue().dynamicCast <const relay>()->getDate(); } catch (vmime::exceptions::no_such_field&) { try { - vmime::dateField& date = dynamic_cast <vmime::dateField&> - (*msg->getHeader()->findField(fields::DATE)); - - m_date = date.getValue(); + const headerField& date = *msg->getHeader()->findField(fields::DATE); + m_date = *date.getValue().dynamicCast <const datetime>(); } catch (vmime::exceptions::no_such_field&) { @@ -125,13 +124,16 @@ void messageParser::findTextParts(const bodyPart& msg, const bodyPart& part) const contentTypeField& ctf = dynamic_cast<contentTypeField&> (*msg.getHeader()->findField(fields::CONTENT_TYPE)); - if (ctf.getValue().getType() == mediaTypes::TEXT) + const mediaType ctfType = + *ctf.getValue().dynamicCast <const mediaType>(); + + if (ctfType.getType() == mediaTypes::TEXT) { - type = ctf.getValue(); + type = ctfType; accept = true; } } - catch (exceptions::no_such_field) + catch (exceptions::no_such_field&) { // No "Content-type" field: assume "text/plain". accept = true; @@ -171,12 +173,14 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part) const contentTypeField& ctf = dynamic_cast <const contentTypeField&> (*(p->getHeader()->findField(fields::CONTENT_TYPE))); - if (ctf.getValue().getType() == mediaTypes::TEXT) + const mediaType type = *ctf.getValue().dynamicCast <const mediaType>(); + + if (type.getType() == mediaTypes::TEXT) { textParts.push_back(p); } } - catch (exceptions::no_such_field) + catch (exceptions::no_such_field&) { // No "Content-type" field. } @@ -191,9 +195,11 @@ bool messageParser::findSubTextParts(const bodyPart& msg, const bodyPart& part) const contentTypeField& ctf = dynamic_cast <const contentTypeField&> (*((*p)->getHeader()->findField(fields::CONTENT_TYPE))); + const mediaType type = *ctf.getValue().dynamicCast <const mediaType>(); + try { - ref <textPart> txtPart = textPartFactory::getInstance()->create(ctf.getValue()); + ref <textPart> txtPart = textPartFactory::getInstance()->create(type); txtPart->parse(msg, part, **p); m_textParts.push_back(txtPart); diff --git a/src/misc/importanceHelper.cpp b/src/misc/importanceHelper.cpp index 4c5bf5d4..83df4548 100644 --- a/src/misc/importanceHelper.cpp +++ b/src/misc/importanceHelper.cpp @@ -20,6 +20,8 @@ #include "vmime/misc/importanceHelper.hpp" #include "vmime/exception.hpp" +#include "vmime/text.hpp" + namespace vmime { namespace misc { @@ -66,8 +68,8 @@ const importanceHelper::Importance importanceHelper::getImportanceHeader(ref <co // Try "X-Priority" field try { - const ref <const defaultField> fld = hdr->findField("X-Priority").dynamicCast <const defaultField>(); - const string value = fld->getValue(); + const ref <const headerField> fld = hdr->findField("X-Priority"); + const string value = fld->getValue().dynamicCast <const text>()->getWholeBuffer(); int n = IMPORTANCE_NORMAL; @@ -92,8 +94,9 @@ const importanceHelper::Importance importanceHelper::getImportanceHeader(ref <co // Try "Importance" field try { - const ref <const defaultField> fld = hdr->findField("Importance").dynamicCast <const defaultField>(); - const string value = utility::stringUtils::toLower(utility::stringUtils::trim(fld->getValue())); + const ref <const headerField> fld = hdr->findField("Importance"); + const string value = utility::stringUtils::toLower(utility::stringUtils::trim + (fld->getValue().dynamicCast <const text>()->getWholeBuffer())); if (value == "low") return (IMPORTANCE_LOWEST); @@ -123,7 +126,7 @@ void importanceHelper::setImportance(ref <message> msg, const Importance i) void importanceHelper::setImportanceHeader(ref <header> hdr, const Importance i) { // "X-Priority:" Field - ref <defaultField> fld = hdr->getField("X-Priority").dynamicCast <defaultField>(); + ref <headerField> fld = hdr->getField("X-Priority"); switch (i) { @@ -136,7 +139,7 @@ void importanceHelper::setImportanceHeader(ref <header> hdr, const Importance i) } // "Importance:" Field - fld = hdr->getField("Importance").dynamicCast <defaultField>(); + fld = hdr->getField("Importance"); switch (i) { diff --git a/src/net/transport.cpp b/src/net/transport.cpp index 85d227e4..6dcf3101 100644 --- a/src/net/transport.cpp +++ b/src/net/transport.cpp @@ -54,9 +54,10 @@ void transport::send(ref <vmime::message> msg, utility::progressListener* progre try { - const mailboxField& from = dynamic_cast <const mailboxField&> - (*msg->getHeader()->findField(fields::FROM)); - expeditor = from.getValue(); + const mailbox& mbox = *msg->getHeader()->findField(fields::FROM)-> + getValue().dynamicCast <const mailbox>(); + + expeditor = mbox; } catch (exceptions::no_such_field&) { @@ -68,25 +69,28 @@ void transport::send(ref <vmime::message> msg, utility::progressListener* progre try { - const addressListField& to = dynamic_cast <const addressListField&> - (*msg->getHeader()->findField(fields::TO)); - extractMailboxes(recipients, to.getValue()); + const addressList& to = *msg->getHeader()->findField(fields::TO)-> + getValue().dynamicCast <const addressList>(); + + extractMailboxes(recipients, to); } catch (exceptions::no_such_field&) { } try { - const addressListField& cc = dynamic_cast <const addressListField&> - (*msg->getHeader()->findField(fields::CC)); - extractMailboxes(recipients, cc.getValue()); + const addressList& cc = *msg->getHeader()->findField(fields::CC)-> + getValue().dynamicCast <const addressList>(); + + extractMailboxes(recipients, cc); } catch (exceptions::no_such_field&) { } try { - const addressListField& bcc = dynamic_cast <const addressListField&> - (*msg->getHeader()->findField(fields::BCC)); - extractMailboxes(recipients, bcc.getValue()); + const addressList& bcc = *msg->getHeader()->findField(fields::BCC)-> + getValue().dynamicCast <const addressList>(); + + extractMailboxes(recipients, bcc); } catch (exceptions::no_such_field&) { } diff --git a/src/parameter.cpp b/src/parameter.cpp index d6881a00..9b4325f8 100644 --- a/src/parameter.cpp +++ b/src/parameter.cpp @@ -22,16 +22,42 @@ // #include "vmime/parameter.hpp" -#include "vmime/parameterFactory.hpp" +#include "vmime/parserHelpers.hpp" + +#include "vmime/text.hpp" namespace vmime { +parameter::parameter(const string& name) + : m_name(name) +{ +} + + +parameter::parameter(const string& name, const word& value) + : m_name(name), m_value(value) +{ +} + + +parameter::parameter(const string& name, const string& value) + : m_name(name), m_value(value) +{ +} + + +parameter::parameter(const parameter&) + : component() +{ +} + + ref <component> parameter::clone() const { - ref <parameter> p = parameterFactory::getInstance()->create(m_name); + ref <parameter> p = vmime::create <parameter>(m_name); p->copyFrom(*this); return (p); @@ -43,8 +69,7 @@ void parameter::copyFrom(const component& other) const parameter& param = dynamic_cast <const parameter&>(other); m_name = param.m_name; - - getValue().copyFrom(param.getValue()); + m_value.copyFrom(param.m_value); } @@ -57,16 +82,38 @@ parameter& parameter::operator=(const parameter& other) const string& parameter::getName() const { - return (m_name); + return m_name; +} + + +const word& parameter::getValue() const +{ + return m_value; +} + + +void parameter::setValue(const component& value) +{ + std::ostringstream oss; + utility::outputStreamAdapter vos(oss); + + value.generate(vos); + + setValue(word(oss.str(), vmime::charsets::US_ASCII)); +} + + +void parameter::setValue(const word& value) +{ + m_value = value; } void parameter::parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition) { - getValue().parse(buffer, position, end, newPosition); - - setParsedBounds(position, end); + m_value.setBuffer(string(buffer.begin() + position, buffer.begin() + end)); + m_value.setCharset(charset(charsets::US_ASCII)); if (newPosition) *newPosition = end; @@ -75,69 +122,157 @@ void parameter::parse(const string& buffer, const string::size_type position, void parameter::parse(const std::vector <valueChunk>& chunks) { - string value; + bool foundCharsetChunk = false; + + charset ch(charsets::US_ASCII); + std::ostringstream value; - for (std::vector <valueChunk>::const_iterator it = chunks.begin() ; - it != chunks.end() ; ++it) + for (std::vector <valueChunk>::size_type i = 0 ; i < chunks.size() ; ++i) { - value += (*it).data; + const valueChunk& chunk = chunks[i]; + + // Decode following data + if (chunk.encoded) + { + const string::size_type len = chunk.data.length(); + string::size_type pos = 0; + + // If this is the first encoded chunk, extract charset + // and language information + if (!foundCharsetChunk) + { + // Eg. "us-ascii'en'This%20is%20even%20more%20" + string::size_type q = chunk.data.find_first_of('\''); + + if (q != string::npos) + { + const string chs = chunk.data.substr(0, q); + + if (!chs.empty()) + ch = charset(chs); + + ++q; + pos = q; + } + + q = chunk.data.find_first_of('\'', pos); + + if (q != string::npos) + { + // Ignore language + ++q; + pos = q; + } + + foundCharsetChunk = true; + } + + for (string::size_type i = pos ; i < len ; ++i) + { + const string::value_type c = chunk.data[i]; + + if (c == '%' && i + 2 < len) + { + string::value_type v = 0; + + // First char + switch (chunk.data[i + 1]) + { + case 'a': case 'A': v += 10; break; + case 'b': case 'B': v += 11; break; + case 'c': case 'C': v += 12; break; + case 'd': case 'D': v += 13; break; + case 'e': case 'E': v += 14; break; + case 'f': case 'F': v += 15; break; + default: // assume 0-9 + + v += (chunk.data[i + 1] - '0'); + break; + } + + v *= 16; + + // Second char + switch (chunk.data[i + 2]) + { + case 'a': case 'A': v += 10; break; + case 'b': case 'B': v += 11; break; + case 'c': case 'C': v += 12; break; + case 'd': case 'D': v += 13; break; + case 'e': case 'E': v += 14; break; + case 'f': case 'F': v += 15; break; + default: // assume 0-9 + + v += (chunk.data[i + 2] - '0'); + break; + } + + value << v; + + i += 2; // skip next 2 chars + } + else + { + value << c; + } + } + } + // Simply copy data, as it is not encoded + else + { + // This syntax is non-standard (expressly prohibited + // by RFC-2047), but is used by Mozilla: + // + // Content-Type: image/png; + // name="=?us-ascii?Q?Logo_VMime=2Epng?=" + + // Using 'vmime::text' to parse the data is safe even + // if the data is not encoded, because it can recover + // from parsing errors. + vmime::text t; + t.parse(chunk.data); + + if (t.getWordCount() != 0) + { + value << t.getWholeBuffer(); + + if (!foundCharsetChunk) + ch = t.getWordAt(0)->getCharset(); + } + } } - getValue().parse(value, 0, value.length(), NULL); + m_value.setBuffer(value.str()); + m_value.setCharset(ch); } void parameter::generate(utility::outputStream& os, const string::size_type maxLineLength, const string::size_type curLinePos, string::size_type* newLinePos) const { + const string& name = m_name; + const string& value = m_value.getBuffer(); + + // For compatibility with implementations that do not understand RFC-2231, + // also generate a normal "7bit/us-ascii" parameter string::size_type pos = curLinePos; - if (pos + m_name.length() + 10 > maxLineLength) + if (pos + name.length() + 10 + value.length() > maxLineLength) { os << NEW_LINE_SEQUENCE; pos = NEW_LINE_SEQUENCE_LENGTH; } - os << m_name << "="; - pos += m_name.length() + 1; - - generateValue(os, maxLineLength, pos, newLinePos); -} - - -void parameter::generateValue(utility::outputStream& os, const string::size_type /* maxLineLength */, - const string::size_type curLinePos, string::size_type* newLinePos) const -{ - // NOTE: This default implementation does not support parameter - // values that span on several lines ('defaultParameter' can do - // that, following rules specified in RFC-2231). - - std::ostringstream valueStream; - utility::outputStreamAdapter valueStreamV(valueStream); - - getValue().generate(valueStreamV, lineLengthLimits::infinite, 0, NULL); + bool needQuoting = false; + string::size_type valueLength = 0; - const string value(valueStream.str()); - - std::ostringstream ss; - string::const_iterator start = value.begin(); - bool quoted = false; - - for (string::const_iterator i = value.begin() ; i != value.end() ; ++i) + for (string::size_type i = 0 ; (i < value.length()) && (pos + valueLength < maxLineLength - 4) ; ++i, ++valueLength) { - switch (*i) + switch (value[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': @@ -155,21 +290,194 @@ void parameter::generateValue(utility::outputStream& os, const string::size_type case '?': case '=': - quoted = true; + needQuoting = true; break; } } - if (start != value.end()) - ss << string(start, value.end()); + const bool cutValue = (valueLength != value.length()); // has the value been cut? - if (quoted) - os << "\"" << ss.str() << "\""; + if (needQuoting) + { + os << name << "=\""; + pos += name.length() + 2; + } else - os << ss.str(); + { + os << name << "="; + pos += name.length() + 1; + } + + bool extended = false; + + for (string::size_type i = 0 ; (i < value.length()) && (pos < maxLineLength - 4) ; ++i) + { + const char_t c = value[i]; + + if (/* needQuoting && */ (c == '"' || c == '\\')) // 'needQuoting' is implicit + { + os << '\\' << value[i]; // escape 'x' with '\x' + pos += 2; + } + else if (parserHelpers::isAscii(c)) + { + os << value[i]; + ++pos; + } + else + { + extended = true; + } + } + + if (needQuoting) + { + os << '"'; + ++pos; + } + + // Also generate an extended parameter if the value contains 8-bit characters + // or is too long for a single line + if (extended || cutValue) + { + os << ';'; + ++pos; + + /* RFC-2231 + * ======== + * + * Content-Type: message/external-body; access-type=URL; + * URL*0="ftp://"; + * URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" + * + * Content-Type: application/x-stuff; + * title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A + * + * Content-Type: application/x-stuff; + * title*0*=us-ascii'en'This%20is%20even%20more%20 + * title*1*=%2A%2A%2Afun%2A%2A%2A%20 + * title*2="isn't it!" + */ + + // Check whether there is enough space for the first section: + // parameter name, section identifier, charset and separators + // + at least 5 characters for the value + const string::size_type firstSectionLength = + name.length() + 4 /* *0*= */ + 2 /* '' */ + + m_value.getCharset().getName().length(); + + if (pos + firstSectionLength + 5 >= maxLineLength) + { + os << NEW_LINE_SEQUENCE; + pos = NEW_LINE_SEQUENCE_LENGTH; + } + + // Split text into multiple sections that fit on one line + int sectionCount = 0; + std::vector <string> sectionText; + + string currentSection; + string::size_type currentSectionLength = firstSectionLength; + + for (string::size_type i = 0 ; i < value.length() ; ++i) + { + // Check whether we should start a new line (taking into + // account the next character will be encoded = worst case) + if (currentSectionLength + 3 >= maxLineLength) + { + sectionText.push_back(currentSection); + sectionCount++; + + currentSection.clear(); + currentSectionLength = NEW_LINE_SEQUENCE_LENGTH + + name.length() + 6; + } + + // Output next character + const char_t c = value[i]; + bool encode = false; + + switch (c) + { + // special characters + case ' ': + case '\t': + case '\r': + case '\n': + case '"': + case ';': + case ',': + + encode = true; + break; + + default: + + encode = (!parserHelpers::isPrint(c) || + !parserHelpers::isAscii(c)); + + break; + } + + if (encode) // need encoding + { + const int h1 = static_cast <unsigned char>(c) / 16; + const int h2 = static_cast <unsigned char>(c) % 16; + + currentSection += '%'; + currentSection += "0123456789ABCDEF"[h1]; + currentSection += "0123456789ABCDEF"[h2]; + + pos += 3; + currentSectionLength += 3; + } + else + { + currentSection += value[i]; + + ++pos; + ++currentSectionLength; + } + } + + if (!currentSection.empty()) + { + sectionText.push_back(currentSection); + sectionCount++; + } + + // Output sections + for (int sectionNumber = 0 ; sectionNumber < sectionCount ; ++sectionNumber) + { + os << name; + + if (sectionCount != 1) // no section specifier when only a single one + { + os << '*'; + os << sectionNumber; + } + + os << "*="; + + if (sectionNumber == 0) + { + os << m_value.getCharset().getName(); + os << '\'' << /* No language */ '\''; + } + + os << sectionText[sectionNumber]; + + if (sectionNumber + 1 < sectionCount) + { + os << ';'; + os << NEW_LINE_SEQUENCE; + pos = NEW_LINE_SEQUENCE_LENGTH; + } + } + } if (newLinePos) - *newLinePos = curLinePos + ss.str().length() + 2; + *newLinePos = pos; } @@ -177,10 +485,11 @@ const std::vector <ref <const component> > parameter::getChildComponents() const { std::vector <ref <const component> > list; - list.push_back(getValueImp()); + list.push_back(ref <const component>::fromPtr(&m_value)); - return (list); + return list; } } // vmime + diff --git a/src/parameterFactory.cpp b/src/parameterFactory.cpp deleted file mode 100644 index ce183319..00000000 --- a/src/parameterFactory.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2005 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 -// 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., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - -#include "vmime/parameterFactory.hpp" -#include "vmime/exception.hpp" - -#include "vmime/standardParams.hpp" - - -namespace vmime -{ - - -parameterFactory::parameterFactory() -{ - // Register some default names - registerName <charsetParameter>("charset"); - registerName <dateParameter>("creation-date"); - registerName <dateParameter>("modification-date"); - registerName <dateParameter>("read-date"); -} - - -parameterFactory::~parameterFactory() -{ -} - - -parameterFactory* parameterFactory::getInstance() -{ - static parameterFactory instance; - return (&instance); -} - - -ref <parameter> parameterFactory::create - (const string& name, const string& value) -{ - const string lcName = utility::stringUtils::toLower(name); - - NameMap::const_iterator pos = m_nameMap.find(lcName); - ref <parameter> param; - - if (pos != m_nameMap.end()) - { - param = ((*pos).second)(); - } - else - { - param = registerer <defaultParameter>::creator(); - } - - param->m_name = name; - if (value != NULL_STRING) param->parse(value); - - return (param); -} - - -ref <parameter> parameterFactory::create(const string& name, const component& value) -{ - const string lcName = utility::stringUtils::toLower(name); - - NameMap::const_iterator pos = m_nameMap.find(lcName); - ref <parameter> param; - - if (pos != m_nameMap.end()) - { - param = ((*pos).second)(); - } - else - { - param = registerer <defaultParameter>::creator(); - } - - param->m_name = name; - param->setValue(value); - - return (param); -} - - -} // vmime diff --git a/src/parameterizedHeaderField.cpp b/src/parameterizedHeaderField.cpp index 096dd497..771fcbb1 100644 --- a/src/parameterizedHeaderField.cpp +++ b/src/parameterizedHeaderField.cpp @@ -22,7 +22,6 @@ // #include "vmime/parameterizedHeaderField.hpp" -#include "vmime/parameterFactory.hpp" #include "vmime/text.hpp" #include "vmime/parserHelpers.hpp" @@ -90,7 +89,7 @@ void parameterizedHeaderField::parse(const string& buffer, const string::size_ty while (p < pend && *p != ';') ++p; - getValue().parse(buffer, start, position + (p - pstart)); + getValue()->parse(buffer, start, position + (p - pstart)); removeAllParameters(); @@ -295,7 +294,7 @@ void parameterizedHeaderField::parse(const string& buffer, const string::size_ty const paramInfo& info = (*it).second; // Append this parameter to the list - ref <parameter> param = parameterFactory::getInstance()->create((*it).first); + ref <parameter> param = vmime::create <parameter>((*it).first); param->parse(info.value); param->setParsedBounds(info.start, info.end); @@ -404,7 +403,7 @@ ref <parameter> parameterizedHeaderField::getParameter(const string& paramName) // If no parameter with this name can be found, create a new one if (pos == end) { - ref <parameter> param = parameterFactory::getInstance()->create(paramName); + ref <parameter> param = vmime::create <parameter>(paramName); appendParameter(param); diff --git a/src/path.cpp b/src/path.cpp index 57cab716..7fefc10d 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -41,7 +41,7 @@ path::path(const string& localPart, const string& domain) path::path(const path& p) - : component(), m_localPart(p.m_localPart), m_domain(p.m_domain) + : headerFieldValue(), m_localPart(p.m_localPart), m_domain(p.m_domain) { } diff --git a/src/plainTextPart.cpp b/src/plainTextPart.cpp index 45a66e36..ad048c2b 100644 --- a/src/plainTextPart.cpp +++ b/src/plainTextPart.cpp @@ -25,6 +25,8 @@ #include "vmime/header.hpp" #include "vmime/exception.hpp" +#include "vmime/contentTypeField.hpp" + #include "vmime/emptyContentHandler.hpp" @@ -63,7 +65,7 @@ void plainTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const // Set header fields part->getHeader()->ContentType()->setValue(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); - part->getHeader()->ContentType()->setCharset(m_charset); + part->getHeader()->ContentType().dynamicCast <contentTypeField>()->setCharset(m_charset); part->getHeader()->ContentTransferEncoding()->setValue(encoding(encodingTypes::QUOTED_PRINTABLE)); // Set contents @@ -83,11 +85,11 @@ void plainTextPart::parse(const bodyPart& /* message */, m_charset = ctf.getCharset(); } - catch (exceptions::no_such_field) + catch (exceptions::no_such_field&) { // No "Content-type" field. } - catch (exceptions::no_such_parameter) + catch (exceptions::no_such_parameter&) { // No "charset" parameter. } diff --git a/src/relay.cpp b/src/relay.cpp index cddd231b..88a9097e 100644 --- a/src/relay.cpp +++ b/src/relay.cpp @@ -38,7 +38,7 @@ relay::relay() relay::relay(const relay& r) - : component() + : headerFieldValue() { copyFrom(r); } diff --git a/src/text.cpp b/src/text.cpp index 51593763..8436c44b 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -36,7 +36,7 @@ text::text() text::text(const text& t) - : component() + : headerFieldValue() { copyFrom(t); } @@ -383,4 +383,18 @@ const std::vector <ref <const component> > text::getChildComponents() const } +const string text::getWholeBuffer() const +{ + string res; + + for (std::vector <ref <word> >::const_iterator it = m_words.begin() ; + it != m_words.end() ; ++it) + { + res += (*it)->getBuffer(); + } + + return res; +} + + } // vmime diff --git a/src/typeAdapter.cpp b/src/typeAdapter.cpp deleted file mode 100644 index 1646edc2..00000000 --- a/src/typeAdapter.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2005 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 -// 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., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules is making -// a combined work based on this library. Thus, the terms and conditions of -// the GNU General Public License cover the whole combination. -// - - -#include "vmime/typeAdapter.hpp" - - -namespace vmime -{ - - -#if (!defined(__GNUC__) || ((__GNUC__ >= 3) && (__GNUC_MINOR__ >= 3))) && !defined(_MSC_VER) - -template <> -void typeAdapter <string>::parse(const string& buffer, const string::size_type position, - const string::size_type end, string::size_type* newPosition) -{ - m_value = string(buffer.begin() + position, buffer.begin() + end); - - setParsedBounds(position, end); - - if (newPosition) - *newPosition = end; -} - -#endif // (!defined(__GNUC__) || ((__GNUC__ >= 3) && (__GNUC_MINOR__ >= 3))) && !defined(_MSC_VER) - - -} // vmime diff --git a/src/word.cpp b/src/word.cpp index f4fc89d2..ccb5d554 100644 --- a/src/word.cpp +++ b/src/word.cpp @@ -44,7 +44,7 @@ word::word() word::word(const word& w) - : component(), m_buffer(w.m_buffer), m_charset(w.m_charset) + : headerFieldValue(), m_buffer(w.m_buffer), m_charset(w.m_charset) { } |