aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--SConstruct3
-rw-r--r--src/addressList.cpp2
-rw-r--r--src/attachmentHelper.cpp12
-rw-r--r--src/base.cpp2
-rw-r--r--src/body.cpp15
-rw-r--r--src/bodyPartAttachment.cpp11
-rw-r--r--src/contentDisposition.cpp2
-rw-r--r--src/contentDispositionField.cpp30
-rw-r--r--src/contentTypeField.cpp19
-rw-r--r--src/dateTime.cpp2
-rw-r--r--src/defaultAttachment.cpp2
-rw-r--r--src/defaultParameter.cpp437
-rw-r--r--src/encoding.cpp2
-rw-r--r--src/fileAttachment.cpp5
-rw-r--r--src/headerField.cpp47
-rw-r--r--src/headerFieldFactory.cpp105
-rw-r--r--src/htmlTextPart.cpp56
-rw-r--r--src/mailboxField.cpp19
-rw-r--r--src/mailboxList.cpp2
-rw-r--r--src/mdn/MDNHelper.cpp58
-rw-r--r--src/mdn/receivedMDNInfos.cpp7
-rw-r--r--src/messageBuilder.cpp1
-rw-r--r--src/messageId.cpp2
-rw-r--r--src/messageIdSequence.cpp2
-rw-r--r--src/messageParser.cpp46
-rw-r--r--src/misc/importanceHelper.cpp15
-rw-r--r--src/net/transport.cpp28
-rw-r--r--src/parameter.cpp423
-rw-r--r--src/parameterFactory.cpp103
-rw-r--r--src/parameterizedHeaderField.cpp7
-rw-r--r--src/path.cpp2
-rw-r--r--src/plainTextPart.cpp8
-rw-r--r--src/relay.cpp2
-rw-r--r--src/text.cpp16
-rw-r--r--src/word.cpp2
-rw-r--r--tests/misc/importanceHelperTest.cpp4
-rw-r--r--tests/parser/parameterTest.cpp59
-rw-r--r--vmime/address.hpp4
-rw-r--r--vmime/addressList.hpp4
-rw-r--r--vmime/bodyPartAttachment.hpp3
-rw-r--r--vmime/contentDisposition.hpp4
-rw-r--r--vmime/contentDispositionField.hpp59
-rw-r--r--vmime/contentTypeField.hpp22
-rw-r--r--vmime/dateTime.hpp4
-rw-r--r--vmime/defaultParameter.hpp77
-rw-r--r--vmime/disposition.hpp4
-rw-r--r--vmime/encoding.hpp4
-rw-r--r--vmime/fileAttachment.hpp2
-rw-r--r--vmime/header.hpp71
-rw-r--r--vmime/headerField.hpp40
-rw-r--r--vmime/headerFieldFactory.hpp52
-rw-r--r--vmime/headerFieldValue.hpp (renamed from src/typeAdapter.cpp)26
-rw-r--r--vmime/mailboxField.hpp16
-rw-r--r--vmime/mailboxList.hpp2
-rw-r--r--vmime/mdn/MDNHelper.hpp2
-rw-r--r--vmime/mdn/receivedMDNInfos.hpp3
-rw-r--r--vmime/mdn/sendableMDNInfos.hpp2
-rw-r--r--vmime/mediaType.hpp4
-rw-r--r--vmime/messageId.hpp4
-rw-r--r--vmime/messageIdSequence.hpp2
-rw-r--r--vmime/messageParser.hpp4
-rw-r--r--vmime/net/message.hpp1
-rw-r--r--vmime/net/pop3/POP3Store.hpp1
-rw-r--r--vmime/net/transport.hpp2
-rw-r--r--vmime/parameter.hpp75
-rw-r--r--vmime/parameterFactory.hpp97
-rw-r--r--vmime/parameterizedHeaderField.hpp5
-rw-r--r--vmime/path.hpp4
-rw-r--r--vmime/relay.hpp4
-rw-r--r--vmime/text.hpp11
-rw-r--r--vmime/typeAdapter.hpp159
-rw-r--r--vmime/vmime.hpp3
-rw-r--r--vmime/word.hpp4
74 files changed, 1061 insertions, 1282 deletions
diff --git a/ChangeLog b/ChangeLog
index 78cbf785..8367a451 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,10 @@
VERSION 0.7.2cvs
================
+2005-11-05 Vincent Richard <[email protected]>
+
+ * Refactored header field values and parameters.
+
2005-10-19 Vincent Richard <[email protected]>
* charsetConverter.{hpp|cpp}: new object 'charsetConverter' for converting
diff --git a/SConstruct b/SConstruct
index 9ae6da73..000fee3e 100644
--- a/SConstruct
+++ b/SConstruct
@@ -91,7 +91,6 @@ libvmime_sources = [
'contentTypeField.cpp', 'contentTypeField.hpp',
'dateTime.cpp', 'dateTime.hpp',
'defaultAttachment.cpp', 'defaultAttachment.hpp',
- 'defaultParameter.cpp', 'defaultParameter.hpp',
'disposition.cpp', 'disposition.hpp',
'emptyContentHandler.cpp', 'emptyContentHandler.hpp',
'encoder.cpp', 'encoder.hpp',
@@ -126,7 +125,6 @@ libvmime_sources = [
'options.cpp', 'options.hpp',
'path.cpp', 'path.hpp',
'parameter.cpp', 'parameter.hpp',
- 'parameterFactory.cpp', 'parameterFactory.hpp',
'parameterizedHeaderField.cpp', 'parameterizedHeaderField.hpp',
'parserHelpers.hpp',
'plainTextPart.cpp', 'plainTextPart.hpp',
@@ -140,7 +138,6 @@ libvmime_sources = [
'text.cpp', 'text.hpp',
'textPartFactory.cpp', 'textPartFactory.hpp',
'textPart.hpp',
- 'typeAdapter.cpp', 'typeAdapter.hpp',
'types.hpp',
'word.cpp', 'word.hpp',
'vmime.hpp',
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/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)
{
}
diff --git a/tests/misc/importanceHelperTest.cpp b/tests/misc/importanceHelperTest.cpp
index 9c1ee670..60af1cde 100644
--- a/tests/misc/importanceHelperTest.cpp
+++ b/tests/misc/importanceHelperTest.cpp
@@ -78,10 +78,10 @@ VMIME_TEST_SUITE_BEGIN
vmime::misc::importanceHelper::setImportanceHeader(hdr, i);
VASSERT_NO_THROW("1", hdr->findField("Importance"));
- VASSERT_EQ("2", ImportanceValue, hdr->findField("Importance")->getValue().generate());
+ VASSERT_EQ("2", ImportanceValue, hdr->findField("Importance")->getValue()->generate());
VASSERT_NO_THROW("3", hdr->findField("X-Priority"));
- VASSERT_EQ("4", XPriorityValue, hdr->findField("X-Priority")->getValue().generate());
+ VASSERT_EQ("4", XPriorityValue, hdr->findField("X-Priority")->getValue()->generate());
}
void testSetImportance1()
diff --git a/tests/parser/parameterTest.cpp b/tests/parser/parameterTest.cpp
index 5f64a7c0..95cdf626 100644
--- a/tests/parser/parameterTest.cpp
+++ b/tests/parser/parameterTest.cpp
@@ -33,40 +33,30 @@ VMIME_TEST_SUITE_BEGIN
VMIME_TEST_LIST_BEGIN
VMIME_TEST(testParse)
VMIME_TEST(testGenerate)
+ VMIME_TEST(testNonStandardEncodedParam)
VMIME_TEST_LIST_END
// HACK: parameterizedHeaderField constructor is private
class parameterizedHeaderField : public vmime::parameterizedHeaderField
{
- private:
-
- vmime::ref <vmime::typeAdapter <vmime::string> > m_value;
-
public:
parameterizedHeaderField()
- : headerField("F"),
- m_value(vmime::create <vmime::typeAdapter <vmime::string> >("X"))
+ : headerField("F")
{
+ setValue(vmime::headerFieldFactory::getInstance()->createValue(getName()));
+ setValue(vmime::word("X"));
}
-
- const vmime::component& getValue() const { return *m_value; }
- vmime::component& getValue() { return *m_value; }
-
- void setValue(const vmime::component&) { /* Do nothing */ }
-
- const vmime::ref <const vmime::component> getValueImp() const { return m_value; }
- vmime::ref <vmime::component> getValueImp() { return m_value; }
};
#define PARAM_VALUE(p, n) (p.getParameterAt(n)->getValue().generate())
#define PARAM_NAME(p, n) (p.getParameterAt(n)->getName())
-#define PARAM_CHARSET(p, n) ( \
- (p.getParameterAt(n).staticCast <vmime::defaultParameter>())->getValue().getCharset().generate())
-#define PARAM_BUFFER(p, n) ( \
- (p.getParameterAt(n).staticCast <vmime::defaultParameter>())->getValue().getBuffer())
+#define PARAM_CHARSET(p, n) \
+ (p.getParameterAt(n)->getValue().getCharset().generate())
+#define PARAM_BUFFER(p, n) \
+ (p.getParameterAt(n)->getValue().getBuffer())
void testParse()
@@ -201,32 +191,32 @@ VMIME_TEST_SUITE_BEGIN
{
// Simple parameter/value
parameterizedHeaderField p1;
- p1.appendParameter(vmime::parameterFactory::getInstance()->create("param1", "value1"));
+ p1.appendParameter(vmime::create <vmime::parameter>("param1", "value1"));
VASSERT_EQ("1", "F: X; param1=value1", p1.generate());
// Value that needs quoting (1/2)
parameterizedHeaderField p2a;
- p2a.appendParameter(vmime::parameterFactory::getInstance()->create("param1", "value1a;value1b"));
+ p2a.appendParameter(vmime::create <vmime::parameter>("param1", "value1a;value1b"));
VASSERT_EQ("2a", "F: X; param1=\"value1a;value1b\"", p2a.generate());
// Value that needs quoting (2/2)
parameterizedHeaderField p2b;
- p2b.appendParameter(vmime::parameterFactory::getInstance()->create("param1", "va\\lue\"1"));
+ p2b.appendParameter(vmime::create <vmime::parameter>("param1", "va\\lue\"1"));
VASSERT_EQ("2b", "F: X; param1=\"va\\\\lue\\\"1\"", p2b.generate());
// Extended parameter with charset specifier
parameterizedHeaderField p3;
- p3.appendParameter(vmime::parameterFactory::getInstance()->create("param1",
+ p3.appendParameter(vmime::create <vmime::parameter>("param1",
vmime::word("value 1\xe9", vmime::charset("charset"))));
VASSERT_EQ("3", "F: X; param1=\"value 1\";param1*=charset''value%201%E9", p3.generate());
// Value that spans on multiple lines
parameterizedHeaderField p4;
- p4.appendParameter(vmime::parameterFactory::getInstance()->create("param1",
+ p4.appendParameter(vmime::create <vmime::parameter>("param1",
vmime::word("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
vmime::charset("charset"))));
@@ -241,5 +231,28 @@ VMIME_TEST_SUITE_BEGIN
"param1*6*=WXYZ", p4.generate(25)); // max line length = 25
}
+ void testNonStandardEncodedParam()
+ {
+ // 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?="
+
+ parameterizedHeaderField p1;
+ p1.parse("image/png; name=\"=?us-ascii?Q?Logo_VMime=2Epng?=\"");
+
+ VASSERT_EQ("1.1", 1, p1.getParameterCount());
+ VASSERT_EQ("1.2", "name", PARAM_NAME(p1, 0));
+ VASSERT_EQ("1.3", "Logo VMime.png", PARAM_VALUE(p1, 0));
+
+ parameterizedHeaderField p2;
+ p2.parse("image/png; name=\"Logo =?us-ascii?Q?VMime=2Epng?=\"");
+
+ VASSERT_EQ("2.1", 1, p2.getParameterCount());
+ VASSERT_EQ("2.2", "name", PARAM_NAME(p2, 0));
+ VASSERT_EQ("2.3", "Logo VMime.png", PARAM_VALUE(p2, 0));
+ }
+
VMIME_TEST_SUITE_END
diff --git a/vmime/address.hpp b/vmime/address.hpp
index 6e73e3a1..5fb3c99d 100644
--- a/vmime/address.hpp
+++ b/vmime/address.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
namespace vmime
@@ -39,7 +39,7 @@ namespace vmime
* and mailboxGroup classes.
*/
-class address : public component
+class address : public headerFieldValue
{
friend class addressList;
diff --git a/vmime/addressList.hpp b/vmime/addressList.hpp
index a48aabbe..4b4e43d0 100644
--- a/vmime/addressList.hpp
+++ b/vmime/addressList.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
#include "vmime/address.hpp"
@@ -41,7 +41,7 @@ class mailboxList;
/** A list of addresses.
*/
-class addressList : public component
+class addressList : public headerFieldValue
{
public:
diff --git a/vmime/bodyPartAttachment.hpp b/vmime/bodyPartAttachment.hpp
index c079b0d6..7ac1914e 100644
--- a/vmime/bodyPartAttachment.hpp
+++ b/vmime/bodyPartAttachment.hpp
@@ -27,6 +27,9 @@
#include "vmime/attachment.hpp"
+#include "vmime/contentDispositionField.hpp"
+#include "vmime/contentTypeField.hpp"
+
namespace vmime
{
diff --git a/vmime/contentDisposition.hpp b/vmime/contentDisposition.hpp
index 6c4a9cd0..fa3cf7f9 100644
--- a/vmime/contentDisposition.hpp
+++ b/vmime/contentDisposition.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
namespace vmime
@@ -36,7 +36,7 @@ namespace vmime
/** Content disposition (basic type).
*/
-class contentDisposition : public component
+class contentDisposition : public headerFieldValue
{
public:
diff --git a/vmime/contentDispositionField.hpp b/vmime/contentDispositionField.hpp
index e7f79296..e02f64fa 100644
--- a/vmime/contentDispositionField.hpp
+++ b/vmime/contentDispositionField.hpp
@@ -26,7 +26,6 @@
#include "vmime/parameterizedHeaderField.hpp"
-#include "vmime/genericField.hpp"
#include "vmime/contentDisposition.hpp"
#include "vmime/dateTime.hpp"
@@ -37,7 +36,7 @@ namespace vmime
{
-class contentDispositionField : public parameterizedHeaderField, public genericField <contentDisposition>
+class contentDispositionField : public parameterizedHeaderField
{
friend class vmime::creator; // create ref
@@ -48,19 +47,69 @@ protected:
public:
- const datetime& getCreationDate() const;
+ /** Return the value of the "creation-date" parameter.
+ *
+ * @return value of the "creation-date" parameter
+ * @throw exceptions::no_such_parameter if the parameter does not exist
+ */
+ const datetime getCreationDate() const;
+
+ /** Set the value of the "creation-date" parameter.
+ *
+ * @param creationDate new value for the "creation-date" parameter
+ */
void setCreationDate(const datetime& creationDate);
- const datetime& getModificationDate() const;
+ /** Return the value of the "modification-date" parameter.
+ *
+ * @return value of the "modification-date" parameter
+ * @throw exceptions::no_such_parameter if the parameter does not exist
+ */
+ const datetime getModificationDate() const;
+
+ /** Set the value of the "modification-date" parameter.
+ *
+ * @param modificationDate new value for the "modification-date" parameter
+ */
void setModificationDate(const datetime& modificationDate);
- const datetime& getReadDate() const;
+ /** Return the value of the "read-date" parameter.
+ *
+ * @return value of the "read-date" parameter
+ * @throw exceptions::no_such_parameter if the parameter does not exist
+ */
+ const datetime getReadDate() const;
+
+ /** Set the value of the "read-date" parameter.
+ *
+ * @param readDate new value for the "read-date" parameter
+ */
void setReadDate(const datetime& readDate);
+ /** Return the value of the "filename" parameter.
+ *
+ * @return value of the "filename" parameter
+ * @throw exceptions::no_such_parameter if the parameter does not exist
+ */
const word getFilename() const;
+
+ /** Set the value of the "filename" parameter.
+ *
+ * @param filename new value for the "filename" parameter
+ */
void setFilename(const word& filename);
+ /** Return the value of the "size" parameter.
+ *
+ * @return value of the "size" parameter
+ * @throw exceptions::no_such_parameter if the parameter does not exist
+ */
const string getSize() const;
+
+ /** Set the value of the "size" parameter.
+ *
+ * @param size new value for the "size" parameter
+ */
void setSize(const string& size);
};
diff --git a/vmime/contentTypeField.hpp b/vmime/contentTypeField.hpp
index b66f20d0..c78642f1 100644
--- a/vmime/contentTypeField.hpp
+++ b/vmime/contentTypeField.hpp
@@ -26,7 +26,6 @@
#include "vmime/parameterizedHeaderField.hpp"
-#include "vmime/genericField.hpp"
#include "vmime/mediaType.hpp"
#include "vmime/charset.hpp"
@@ -36,7 +35,7 @@ namespace vmime
{
-class contentTypeField : public parameterizedHeaderField, public genericField <mediaType>
+class contentTypeField : public parameterizedHeaderField
{
friend class vmime::creator; // create ref
@@ -47,25 +46,33 @@ protected:
public:
- /** Return the value of the "boundary" parameter.
+ /** Return the value of the "boundary" parameter. Boundary is a
+ * random string used to separate body parts.
*
* @return value of the "boundary" parameter
+ * @throw exceptions::no_such_parameter if the parameter does not exist
*/
const string getBoundary() const;
- /** Set the value of the "boundary" parameter.
+ /** Set the value of the "boundary" parameter. Boundary is a
+ * random string used to separate body parts. Normally, the
+ * boundary is generated automatically by VMime, you should
+ * not need to call this.
*
* @param boundary new value for the "boundary" parameter
*/
void setBoundary(const string& boundary);
- /** Return the value of the "charset" parameter.
+ /** Return the value of the "charset" parameter. It specifies the
+ * charset used in the body part contents.
*
* @return value of the "charset" parameter
+ * @throw exceptions::no_such_parameter if the parameter does not exist
*/
- const charset& getCharset() const;
+ const charset getCharset() const;
- /** Set the value of the "charset" parameter.
+ /** Set the value of the "charset" parameter. It specifies the
+ * charset used in the body part contents.
*
* @param ch new value for the "charset" parameter
*/
@@ -74,6 +81,7 @@ public:
/** Return the value of the "report-type" parameter (RFC-1892).
*
* @return value of the "report-type" parameter
+ * @throw exceptions::no_such_parameter if the parameter does not exist
*/
const string getReportType() const;
diff --git a/vmime/dateTime.hpp b/vmime/dateTime.hpp
index 5f2499ce..ffc17bde 100644
--- a/vmime/dateTime.hpp
+++ b/vmime/dateTime.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
#include <ctime>
@@ -38,7 +38,7 @@ namespace vmime
/** Date and time (basic type).
*/
-class datetime : public component
+class datetime : public headerFieldValue
{
public:
diff --git a/vmime/defaultParameter.hpp b/vmime/defaultParameter.hpp
deleted file mode 100644
index a6546a4b..00000000
--- a/vmime/defaultParameter.hpp
+++ /dev/null
@@ -1,77 +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.
-//
-
-#ifndef VMIME_DEFAULTPARAMETER_HPP_INCLUDED
-#define VMIME_DEFAULTPARAMETER_HPP_INCLUDED
-
-
-#include "vmime/parameter.hpp"
-#include "vmime/parameterFactory.hpp"
-
-#include "vmime/word.hpp"
-
-
-namespace vmime
-{
-
-
-/** Default parameter implementation (with support for RFC-2231).
- */
-
-class defaultParameter : public parameter
-{
- friend class vmime::creator; // create ref
-
-protected:
-
- defaultParameter();
-
-public:
-
- defaultParameter& operator=(const defaultParameter& other);
-
- const word& getValue() const;
- word& getValue();
-
- void setValue(const word& value);
- void setValue(const component& value);
-
- void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
- void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
-
-private:
-
- void parse(const std::vector <valueChunk>& chunks);
-
- const ref <const component> getValueImp() const;
- const ref <component> getValueImp();
-
-
- ref <word> m_value;
-};
-
-
-} // vmime
-
-
-#endif // VMIME_DEFAULTPARAMETER_HPP_INCLUDED
diff --git a/vmime/disposition.hpp b/vmime/disposition.hpp
index 03d476db..b98b558c 100644
--- a/vmime/disposition.hpp
+++ b/vmime/disposition.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
#include <vector>
@@ -38,7 +38,7 @@ namespace vmime
/** Disposition - from RFC-3798 (basic type).
*/
-class disposition : public component
+class disposition : public headerFieldValue
{
public:
diff --git a/vmime/encoding.hpp b/vmime/encoding.hpp
index 692585b0..4308de05 100644
--- a/vmime/encoding.hpp
+++ b/vmime/encoding.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
#include "vmime/encoder.hpp"
@@ -40,7 +40,7 @@ class contentHandler;
/** Content encoding (basic type).
*/
-class encoding : public component
+class encoding : public headerFieldValue
{
public:
diff --git a/vmime/fileAttachment.hpp b/vmime/fileAttachment.hpp
index 3fb24ebf..785690db 100644
--- a/vmime/fileAttachment.hpp
+++ b/vmime/fileAttachment.hpp
@@ -27,6 +27,8 @@
#include "vmime/defaultAttachment.hpp"
+#include "vmime/dateTime.hpp"
+
namespace vmime
{
diff --git a/vmime/header.hpp b/vmime/header.hpp
index e7a834df..bb806fc7 100644
--- a/vmime/header.hpp
+++ b/vmime/header.hpp
@@ -32,13 +32,6 @@
#include "vmime/headerField.hpp"
#include "vmime/headerFieldFactory.hpp"
-#include "vmime/mailboxField.hpp"
-#include "vmime/contentTypeField.hpp"
-#include "vmime/contentDispositionField.hpp"
-
-#include "vmime/standardFields.hpp"
-#include "vmime/standardParams.hpp"
-
namespace vmime
{
@@ -61,38 +54,38 @@ public:
header();
~header();
-#define FIELD_ACCESS(methodName, fieldName, type) \
- ref <type> methodName() { return getField(fields::fieldName).dynamicCast <type>(); } \
- ref <const type> methodName() const { return findField(fields::fieldName).dynamicCast <const type>(); }
-
- FIELD_ACCESS(From, FROM, mailboxField)
- FIELD_ACCESS(Sender, SENDER, mailboxField)
- FIELD_ACCESS(ReplyTo, REPLY_TO, mailboxField)
- FIELD_ACCESS(DeliveredTo, DELIVERED_TO, mailboxField)
- FIELD_ACCESS(InReplyTo, IN_REPLY_TO, messageIdSequenceField)
- FIELD_ACCESS(ReturnPath, RETURN_PATH, pathField)
- FIELD_ACCESS(References, REFERENCES, messageIdSequenceField)
-
- FIELD_ACCESS(To, TO, addressListField)
- FIELD_ACCESS(Cc, CC, addressListField)
- FIELD_ACCESS(Bcc, BCC, addressListField)
- FIELD_ACCESS(Date, DATE, dateField)
- FIELD_ACCESS(Subject, SUBJECT, textField)
- FIELD_ACCESS(Organization, ORGANIZATION, textField)
- FIELD_ACCESS(UserAgent, USER_AGENT, textField)
-
- FIELD_ACCESS(ContentType, CONTENT_TYPE, contentTypeField)
- FIELD_ACCESS(ContentDescription, CONTENT_DESCRIPTION, textField)
- FIELD_ACCESS(ContentTransferEncoding, CONTENT_TRANSFER_ENCODING, contentEncodingField)
- FIELD_ACCESS(MimeVersion, MIME_VERSION, defaultField)
- FIELD_ACCESS(ContentDisposition, CONTENT_DISPOSITION, contentDispositionField)
- FIELD_ACCESS(ContentId, CONTENT_ID, messageIdField)
- FIELD_ACCESS(MessageId, MESSAGE_ID, messageIdField)
- FIELD_ACCESS(ContentLocation, CONTENT_LOCATION, defaultField)
-
- FIELD_ACCESS(OriginalMessageId, ORIGINAL_MESSAGE_ID, messageIdField)
- FIELD_ACCESS(Disposition, DISPOSITION, dispositionField)
- FIELD_ACCESS(DispositionNotificationTo, DISPOSITION_NOTIFICATION_TO, mailboxListField)
+#define FIELD_ACCESS(methodName, fieldName) \
+ ref <headerField> methodName() { return getField(fields::fieldName); } \
+ ref <const headerField> methodName() const { return findField(fields::fieldName); }
+
+ FIELD_ACCESS(From, FROM)
+ FIELD_ACCESS(Sender, SENDER)
+ FIELD_ACCESS(ReplyTo, REPLY_TO)
+ FIELD_ACCESS(DeliveredTo, DELIVERED_TO)
+ FIELD_ACCESS(InReplyTo, IN_REPLY_TO)
+ FIELD_ACCESS(ReturnPath, RETURN_PATH)
+ FIELD_ACCESS(References, REFERENCES)
+
+ FIELD_ACCESS(To, TO)
+ FIELD_ACCESS(Cc, CC)
+ FIELD_ACCESS(Bcc, BCC)
+ FIELD_ACCESS(Date, DATE)
+ FIELD_ACCESS(Subject, SUBJECT)
+ FIELD_ACCESS(Organization, ORGANIZATION)
+ FIELD_ACCESS(UserAgent, USER_AGENT)
+
+ FIELD_ACCESS(ContentType, CONTENT_TYPE)
+ FIELD_ACCESS(ContentDescription, CONTENT_DESCRIPTION)
+ FIELD_ACCESS(ContentTransferEncoding, CONTENT_TRANSFER_ENCODING)
+ FIELD_ACCESS(MimeVersion, MIME_VERSION)
+ FIELD_ACCESS(ContentDisposition, CONTENT_DISPOSITION)
+ FIELD_ACCESS(ContentId, CONTENT_ID)
+ FIELD_ACCESS(MessageId, MESSAGE_ID)
+ FIELD_ACCESS(ContentLocation, CONTENT_LOCATION)
+
+ FIELD_ACCESS(OriginalMessageId, ORIGINAL_MESSAGE_ID)
+ FIELD_ACCESS(Disposition, DISPOSITION)
+ FIELD_ACCESS(DispositionNotificationTo, DISPOSITION_NOTIFICATION_TO)
#undef FIELD_ACCESS
diff --git a/vmime/headerField.hpp b/vmime/headerField.hpp
index 9047a2ac..27d53f0c 100644
--- a/vmime/headerField.hpp
+++ b/vmime/headerField.hpp
@@ -27,6 +27,7 @@
#include "vmime/base.hpp"
#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
namespace vmime
@@ -41,8 +42,12 @@ class headerField : public component
friend class headerFieldFactory;
friend class header;
+ friend class vmime::creator; // create ref
+
protected:
+ // Protected constructor to prevent the user from creating
+ // new objects without using 'headerFieldFactory'
headerField();
headerField(const string& fieldName);
@@ -56,6 +61,12 @@ public:
const std::vector <ref <const component> > getChildComponents() const;
+ /** Sets the name of this field.
+ *
+ * @param name field name (eg: "From" or "X-MyField").
+ */
+ void setName(const string& name);
+
/** Return the name of this field.
*
* @return field name
@@ -73,21 +84,32 @@ public:
*
* @return read-only value object
*/
- virtual const component& getValue() const = 0;
+ virtual ref <const headerFieldValue> getValue() const;
/** Return the value object attached to this field.
*
* @return value object
*/
- virtual component& getValue() = 0;
+ virtual ref <headerFieldValue> getValue();
/** Set the value of this field.
*
- * @throw std::bad_cast_exception if the value type is
- * incompatible with the header field type
- * @param value value object
+ * @param value new value
+ */
+ virtual void setValue(ref <headerFieldValue> value);
+
+ /** Set the value of this field by cloning the specified value.
+ *
+ * @param value new value
+ */
+ virtual void setValueConst(ref <const headerFieldValue> value);
+
+ /** Set the value of this field (reference version).
+ * The value will be cloned.
+ *
+ * @param value new value
*/
- virtual void setValue(const component& value) = 0;
+ virtual void setValue(const headerFieldValue& value);
/** Set the value of this field given a character string.
*
@@ -104,15 +126,11 @@ public:
protected:
- virtual const ref <const component> getValueImp() const = 0;
- virtual ref <component> getValueImp() = 0;
-
-private:
-
static ref <headerField> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
string m_name;
+ ref <headerFieldValue> m_value;
};
diff --git a/vmime/headerFieldFactory.hpp b/vmime/headerFieldFactory.hpp
index 2099e341..04867547 100644
--- a/vmime/headerFieldFactory.hpp
+++ b/vmime/headerFieldFactory.hpp
@@ -33,6 +33,9 @@ namespace vmime
{
+/** Creates header field and header field value objects.
+ */
+
class headerFieldFactory
{
protected:
@@ -45,17 +48,23 @@ protected:
NameMap m_nameMap;
+ typedef ref <headerFieldValue> (*ValueAllocFunc)(void);
+ typedef std::map <string, ValueAllocFunc> ValueMap;
+
+ ValueMap m_valueMap;
+
public:
static headerFieldFactory* getInstance();
#ifndef VMIME_BUILDING_DOC
- template <class TYPE>
+ // TYPE must inherit from BASE_TYPE
+ template <class BASE_TYPE, class TYPE>
class registerer
{
public:
- static ref <headerField> creator()
+ static ref <BASE_TYPE> creator()
{
// Allocate a new object
return vmime::create <TYPE>();
@@ -64,14 +73,49 @@ public:
#endif // VMIME_BUILDING_DOC
+ /** Register a field type.
+ *
+ * @param T field class (must inherit from 'headerField')
+ * @param name field name (eg. "X-MyField")
+ */
template <class T>
- void registerName(const string& name)
+ void registerField(const string& name)
{
m_nameMap.insert(NameMap::value_type
- (utility::stringUtils::toLower(name), &registerer<T>::creator));
+ (utility::stringUtils::toLower(name),
+ &registerer <headerField, T>::creator));
+ }
+
+ /** Register a field value type.
+ *
+ * @param T value class (must inherit from 'headerFieldValue')
+ * @param name field name
+ */
+ template <class T>
+ void registerFieldValue(const string& name)
+ {
+ m_valueMap.insert(ValueMap::value_type
+ (utility::stringUtils::toLower(name),
+ &registerer <headerFieldValue, T>::creator));
}
+ /** Create a new field object for the specified field name.
+ * If the field name has not been registered, a default type
+ * is used.
+ *
+ * @param name field name
+ * @param body string that will be parsed to initialize
+ * the value of the field
+ * @return a new field object
+ */
ref <headerField> create(const string& name, const string& body = NULL_STRING);
+
+ /** Create a new field value for the specified field.
+ *
+ * @param fieldName name of the field for which to create value
+ * @return a new value object for the field
+ */
+ ref <headerFieldValue> createValue(const string& fieldName);
};
diff --git a/src/typeAdapter.cpp b/vmime/headerFieldValue.hpp
index 1646edc2..ed26bb51 100644
--- a/src/typeAdapter.cpp
+++ b/vmime/headerFieldValue.hpp
@@ -21,29 +21,31 @@
// the GNU General Public License cover the whole combination.
//
+#ifndef VMIME_HEADERFIELDVALUE_HPP_INCLUDED
+#define VMIME_HEADERFIELDVALUE_HPP_INCLUDED
-#include "vmime/typeAdapter.hpp"
+
+#include "vmime/base.hpp"
+#include "vmime/component.hpp"
namespace vmime
{
-#if (!defined(__GNUC__) || ((__GNUC__ >= 3) && (__GNUC_MINOR__ >= 3))) && !defined(_MSC_VER)
+/** Base class for all classes that can be used as a value
+ * for a header field.
+ */
-template <>
-void typeAdapter <string>::parse(const string& buffer, const string::size_type position,
- const string::size_type end, string::size_type* newPosition)
+class headerFieldValue : public component
{
- m_value = string(buffer.begin() + position, buffer.begin() + end);
+public:
+
+};
- setParsedBounds(position, end);
- if (newPosition)
- *newPosition = end;
-}
+} // vmime
-#endif // (!defined(__GNUC__) || ((__GNUC__ >= 3) && (__GNUC_MINOR__ >= 3))) && !defined(_MSC_VER)
+#endif // VMIME_HEADERFIELDVALUE_HPP_INCLUDED
-} // vmime
diff --git a/vmime/mailboxField.hpp b/vmime/mailboxField.hpp
index afd61ac7..18a016de 100644
--- a/vmime/mailboxField.hpp
+++ b/vmime/mailboxField.hpp
@@ -25,15 +25,23 @@
#define VMIME_MAILBOXFIELD_HPP_INCLUDED
-#include "vmime/genericField.hpp"
+#include "vmime/headerField.hpp"
#include "vmime/mailbox.hpp"
+// Hide implementation details from user
+#ifndef VMIME_BUILDING_DOC
+
+
namespace vmime
{
-class mailboxField : public genericField <mailbox>
+/** Work-around for malformed header fields that are of type 'mailbox'
+ * and contains multiple addresses.
+ */
+
+class mailboxField : public headerField
{
friend class vmime::creator; // create ref
@@ -48,7 +56,11 @@ public:
};
+#endif // VMIME_BUILDING_DOC
+
+
} // vmime
#endif // VMIME_MAILBOXFIELD_HPP_INCLUDED
+
diff --git a/vmime/mailboxList.hpp b/vmime/mailboxList.hpp
index fe417c42..126d1ae6 100644
--- a/vmime/mailboxList.hpp
+++ b/vmime/mailboxList.hpp
@@ -39,7 +39,7 @@ namespace vmime
* from inserting mailbox groups where it is not allowed by the RFC.
*/
-class mailboxList : public component
+class mailboxList : public headerFieldValue
{
public:
diff --git a/vmime/mdn/MDNHelper.hpp b/vmime/mdn/MDNHelper.hpp
index 322c61ab..ad6b9409 100644
--- a/vmime/mdn/MDNHelper.hpp
+++ b/vmime/mdn/MDNHelper.hpp
@@ -28,6 +28,8 @@
#include "vmime/mdn/receivedMDNInfos.hpp"
#include "vmime/mdn/sendableMDNInfos.hpp"
+#include "vmime/mailboxList.hpp"
+
namespace vmime {
namespace mdn {
diff --git a/vmime/mdn/receivedMDNInfos.hpp b/vmime/mdn/receivedMDNInfos.hpp
index 0ba88fc6..b8041d16 100644
--- a/vmime/mdn/receivedMDNInfos.hpp
+++ b/vmime/mdn/receivedMDNInfos.hpp
@@ -26,7 +26,10 @@
#include "vmime/mdn/MDNInfos.hpp"
+
#include "vmime/disposition.hpp"
+#include "vmime/messageId.hpp"
+#include "vmime/mailbox.hpp"
namespace vmime {
diff --git a/vmime/mdn/sendableMDNInfos.hpp b/vmime/mdn/sendableMDNInfos.hpp
index ae3c8ea0..ea01edd0 100644
--- a/vmime/mdn/sendableMDNInfos.hpp
+++ b/vmime/mdn/sendableMDNInfos.hpp
@@ -27,6 +27,8 @@
#include "vmime/mdn/MDNInfos.hpp"
+#include "vmime/mailbox.hpp"
+
namespace vmime {
namespace mdn {
diff --git a/vmime/mediaType.hpp b/vmime/mediaType.hpp
index 3e5c86ce..1bdda268 100644
--- a/vmime/mediaType.hpp
+++ b/vmime/mediaType.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
namespace vmime
@@ -36,7 +36,7 @@ namespace vmime
/** Content media type (basic type).
*/
-class mediaType : public component
+class mediaType : public headerFieldValue
{
public:
diff --git a/vmime/messageId.hpp b/vmime/messageId.hpp
index 1853d24d..d83bf242 100644
--- a/vmime/messageId.hpp
+++ b/vmime/messageId.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
namespace vmime
@@ -36,7 +36,7 @@ namespace vmime
/** Message identifier (basic type).
*/
-class messageId : public component
+class messageId : public headerFieldValue
{
friend class messageIdSequence;
diff --git a/vmime/messageIdSequence.hpp b/vmime/messageIdSequence.hpp
index a33d8a57..f7c96151 100644
--- a/vmime/messageIdSequence.hpp
+++ b/vmime/messageIdSequence.hpp
@@ -35,7 +35,7 @@ namespace vmime
/** A list of message identifiers (basic type).
*/
-class messageIdSequence : public component
+class messageIdSequence : public headerFieldValue
{
public:
diff --git a/vmime/messageParser.hpp b/vmime/messageParser.hpp
index 73bd4769..8c539c4f 100644
--- a/vmime/messageParser.hpp
+++ b/vmime/messageParser.hpp
@@ -30,6 +30,10 @@
#include "vmime/message.hpp"
#include "vmime/attachment.hpp"
+#include "vmime/mailbox.hpp"
+#include "vmime/addressList.hpp"
+#include "vmime/dateTime.hpp"
+
#include "vmime/textPart.hpp"
diff --git a/vmime/net/message.hpp b/vmime/net/message.hpp
index 7f77747e..63656608 100644
--- a/vmime/net/message.hpp
+++ b/vmime/net/message.hpp
@@ -26,6 +26,7 @@
#include "vmime/header.hpp"
+#include "vmime/mediaType.hpp"
#include "vmime/utility/progressListener.hpp"
#include "vmime/utility/stream.hpp"
diff --git a/vmime/net/pop3/POP3Store.hpp b/vmime/net/pop3/POP3Store.hpp
index ad58f043..2839d198 100644
--- a/vmime/net/pop3/POP3Store.hpp
+++ b/vmime/net/pop3/POP3Store.hpp
@@ -26,6 +26,7 @@
#include "vmime/config.hpp"
+#include "vmime/messageId.hpp"
#include "vmime/net/store.hpp"
#include "vmime/net/socket.hpp"
diff --git a/vmime/net/transport.hpp b/vmime/net/transport.hpp
index 8d297166..b43c05f0 100644
--- a/vmime/net/transport.hpp
+++ b/vmime/net/transport.hpp
@@ -28,6 +28,8 @@
#include "vmime/net/service.hpp"
#include "vmime/utility/stream.hpp"
+#include "vmime/mailboxList.hpp"
+
namespace vmime {
diff --git a/vmime/parameter.hpp b/vmime/parameter.hpp
index cf676084..8ac7e82c 100644
--- a/vmime/parameter.hpp
+++ b/vmime/parameter.hpp
@@ -27,6 +27,7 @@
#include "vmime/base.hpp"
#include "vmime/component.hpp"
+#include "vmime/word.hpp"
namespace vmime
@@ -35,11 +36,19 @@ namespace vmime
class parameter : public component
{
- friend class parameterFactory;
friend class parameterizedHeaderField;
+private:
+
+ parameter(const parameter&);
+
public:
+ parameter(const string& name);
+ parameter(const string& name, const word& value);
+ parameter(const string& name, const string& value);
+
+
#ifndef VMIME_BUILDING_DOC
/** A single section of a multi-section parameter,
@@ -60,31 +69,58 @@ public:
const std::vector <ref <const component> > getChildComponents() const;
- /** Return the name of the parameter.
+ /** Return the name of this parameter.
*
- * @return name of the parameter
+ * @return name of this parameter
*/
const string& getName() const;
- /** Return the read-only value object attached to this field.
+ /** Return the raw value of this parameter.
*
- * @return read-only value object
+ * @return read-only value
*/
- virtual const component& getValue() const = 0;
+ const word& getValue() const;
- /** Return the value object attached to this field.
+ /** Return the value of this object in the specified type.
+ * For example, the following code:
*
- * @return value object
+ * <pre>
+ * getParameter("creation-date")->getValueAs <vmime::dateTime>()</pre>
+ * </pre>
+ *
+ * is equivalent to:
+ *
+ * <pre>
+ * ref <vmime::word> rawValue = getParameter("creation-date");
+ *
+ * vmime::dateTime theDate;
+ * theDate.parse(rawValue->getBuffer());
+ * </pre>
+ *
+ * @param T type to which convert the value
+ * @return value
*/
- virtual component& getValue() = 0;
+ template <typename T>
+ const T getValueAs() const
+ {
+ T ret;
+ ret.parse(m_value.getBuffer());
- /** Set the value of the parameter.
+ return ret;
+ }
+
+ /** Set the value of this parameter.
*
- * @throw std::bad_cast_exception if the value type is
- * incompatible with the parameter type
- * @param value value object
+ * @param value new value
*/
- virtual void setValue(const component& value) = 0;
+ void setValue(const component& value);
+
+ /** Set the raw value of this parameter.
+ *
+ * @param value new value
+ */
+ void setValue(const word& value);
+
using component::parse;
using component::generate;
@@ -92,18 +128,13 @@ public:
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
-protected:
-
- virtual const ref <const component> getValueImp() const = 0;
- virtual const ref <component> getValueImp() = 0;
-
private:
- string m_name;
+ void parse(const std::vector <valueChunk>& chunks);
- void generateValue(utility::outputStream& os, const string::size_type maxLineLength, const string::size_type curLinePos, string::size_type* newLinePos) const;
- virtual void parse(const std::vector <valueChunk>& chunks);
+ string m_name;
+ word m_value;
};
diff --git a/vmime/parameterFactory.hpp b/vmime/parameterFactory.hpp
deleted file mode 100644
index 358f2172..00000000
--- a/vmime/parameterFactory.hpp
+++ /dev/null
@@ -1,97 +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.
-//
-
-#ifndef VMIME_PARAMETERFACTORY_HPP_INCLUDED
-#define VMIME_PARAMETERFACTORY_HPP_INCLUDED
-
-
-#include "vmime/parameter.hpp"
-#include "vmime/utility/stringUtils.hpp"
-
-
-namespace vmime
-{
-
-
-class parameterFactory
-{
-protected:
-
- parameterFactory();
- ~parameterFactory();
-
- typedef ref <parameter> (*AllocFunc)(void);
- typedef std::map <string, AllocFunc> NameMap;
-
- NameMap m_nameMap;
-
-public:
-
- static parameterFactory* getInstance();
-
-#ifndef VMIME_BUILDING_DOC
- template <class TYPE>
- class registerer
- {
- public:
-
- static ref <parameter> creator()
- {
- // Allocate a new object
- return vmime::create <TYPE>();
- }
- };
-#endif // VMIME_BUILDING_DOC
-
-
- template <class T>
- void registerName(const string& name)
- {
- m_nameMap.insert(NameMap::value_type
- (utility::stringUtils::toLower(name), &registerer<T>::creator));
- }
-
- /** Create a new parameter and parse its value. The returned parameter
- * can then be added in a vmime::parameterizedHeaderField object.
- *
- * @param name parameter name (ASCII characters only)
- * @param value value to be parsed
- * @return created parameter
- */
- ref <parameter> create(const string& name, const string& value = NULL_STRING);
-
- /** Create a new parameter and set its value. The returned parameter
- * can then be added in a vmime::parameterizedHeaderField object.
- *
- * @param name parameter name (ASCII characters only)
- * @param value value to be set
- * @return created parameter
- */
- ref <parameter> create(const string& name, const component& value);
-};
-
-
-} // vmime
-
-
-#endif // VMIME_PARAMETERFACTORY_HPP_INCLUDED
diff --git a/vmime/parameterizedHeaderField.hpp b/vmime/parameterizedHeaderField.hpp
index 79ab49b5..bc1dc5be 100644
--- a/vmime/parameterizedHeaderField.hpp
+++ b/vmime/parameterizedHeaderField.hpp
@@ -29,7 +29,6 @@
#include "vmime/headerFieldFactory.hpp"
#include "vmime/parameter.hpp"
#include "vmime/exception.hpp"
-#include "vmime/parameterFactory.hpp"
namespace vmime
@@ -42,10 +41,12 @@ namespace vmime
class parameterizedHeaderField : virtual public headerField
{
- friend class headerFieldFactory::registerer <parameterizedHeaderField>;
+ friend class vmime::creator; // create ref
protected:
+ // Protected constructor to prevent the user from creating
+ // new objects without using 'headerFieldFactory'
parameterizedHeaderField();
public:
diff --git a/vmime/path.hpp b/vmime/path.hpp
index 5e45aa2c..0e8f6d3b 100644
--- a/vmime/path.hpp
+++ b/vmime/path.hpp
@@ -25,7 +25,7 @@
#define VMIME_PATH_HPP_INCLUDED
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
namespace vmime
@@ -35,7 +35,7 @@ namespace vmime
/** A path: a local part + '@' + a domain.
*/
-class path : public component
+class path : public headerFieldValue
{
public:
diff --git a/vmime/relay.hpp b/vmime/relay.hpp
index 9f21da2b..f6391221 100644
--- a/vmime/relay.hpp
+++ b/vmime/relay.hpp
@@ -26,7 +26,7 @@
#include "vmime/base.hpp"
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
#include "vmime/dateTime.hpp"
@@ -38,7 +38,7 @@ namespace vmime
/** Trace information about a relay (basic type).
*/
-class relay : public component
+class relay : public headerFieldValue
{
public:
diff --git a/vmime/text.hpp b/vmime/text.hpp
index a2914fa4..8da6d9e0 100644
--- a/vmime/text.hpp
+++ b/vmime/text.hpp
@@ -25,6 +25,7 @@
#define VMIME_TEXT_HPP_INCLUDED
+#include "vmime/headerFieldValue.hpp"
#include "vmime/base.hpp"
#include "vmime/word.hpp"
@@ -36,7 +37,7 @@ namespace vmime
/** List of encoded-words, as defined in RFC-2047 (basic type).
*/
-class text : public component
+class text : public headerFieldValue
{
public:
@@ -142,6 +143,14 @@ public:
*/
const string getConvertedText(const charset& dest) const;
+ /** Return the unconverted (raw) data of all words. This is the
+ * concatenation of the results returned by getBuffer() on
+ * the contained words.
+ *
+ * @return raw data
+ */
+ const string getWholeBuffer() const;
+
/** This function can be used to make several encoded words from a text.
* All the characters in the text must be in the same specified charset.
*
diff --git a/vmime/typeAdapter.hpp b/vmime/typeAdapter.hpp
deleted file mode 100644
index 2ad8e80a..00000000
--- a/vmime/typeAdapter.hpp
+++ /dev/null
@@ -1,159 +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.
-//
-
-#ifndef VMIME_TYPEADAPTER_HPP_INCLUDED
-#define VMIME_TYPEADAPTER_HPP_INCLUDED
-
-
-#include <sstream>
-
-#include "vmime/component.hpp"
-
-
-namespace vmime
-{
-
-
-/** An adapter to allow any type to act as a 'component'.
- */
-
-template <class TYPE>
-class typeAdapter : public component
-{
-public:
-
- typeAdapter()
- {
- }
-
- typeAdapter(typeAdapter& a)
- : component(), m_value(a.m_value)
- {
- }
-
- typeAdapter(const TYPE& v)
- : m_value(v)
- {
- }
-
-
- ref <component> clone() const
- {
- return create <typeAdapter>(*this);
- }
-
-
- void copyFrom(const component& other)
- {
- m_value = dynamic_cast <const typeAdapter <TYPE>&>(other).m_value;
- }
-
-
- typeAdapter& operator=(const TYPE& v)
- {
- m_value = v;
- return (*this);
- }
-
-
- typeAdapter& operator=(const component& other)
- {
- copyFrom(other);
- return (*this);
- }
-
-
- operator TYPE() const
- {
- return (m_value);
- }
-
-
- void parse(const string& buffer, const string::size_type position,
- const string::size_type end, string::size_type* newPosition = NULL)
- {
- std::istringstream iss(string(buffer.begin() + position, buffer.begin() + end));
- iss >> m_value;
-
- setParsedBounds(position, end);
-
- if (newPosition)
- *newPosition = end;
- }
-
-
- void generate(utility::outputStream& os,
- const string::size_type /* maxLineLength */ = lineLengthLimits::infinite,
- const string::size_type curLinePos = 0,
- string::size_type* newLinePos = NULL) const
- {
- std::ostringstream oss;
- oss << m_value;
-
- os << oss.str();
-
- if (newLinePos)
- *newLinePos = curLinePos + oss.str().length();
- }
-
- const std::vector <ref <const component> > getChildComponents() const
- {
- return std::vector <ref <const component> >();
- }
-
-private:
-
- TYPE m_value;
-};
-
-
-#if (defined(__GNUC__) && (__GNUC__ >= 3) && (__GNUC_MINOR__ <= 2)) || defined(_MSC_VER)
-
- // Because of a bug with g++ <= 3.2, we have to put the implementation
- // of the function inline.
-
- template <>
- inline 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);
-
- if (newPosition)
- *newPosition = end;
- }
-
-#else
-
- template <>
- void typeAdapter <string>::parse
- (const string& buffer, const string::size_type position,
- const string::size_type end, string::size_type* newPosition);
-
-#endif // (defined(__GNUC__) && (__GNUC__ >= 3) && (__GNUC_MINOR__ <= 2)) || defined(_MSC_VER)
-
-
-} // vmime
-
-
-#endif // VMIME_TYPEADAPTE_HPP_INCLUDED
diff --git a/vmime/vmime.hpp b/vmime/vmime.hpp
index 36b9e0e3..cbae859e 100644
--- a/vmime/vmime.hpp
+++ b/vmime/vmime.hpp
@@ -48,8 +48,10 @@
#include "vmime/addressList.hpp"
#include "vmime/mediaType.hpp"
#include "vmime/messageId.hpp"
+#include "vmime/messageIdSequence.hpp"
#include "vmime/relay.hpp"
#include "vmime/disposition.hpp"
+#include "vmime/path.hpp"
#include "vmime/emptyContentHandler.hpp"
#include "vmime/stringContentHandler.hpp"
@@ -62,7 +64,6 @@
#include "vmime/headerFieldFactory.hpp"
#include "vmime/mailboxField.hpp"
#include "vmime/parameterizedHeaderField.hpp"
-#include "vmime/standardFields.hpp"
// Encoders
#include "vmime/encoderFactory.hpp"
diff --git a/vmime/word.hpp b/vmime/word.hpp
index 79aef9c8..284b64d6 100644
--- a/vmime/word.hpp
+++ b/vmime/word.hpp
@@ -25,7 +25,7 @@
#define VMIME_WORD_HPP_INCLUDED
-#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
#include "vmime/charset.hpp"
@@ -37,7 +37,7 @@ namespace vmime
* some text encoded into one specified charset.
*/
-class word : public component
+class word : public headerFieldValue
{
friend class text;