aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2005-03-27 13:06:45 +0000
committerVincent Richard <[email protected]>2005-03-27 13:06:45 +0000
commit4ab9332ce6269807edb45e69f7e6000aa40d4478 (patch)
tree6f5e4e583ff7d7b88e62dac7b81a90c129a7d3b9
parentSome fixes for Visual C++/Windows. (diff)
downloadvmime-4ab9332ce6269807edb45e69f7e6000aa40d4478.tar.gz
vmime-4ab9332ce6269807edb45e69f7e6000aa40d4478.zip
Added new basic type 'messageIdSequence'.
-rw-r--r--ChangeLog6
-rw-r--r--SConstruct3
-rw-r--r--src/addressList.cpp25
-rw-r--r--src/constants.cpp1
-rw-r--r--src/exception.cpp12
-rw-r--r--src/headerFieldFactory.cpp3
-rw-r--r--src/messageId.cpp43
-rw-r--r--src/messageIdSequence.cpp246
-rw-r--r--tests/parser/messageIdSequenceTest.cpp95
-rw-r--r--tests/parser/messageIdTest.cpp84
-rw-r--r--vmime/constants.hpp1
-rw-r--r--vmime/exception.hpp12
-rw-r--r--vmime/header.hpp3
-rw-r--r--vmime/messageId.hpp14
-rw-r--r--vmime/messageIdSequence.hpp163
-rw-r--r--vmime/standardFields.hpp2
16 files changed, 694 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 749d0efc..bcbeb3d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,12 @@
VERSION 0.6.4cvs
================
+2005-03-27 Vincent Richard <[email protected]>
+
+ * messageIdSequence.{cpp|hpp}: added a new basic type "messageIdSequence" for
+ a list of message-ids separated by CFWS (used in "References:" field, for
+ example).
+
2005-03-25 Vincent Richard <[email protected]>
* mdn/*.{cpp|hpp}: added support for Message Disposition Notifications (MDN),
diff --git a/SConstruct b/SConstruct
index e378fb86..dfe0a7c6 100644
--- a/SConstruct
+++ b/SConstruct
@@ -122,6 +122,7 @@ libvmime_sources = [
'messageBuilder.cpp', 'messageBuilder.hpp',
'message.cpp', 'message.hpp',
'messageId.cpp', 'messageId.hpp',
+ 'messageIdSequence.cpp', 'messageIdSequence.hpp',
'messageParser.cpp', 'messageParser.hpp',
'options.cpp', 'options.hpp',
'path.cpp', 'path.hpp',
@@ -317,6 +318,8 @@ libvmimetest_sources = [
[ 'tests/parser/headerTest', [ 'tests/parser/headerTest.cpp' ] ],
[ 'tests/parser/mailboxTest', [ 'tests/parser/mailboxTest.cpp' ] ],
[ 'tests/parser/mediaTypeTest', [ 'tests/parser/mediaTypeTest.cpp' ] ],
+ [ 'tests/parser/messageIdTest', [ 'tests/parser/messageIdTest.cpp' ] ],
+ [ 'tests/parser/messageIdSequenceTest', [ 'tests/parser/messageIdSequenceTest.cpp' ] ],
[ 'tests/parser/pathTest', [ 'tests/parser/pathTest.cpp' ] ],
[ 'tests/parser/textTest', [ 'tests/parser/textTest.cpp' ] ],
[ 'tests/utility/md5Test', [ 'tests/utility/md5Test.cpp' ] ],
diff --git a/src/addressList.cpp b/src/addressList.cpp
index c6d9c9ad..9693a663 100644
--- a/src/addressList.cpp
+++ b/src/addressList.cpp
@@ -70,29 +70,24 @@ void addressList::parse(const string& buffer, const string::size_type position,
void addressList::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
+ string::size_type pos = curLinePos;
+
if (!m_list.empty())
{
- string::size_type pos = curLinePos;
- std::vector <address*>::const_iterator i = m_list.begin();
-
- for ( ; ; )
+ for (std::vector <address*>::const_iterator i = m_list.begin() ; ; )
{
(*i)->generate(os, maxLineLength - 2, pos, &pos);
- if (++i != m_list.end())
- {
- os << ", ";
- pos += 2;
- }
- else
- {
+ if (++i == m_list.end())
break;
- }
- }
- if (newLinePos)
- *newLinePos = pos;
+ os << ", ";
+ pos += 2;
+ }
}
+
+ if (newLinePos)
+ *newLinePos = pos;
}
diff --git a/src/constants.cpp b/src/constants.cpp
index 5ca08960..494428a2 100644
--- a/src/constants.cpp
+++ b/src/constants.cpp
@@ -176,6 +176,7 @@ namespace fields
const string::value_type* const CONTENT_ID = "Content-Id";
const string::value_type* const CONTENT_LOCATION = "Content-Location";
const string::value_type* const IN_REPLY_TO = "In-Reply-To";
+ const string::value_type* const REFERENCES = "References";
const string::value_type* const X_MAILER = "X-Mailer";
const string::value_type* const X_PRIORITY = "X-Priority";
diff --git a/src/exception.cpp b/src/exception.cpp
index 4bbdefd3..b7be006c 100644
--- a/src/exception.cpp
+++ b/src/exception.cpp
@@ -163,6 +163,18 @@ const string no_such_mailbox::name() const { return "no_such_mailbox"; }
//
+// no_such_message_id
+//
+
+no_such_message_id::~no_such_message_id() throw() {}
+no_such_message_id::no_such_message_id(const exception& other)
+ : exception("Message-Id not found.", other) {}
+
+exception* no_such_message_id::clone() const { return new no_such_message_id(*this); }
+const string no_such_message_id::name() const { return "no_such_message_id"; }
+
+
+//
// no_such_address
//
diff --git a/src/headerFieldFactory.cpp b/src/headerFieldFactory.cpp
index 62eff647..fa990c6f 100644
--- a/src/headerFieldFactory.cpp
+++ b/src/headerFieldFactory.cpp
@@ -55,7 +55,8 @@ headerFieldFactory::headerFieldFactory()
registerName <messageIdField>(vmime::fields::CONTENT_ID);
registerName <messageIdField>(vmime::fields::MESSAGE_ID);
registerName <defaultField>(vmime::fields::CONTENT_LOCATION);
- registerName <messageIdField>(vmime::fields::IN_REPLY_TO);
+ registerName <messageIdSequenceField>(vmime::fields::IN_REPLY_TO);
+ registerName <messageIdSequenceField>(vmime::fields::REFERENCES);
registerName <messageIdField>(vmime::fields::ORIGINAL_MESSAGE_ID);
registerName <dispositionField>(vmime::fields::DISPOSITION);
diff --git a/src/messageId.cpp b/src/messageId.cpp
index 815266d5..9e878c2f 100644
--- a/src/messageId.cpp
+++ b/src/messageId.cpp
@@ -129,19 +129,58 @@ void messageId::parse(const string& buffer, const string::size_type position,
}
+messageId* messageId::parseNext(const string& buffer, const string::size_type position,
+ const string::size_type end, string::size_type* newPosition)
+{
+ string::size_type pos = position;
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos]))
+ ++pos;
+
+ if (pos != end)
+ {
+ const string::size_type begin = pos;
+
+ while (pos < end && !parserHelpers::isSpace(buffer[pos]))
+ ++pos;
+
+ messageId* mid = new messageId();
+ mid->parse(buffer, begin, pos, NULL);
+
+ if (newPosition != NULL)
+ *newPosition = pos;
+
+ return (mid);
+ }
+
+ if (newPosition != NULL)
+ *newPosition = end;
+
+ return (NULL);
+}
+
+
const string messageId::getId() const
{
return (m_left + '@' + m_right);
}
-void messageId::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
+void messageId::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
+ string::size_type pos = curLinePos;
+
+ if (curLinePos + m_left.length() + m_right.length() + 3 > maxLineLength)
+ {
+ os << NEW_LINE_SEQUENCE;
+ pos = NEW_LINE_SEQUENCE_LENGTH;
+ }
+
os << '<' << m_left << '@' << m_right << '>';
if (newLinePos)
- *newLinePos = curLinePos + m_left.length() + m_right.length() + 3;
+ *newLinePos = pos + m_left.length() + m_right.length() + 3;
}
diff --git a/src/messageIdSequence.cpp b/src/messageIdSequence.cpp
new file mode 100644
index 00000000..7b3eae0d
--- /dev/null
+++ b/src/messageIdSequence.cpp
@@ -0,0 +1,246 @@
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#include "vmime/messageIdSequence.hpp"
+#include "vmime/exception.hpp"
+
+
+namespace vmime
+{
+
+
+
+
+messageIdSequence::messageIdSequence()
+{
+}
+
+
+messageIdSequence::~messageIdSequence()
+{
+ removeAllMessageIds();
+}
+
+
+messageIdSequence::messageIdSequence(const messageIdSequence& midSeq)
+ : component()
+{
+ copyFrom(midSeq);
+}
+
+
+messageIdSequence* messageIdSequence::clone() const
+{
+ return new messageIdSequence(*this);
+}
+
+
+void messageIdSequence::copyFrom(const component& other)
+{
+ const messageIdSequence& midSeq = dynamic_cast <const messageIdSequence&>(other);
+
+ removeAllMessageIds();
+
+ for (unsigned int i = 0 ; i < midSeq.m_list.size() ; ++i)
+ m_list.push_back(midSeq.m_list[i]->clone());
+}
+
+
+messageIdSequence& messageIdSequence::operator=(const messageIdSequence& other)
+{
+ copyFrom(other);
+ return (*this);
+}
+
+
+const std::vector <const component*> messageIdSequence::getChildComponents() const
+{
+ std::vector <const component*> res;
+
+ copy_vector(m_list, res);
+
+ return (res);
+}
+
+
+void messageIdSequence::parse(const string& buffer, const string::size_type position,
+ const string::size_type end, string::size_type* newPosition)
+{
+ removeAllMessageIds();
+
+ string::size_type pos = position;
+
+ while (pos < end)
+ {
+ messageId* parsedMid = messageId::parseNext(buffer, pos, end, &pos);
+
+ if (parsedMid != NULL)
+ m_list.push_back(parsedMid);
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition)
+ *newPosition = end;
+}
+
+
+void messageIdSequence::generate(utility::outputStream& os, const string::size_type maxLineLength,
+ const string::size_type curLinePos, string::size_type* newLinePos) const
+{
+ string::size_type pos = curLinePos;
+
+ if (!m_list.empty())
+ {
+ for (std::vector <messageId*>::const_iterator it = m_list.begin() ; ; )
+ {
+ (*it)->generate(os, maxLineLength - 2, pos, &pos);
+
+ if (++it == m_list.end())
+ break;
+
+ os << " ";
+ pos++;
+ }
+ }
+
+ if (newLinePos)
+ *newLinePos = pos;
+}
+
+
+void messageIdSequence::appendMessageId(messageId* mid)
+{
+ m_list.push_back(mid);
+}
+
+
+void messageIdSequence::insertMessageIdBefore(messageId* beforeMid, messageId* mid)
+{
+ const std::vector <messageId*>::iterator it = std::find
+ (m_list.begin(), m_list.end(), beforeMid);
+
+ if (it == m_list.end())
+ throw exceptions::no_such_message_id();
+
+ m_list.insert(it, mid);
+}
+
+
+void messageIdSequence::insertMessageIdBefore(const int pos, messageId* mid)
+{
+ m_list.insert(m_list.begin() + pos, mid);
+}
+
+
+void messageIdSequence::insertMessageIdAfter(messageId* afterMid, messageId* mid)
+{
+ const std::vector <messageId*>::iterator it = std::find
+ (m_list.begin(), m_list.end(), afterMid);
+
+ if (it == m_list.end())
+ throw exceptions::no_such_message_id();
+
+ m_list.insert(it + 1, mid);
+}
+
+
+void messageIdSequence::insertMessageIdAfter(const int pos, messageId* mid)
+{
+ m_list.insert(m_list.begin() + pos + 1, mid);
+}
+
+
+void messageIdSequence::removeMessageId(messageId* mid)
+{
+ const std::vector <messageId*>::iterator it = std::find
+ (m_list.begin(), m_list.end(), mid);
+
+ if (it == m_list.end())
+ throw exceptions::no_such_message_id();
+
+ delete (*it);
+
+ m_list.erase(it);
+}
+
+
+void messageIdSequence::removeMessageId(const int pos)
+{
+ const std::vector <messageId*>::iterator it = m_list.begin() + pos;
+
+ delete (*it);
+
+ m_list.erase(it);
+}
+
+
+void messageIdSequence::removeAllMessageIds()
+{
+ free_container(m_list);
+}
+
+
+const int messageIdSequence::getMessageIdCount() const
+{
+ return (m_list.size());
+}
+
+
+const bool messageIdSequence::isEmpty() const
+{
+ return (m_list.empty());
+}
+
+
+messageId* messageIdSequence::getMessageIdAt(const int pos)
+{
+ return (m_list[pos]);
+}
+
+
+const messageId* messageIdSequence::getMessageIdAt(const int pos) const
+{
+ return (m_list[pos]);
+}
+
+
+const std::vector <const messageId*> messageIdSequence::getMessageIdList() const
+{
+ std::vector <const messageId*> list;
+
+ list.reserve(m_list.size());
+
+ for (std::vector <messageId*>::const_iterator it = m_list.begin() ;
+ it != m_list.end() ; ++it)
+ {
+ list.push_back(*it);
+ }
+
+ return (list);
+}
+
+
+const std::vector <messageId*> messageIdSequence::getMessageIdList()
+{
+ return (m_list);
+}
+
+
+} // vmime
diff --git a/tests/parser/messageIdSequenceTest.cpp b/tests/parser/messageIdSequenceTest.cpp
new file mode 100644
index 00000000..b80a34d9
--- /dev/null
+++ b/tests/parser/messageIdSequenceTest.cpp
@@ -0,0 +1,95 @@
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#include "../lib/unit++/unit++.h"
+
+#include <iostream>
+#include <ostream>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+#include "tests/parser/testUtils.hpp"
+
+using namespace unitpp;
+
+
+namespace
+{
+ class messageIdSequenceTest : public suite
+ {
+ void testParse()
+ {
+ vmime::messageIdSequence s1;
+ s1.parse("");
+
+ assert_eq("1", 0, s1.getMessageIdCount());
+
+ vmime::messageIdSequence s2;
+ s2.parse(" \t ");
+
+ assert_eq("2", 0, s2.getMessageIdCount());
+
+ vmime::messageIdSequence s3;
+ s3.parse("<a@b>");
+
+ assert_eq("3.1", 1, s3.getMessageIdCount());
+ assert_eq("3.2", "a", s3.getMessageIdAt(0)->getLeft());
+ assert_eq("3.3", "b", s3.getMessageIdAt(0)->getRight());
+
+ vmime::messageIdSequence s4;
+ s4.parse("<a@b> \r\n\t<c@d>");
+
+ assert_eq("4.1", 2, s4.getMessageIdCount());
+ assert_eq("4.2", "a", s4.getMessageIdAt(0)->getLeft());
+ assert_eq("4.3", "b", s4.getMessageIdAt(0)->getRight());
+ assert_eq("4.4", "c", s4.getMessageIdAt(1)->getLeft());
+ assert_eq("4.5", "d", s4.getMessageIdAt(1)->getRight());
+ }
+
+ void testGenerate()
+ {
+ vmime::messageIdSequence s1;
+ s1.appendMessageId(new vmime::messageId("a", "b"));
+
+ assert_eq("1", "<a@b>", s1.generate());
+
+ vmime::messageIdSequence s2;
+ s2.appendMessageId(new vmime::messageId("a", "b"));
+ s2.appendMessageId(new vmime::messageId("c", "d"));
+
+ assert_eq("2", "<a@b> <c@d>", s2.generate());
+ }
+
+ public:
+
+ messageIdSequenceTest() : suite("vmime::messageIdSequence")
+ {
+ vmime::platformDependant::setHandler<vmime::platforms::posix::posixHandler>();
+
+ add("Parse", testcase(this, "Parse", &messageIdSequenceTest::testParse));
+ add("Generate", testcase(this, "Generate", &messageIdSequenceTest::testGenerate));
+
+ suite::main().add("vmime::messageIdSequence", this);
+ }
+
+ };
+
+ messageIdSequenceTest* theTest = new messageIdSequenceTest();
+}
diff --git a/tests/parser/messageIdTest.cpp b/tests/parser/messageIdTest.cpp
new file mode 100644
index 00000000..e05ac9c1
--- /dev/null
+++ b/tests/parser/messageIdTest.cpp
@@ -0,0 +1,84 @@
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#include "../lib/unit++/unit++.h"
+
+#include <iostream>
+#include <ostream>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+#include "tests/parser/testUtils.hpp"
+
+using namespace unitpp;
+
+
+namespace
+{
+ class messageIdTest : public suite
+ {
+ void testParse()
+ {
+ vmime::messageId m1;
+ m1.parse("<a@b>");
+
+ assert_eq("1.1", "a", m1.getLeft());
+ assert_eq("1.2", "b", m1.getRight());
+ }
+
+ void testGenerate()
+ {
+ vmime::messageId m1;
+
+ assert_eq("1", "<@>", m1.generate());
+
+ vmime::messageId m2;
+ m2.setLeft("a");
+
+ assert_eq("2", "<a@>", m2.generate());
+
+ vmime::messageId m3;
+ m3.setRight("b");
+
+ assert_eq("3", "<@b>", m3.generate());
+
+ vmime::messageId m4;
+ m4.setLeft("a");
+ m4.setRight("b");
+
+ assert_eq("4", "<a@b>", m4.generate());
+ }
+
+ public:
+
+ messageIdTest() : suite("vmime::messageId")
+ {
+ vmime::platformDependant::setHandler<vmime::platforms::posix::posixHandler>();
+
+ add("Parse", testcase(this, "Parse", &messageIdTest::testParse));
+ add("Generate", testcase(this, "Generate", &messageIdTest::testGenerate));
+
+ suite::main().add("vmime::messageId", this);
+ }
+
+ };
+
+ messageIdTest* theTest = new messageIdTest();
+}
diff --git a/vmime/constants.hpp b/vmime/constants.hpp
index 7a3482f1..90a9c699 100644
--- a/vmime/constants.hpp
+++ b/vmime/constants.hpp
@@ -186,6 +186,7 @@ namespace vmime
extern const string::value_type* const CONTENT_ID;
extern const string::value_type* const CONTENT_LOCATION;
extern const string::value_type* const IN_REPLY_TO;
+ extern const string::value_type* const REFERENCES;
extern const string::value_type* const X_MAILER;
extern const string::value_type* const X_PRIORITY;
diff --git a/vmime/exception.hpp b/vmime/exception.hpp
index 763d2a5c..85f0a3ff 100644
--- a/vmime/exception.hpp
+++ b/vmime/exception.hpp
@@ -164,6 +164,18 @@ public:
};
+class no_such_message_id : public vmime::exception
+{
+public:
+
+ no_such_message_id(const exception& other = NO_EXCEPTION);
+ ~no_such_message_id() throw();
+
+ exception* clone() const;
+ const string name() const;
+};
+
+
class no_such_address : public vmime::exception
{
public:
diff --git a/vmime/header.hpp b/vmime/header.hpp
index 7050c1dd..e663e297 100644
--- a/vmime/header.hpp
+++ b/vmime/header.hpp
@@ -67,8 +67,9 @@ public:
FIELD_ACCESS(Sender, SENDER, mailboxField)
FIELD_ACCESS(ReplyTo, REPLY_TO, mailboxField)
FIELD_ACCESS(DeliveredTo, DELIVERED_TO, mailboxField)
- FIELD_ACCESS(InReplyTo, IN_REPLY_TO, messageIdField)
+ 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)
diff --git a/vmime/messageId.hpp b/vmime/messageId.hpp
index 83288c17..0b471ab2 100644
--- a/vmime/messageId.hpp
+++ b/vmime/messageId.hpp
@@ -34,6 +34,8 @@ namespace vmime
class messageId : public component
{
+ friend class messageIdSequence;
+
public:
messageId();
@@ -106,6 +108,18 @@ public:
// Component parsing & assembling
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:
+
+ /** Parse a message-id from an input buffer.
+ *
+ * @param buffer input buffer
+ * @param position position in the input buffer
+ * @param end end position in the input buffer
+ * @param newPosition will receive the new position in the input buffer
+ * @return a new message-id object, or null if no more message-id can be parsed from the input buffer
+ */
+ static messageId* parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition);
};
diff --git a/vmime/messageIdSequence.hpp b/vmime/messageIdSequence.hpp
new file mode 100644
index 00000000..405ab322
--- /dev/null
+++ b/vmime/messageIdSequence.hpp
@@ -0,0 +1,163 @@
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#ifndef VMIME_MESSAGEIDSEQUENCE_HPP_INCLUDED
+#define VMIME_MESSAGEIDSEQUENCE_HPP_INCLUDED
+
+
+#include "vmime/messageId.hpp"
+
+
+namespace vmime
+{
+
+
+/** A list of message identifiers (basic type).
+ */
+
+class messageIdSequence : public component
+{
+public:
+
+ messageIdSequence();
+ messageIdSequence(const messageIdSequence& midSeq);
+
+ ~messageIdSequence();
+
+
+ messageIdSequence* clone() const;
+ void copyFrom(const component& other);
+ messageIdSequence& operator=(const messageIdSequence& other);
+
+ const std::vector <const component*> getChildComponents() const;
+
+
+ /** Add a message-id at the end of the list.
+ *
+ * @param mid message-id to append
+ */
+ void appendMessageId(messageId* mid);
+
+ /** Insert a new message-id before the specified message-id.
+ *
+ * @param beforeMid message-id before which the new message-id will be inserted
+ * @param mid message-id to insert
+ * @throw exceptions::no_such_messageid if the message-id is not in the list
+ */
+ void insertMessageIdBefore(messageId* beforeMid, messageId* mid);
+
+ /** Insert a new message-id before the specified position.
+ *
+ * @param pos position at which to insert the new message-id (0 to insert at
+ * the beginning of the list)
+ * @param mid message-id to insert
+ */
+ void insertMessageIdBefore(const int pos, messageId* mid);
+
+ /** Insert a new message-id after the specified message-id.
+ *
+ * @param afterMid message-id after which the new message-id will be inserted
+ * @param mid message-id to insert
+ * @throw exceptions::no_such_message_id if the message-id is not in the list
+ */
+ void insertMessageIdAfter(messageId* afterMid, messageId* mid);
+
+ /** Insert a new message-id after the specified position.
+ *
+ * @param pos position of the message-id before the new message-id
+ * @param mid message-id to insert
+ */
+ void insertMessageIdAfter(const int pos, messageId* mid);
+
+ /** Remove the specified message-id from the list.
+ *
+ * @param mid message-id to remove
+ * @throw exceptions::no_such_message_id if the message-id is not in the list
+ */
+ void removeMessageId(messageId* mid);
+
+ /** Remove the message-id at the specified position.
+ *
+ * @param pos position of the message-id to remove
+ */
+ void removeMessageId(const int pos);
+
+ /** Remove all message-ids from the list.
+ */
+ void removeAllMessageIds();
+
+ /** Return the number of message-ides in the list.
+ *
+ * @return number of message-ides
+ */
+ const int getMessageIdCount() const;
+
+ /** Tests whether the list of message-ides is empty.
+ *
+ * @return true if there is no message-id, false otherwise
+ */
+ const bool isEmpty() const;
+
+ /** Return the message-id at the specified position.
+ *
+ * @param pos position
+ * @return message-id at position 'pos'
+ */
+ messageId* getMessageIdAt(const int pos);
+
+ /** Return the message-id at the specified position.
+ *
+ * @param pos position
+ * @return message-id at position 'pos'
+ */
+ const messageId* getMessageIdAt(const int pos) const;
+
+ /** Return the message-id list.
+ *
+ * @return list of message-ids
+ */
+ const std::vector <const messageId*> getMessageIdList() const;
+
+ /** Return the message-id list.
+ *
+ * @return list of message-ids
+ */
+ const std::vector <messageId*> getMessageIdList();
+
+private:
+
+ std::vector <messageId*> m_list;
+
+public:
+
+ using component::parse;
+ using component::generate;
+
+ // Component parsing & assembling
+ 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;
+};
+
+
+
+
+} // vmime
+
+
+#endif // VMIME_MESSAGEIDSEQUENCE_HPP_INCLUDED
diff --git a/vmime/standardFields.hpp b/vmime/standardFields.hpp
index 7d0905dd..8fdb2a99 100644
--- a/vmime/standardFields.hpp
+++ b/vmime/standardFields.hpp
@@ -35,6 +35,7 @@
#include "vmime/mailboxList.hpp"
#include "vmime/disposition.hpp"
#include "vmime/path.hpp"
+#include "vmime/messageIdSequence.hpp"
namespace vmime
@@ -96,6 +97,7 @@ DECLARE_STANDARD_FIELD(relayField, relay);
DECLARE_STANDARD_FIELD(mailboxListField, mailboxList);
DECLARE_STANDARD_FIELD(dispositionField, disposition);
DECLARE_STANDARD_FIELD(pathField, path);
+DECLARE_STANDARD_FIELD(messageIdSequenceField, messageIdSequence);
#undef DECLARE_STANDARD_FIELD