changeset 2847:d37122aa7a10

package vmime: use github tarball This seems like a much better idea than applying our own copy of the patches to the 0.9.1 tarball.
author Mark Brand <mabrand@mabrand.nl>
date Mon, 12 Nov 2012 21:56:00 +0100
parents 9196b5fdf1c5
children 7836cad5a075
files index.html src/vmime-1-fixes.patch src/vmime.mk
diffstat 3 files changed, 9 insertions(+), 10497 deletions(-) [+]
line wrap: on
line diff
--- a/index.html	Sat Nov 10 11:50:40 2012 +0100
+++ b/index.html	Mon Nov 12 21:56:00 2012 +0100
@@ -1920,8 +1920,8 @@
     </tr>
     <tr>
         <td id="vmime-package">vmime</td>
-        <td id="vmime-version">0.9.1</td>
-        <td id="vmime-website"><a href="http://vmime.sourceforge.net/">VMime</a></td>
+        <td id="vmime-version">794afe9</td>
+        <td id="vmime-website"><a href="http://www.vmime.org/">VMime</a></td>
     </tr>
     <tr>
         <td id="vorbis-package">vorbis</td>
--- a/src/vmime-1-fixes.patch	Sat Nov 10 11:50:40 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10488 +0,0 @@
-This file is part of MXE.
-See index.html for further information.
-
-Commits from master branch of git://github.com/kisli/vmime
-rebased onto version 0.9.1 tarball files.
-
-From 17ff5157ffdc749f60b8285f84e64ac5e06d4283 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Tue, 16 Nov 2010 13:28:05 +0000
-Subject: [PATCH 01/47] Started version 0.9.2.
-
-
-diff --git a/ChangeLog b/ChangeLog
-index 871d055..8fdcdb0 100644
---- a/ChangeLog
-+++ b/ChangeLog
-@@ -1,4 +1,12 @@
- 
-+VERSION 0.9.2svn
-+================
-+
-+2010-11-16  Vincent Richard  <vincent@vincent-richard.net>
-+
-+ * Started version 0.9.2.
-+
-+
- VERSION 0.9.1
- =============
- 
-diff --git a/SConstruct b/SConstruct
-index fb01edf..55f9223 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -29,7 +29,7 @@ import string
- # Package version number
- packageVersionMajor = 0
- packageVersionMinor = 9
--packageVersionMicro = 1
-+packageVersionMicro = 2
- 
- # API version number (libtool)
- #
--- 
-1.7.10.4
-
-
-From c12ee2b267b9dcfd092a298dfd9a8eec81ab3a0b Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Tue, 30 Nov 2010 14:57:03 +0000
-Subject: [PATCH 02/47] Initialize and delete object.
-
-
-diff --git a/vmime/net/imap/IMAPParser.hpp b/vmime/net/imap/IMAPParser.hpp
-index 0f3e9ec..d71c3ca 100644
---- a/vmime/net/imap/IMAPParser.hpp
-+++ b/vmime/net/imap/IMAPParser.hpp
-@@ -3823,7 +3823,9 @@ public:
- 
- 		msg_att_item()
- 			: m_date_time(NULL), m_number(NULL), m_envelope(NULL),
--			  m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL)
-+			  m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL),
-+			  m_section(NULL)
-+              
- 		{
- 		}
- 
-@@ -3836,6 +3838,7 @@ public:
- 			delete (m_nstring);
- 			delete (m_body);
- 			delete (m_flag_list);
-+ 			delete (m_section);
- 		}
- 
- 		void go(IMAPParser& parser, string& line, string::size_type* currentPos)
--- 
-1.7.10.4
-
-
-From fd277afe87485c9d3377964794b76006c6d36a56 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Wed, 8 Dec 2010 08:52:54 +0000
-Subject: [PATCH 03/47] No extra space between ':' and '<' in MAIL FROM and
- RCPT TO. Wait for server response after QUIT and
- before closing connection.
-
-
-diff --git a/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp
-index 204daae..d9fb7b8 100644
---- a/src/net/smtp/SMTPTransport.cpp
-+++ b/src/net/smtp/SMTPTransport.cpp
-@@ -516,6 +516,7 @@ void SMTPTransport::internalDisconnect()
- 	try
- 	{
- 		sendRequest("QUIT");
-+		readResponse();
- 	}
- 	catch (exception&)
- 	{
-@@ -565,7 +566,7 @@ void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients
- 	// Emit the "MAIL" command
- 	ref <SMTPResponse> resp;
- 
--	sendRequest("MAIL FROM: <" + expeditor.getEmail() + ">");
-+	sendRequest("MAIL FROM:<" + expeditor.getEmail() + ">");
- 
- 	if ((resp = readResponse())->getCode() != 250)
- 	{
-@@ -578,7 +579,7 @@ void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients
- 	{
- 		const mailbox& mbox = *recipients.getMailboxAt(i);
- 
--		sendRequest("RCPT TO: <" + mbox.getEmail() + ">");
-+		sendRequest("RCPT TO:<" + mbox.getEmail() + ">");
- 
- 		if ((resp = readResponse())->getCode() != 250)
- 		{
--- 
-1.7.10.4
-
-
-From d64da50e879c0e480d2e65c43e3b903c3e80101f Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 10 Dec 2010 16:24:06 +0000
-Subject: [PATCH 04/47] Fixed unit test after bug fix.
-
-
-diff --git a/tests/net/smtp/SMTPTransportTest.cpp b/tests/net/smtp/SMTPTransportTest.cpp
-index 5015552..6552f9e 100644
---- a/tests/net/smtp/SMTPTransportTest.cpp
-+++ b/tests/net/smtp/SMTPTransportTest.cpp
-@@ -165,7 +165,7 @@ public:
- 			}
- 			else if (cmd == "MAIL")
- 			{
--				VASSERT_EQ("MAIL", std::string("MAIL FROM: <expeditor@test.vmime.org>"), line);
-+				VASSERT_EQ("MAIL", std::string("MAIL FROM:<expeditor@test.vmime.org>"), line);
- 
- 				localSend("250 OK\r\n");
- 			}
--- 
-1.7.10.4
-
-
-From 130d0aabda2a9988913ad201390796775dc16a65 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 10 Dec 2010 16:54:38 +0000
-Subject: [PATCH 05/47] Fixed boundary parsing (thanks to John van der Kamp,
- Zarafa).
-
-
-diff --git a/src/body.cpp b/src/body.cpp
-index 13dff6b..738d3e7 100644
---- a/src/body.cpp
-+++ b/src/body.cpp
-@@ -127,10 +127,30 @@ void body::parse(const string& buffer, const string::size_type position,
- 		const string boundarySep("--" + boundary);
- 
- 		string::size_type partStart = position;
--		string::size_type pos = buffer.find(boundarySep, position);
-+		string::size_type pos = position;
- 
- 		bool lastPart = false;
- 
-+		while (pos != string::npos && pos < end)
-+		{
-+			pos = buffer.find(boundarySep, pos);
-+
-+			if (pos == string::npos ||
-+			    ((pos == 0 || buffer[pos - 1] == '\n') &&
-+			     (buffer[pos + boundarySep.length()] == '\r' ||
-+			      buffer[pos + boundarySep.length()] == '\n' ||
-+			      buffer[pos + boundarySep.length()] == '-'
-+			     )
-+			    )
-+			   )
-+			{
-+				break;
-+			}
-+
-+			// boundary not a beginning of line, or just a prefix of another, continue the search.
-+			pos++;
-+		}
-+
- 		if (pos != string::npos && pos < end)
- 		{
- 			m_prologText = string(buffer.begin() + position, buffer.begin() + pos);
-@@ -181,7 +201,26 @@ void body::parse(const string& buffer, const string::size_type position,
- 			}
- 
- 			partStart = pos;
--			pos = buffer.find(boundarySep, partStart);
-+
-+			while (pos != string::npos && pos < end)
-+			{
-+				pos = buffer.find(boundarySep, pos);
-+
-+				if (pos == string::npos ||
-+				    ((pos == 0 || buffer[pos - 1] == '\n') &&
-+				     (buffer[pos + boundarySep.length()] == '\r' ||
-+				      buffer[pos + boundarySep.length()] == '\n' ||
-+					buffer[pos + boundarySep.length()] == '-'
-+				     )
-+				    )
-+				   )
-+				{
-+					break;
-+				}
-+
-+				// boundary not a beginning of line, or just a prefix of another, continue the search.
-+				pos++;
-+			}
- 		}
- 
- 		m_contents = vmime::create <emptyContentHandler>();
-diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp
-index 12c4f74..df2bf85 100644
---- a/tests/parser/bodyPartTest.cpp
-+++ b/tests/parser/bodyPartTest.cpp
-@@ -84,7 +84,7 @@ VMIME_TEST_SUITE_BEGIN
- 		vmime::string str =
- 			"Content-Type: multipart/mixed; boundary=\"MY-BOUNDARY\""
- 			"\r\n\r\n"
--			"--MY-BOUNDARY\r\nHEADER1\r\n\r\nBODY1"
-+			"--MY-BOUNDARY\r\nHEADER1\r\n\r\nBODY1\r\n"
- 			"--MY-BOUNDARY\r\nHEADER2\r\n\r\nBODY2";
- 
- 		vmime::bodyPart p;
--- 
-1.7.10.4
-
-
-From c63f37c888798f0e7e99aa03afda16445a72b7b2 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 21 Jan 2011 15:28:06 +0000
-Subject: [PATCH 06/47] Fixed possible infinite loop (thanks to John van der
- Kamp, Zarafa).
-
-
-diff --git a/src/word.cpp b/src/word.cpp
-index db720dc..1c1c1a6 100644
---- a/src/word.cpp
-+++ b/src/word.cpp
-@@ -386,7 +386,7 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe
- 
- 		maxRunLength = std::max(maxRunLength, curRunLength);
- 
--		if (maxRunLength >= maxLineLength - 3)
-+		if (((flags & text::FORCE_NO_ENCODING) == 0) && maxRunLength >= maxLineLength - 3)
- 		{
- 			// Generate with encoding forced
- 			generate(os, maxLineLength, curLinePos, newLinePos, flags | text::FORCE_ENCODING, state);
-diff --git a/tests/parser/textTest.cpp b/tests/parser/textTest.cpp
-index b84f376..746ac94 100644
---- a/tests/parser/textTest.cpp
-+++ b/tests/parser/textTest.cpp
-@@ -52,6 +52,7 @@ VMIME_TEST_SUITE_BEGIN
- 		VMIME_TEST(testWhitespaceMBox)
- 
- 		VMIME_TEST(testFoldingAscii)
-+		VMIME_TEST(testForcedNonEncoding)
- 	VMIME_TEST_LIST_END
- 
- 
-@@ -442,5 +443,15 @@ VMIME_TEST_SUITE_BEGIN
- 			" =?us-ascii?Q?9012345678901234567890123456789?=", w.generate(50));
- 	}
- 
-+	void testForcedNonEncoding()
-+	{
-+		// Testing long unbreakable and unencodable header
-+		vmime::relay r;
-+		r.parse(" from User (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1]) by servername.hostname.com\n\t"
-+				"with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009 09:23:49 +0100");
-+
-+		VASSERT_EQ("received.long", "from User\r\n (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1])\r\n by servername.hostname.com with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009\r\n 09:23:49 +0100", r.generate(78));
-+	}
-+
- VMIME_TEST_SUITE_END
- 
--- 
-1.7.10.4
-
-
-From 1fafad8f913e700b350e6915de8be710fc2d1ced Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 28 Jan 2011 12:11:08 +0000
-Subject: [PATCH 07/47] Fixed possible read to invalid memory location (thanks
- to Alexander Konovalov).
-
-
-diff --git a/src/word.cpp b/src/word.cpp
-index 1c1c1a6..fa08d33 100644
---- a/src/word.cpp
-+++ b/src/word.cpp
-@@ -460,7 +460,7 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe
- 
- 					os << string(curLineStart, p);
- 
--					if (parserHelpers::isSpace(*(p - 1)))
-+					if (p != m_buffer.begin() && parserHelpers::isSpace(*(p - 1)))
- 						state->lastCharIsSpace = true;
- 					else
- 						state->lastCharIsSpace = false;
--- 
-1.7.10.4
-
-
-From 73298423f695d7c4441d44619e4b7f9de75f566e Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Wed, 9 Mar 2011 18:03:31 +0000
-Subject: [PATCH 08/47] Fixed bug #3174903. Fixed word parsing when buffer
- does not end with NL. Fixed 'no encoding' when
- forced.
-
-
-diff --git a/src/body.cpp b/src/body.cpp
-index 738d3e7..8596833 100644
---- a/src/body.cpp
-+++ b/src/body.cpp
-@@ -153,7 +153,10 @@ void body::parse(const string& buffer, const string::size_type position,
- 
- 		if (pos != string::npos && pos < end)
- 		{
--			m_prologText = string(buffer.begin() + position, buffer.begin() + pos);
-+			vmime::text text;
-+			text.parse(buffer, position, pos);
-+
-+			m_prologText = text.getWholeBuffer();
- 		}
- 
- 		for (int index = 0 ; !lastPart && (pos != string::npos) && (pos < end) ; ++index)
-@@ -246,7 +249,10 @@ void body::parse(const string& buffer, const string::size_type position,
- 		// Treat remaining text as epilog
- 		else if (partStart < end)
- 		{
--			m_epilogText = string(buffer.begin() + partStart, buffer.begin() + end);
-+			vmime::text text;
-+			text.parse(buffer, partStart, end);
-+
-+			m_epilogText = text.getWholeBuffer();
- 		}
- 	}
- 	// Treat the contents as 'simple' data
-@@ -333,7 +339,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
- 
- 		if (!prologText.empty())
- 		{
--			text prolog(word(prologText, getCharset()));
-+			text prolog(prologText, vmime::charset("us-ascii"));
- 
- 			prolog.encodeAndFold(os, maxLineLength, 0,
- 				NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE);
-@@ -356,7 +362,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
- 
- 		if (!epilogText.empty())
- 		{
--			text epilog(word(epilogText, getCharset()));
-+			text epilog(epilogText, vmime::charset("us-ascii"));
- 
- 			epilog.encodeAndFold(os, maxLineLength, 0,
- 				NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE);
-diff --git a/src/word.cpp b/src/word.cpp
-index fa08d33..aeaa737 100644
---- a/src/word.cpp
-+++ b/src/word.cpp
-@@ -102,7 +102,9 @@ ref <word> word::parseNext(const string& buffer, const string::size_type positio
- 				++pos;
- 
- 			unencoded += buffer.substr(startPos, endPos - startPos);
--			unencoded += ' ';
-+
-+			if (pos != end)  // ignore white-spaces at end
-+				unencoded += ' ';
- 
- 			startPos = pos;
- 			continue;
-@@ -191,14 +193,15 @@ ref <word> word::parseNext(const string& buffer, const string::size_type positio
- 		++pos;
- 	}
- 
--	// Treat unencoded text at the end of the buffer
--	if (end != startPos)
--	{
--		if (startPos != pos && !isFirst && prevIsEncoded)
--			unencoded += whiteSpaces;
-+	if (startPos != end && !isFirst && prevIsEncoded)
-+		unencoded += whiteSpaces;
- 
-+	if (startPos != end)
- 		unencoded += buffer.substr(startPos, end - startPos);
- 
-+	// Treat unencoded text at the end of the buffer
-+	if (!unencoded.empty())
-+	{
- 		ref <word> w = vmime::create <word>(unencoded, charset(charsets::US_ASCII));
- 		w->setParsedBounds(position, end);
- 
-@@ -337,12 +340,14 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe
- 		state = &defaultGeneratorState;
- 
- 	// Find out if encoding is forced or required by contents + charset
--	bool encodingNeeded = (flags & text::FORCE_ENCODING) != 0;
-+	bool encodingNeeded = false;
- 
--	if (encodingNeeded == false)
--		encodingNeeded = wordEncoder::isEncodingNeeded(m_buffer, m_charset);
--	else if ((flags & text::FORCE_NO_ENCODING) != 0)
-+	if ((flags & text::FORCE_NO_ENCODING) != 0)
- 		encodingNeeded = false;
-+	else if ((flags & text::FORCE_ENCODING) != 0)
-+		encodingNeeded = true;
-+	else  // auto-detect
-+		encodingNeeded = wordEncoder::isEncodingNeeded(m_buffer, m_charset);
- 
- 	// If possible and requested (with flag), quote the buffer (no folding is performed).
- 	// Quoting is possible if and only if:
-diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp
-index df2bf85..b129913 100644
---- a/tests/parser/bodyPartTest.cpp
-+++ b/tests/parser/bodyPartTest.cpp
-@@ -34,6 +34,8 @@ VMIME_TEST_SUITE_BEGIN
- 		VMIME_TEST(testParse)
- 		VMIME_TEST(testGenerate)
- 		VMIME_TEST(testParseMissingLastBoundary)
-+		VMIME_TEST(testPrologEpilog)
-+		VMIME_TEST(testPrologEncoding)
- 	VMIME_TEST_LIST_END
- 
- 
-@@ -105,5 +107,79 @@ VMIME_TEST_SUITE_BEGIN
- 		VASSERT_EQ("1", "Foo: bar\r\n\r\nBaz", p1.generate());
- 	}
- 
-+	void testPrologEpilog()
-+	{
-+		const char testMail[] =
-+			"To: test@vmime.org\r\n"
-+			"From: test@vmime.org\r\n"
-+			"Subject: Prolog and epilog test\r\n"
-+			"Content-Type: multipart/mixed; \r\n"
-+			" boundary=\"=_boundary\"\r\n"
-+			"\r\n"
-+			"Prolog text\r\n"
-+			"--=_boundary\r\n"
-+			"Content-Type: text/plain\r\n"
-+			"\r\n"
-+			"Part1\r\n"
-+			"--=_boundary--\r\n"
-+			"Epilog text";
-+
-+		vmime::bodyPart part;
-+		part.parse(testMail);
-+
-+		VASSERT_EQ("prolog", "Prolog text", part.getBody()->getPrologText());
-+		VASSERT_EQ("epilog", "Epilog text", part.getBody()->getEpilogText());
-+	}
-+
-+	// Test for bug fix: prolog should not be encoded
-+	// http://sourceforge.net/tracker/?func=detail&atid=525568&aid=3174903&group_id=69724
-+	void testPrologEncoding()
-+	{
-+		const char testmail[] =
-+			"To: test@vmime.org\r\n"
-+			"From: test@vmime.org\r\n"
-+			"Subject: Prolog encoding test\r\n"
-+			"Content-Type: multipart/mixed; \r\n"
-+			" boundary=\"=_+ZWjySayKqSf2CyrfnNpaAcO6-G1HpoXdHZ4YyswAWqEY39Q\"\r\n"
-+			"\r\n"
-+			"This is a multi-part message in MIME format. Your mail reader does not\r\n"
-+			"understand MIME message format.\r\n"
-+			"--=_+ZWjySayKqSf2CyrfnNpaAcO6-G1HpoXdHZ4YyswAWqEY39Q\r\n"
-+			"Content-Type: text/html; charset=windows-1251\r\n"
-+			"Content-Transfer-Encoding: quoted-printable\r\n"
-+			"\r\n"
-+			"=DD=F2=EE =F2=E5=EA=F1=F2=EE=E2=E0=FF =F7=E0=F1=F2=FC =F1=EB=EE=E6=ED=EE=E3=\r\n"
-+			"=EE =F1=EE=EE=E1=F9=E5=ED=E8=FF\r\n"
-+			"--=_+ZWjySayKqSf2CyrfnNpaAcO6-G1HpoXdHZ4YyswAWqEY39Q\r\n"
-+			"Content-Type: application/octet-stream; charset=windows-1251\r\n"
-+			"Content-Disposition: attachment; filename=FNS.zip\r\n"
-+			"Content-Transfer-Encoding: base64\r\n"
-+			"\r\n"
-+			"UEsDBB...snap...EEAAAAAA==\r\n"
-+			"--=_+ZWjySayKqSf2CyrfnNpaAcO6-G1HpoXdHZ4YyswAWqEY39Q--\r\n"
-+			"Epilog text";
-+
-+		vmime::ref<vmime::message> msg = vmime::create<vmime::message>();
-+
-+		std::string istr(testmail);
-+
-+		std::string ostr;
-+		vmime::utility::outputStreamStringAdapter out(ostr);
-+
-+		for (int i = 0 ; i < 10 ; ++i)
-+		{
-+			ostr.clear();
-+
-+			msg->parse(istr);
-+			msg->generate(out);
-+
-+			istr = ostr;
-+		}
-+
-+		VASSERT_EQ("prolog", "This is a multi-part message in MIME format. Your mail reader"
-+					   " does not understand MIME message format.", msg->getBody()->getPrologText());
-+		VASSERT_EQ("epilog", "Epilog text", msg->getBody()->getEpilogText());
-+	}
-+
- VMIME_TEST_SUITE_END
- 
--- 
-1.7.10.4
-
-
-From 5f5757b9d4bb0febb1e2183578eb91e801a08038 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 27 Mar 2011 11:26:55 +0000
-Subject: [PATCH 09/47] Allow static linking in mingw-cross-env. Added 'iconv'
- and uses 'ws2_32' instead of 'winsock32' (#3213487).
-
-
-diff --git a/SConstruct b/SConstruct
-index 55f9223..177f5b4 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -1089,7 +1089,7 @@ def generateAutotools(target, source, env):
- 	vmime_pc_in.write("Description: " + packageDescription + "\n")
- 	vmime_pc_in.write("Version: @VERSION@\n")
- 	vmime_pc_in.write("Requires: @GSASL_REQUIRED@\n")
--	vmime_pc_in.write("Libs: -L${libdir} -l@GENERIC_VERSIONED_LIBRARY_NAME@ @GSASL_LIBS@ @LIBGNUTLS_LIBS@ @VMIME_ADDITIONAL_PC_LIBS@\n")
-+	vmime_pc_in.write("Libs: -L${libdir} -l@GENERIC_VERSIONED_LIBRARY_NAME@ @GSASL_LIBS@ @LIBGNUTLS_LIBS@ @LIBICONV@ @PTHREAD_LIBS@ @VMIME_ADDITIONAL_PC_LIBS@\n")
- 	#vmime_pc_in.write("Cflags: -I${includedir}/@GENERIC_VERSIONED_LIBRARY_NAME@\n")
- 	vmime_pc_in.write("Cflags: -I${includedir}/ @LIBGNUTLS_CFLAGS@\n")
- 	vmime_pc_in.close()
-@@ -1709,7 +1709,7 @@ fi
- 
- # -- Link with Winsock (Windows)
- if test "x$VMIME_DETECT_PLATFORM" = "xwindows"; then
--	VMIME_ADDITIONAL_PC_LIBS="$VMIME_ADDITIONAL_PC_LIBS -lwsock32"
-+	VMIME_ADDITIONAL_PC_LIBS="$VMIME_ADDITIONAL_PC_LIBS -lws2_32"
- fi
- 
- # -- getaddrinfo (POSIX)
--- 
-1.7.10.4
-
-
-From 2b48b4a68ce3e9b9b1a3f485123af5938a568324 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 31 Mar 2011 19:13:03 +0000
-Subject: [PATCH 10/47] Flush stateful data from iconv (thanks to John van der
- Kamp, Zarafa).
-
-
-diff --git a/src/charsetConverter.cpp b/src/charsetConverter.cpp
-index 38b9e5e..2135788 100644
---- a/src/charsetConverter.cpp
-+++ b/src/charsetConverter.cpp
-@@ -119,6 +119,7 @@ void charsetConverter::convert(utility::inputStream& in, utility::outputStream&
- 	size_t inPos = 0;
- 
- 	bool prevIsInvalid = false;
-+	bool breakAfterNext = false;
- 
- 	while (true)
- 	{
-@@ -126,11 +127,12 @@ void charsetConverter::convert(utility::inputStream& in, utility::outputStream&
- 		size_t inLength = static_cast <size_t>(in.read(inBuffer + inPos, sizeof(inBuffer) - inPos) + inPos);
- 		size_t outLength = sizeof(outBuffer);
- 
--		const char* inPtr = inBuffer;
-+		const char* inPtr = breakAfterNext ? NULL : inBuffer;
-+		size_t *ptrLength = breakAfterNext ? NULL : &inLength;
- 		char* outPtr = outBuffer;
- 
- 		// Convert input bytes
--		if (iconv(cd, ICONV_HACK(&inPtr), &inLength,
-+		if (iconv(cd, ICONV_HACK(&inPtr), ptrLength,
- 			      &outPtr, &outLength) == static_cast <size_t>(-1))
- 		{
- 			// Illegal input sequence or input sequence has no equivalent
-@@ -170,9 +172,12 @@ void charsetConverter::convert(utility::inputStream& in, utility::outputStream&
- 			prevIsInvalid = false;
- 		}
- 
--		// Check for end of data
--		if (in.eof() && inPos == 0)
-+		if (breakAfterNext)
- 			break;
-+
-+		// Check for end of data, loop again to flush stateful data from iconv
-+		if (in.eof() && inPos == 0)
-+			breakAfterNext = true;
- 	}
- }
- 
-diff --git a/tests/parser/charsetTest.cpp b/tests/parser/charsetTest.cpp
-index 8ad71d7..54a09a7 100644
---- a/tests/parser/charsetTest.cpp
-+++ b/tests/parser/charsetTest.cpp
-@@ -100,6 +100,7 @@ VMIME_TEST_SUITE_BEGIN
- 		VMIME_TEST(testFilterValid1)
- 		VMIME_TEST(testFilterValid2)
- 		VMIME_TEST(testFilterValid3)
-+		VMIME_TEST(testEncodingHebrew1255)
- 
- 		// Test invalid input
- 		VMIME_TEST(testFilterInvalid1)
-@@ -227,6 +228,15 @@ VMIME_TEST_SUITE_BEGIN
- 		VASSERT_EQ("1", toHex(expectedOut), toHex(actualOut));
- 	}
- 
-+	void testEncodingHebrew1255()
-+	{
-+		// hewbrew string in windows-1255 charset
-+		const char data[] = "\xe9\xf9\xf7\xf8\xe9\xf9\xf8\xf7\xe9\xe9\xf9";
-+		vmime::word w = vmime::word(data, "windows-1255");
-+		vmime::string encoded = w.generate();
-+		// less than 60% ascii, base64 received
-+		VASSERT_EQ("1", "=?windows-1255?B?6fn3+On5+Pfp6fk=?=", encoded);
-+	}
- 
- 	// Conversion to hexadecimal for easier debugging
- 	static const vmime::string toHex(const vmime::string str)
--- 
-1.7.10.4
-
-
-From 8d2e039c5201e144ff08e2ff7cf9efe77fe4b3d0 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 10 Jun 2011 19:39:09 +0000
-Subject: [PATCH 11/47] Requested email change.
-
-
-diff --git a/AUTHORS b/AUTHORS
-index 20a0181..bbddb30 100644
---- a/AUTHORS
-+++ b/AUTHORS
-@@ -21,7 +21,7 @@ AUTHORS file.
-  - Rafael Fernandez <prf@adinet.com.uy>
-  - Xin Li <lixin3@staff.sina.com.cn>
-  - Benjamin Biron <benbiron@gmail.com>
-- - Bertrand Benoit <bsquare@bsquare.levillage.org>
-+ - Bertrand Benoit <projettwk@users.sourceforge.net>
-  - Tim Teulings <rael@edge.ping.de>
-  - Georg Sauthoff <gsauthof@techfak.uni-bielefeld.de>
-  - Pierre Thierry <nowhere.man@levallois.eu.org> (patches for STL algorithms)
--- 
-1.7.10.4
-
-
-From cc6317f28ae0b61fea36e1bc78b09dc8300579f8 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Tue, 14 Jun 2011 18:37:54 +0000
-Subject: [PATCH 12/47] Fixed compilation issue following namespace change.
-
-
-diff --git a/examples/example7.cpp b/examples/example7.cpp
-index 1ddb3d0..243b1da 100644
---- a/examples/example7.cpp
-+++ b/examples/example7.cpp
-@@ -43,18 +43,18 @@ int main()
- 	vmime::platform::setHandler<vmime::platforms::posix::posixHandler>();
- 
- 	// Enumerate encoders
--	vmime::encoderFactory* ef = vmime::encoderFactory::getInstance();
-+	vmime::utility::encoder::encoderFactory* ef = vmime::utility::encoder::encoderFactory::getInstance();
- 
- 	std::cout << "Available encoders:" << std::endl;
- 
- 	for (int i = 0 ; i < ef->getEncoderCount() ; ++i)
- 	{
--		vmime::ref <const vmime::encoderFactory::registeredEncoder>
-+		vmime::ref <const vmime::utility::encoder::encoderFactory::registeredEncoder>
- 			enc = ef->getEncoderAt(i);
- 
- 		std::cout << "  * " << enc->getName() << std::endl;
- 
--		vmime::ref <vmime::encoder> e = enc->create();
-+		vmime::ref <vmime::utility::encoder::encoder> e = enc->create();
- 
- 		std::vector <vmime::string> props = e->getAvailableProperties();
- 
--- 
-1.7.10.4
-
-
-From a916d12d44ac43fc8e4729e0a91f4d6243f29a11 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 19 Jun 2011 17:51:33 +0000
-Subject: [PATCH 13/47] Fixed parsing of an attachment filename that is
- between 66 and 76 characters long (Zarafa).
-
-
-diff --git a/src/parameter.cpp b/src/parameter.cpp
-index 91a7e5c..f59d5ab 100644
---- a/src/parameter.cpp
-+++ b/src/parameter.cpp
-@@ -281,7 +281,8 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 	bool needQuoting = false;
- 	string::size_type valueLength = 0;
- 
--	for (string::size_type i = 0 ; (i < value.length()) && (pos + valueLength < maxLineLength - 4) ; ++i, ++valueLength)
-+	// Use worst-case length name.length()+2 for 'name=' part of line
-+	for (string::size_type i = 0 ; (i < value.length()) && (pos + name.length() + 2 + valueLength < maxLineLength - 4) ; ++i, ++valueLength)
- 	{
- 		switch (value[i])
- 		{
--- 
-1.7.10.4
-
-
-From 9735165c57000a6368e91ce8852206a20930c1ca Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 19 Jun 2011 18:08:12 +0000
-Subject: [PATCH 14/47] Correctly generate attachment names which are long and
- have high characters for Outlook Express (Zarafa).
-
-
-diff --git a/src/parameter.cpp b/src/parameter.cpp
-index f59d5ab..d757e1b 100644
---- a/src/parameter.cpp
-+++ b/src/parameter.cpp
-@@ -268,17 +268,19 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 	// value is to be generated.
- 
- 	// A stream for a temporary storage
--	std::ostringstream sevenBitBuffer;
-+	std::string sevenBitBuffer;
-+	utility::outputStreamStringAdapter sevenBitStream(sevenBitBuffer);
- 
- 	string::size_type pos = curLinePos;
- 
- 	if (pos + name.length() + 10 + value.length() > maxLineLength)
- 	{
--		sevenBitBuffer << NEW_LINE_SEQUENCE;
-+		sevenBitStream << NEW_LINE_SEQUENCE;
- 		pos = NEW_LINE_SEQUENCE_LENGTH;
- 	}
- 
- 	bool needQuoting = false;
-+	bool needQuotedPrintable = false;
- 	string::size_type valueLength = 0;
- 
- 	// Use worst-case length name.length()+2 for 'name=' part of line
-@@ -308,6 +310,16 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 
- 			needQuoting = true;
- 			break;
-+
-+		default:
-+
-+			if (!parserHelpers::isAscii(value[i]))
-+			{
-+				needQuotedPrintable = true;
-+				needQuoting = true;
-+			}
-+
-+			break;
- 		}
- 	}
- 
-@@ -315,12 +327,12 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 
- 	if (needQuoting)
- 	{
--		sevenBitBuffer << name << "=\"";
-+		sevenBitStream << name << "=\"";
- 		pos += name.length() + 2;
- 	}
- 	else
- 	{
--		sevenBitBuffer << name << "=";
-+		sevenBitStream << name << "=";
- 		pos += name.length() + 1;
- 	}
- 
-@@ -332,29 +344,43 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 	const bool alwaysEncode = m_value.getCharset().getRecommendedEncoding(recommendedEnc);
- 	bool extended = alwaysEncode;
- 
--	for (string::size_type i = 0 ; (i < value.length()) && (pos < maxLineLength - 4) ; ++i)
-+	if (needQuotedPrintable)
- 	{
--		const char_t c = value[i];
--
--		if (/* needQuoting && */ (c == '"' || c == '\\'))  // 'needQuoting' is implicit
--		{
--			sevenBitBuffer << '\\' << value[i];  // escape 'x' with '\x'
--			pos += 2;
--		}
--		else if (parserHelpers::isAscii(c))
--		{
--			sevenBitBuffer << value[i];
--			++pos;
--		}
--		else
-+		// Send the name in quoted-printable, so outlook express et.al.
-+		// will understand the real filename
-+		size_t oldLen = sevenBitBuffer.length();
-+		m_value.generate(sevenBitStream);
-+		pos += sevenBitBuffer.length() - oldLen;
-+		extended = true;		// also send with RFC-2231 encoding
-+	}
-+	else
-+	{
-+		// Do not chop off this value, but just add the complete name as one header line.
-+		for (string::size_type i = 0 ; i < value.length() ; ++i)
- 		{
--			extended = true;
-+			const char_t c = value[i];
-+
-+			if (/* needQuoting && */ (c == '"' || c == '\\'))  // 'needQuoting' is implicit
-+			{
-+				sevenBitStream << '\\' << value[i];  // escape 'x' with '\x'
-+				pos += 2;
-+			}
-+			else if (parserHelpers::isAscii(c))
-+			{
-+				sevenBitStream << value[i];
-+				++pos;
-+			}
-+			else
-+			{
-+				extended = true;
-+			}
- 		}
--	}
-+
-+	} // !needQuotedPrintable
- 
- 	if (needQuoting)
- 	{
--		sevenBitBuffer << '"';
-+		sevenBitStream << '"';
- 		++pos;
- 	}
- 
-@@ -532,7 +558,7 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 		// "7bit/us-ascii" will suffice in this case.
- 
- 		// Output what has been stored in temporary buffer so far
--		os << sevenBitBuffer.str();
-+		os << sevenBitBuffer;
- 	}
- #endif // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
- 
--- 
-1.7.10.4
-
-
-From 8d69ad6849d8d6b211674942157f2af8bcd51c26 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 19 Jun 2011 18:16:49 +0000
-Subject: [PATCH 15/47] Alias for UTF-7 charset.
-
-
-diff --git a/src/charset.cpp b/src/charset.cpp
-index e043186..0fda450 100644
---- a/src/charset.cpp
-+++ b/src/charset.cpp
-@@ -45,6 +45,9 @@ charset::charset()
- charset::charset(const string& name)
- 	: m_name(name)
- {
-+	// If we receive this rfc-1642 valid MIME charset, convert it to something usefull for iconv
-+	if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7"))
-+		m_name = "utf-7";
- }
- 
- 
-@@ -60,6 +63,10 @@ void charset::parse(const string& buffer, const string::size_type position,
- 	m_name = utility::stringUtils::trim
- 		(string(buffer.begin() + position, buffer.begin() + end));
- 
-+	// If we parsed this rfc-1642 valid MIME charset, convert it to something usefull for iconv
-+	if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7"))
-+		m_name = "utf-7";
-+
- 	setParsedBounds(position, end);
- 
- 	if (newPosition)
--- 
-1.7.10.4
-
-
-From ccd95daf9cdd7171fc2027afa5d0ad80b0475ded Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 19 Jun 2011 18:39:35 +0000
-Subject: [PATCH 16/47] Fixed messageBuilder to accept an empty mailbox group
- in 'To:' field, to allow for undisclosed-recipients
- (Zarafa).
-
-
-diff --git a/src/messageBuilder.cpp b/src/messageBuilder.cpp
-index 870d59e..3597b3a 100644
---- a/src/messageBuilder.cpp
-+++ b/src/messageBuilder.cpp
-@@ -51,17 +51,15 @@ ref <message> messageBuilder::construct() const
- 	// Generate the header fields
- 	msg->getHeader()->Subject()->setValue(m_subject);
- 
--	if (m_from.isEmpty())
--		throw exceptions::no_expeditor();
--
--	if ((m_to.isEmpty() || m_to.getAddressAt(0)->isEmpty()) &&
-+	if (((m_to.isEmpty()) || (m_to.getAddressAt(0)->isEmpty() && !m_to.getAddressAt(0)->isGroup())) &&
- 	    (m_cc.isEmpty() || m_cc.getAddressAt(0)->isEmpty()) &&
- 	    (m_bcc.isEmpty() || m_bcc.getAddressAt(0)->isEmpty()))
- 	{
- 		throw exceptions::no_recipient();
- 	}
- 
--	msg->getHeader()->From()->setValue(m_from);
-+	if (!m_from.isEmpty())
-+		msg->getHeader()->From()->setValue(m_from);
- 
- 	if (!m_to.isEmpty())
- 		msg->getHeader()->To()->setValue(m_to);
--- 
-1.7.10.4
-
-
-From 583e25bcdee132e53e0792cd8f0d8e535cabb743 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 19 Jun 2011 18:49:55 +0000
-Subject: [PATCH 17/47] Added support for mailboxes that specify an (encoded)
- full name with an empty email address, set by a <>
- marker (Zarafa).
-
-
-diff --git a/src/mailbox.cpp b/src/mailbox.cpp
-index 5cb0139..fea7479 100644
---- a/src/mailbox.cpp
-+++ b/src/mailbox.cpp
-@@ -88,6 +88,7 @@ void mailbox::parse(const string& buffer, const string::size_type position,
- 	// Temporary buffers for extracted name and address
- 	string name;
- 	string address;
-+	bool hadBrackets = false;
- 
- 	while (p < pend)
- 	{
-@@ -283,6 +284,7 @@ void mailbox::parse(const string& buffer, const string::size_type position,
- 				}
- 				else if (*p == '>')
- 				{
-+					hadBrackets = true;
- 					break;
- 				}
- 				else if (!parserHelpers::isSpace(*p))
-@@ -309,7 +311,7 @@ void mailbox::parse(const string& buffer, const string::size_type position,
- 
- 	// Swap name and address when no address was found
- 	// (email address is mandatory, whereas name is optional).
--	if (address.empty() && !name.empty())
-+	if (address.empty() && !name.empty() && !hadBrackets)
- 	{
- 		m_email.clear();
- 		m_email.reserve(name.size());
-diff --git a/tests/parser/mailboxTest.cpp b/tests/parser/mailboxTest.cpp
-index 8411daa..9ebadca 100644
---- a/tests/parser/mailboxTest.cpp
-+++ b/tests/parser/mailboxTest.cpp
-@@ -32,6 +32,7 @@ VMIME_TEST_SUITE_BEGIN
- 
- 	VMIME_TEST_LIST_BEGIN
- 		VMIME_TEST(testParse)
-+		VMIME_TEST(testEmptyEmailAddress)
- 	VMIME_TEST_LIST_END
- 
- 
-@@ -113,5 +114,19 @@ VMIME_TEST_SUITE_BEGIN
- 		}
- 	}
- 
-+	void testEmptyEmailAddress()
-+	{
-+		vmime::addressList addrList;
-+		addrList.parse("\"Full Name\" <>");
-+
-+		VASSERT_EQ("count", 1, addrList.getAddressCount());
-+		VASSERT_EQ("!group", false, addrList.getAddressAt(0)->isGroup());
-+
-+		vmime::ref <vmime::mailbox> mbox = addrList.getAddressAt(0).dynamicCast <vmime::mailbox>();
-+
-+		VASSERT_EQ("name", "Full Name", mbox->getName());
-+		VASSERT_EQ("email", "", mbox->getEmail());
-+	}
-+
- VMIME_TEST_SUITE_END
- 
--- 
-1.7.10.4
-
-
-From 461b92f84d5c16b297d33610fcd89fc7ca5a161a Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 24 Jun 2011 15:46:23 +0000
-Subject: [PATCH 18/47] Added missing libs in pkg-config file.
-
-
-diff --git a/SConstruct b/SConstruct
-index 177f5b4..37c0ac6 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -1089,7 +1089,7 @@ def generateAutotools(target, source, env):
- 	vmime_pc_in.write("Description: " + packageDescription + "\n")
- 	vmime_pc_in.write("Version: @VERSION@\n")
- 	vmime_pc_in.write("Requires: @GSASL_REQUIRED@\n")
--	vmime_pc_in.write("Libs: -L${libdir} -l@GENERIC_VERSIONED_LIBRARY_NAME@ @GSASL_LIBS@ @LIBGNUTLS_LIBS@ @LIBICONV@ @PTHREAD_LIBS@ @VMIME_ADDITIONAL_PC_LIBS@\n")
-+	vmime_pc_in.write("Libs: -L${libdir} -l@GENERIC_VERSIONED_LIBRARY_NAME@ @GSASL_LIBS@ @LIBGNUTLS_LIBS@ @LIBICONV@ @PTHREAD_LIBS@ @LIBICONV@ @PTHREAD_LIBS@ @VMIME_ADDITIONAL_PC_LIBS@\n")
- 	#vmime_pc_in.write("Cflags: -I${includedir}/@GENERIC_VERSIONED_LIBRARY_NAME@\n")
- 	vmime_pc_in.write("Cflags: -I${includedir}/ @LIBGNUTLS_CFLAGS@\n")
- 	vmime_pc_in.close()
--- 
-1.7.10.4
-
-
-From 2b2c0abd02a17ccff7d49e266b9854f4ea47f8e4 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sat, 25 Jun 2011 17:07:53 +0000
-Subject: [PATCH 19/47] Fixed parsing of empty body parts (thanks to John van
- der Kamp, from Zarafa).
-
-
-diff --git a/src/body.cpp b/src/body.cpp
-index 8596833..9d7d57f 100644
---- a/src/body.cpp
-+++ b/src/body.cpp
-@@ -197,6 +197,11 @@ void body::parse(const string& buffer, const string::size_type position,
- 			{
- 				ref <bodyPart> part = vmime::create <bodyPart>();
- 
-+				// End before start may happen on empty bodyparts (directly
-+				// successive boundaries without even a line-break)
-+				if (partEnd < partStart)
-+					std::swap(partStart, partEnd);
-+
- 				part->parse(buffer, partStart, partEnd, NULL);
- 				part->m_parent = m_part;
- 
-diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp
-index b129913..075b8f9 100644
---- a/tests/parser/bodyPartTest.cpp
-+++ b/tests/parser/bodyPartTest.cpp
-@@ -36,6 +36,7 @@ VMIME_TEST_SUITE_BEGIN
- 		VMIME_TEST(testParseMissingLastBoundary)
- 		VMIME_TEST(testPrologEpilog)
- 		VMIME_TEST(testPrologEncoding)
-+		VMIME_TEST(testSuccessiveBoundaries)
- 	VMIME_TEST_LIST_END
- 
- 
-@@ -181,5 +182,23 @@ VMIME_TEST_SUITE_BEGIN
- 		VASSERT_EQ("epilog", "Epilog text", msg->getBody()->getEpilogText());
- 	}
- 
-+	void testSuccessiveBoundaries()
-+	{
-+		vmime::string str =
-+			"Content-Type: multipart/mixed; boundary=\"MY-BOUNDARY\""
-+			"\r\n\r\n"
-+			"--MY-BOUNDARY\r\nHEADER1\r\n\r\nBODY1\r\n"
-+			"--MY-BOUNDARY\r\n"
-+			"--MY-BOUNDARY--\r\n";
-+
-+		vmime::bodyPart p;
-+		p.parse(str);
-+
-+		VASSERT_EQ("count", 2, p.getBody()->getPartCount());
-+
-+		VASSERT_EQ("part1-body", "BODY1", extractContents(p.getBody()->getPartAt(0)->getBody()->getContents()));
-+		VASSERT_EQ("part2-body", "", extractContents(p.getBody()->getPartAt(1)->getBody()->getContents()));
-+	}
-+
- VMIME_TEST_SUITE_END
- 
--- 
-1.7.10.4
-
-
-From 2648d744da0e2e744c7959999ac513c3016072b4 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 26 Jun 2011 08:19:11 +0000
-Subject: [PATCH 20/47] Use gnutls_priority_set_direct() instead of GNUTLS
- deprecated functions.
-
-
-diff --git a/SConstruct b/SConstruct
-index 37c0ac6..01ad3f3 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -816,6 +816,7 @@ else:
- config_hpp.write('// -- TLS/SSL support\n')
- if env['with_tls'] == 'yes':
- 	config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 1\n')
-+	config_hpp.write('#define HAVE_GNUTLS_PRIORITY_FUNCS 1\n')
- else:
- 	config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 0\n')
- 
-@@ -1626,11 +1627,42 @@ if test "x$conf_tls" = "xyes"; then
- 	else
- 		AC_MSG_ERROR(can't find an usable version of GNU TLS library)
- 	fi
-+
-+	# -- check for gnutls_priority_set_direct() function
-+	if test "x$have_gnutls" = "xyes"; then
-+		AC_MSG_CHECKING(for gnutls_priority_set_direct)
-+
-+		LIBS_save="$LIBS"
-+		LIBS="$LIBS $LIBGNUTLS_LIBS"
-+		CPPFLAGS_save="$CPPFLAGS"
-+		CPPFLAGS="$CPPFLAGS $LIBGNUTLS_CFLAGS"
-+
-+		AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <gnutls/gnutls.h>],
-+		                                [gnutls_session s; gnutls_priority_set_direct(s, NULL, NULL);])],
-+		               [have_gnutls_priority_funcs=yes],
-+		               [have_gnutls_priority_funcs=no])
-+
-+		CPPFLAGS="$CPPFLAGS_save"
-+		LIBS="$LIBS_save"
-+
-+		AC_MSG_RESULT([$have_gnutls_priority_funcs])
-+
-+		if test "x$have_gnutls_priority_funcs" = "xyes"; then
-+			AM_CONDITIONAL(HAVE_GNUTLS_PRIORITY_FUNCS, true)
-+			HAVE_GNUTLS_PRIORITY_FUNCS=1
-+		else
-+			AM_CONDITIONAL(HAVE_GNUTLS_PRIORITY_FUNCS, false)
-+			HAVE_GNUTLS_PRIORITY_FUNCS=0
-+		fi
-+	fi
- else
- 	AM_CONDITIONAL(VMIME_HAVE_TLS_SUPPORT, false)
- 	VMIME_HAVE_TLS_SUPPORT=0
- fi
- 
-+AC_SUBST(LIBGNUTLS_CFLAGS)
-+AC_SUBST(LIBGNUTLS_LIBS)
-+
- # ** platform handlers
- 
- VMIME_BUILTIN_PLATFORMS=''
-@@ -1919,6 +1951,7 @@ typedef unsigned ${VMIME_TYPE_INT32} vmime_uint32;
- #define VMIME_HAVE_SASL_SUPPORT ${VMIME_HAVE_SASL_SUPPORT}
- // -- TLS support
- #define VMIME_HAVE_TLS_SUPPORT ${VMIME_HAVE_TLS_SUPPORT}
-+#define HAVE_GNUTLS_PRIORITY_FUNCS ${HAVE_GNUTLS_PRIORITY_FUNCS}
- // -- Messaging support
- #define VMIME_HAVE_MESSAGING_FEATURES ${VMIME_HAVE_MESSAGING_FEATURES}
- """)
-diff --git a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp
-index 010c007..af73a05 100644
---- a/src/net/tls/TLSSession.cpp
-+++ b/src/net/tls/TLSSession.cpp
-@@ -123,6 +123,21 @@ TLSSession::TLSSession(ref <security::cert::certificateVerifier> cv)
- 
- 	// Sets some default priority on the ciphers, key exchange methods,
- 	// macs and compression methods.
-+#if HAVE_GNUTLS_PRIORITY_FUNCS
-+
-+	if ((res = gnutls_priority_set_direct
-+		(*m_gnutlsSession, "NORMAL:%SSL3_RECORD_VERSION", NULL)) != 0)
-+	{
-+		if ((res = gnutls_priority_set_direct
-+			(*m_gnutlsSession, "NORMAL", NULL)) != 0)
-+		{
-+			throwTLSException
-+				("gnutls_priority_set_direct", res);
-+		}
-+	}
-+
-+#else  // !HAVE_GNUTLS_PRIORITY_FUNCS
-+
- 	gnutls_set_default_priority(*m_gnutlsSession);
- 
- 	// Sets the priority on the certificate types supported by gnutls.
-@@ -197,6 +212,8 @@ TLSSession::TLSSession(ref <security::cert::certificateVerifier> cv)
- 
- 	gnutls_compression_set_priority(*m_gnutlsSession, compressionPriority);
- 
-+#endif // !HAVE_GNUTLS_PRIORITY_FUNCS
-+
- 	// Initialize credentials
- 	gnutls_credentials_set(*m_gnutlsSession,
- 		GNUTLS_CRD_ANON, g_gnutlsGlobal.anonCred);
--- 
-1.7.10.4
-
-
-From 1060121ffd4315c3158ffc001040f4f705514e7a Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 26 Jun 2011 12:47:25 +0000
-Subject: [PATCH 21/47] Fixed encoding of whitespace. Fixed old test case.
-
-
-diff --git a/src/text.cpp b/src/text.cpp
-index 2454456..66c3b35 100644
---- a/src/text.cpp
-+++ b/src/text.cpp
-@@ -320,12 +320,6 @@ void text::createFromString(const string& in, const charset& ch)
- 					}
- 					else
- 					{
--						if (count)
--						{
--							ref <word> w = getWordAt(getWordCount() - 1);
--							w->getBuffer() += ' ';
--						}
--
- 						appendWord(vmime::create <word>
- 							(chunk, charset(charsets::US_ASCII)));
- 
-diff --git a/tests/parser/textTest.cpp b/tests/parser/textTest.cpp
-index 746ac94..43ec836 100644
---- a/tests/parser/textTest.cpp
-+++ b/tests/parser/textTest.cpp
-@@ -53,6 +53,8 @@ VMIME_TEST_SUITE_BEGIN
- 
- 		VMIME_TEST(testFoldingAscii)
- 		VMIME_TEST(testForcedNonEncoding)
-+
-+		VMIME_TEST(testBugFix20110511)
- 	VMIME_TEST_LIST_END
- 
- 
-@@ -149,7 +151,7 @@ VMIME_TEST_SUITE_BEGIN
- 		VASSERT_EQ("2.1", 3, t2.getWordCount());
- 		VASSERT_EQ("2.2", "some ASCII characters and special chars: ", t2.getWordAt(0)->getBuffer());
- 		VASSERT_EQ("2.3", vmime::charset(vmime::charsets::US_ASCII), t2.getWordAt(0)->getCharset());
--		VASSERT_EQ("2.4", "\xf1\xf2\xf3\xf4 ", t2.getWordAt(1)->getBuffer());
-+		VASSERT_EQ("2.4", "\xf1\xf2\xf3\xf4", t2.getWordAt(1)->getBuffer());
- 		VASSERT_EQ("2.5", c2, t2.getWordAt(1)->getCharset());
- 		VASSERT_EQ("2.6", "and then more ASCII chars.", t2.getWordAt(2)->getBuffer());
- 		VASSERT_EQ("2.7", vmime::charset(vmime::charsets::US_ASCII), t2.getWordAt(2)->getCharset());
-@@ -453,5 +455,43 @@ VMIME_TEST_SUITE_BEGIN
- 		VASSERT_EQ("received.long", "from User\r\n (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1])\r\n by servername.hostname.com with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009\r\n 09:23:49 +0100", r.generate(78));
- 	}
- 
-+	void testBugFix20110511()
-+	{
-+		/*
-+
-+		 Using the latest version of vmime (0.9.1), encoding the following string: Jean
-+		 Gwenaël Dutourd will result in:
-+		 Jean =?utf-8?Q?Gwena=C3=ABl_?= Dutourd
-+		 However, decoding this will result in Jean Gwenaël  Dutourd (notice two spaces
-+		 between the last 2 words).  The encoder adds a _ after the second word, but
-+		 since the last word is not encoded, the space between them is not ignored, and
-+		 is decoded into an additional space.
-+
-+		 See: http://sourceforge.net/projects/vmime/forums/forum/237357/topic/4531365
-+
-+		*/
-+
-+		const std::string DECODED_TEXT = "Jean Gwenaël Dutourd";
-+		const std::string ENCODED_TEXT = "Jean =?utf-8?Q?Gwena=C3=ABl?= Dutourd";
-+
-+		// Encode
-+		VASSERT_EQ("encode", ENCODED_TEXT,
-+			vmime::text::newFromString(DECODED_TEXT, vmime::charset("utf-8"))->generate());
-+
-+		// Decode
-+		vmime::text t;
-+		t.parse(ENCODED_TEXT);
-+
-+		// -- words
-+		std::ostringstream oss; oss << t;
-+		VASSERT_EQ("decode1",
-+			"[text: [[word: charset=us-ascii, buffer=Jean ],"
-+			        "[word: charset=utf-8, buffer=Gwenaël],"
-+				  "[word: charset=us-ascii, buffer= Dutourd]]]", oss.str());
-+
-+		// -- getWholeBuffer
-+		VASSERT_EQ("decode2", DECODED_TEXT, t.getWholeBuffer());
-+	}
-+
- VMIME_TEST_SUITE_END
- 
--- 
-1.7.10.4
-
-
-From dc6dc039fc0edccf4630894fa6ed8cd4bf3bb3ce Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sat, 20 Aug 2011 06:35:06 +0000
-Subject: [PATCH 22/47] Use gnutls_strerror() for reporting errors.
-
-
-diff --git a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp
-index af73a05..7426a73 100644
---- a/src/net/tls/TLSSession.cpp
-+++ b/src/net/tls/TLSSession.cpp
-@@ -41,6 +41,9 @@
- //#define GNUTLS_DEBUG 1
- 
- 
-+#include <sstream>
-+#include <iomanip>
-+
- #if VMIME_DEBUG && GNUTLS_DEBUG
- 	#include <iostream>
- #endif // VMIME_DEBUG && GNUTLS_DEBUG
-@@ -257,119 +260,14 @@ ref <security::cert::certificateVerifier> TLSSession::getCertificateVerifier()
- 
- void TLSSession::throwTLSException(const string& fname, const int code)
- {
--	string msg = fname + "() returned ";
--
--#define ERROR(x) \
--	case x: msg += #x; break;
--
--	switch (code)
--	{
--	ERROR(GNUTLS_E_SUCCESS)
--	ERROR(GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM)
--	ERROR(GNUTLS_E_UNKNOWN_CIPHER_TYPE)
--	ERROR(GNUTLS_E_LARGE_PACKET)
--	ERROR(GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
--	ERROR(GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
--	ERROR(GNUTLS_E_INVALID_SESSION)
--	ERROR(GNUTLS_E_FATAL_ALERT_RECEIVED)
--	ERROR(GNUTLS_E_UNEXPECTED_PACKET)
--	ERROR(GNUTLS_E_WARNING_ALERT_RECEIVED)
--	ERROR(GNUTLS_E_ERROR_IN_FINISHED_PACKET)
--	ERROR(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET)
--	ERROR(GNUTLS_E_UNKNOWN_CIPHER_SUITE)
--	ERROR(GNUTLS_E_UNWANTED_ALGORITHM)
--	ERROR(GNUTLS_E_MPI_SCAN_FAILED)
--	ERROR(GNUTLS_E_DECRYPTION_FAILED)
--	ERROR(GNUTLS_E_MEMORY_ERROR)
--	ERROR(GNUTLS_E_DECOMPRESSION_FAILED)
--	ERROR(GNUTLS_E_COMPRESSION_FAILED)
--	ERROR(GNUTLS_E_AGAIN)
--	ERROR(GNUTLS_E_EXPIRED)
--	ERROR(GNUTLS_E_DB_ERROR)
--	ERROR(GNUTLS_E_SRP_PWD_ERROR)
--	ERROR(GNUTLS_E_INSUFFICIENT_CREDENTIALS)
--	ERROR(GNUTLS_E_HASH_FAILED)
--	ERROR(GNUTLS_E_BASE64_DECODING_ERROR)
--	ERROR(GNUTLS_E_MPI_PRINT_FAILED)
--	ERROR(GNUTLS_E_REHANDSHAKE)
--	ERROR(GNUTLS_E_GOT_APPLICATION_DATA)
--	ERROR(GNUTLS_E_RECORD_LIMIT_REACHED)
--	ERROR(GNUTLS_E_ENCRYPTION_FAILED)
--	ERROR(GNUTLS_E_PK_ENCRYPTION_FAILED)
--	ERROR(GNUTLS_E_PK_DECRYPTION_FAILED)
--	ERROR(GNUTLS_E_PK_SIGN_FAILED)
--	ERROR(GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION)
--	ERROR(GNUTLS_E_KEY_USAGE_VIOLATION)
--	ERROR(GNUTLS_E_NO_CERTIFICATE_FOUND)
--	ERROR(GNUTLS_E_INVALID_REQUEST)
--	ERROR(GNUTLS_E_SHORT_MEMORY_BUFFER)
--	ERROR(GNUTLS_E_INTERRUPTED)
--	ERROR(GNUTLS_E_PUSH_ERROR)
--	ERROR(GNUTLS_E_PULL_ERROR)
--	ERROR(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER)
--	ERROR(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
--	ERROR(GNUTLS_E_PKCS1_WRONG_PAD)
--	ERROR(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION)
--	ERROR(GNUTLS_E_INTERNAL_ERROR)
--	ERROR(GNUTLS_E_DH_PRIME_UNACCEPTABLE)
--	ERROR(GNUTLS_E_FILE_ERROR)
--	ERROR(GNUTLS_E_TOO_MANY_EMPTY_PACKETS)
--	ERROR(GNUTLS_E_UNKNOWN_PK_ALGORITHM)
--	ERROR(GNUTLS_E_INIT_LIBEXTRA)
--	ERROR(GNUTLS_E_LIBRARY_VERSION_MISMATCH)
--	ERROR(GNUTLS_E_NO_TEMPORARY_RSA_PARAMS)
--	ERROR(GNUTLS_E_LZO_INIT_FAILED)
--	ERROR(GNUTLS_E_NO_COMPRESSION_ALGORITHMS)
--	ERROR(GNUTLS_E_NO_CIPHER_SUITES)
--	ERROR(GNUTLS_E_OPENPGP_GETKEY_FAILED)
--	ERROR(GNUTLS_E_PK_SIG_VERIFY_FAILED)
--	ERROR(GNUTLS_E_ILLEGAL_SRP_USERNAME)
--	ERROR(GNUTLS_E_SRP_PWD_PARSING_ERROR)
--	ERROR(GNUTLS_E_NO_TEMPORARY_DH_PARAMS)
--	ERROR(GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
--	ERROR(GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND)
--	ERROR(GNUTLS_E_ASN1_DER_ERROR)
--	ERROR(GNUTLS_E_ASN1_VALUE_NOT_FOUND)
--	ERROR(GNUTLS_E_ASN1_GENERIC_ERROR)
--	ERROR(GNUTLS_E_ASN1_VALUE_NOT_VALID)
--	ERROR(GNUTLS_E_ASN1_TAG_ERROR)
--	ERROR(GNUTLS_E_ASN1_TAG_IMPLICIT)
--	ERROR(GNUTLS_E_ASN1_TYPE_ANY_ERROR)
--	ERROR(GNUTLS_E_ASN1_SYNTAX_ERROR)
--	ERROR(GNUTLS_E_ASN1_DER_OVERFLOW)
--	//ERROR(GNUTLS_E_OPENPGP_TRUSTDB_VERSION_UNSUPPORTED)
--	ERROR(GNUTLS_E_OPENPGP_UID_REVOKED)
--	ERROR(GNUTLS_E_CERTIFICATE_ERROR)
--	//ERROR(GNUTLS_E_X509_CERTIFICATE_ERROR)
--	ERROR(GNUTLS_E_CERTIFICATE_KEY_MISMATCH)
--	ERROR(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE)
--	ERROR(GNUTLS_E_X509_UNKNOWN_SAN)
--	ERROR(GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED)
--	ERROR(GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE)
--	ERROR(GNUTLS_E_UNKNOWN_HASH_ALGORITHM)
--	ERROR(GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE)
--	ERROR(GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE)
--	ERROR(GNUTLS_E_INVALID_PASSWORD)
--	ERROR(GNUTLS_E_MAC_VERIFY_FAILED)
--	ERROR(GNUTLS_E_CONSTRAINT_ERROR)
--	ERROR(GNUTLS_E_BASE64_ENCODING_ERROR)
--	ERROR(GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY)
--	//ERROR(GNUTLS_E_INCOMPATIBLE_CRYPTO_LIBRARY)
--	ERROR(GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY)
--	ERROR(GNUTLS_E_OPENPGP_KEYRING_ERROR)
--	ERROR(GNUTLS_E_X509_UNSUPPORTED_OID)
--	//ERROR(GNUTLS_E_RANDOM_FAILED)
--	ERROR(GNUTLS_E_UNIMPLEMENTED_FEATURE)
--
--	default:
--
--		msg += "unknown error";
--		break;
--	}
-+	std::ostringstream msg;
- 
--#undef ERROR
-+	msg << fname + "() returned code ";
-+	msg << std::hex << code;
-+	msg << ": ";
-+	msg << gnutls_strerror(code);
- 
--	throw exceptions::tls_exception(msg);
-+	throw exceptions::tls_exception(msg.str());
- }
- 
- 
--- 
-1.7.10.4
-
-
-From 7ea6fc3737ef36407e1c90f3aa05f89a39bdefb7 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 21 Aug 2011 08:55:46 +0000
-Subject: [PATCH 23/47] Removed dependency on gcrypt for gnutls version >=
- 2.12.
-
-
-diff --git a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp
-index 7426a73..d3f6d49 100644
---- a/src/net/tls/TLSSession.cpp
-+++ b/src/net/tls/TLSSession.cpp
-@@ -26,9 +26,17 @@
- 
- #include "vmime/config.hpp"
- 
-+// Dependency on gcrypt is not needed since GNU TLS version 2.12.
-+// See here: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=638651
-+#if GNUTLS_VERSION_NUMBER <= 0x020b00
-+#	define VMIME_GNUTLS_NEEDS_GCRYPT  1
-+#endif
-+
- #if VMIME_HAVE_PTHREAD
- #	include <pthread.h>
--#	include <gcrypt.h>
-+#	if VMIME_GNUTLS_NEEDS_GCRYPT
-+#		include <gcrypt.h>
-+#	endif
- #	include <errno.h>
- #endif // VMIME_HAVE_PTHREAD
- 
-@@ -49,7 +57,7 @@
- #endif // VMIME_DEBUG && GNUTLS_DEBUG
- 
- 
--#if VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL)
-+#if VMIME_HAVE_PTHREAD && VMIME_GNUTLS_NEEDS_GCRYPT && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL)
- extern "C"
- {
- 	GCRY_THREAD_OPTION_PTHREAD_IMPL;
-@@ -70,7 +78,9 @@ struct TLSGlobal
- 	TLSGlobal()
- 	{
- #if VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL)
-+	#if VMIME_GNUTLS_NEEDS_GCRYPT
- 		gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
-+	#endif // VMIME_GNUTLS_NEEDS_GCRYPT
- #endif // VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL
- 
- 		gnutls_global_init();
--- 
-1.7.10.4
-
-
-From f21c55be642b166a2f0518ace2b179bed3916b23 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sun, 21 Aug 2011 09:04:46 +0000
-Subject: [PATCH 24/47] Fixed HAVE_GNUTLS_PRIORITY_FUNCS never defined when
- configured with no TLS support.
-
-
-diff --git a/SConstruct b/SConstruct
-index 01ad3f3..11e884b 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -1654,10 +1654,16 @@ if test "x$conf_tls" = "xyes"; then
- 			AM_CONDITIONAL(HAVE_GNUTLS_PRIORITY_FUNCS, false)
- 			HAVE_GNUTLS_PRIORITY_FUNCS=0
- 		fi
-+	else
-+		AM_CONDITIONAL(HAVE_GNUTLS_PRIORITY_FUNCS, false)
-+		HAVE_GNUTLS_PRIORITY_FUNCS=0
- 	fi
- else
- 	AM_CONDITIONAL(VMIME_HAVE_TLS_SUPPORT, false)
- 	VMIME_HAVE_TLS_SUPPORT=0
-+
-+	AM_CONDITIONAL(HAVE_GNUTLS_PRIORITY_FUNCS, false)
-+	HAVE_GNUTLS_PRIORITY_FUNCS=0
- fi
- 
- AC_SUBST(LIBGNUTLS_CFLAGS)
--- 
-1.7.10.4
-
-
-From d4e66226a696745adafa1767210580f8fbb7ae00 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Tue, 15 Nov 2011 11:40:42 +0000
-Subject: [PATCH 25/47] GNU TLS 3 has no 'extra' (thanks to mabrand).
-
-
-diff --git a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp
-index d3f6d49..cb50acc 100644
---- a/src/net/tls/TLSSession.cpp
-+++ b/src/net/tls/TLSSession.cpp
-@@ -22,7 +22,9 @@
- //
- 
- #include <gnutls/gnutls.h>
-+#if GNUTLS_VERSION_NUMBER < 0x030000
- #include <gnutls/extra.h>
-+#endif
- 
- #include "vmime/config.hpp"
- 
--- 
-1.7.10.4
-
-
-From bacbe512e406d22f6acc83597fcdfc2d624cf82b Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Tue, 15 Nov 2011 11:46:07 +0000
-Subject: [PATCH 26/47] Set Diffie-Hellman prime size (bug SF#3434852).
-
-
-diff --git a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp
-index cb50acc..0606808 100644
---- a/src/net/tls/TLSSession.cpp
-+++ b/src/net/tls/TLSSession.cpp
-@@ -139,6 +139,7 @@ TLSSession::TLSSession(ref <security::cert::certificateVerifier> cv)
- 	// Sets some default priority on the ciphers, key exchange methods,
- 	// macs and compression methods.
- #if HAVE_GNUTLS_PRIORITY_FUNCS
-+	gnutls_dh_set_prime_bits(*m_gnutlsSession, 128);
- 
- 	if ((res = gnutls_priority_set_direct
- 		(*m_gnutlsSession, "NORMAL:%SSL3_RECORD_VERSION", NULL)) != 0)
--- 
-1.7.10.4
-
-
-From 6574b60a303c5d864e840aa23959656bb2803485 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 22 Dec 2011 08:51:28 +0000
-Subject: [PATCH 27/47] Updated coding conventions.
-
-
-diff --git a/HACKING b/HACKING
-index 4f35a53..f51d738 100644
---- a/HACKING
-+++ b/HACKING
-@@ -1,10 +1,10 @@
- 
--This file contains coding guidelines for VMime. You should follow these
--guidelines if you want to contribute to VMime. It guarantees some minimal
--quality of the code.
-+This file contains coding guidelines for VMime. You should follow them
-+if you want to contribute to VMime. The rules below are not guidelines
-+or recommendations, but strict rules.
- 
- 
--1. General guidelines
-+1. General rules
-      1.1. Language
-      1.2. Unit tests
-      1.3. CVS
-@@ -18,19 +18,22 @@ quality of the code.
-      2.5. Line length
-      2.6. Spaces and parentheses
-      2.7. End-of-line character
-+     2.8. Short functions
-+     2.9. Limit Variable Scope
- 3. Naming conventions
-      3.1. Classes
-      3.2. Variables/parameters/member variables
-      3.3. Member variables
-      3.4. Files
-      3.5. Namespaces
-+     3.6. Constants
- 4. Comments
- 5. Miscellaneous
- 
- 
- 
--1. General guidelines
--=====================
-+1. General rules
-+================
- 
- 1.1. Language
- -------------
-@@ -50,7 +53,7 @@ When you fix a bug, also add a new test case to ensure the bug will not
- happen anymore.
- 
- 
--1.3. CVS
-+1.3. SVN
- --------
- 
- Each commit MUST be done with a message ('-m' flag) that briefly describes what
-@@ -154,7 +157,11 @@ Except when body spans over multiple lines:
- 2.5. Line length
- ----------------
- 
--Line length should not exceed 80 characters.
-+Each line of text should not exceed 80 characters.
-+
-+Exception: if a comment line contains an example command or a literal URL
-+longer than 100 characters, that line may be longer than 100 characters
-+for ease of cut and paste.
- 
- 
- 2.6. Spaces and parentheses
-@@ -193,6 +200,30 @@ Configure your editor to use "\n" (UNIX convention) for end-of-line sequence,
- and not "\r\n" (Windows), nor "\n\r", nor any other combination.
- 
- 
-+2.8. Short functions
-+--------------------
-+
-+To the extent that it is feasible, functions should be kept small and focused.
-+It is, however, recognized that long functions are sometimes appropriate, so no
-+hard limit is placed on method length. If a function exceeds 40 lines or so,
-+think about whether it can be broken up without harming the structure of the
-+program.
-+
-+
-+2.9. Limit Variable Scope
-+-------------------------
-+
-+The scope of local variables should be kept to a minimum. By doing so, you
-+increase the readability and maintainability of your code and reduce the
-+likelihood of error. Each variable should be declared in the innermost block
-+that encloses all uses of the variable.
-+
-+Local variables should be declared at the point they are first used. Nearly
-+every local variable declaration should contain an initializer. If you don't
-+yet have enough information to initialize a variable sensibly, you should
-+postpone the declaration until you do.
-+
-+
- 
- 3. Naming conventions
- =====================
-@@ -255,6 +286,12 @@ Implementation files must be placed in 'src/' directory.
- Namespaces are named exactly like variables.
- 
- 
-+3.6. Constants
-+--------------
-+
-+Constants are ALL_CAPS_WITH_UNDERSCORES.
-+
-+
- 
- 4. Comments
- ===========
--- 
-1.7.10.4
-
-
-From 130e5223dea0af2f8d9d01cca7845be4e1a08d13 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 5 Apr 2012 11:46:39 +0200
-Subject: [PATCH 28/47] Added function to retrieve sequence numbers of
- messages whose UID is greater or equal than a
- specified UID (thanks to Zahi Mashael).
-
-
-diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp
-index 0122d21..50a2f2b 100644
---- a/src/net/imap/IMAPFolder.cpp
-+++ b/src/net/imap/IMAPFolder.cpp
-@@ -1772,6 +1772,62 @@ void IMAPFolder::status(int& count, int& unseen)
- }
- 
- 
-+std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid)
-+{
-+	std::vector<int> v;
-+
-+	std::ostringstream command;
-+	command.imbue(std::locale::classic());
-+
-+	command << "SEARCH UID " << uid;
-+
-+	// Send the request
-+	m_connection->send(true, command.str(), true);
-+
-+	// Get the response
-+	utility::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
-+
-+	if (resp->isBad() ||
-+	    resp->response_done()->response_tagged()->resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
-+	{
-+		throw exceptions::command_error("SEARCH",
-+			m_connection->getParser()->lastLine(), "bad response");
-+	}
-+
-+	const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = resp->continue_req_or_response_data();
-+
-+	for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
-+	     it = respDataList.begin() ; it != respDataList.end() ; ++it)
-+	{
-+		if ((*it)->response_data() == NULL)
-+		{
-+			throw exceptions::command_error("SEARCH",
-+				m_connection->getParser()->lastLine(), "invalid response");
-+		}
-+
-+		const IMAPParser::mailbox_data* mailboxData =
-+			(*it)->response_data()->mailbox_data();
-+
-+		// We are only interested in responses of type "SEARCH"
-+		if (mailboxData == NULL ||
-+		    mailboxData->type() != IMAPParser::mailbox_data::SEARCH)
-+		{
-+			continue;
-+		}
-+
-+		for (std::vector <IMAPParser::nz_number*>::const_iterator
-+				it = mailboxData->search_nz_number_list().begin() ;
-+		     it != mailboxData->search_nz_number_list().end();
-+		     ++it)
-+		{
-+			v.push_back((*it)->value());
-+		}
-+	}
-+
-+	return v;
-+}
-+
-+
- } // imap
- } // net
- } // vmime
-diff --git a/src/net/maildir/maildirFolder.cpp b/src/net/maildir/maildirFolder.cpp
-index dd680c9..d11ae3b 100644
---- a/src/net/maildir/maildirFolder.cpp
-+++ b/src/net/maildir/maildirFolder.cpp
-@@ -1363,6 +1363,12 @@ const utility::file::path maildirFolder::getMessageFSPath(const int number) cons
- }
- 
- 
-+std::vector <int> maildirFolder::getMessageNumbersStartingOnUID(const message::uid& /* uid */)
-+{
-+	throw exceptions::operation_not_supported();
-+}
-+
-+
- } // maildir
- } // net
- } // vmime
-diff --git a/src/net/pop3/POP3Folder.cpp b/src/net/pop3/POP3Folder.cpp
-index d5fc687..e085609 100644
---- a/src/net/pop3/POP3Folder.cpp
-+++ b/src/net/pop3/POP3Folder.cpp
-@@ -843,6 +843,12 @@ void POP3Folder::expunge()
- }
- 
- 
-+std::vector <int> POP3Folder::getMessageNumbersStartingOnUID(const message::uid& /* uid */)
-+{
-+	throw exceptions::operation_not_supported();
-+}
-+
-+
- } // pop3
- } // net
- } // vmime
-diff --git a/vmime/net/folder.hpp b/vmime/net/folder.hpp
-index b20e9c9..df9cbaf 100644
---- a/vmime/net/folder.hpp
-+++ b/vmime/net/folder.hpp
-@@ -383,6 +383,13 @@ public:
- 	  */
- 	virtual int getFetchCapabilities() const = 0;
- 
-+	/** Return the sequence numbers of messages whose UID equal or greater than uid
-+ 	  *
-+ 	  * @param uid the uid of the first message
-+ 	  * @throw net_exception if an error occurs
-+ 	  */
-+	virtual std::vector <int> getMessageNumbersStartingOnUID(const message::uid& uid) = 0;
-+
- 	// Event listeners
- 	void addMessageChangedListener(events::messageChangedListener* l);
- 	void removeMessageChangedListener(events::messageChangedListener* l);
-diff --git a/vmime/net/imap/IMAPFolder.hpp b/vmime/net/imap/IMAPFolder.hpp
-index dec3878..cc52596 100644
---- a/vmime/net/imap/IMAPFolder.hpp
-+++ b/vmime/net/imap/IMAPFolder.hpp
-@@ -120,6 +120,8 @@ public:
- 
- 	int getFetchCapabilities() const;
- 
-+	std::vector <int> getMessageNumbersStartingOnUID(const message::uid& uid);
-+
- private:
- 
- 	void registerMessage(IMAPMessage* msg);
-diff --git a/vmime/net/maildir/maildirFolder.hpp b/vmime/net/maildir/maildirFolder.hpp
-index 7474b1a..68b5b89 100644
---- a/vmime/net/maildir/maildirFolder.hpp
-+++ b/vmime/net/maildir/maildirFolder.hpp
-@@ -121,6 +121,8 @@ public:
- 
- 	int getFetchCapabilities() const;
- 
-+	std::vector <int> getMessageNumbersStartingOnUID(const message::uid& uid);
-+
- private:
- 
- 	void scanFolder();
-diff --git a/vmime/net/pop3/POP3Folder.hpp b/vmime/net/pop3/POP3Folder.hpp
-index abaa8eb..c482908 100644
---- a/vmime/net/pop3/POP3Folder.hpp
-+++ b/vmime/net/pop3/POP3Folder.hpp
-@@ -119,6 +119,8 @@ public:
- 
- 	int getFetchCapabilities() const;
- 
-+	std::vector <int> getMessageNumbersStartingOnUID(const message::uid& uid);
-+
- private:
- 
- 	void registerMessage(POP3Message* msg);
--- 
-1.7.10.4
-
-
-From 3f1a565b8b532f0d11a13d3f6d763b00c8ce625b Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 5 Apr 2012 11:55:07 +0200
-Subject: [PATCH 29/47] Added .gitignore.
-
-
-diff --git a/.gitignore b/.gitignore
-new file mode 100644
-index 0000000..44e03a8
---- /dev/null
-+++ b/.gitignore
-@@ -0,0 +1,11 @@
-+*.o
-+*.swp
-+build/
-+
-+/libvmime.a
-+/vmime.pc
-+/vmime/config.hpp
-+
-+# SConstruct
-+.sconsign.dblite
-+/options.cache
--- 
-1.7.10.4
-
-
-From 5937bcda0fac9cb80d0cecbaa663ecdfe2839c09 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 5 Apr 2012 12:08:01 +0200
-Subject: [PATCH 30/47] Added check before dereferencing.
-
-
-diff --git a/vmime/utility/smartPtr.hpp b/vmime/utility/smartPtr.hpp
-index c448632..df63685 100644
---- a/vmime/utility/smartPtr.hpp
-+++ b/vmime/utility/smartPtr.hpp
-@@ -338,7 +338,9 @@ protected:
- 	{
- 		if (m_ptr)
- 		{
--			m_ptr->getRefManager()->releaseStrong();
-+			if (m_ptr->getRefManager())
-+				m_ptr->getRefManager()->releaseStrong();
-+
- 			m_ptr = 0;
- 		}
- 	}
--- 
-1.7.10.4
-
-
-From b0d74ce63ea9563ef4b218bce2497bd668dfad29 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 5 Apr 2012 12:34:51 +0200
-Subject: [PATCH 31/47] Updated README.
-
-
-diff --git a/README b/README
-index 6921cea..7db9175 100644
---- a/README
-+++ b/README
-@@ -1,2 +1,30 @@
- 
--TODO
-+VMime is a powerful C++ class library for working with RFC-822 and MIME messages
-+and Internet messaging services like IMAP, POP or SMTP.
-+
-+With VMime you can parse, generate and modify messages, and also connect to store
-+and transport services to receive or send messages over the Internet. The library
-+offers all the features to build a complete mail client.
-+
-+Key Features
-+------------
-+
-+* it is free software! GNU GPL license (Commercial licenses available!)
-+* fully RFC-compliant implementation
-+* object-oriented and modular design
-+* very easy-to-use (intuitive design)
-+* well documented code
-+* very high reliability
-+* maximum portability
-+
-+Features Overview
-+-----------------
-+
-+* RFC-2822 and multipart messages
-+* aggregate documents and embedded objects
-+* 8-bit MIME and encoded word extensions
-+* full support for attachments
-+* POP3, IMAP, SMTP, maildir and sendmail
-+* SSL/TLS security layer and X.509 certificates (using GNU TLS)
-+* SASL authentication (using GNU SASL)
-+
--- 
-1.7.10.4
-
-
-From 350fada21a4f11c2f633a3cde1f2195efefe7e32 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 5 Apr 2012 22:10:54 +0200
-Subject: [PATCH 32/47] Added test: Ensure '7bit' encoding is used when body
- is 7-bit only.
-
-
-diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp
-index 075b8f9..e1d47a3 100644
---- a/tests/parser/bodyPartTest.cpp
-+++ b/tests/parser/bodyPartTest.cpp
-@@ -37,6 +37,7 @@ VMIME_TEST_SUITE_BEGIN
- 		VMIME_TEST(testPrologEpilog)
- 		VMIME_TEST(testPrologEncoding)
- 		VMIME_TEST(testSuccessiveBoundaries)
-+		VMIME_TEST(testGenerate7bit)
- 	VMIME_TEST_LIST_END
- 
- 
-@@ -200,5 +201,18 @@ VMIME_TEST_SUITE_BEGIN
- 		VASSERT_EQ("part2-body", "", extractContents(p.getBody()->getPartAt(1)->getBody()->getContents()));
- 	}
- 
-+	/** Ensure '7bit' encoding is used when body is 7-bit only. */
-+	void testGenerate7bit()
-+	{
-+		vmime::ref <vmime::plainTextPart> p1 = vmime::create <vmime::plainTextPart>();
-+		p1->setText(vmime::create <vmime::stringContentHandler>("Part1 is US-ASCII only."));
-+
-+		vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
-+		p1->generateIn(msg, msg);
-+
-+		vmime::ref <vmime::header> header1 = msg->getBody()->getPartAt(0)->getHeader();
-+		VASSERT_EQ("1", "7bit", header1->ContentTransferEncoding()->getValue()->generate());
-+	}
-+
- VMIME_TEST_SUITE_END
- 
--- 
-1.7.10.4
-
-
-From 6c877ea41a2e408df61ac6f988c3bae7e0821141 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 5 Apr 2012 22:29:32 +0200
-Subject: [PATCH 33/47] Added tests for Quoted-Printable encoding.
-
-
-diff --git a/tests/utility/encoderTest.cpp b/tests/utility/encoderTest.cpp
-index f2d42b6..b2d6bc8 100644
---- a/tests/utility/encoderTest.cpp
-+++ b/tests/utility/encoderTest.cpp
-@@ -33,6 +33,8 @@ VMIME_TEST_SUITE_BEGIN
- 	VMIME_TEST_LIST_BEGIN
- 		VMIME_TEST(testBase64)
- 		VMIME_TEST(testQuotedPrintable)
-+		VMIME_TEST(testQuotedPrintable_SoftLineBreaks)
-+		VMIME_TEST(testQuotedPrintable_CRLF)
- 		VMIME_TEST(testQuotedPrintable_RFC2047)
- 	VMIME_TEST_LIST_END
- 
-@@ -288,6 +290,35 @@ VMIME_TEST_SUITE_BEGIN
- 		}
- 	}
- 
-+	/** Tests Soft Line Breaks (RFC-2047/6.7(5). */
-+	void testQuotedPrintable_SoftLineBreaks()
-+	{
-+		VASSERT_EQ("1", "Now's the time=\r\n"
-+		                " for all folk =\r\n"
-+		                "to come to the=\r\n"
-+		                " aid of their =\r\n"
-+		                "country.",
-+		                encode("quoted-printable", "Now's the time for all folk "
-+		                                           "to come to the aid of their country.", 15));
-+	}
-+
-+	/** In text mode, ensure line breaks in QP-encoded text are represented
-+	  * by a CRLF sequence, as per RFC-2047/6.7(4). */
-+	void testQuotedPrintable_CRLF()
-+	{
-+		vmime::propertySet encProps;
-+
-+		// in "text" mode
-+		encProps["text"] = true;
-+		VASSERT_EQ("text", "line1\r\nline2",
-+		           encode("quoted-printable", "line1\r\nline2", 80, encProps));
-+
-+		// in "binary" mode
-+		encProps["text"] = false;
-+		VASSERT_EQ("binary", "line1=0D=0Aline2",
-+		           encode("quoted-printable", "line1\r\nline2", 80, encProps));
-+	}
-+
- 	void testQuotedPrintable_RFC2047()
- 	{
- 		/*
--- 
-1.7.10.4
-
-
-From e88f062ab58654aee3cf45f94e8a5dd6c1256279 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Thu, 5 Apr 2012 23:15:04 +0200
-Subject: [PATCH 34/47] Fixed wrong encoding of line breaks in QP-encoded text
- (issue #7).
-
-
-diff --git a/src/encoding.cpp b/src/encoding.cpp
-index 0919d44..b4e79db 100644
---- a/src/encoding.cpp
-+++ b/src/encoding.cpp
-@@ -34,19 +34,28 @@ namespace vmime
- 
- 
- encoding::encoding()
--	: m_name(encodingTypes::SEVEN_BIT)
-+	: m_name(encodingTypes::SEVEN_BIT),
-+	  m_usage(USAGE_UNKNOWN)
- {
- }
- 
- 
- encoding::encoding(const string& name)
--	: m_name(utility::stringUtils::toLower(name))
-+	: m_name(utility::stringUtils::toLower(name)),
-+	  m_usage(USAGE_UNKNOWN)
-+{
-+}
-+
-+
-+encoding::encoding(const string& name, const EncodingUsage usage)
-+	: m_name(utility::stringUtils::toLower(name)),
-+	  m_usage(usage)
- {
- }
- 
- 
- encoding::encoding(const encoding& enc)
--	: headerFieldValue(), m_name(enc.m_name)
-+	: headerFieldValue(), m_name(enc.m_name), m_usage(enc.m_usage)
- {
- }
- 
-@@ -54,6 +63,8 @@ encoding::encoding(const encoding& enc)
- void encoding::parse(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
-+	m_usage = USAGE_UNKNOWN;
-+
- 	m_name = utility::stringUtils::toLower(utility::stringUtils::trim
- 		(utility::stringUtils::unquote(utility::stringUtils::trim
- 			(string(buffer.begin() + position, buffer.begin() + end)))));
-@@ -80,7 +91,14 @@ void encoding::generate(utility::outputStream& os, const string::size_type /* ma
- 
- ref <utility::encoder::encoder> encoding::getEncoder() const
- {
--	return (utility::encoder::encoderFactory::getInstance()->create(generate()));
-+	ref <utility::encoder::encoder> encoder =
-+		utility::encoder::encoderFactory::getInstance()->create(generate());
-+
-+	// FIXME: this should not be here (move me into QP encoder instead?)
-+	if (m_usage == USAGE_TEXT && m_name == encodingTypes::QUOTED_PRINTABLE)
-+		encoder->getProperties()["text"] = true;
-+
-+	return encoder;
- }
- 
- 
-@@ -94,6 +112,7 @@ encoding& encoding::operator=(const encoding& other)
- encoding& encoding::operator=(const string& name)
- {
- 	m_name = utility::stringUtils::toLower(name);
-+	m_usage = USAGE_UNKNOWN;
- 	return (*this);
- }
- 
-@@ -167,6 +186,8 @@ const encoding encoding::decideImpl
- const encoding encoding::decide
- 	(ref <const contentHandler> data, const EncodingUsage usage)
- {
-+	encoding enc;
-+
- 	if (usage == USAGE_TEXT && data->isBuffered() &&
- 	    data->getLength() > 0 && data->getLength() < 32768)
- 	{
-@@ -177,12 +198,16 @@ const encoding encoding::decide
- 		data->extract(os);
- 		os.flush();
- 
--		return decideImpl(buffer.begin(), buffer.end());
-+		enc = decideImpl(buffer.begin(), buffer.end());
- 	}
- 	else
- 	{
--		return encoding(encodingTypes::BASE64);
-+		enc = encoding(encodingTypes::BASE64);
- 	}
-+
-+	enc.setUsage(usage);
-+
-+	return enc;
- }
- 
- 
-@@ -194,7 +219,10 @@ const encoding encoding::decide(ref <const contentHandler> data,
- 		encoding recEncoding;
- 
- 		if (chset.getRecommendedEncoding(recEncoding))
-+		{
-+			recEncoding.setUsage(usage);
- 			return recEncoding;
-+		}
- 	}
- 
- 	return decide(data, usage);
-@@ -227,6 +255,18 @@ void encoding::setName(const string& name)
- }
- 
- 
-+encoding::EncodingUsage encoding::getUsage() const
-+{
-+	return m_usage;
-+}
-+
-+
-+void encoding::setUsage(const EncodingUsage usage)
-+{
-+	m_usage = usage;
-+}
-+
-+
- const std::vector <ref <const component> > encoding::getChildComponents() const
- {
- 	return std::vector <ref <const component> >();
-diff --git a/src/utility/encoder/qpEncoder.cpp b/src/utility/encoder/qpEncoder.cpp
-index aa95022..ab8db2e 100644
---- a/src/utility/encoder/qpEncoder.cpp
-+++ b/src/utility/encoder/qpEncoder.cpp
-@@ -292,14 +292,15 @@ utility::stream::size_type qpEncoder::encode(utility::inputStream& in,
- 			case 13:  // CR
- 			case 10:  // LF
- 			{
--				// Text mode (where using CRLF or LF or ... does not
--				// care for a new line...)
--				if (text)
-+				// RFC-2045/6.7(4)
-+
-+				// Text data
-+				if (text && !rfc2047)
- 				{
- 					outBuffer[outBufferPos++] = c;
- 					++curCol;
- 				}
--				// Binary mode (where CR and LF bytes are important!)
-+				// Binary data
- 				else
- 				{
- 					QP_ENCODE_HEX(c);
-diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp
-index e1d47a3..9d51262 100644
---- a/tests/parser/bodyPartTest.cpp
-+++ b/tests/parser/bodyPartTest.cpp
-@@ -38,6 +38,7 @@ VMIME_TEST_SUITE_BEGIN
- 		VMIME_TEST(testPrologEncoding)
- 		VMIME_TEST(testSuccessiveBoundaries)
- 		VMIME_TEST(testGenerate7bit)
-+		VMIME_TEST(testTextUsageForQPEncoding)
- 	VMIME_TEST_LIST_END
- 
- 
-@@ -214,5 +215,28 @@ VMIME_TEST_SUITE_BEGIN
- 		VASSERT_EQ("1", "7bit", header1->ContentTransferEncoding()->getValue()->generate());
- 	}
- 
-+	void testTextUsageForQPEncoding()
-+	{
-+		vmime::ref <vmime::plainTextPart> part = vmime::create <vmime::plainTextPart>();
-+		part->setText(vmime::create <vmime::stringContentHandler>("Part1-line1\r\nPart1-line2\r\n\x89"));
-+
-+		vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
-+		part->generateIn(msg, msg);
-+
-+		vmime::ref <vmime::body> body = msg->getBody()->getPartAt(0)->getBody();
-+		vmime::ref <vmime::header> header = msg->getBody()->getPartAt(0)->getHeader();
-+
-+		std::ostringstream oss;
-+		vmime::utility::outputStreamAdapter os(oss);
-+		body->generate(os, 80);
-+
-+		VASSERT_EQ("1", "quoted-printable", header->ContentTransferEncoding()->getValue()->generate());
-+
-+		// This should *NOT* be:
-+		//    Part1-line1=0D=0APart1-line2=0D=0A=89
-+		VASSERT_EQ("2", "Part1-line1\r\nPart1-line2\r\n=89", oss.str());
-+	}
-+
-+
- VMIME_TEST_SUITE_END
- 
-diff --git a/vmime/encoding.hpp b/vmime/encoding.hpp
-index ba78081..42f5246 100644
---- a/vmime/encoding.hpp
-+++ b/vmime/encoding.hpp
-@@ -47,6 +47,7 @@ public:
- 
- 	enum EncodingUsage
- 	{
-+		USAGE_UNKNOWN,
- 		USAGE_TEXT,         /**< Use for body text. */
- 		USAGE_BINARY_DATA   /**< Use for attachment, image... */
- 	};
-@@ -54,6 +55,7 @@ public:
- 
- 	encoding();
- 	explicit encoding(const string& name);
-+	encoding(const string& name, const EncodingUsage usage);
- 	encoding(const encoding& enc);
- 
- public:
-@@ -72,6 +74,19 @@ public:
- 	  */
- 	void setName(const string& name);
- 
-+	/** Return the type of contents this encoding is used for.
-+	  * See the EncodingUsage enum.
-+	  */
-+	EncodingUsage getUsage() const;
-+
-+	/** Set the type of contents this encoding is used for.
-+	  * See the EncodingUsage enum.
-+	  *
-+	  * @param usage type of contents
-+	  */
-+	void setUsage(const EncodingUsage usage);
-+
-+
- 	encoding& operator=(const encoding& other);
- 	encoding& operator=(const string& name);
- 
-@@ -113,6 +128,7 @@ public:
- private:
- 
- 	string m_name;
-+	EncodingUsage m_usage;
- 
- 	/** Decide which encoding to use based on the specified data.
- 	  *
--- 
-1.7.10.4
-
-
-From ea77bdba96588345090e3de81d9d6af116edeeb5 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 6 Apr 2012 22:26:18 +0200
-Subject: [PATCH 35/47] Fixed memory leak.
-
-
-diff --git a/src/net/tls/TLSSocket.cpp b/src/net/tls/TLSSocket.cpp
-index dab0338..3cccc1e 100644
---- a/src/net/tls/TLSSocket.cpp
-+++ b/src/net/tls/TLSSocket.cpp
-@@ -50,6 +50,12 @@ TLSSocket::TLSSocket(ref <TLSSession> session, ref <socket> sok)
- 
- TLSSocket::~TLSSocket()
- {
-+	if (m_ex)
-+	{
-+		delete m_ex;
-+		m_ex = NULL;
-+	}
-+
- 	try
- 	{
- 		disconnect();
--- 
-1.7.10.4
-
-
-From 440d491fd6da134fcb5f19416743e8f2044556bf Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sat, 14 Apr 2012 13:46:05 +0200
-Subject: [PATCH 36/47] Split stream.hpp/.cpp into multiple source files.
-
-
-diff --git a/SConstruct b/SConstruct
-index 11e884b..ea5c4eb 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -144,6 +144,20 @@ libvmime_sources = [
- 	'utility/smartPtr.cpp', 'utility/smartPtr.hpp',
- 	'utility/smartPtrInt.cpp', 'utility/smartPtrInt.hpp',
- 	'utility/stream.cpp', 'utility/stream.hpp',
-+	'utility/streamUtils.cpp', 'utility/streamUtils.hpp',
-+	'utility/filteredStream.cpp', 'utility/filteredStream.hpp',
-+	'utility/inputStream.cpp', 'utility/inputStream.hpp',
-+	'utility/inputStreamAdapter.cpp', 'utility/inputStreamAdapter.hpp',
-+	'utility/inputStreamByteBufferAdapter.cpp', 'utility/inputStreamByteBufferAdapter.hpp',
-+	'utility/inputStreamPointerAdapter.cpp', 'utility/inputStreamPointerAdapter.hpp',
-+	'utility/inputStreamSocketAdapter.cpp', 'utility/inputStreamSocketAdapter.hpp',
-+	'utility/inputStreamStringAdapter.cpp', 'utility/inputStreamStringAdapter.hpp',
-+	'utility/inputStreamStringProxyAdapter.cpp', 'utility/inputStreamStringProxyAdapter.hpp',
-+	'utility/outputStream.cpp', 'utility/outputStream.hpp',
-+	'utility/outputStreamAdapter.cpp', 'utility/outputStreamAdapter.hpp',
-+	'utility/outputStreamByteArrayAdapter.cpp', 'utility/outputStreamByteArrayAdapter.hpp',
-+	'utility/outputStreamSocketAdapter.cpp', 'utility/outputStreamSocketAdapter.hpp',
-+	'utility/outputStreamStringAdapter.cpp', 'utility/outputStreamStringAdapter.hpp',
- 	'utility/stringProxy.cpp', 'utility/stringProxy.hpp',
- 	'utility/stringUtils.cpp', 'utility/stringUtils.hpp',
- 	'utility/url.cpp', 'utility/url.hpp',
-diff --git a/src/charsetConverter.cpp b/src/charsetConverter.cpp
-index 2135788..cf75bdd 100644
---- a/src/charsetConverter.cpp
-+++ b/src/charsetConverter.cpp
-@@ -23,6 +23,8 @@
- 
- #include "vmime/charsetConverter.hpp"
- #include "vmime/exception.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+#include "vmime/utility/outputStreamStringAdapter.hpp"
- 
- 
- extern "C"
-diff --git a/src/component.cpp b/src/component.cpp
-index fbf677b..139cf66 100644
---- a/src/component.cpp
-+++ b/src/component.cpp
-@@ -23,6 +23,7 @@
- 
- #include "vmime/component.hpp"
- #include "vmime/base.hpp"
-+#include "vmime/utility/outputStreamAdapter.hpp"
- 
- #include <sstream>
- 
-diff --git a/src/encoding.cpp b/src/encoding.cpp
-index b4e79db..5d99ab6 100644
---- a/src/encoding.cpp
-+++ b/src/encoding.cpp
-@@ -24,6 +24,7 @@
- #include "vmime/encoding.hpp"
- #include "vmime/contentHandler.hpp"
- 
-+#include "vmime/utility/outputStreamStringAdapter.hpp"
- #include "vmime/utility/encoder/encoderFactory.hpp"
- 
- #include <algorithm>
-diff --git a/src/fileAttachment.cpp b/src/fileAttachment.cpp
-index da7c4b7..cb23cd0 100644
---- a/src/fileAttachment.cpp
-+++ b/src/fileAttachment.cpp
-@@ -28,6 +28,7 @@
- #include "vmime/exception.hpp"
- 
- #include "vmime/streamContentHandler.hpp"
-+#include "vmime/utility/inputStreamPointerAdapter.hpp"
- 
- #include "vmime/contentDispositionField.hpp"
- 
-diff --git a/src/generatedMessageAttachment.cpp b/src/generatedMessageAttachment.cpp
-index e9bd1a6..443a9d3 100644
---- a/src/generatedMessageAttachment.cpp
-+++ b/src/generatedMessageAttachment.cpp
-@@ -23,6 +23,8 @@
- 
- #include "vmime/generatedMessageAttachment.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- 
- namespace vmime
- {
-diff --git a/src/htmlTextPart.cpp b/src/htmlTextPart.cpp
-index c845b57..98524af 100644
---- a/src/htmlTextPart.cpp
-+++ b/src/htmlTextPart.cpp
-@@ -31,6 +31,8 @@
- #include "vmime/emptyContentHandler.hpp"
- #include "vmime/stringContentHandler.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- 
- namespace vmime
- {
-diff --git a/src/mdn/MDNHelper.cpp b/src/mdn/MDNHelper.cpp
-index b419b85..1dd7ff3 100644
---- a/src/mdn/MDNHelper.cpp
-+++ b/src/mdn/MDNHelper.cpp
-@@ -31,6 +31,8 @@
- #include "vmime/path.hpp"
- #include "vmime/dateTime.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- 
- namespace vmime {
- namespace mdn {
-diff --git a/src/mdn/receivedMDNInfos.cpp b/src/mdn/receivedMDNInfos.cpp
-index cff211c..f97a58d 100644
---- a/src/mdn/receivedMDNInfos.cpp
-+++ b/src/mdn/receivedMDNInfos.cpp
-@@ -23,6 +23,8 @@
- 
- #include "vmime/mdn/receivedMDNInfos.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- 
- namespace vmime {
- namespace mdn {
-diff --git a/src/message.cpp b/src/message.cpp
-index 6f4b046..1b4f086 100644
---- a/src/message.cpp
-+++ b/src/message.cpp
-@@ -24,6 +24,8 @@
- #include "vmime/message.hpp"
- #include "vmime/options.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- #include <sstream>
- 
- 
-diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp
-index 50a2f2b..81bf386 100644
---- a/src/net/imap/IMAPFolder.cpp
-+++ b/src/net/imap/IMAPFolder.cpp
-@@ -34,6 +34,8 @@
- #include "vmime/exception.hpp"
- #include "vmime/utility/smartPtr.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- #include <algorithm>
- #include <sstream>
- 
-diff --git a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp
-index bc661ed..702d5f2 100644
---- a/src/net/imap/IMAPMessage.cpp
-+++ b/src/net/imap/IMAPMessage.cpp
-@@ -31,6 +31,8 @@
- #include "vmime/net/imap/IMAPPart.hpp"
- #include "vmime/net/imap/IMAPMessagePartContentHandler.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- #include <sstream>
- #include <iterator>
- #include <typeinfo>
-diff --git a/src/net/imap/IMAPMessagePartContentHandler.cpp b/src/net/imap/IMAPMessagePartContentHandler.cpp
-index 4e6ba97..85c6ec2 100644
---- a/src/net/imap/IMAPMessagePartContentHandler.cpp
-+++ b/src/net/imap/IMAPMessagePartContentHandler.cpp
-@@ -23,6 +23,9 @@
- 
- #include "vmime/net/imap/IMAPMessagePartContentHandler.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+#include "vmime/utility/inputStreamStringProxyAdapter.hpp"
-+
- 
- namespace vmime {
- namespace net {
-diff --git a/src/net/maildir/maildirFolder.cpp b/src/net/maildir/maildirFolder.cpp
-index d11ae3b..8c4b275 100644
---- a/src/net/maildir/maildirFolder.cpp
-+++ b/src/net/maildir/maildirFolder.cpp
-@@ -35,6 +35,9 @@
- #include "vmime/exception.hpp"
- #include "vmime/platform.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+
- 
- namespace vmime {
- namespace net {
-diff --git a/src/net/maildir/maildirMessage.cpp b/src/net/maildir/maildirMessage.cpp
-index 51cd1ba..4ab75e7 100644
---- a/src/net/maildir/maildirMessage.cpp
-+++ b/src/net/maildir/maildirMessage.cpp
-@@ -31,6 +31,8 @@
- #include "vmime/exception.hpp"
- #include "vmime/platform.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- 
- namespace vmime {
- namespace net {
-diff --git a/src/net/pop3/POP3Message.cpp b/src/net/pop3/POP3Message.cpp
-index 50f4f87..69ef004 100644
---- a/src/net/pop3/POP3Message.cpp
-+++ b/src/net/pop3/POP3Message.cpp
-@@ -25,6 +25,8 @@
- #include "vmime/net/pop3/POP3Folder.hpp"
- #include "vmime/net/pop3/POP3Store.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- #include <sstream>
- 
- 
-diff --git a/src/net/pop3/POP3Store.cpp b/src/net/pop3/POP3Store.cpp
-index 9d554c6..793112a 100644
---- a/src/net/pop3/POP3Store.cpp
-+++ b/src/net/pop3/POP3Store.cpp
-@@ -30,6 +30,7 @@
- #include "vmime/security/digest/messageDigestFactory.hpp"
- #include "vmime/utility/filteredStream.hpp"
- #include "vmime/utility/stringUtils.hpp"
-+#include "vmime/utility/inputStreamSocketAdapter.hpp"
- 
- #include "vmime/net/defaultConnectionInfos.hpp"
- 
-diff --git a/src/net/sendmail/sendmailTransport.cpp b/src/net/sendmail/sendmailTransport.cpp
-index 53ff0d1..e7762cc 100644
---- a/src/net/sendmail/sendmailTransport.cpp
-+++ b/src/net/sendmail/sendmailTransport.cpp
-@@ -32,6 +32,8 @@
- #include "vmime/utility/childProcess.hpp"
- #include "vmime/utility/smartPtr.hpp"
- 
-+#include "vmime/utility/streamUtils.hpp"
-+
- #include "vmime/net/defaultConnectionInfos.hpp"
- 
- #include "vmime/config.hpp"
-diff --git a/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp
-index d9fb7b8..bbbea75 100644
---- a/src/net/smtp/SMTPTransport.cpp
-+++ b/src/net/smtp/SMTPTransport.cpp
-@@ -30,6 +30,8 @@
- 
- #include "vmime/utility/filteredStream.hpp"
- #include "vmime/utility/stringUtils.hpp"
-+#include "vmime/utility/outputStreamSocketAdapter.hpp"
-+#include "vmime/utility/streamUtils.hpp"
- 
- #include "vmime/net/defaultConnectionInfos.hpp"
- 
-diff --git a/src/net/transport.cpp b/src/net/transport.cpp
-index dd4663d..f8ca7b7 100644
---- a/src/net/transport.cpp
-+++ b/src/net/transport.cpp
-@@ -27,6 +27,9 @@
- #include "vmime/mailboxList.hpp"
- #include "vmime/message.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+
- 
- namespace vmime {
- namespace net {
-diff --git a/src/parameter.cpp b/src/parameter.cpp
-index d757e1b..ccbe1a5 100644
---- a/src/parameter.cpp
-+++ b/src/parameter.cpp
-@@ -27,6 +27,9 @@
- #include "vmime/text.hpp"
- #include "vmime/encoding.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+#include "vmime/utility/outputStreamStringAdapter.hpp"
-+
- 
- namespace vmime
- {
-diff --git a/src/parsedMessageAttachment.cpp b/src/parsedMessageAttachment.cpp
-index bde56aa..cb7d71d 100644
---- a/src/parsedMessageAttachment.cpp
-+++ b/src/parsedMessageAttachment.cpp
-@@ -26,6 +26,8 @@
- #include "vmime/stringContentHandler.hpp"
- #include "vmime/contentDisposition.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- 
- namespace vmime
- {
-diff --git a/src/security/cert/X509Certificate.cpp b/src/security/cert/X509Certificate.cpp
-index 1cd079c..8df4e5e 100644
---- a/src/security/cert/X509Certificate.cpp
-+++ b/src/security/cert/X509Certificate.cpp
-@@ -28,6 +28,8 @@
- 
- #include "vmime/security/cert/X509Certificate.hpp"
- 
-+#include "vmime/utility/outputStreamByteArrayAdapter.hpp"
-+
- 
- namespace vmime {
- namespace security {
-diff --git a/src/security/sasl/SASLContext.cpp b/src/security/sasl/SASLContext.cpp
-index 51c2bed..4bb33c1 100644
---- a/src/security/sasl/SASLContext.cpp
-+++ b/src/security/sasl/SASLContext.cpp
-@@ -33,6 +33,9 @@
- #include "vmime/utility/encoder/encoderFactory.hpp"
- 
- #include "vmime/utility/stream.hpp"
-+#include "vmime/utility/outputStreamStringAdapter.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+#include "vmime/utility/inputStreamByteBufferAdapter.hpp"
- 
- 
- namespace vmime {
-diff --git a/src/streamContentHandler.cpp b/src/streamContentHandler.cpp
-index 2ebd073..89a36b4 100644
---- a/src/streamContentHandler.cpp
-+++ b/src/streamContentHandler.cpp
-@@ -23,6 +23,10 @@
- 
- #include "vmime/streamContentHandler.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+#include "vmime/utility/streamUtils.hpp"
-+
- 
- namespace vmime
- {
-diff --git a/src/stringContentHandler.cpp b/src/stringContentHandler.cpp
-index 4e85a6c..5a1e72c 100644
---- a/src/stringContentHandler.cpp
-+++ b/src/stringContentHandler.cpp
-@@ -23,6 +23,10 @@
- 
- #include "vmime/stringContentHandler.hpp"
- 
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+#include "vmime/utility/inputStreamStringProxyAdapter.hpp"
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- 
- namespace vmime
- {
-diff --git a/src/utility/encoder/defaultEncoder.cpp b/src/utility/encoder/defaultEncoder.cpp
-index 4d0ffb5..e2d226e 100644
---- a/src/utility/encoder/defaultEncoder.cpp
-+++ b/src/utility/encoder/defaultEncoder.cpp
-@@ -23,6 +23,8 @@
- 
- #include "vmime/utility/encoder/defaultEncoder.hpp"
- 
-+#include "vmime/utility/streamUtils.hpp"
-+
- 
- namespace vmime {
- namespace utility {
-diff --git a/src/utility/inputStream.cpp b/src/utility/inputStream.cpp
-new file mode 100644
-index 0000000..dd0adf4
---- /dev/null
-+++ b/src/utility/inputStream.cpp
-@@ -0,0 +1,33 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/inputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/inputStreamAdapter.cpp b/src/utility/inputStreamAdapter.cpp
-new file mode 100644
-index 0000000..b44b084
---- /dev/null
-+++ b/src/utility/inputStreamAdapter.cpp
-@@ -0,0 +1,70 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/inputStreamAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+inputStreamAdapter::inputStreamAdapter(std::istream& is)
-+	: m_stream(is)
-+{
-+}
-+
-+
-+bool inputStreamAdapter::eof() const
-+{
-+	return (m_stream.eof());
-+}
-+
-+
-+void inputStreamAdapter::reset()
-+{
-+	m_stream.exceptions(std::ios_base::badbit);
-+	m_stream.seekg(0, std::ios::beg);
-+	m_stream.clear();
-+}
-+
-+
-+stream::size_type inputStreamAdapter::read
-+	(value_type* const data, const size_type count)
-+{
-+	m_stream.exceptions(std::ios_base::badbit);
-+	m_stream.read(data, count);
-+	return (m_stream.gcount());
-+}
-+
-+
-+stream::size_type inputStreamAdapter::skip(const size_type count)
-+{
-+	m_stream.exceptions(std::ios_base::badbit);
-+	m_stream.ignore(count);
-+	return (m_stream.gcount());
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/inputStreamByteBufferAdapter.cpp b/src/utility/inputStreamByteBufferAdapter.cpp
-new file mode 100644
-index 0000000..92e779f
---- /dev/null
-+++ b/src/utility/inputStreamByteBufferAdapter.cpp
-@@ -0,0 +1,90 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/inputStreamByteBufferAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+inputStreamByteBufferAdapter::inputStreamByteBufferAdapter(const byte_t* buffer, const size_type length)
-+	: m_buffer(buffer), m_length(length), m_pos(0)
-+{
-+}
-+
-+
-+bool inputStreamByteBufferAdapter::eof() const
-+{
-+	return m_pos >= m_length;
-+}
-+
-+
-+void inputStreamByteBufferAdapter::reset()
-+{
-+	m_pos = 0;
-+}
-+
-+
-+stream::size_type inputStreamByteBufferAdapter::read
-+	(value_type* const data, const size_type count)
-+{
-+	const size_type remaining = m_length - m_pos;
-+
-+	if (remaining < count)
-+	{
-+		std::copy(m_buffer + m_pos, m_buffer + m_pos + remaining, data);
-+		m_pos += remaining;
-+
-+		return remaining;
-+	}
-+	else
-+	{
-+		std::copy(m_buffer + m_pos, m_buffer + m_pos + count, data);
-+		m_pos += count;
-+
-+		return count;
-+	}
-+}
-+
-+
-+stream::size_type inputStreamByteBufferAdapter::skip(const size_type count)
-+{
-+	const size_type remaining = m_length - m_pos;
-+
-+	if (remaining < count)
-+	{
-+		m_pos += remaining;
-+		return remaining;
-+	}
-+	else
-+	{
-+		m_pos += count;
-+		return count;
-+	}
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/inputStreamPointerAdapter.cpp b/src/utility/inputStreamPointerAdapter.cpp
-new file mode 100644
-index 0000000..4d03e30
---- /dev/null
-+++ b/src/utility/inputStreamPointerAdapter.cpp
-@@ -0,0 +1,46 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/inputStreamPointerAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+inputStreamPointerAdapter::inputStreamPointerAdapter(std::istream* is, const bool own)
-+	: inputStreamAdapter(*is), m_stream(is), m_own(own)
-+{
-+}
-+
-+
-+inputStreamPointerAdapter::~inputStreamPointerAdapter()
-+{
-+	if (m_own)
-+		delete (m_stream);
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/inputStreamSocketAdapter.cpp b/src/utility/inputStreamSocketAdapter.cpp
-new file mode 100644
-index 0000000..b93cc3c
---- /dev/null
-+++ b/src/utility/inputStreamSocketAdapter.cpp
-@@ -0,0 +1,82 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/inputStreamSocketAdapter.hpp"
-+
-+
-+#if VMIME_HAVE_MESSAGING_FEATURES
-+
-+
-+#include "vmime/net/socket.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+inputStreamSocketAdapter::inputStreamSocketAdapter(net::socket& sok)
-+	: m_socket(sok)
-+{
-+}
-+
-+
-+bool inputStreamSocketAdapter::eof() const
-+{
-+	// Can't know...
-+	return false;
-+}
-+
-+
-+void inputStreamSocketAdapter::reset()
-+{
-+	// Not supported
-+}
-+
-+
-+stream::size_type inputStreamSocketAdapter::read
-+	(value_type* const data, const size_type count)
-+{
-+	return m_socket.receiveRaw(data, count);
-+}
-+
-+
-+stream::size_type inputStreamSocketAdapter::skip
-+	(const size_type /* count */)
-+{
-+	// Not supported
-+	return 0;
-+}
-+
-+
-+stream::size_type inputStreamSocketAdapter::getBlockSize()
-+{
-+	return m_socket.getBlockSize();
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_HAVE_MESSAGING_FEATURES
-+
-diff --git a/src/utility/inputStreamStringAdapter.cpp b/src/utility/inputStreamStringAdapter.cpp
-new file mode 100644
-index 0000000..31c9fda
---- /dev/null
-+++ b/src/utility/inputStreamStringAdapter.cpp
-@@ -0,0 +1,94 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/inputStreamStringAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer)
-+	: m_buffer(buffer), m_begin(0), m_end(buffer.length()), m_pos(0)
-+{
-+}
-+
-+
-+inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer,
-+	const string::size_type begin, const string::size_type end)
-+	: m_buffer(buffer), m_begin(begin), m_end(end), m_pos(begin)
-+{
-+}
-+
-+
-+bool inputStreamStringAdapter::eof() const
-+{
-+	return (m_pos >= m_end);
-+}
-+
-+
-+void inputStreamStringAdapter::reset()
-+{
-+	m_pos = m_begin;
-+}
-+
-+
-+stream::size_type inputStreamStringAdapter::read
-+	(value_type* const data, const size_type count)
-+{
-+	if (m_pos + count >= m_end)
-+	{
-+		const size_type remaining = m_end - m_pos;
-+
-+		std::copy(m_buffer.begin() + m_pos, m_buffer.end(), data);
-+		m_pos = m_end;
-+		return (remaining);
-+	}
-+	else
-+	{
-+		std::copy(m_buffer.begin() + m_pos, m_buffer.begin() + m_pos + count, data);
-+		m_pos += count;
-+		return (count);
-+	}
-+}
-+
-+
-+stream::size_type inputStreamStringAdapter::skip(const size_type count)
-+{
-+	if (m_pos + count >= m_end)
-+	{
-+		const size_type remaining = m_end - m_pos;
-+		m_pos = m_end;
-+		return (remaining);
-+	}
-+	else
-+	{
-+		m_pos += count;
-+		return (count);
-+	}
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/inputStreamStringProxyAdapter.cpp b/src/utility/inputStreamStringProxyAdapter.cpp
-new file mode 100644
-index 0000000..5e4b60b
---- /dev/null
-+++ b/src/utility/inputStreamStringProxyAdapter.cpp
-@@ -0,0 +1,89 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/inputStreamStringProxyAdapter.hpp"
-+#include "vmime/utility/stringProxy.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+inputStreamStringProxyAdapter::inputStreamStringProxyAdapter(const stringProxy& buffer)
-+	: m_buffer(buffer), m_pos(0)
-+{
-+}
-+
-+
-+bool inputStreamStringProxyAdapter::eof() const
-+{
-+	return (m_pos >= m_buffer.length());
-+}
-+
-+
-+void inputStreamStringProxyAdapter::reset()
-+{
-+	m_pos = 0;
-+}
-+
-+
-+stream::size_type inputStreamStringProxyAdapter::read
-+	(value_type* const data, const size_type count)
-+{
-+	const size_type remaining = m_buffer.length() - m_pos;
-+
-+	if (count > remaining)
-+	{
-+		std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_end(), data);
-+		m_pos = m_buffer.length();
-+		return (remaining);
-+	}
-+	else
-+	{
-+		std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_begin() + m_pos + count, data);
-+		m_pos += count;
-+		return (count);
-+	}
-+}
-+
-+
-+stream::size_type inputStreamStringProxyAdapter::skip(const size_type count)
-+{
-+	const size_type remaining = m_buffer.length() - m_pos;
-+
-+	if (count > remaining)
-+	{
-+		m_pos = m_buffer.length();
-+		return (remaining);
-+	}
-+	else
-+	{
-+		m_pos += count;
-+		return (count);
-+	}
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/outputStream.cpp b/src/utility/outputStream.cpp
-new file mode 100644
-index 0000000..8a65db5
---- /dev/null
-+++ b/src/utility/outputStream.cpp
-@@ -0,0 +1,33 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/outputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/outputStreamAdapter.cpp b/src/utility/outputStreamAdapter.cpp
-new file mode 100644
-index 0000000..2da94f1
---- /dev/null
-+++ b/src/utility/outputStreamAdapter.cpp
-@@ -0,0 +1,54 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/outputStreamAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+outputStreamAdapter::outputStreamAdapter(std::ostream& os)
-+	: m_stream(os)
-+{
-+}
-+
-+
-+void outputStreamAdapter::write
-+	(const value_type* const data, const size_type count)
-+{
-+	m_stream.exceptions(std::ios_base::badbit);
-+	m_stream.write(data, count);
-+}
-+
-+
-+void outputStreamAdapter::flush()
-+{
-+	m_stream.exceptions(std::ios_base::badbit);
-+	m_stream.flush();
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/outputStreamByteArrayAdapter.cpp b/src/utility/outputStreamByteArrayAdapter.cpp
-new file mode 100644
-index 0000000..97b27d2
---- /dev/null
-+++ b/src/utility/outputStreamByteArrayAdapter.cpp
-@@ -0,0 +1,51 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/outputStreamByteArrayAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+outputStreamByteArrayAdapter::outputStreamByteArrayAdapter(byteArray& array)
-+	: m_array(array)
-+{
-+}
-+
-+
-+void outputStreamByteArrayAdapter::write(const value_type* const data, const size_type count)
-+{
-+	m_array.insert(m_array.end(), data, data + count);
-+}
-+
-+
-+void outputStreamByteArrayAdapter::flush()
-+{
-+	// Do nothing
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/outputStreamSocketAdapter.cpp b/src/utility/outputStreamSocketAdapter.cpp
-new file mode 100644
-index 0000000..d933e73
---- /dev/null
-+++ b/src/utility/outputStreamSocketAdapter.cpp
-@@ -0,0 +1,68 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/outputStreamSocketAdapter.hpp"
-+
-+
-+#if VMIME_HAVE_MESSAGING_FEATURES
-+
-+
-+#include "vmime/net/socket.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+outputStreamSocketAdapter::outputStreamSocketAdapter(net::socket& sok)
-+	: m_socket(sok)
-+{
-+}
-+
-+
-+void outputStreamSocketAdapter::write
-+	(const value_type* const data, const size_type count)
-+{
-+	m_socket.sendRaw(data, count);
-+}
-+
-+
-+void outputStreamSocketAdapter::flush()
-+{
-+	// Do nothing
-+}
-+
-+
-+stream::size_type outputStreamSocketAdapter::getBlockSize()
-+{
-+	return m_socket.getBlockSize();
-+}
-+
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_HAVE_MESSAGING_FEATURES
-+
-diff --git a/src/utility/outputStreamStringAdapter.cpp b/src/utility/outputStreamStringAdapter.cpp
-new file mode 100644
-index 0000000..62b2a72
---- /dev/null
-+++ b/src/utility/outputStreamStringAdapter.cpp
-@@ -0,0 +1,51 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/outputStreamStringAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+outputStreamStringAdapter::outputStreamStringAdapter(string& buffer)
-+	: m_buffer(buffer)
-+{
-+}
-+
-+
-+void outputStreamStringAdapter::write(const value_type* const data, const size_type count)
-+{
-+	m_buffer.append(data, count);
-+}
-+
-+
-+void outputStreamStringAdapter::flush()
-+{
-+	// Do nothing
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/stream.cpp b/src/utility/stream.cpp
-index ec30b7d..1c940c2 100644
---- a/src/utility/stream.cpp
-+++ b/src/utility/stream.cpp
-@@ -22,503 +22,18 @@
- //
- 
- #include "vmime/utility/stream.hpp"
--#include "vmime/utility/stringProxy.hpp"
- 
--#include <algorithm>  // for std::copy
--#include <iterator>   // for std::back_inserter
--
--#if VMIME_HAVE_MESSAGING_FEATURES
--   #include "vmime/net/socket.hpp"
--#endif
- 
- 
- namespace vmime {
- namespace utility {
- 
- 
--// stream
--
- stream::size_type stream::getBlockSize()
- {
- 	return 32768;  // 32 KB
- }
- 
- 
--// Helpers
--
--outputStream& operator<<(outputStream& os, const stream::value_type c)
--{
--	os.write(&c, 1);
--	return (os);
--}
--
--
--outputStream& operator<<(outputStream& os, const string& str)
--{
--	os.write(str.data(), str.length());
--	return (os);
--}
--
--
--stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os)
--{
--	return bufferedStreamCopy(is, os, 0, NULL);
--}
--
--
--stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os,
--	const stream::size_type length, progressListener* progress)
--{
--	const stream::size_type blockSize =
--		std::min(is.getBlockSize(), os.getBlockSize());
--
--	std::vector <stream::value_type> vbuffer(blockSize);
--
--	stream::value_type* buffer = &vbuffer.front();
--	stream::size_type total = 0;
--
--	if (progress != NULL)
--		progress->start(length);
--
--	while (!is.eof())
--	{
--		const stream::size_type read = is.read(buffer, blockSize);
--
--		if (read != 0)
--		{
--			os.write(buffer, read);
--			total += read;
--
--			if (progress != NULL)
--				progress->progress(total, std::max(total, length));
--		}
--	}
--
--	if (progress != NULL)
--		progress->stop(total);
--
--	return (total);
--}
--
--
--
--// outputStreamAdapter
--
--outputStreamAdapter::outputStreamAdapter(std::ostream& os)
--	: m_stream(os)
--{
--}
--
--
--void outputStreamAdapter::write
--	(const value_type* const data, const size_type count)
--{
--	m_stream.exceptions(std::ios_base::badbit);
--	m_stream.write(data, count);
--}
--
--
--void outputStreamAdapter::flush()
--{
--	m_stream.exceptions(std::ios_base::badbit);
--	m_stream.flush();
--}
--
--
--
--// outputStreamStringAdapter
--
--outputStreamStringAdapter::outputStreamStringAdapter(string& buffer)
--	: m_buffer(buffer)
--{
--}
--
--
--void outputStreamStringAdapter::write(const value_type* const data, const size_type count)
--{
--	m_buffer.append(data, count);
--}
--
--
--void outputStreamStringAdapter::flush()
--{
--	// Do nothing
--}
--
--
--
--// outputStreamByteArrayAdapter
--
--outputStreamByteArrayAdapter::outputStreamByteArrayAdapter(byteArray& array)
--	: m_array(array)
--{
--}
--
--
--void outputStreamByteArrayAdapter::write(const value_type* const data, const size_type count)
--{
--	m_array.insert(m_array.end(), data, data + count);
--}
--
--
--void outputStreamByteArrayAdapter::flush()
--{
--	// Do nothing
--}
--
--
--
--// inputStreamAdapter
--
--inputStreamAdapter::inputStreamAdapter(std::istream& is)
--	: m_stream(is)
--{
--}
--
--
--bool inputStreamAdapter::eof() const
--{
--	return (m_stream.eof());
--}
--
--
--void inputStreamAdapter::reset()
--{
--	m_stream.exceptions(std::ios_base::badbit);
--	m_stream.seekg(0, std::ios::beg);
--	m_stream.clear();
--}
--
--
--stream::size_type inputStreamAdapter::read
--	(value_type* const data, const size_type count)
--{
--	m_stream.exceptions(std::ios_base::badbit);
--	m_stream.read(data, count);
--	return (m_stream.gcount());
--}
--
--
--stream::size_type inputStreamAdapter::skip(const size_type count)
--{
--	m_stream.exceptions(std::ios_base::badbit);
--	m_stream.ignore(count);
--	return (m_stream.gcount());
--}
--
--
--
--// inputStreamStringAdapter
--
--inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer)
--	: m_buffer(buffer), m_begin(0), m_end(buffer.length()), m_pos(0)
--{
--}
--
--
--inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer,
--	const string::size_type begin, const string::size_type end)
--	: m_buffer(buffer), m_begin(begin), m_end(end), m_pos(begin)
--{
--}
--
--
--bool inputStreamStringAdapter::eof() const
--{
--	return (m_pos >= m_end);
--}
--
--
--void inputStreamStringAdapter::reset()
--{
--	m_pos = m_begin;
--}
--
--
--stream::size_type inputStreamStringAdapter::read
--	(value_type* const data, const size_type count)
--{
--	if (m_pos + count >= m_end)
--	{
--		const size_type remaining = m_end - m_pos;
--
--		std::copy(m_buffer.begin() + m_pos, m_buffer.end(), data);
--		m_pos = m_end;
--		return (remaining);
--	}
--	else
--	{
--		std::copy(m_buffer.begin() + m_pos, m_buffer.begin() + m_pos + count, data);
--		m_pos += count;
--		return (count);
--	}
--}
--
--
--stream::size_type inputStreamStringAdapter::skip(const size_type count)
--{
--	if (m_pos + count >= m_end)
--	{
--		const size_type remaining = m_end - m_pos;
--		m_pos = m_end;
--		return (remaining);
--	}
--	else
--	{
--		m_pos += count;
--		return (count);
--	}
--}
--
--
--
--// inputStreamStringProxyAdapter
--
--inputStreamStringProxyAdapter::inputStreamStringProxyAdapter(const stringProxy& buffer)
--	: m_buffer(buffer), m_pos(0)
--{
--}
--
--
--bool inputStreamStringProxyAdapter::eof() const
--{
--	return (m_pos >= m_buffer.length());
--}
--
--
--void inputStreamStringProxyAdapter::reset()
--{
--	m_pos = 0;
--}
--
--
--stream::size_type inputStreamStringProxyAdapter::read
--	(value_type* const data, const size_type count)
--{
--	const size_type remaining = m_buffer.length() - m_pos;
--
--	if (count > remaining)
--	{
--		std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_end(), data);
--		m_pos = m_buffer.length();
--		return (remaining);
--	}
--	else
--	{
--		std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_begin() + m_pos + count, data);
--		m_pos += count;
--		return (count);
--	}
--}
--
--
--stream::size_type inputStreamStringProxyAdapter::skip(const size_type count)
--{
--	const size_type remaining = m_buffer.length() - m_pos;
--
--	if (count > remaining)
--	{
--		m_pos = m_buffer.length();
--		return (remaining);
--	}
--	else
--	{
--		m_pos += count;
--		return (count);
--	}
--}
--
--
--
--// inputStreamPointerAdapter
--
--inputStreamPointerAdapter::inputStreamPointerAdapter(std::istream* is, const bool own)
--	: m_stream(is), m_own(own)
--{
--}
--
--
--inputStreamPointerAdapter::inputStreamPointerAdapter(const inputStreamPointerAdapter&)
--	: inputStream(), m_stream(NULL), m_own(false)
--{
--	// Not copiable
--}
--
--
--inputStreamPointerAdapter::~inputStreamPointerAdapter()
--{
--	if (m_own)
--		delete (m_stream);
--}
--
--
--bool inputStreamPointerAdapter::eof() const
--{
--	return (m_stream->eof());
--}
--
--
--void inputStreamPointerAdapter::reset()
--{
--	m_stream->exceptions(std::ios_base::badbit);
--	m_stream->seekg(0, std::ios::beg);
--	m_stream->clear();
--}
--
--
--stream::size_type inputStreamPointerAdapter::read
--	(value_type* const data, const size_type count)
--{
--	m_stream->exceptions(std::ios_base::badbit);
--	m_stream->read(data, count);
--	return (m_stream->gcount());
--}
--
--
--stream::size_type inputStreamPointerAdapter::skip(const size_type count)
--{
--	m_stream->exceptions(std::ios_base::badbit);
--	m_stream->ignore(count);
--	return (m_stream->gcount());
--}
--
--
--
--// inputStreamByteBufferAdapter
--
--inputStreamByteBufferAdapter::inputStreamByteBufferAdapter(const byte_t* buffer, const size_type length)
--	: m_buffer(buffer), m_length(length), m_pos(0)
--{
--}
--
--
--bool inputStreamByteBufferAdapter::eof() const
--{
--	return m_pos >= m_length;
--}
--
--
--void inputStreamByteBufferAdapter::reset()
--{
--	m_pos = 0;
--}
--
--
--stream::size_type inputStreamByteBufferAdapter::read
--	(value_type* const data, const size_type count)
--{
--	const size_type remaining = m_length - m_pos;
--
--	if (remaining < count)
--	{
--		std::copy(m_buffer + m_pos, m_buffer + m_pos + remaining, data);
--		m_pos += remaining;
--
--		return remaining;
--	}
--	else
--	{
--		std::copy(m_buffer + m_pos, m_buffer + m_pos + count, data);
--		m_pos += count;
--
--		return count;
--	}
--}
--
--
--stream::size_type inputStreamByteBufferAdapter::skip(const size_type count)
--{
--	const size_type remaining = m_length - m_pos;
--
--	if (remaining < count)
--	{
--		m_pos += remaining;
--		return remaining;
--	}
--	else
--	{
--		m_pos += count;
--		return count;
--	}
--}
--
--
--
--#ifdef VMIME_HAVE_MESSAGING_FEATURES
--
--
--// outputStreamSocketAdapter
--
--outputStreamSocketAdapter::outputStreamSocketAdapter(net::socket& sok)
--	: m_socket(sok)
--{
--}
--
--
--void outputStreamSocketAdapter::write
--	(const value_type* const data, const size_type count)
--{
--	m_socket.sendRaw(data, count);
--}
--
--
--void outputStreamSocketAdapter::flush()
--{
--	// Do nothing
--}
--
--
--stream::size_type outputStreamSocketAdapter::getBlockSize()
--{
--	return m_socket.getBlockSize();
--}
--
--
--
--// inputStreamSocketAdapter
--
--inputStreamSocketAdapter::inputStreamSocketAdapter(net::socket& sok)
--	: m_socket(sok)
--{
--}
--
--
--bool inputStreamSocketAdapter::eof() const
--{
--	// Can't know...
--	return false;
--}
--
--
--void inputStreamSocketAdapter::reset()
--{
--	// Not supported
--}
--
--
--stream::size_type inputStreamSocketAdapter::read
--	(value_type* const data, const size_type count)
--{
--	return m_socket.receiveRaw(data, count);
--}
--
--
--stream::size_type inputStreamSocketAdapter::skip
--	(const size_type /* count */)
--{
--	// Not supported
--	return 0;
--}
--
--
--stream::size_type inputStreamSocketAdapter::getBlockSize()
--{
--	return m_socket.getBlockSize();
--}
--
--
--#endif // VMIME_HAVE_MESSAGING_FEATURES
--
--
- } // utility
- } // vmime
-diff --git a/src/utility/streamUtils.cpp b/src/utility/streamUtils.cpp
-new file mode 100644
-index 0000000..f1d3b9d
---- /dev/null
-+++ b/src/utility/streamUtils.cpp
-@@ -0,0 +1,92 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/streamUtils.hpp"
-+
-+#include <algorithm>  // for std::copy
-+#include <iterator>   // for std::back_inserter
-+
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+outputStream& operator<<(outputStream& os, const stream::value_type c)
-+{
-+	os.write(&c, 1);
-+	return (os);
-+}
-+
-+
-+outputStream& operator<<(outputStream& os, const string& str)
-+{
-+	os.write(str.data(), str.length());
-+	return (os);
-+}
-+
-+
-+stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os)
-+{
-+	return bufferedStreamCopy(is, os, 0, NULL);
-+}
-+
-+
-+stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os,
-+	const stream::size_type length, progressListener* progress)
-+{
-+	const stream::size_type blockSize =
-+		std::min(is.getBlockSize(), os.getBlockSize());
-+
-+	std::vector <stream::value_type> vbuffer(blockSize);
-+
-+	stream::value_type* buffer = &vbuffer.front();
-+	stream::size_type total = 0;
-+
-+	if (progress != NULL)
-+		progress->start(length);
-+
-+	while (!is.eof())
-+	{
-+		const stream::size_type read = is.read(buffer, blockSize);
-+
-+		if (read != 0)
-+		{
-+			os.write(buffer, read);
-+			total += read;
-+
-+			if (progress != NULL)
-+				progress->progress(total, std::max(total, length));
-+		}
-+	}
-+
-+	if (progress != NULL)
-+		progress->stop(total);
-+
-+	return (total);
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/stringProxy.cpp b/src/utility/stringProxy.cpp
-index a4ba6d2..74344b5 100644
---- a/src/utility/stringProxy.cpp
-+++ b/src/utility/stringProxy.cpp
-@@ -23,6 +23,8 @@
- 
- #include "vmime/utility/stringProxy.hpp"
- 
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+
- #include <iterator>
- #include <algorithm>
- 
-diff --git a/src/word.cpp b/src/word.cpp
-index aeaa737..79060a1 100644
---- a/src/word.cpp
-+++ b/src/word.cpp
-@@ -28,6 +28,9 @@
- #include "vmime/utility/smartPtr.hpp"
- #include "vmime/parserHelpers.hpp"
- 
-+#include "vmime/utility/outputStreamStringAdapter.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+
- #include "vmime/utility/encoder/encoder.hpp"
- #include "vmime/utility/encoder/b64Encoder.hpp"
- #include "vmime/utility/encoder/qpEncoder.hpp"
-diff --git a/src/wordEncoder.cpp b/src/wordEncoder.cpp
-index 67bd7a1..194a189 100644
---- a/src/wordEncoder.cpp
-+++ b/src/wordEncoder.cpp
-@@ -33,6 +33,9 @@
- 
- #include "vmime/utility/stringUtils.hpp"
- 
-+#include "vmime/utility/outputStreamStringAdapter.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+
- 
- namespace vmime
- {
-diff --git a/vmime/base.hpp b/vmime/base.hpp
-index 60e637d..b794031 100644
---- a/vmime/base.hpp
-+++ b/vmime/base.hpp
-@@ -35,7 +35,6 @@
- #include "vmime/config.hpp"
- #include "vmime/types.hpp"
- #include "vmime/constants.hpp"
--#include "vmime/utility/stream.hpp"
- #include "vmime/utility/smartPtr.hpp"
- 
- 
-@@ -255,7 +254,26 @@ namespace vmime
- 		return y.dynamicCast <X>();
- 	}
- 
-+	/** Inherit from this class to indicate the subclass is not copyable,
-+	  * ie. you want to prohibit copy construction and copy assignment.
-+	  */
-+	class noncopyable
-+	{
-+	protected:
-+
-+		noncopyable() { }
-+		virtual ~noncopyable() { }
-+
-+	private:
-+
-+		noncopyable(const noncopyable&);
-+		void operator=(const noncopyable&);
-+	};
-+
- } // vmime
- 
- 
-+#include "vmime/utility/stream.hpp"
-+
-+
- #endif // VMIME_BASE_HPP_INCLUDED
-diff --git a/vmime/charset.hpp b/vmime/charset.hpp
-index b2e241c..5f5e8e5 100644
---- a/vmime/charset.hpp
-+++ b/vmime/charset.hpp
-@@ -26,6 +26,8 @@
- 
- 
- #include "vmime/base.hpp"
-+#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/outputStream.hpp"
- #include "vmime/component.hpp"
- 
- 
-diff --git a/vmime/component.hpp b/vmime/component.hpp
-index b38127f..12b0406 100644
---- a/vmime/component.hpp
-+++ b/vmime/component.hpp
-@@ -26,6 +26,8 @@
- 
- 
- #include "vmime/base.hpp"
-+#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/outputStream.hpp"
- 
- 
- namespace vmime
-diff --git a/vmime/net/imap/IMAPParser.hpp b/vmime/net/imap/IMAPParser.hpp
-index d71c3ca..f430510 100644
---- a/vmime/net/imap/IMAPParser.hpp
-+++ b/vmime/net/imap/IMAPParser.hpp
-@@ -37,6 +37,9 @@
- #include "vmime/utility/encoder/b64Encoder.hpp"
- #include "vmime/utility/encoder/qpEncoder.hpp"
- 
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+#include "vmime/utility/outputStreamStringAdapter.hpp"
-+
- #include "vmime/platform.hpp"
- 
- #include "vmime/net/timeoutHandler.hpp"
-@@ -3825,7 +3828,7 @@ public:
- 			: m_date_time(NULL), m_number(NULL), m_envelope(NULL),
- 			  m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL),
- 			  m_section(NULL)
--              
-+
- 		{
- 		}
- 
-diff --git a/vmime/utility/filteredStream.hpp b/vmime/utility/filteredStream.hpp
-index 00be785..2a55edd 100644
---- a/vmime/utility/filteredStream.hpp
-+++ b/vmime/utility/filteredStream.hpp
-@@ -27,7 +27,8 @@
- 
- #include <algorithm>
- 
--#include "vmime/utility/stream.hpp"
-+#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/outputStream.hpp"
- 
- 
- namespace vmime {
-diff --git a/vmime/utility/inputStream.hpp b/vmime/utility/inputStream.hpp
-new file mode 100644
-index 0000000..4a76a7d
---- /dev/null
-+++ b/vmime/utility/inputStream.hpp
-@@ -0,0 +1,76 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_INPUTSTREAM_HPP_INCLUDED
-+#define VMIME_UTILITY_INPUTSTREAM_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/stream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** Simple input stream.
-+  */
-+
-+class inputStream : public stream
-+{
-+public:
-+
-+	/** Test for end of stream (no more data to read).
-+	  *
-+	  * @return true if we have reached the end of stream, false otherwise
-+	  */
-+	virtual bool eof() const = 0;
-+
-+	/** Set the read pointer to the beginning of the stream.
-+	  *
-+	  * @warning WARNING: this may not work for all stream types.
-+	  */
-+	virtual void reset() = 0;
-+
-+	/** Read data from the stream.
-+	  *
-+	  * @param data will receive the data read
-+	  * @param count maximum number of bytes to read
-+	  * @return number of bytes read
-+	  */
-+	virtual size_type read(value_type* const data, const size_type count) = 0;
-+
-+	/** Skip a number of bytes.
-+	  *
-+	  * @param count maximum number of bytes to ignore
-+	  * @return number of bytes skipped
-+	  */
-+	virtual size_type skip(const size_type count) = 0;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_INPUTSTREAM_HPP_INCLUDED
-+
-diff --git a/vmime/utility/inputStreamAdapter.hpp b/vmime/utility/inputStreamAdapter.hpp
-new file mode 100644
-index 0000000..278ab52
---- /dev/null
-+++ b/vmime/utility/inputStreamAdapter.hpp
-@@ -0,0 +1,64 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_INPUTSTREAMADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_INPUTSTREAMADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/inputStream.hpp"
-+
-+#include <istream>
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter class for C++ standard input streams.
-+  */
-+
-+class inputStreamAdapter : public inputStream
-+{
-+public:
-+
-+	/** @param is input stream to wrap
-+	  */
-+	inputStreamAdapter(std::istream& is);
-+
-+	bool eof() const;
-+	void reset();
-+	size_type read(value_type* const data, const size_type count);
-+	size_type skip(const size_type count);
-+
-+private:
-+
-+	std::istream& m_stream;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_INPUTSTREAMADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/inputStreamByteBufferAdapter.hpp b/vmime/utility/inputStreamByteBufferAdapter.hpp
-new file mode 100644
-index 0000000..0f6a442
---- /dev/null
-+++ b/vmime/utility/inputStreamByteBufferAdapter.hpp
-@@ -0,0 +1,63 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_INPUTSTREAMBYTEBUFFERADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_INPUTSTREAMBYTEBUFFERADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/inputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter class for reading from an array of bytes.
-+  */
-+
-+class inputStreamByteBufferAdapter : public inputStream
-+{
-+public:
-+
-+	inputStreamByteBufferAdapter(const byte_t* buffer, size_type length);
-+
-+	bool eof() const;
-+	void reset();
-+	size_type read(value_type* const data, const size_type count);
-+	size_type skip(const size_type count);
-+
-+private:
-+
-+	const byte_t* m_buffer;
-+	const size_type m_length;
-+
-+	size_type m_pos;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_INPUTSTREAMBYTEBUFFERADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/inputStreamPointerAdapter.hpp b/vmime/utility/inputStreamPointerAdapter.hpp
-new file mode 100644
-index 0000000..44e9bad
---- /dev/null
-+++ b/vmime/utility/inputStreamPointerAdapter.hpp
-@@ -0,0 +1,63 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_INPUTSTREAMPOINTERADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_INPUTSTREAMPOINTERADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/inputStreamAdapter.hpp"
-+
-+#include <istream>
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter class for pointer to C++ standard input stream.
-+  */
-+
-+class inputStreamPointerAdapter : public inputStreamAdapter
-+{
-+public:
-+
-+	/** @param is input stream to wrap
-+	  * @param own if set to 'true', the pointer will be deleted when
-+	  * this object is destroyed
-+	  */
-+	inputStreamPointerAdapter(std::istream* is, const bool own = true);
-+	~inputStreamPointerAdapter();
-+
-+private:
-+
-+	std::istream* m_stream;
-+	const bool m_own;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_INPUTSTREAMPOINTERADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/inputStreamSocketAdapter.hpp b/vmime/utility/inputStreamSocketAdapter.hpp
-new file mode 100644
-index 0000000..0f99c21
---- /dev/null
-+++ b/vmime/utility/inputStreamSocketAdapter.hpp
-@@ -0,0 +1,77 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/inputStream.hpp"
-+
-+
-+#if VMIME_HAVE_MESSAGING_FEATURES
-+
-+
-+namespace vmime {
-+namespace net {
-+	class socket;  // forward reference
-+} // net
-+} // vmime
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An input stream that is connected to a socket.
-+  */
-+
-+class inputStreamSocketAdapter : public inputStream
-+{
-+public:
-+
-+	inputStreamSocketAdapter(net::socket& sok);
-+
-+	bool eof() const;
-+	void reset();
-+	size_type read(value_type* const data, const size_type count);
-+	size_type skip(const size_type count);
-+
-+	size_type getBlockSize();
-+
-+private:
-+
-+	inputStreamSocketAdapter(const inputStreamSocketAdapter&);
-+
-+	net::socket& m_socket;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_HAVE_MESSAGING_FEATURES
-+
-+
-+#endif // VMIME_UTILITY_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/inputStreamStringAdapter.hpp b/vmime/utility/inputStreamStringAdapter.hpp
-new file mode 100644
-index 0000000..a7d986f
---- /dev/null
-+++ b/vmime/utility/inputStreamStringAdapter.hpp
-@@ -0,0 +1,66 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/inputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter class for string input.
-+  */
-+
-+class inputStreamStringAdapter : public inputStream
-+{
-+public:
-+
-+	inputStreamStringAdapter(const string& buffer);
-+	inputStreamStringAdapter(const string& buffer, const string::size_type begin, const string::size_type end);
-+
-+	bool eof() const;
-+	void reset();
-+	size_type read(value_type* const data, const size_type count);
-+	size_type skip(const size_type count);
-+
-+private:
-+
-+	inputStreamStringAdapter(const inputStreamStringAdapter&);
-+
-+	const string m_buffer;  // do _NOT_ keep a reference...
-+	const string::size_type m_begin;
-+	const string::size_type m_end;
-+	string::size_type m_pos;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/inputStreamStringProxyAdapter.hpp b/vmime/utility/inputStreamStringProxyAdapter.hpp
-new file mode 100644
-index 0000000..74b3f60
---- /dev/null
-+++ b/vmime/utility/inputStreamStringProxyAdapter.hpp
-@@ -0,0 +1,68 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/inputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+class stringProxy;
-+
-+
-+/** An adapter class for stringProxy input.
-+  */
-+
-+class inputStreamStringProxyAdapter : public inputStream
-+{
-+public:
-+
-+	/** @param buffer stringProxy object to wrap
-+	  */
-+	inputStreamStringProxyAdapter(const stringProxy& buffer);
-+
-+	bool eof() const;
-+	void reset();
-+	size_type read(value_type* const data, const size_type count);
-+	size_type skip(const size_type count);
-+
-+private:
-+
-+	inputStreamStringProxyAdapter(const inputStreamStringProxyAdapter&);
-+
-+	const stringProxy& m_buffer;
-+	string::size_type m_pos;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/outputStream.hpp b/vmime/utility/outputStream.hpp
-new file mode 100644
-index 0000000..7372d20
---- /dev/null
-+++ b/vmime/utility/outputStream.hpp
-@@ -0,0 +1,107 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_OUTPUTSTREAM_HPP_INCLUDED
-+#define VMIME_UTILITY_OUTPUTSTREAM_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/stream.hpp"
-+
-+
-+#if defined(_MSC_VER) && (_MSC_VER <= 1200)  // VC++6
-+#	include <cstring>
-+#endif
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** Simple output stream.
-+  */
-+
-+class outputStream : public stream
-+{
-+public:
-+
-+	/** Write data to the stream.
-+	  *
-+	  * @param data buffer containing data to write
-+	  * @param count number of bytes to write
-+	  */
-+	virtual void write(const value_type* const data, const size_type count) = 0;
-+
-+	/** Flush this output stream and forces any buffered output
-+	  * bytes to be written out to the stream.
-+	  */
-+	virtual void flush() = 0;
-+};
-+
-+
-+// Helpers functions
-+
-+outputStream& operator<<(outputStream& os, const string& str);
-+outputStream& operator<<(outputStream& os, const stream::value_type c);
-+
-+
-+#if defined(_MSC_VER) && (_MSC_VER <= 1200)  // Internal compiler error with VC++6
-+
-+inline outputStream& operator<<(outputStream& os, const char* str)
-+{
-+	os.write(str, ::strlen(str));
-+	return (os);
-+}
-+
-+#else
-+
-+template <int N>
-+outputStream& operator<<(outputStream& os, const char (&str)[N])
-+{
-+	os.write(str, N - 1);
-+	return (os);
-+}
-+
-+#endif // defined(_MSC_VER) && (_MSC_VER <= 1200)
-+
-+
-+template <typename T>
-+outputStream& operator<<(outputStream& os, const T& t)
-+{
-+	std::ostringstream oss;
-+	oss.imbue(std::locale::classic());  // no formatting
-+
-+	oss << t;
-+
-+	os << oss.str();
-+
-+	return (os);
-+}
-+
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_OUTPUTSTREAM_HPP_INCLUDED
-+
-diff --git a/vmime/utility/outputStreamAdapter.hpp b/vmime/utility/outputStreamAdapter.hpp
-new file mode 100644
-index 0000000..be55d8d
---- /dev/null
-+++ b/vmime/utility/outputStreamAdapter.hpp
-@@ -0,0 +1,62 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_OUTPUTSTREAMADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_OUTPUTSTREAMADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/outputStream.hpp"
-+
-+#include <ostream>
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter class for C++ standard output streams.
-+  */
-+
-+class outputStreamAdapter : public outputStream
-+{
-+public:
-+
-+	/** @param os output stream to wrap
-+	  */
-+	outputStreamAdapter(std::ostream& os);
-+
-+	void write(const value_type* const data, const size_type count);
-+	void flush();
-+
-+private:
-+
-+	std::ostream& m_stream;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_OUTPUTSTREAMADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/outputStreamByteArrayAdapter.hpp b/vmime/utility/outputStreamByteArrayAdapter.hpp
-new file mode 100644
-index 0000000..bf7d839
---- /dev/null
-+++ b/vmime/utility/outputStreamByteArrayAdapter.hpp
-@@ -0,0 +1,58 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/outputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter class for byte array output.
-+  */
-+
-+class outputStreamByteArrayAdapter : public outputStream
-+{
-+public:
-+
-+	outputStreamByteArrayAdapter(byteArray& array);
-+
-+	void write(const value_type* const data, const size_type count);
-+	void flush();
-+
-+private:
-+
-+	byteArray& m_array;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/outputStreamSocketAdapter.hpp b/vmime/utility/outputStreamSocketAdapter.hpp
-new file mode 100644
-index 0000000..e3d3eb0
---- /dev/null
-+++ b/vmime/utility/outputStreamSocketAdapter.hpp
-@@ -0,0 +1,75 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/outputStream.hpp"
-+
-+
-+#if VMIME_HAVE_MESSAGING_FEATURES
-+
-+
-+namespace vmime {
-+namespace net {
-+	class socket;  // forward reference
-+} // net
-+} // vmime
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An output stream that is connected to a socket.
-+  */
-+
-+class outputStreamSocketAdapter : public outputStream
-+{
-+public:
-+
-+	outputStreamSocketAdapter(net::socket& sok);
-+
-+	void write(const value_type* const data, const size_type count);
-+	void flush();
-+
-+	size_type getBlockSize();
-+
-+private:
-+
-+	outputStreamSocketAdapter(const outputStreamSocketAdapter&);
-+
-+	net::socket& m_socket;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_HAVE_MESSAGING_FEATURES
-+
-+
-+#endif // VMIME_UTILITY_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/outputStreamStringAdapter.hpp b/vmime/utility/outputStreamStringAdapter.hpp
-new file mode 100644
-index 0000000..8c8b304
---- /dev/null
-+++ b/vmime/utility/outputStreamStringAdapter.hpp
-@@ -0,0 +1,59 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/outputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter class for string output.
-+  */
-+
-+class outputStreamStringAdapter : public outputStream
-+{
-+public:
-+
-+	outputStreamStringAdapter(string& buffer);
-+
-+	void write(const value_type* const data, const size_type count);
-+	void flush();
-+
-+size_type getBlockSize(){return 8192;}
-+private:
-+
-+	string& m_buffer;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/stream.hpp b/vmime/utility/stream.hpp
-index 1faab55..566ab9d 100644
---- a/vmime/utility/stream.hpp
-+++ b/vmime/utility/stream.hpp
-@@ -25,40 +25,22 @@
- #define VMIME_UTILITY_STREAM_HPP_INCLUDED
- 
- 
--#include <istream>
--#include <ostream>
- #include <sstream>
- 
- #include "vmime/config.hpp"
- #include "vmime/types.hpp"
--
--#include "vmime/utility/progressListener.hpp"
--
--
--#if VMIME_HAVE_MESSAGING_FEATURES
--	namespace vmime {
--	namespace net {
--		class socket;  // forward reference
--	} // net
--	} // vmime
--#endif
--
--#if defined(_MSC_VER) && (_MSC_VER <= 1200)  // VC++6
--#   include <cstring>
--#endif
-+#include "vmime/base.hpp"
- 
- 
- namespace vmime {
- namespace utility {
- 
- 
--class stringProxy;
--
- 
- /** Base class for input/output stream.
-   */
- 
--class stream : public object
-+class stream : public object, private noncopyable
- {
- public:
- 
-@@ -81,365 +63,6 @@ public:
- };
- 
- 
--
--/** Simple output stream.
--  */
--
--class outputStream : public stream
--{
--public:
--
--	/** Write data to the stream.
--	  *
--	  * @param data buffer containing data to write
--	  * @param count number of bytes to write
--	  */
--	virtual void write(const value_type* const data, const size_type count) = 0;
--
--	/** Flush this output stream and forces any buffered output
--	  * bytes to be written out to the stream.
--	  */
--	virtual void flush() = 0;
--};
--
--
--
--/** Simple input stream.
--  */
--
--class inputStream : public stream
--{
--public:
--
--	/** Test for end of stream (no more data to read).
--	  *
--	  * @return true if we have reached the end of stream, false otherwise
--	  */
--	virtual bool eof() const = 0;
--
--	/** Set the read pointer to the beginning of the stream.
--	  *
--	  * @warning WARNING: this may not work for all stream types.
--	  */
--	virtual void reset() = 0;
--
--	/** Read data from the stream.
--	  *
--	  * @param data will receive the data read
--	  * @param count maximum number of bytes to read
--	  * @return number of bytes read
--	  */
--	virtual size_type read(value_type* const data, const size_type count) = 0;
--
--	/** Skip a number of bytes.
--	  *
--	  * @param count maximum number of bytes to ignore
--	  * @return number of bytes skipped
--	  */
--	virtual size_type skip(const size_type count) = 0;
--};
--
--
--
--// Helpers functions
--
--outputStream& operator<<(outputStream& os, const string& str);
--outputStream& operator<<(outputStream& os, const stream::value_type c);
--
--
--#if defined(_MSC_VER) && (_MSC_VER <= 1200)  // Internal compiler error with VC++6
--
--inline outputStream& operator<<(outputStream& os, const char* str)
--{
--	os.write(str, ::strlen(str));
--	return (os);
--}
--
--#else
--
--template <int N>
--outputStream& operator<<(outputStream& os, const char (&str)[N])
--{
--	os.write(str, N - 1);
--	return (os);
--}
--
--#endif // defined(_MSC_VER) && (_MSC_VER <= 1200)
--
--
--template <typename T>
--outputStream& operator<<(outputStream& os, const T& t)
--{
--	std::ostringstream oss;
--	oss.imbue(std::locale::classic());  // no formatting
--
--	oss << t;
--
--	os << oss.str();
--
--	return (os);
--}
--
--
--/** Copy data from one stream into another stream using a buffered method.
--  *
--  * @param is input stream (source data)
--  * @param os output stream (destination for data)
--  * @return number of bytes copied
--  */
--
--stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os);
--
--/** Copy data from one stream into another stream using a buffered method
--  * and notify progress state of the operation.
--  *
--  * @param is input stream (source data)
--  * @param os output stream (destination for data)
--  * @param length predicted number of bytes to copy
--  * @param progress listener to notify
--  * @return number of bytes copied
--  */
--
--stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os,
--	const stream::size_type length, progressListener* progress);
--
--
--// Adapters
--
--
--/** An adapter class for C++ standard output streams.
--  */
--
--class outputStreamAdapter : public outputStream
--{
--public:
--
--	/** @param os output stream to wrap
--	  */
--	outputStreamAdapter(std::ostream& os);
--
--	void write(const value_type* const data, const size_type count);
--	void flush();
--
--private:
--
--	std::ostream& m_stream;
--};
--
--
--/** An adapter class for string output.
--  */
--
--class outputStreamStringAdapter : public outputStream
--{
--public:
--
--	outputStreamStringAdapter(string& buffer);
--
--	void write(const value_type* const data, const size_type count);
--	void flush();
--
--size_type getBlockSize(){return 8192;}
--private:
--
--	string& m_buffer;
--};
--
--
--/** An adapter class for byte array output.
--  */
--
--class outputStreamByteArrayAdapter : public outputStream
--{
--public:
--
--	outputStreamByteArrayAdapter(byteArray& array);
--
--	void write(const value_type* const data, const size_type count);
--	void flush();
--
--private:
--
--	byteArray& m_array;
--};
--
--
--/** An adapter class for C++ standard input streams.
--  */
--
--class inputStreamAdapter : public inputStream
--{
--public:
--
--	/** @param is input stream to wrap
--	  */
--	inputStreamAdapter(std::istream& is);
--
--	bool eof() const;
--	void reset();
--	size_type read(value_type* const data, const size_type count);
--	size_type skip(const size_type count);
--
--private:
--
--	std::istream& m_stream;
--};
--
--
--/** An adapter class for string input.
--  */
--
--class inputStreamStringAdapter : public inputStream
--{
--public:
--
--	inputStreamStringAdapter(const string& buffer);
--	inputStreamStringAdapter(const string& buffer, const string::size_type begin, const string::size_type end);
--
--	bool eof() const;
--	void reset();
--	size_type read(value_type* const data, const size_type count);
--	size_type skip(const size_type count);
--
--private:
--
--	inputStreamStringAdapter(const inputStreamStringAdapter&);
--
--	const string m_buffer;  // do _NOT_ keep a reference...
--	const string::size_type m_begin;
--	const string::size_type m_end;
--	string::size_type m_pos;
--};
--
--
--/** An adapter class for stringProxy input.
--  */
--
--class inputStreamStringProxyAdapter : public inputStream
--{
--public:
--
--	/** @param buffer stringProxy object to wrap
--	  */
--	inputStreamStringProxyAdapter(const stringProxy& buffer);
--
--	bool eof() const;
--	void reset();
--	size_type read(value_type* const data, const size_type count);
--	size_type skip(const size_type count);
--
--private:
--
--	inputStreamStringProxyAdapter(const inputStreamStringProxyAdapter&);
--
--	const stringProxy& m_buffer;
--	string::size_type m_pos;
--};
--
--
--/** An adapter class for pointer to C++ standard input stream.
--  */
--
--class inputStreamPointerAdapter : public inputStream
--{
--public:
--
--	/** @param is input stream to wrap
--	  * @param own if set to 'true', the pointer will be deleted when
--	  * this object is destroyed
--	  */
--	inputStreamPointerAdapter(std::istream* is, const bool own = true);
--	~inputStreamPointerAdapter();
--
--	bool eof() const;
--	void reset();
--	size_type read(value_type* const data, const size_type count);
--	size_type skip(const size_type count);
--
--private:
--
--	inputStreamPointerAdapter(const inputStreamPointerAdapter&);
--
--	std::istream* m_stream;
--	const bool m_own;
--};
--
--
--/** An adapter class for reading from an array of bytes.
--  */
--
--class inputStreamByteBufferAdapter : public inputStream
--{
--public:
--
--	inputStreamByteBufferAdapter(const byte_t* buffer, size_type length);
--
--	bool eof() const;
--	void reset();
--	size_type read(value_type* const data, const size_type count);
--	size_type skip(const size_type count);
--
--private:
--
--	const byte_t* m_buffer;
--	const size_type m_length;
--
--	size_type m_pos;
--};
--
--
--#if VMIME_HAVE_MESSAGING_FEATURES
--
--
--/** An output stream that is connected to a socket.
--  */
--
--class outputStreamSocketAdapter : public outputStream
--{
--public:
--
--	outputStreamSocketAdapter(net::socket& sok);
--
--	void write(const value_type* const data, const size_type count);
--	void flush();
--
--	size_type getBlockSize();
--
--private:
--
--	outputStreamSocketAdapter(const outputStreamSocketAdapter&);
--
--	net::socket& m_socket;
--};
--
--
--/** An input stream that is connected to a socket.
--  */
--
--class inputStreamSocketAdapter : public inputStream
--{
--public:
--
--	inputStreamSocketAdapter(net::socket& sok);
--
--	bool eof() const;
--	void reset();
--	size_type read(value_type* const data, const size_type count);
--	size_type skip(const size_type count);
--
--	size_type getBlockSize();
--
--private:
--
--	inputStreamSocketAdapter(const inputStreamSocketAdapter&);
--
--	net::socket& m_socket;
--};
--
--
--#endif // VMIME_HAVE_MESSAGING_FEATURES
--
--
- } // utility
- } // vmime
- 
-diff --git a/vmime/utility/streamUtils.hpp b/vmime/utility/streamUtils.hpp
-new file mode 100644
-index 0000000..cdf70aa
---- /dev/null
-+++ b/vmime/utility/streamUtils.hpp
-@@ -0,0 +1,66 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_STREAMUTILS_HPP_INCLUDED
-+#define VMIME_UTILITY_STREAMUTILS_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/outputStream.hpp"
-+
-+#include "vmime/utility/progressListener.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** Copy data from one stream into another stream using a buffered method.
-+  *
-+  * @param is input stream (source data)
-+  * @param os output stream (destination for data)
-+  * @return number of bytes copied
-+  */
-+
-+stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os);
-+
-+/** Copy data from one stream into another stream using a buffered method
-+  * and notify progress state of the operation.
-+  *
-+  * @param is input stream (source data)
-+  * @param os output stream (destination for data)
-+  * @param length predicted number of bytes to copy
-+  * @param progress listener to notify
-+  * @return number of bytes copied
-+  */
-+
-+stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os,
-+	const stream::size_type length, progressListener* progress);
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_STREAMUTILS_HPP_INCLUDED
-+
-diff --git a/vmime/utility/stringProxy.hpp b/vmime/utility/stringProxy.hpp
-index 21c65ea..66a6dfd 100644
---- a/vmime/utility/stringProxy.hpp
-+++ b/vmime/utility/stringProxy.hpp
-@@ -29,6 +29,7 @@
- 
- #include "vmime/types.hpp"
- #include "vmime/utility/stream.hpp"
-+#include "vmime/utility/outputStream.hpp"
- #include "vmime/utility/progressListener.hpp"
- 
- 
-diff --git a/vmime/vmime.hpp b/vmime/vmime.hpp
-index f187b9e..fd04853 100644
---- a/vmime/vmime.hpp
-+++ b/vmime/vmime.hpp
-@@ -68,6 +68,22 @@
- // Encoders
- #include "vmime/utility/encoder/encoderFactory.hpp"
- 
-+// Streams
-+#include "vmime/utility/filteredStream.hpp"
-+#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/inputStreamAdapter.hpp"
-+#include "vmime/utility/inputStreamByteBufferAdapter.hpp"
-+#include "vmime/utility/inputStreamPointerAdapter.hpp"
-+#include "vmime/utility/inputStreamSocketAdapter.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
-+#include "vmime/utility/inputStreamStringProxyAdapter.hpp"
-+#include "vmime/utility/outputStream.hpp"
-+#include "vmime/utility/outputStreamAdapter.hpp"
-+#include "vmime/utility/outputStreamByteArrayAdapter.hpp"
-+#include "vmime/utility/outputStreamSocketAdapter.hpp"
-+#include "vmime/utility/outputStreamStringAdapter.hpp"
-+#include "vmime/utility/streamUtils.hpp"
-+
- // Message builder/parser
- #include "vmime/messageBuilder.hpp"
- #include "vmime/messageParser.hpp"
--- 
-1.7.10.4
-
-
-From be30b47f09c5358db2ac8e42fa2bb4a14ec24c51 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Mon, 16 Apr 2012 22:32:33 +0200
-Subject: [PATCH 37/47] Added ability to parse directly from an input stream
- (eg. file). This allows very big messages to be
- parsed without loading the whole message data into
- memory.
-
-
-diff --git a/ChangeLog b/ChangeLog
-index 8fdcdb0..1b5b2cf 100644
---- a/ChangeLog
-+++ b/ChangeLog
-@@ -2,6 +2,12 @@
- VERSION 0.9.2svn
- ================
- 
-+2012-04-16  Vincent Richard  <vincent@vincent-richard.net>
-+
-+ * MIME Parser can now operate directly on an input stream (eg. file).
-+   This allows very big messages to be parsed without loading the whole
-+   message data into memory.
-+
- 2010-11-16  Vincent Richard  <vincent@vincent-richard.net>
- 
-  * Started version 0.9.2.
-diff --git a/SConstruct b/SConstruct
-index ea5c4eb..2690172 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -153,11 +153,14 @@ libvmime_sources = [
- 	'utility/inputStreamSocketAdapter.cpp', 'utility/inputStreamSocketAdapter.hpp',
- 	'utility/inputStreamStringAdapter.cpp', 'utility/inputStreamStringAdapter.hpp',
- 	'utility/inputStreamStringProxyAdapter.cpp', 'utility/inputStreamStringProxyAdapter.hpp',
-+	'utility/seekableInputStream.hpp',
-+	'utility/seekableInputStreamRegionAdapter.cpp', 'utility/seekableInputStreamRegionAdapter.hpp',
- 	'utility/outputStream.cpp', 'utility/outputStream.hpp',
- 	'utility/outputStreamAdapter.cpp', 'utility/outputStreamAdapter.hpp',
- 	'utility/outputStreamByteArrayAdapter.cpp', 'utility/outputStreamByteArrayAdapter.hpp',
- 	'utility/outputStreamSocketAdapter.cpp', 'utility/outputStreamSocketAdapter.hpp',
- 	'utility/outputStreamStringAdapter.cpp', 'utility/outputStreamStringAdapter.hpp',
-+	'utility/parserInputStreamAdapter.cpp', 'utility/parserInputStreamAdapter.hpp',
- 	'utility/stringProxy.cpp', 'utility/stringProxy.hpp',
- 	'utility/stringUtils.cpp', 'utility/stringUtils.hpp',
- 	'utility/url.cpp', 'utility/url.hpp',
-diff --git a/src/addressList.cpp b/src/addressList.cpp
-index 31a2a3d..f06460d 100644
---- a/src/addressList.cpp
-+++ b/src/addressList.cpp
-@@ -50,7 +50,7 @@ addressList::~addressList()
- }
- 
- 
--void addressList::parse(const string& buffer, const string::size_type position,
-+void addressList::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	removeAllAddresses();
-@@ -72,7 +72,7 @@ void addressList::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void addressList::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void addressList::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	string::size_type pos = curLinePos;
-@@ -248,9 +248,9 @@ const std::vector <ref <address> > addressList::getAddressList()
- }
- 
- 
--const std::vector <ref <const component> > addressList::getChildComponents() const
-+const std::vector <ref <component> > addressList::getChildComponents()
- {
--	std::vector <ref <const component> > list;
-+	std::vector <ref <component> > list;
- 
- 	copy_vector(m_list, list);
- 
-diff --git a/src/body.cpp b/src/body.cpp
-index 9d7d57f..732fa8b 100644
---- a/src/body.cpp
-+++ b/src/body.cpp
-@@ -31,10 +31,13 @@
- 
- #include "vmime/utility/random.hpp"
- 
-+#include "vmime/utility/seekableInputStreamRegionAdapter.hpp"
-+
- #include "vmime/parserHelpers.hpp"
- 
- #include "vmime/emptyContentHandler.hpp"
- #include "vmime/stringContentHandler.hpp"
-+#include "vmime/streamContentHandler.hpp"
- 
- 
- namespace vmime
-@@ -52,11 +55,28 @@ body::~body()
- }
- 
- 
--void body::parse(const string& buffer, const string::size_type position,
--	const string::size_type end, string::size_type* newPosition)
-+void body::parseImpl
-+	(ref <utility::parserInputStreamAdapter> parser,
-+	 const utility::stream::size_type position,
-+	 const utility::stream::size_type end,
-+	 utility::stream::size_type* newPosition)
- {
- 	removeAllParts();
- 
-+	m_prologText.clear();
-+	m_epilogText.clear();
-+
-+	if (end == position)
-+	{
-+
-+		setParsedBounds(position, end);
-+
-+		if (newPosition)
-+			*newPosition = end;
-+
-+		return;
-+	}
-+
- 	// Check whether the body is a MIME-multipart
- 	bool isMultipart = false;
- 	string boundary;
-@@ -80,37 +100,61 @@ void body::parse(const string& buffer, const string::size_type position,
- 			{
- 				// No "boundary" parameter specified: we can try to
- 				// guess it by scanning the body contents...
--				string::size_type pos = buffer.find("\n--", position);
-+				utility::stream::size_type pos = position;
-+
-+				parser->seek(pos);
-+
-+				if (pos + 2 < end && parser->matchBytes("--", 2))
-+				{
-+					pos += 2;
-+				}
-+				else
-+				{
-+					pos = parser->findNext("\n--", position);
- 
--				if ((pos != string::npos) && (pos < end))
-+					if ((pos != utility::stream::npos) && (pos + 3 < end))
-+						pos += 3;  // skip \n--
-+				}
-+
-+				if ((pos != utility::stream::npos) && (pos < end))
- 				{
--					pos += 3;
-+					parser->seek(pos);
- 
--					const string::size_type start = pos;
-+					// Read some bytes after boundary separator
-+					utility::stream::value_type buffer[256];
-+					const utility::stream::size_type bufferLen =
-+						parser->read(buffer, std::min(end - pos, sizeof(buffer) / sizeof(buffer[0])));
- 
--					char_t c = buffer[pos];
--					string::size_type length = 0;
-+					buffer[sizeof(buffer) / sizeof(buffer[0]) - 1] = '\0';
- 
-+					// Extract boundary from buffer (stop at first CR or LF).
- 					// We have to stop after a reasonnably long boundary length (100)
- 					// not to take the whole body contents for a boundary...
--					while (pos < end && length < 100 && !(c == '\r' || c == '\n'))
-+					string::value_type boundaryBytes[100];
-+					string::size_type boundaryLen = 0;
-+
-+					for (string::value_type c = buffer[0] ;
-+					     boundaryLen < bufferLen && boundaryLen < 100 && !(c == '\r' || c == '\n') ;
-+					     c = buffer[++boundaryLen])
- 					{
--						++length;
--						c = buffer[pos++];
-+						boundaryBytes[boundaryLen] = buffer[boundaryLen];
- 					}
- 
--					if (pos < end && length < 100)
-+					if (boundaryLen >= 1 && boundaryLen < 100)
- 					{
- 						// RFC #1521, Page 31:
- 						// "...the boundary parameter, which consists of 1 to 70
- 						//  characters from a set of characters known to be very
- 						//  robust through email gateways, and NOT ending with
- 						//  white space..."
--						while (pos != start && parserHelpers::isSpace(buffer[pos - 1]))
--							--pos;
--
--						boundary = string(buffer.begin() + start,
--						                  buffer.begin() + pos);
-+						while (boundaryLen != 0 &&
-+						       parserHelpers::isSpace(boundaryBytes[boundaryLen - 1]))
-+						{
-+							boundaryLen--;
-+						}
-+
-+						if (boundaryLen >= 1)
-+							boundary = string(boundaryBytes, boundaryBytes + boundaryLen);
- 					}
- 				}
- 			}
-@@ -126,51 +170,79 @@ void body::parse(const string& buffer, const string::size_type position,
- 	{
- 		const string boundarySep("--" + boundary);
- 
--		string::size_type partStart = position;
--		string::size_type pos = position;
-+		utility::stream::size_type partStart = position;
-+		utility::stream::size_type pos = position;
- 
- 		bool lastPart = false;
- 
--		while (pos != string::npos && pos < end)
-+		while (pos != utility::stream::npos && pos < end)
- 		{
--			pos = buffer.find(boundarySep, pos);
--
--			if (pos == string::npos ||
--			    ((pos == 0 || buffer[pos - 1] == '\n') &&
--			     (buffer[pos + boundarySep.length()] == '\r' ||
--			      buffer[pos + boundarySep.length()] == '\n' ||
--			      buffer[pos + boundarySep.length()] == '-'
--			     )
--			    )
--			   )
-+			pos = parser->findNext(boundarySep, pos);
-+
-+			if (pos == utility::stream::npos)
-+				break;  // not found
-+
-+			if (pos != 0)
- 			{
--				break;
-+				parser->seek(pos - 1);
-+
-+				if (parser->peekByte() != '\n')
-+				{
-+					// Boundary is not at a beginning of a line
-+					pos++;
-+					continue;
-+				}
-+
-+				parser->skip(1 + boundarySep.length());
-+			}
-+			else
-+			{
-+				parser->seek(pos + boundarySep.length());
- 			}
- 
--			// boundary not a beginning of line, or just a prefix of another, continue the search.
-+			const utility::stream::value_type next = parser->peekByte();
-+
-+			if (next == '\r' || next == '\n' || next == '-')
-+				break;
-+
-+			// Boundary is a prefix of another, continue the search
- 			pos++;
- 		}
- 
--		if (pos != string::npos && pos < end)
-+		if (pos != utility::stream::npos && pos < end)
- 		{
- 			vmime::text text;
--			text.parse(buffer, position, pos);
-+			text.parse(parser, position, pos);
- 
- 			m_prologText = text.getWholeBuffer();
- 		}
- 
--		for (int index = 0 ; !lastPart && (pos != string::npos) && (pos < end) ; ++index)
-+		for (int index = 0 ; !lastPart && (pos != utility::stream::npos) && (pos < end) ; ++index)
- 		{
--			string::size_type partEnd = pos;
-+			utility::stream::size_type partEnd = pos;
- 
- 			// Get rid of the [CR]LF just before the boundary string
--			if (pos >= (position + 1) && buffer[pos - 1] == '\n') --partEnd;
--			if (pos >= (position + 2) && buffer[pos - 2] == '\r') --partEnd;
-+			if (pos >= (position + 1))
-+			{
-+				parser->seek(pos - 1);
-+
-+				if (parser->peekByte() == '\n')
-+					--partEnd;
-+			}
-+
-+			if (pos >= (position + 2))
-+			{
-+				parser->seek(pos - 2);
-+
-+				if (parser->peekByte() == '\r')
-+					--partEnd;
-+			}
- 
- 			// Check whether it is the last part (boundary terminated by "--")
- 			pos += boundarySep.length();
-+			parser->seek(pos);
- 
--			if (pos + 1 < end && buffer[pos] == '-' && buffer[pos + 1] == '-')
-+			if (pos + 1 < end && parser->matchBytes("--", 2))
- 			{
- 				lastPart = true;
- 				pos += 2;
-@@ -180,15 +252,15 @@ void body::parse(const string& buffer, const string::size_type position,
- 			// "...(If a boundary appears to end with white space, the
- 			//  white space must be presumed to have been added by a
- 			//  gateway, and must be deleted.)..."
--			while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t'))
--				++pos;
-+			parser->seek(pos);
-+			pos += parser->skipIf(parserHelpers::isSpaceOrTab, end);
- 
- 			// End of boundary line
--			if (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] =='\n')
-+			if (pos + 1 < end && parser->matchBytes("\r\n", 2))
- 			{
- 				pos += 2;
- 			}
--			else if (pos < end && buffer[pos] == '\n')
-+			else if (pos < end && parser->peekByte() == '\n')
- 			{
- 				++pos;
- 			}
-@@ -202,7 +274,7 @@ void body::parse(const string& buffer, const string::size_type position,
- 				if (partEnd < partStart)
- 					std::swap(partStart, partEnd);
- 
--				part->parse(buffer, partStart, partEnd, NULL);
-+				part->parse(parser, partStart, partEnd, NULL);
- 				part->m_parent = m_part;
- 
- 				m_parts.push_back(part);
-@@ -210,23 +282,37 @@ void body::parse(const string& buffer, const string::size_type position,
- 
- 			partStart = pos;
- 
--			while (pos != string::npos && pos < end)
-+			while (pos != utility::stream::npos && pos < end)
- 			{
--				pos = buffer.find(boundarySep, pos);
--
--				if (pos == string::npos ||
--				    ((pos == 0 || buffer[pos - 1] == '\n') &&
--				     (buffer[pos + boundarySep.length()] == '\r' ||
--				      buffer[pos + boundarySep.length()] == '\n' ||
--					buffer[pos + boundarySep.length()] == '-'
--				     )
--				    )
--				   )
-+				pos = parser->findNext(boundarySep, pos);
-+
-+				if (pos == utility::stream::npos)
-+					break;  // not found
-+
-+				if (pos != 0)
- 				{
--					break;
-+					parser->seek(pos - 1);
-+
-+					if (parser->peekByte() != '\n')
-+					{
-+						// Boundary is not at a beginning of a line
-+						pos++;
-+						continue;
-+					}
-+
-+					parser->skip(1 + boundarySep.length());
-+				}
-+				else
-+				{
-+					parser->seek(pos + boundarySep.length());
- 				}
- 
--				// boundary not a beginning of line, or just a prefix of another, continue the search.
-+				const utility::stream::value_type next = parser->peekByte();
-+
-+				if (next == '\r' || next == '\n' || next == '-')
-+					break;
-+
-+				// Boundary is a prefix of another, continue the search
- 				pos++;
- 			}
- 		}
-@@ -234,13 +320,13 @@ void body::parse(const string& buffer, const string::size_type position,
- 		m_contents = vmime::create <emptyContentHandler>();
- 
- 		// Last part was not found: recover from missing boundary
--		if (!lastPart && pos == string::npos)
-+		if (!lastPart && pos == utility::stream::npos)
- 		{
- 			ref <bodyPart> part = vmime::create <bodyPart>();
- 
- 			try
- 			{
--				part->parse(buffer, partStart, end);
-+				part->parse(parser, partStart, end);
- 			}
- 			catch (std::exception&)
- 			{
-@@ -255,7 +341,7 @@ void body::parse(const string& buffer, const string::size_type position,
- 		else if (partStart < end)
- 		{
- 			vmime::text text;
--			text.parse(buffer, partStart, end);
-+			text.parse(parser, partStart, end);
- 
- 			m_epilogText = text.getWholeBuffer();
- 		}
-@@ -282,7 +368,13 @@ void body::parse(const string& buffer, const string::size_type position,
- 		}
- 
- 		// Extract the (encoded) contents
--		m_contents = vmime::create <stringContentHandler>(buffer, position, end, enc);
-+		const utility::stream::size_type length = end - position;
-+
-+		ref <utility::inputStream> contentStream =
-+			vmime::create <utility::seekableInputStreamRegionAdapter>
-+				(parser->getUnderlyingStream(), position, length);
-+
-+		m_contents = vmime::create <streamContentHandler>(contentStream, length, enc);
- 	}
- 
- 	setParsedBounds(position, end);
-@@ -292,7 +384,7 @@ void body::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void body::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void body::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type /* curLinePos */, string::size_type* newLinePos) const
- {
- 	// MIME-Multipart
-@@ -862,9 +954,9 @@ const std::vector <ref <bodyPart> > body::getPartList()
- }
- 
- 
--const std::vector <ref <const component> > body::getChildComponents() const
-+const std::vector <ref <component> > body::getChildComponents()
- {
--	std::vector <ref <const component> > list;
-+	std::vector <ref <component> > list;
- 
- 	copy_vector(m_parts, list);
- 
-diff --git a/src/bodyPart.cpp b/src/bodyPart.cpp
-index 7d60461..522cbb2 100644
---- a/src/bodyPart.cpp
-+++ b/src/bodyPart.cpp
-@@ -46,15 +46,18 @@ bodyPart::bodyPart(weak_ref <vmime::bodyPart> parentPart)
- }
- 
- 
--void bodyPart::parse(const string& buffer, const string::size_type position,
--	const string::size_type end, string::size_type* newPosition)
-+void bodyPart::parseImpl
-+	(ref <utility::parserInputStreamAdapter> parser,
-+	 const utility::stream::size_type position,
-+	 const utility::stream::size_type end,
-+	 utility::stream::size_type* newPosition)
- {
- 	// Parse the headers
- 	string::size_type pos = position;
--	m_header->parse(buffer, pos, end, &pos);
-+	m_header->parse(parser, pos, end, &pos);
- 
- 	// Parse the body contents
--	m_body->parse(buffer, pos, end, NULL);
-+	m_body->parse(parser, pos, end, NULL);
- 
- 	setParsedBounds(position, end);
- 
-@@ -63,7 +66,7 @@ void bodyPart::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void bodyPart::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void bodyPart::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type /* curLinePos */, string::size_type* newLinePos) const
- {
- 	m_header->generate(os, maxLineLength);
-@@ -142,9 +145,9 @@ ref <const bodyPart> bodyPart::getParentPart() const
- }
- 
- 
--const std::vector <ref <const component> > bodyPart::getChildComponents() const
-+const std::vector <ref <component> > bodyPart::getChildComponents()
- {
--	std::vector <ref <const component> > list;
-+	std::vector <ref <component> > list;
- 
- 	list.push_back(m_header);
- 	list.push_back(m_body);
-diff --git a/src/charset.cpp b/src/charset.cpp
-index 0fda450..705664f 100644
---- a/src/charset.cpp
-+++ b/src/charset.cpp
-@@ -57,7 +57,7 @@ charset::charset(const char* name)
- }
- 
- 
--void charset::parse(const string& buffer, const string::size_type position,
-+void charset::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	m_name = utility::stringUtils::trim
-@@ -74,7 +74,7 @@ void charset::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void charset::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
-+void charset::generateImpl(utility::outputStream& os, const string::size_type /* maxLineLength */,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	os << m_name;
-@@ -142,9 +142,9 @@ void charset::copyFrom(const component& other)
- }
- 
- 
--const std::vector <ref <const component> > charset::getChildComponents() const
-+const std::vector <ref <component> > charset::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/src/component.cpp b/src/component.cpp
-index 139cf66..e93aacf 100644
---- a/src/component.cpp
-+++ b/src/component.cpp
-@@ -23,6 +23,9 @@
- 
- #include "vmime/component.hpp"
- #include "vmime/base.hpp"
-+
-+#include "vmime/utility/streamUtils.hpp"
-+#include "vmime/utility/inputStreamStringAdapter.hpp"
- #include "vmime/utility/outputStreamAdapter.hpp"
- 
- #include <sstream>
-@@ -43,9 +46,102 @@ component::~component()
- }
- 
- 
-+void component::parse
-+	(ref <utility::inputStream> inputStream, const utility::stream::size_type length)
-+{
-+	parse(inputStream, 0, length, NULL);
-+}
-+
-+
-+void component::parse
-+	(ref <utility::inputStream> inputStream, const utility::stream::size_type position,
-+	 const utility::stream::size_type end, utility::stream::size_type* newPosition)
-+{
-+	m_parsedOffset = m_parsedLength = 0;
-+
-+	ref <utility::seekableInputStream> seekableStream =
-+		inputStream.dynamicCast <utility::seekableInputStream>();
-+
-+	if (seekableStream == NULL || end == 0)
-+	{
-+		// Read the whole stream into a buffer
-+		std::ostringstream oss;
-+		utility::outputStreamAdapter ossAdapter(oss);
-+
-+		utility::bufferedStreamCopyRange(*inputStream, ossAdapter, position, end - position);
-+
-+		const string buffer = oss.str();
-+		parseImpl(buffer, 0, buffer.length(), NULL);
-+	}
-+	else
-+	{
-+		ref <utility::parserInputStreamAdapter> parser =
-+			vmime::create <utility::parserInputStreamAdapter>(seekableStream);
-+
-+		parseImpl(parser, position, end, newPosition);
-+	}
-+}
-+
-+
- void component::parse(const string& buffer)
- {
--	parse(buffer, 0, buffer.length(), NULL);
-+	m_parsedOffset = m_parsedLength = 0;
-+
-+	parseImpl(buffer, 0, buffer.length(), NULL);
-+}
-+
-+
-+void component::parse
-+	(const string& buffer, const string::size_type position,
-+	 const string::size_type end, string::size_type* newPosition)
-+{
-+	m_parsedOffset = m_parsedLength = 0;
-+
-+	parseImpl(buffer, position, end, newPosition);
-+}
-+
-+
-+void component::offsetParsedBounds(const utility::stream::size_type offset)
-+{
-+	// Offset parsed bounds of this component
-+	if (m_parsedLength != 0)
-+		m_parsedOffset += offset;
-+
-+	// Offset parsed bounds of our children
-+	std::vector <ref <component> > children = getChildComponents();
-+
-+	for (unsigned int i = 0, n = children.size() ; i < n ; ++i)
-+		children[i]->offsetParsedBounds(offset);
-+}
-+
-+
-+void component::parseImpl
-+	(ref <utility::parserInputStreamAdapter> parser, const utility::stream::size_type position,
-+	 const utility::stream::size_type end, utility::stream::size_type* newPosition)
-+{
-+	const std::string buffer = parser->extract(position, end);
-+	parseImpl(buffer, 0, buffer.length(), newPosition);
-+
-+	// Recursivey offset parsed bounds on children
-+	if (position != 0)
-+		offsetParsedBounds(position);
-+
-+	if (newPosition != NULL)
-+		*newPosition += position;
-+}
-+
-+
-+void component::parseImpl
-+	(const string& buffer, const string::size_type position,
-+	 const string::size_type end, string::size_type* newPosition)
-+{
-+	ref <utility::seekableInputStream> stream =
-+		vmime::create <utility::inputStreamStringAdapter>(buffer);
-+
-+	ref <utility::parserInputStreamAdapter> parser =
-+		vmime::create <utility::parserInputStreamAdapter>(stream);
-+
-+	parseImpl(parser, position, end, newPosition);
- }
- 
- 
-@@ -61,6 +157,26 @@ const string component::generate(const string::size_type maxLineLength,
- }
- 
- 
-+void component::generate
-+	(utility::outputStream& os,
-+	 const string::size_type maxLineLength,
-+	 const string::size_type curLinePos,
-+	 string::size_type* newLinePos) const
-+{
-+	generateImpl(os, maxLineLength, curLinePos, newLinePos);
-+}
-+
-+
-+void component::generate
-+	(ref <utility::outputStream> os,
-+	 const string::size_type maxLineLength,
-+	 const string::size_type curLinePos,
-+	 string::size_type* newLinePos) const
-+{
-+	generateImpl(*os, maxLineLength, curLinePos, newLinePos);
-+}
-+
-+
- string::size_type component::getParsedOffset() const
- {
- 	return (m_parsedOffset);
-@@ -80,22 +196,5 @@ void component::setParsedBounds(const string::size_type start, const string::siz
- }
- 
- 
--const std::vector <ref <component> > component::getChildComponents()
--{
--	const std::vector <ref <const component> > constList =
--		const_cast <const component*>(this)->getChildComponents();
--
--	std::vector <ref <component> > list;
--
--	const std::vector <ref <const component> >::size_type count = constList.size();
-+} // vmime
- 
--	list.resize(count);
--
--	for (std::vector <ref <const component> >::size_type i = 0 ; i < count ; ++i)
--		list[i] = constList[i].constCast <component>();
--
--	return (list);
--}
--
--
--}
-diff --git a/src/contentDisposition.cpp b/src/contentDisposition.cpp
-index 0ab7c45..253dbba 100644
---- a/src/contentDisposition.cpp
-+++ b/src/contentDisposition.cpp
-@@ -47,7 +47,7 @@ contentDisposition::contentDisposition(const contentDisposition& type)
- }
- 
- 
--void contentDisposition::parse(const string& buffer, const string::size_type position,
-+void contentDisposition::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	m_name = utility::stringUtils::trim(utility::stringUtils::toLower
-@@ -60,7 +60,7 @@ void contentDisposition::parse(const string& buffer, const string::size_type pos
- }
- 
- 
--void contentDisposition::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
-+void contentDisposition::generateImpl(utility::outputStream& os, const string::size_type /* maxLineLength */,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	os << m_name;
-@@ -122,9 +122,9 @@ void contentDisposition::setName(const string& name)
- }
- 
- 
--const std::vector <ref <const component> > contentDisposition::getChildComponents() const
-+const std::vector <ref <component> > contentDisposition::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/src/dateTime.cpp b/src/dateTime.cpp
-index 089a900..0d97b2f 100644
---- a/src/dateTime.cpp
-+++ b/src/dateTime.cpp
-@@ -67,7 +67,7 @@ zone = "UT" / "GMT"                               ; Universal Time
- */
- 
- 
--void datetime::parse(const string& buffer, const string::size_type position,
-+void datetime::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	const string::value_type* const pend = buffer.data() + end;
-@@ -588,7 +588,7 @@ void datetime::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void datetime::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
-+void datetime::generateImpl(utility::outputStream& os, const string::size_type /* maxLineLength */,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	static const string::value_type* dayNames[] =
-@@ -784,9 +784,9 @@ ref <component> datetime::clone() const
- }
- 
- 
--const std::vector <ref <const component> > datetime::getChildComponents() const
-+const std::vector <ref <component> > datetime::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/src/disposition.cpp b/src/disposition.cpp
-index b8059a7..24a4579 100644
---- a/src/disposition.cpp
-+++ b/src/disposition.cpp
-@@ -79,9 +79,9 @@ disposition& disposition::operator=(const disposition& other)
- }
- 
- 
--const std::vector <ref <const component> > disposition::getChildComponents() const
-+const std::vector <ref <component> > disposition::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-@@ -171,7 +171,7 @@ const std::vector <string> disposition::getModifierList() const
- }
- 
- 
--void disposition::parse(const string& buffer, const string::size_type position,
-+void disposition::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	// disposition-mode ";" disposition-type
-@@ -276,7 +276,7 @@ void disposition::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void disposition::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void disposition::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	string::size_type pos = curLinePos;
-diff --git a/src/encoding.cpp b/src/encoding.cpp
-index 5d99ab6..343a822 100644
---- a/src/encoding.cpp
-+++ b/src/encoding.cpp
-@@ -61,7 +61,7 @@ encoding::encoding(const encoding& enc)
- }
- 
- 
--void encoding::parse(const string& buffer, const string::size_type position,
-+void encoding::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	m_usage = USAGE_UNKNOWN;
-@@ -80,7 +80,7 @@ void encoding::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void encoding::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
-+void encoding::generateImpl(utility::outputStream& os, const string::size_type /* maxLineLength */,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	os << m_name;
-@@ -268,9 +268,9 @@ void encoding::setUsage(const EncodingUsage usage)
- }
- 
- 
--const std::vector <ref <const component> > encoding::getChildComponents() const
-+const std::vector <ref <component> > encoding::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/src/header.cpp b/src/header.cpp
-index 443aab8..fcdca2c 100644
---- a/src/header.cpp
-+++ b/src/header.cpp
-@@ -61,7 +61,7 @@ field-body-contents =
- 		 specials tokens, or else consisting of texts>
- */
- 
--void header::parse(const string& buffer, const string::size_type position,
-+void header::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	string::size_type pos = position;
-@@ -83,7 +83,7 @@ void header::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void header::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void header::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type /* curLinePos */, string::size_type* newLinePos) const
- {
- 	// Generate the fields
-@@ -337,9 +337,9 @@ const std::vector <ref <headerField> > header::getFieldList()
- }
- 
- 
--const std::vector <ref <const component> > header::getChildComponents() const
-+const std::vector <ref <component> > header::getChildComponents()
- {
--	std::vector <ref <const component> > list;
-+	std::vector <ref <component> > list;
- 
- 	copy_vector(m_fields, list);
- 
-diff --git a/src/headerField.cpp b/src/headerField.cpp
-index d1d4236..a8460aa 100644
---- a/src/headerField.cpp
-+++ b/src/headerField.cpp
-@@ -262,14 +262,14 @@ 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,
-+void headerField::parseImpl(const string& buffer, const string::size_type position, const string::size_type end,
- 	string::size_type* newPosition)
- {
- 	m_value->parse(buffer, position, end, newPosition);
- }
- 
- 
--void headerField::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void headerField::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	os << m_name + ": ";
-@@ -296,9 +296,9 @@ bool headerField::isCustom() const
- }
- 
- 
--const std::vector <ref <const component> > headerField::getChildComponents() const
-+const std::vector <ref <component> > headerField::getChildComponents()
- {
--	std::vector <ref <const component> > list;
-+	std::vector <ref <component> > list;
- 
- 	if (m_value)
- 		list.push_back(m_value);
-diff --git a/src/mailbox.cpp b/src/mailbox.cpp
-index fea7479..dfdccad 100644
---- a/src/mailbox.cpp
-+++ b/src/mailbox.cpp
-@@ -65,7 +65,7 @@ angle-addr      =       [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
- 
- */
- 
--void mailbox::parse(const string& buffer, const string::size_type position,
-+void mailbox::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	const string::value_type* const pend = buffer.data() + end;
-@@ -343,7 +343,7 @@ void mailbox::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void mailbox::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void mailbox::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	if (m_name.isEmpty())
-@@ -514,9 +514,9 @@ void mailbox::setEmail(const string& email)
- }
- 
- 
--const std::vector <ref <const component> > mailbox::getChildComponents() const
-+const std::vector <ref <component> > mailbox::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/src/mailboxGroup.cpp b/src/mailboxGroup.cpp
-index 94f7ba6..c37444a 100644
---- a/src/mailboxGroup.cpp
-+++ b/src/mailboxGroup.cpp
-@@ -54,7 +54,7 @@ mailboxGroup::~mailboxGroup()
- }
- 
- 
--void mailboxGroup::parse(const string& buffer, const string::size_type position,
-+void mailboxGroup::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	const string::value_type* const pend = buffer.data() + end;
-@@ -111,7 +111,7 @@ void mailboxGroup::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void mailboxGroup::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void mailboxGroup::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	// We have to encode the name:
-@@ -348,9 +348,9 @@ const std::vector <ref <mailbox> > mailboxGroup::getMailboxList()
- }
- 
- 
--const std::vector <ref <const component> > mailboxGroup::getChildComponents() const
-+const std::vector <ref <component> > mailboxGroup::getChildComponents()
- {
--	std::vector <ref <const component> > list;
-+	std::vector <ref <component> > list;
- 
- 	copy_vector(m_list, list);
- 
-diff --git a/src/mailboxList.cpp b/src/mailboxList.cpp
-index 0023d9d..f87fb48 100644
---- a/src/mailboxList.cpp
-+++ b/src/mailboxList.cpp
-@@ -190,20 +190,20 @@ mailboxList& mailboxList::operator=(const mailboxList& other)
- }
- 
- 
--const std::vector <ref <const component> > mailboxList::getChildComponents() const
-+const std::vector <ref <component> > mailboxList::getChildComponents()
- {
- 	return (m_list.getChildComponents());
- }
- 
- 
--void mailboxList::parse(const string& buffer, const string::size_type position,
-+void mailboxList::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	m_list.parse(buffer, position, end, newPosition);
- }
- 
- 
--void mailboxList::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void mailboxList::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	m_list.generate(os, maxLineLength, curLinePos, newLinePos);
-diff --git a/src/mediaType.cpp b/src/mediaType.cpp
-index 725f933..627b276 100644
---- a/src/mediaType.cpp
-+++ b/src/mediaType.cpp
-@@ -48,7 +48,7 @@ mediaType::mediaType(const string& type, const string& subType)
- }
- 
- 
--void mediaType::parse(const string& buffer, const string::size_type position,
-+void mediaType::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	const string::value_type* const pend = buffer.data() + end;
-@@ -82,7 +82,7 @@ void mediaType::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void mediaType::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void mediaType::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	const string value = m_type + "/" + m_subType;
-@@ -176,9 +176,9 @@ void mediaType::setFromString(const string& type)
- }
- 
- 
--const std::vector <ref <const component> > mediaType::getChildComponents() const
-+const std::vector <ref <component> > mediaType::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/src/message.cpp b/src/message.cpp
-index 1b4f086..3fa9b6a 100644
---- a/src/message.cpp
-+++ b/src/message.cpp
-@@ -61,9 +61,14 @@ const string message::generate(const string::size_type maxLineLength,
- }
- 
- 
--void message::parse(const string& buffer)
-+
-+void message::generate
-+	(ref <utility::outputStream> os,
-+	 const string::size_type maxLineLength,
-+	 const string::size_type curLinePos,
-+	 string::size_type* newLinePos) const
- {
--	bodyPart::parse(buffer);
-+	bodyPart::generate(os, maxLineLength, curLinePos, newLinePos);
- }
- 
- 
-diff --git a/src/messageId.cpp b/src/messageId.cpp
-index 961fb63..1f4b186 100644
---- a/src/messageId.cpp
-+++ b/src/messageId.cpp
-@@ -61,7 +61,7 @@ messageId::messageId(const string& left, const string& right)
- 	msg-id          =       [CFWS] "<" id-left "@" id-right ">" [CFWS]
- */
- 
--void messageId::parse(const string& buffer, const string::size_type position,
-+void messageId::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	const string::value_type* const pend = buffer.data() + end;
-@@ -185,7 +185,7 @@ const string messageId::getId() const
- }
- 
- 
--void messageId::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void messageId::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	string::size_type pos = curLinePos;
-@@ -288,9 +288,9 @@ void messageId::setRight(const string& right)
- }
- 
- 
--const std::vector <ref <const component> > messageId::getChildComponents() const
-+const std::vector <ref <component> > messageId::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/src/messageIdSequence.cpp b/src/messageIdSequence.cpp
-index 08103d0..0a5c9a0 100644
---- a/src/messageIdSequence.cpp
-+++ b/src/messageIdSequence.cpp
-@@ -74,9 +74,9 @@ messageIdSequence& messageIdSequence::operator=(const messageIdSequence& other)
- }
- 
- 
--const std::vector <ref <const component> > messageIdSequence::getChildComponents() const
-+const std::vector <ref <component> > messageIdSequence::getChildComponents()
- {
--	std::vector <ref <const component> > res;
-+	std::vector <ref <component> > res;
- 
- 	copy_vector(m_list, res);
- 
-@@ -84,7 +84,7 @@ const std::vector <ref <const component> > messageIdSequence::getChildComponents
- }
- 
- 
--void messageIdSequence::parse(const string& buffer, const string::size_type position,
-+void messageIdSequence::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	removeAllMessageIds();
-@@ -106,7 +106,7 @@ void messageIdSequence::parse(const string& buffer, const string::size_type posi
- }
- 
- 
--void messageIdSequence::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void messageIdSequence::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	string::size_type pos = curLinePos;
-diff --git a/src/parameter.cpp b/src/parameter.cpp
-index ccbe1a5..58d9a3e 100644
---- a/src/parameter.cpp
-+++ b/src/parameter.cpp
-@@ -36,19 +36,19 @@ namespace vmime
- 
- 
- parameter::parameter(const string& name)
--	: m_name(name)
-+	: m_name(name), m_value(vmime::create <word>())
- {
- }
- 
- 
- parameter::parameter(const string& name, const word& value)
--	: m_name(name), m_value(value)
-+	: m_name(name), m_value(vmime::create <word>(value))
- {
- }
- 
- 
- parameter::parameter(const string& name, const string& value)
--	: m_name(name), m_value(value)
-+	: m_name(name), m_value(vmime::create <word>(value))
- {
- }
- 
-@@ -73,7 +73,7 @@ void parameter::copyFrom(const component& other)
- 	const parameter& param = dynamic_cast <const parameter&>(other);
- 
- 	m_name = param.m_name;
--	m_value.copyFrom(param.m_value);
-+	m_value->copyFrom(*param.m_value);
- }
- 
- 
-@@ -92,7 +92,7 @@ const string& parameter::getName() const
- 
- const word& parameter::getValue() const
- {
--	return m_value;
-+	return *m_value;
- }
- 
- 
-@@ -109,15 +109,15 @@ void parameter::setValue(const component& value)
- 
- void parameter::setValue(const word& value)
- {
--	m_value = value;
-+	*m_value = value;
- }
- 
- 
--void parameter::parse(const string& buffer, const string::size_type position,
-+void parameter::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
--	m_value.setBuffer(string(buffer.begin() + position, buffer.begin() + end));
--	m_value.setCharset(charset(charsets::US_ASCII));
-+	m_value->setBuffer(string(buffer.begin() + position, buffer.begin() + end));
-+	m_value->setCharset(charset(charsets::US_ASCII));
- 
- 	if (newPosition)
- 		*newPosition = end;
-@@ -248,16 +248,16 @@ void parameter::parse(const std::vector <valueChunk>& chunks)
- 		}
- 	}
- 
--	m_value.setBuffer(value.str());
--	m_value.setCharset(ch);
-+	m_value->setBuffer(value.str());
-+	m_value->setCharset(ch);
- }
- 
- 
--void parameter::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void parameter::generateImpl(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();
-+	const string& value = m_value->getBuffer();
- 
- 	// For compatibility with implementations that do not understand RFC-2231,
- 	// also generate a normal "7bit/us-ascii" parameter
-@@ -344,7 +344,7 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 	// 7-bit (ASCII) bytes in the input will be used to determine if
- 	// we need to encode the whole buffer.
- 	encoding recommendedEnc;
--	const bool alwaysEncode = m_value.getCharset().getRecommendedEncoding(recommendedEnc);
-+	const bool alwaysEncode = m_value->getCharset().getRecommendedEncoding(recommendedEnc);
- 	bool extended = alwaysEncode;
- 
- 	if (needQuotedPrintable)
-@@ -352,7 +352,7 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 		// Send the name in quoted-printable, so outlook express et.al.
- 		// will understand the real filename
- 		size_t oldLen = sevenBitBuffer.length();
--		m_value.generate(sevenBitStream);
-+		m_value->generate(sevenBitStream);
- 		pos += sevenBitBuffer.length() - oldLen;
- 		extended = true;		// also send with RFC-2231 encoding
- 	}
-@@ -429,7 +429,7 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 		// + at least 5 characters for the value
- 		const string::size_type firstSectionLength =
- 			  name.length() + 4 /* *0*= */ + 2 /* '' */
--			+ m_value.getCharset().getName().length();
-+			+ m_value->getCharset().getName().length();
- 
- 		if (pos + firstSectionLength + 5 >= maxLineLength)
- 		{
-@@ -539,7 +539,7 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- 
- 			if (sectionNumber == 0)
- 			{
--				os << m_value.getCharset().getName();
-+				os << m_value->getCharset().getName();
- 				os << '\'' << /* No language */ '\'';
- 			}
- 
-@@ -570,11 +570,11 @@ void parameter::generate(utility::outputStream& os, const string::size_type maxL
- }
- 
- 
--const std::vector <ref <const component> > parameter::getChildComponents() const
-+const std::vector <ref <component> > parameter::getChildComponents()
- {
--	std::vector <ref <const component> > list;
-+	std::vector <ref <component> > list;
- 
--	list.push_back(ref <const component>::fromPtr(&m_value));
-+	list.push_back(m_value);
- 
- 	return list;
- }
-diff --git a/src/parameterizedHeaderField.cpp b/src/parameterizedHeaderField.cpp
-index 464990e..756d02f 100644
---- a/src/parameterizedHeaderField.cpp
-+++ b/src/parameterizedHeaderField.cpp
-@@ -78,7 +78,7 @@ struct paramInfo
- #endif // VMIME_BUILDING_DOC
- 
- 
--void parameterizedHeaderField::parse(const string& buffer, const string::size_type position,
-+void parameterizedHeaderField::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	const string::value_type* const pend = buffer.data() + end;
-@@ -328,13 +328,13 @@ void parameterizedHeaderField::parse(const string& buffer, const string::size_ty
- }
- 
- 
--void parameterizedHeaderField::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void parameterizedHeaderField::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	string::size_type pos = curLinePos;
- 
- 	// Parent header field
--	headerField::generate(os, maxLineLength, pos, &pos);
-+	headerField::generateImpl(os, maxLineLength, pos, &pos);
- 
- 	// Parameters
- 	for (std::vector <ref <parameter> >::const_iterator
-@@ -552,11 +552,11 @@ const std::vector <ref <parameter> > parameterizedHeaderField::getParameterList(
- }
- 
- 
--const std::vector <ref <const component> > parameterizedHeaderField::getChildComponents() const
-+const std::vector <ref <component> > parameterizedHeaderField::getChildComponents()
- {
--	std::vector <ref <const component> > list = headerField::getChildComponents();
-+	std::vector <ref <component> > list = headerField::getChildComponents();
- 
--	for (std::vector <ref <parameter> >::const_iterator it = m_params.begin() ;
-+	for (std::vector <ref <parameter> >::iterator it = m_params.begin() ;
- 	     it != m_params.end() ; ++it)
- 	{
- 		list.push_back(*it);
-diff --git a/src/path.cpp b/src/path.cpp
-index 37a4090..d92bb0a 100644
---- a/src/path.cpp
-+++ b/src/path.cpp
-@@ -106,14 +106,14 @@ path& path::operator=(const path& other)
- }
- 
- 
--const std::vector <ref <const component> > path::getChildComponents() const
-+const std::vector <ref <component> > path::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
--void path::parse(const string& buffer, const string::size_type position,
--                 const string::size_type end, string::size_type* newPosition)
-+void path::parseImpl(const string& buffer, const string::size_type position,
-+	const string::size_type end, string::size_type* newPosition)
- {
- 	string::size_type pos = position;
- 
-@@ -165,8 +165,8 @@ void path::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void path::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
--                    const string::size_type curLinePos, string::size_type* newLinePos) const
-+void path::generateImpl(utility::outputStream& os, const string::size_type /* maxLineLength */,
-+	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	if (m_localPart.empty() && m_domain.empty())
- 	{
-diff --git a/src/platforms/posix/posixFile.cpp b/src/platforms/posix/posixFile.cpp
-index ec529eb..4087a21 100644
---- a/src/platforms/posix/posixFile.cpp
-+++ b/src/platforms/posix/posixFile.cpp
-@@ -224,6 +224,26 @@ vmime::utility::stream::size_type posixFileReaderInputStream::skip(const size_ty
- }
- 
- 
-+vmime::utility::stream::size_type posixFileReaderInputStream::getPosition() const
-+{
-+	const off_t curPos = ::lseek(m_fd, 0, SEEK_CUR);
-+
-+	if (curPos == off_t(-1))
-+		posixFileSystemFactory::reportError(m_path, errno);
-+
-+	return static_cast <size_type>(curPos);
-+}
-+
-+
-+void posixFileReaderInputStream::seek(const size_type pos)
-+{
-+	const off_t newPos = ::lseek(m_fd, pos, SEEK_SET);
-+
-+	if (newPos == off_t(-1))
-+		posixFileSystemFactory::reportError(m_path, errno);
-+}
-+
-+
- 
- //
- // posixFileWriter
-diff --git a/src/platforms/windows/windowsFile.cpp b/src/platforms/windows/windowsFile.cpp
-index 624612a..5da786e 100644
---- a/src/platforms/windows/windowsFile.cpp
-+++ b/src/platforms/windows/windowsFile.cpp
-@@ -479,6 +479,24 @@ vmime::utility::stream::size_type windowsFileReaderInputStream::skip(const size_
- 	return (dwNewPos - dwCurPos);
- }
- 
-+vmime::utility::stream::size_type windowsFileReaderInputStream::getPosition() const
-+{
-+	DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
-+
-+	if (dwCurPos == INVALID_SET_FILE_POINTER)
-+		windowsFileSystemFactory::reportError(m_path, GetLastError());
-+
-+	return static_cast <size_type>(dwCurPos);
-+}
-+
-+void windowsFileReaderInputStream::seek(const size_type pos)
-+{
-+	DWORD dwNewPos = SetFilePointer(m_hFile, (LONG)pos, NULL, FILE_BEGIN);
-+
-+	if (dwNewPos == INVALID_SET_FILE_POINTER)
-+		windowsFileSystemFactory::reportError(m_path, GetLastError());
-+}
-+
- windowsFileWriter::windowsFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath)
- : m_path(path), m_nativePath(nativePath)
- {
-diff --git a/src/relay.cpp b/src/relay.cpp
-index 5cd454f..97f793d 100644
---- a/src/relay.cpp
-+++ b/src/relay.cpp
-@@ -57,7 +57,7 @@ relay::relay(const relay& r)
-                        ["for"  addr-spec]        ; initial form
- */
- 
--void relay::parse(const string& buffer, const string::size_type position,
-+void relay::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	const string::value_type* const pend = buffer.data() + end;
-@@ -198,7 +198,7 @@ void relay::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void relay::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void relay::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	std::ostringstream oss;
-@@ -338,10 +338,10 @@ std::vector <string>& relay::getWithList()
- }
- 
- 
--const std::vector <ref <const component> > relay::getChildComponents() const
-+const std::vector <ref <component> > relay::getChildComponents()
- {
- 	// TODO: should fields inherit from 'component'? (using typeAdapter)
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/src/streamContentHandler.cpp b/src/streamContentHandler.cpp
-index 89a36b4..14837d2 100644
---- a/src/streamContentHandler.cpp
-+++ b/src/streamContentHandler.cpp
-@@ -25,6 +25,7 @@
- 
- #include "vmime/utility/outputStreamAdapter.hpp"
- #include "vmime/utility/inputStreamStringAdapter.hpp"
-+#include "vmime/utility/seekableInputStream.hpp"
- #include "vmime/utility/streamUtils.hpp"
- 
- 
-@@ -207,6 +208,9 @@ const vmime::encoding& streamContentHandler::getEncoding() const
- 
- bool streamContentHandler::isBuffered() const
- {
-+	if (m_stream.dynamicCast <utility::seekableInputStream>() != NULL)
-+		return true;
-+
- 	// FIXME: some streams can be resetted
- 	return false;
- }
-diff --git a/src/text.cpp b/src/text.cpp
-index 66c3b35..91b81e1 100644
---- a/src/text.cpp
-+++ b/src/text.cpp
-@@ -67,7 +67,7 @@ text::~text()
- }
- 
- 
--void text::parse(const string& buffer, const string::size_type position,
-+void text::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	removeAllWords();
-@@ -85,7 +85,7 @@ void text::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void text::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void text::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	encodeAndFold(os, maxLineLength, curLinePos, newLinePos, 0);
-@@ -389,9 +389,9 @@ text* text::decodeAndUnfold(const string& in, text* generateInExisting)
- }
- 
- 
--const std::vector <ref <const component> > text::getChildComponents() const
-+const std::vector <ref <component> > text::getChildComponents()
- {
--	std::vector <ref <const component> > list;
-+	std::vector <ref <component> > list;
- 
- 	copy_vector(m_words, list);
- 
-diff --git a/src/utility/inputStreamAdapter.cpp b/src/utility/inputStreamAdapter.cpp
-index b44b084..441307b 100644
---- a/src/utility/inputStreamAdapter.cpp
-+++ b/src/utility/inputStreamAdapter.cpp
-@@ -65,6 +65,18 @@ stream::size_type inputStreamAdapter::skip(const size_type count)
- }
- 
- 
-+stream::size_type inputStreamAdapter::getPosition() const
-+{
-+	return m_stream.tellg();
-+}
-+
-+
-+void inputStreamAdapter::seek(const size_type pos)
-+{
-+	m_stream.seekg(pos, std::ios_base::beg);
-+}
-+
-+
- } // utility
- } // vmime
- 
-diff --git a/src/utility/inputStreamByteBufferAdapter.cpp b/src/utility/inputStreamByteBufferAdapter.cpp
-index 92e779f..907f1ee 100644
---- a/src/utility/inputStreamByteBufferAdapter.cpp
-+++ b/src/utility/inputStreamByteBufferAdapter.cpp
-@@ -85,6 +85,19 @@ stream::size_type inputStreamByteBufferAdapter::skip(const size_type count)
- }
- 
- 
-+stream::size_type inputStreamByteBufferAdapter::getPosition() const
-+{
-+	return m_pos;
-+}
-+
-+
-+void inputStreamByteBufferAdapter::seek(const size_type pos)
-+{
-+	if (pos <= m_length)
-+		m_pos = pos;
-+}
-+
-+
- } // utility
- } // vmime
- 
-diff --git a/src/utility/inputStreamStringAdapter.cpp b/src/utility/inputStreamStringAdapter.cpp
-index 31c9fda..9b8fb0c 100644
---- a/src/utility/inputStreamStringAdapter.cpp
-+++ b/src/utility/inputStreamStringAdapter.cpp
-@@ -89,6 +89,19 @@ stream::size_type inputStreamStringAdapter::skip(const size_type count)
- }
- 
- 
-+stream::size_type inputStreamStringAdapter::getPosition() const
-+{
-+	return m_pos - m_begin;
-+}
-+
-+
-+void inputStreamStringAdapter::seek(const size_type pos)
-+{
-+	if (m_begin + pos <= m_end)
-+		m_pos = m_begin + pos;
-+}
-+
-+
- } // utility
- } // vmime
- 
-diff --git a/src/utility/inputStreamStringProxyAdapter.cpp b/src/utility/inputStreamStringProxyAdapter.cpp
-index 5e4b60b..feecddd 100644
---- a/src/utility/inputStreamStringProxyAdapter.cpp
-+++ b/src/utility/inputStreamStringProxyAdapter.cpp
-@@ -84,6 +84,19 @@ stream::size_type inputStreamStringProxyAdapter::skip(const size_type count)
- }
- 
- 
-+stream::size_type inputStreamStringProxyAdapter::getPosition() const
-+{
-+	return m_pos;
-+}
-+
-+
-+void inputStreamStringProxyAdapter::seek(const size_type pos)
-+{
-+	if (pos <= m_buffer.length())
-+		m_pos = pos;
-+}
-+
-+
- } // utility
- } // vmime
- 
-diff --git a/src/utility/parserInputStreamAdapter.cpp b/src/utility/parserInputStreamAdapter.cpp
-new file mode 100644
-index 0000000..7a38ef1
---- /dev/null
-+++ b/src/utility/parserInputStreamAdapter.cpp
-@@ -0,0 +1,162 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/parserInputStreamAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+parserInputStreamAdapter::parserInputStreamAdapter(ref <seekableInputStream> stream)
-+	: m_stream(stream)
-+{
-+}
-+
-+
-+bool parserInputStreamAdapter::eof() const
-+{
-+	return m_stream->eof();
-+}
-+
-+
-+void parserInputStreamAdapter::reset()
-+{
-+	m_stream->reset();
-+}
-+
-+
-+stream::size_type parserInputStreamAdapter::read
-+	(value_type* const data, const size_type count)
-+{
-+	return m_stream->read(data, count);
-+}
-+
-+
-+ref <seekableInputStream> parserInputStreamAdapter::getUnderlyingStream()
-+{
-+	return m_stream;
-+}
-+
-+
-+const string parserInputStreamAdapter::extract(const size_type begin, const size_type end) const
-+{
-+	const size_type initialPos = m_stream->getPosition();
-+
-+	try
-+	{
-+		value_type *buffer = new value_type[end - begin + 1];
-+
-+		m_stream->seek(begin);
-+
-+		const size_type readBytes = m_stream->read(buffer, end - begin);
-+		buffer[readBytes] = '\0';
-+
-+		m_stream->seek(initialPos);
-+
-+		string str(buffer, buffer + readBytes);
-+		delete [] buffer;
-+
-+		return str;
-+	}
-+	catch (...)
-+	{
-+		m_stream->seek(initialPos);
-+		throw;
-+	}
-+}
-+
-+
-+stream::size_type parserInputStreamAdapter::findNext
-+	(const std::string& token, const size_type startPosition)
-+{
-+	static const unsigned int BUFFER_SIZE = 4096;
-+
-+	// Token must not be longer than BUFFER_SIZE/2
-+	if (token.empty() || token.length() > BUFFER_SIZE / 2)
-+		return npos;
-+
-+	const size_type initialPos = getPosition();
-+
-+	seek(startPosition);
-+
-+	try
-+	{
-+		value_type findBuffer[BUFFER_SIZE];
-+		value_type* findBuffer1 = findBuffer;
-+		value_type* findBuffer2 = findBuffer + (BUFFER_SIZE / 2) * sizeof(value_type);
-+
-+		size_type findBufferLen = 0;
-+		size_type findBufferOffset = 0;
-+
-+		// Fill in initial buffer
-+		findBufferLen = read(findBuffer, BUFFER_SIZE * sizeof(value_type));
-+
-+		for (;;)
-+		{
-+			// Find token
-+			for (value_type *begin = findBuffer, *end = findBuffer + findBufferLen - token.length() ;
-+			     begin <= end ; ++begin)
-+			{
-+				if (begin[0] == token[0] &&
-+				    (token.length() == 1 ||
-+				     memcmp(static_cast <const void *>(&begin[1]),
-+				            static_cast <const void *>(token.data() + 1),
-+				            token.length() - 1) == 0))
-+				{
-+					seek(initialPos);
-+					return startPosition + findBufferOffset + (begin - findBuffer);
-+				}
-+			}
-+
-+			// Rotate buffer
-+			memcpy(findBuffer1, findBuffer2, (BUFFER_SIZE / 2) * sizeof(value_type));
-+
-+			// Read more bytes
-+			if (findBufferLen < BUFFER_SIZE && eof())
-+			{
-+				break;
-+			}
-+			else
-+			{
-+				const size_type bytesRead = read(findBuffer2, (BUFFER_SIZE / 2) * sizeof(value_type));
-+				findBufferLen = (BUFFER_SIZE / 2) + bytesRead;
-+				findBufferOffset += (BUFFER_SIZE / 2);
-+			}
-+		}
-+
-+		seek(initialPos);
-+	}
-+	catch (...)
-+	{
-+		seek(initialPos);
-+		throw;
-+	}
-+
-+	return npos;
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/seekableInputStreamRegionAdapter.cpp b/src/utility/seekableInputStreamRegionAdapter.cpp
-new file mode 100644
-index 0000000..348618c
---- /dev/null
-+++ b/src/utility/seekableInputStreamRegionAdapter.cpp
-@@ -0,0 +1,95 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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/utility/seekableInputStreamRegionAdapter.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+seekableInputStreamRegionAdapter::seekableInputStreamRegionAdapter
-+	(ref <seekableInputStream> stream, const size_type begin, const size_type length)
-+	: m_stream(stream), m_begin(begin), m_length(length)
-+{
-+}
-+
-+
-+bool seekableInputStreamRegionAdapter::eof() const
-+{
-+	return getPosition() >= m_length;
-+}
-+
-+
-+void seekableInputStreamRegionAdapter::reset()
-+{
-+	m_stream->seek(m_begin);
-+}
-+
-+
-+stream::size_type seekableInputStreamRegionAdapter::read
-+	(value_type* const data, const size_type count)
-+{
-+	if (getPosition() + count >= m_length)
-+	{
-+		const size_type remaining = m_length - getPosition();
-+		return m_stream->read(data, remaining);
-+	}
-+	else
-+	{
-+		return m_stream->read(data, count);
-+	}
-+}
-+
-+
-+stream::size_type seekableInputStreamRegionAdapter::skip(const size_type count)
-+{
-+	if (getPosition() + count >= m_length)
-+	{
-+		const size_type remaining = m_length - getPosition();
-+		m_stream->skip(remaining);
-+		return remaining;
-+	}
-+	else
-+	{
-+		m_stream->skip(count);
-+		return count;
-+	}
-+}
-+
-+
-+stream::size_type seekableInputStreamRegionAdapter::getPosition() const
-+{
-+	return m_stream->getPosition() - m_begin;
-+}
-+
-+
-+void seekableInputStreamRegionAdapter::seek(const size_type pos)
-+{
-+	m_stream->seek(m_begin + pos);
-+}
-+
-+
-+} // utility
-+} // vmime
-+
-diff --git a/src/utility/stream.cpp b/src/utility/stream.cpp
-index 1c940c2..67c1f33 100644
---- a/src/utility/stream.cpp
-+++ b/src/utility/stream.cpp
-@@ -29,6 +29,9 @@ namespace vmime {
- namespace utility {
- 
- 
-+const stream::size_type stream::npos = static_cast <size_type>(vmime::string::npos);
-+
-+
- stream::size_type stream::getBlockSize()
- {
- 	return 32768;  // 32 KB
-@@ -37,3 +40,4 @@ stream::size_type stream::getBlockSize()
- 
- } // utility
- } // vmime
-+
-diff --git a/src/utility/streamUtils.cpp b/src/utility/streamUtils.cpp
-index f1d3b9d..f7ea62f 100644
---- a/src/utility/streamUtils.cpp
-+++ b/src/utility/streamUtils.cpp
-@@ -52,6 +52,35 @@ stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os)
- }
- 
- 
-+stream::size_type bufferedStreamCopyRange(inputStream& is, outputStream& os,
-+	const stream::size_type start, const stream::size_type length)
-+{
-+	const stream::size_type blockSize =
-+		std::min(is.getBlockSize(), os.getBlockSize());
-+
-+	is.skip(start);
-+
-+	std::vector <stream::value_type> vbuffer(blockSize);
-+
-+	stream::value_type* buffer = &vbuffer.front();
-+	stream::size_type total = 0;
-+
-+	while (!is.eof() && total < length)
-+	{
-+		const stream::size_type remaining = std::min(length - total, blockSize);
-+		const stream::size_type read = is.read(buffer, blockSize);
-+
-+		if (read != 0)
-+		{
-+			os.write(buffer, read);
-+			total += read;
-+		}
-+	}
-+
-+	return total;
-+}
-+
-+
- stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os,
- 	const stream::size_type length, progressListener* progress)
- {
-diff --git a/src/word.cpp b/src/word.cpp
-index 79060a1..2876ddf 100644
---- a/src/word.cpp
-+++ b/src/word.cpp
-@@ -241,7 +241,7 @@ const std::vector <ref <word> > word::parseMultiple(const string& buffer, const
- }
- 
- 
--void word::parse(const string& buffer, const string::size_type position,
-+void word::parseImpl(const string& buffer, const string::size_type position,
- 	const string::size_type end, string::size_type* newPosition)
- {
- 	if (position + 6 < end && // 6 = "=?(.+)?(.*)?="
-@@ -324,7 +324,7 @@ void word::parse(const string& buffer, const string::size_type position,
- }
- 
- 
--void word::generate(utility::outputStream& os, const string::size_type maxLineLength,
-+void word::generateImpl(utility::outputStream& os, const string::size_type maxLineLength,
- 	const string::size_type curLinePos, string::size_type* newLinePos) const
- {
- 	generate(os, maxLineLength, curLinePos, newLinePos, 0, NULL);
-@@ -743,9 +743,9 @@ void word::setBuffer(const string& buffer)
- }
- 
- 
--const std::vector <ref <const component> > word::getChildComponents() const
-+const std::vector <ref <component> > word::getChildComponents()
- {
--	return std::vector <ref <const component> >();
-+	return std::vector <ref <component> >();
- }
- 
- 
-diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp
-index 9d51262..deb4b9c 100644
---- a/tests/parser/bodyPartTest.cpp
-+++ b/tests/parser/bodyPartTest.cpp
-@@ -33,12 +33,14 @@ VMIME_TEST_SUITE_BEGIN
- 	VMIME_TEST_LIST_BEGIN
- 		VMIME_TEST(testParse)
- 		VMIME_TEST(testGenerate)
-+		VMIME_TEST(testParseGuessBoundary)
- 		VMIME_TEST(testParseMissingLastBoundary)
- 		VMIME_TEST(testPrologEpilog)
- 		VMIME_TEST(testPrologEncoding)
- 		VMIME_TEST(testSuccessiveBoundaries)
- 		VMIME_TEST(testGenerate7bit)
- 		VMIME_TEST(testTextUsageForQPEncoding)
-+		VMIME_TEST(testParseVeryBigMessage)
- 	VMIME_TEST_LIST_END
- 
- 
-@@ -237,6 +239,93 @@ VMIME_TEST_SUITE_BEGIN
- 		VASSERT_EQ("2", "Part1-line1\r\nPart1-line2\r\n=89", oss.str());
- 	}
- 
-+	void testParseGuessBoundary()
-+	{
-+		// Boundary is not specified in "Content-Type" field
-+		// Parser will try to guess it from message contents.
-+
-+		vmime::string str =
-+			"Content-Type: multipart/mixed"
-+			"\r\n\r\n"
-+			"--UNKNOWN-BOUNDARY\r\nHEADER1\r\n\r\nBODY1\r\n"
-+			"--UNKNOWN-BOUNDARY\r\nHEADER2\r\n\r\nBODY2\r\n"
-+			"--UNKNOWN-BOUNDARY--";
-+
-+		vmime::bodyPart p;
-+		p.parse(str);
-+
-+		VASSERT_EQ("count", 2, p.getBody()->getPartCount());
-+
-+		VASSERT_EQ("part1-body", "BODY1", extractContents(p.getBody()->getPartAt(0)->getBody()->getContents()));
-+		VASSERT_EQ("part2-body", "BODY2", extractContents(p.getBody()->getPartAt(1)->getBody()->getContents()));
-+	}
-+
-+	void testParseVeryBigMessage()
-+	{
-+		// When parsing from a seekable input stream, body contents should not
-+		// be kept in memory in a "stringContentHandler" object. Instead, content
-+		// should be accessible via a "streamContentHandler" object.
-+
-+		static const std::string BODY1_BEGIN = "BEGIN1BEGIN1BEGIN1";
-+		static const std::string BODY1_LINE = "BODY1BODY1BODY1BODY1BODY1BODY1BODY1BODY1BODY1BODY1BODY1BODY1BODY1";
-+		static const std::string BODY1_END = "END1END1";
-+		static const unsigned int BODY1_REPEAT = 35000;
-+		static const unsigned int BODY1_LENGTH =
-+			BODY1_BEGIN.length() + BODY1_LINE.length() * BODY1_REPEAT + BODY1_END.length();
-+
-+		static const std::string BODY2_LINE = "BODY2BODY2BODY2BODY2BODY2BODY2BODY2BODY2BODY2BODY2BODY2BODY2BODY2";
-+		static const unsigned int BODY2_REPEAT = 20000;
-+
-+		std::ostringstream oss;
-+		oss << "Content-Type: multipart/mixed; boundary=\"MY-BOUNDARY\""
-+		    << "\r\n\r\n"
-+		    << "--MY-BOUNDARY\r\n"
-+		    << "HEADER1\r\n"
-+		    << "\r\n";
-+
-+		oss << BODY1_BEGIN;
-+
-+		for (unsigned int i = 0 ; i < BODY1_REPEAT ; ++i)
-+			oss << BODY1_LINE;
-+
-+		oss << BODY1_END;
-+
-+		oss << "\r\n"
-+		    << "--MY-BOUNDARY\r\n"
-+		    << "HEADER2\r\n"
-+		    << "\r\n";
-+
-+		for (unsigned int i = 0 ; i < BODY2_REPEAT ; ++i)
-+			oss << BODY2_LINE;
-+
-+		oss << "\r\n"
-+		    << "--MY-BOUNDARY--\r\n";
-+
-+		vmime::ref <vmime::utility::inputStreamStringAdapter> is =
-+			vmime::create <vmime::utility::inputStreamStringAdapter>(oss.str());
-+
-+		vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
-+		msg->parse(is, oss.str().length());
-+
-+		vmime::ref <vmime::body> body1 = msg->getBody()->getPartAt(0)->getBody();
-+		vmime::ref <const vmime::contentHandler> body1Cts = body1->getContents();
-+
-+		vmime::ref <vmime::body> body2 = msg->getBody()->getPartAt(1)->getBody();
-+		vmime::ref <const vmime::contentHandler> body2Cts = body2->getContents();
-+
-+		vmime::string body1CtsExtracted;
-+		vmime::utility::outputStreamStringAdapter body1CtsExtractStream(body1CtsExtracted);
-+		body1Cts->extract(body1CtsExtractStream);
-+
-+		VASSERT_EQ("1.1", BODY1_LENGTH, body1Cts->getLength());
-+		VASSERT("1.2", body1Cts.dynamicCast <const vmime::streamContentHandler>() != NULL);
-+		VASSERT_EQ("1.3", BODY1_LENGTH, body1CtsExtracted.length());
-+		VASSERT_EQ("1.4", BODY1_BEGIN, body1CtsExtracted.substr(0, BODY1_BEGIN.length()));
-+		VASSERT_EQ("1.5", BODY1_END, body1CtsExtracted.substr(BODY1_LENGTH - BODY1_END.length(), BODY1_END.length()));
-+
-+		VASSERT_EQ("2.1", BODY2_LINE.length() * BODY2_REPEAT, body2Cts->getLength());
-+		VASSERT("2.2", body2Cts.dynamicCast <const vmime::streamContentHandler>() != NULL);
-+	}
- 
- VMIME_TEST_SUITE_END
- 
-diff --git a/vmime/addressList.hpp b/vmime/addressList.hpp
-index 2e537c0..9dc283c 100644
---- a/vmime/addressList.hpp
-+++ b/vmime/addressList.hpp
-@@ -56,7 +56,7 @@ public:
- 	addressList& operator=(const addressList& other);
- 	addressList& operator=(const mailboxList& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 
- 	/** Add a address at the end of the list.
-@@ -163,14 +163,20 @@ private:
- 
- 	std::vector <ref <address> > m_list;
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/body.hpp b/vmime/body.hpp
-index 9e83d6b..bd5bbb9 100644
---- a/vmime/body.hpp
-+++ b/vmime/body.hpp
-@@ -278,7 +278,7 @@ public:
- 	void copyFrom(const component& other);
- 	body& operator=(const body& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- private:
- 
-@@ -299,14 +299,20 @@ private:
- 
- 	void initNewPart(ref <bodyPart> part);
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(ref <utility::parserInputStreamAdapter> parser,
-+		 const utility::stream::size_type position,
-+		 const utility::stream::size_type end,
-+		 utility::stream::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/bodyPart.hpp b/vmime/bodyPart.hpp
-index aa0f040..5f36d90 100644
---- a/vmime/bodyPart.hpp
-+++ b/vmime/bodyPart.hpp
-@@ -89,7 +89,7 @@ public:
- 	void copyFrom(const component& other);
- 	bodyPart& operator=(const bodyPart& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- private:
- 
-@@ -98,14 +98,20 @@ private:
- 
- 	weak_ref <bodyPart> m_parent;
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(ref <utility::parserInputStreamAdapter> parser,
-+		 const utility::stream::size_type position,
-+		 const utility::stream::size_type end,
-+		 utility::stream::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/charset.hpp b/vmime/charset.hpp
-index 5f5e8e5..26abb4f 100644
---- a/vmime/charset.hpp
-+++ b/vmime/charset.hpp
-@@ -62,7 +62,7 @@ public:
- 	bool operator==(const charset& value) const;
- 	bool operator!=(const charset& value) const;
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	/** Gets the recommended encoding for this charset.
- 	  * Note: there may be no recommended encoding.
-@@ -117,14 +117,20 @@ private:
- 
- 	string m_name;
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/component.hpp b/vmime/component.hpp
-index 12b0406..5e6f393 100644
---- a/vmime/component.hpp
-+++ b/vmime/component.hpp
-@@ -27,6 +27,8 @@
- 
- #include "vmime/base.hpp"
- #include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/seekableInputStream.hpp"
-+#include "vmime/utility/parserInputStreamAdapter.hpp"
- #include "vmime/utility/outputStream.hpp"
- 
- 
-@@ -51,6 +53,12 @@ public:
- 	  */
- 	void parse(const string& buffer);
- 
-+	/** Parse RFC-822/MIME data for this component. If stream is not seekable,
-+	  * or if length is not specified, entire contents of the stream will
-+	  * be loaded into memory before parsing.
-+	  */
-+	void parse(ref <utility::inputStream> inputStream, const utility::stream::size_type length);
-+
- 	/** Parse RFC-822/MIME data for this component.
- 	  *
- 	  * @param buffer input buffer
-@@ -58,7 +66,26 @@ public:
- 	  * @param end end position in the input buffer
- 	  * @param newPosition will receive the new position in the input buffer
- 	  */
--	virtual void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL) = 0;
-+	void parse
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	/** Parse RFC-822/MIME data for this component. If stream is not seekable,
-+	  * or if end position is not specified, entire contents of the stream will
-+	  * be loaded into memory before parsing.
-+	  *
-+	  * @param inputStream stream from which to read data
-+	  * @param position current position in the input stream
-+	  * @param end end position in the input stream
-+	  * @param newPosition will receive the new position in the input stream
-+	  */
-+	void parse
-+		(ref <utility::inputStream> inputStream,
-+		 const utility::stream::size_type position,
-+		 const utility::stream::size_type end,
-+		 utility::stream::size_type* newPosition = NULL);
- 
- 	/** Generate RFC-2822/MIME data for this component.
- 	  *
-@@ -68,16 +95,35 @@ public:
- 	  * @param curLinePos length of the current line in the output buffer
- 	  * @return generated data
- 	  */
--	const string generate(const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0) const;
-+	virtual const string generate
-+		(const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0) const;
- 
- 	/** Generate RFC-2822/MIME data for this component.
- 	  *
--	  * @param os output stream
-+	  * @param outputStream output stream
- 	  * @param maxLineLength maximum line length for output
- 	  * @param curLinePos length of the current line in the output buffer
- 	  * @param newLinePos will receive the new line position (length of the last line written)
- 	  */
--	virtual void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const = 0;
-+	virtual void generate
-+		(utility::outputStream& outputStream,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
-+
-+	/** Generate RFC-2822/MIME data for this component.
-+	  *
-+	  * @param outputStream output stream
-+	  * @param maxLineLength maximum line length for output
-+	  * @param curLinePos length of the current line in the output buffer
-+	  * @param newLinePos will receive the new line position (length of the last line written)
-+	  */
-+	virtual void generate
-+		(ref <utility::outputStream> outputStream,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- 
- 	/** Clone this component.
- 	  *
-@@ -95,41 +141,56 @@ public:
- 	virtual void copyFrom(const component& other) = 0;
- 
- 	/** Return the start position of this component in the
--	  * parsed message contents.
-+	  * parsed message contents. Use for debugging only.
- 	  *
- 	  * @return start position in parsed buffer
- 	  * or 0 if this component has not been parsed
- 	  */
--	string::size_type getParsedOffset() const;
-+	utility::stream::size_type getParsedOffset() const;
- 
- 	/** Return the length of this component in the
--	  * parsed message contents.
-+	  * parsed message contents. Use for debugging only.
- 	  *
- 	  * @return length of the component in parsed buffer
- 	  * or 0 if this component has not been parsed
- 	  */
--	string::size_type getParsedLength() const;
-+	utility::stream::size_type getParsedLength() const;
- 
- 	/** Return the list of children of this component.
- 	  *
- 	  * @return list of child components
- 	  */
--	const std::vector <ref <component> > getChildComponents();
--
--	/** Return the list of children of this component (const version).
--	  *
--	  * @return list of child components
--	  */
--	virtual const std::vector <ref <const component> > getChildComponents() const = 0;
-+	virtual const std::vector <ref <component> > getChildComponents() = 0;
- 
- protected:
- 
--	void setParsedBounds(const string::size_type start, const string::size_type end);
-+	void setParsedBounds(const utility::stream::size_type start, const utility::stream::size_type end);
-+
-+	// AT LEAST ONE of these parseImpl() functions MUST be implemented in derived class
-+	virtual void parseImpl
-+		(ref <utility::parserInputStreamAdapter> parser,
-+		 const utility::stream::size_type position,
-+		 const utility::stream::size_type end,
-+		 utility::stream::size_type* newPosition = NULL);
-+
-+	virtual void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	virtual void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const = 0;
- 
- private:
- 
--	string::size_type m_parsedOffset;
--	string::size_type m_parsedLength;
-+	void offsetParsedBounds(const utility::stream::size_type offset);
-+
-+	utility::stream::size_type m_parsedOffset;
-+	utility::stream::size_type m_parsedLength;
- };
- 
- 
-diff --git a/vmime/contentDisposition.hpp b/vmime/contentDisposition.hpp
-index 9d1749b..abd2e1a 100644
---- a/vmime/contentDisposition.hpp
-+++ b/vmime/contentDisposition.hpp
-@@ -63,7 +63,7 @@ public:
- 	void copyFrom(const component& other);
- 	contentDisposition& operator=(const contentDisposition& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 
- 	contentDisposition& operator=(const string& name);
-@@ -75,14 +75,20 @@ private:
- 
- 	string m_name;
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/dateTime.hpp b/vmime/dateTime.hpp
-index 8e99640..053f4a6 100644
---- a/vmime/dateTime.hpp
-+++ b/vmime/dateTime.hpp
-@@ -237,16 +237,22 @@ public:
- 	// Current date and time
- 	static const datetime now();
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/disposition.hpp b/vmime/disposition.hpp
-index 05bfca2..7bdc832 100644
---- a/vmime/disposition.hpp
-+++ b/vmime/disposition.hpp
-@@ -50,7 +50,7 @@ public:
- 	void copyFrom(const component& other);
- 	disposition& operator=(const disposition& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 
- 	/** Set the disposition action mode.
-@@ -134,14 +134,20 @@ private:
- 
- 	std::vector <string> m_modifiers;
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/encoding.hpp b/vmime/encoding.hpp
-index 42f5246..4322b29 100644
---- a/vmime/encoding.hpp
-+++ b/vmime/encoding.hpp
-@@ -93,7 +93,7 @@ public:
- 	bool operator==(const encoding& value) const;
- 	bool operator!=(const encoding& value) const;
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	/** Decide which encoding to use based on the specified data.
- 	  *
-@@ -141,14 +141,20 @@ private:
- 	  */
- 	static const encoding decideImpl(const string::const_iterator begin, const string::const_iterator end);
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/header.hpp b/vmime/header.hpp
-index 95a9326..ed555b0 100644
---- a/vmime/header.hpp
-+++ b/vmime/header.hpp
-@@ -220,7 +220,7 @@ public:
- 	void copyFrom(const component& other);
- 	header& operator=(const header& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- private:
- 
-@@ -251,14 +251,20 @@ private:
- 		string m_name;
- 	};
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/headerField.hpp b/vmime/headerField.hpp
-index 50494c9..61e01ee 100644
---- a/vmime/headerField.hpp
-+++ b/vmime/headerField.hpp
-@@ -59,7 +59,7 @@ public:
- 	void copyFrom(const component& other);
- 	headerField& operator=(const headerField& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	/** Sets the name of this field.
- 	  *
-@@ -118,15 +118,26 @@ public:
- 	void setValue(const string& value);
- 
- 
--	using component::parse;
--	using component::generate;
-+protected:
- 
--	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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- 
--protected:
- 
--	static ref <headerField> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
-+	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;
-diff --git a/vmime/mailbox.hpp b/vmime/mailbox.hpp
-index 2072be8..2099355 100644
---- a/vmime/mailbox.hpp
-+++ b/vmime/mailbox.hpp
-@@ -85,7 +85,7 @@ public:
- 
- 	void clear();
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 
- 	bool isGroup() const;
-@@ -101,8 +101,17 @@ public:
- 	using address::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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/mailboxGroup.hpp b/vmime/mailboxGroup.hpp
-index 0061d5b..1433141 100644
---- a/vmime/mailboxGroup.hpp
-+++ b/vmime/mailboxGroup.hpp
-@@ -52,7 +52,7 @@ public:
- 	ref <component> clone() const;
- 	mailboxGroup& operator=(const component& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	/** Return the name of the group.
- 	  *
-@@ -165,14 +165,20 @@ private:
- 	text m_name;
- 	std::vector <ref <mailbox> > m_list;
- 
--public:
--
--	using address::parse;
--	using address::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/mailboxList.hpp b/vmime/mailboxList.hpp
-index 11e4e79..1b480c1 100644
---- a/vmime/mailboxList.hpp
-+++ b/vmime/mailboxList.hpp
-@@ -51,7 +51,7 @@ public:
- 	void copyFrom(const component& other);
- 	mailboxList& operator=(const mailboxList& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	/** Add a mailbox at the end of the list.
- 	  *
-@@ -155,14 +155,20 @@ private:
- 
- 	addressList m_list;
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/mediaType.hpp b/vmime/mediaType.hpp
-index 658b21f..18182f0 100644
---- a/vmime/mediaType.hpp
-+++ b/vmime/mediaType.hpp
-@@ -55,7 +55,7 @@ public:
- 	void copyFrom(const component& other);
- 	mediaType& operator=(const mediaType& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	/** Return the media type.
- 	  * See the constants in vmime::mediaTypes.
-@@ -97,14 +97,18 @@ protected:
- 	string m_type;
- 	string m_subType;
- 
--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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/message.hpp b/vmime/message.hpp
-index f3be229..9767564 100644
---- a/vmime/message.hpp
-+++ b/vmime/message.hpp
-@@ -43,12 +43,25 @@ public:
- 	message();
- 
- 
--	// Component parsing & assembling
--	void generate(utility::outputStream& os, const string::size_type maxLineLength = options::getInstance()->message.maxLineLength(), const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
--
--	const string generate(const string::size_type maxLineLength = options::getInstance()->message.maxLineLength(), const string::size_type curLinePos = 0) const;
-+public:
- 
--	void parse(const string& buffer);
-+	// Override default generate() functions so that we can change
-+	// the default 'maxLineLength' value
-+	void generate
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = options::getInstance()->message.maxLineLength(),
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
-+
-+	const string generate
-+		(const string::size_type maxLineLength = options::getInstance()->message.maxLineLength(),
-+		 const string::size_type curLinePos = 0) const;
-+
-+	void generate
-+		(ref <utility::outputStream> os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/messageId.hpp b/vmime/messageId.hpp
-index 3686b11..ac408e6 100644
---- a/vmime/messageId.hpp
-+++ b/vmime/messageId.hpp
-@@ -97,23 +97,27 @@ public:
- 	void copyFrom(const component& other);
- 	messageId& operator=(const messageId& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- private:
- 
- 	string m_left;
- 	string m_right;
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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:
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- 
- 	/** Parse a message-id from an input buffer.
- 	  *
-@@ -123,7 +127,11 @@ protected:
- 	  * @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 ref <messageId> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition);
-+	static ref <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
-index 5dfb840..6736d0a 100644
---- a/vmime/messageIdSequence.hpp
-+++ b/vmime/messageIdSequence.hpp
-@@ -49,7 +49,7 @@ public:
- 	void copyFrom(const component& other);
- 	messageIdSequence& operator=(const messageIdSequence& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 
- 	/** Add a message-id at the end of the list.
-@@ -148,14 +148,20 @@ private:
- 
- 	std::vector <ref <messageId> > m_list;
- 
--public:
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/parameter.hpp b/vmime/parameter.hpp
-index e1b13a1..0773ea6 100644
---- a/vmime/parameter.hpp
-+++ b/vmime/parameter.hpp
-@@ -67,7 +67,7 @@ public:
- 	void copyFrom(const component& other);
- 	parameter& operator=(const parameter& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	/** Return the name of this parameter.
- 	  *
-@@ -104,7 +104,7 @@ public:
- 	const T getValueAs() const
- 	{
- 		T ret;
--		ret.parse(m_value.getBuffer());
-+		ret.parse(m_value->getBuffer());
- 
- 		return ret;
- 	}
-@@ -122,11 +122,19 @@ public:
- 	void setValue(const word& value);
- 
- 
--	using component::parse;
--	using component::generate;
-+protected:
- 
--	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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- 
- private:
- 
-@@ -134,7 +142,7 @@ private:
- 
- 
- 	string m_name;
--	word m_value;
-+	ref <word> m_value;
- };
- 
- 
-diff --git a/vmime/parameterizedHeaderField.hpp b/vmime/parameterizedHeaderField.hpp
-index 2940ca3..d2c934f 100644
---- a/vmime/parameterizedHeaderField.hpp
-+++ b/vmime/parameterizedHeaderField.hpp
-@@ -172,19 +172,25 @@ public:
- 	  */
- 	const std::vector <ref <parameter> > getParameterList();
- 
-+	const std::vector <ref <component> > getChildComponents();
-+
- private:
- 
- 	std::vector <ref <parameter> > m_params;
- 
--public:
--
--	using headerField::parse;
--	using headerField::generate;
--
--	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:
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/parserHelpers.hpp b/vmime/parserHelpers.hpp
-index 9b075f7..d4f1246 100644
---- a/vmime/parserHelpers.hpp
-+++ b/vmime/parserHelpers.hpp
-@@ -45,6 +45,10 @@ public:
- 		return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
- 	}
- 
-+	static bool isSpaceOrTab(const char_t c)
-+	{
-+		return (c == ' ' || c == '\t');
-+	}
- 
- 	static bool isDigit(const char_t c)
- 	{
-diff --git a/vmime/path.hpp b/vmime/path.hpp
-index beaa72b..eec8dfc 100644
---- a/vmime/path.hpp
-+++ b/vmime/path.hpp
-@@ -76,21 +76,26 @@ public:
- 	ref <component> clone() const;
- 	path& operator=(const path& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- protected:
- 
- 	string m_localPart;
- 	string m_domain;
- 
--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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/platforms/posix/posixFile.hpp b/vmime/platforms/posix/posixFile.hpp
-index 70986df..704b7b0 100644
---- a/vmime/platforms/posix/posixFile.hpp
-+++ b/vmime/platforms/posix/posixFile.hpp
-@@ -26,6 +26,7 @@
- 
- 
- #include "vmime/utility/file.hpp"
-+#include "vmime/utility/seekableInputStream.hpp"
- 
- 
- #if VMIME_HAVE_FILESYSTEM_FEATURES
-@@ -57,7 +58,7 @@ private:
- 
- 
- 
--class posixFileReaderInputStream : public vmime::utility::inputStream
-+class posixFileReaderInputStream : public vmime::utility::seekableInputStream
- {
- public:
- 
-@@ -72,6 +73,9 @@ public:
- 
- 	size_type skip(const size_type count);
- 
-+	size_type getPosition() const;
-+	void seek(const size_type pos);
-+
- private:
- 
- 	const vmime::utility::file::path m_path;
-diff --git a/vmime/platforms/windows/windowsFile.hpp b/vmime/platforms/windows/windowsFile.hpp
-index 6e1c8fb..f417032 100644
---- a/vmime/platforms/windows/windowsFile.hpp
-+++ b/vmime/platforms/windows/windowsFile.hpp
-@@ -26,6 +26,7 @@
- 
- 
- #include "vmime/utility/file.hpp"
-+#include "vmime/utility/seekableInputStream.hpp"
- 
- #include <windows.h>
- 
-@@ -157,6 +158,8 @@ public:
- 	void reset();
- 	size_type read(value_type* const data, const size_type count);
- 	size_type skip(const size_type count);
-+	size_type getPosition() const;
-+	void seek(const size_type pos);
- 
- private:
- 
-diff --git a/vmime/relay.hpp b/vmime/relay.hpp
-index 583ad80..dbaedf2 100644
---- a/vmime/relay.hpp
-+++ b/vmime/relay.hpp
-@@ -51,7 +51,7 @@ public:
- 	void copyFrom(const component& other);
- 	relay& operator=(const relay& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	const string& getFrom() const;
- 	void setFrom(const string& from);
-@@ -85,13 +85,19 @@ private:
- 
- 	datetime m_date;
- 
--public:
-+protected:
- 
--	using component::parse;
--	using component::generate;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
- 
--	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;
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- };
- 
- 
-diff --git a/vmime/text.hpp b/vmime/text.hpp
-index 15e11ae..778ce86 100644
---- a/vmime/text.hpp
-+++ b/vmime/text.hpp
-@@ -58,7 +58,7 @@ public:
- 	text& operator=(const component& other);
- 	text& operator=(const text& other);
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+	const std::vector <ref <component> > getChildComponents();
- 
- 	/** Add a word at the end of the list.
- 	  *
-@@ -226,13 +226,20 @@ public:
- 	  */
- 	static text* decodeAndUnfold(const string& in, text* generateInExisting);
- 
--
--	using component::parse;
--	using component::generate;
-+protected:
- 
- 	// 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;
-+	void parseImpl
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition = NULL);
-+
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- 
- private:
- 
-diff --git a/vmime/utility/inputStreamAdapter.hpp b/vmime/utility/inputStreamAdapter.hpp
-index 278ab52..bd4d21e 100644
---- a/vmime/utility/inputStreamAdapter.hpp
-+++ b/vmime/utility/inputStreamAdapter.hpp
-@@ -25,7 +25,7 @@
- #define VMIME_UTILITY_INPUTSTREAMADAPTER_HPP_INCLUDED
- 
- 
--#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/seekableInputStream.hpp"
- 
- #include <istream>
- 
-@@ -37,7 +37,7 @@ namespace utility {
- /** An adapter class for C++ standard input streams.
-   */
- 
--class inputStreamAdapter : public inputStream
-+class inputStreamAdapter : public seekableInputStream
- {
- public:
- 
-@@ -49,6 +49,8 @@ public:
- 	void reset();
- 	size_type read(value_type* const data, const size_type count);
- 	size_type skip(const size_type count);
-+	size_type getPosition() const;
-+	void seek(const size_type pos);
- 
- private:
- 
-diff --git a/vmime/utility/inputStreamByteBufferAdapter.hpp b/vmime/utility/inputStreamByteBufferAdapter.hpp
-index 0f6a442..b3dafd9 100644
---- a/vmime/utility/inputStreamByteBufferAdapter.hpp
-+++ b/vmime/utility/inputStreamByteBufferAdapter.hpp
-@@ -25,7 +25,7 @@
- #define VMIME_UTILITY_INPUTSTREAMBYTEBUFFERADAPTER_HPP_INCLUDED
- 
- 
--#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/seekableInputStream.hpp"
- 
- 
- namespace vmime {
-@@ -35,7 +35,7 @@ namespace utility {
- /** An adapter class for reading from an array of bytes.
-   */
- 
--class inputStreamByteBufferAdapter : public inputStream
-+class inputStreamByteBufferAdapter : public seekableInputStream
- {
- public:
- 
-@@ -45,6 +45,8 @@ public:
- 	void reset();
- 	size_type read(value_type* const data, const size_type count);
- 	size_type skip(const size_type count);
-+	size_type getPosition() const;
-+	void seek(const size_type pos);
- 
- private:
- 
-diff --git a/vmime/utility/inputStreamStringAdapter.hpp b/vmime/utility/inputStreamStringAdapter.hpp
-index a7d986f..18a9083 100644
---- a/vmime/utility/inputStreamStringAdapter.hpp
-+++ b/vmime/utility/inputStreamStringAdapter.hpp
-@@ -25,7 +25,7 @@
- #define VMIME_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED
- 
- 
--#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/seekableInputStream.hpp"
- 
- 
- namespace vmime {
-@@ -35,7 +35,7 @@ namespace utility {
- /** An adapter class for string input.
-   */
- 
--class inputStreamStringAdapter : public inputStream
-+class inputStreamStringAdapter : public seekableInputStream
- {
- public:
- 
-@@ -46,6 +46,8 @@ public:
- 	void reset();
- 	size_type read(value_type* const data, const size_type count);
- 	size_type skip(const size_type count);
-+	size_type getPosition() const;
-+	void seek(const size_type pos);
- 
- private:
- 
-diff --git a/vmime/utility/inputStreamStringProxyAdapter.hpp b/vmime/utility/inputStreamStringProxyAdapter.hpp
-index 74b3f60..dc52637 100644
---- a/vmime/utility/inputStreamStringProxyAdapter.hpp
-+++ b/vmime/utility/inputStreamStringProxyAdapter.hpp
-@@ -25,7 +25,7 @@
- #define VMIME_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED
- 
- 
--#include "vmime/utility/inputStream.hpp"
-+#include "vmime/utility/seekableInputStream.hpp"
- 
- 
- namespace vmime {
-@@ -38,7 +38,7 @@ class stringProxy;
- /** An adapter class for stringProxy input.
-   */
- 
--class inputStreamStringProxyAdapter : public inputStream
-+class inputStreamStringProxyAdapter : public seekableInputStream
- {
- public:
- 
-@@ -50,6 +50,8 @@ public:
- 	void reset();
- 	size_type read(value_type* const data, const size_type count);
- 	size_type skip(const size_type count);
-+	size_type getPosition() const;
-+	void seek(const size_type pos);
- 
- private:
- 
-diff --git a/vmime/utility/parserInputStreamAdapter.hpp b/vmime/utility/parserInputStreamAdapter.hpp
-new file mode 100644
-index 0000000..c24fa44
---- /dev/null
-+++ b/vmime/utility/parserInputStreamAdapter.hpp
-@@ -0,0 +1,173 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/seekableInputStream.hpp"
-+
-+#include <cstring>
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter class used for parsing from an input stream.
-+  */
-+
-+class parserInputStreamAdapter : public seekableInputStream
-+{
-+public:
-+
-+	/** @param is input stream to wrap
-+	  */
-+	parserInputStreamAdapter(ref <seekableInputStream> inputStream);
-+
-+	ref <seekableInputStream> getUnderlyingStream();
-+
-+	bool eof() const;
-+	void reset();
-+	size_type read(value_type* const data, const size_type count);
-+
-+	void seek(const size_type pos)
-+	{
-+		m_stream->seek(pos);
-+	}
-+
-+	size_type skip(const size_type count)
-+	{
-+		return m_stream->skip(count);
-+	}
-+
-+	size_type getPosition() const
-+	{
-+		return m_stream->getPosition();
-+	}
-+
-+	/** Get the byte at the current position without updating the
-+	  * current position.
-+	  *
-+	  * @return byte at the current position
-+	  */
-+	value_type peekByte() const
-+	{
-+		const size_type initialPos = m_stream->getPosition();
-+
-+		try
-+		{
-+			value_type buffer[1];
-+			const size_type readBytes = m_stream->read(buffer, 1);
-+
-+			m_stream->seek(initialPos);
-+
-+			return (readBytes == 1 ? buffer[0] : 0);
-+		}
-+		catch (...)
-+		{
-+			m_stream->seek(initialPos);
-+			throw;
-+		}
-+	}
-+
-+	/** Get the byte at the current position and advance current
-+	  * position by one byte.
-+	  *
-+	  * @return byte at the current position
-+	  */
-+	value_type getByte()
-+	{
-+		value_type buffer[1];
-+		const size_type readBytes = m_stream->read(buffer, 1);
-+
-+		return (readBytes == 1 ? buffer[0] : 0);
-+	}
-+
-+	/** Check whether the bytes following the current position match
-+	  * the specified bytes. Position is not updated.
-+	  *
-+	  * @param bytes bytes to compare
-+	  * @param length number of bytes
-+	  * @return true if the next bytes match the pattern, false otherwise
-+	  */
-+	bool matchBytes(const value_type* bytes, const size_type length) const
-+	{
-+		const size_type initialPos = m_stream->getPosition();
-+
-+		try
-+		{
-+			value_type buffer[32];
-+			const size_type readBytes = m_stream->read(buffer, length);
-+
-+			m_stream->seek(initialPos);
-+
-+			return readBytes == length &&
-+			       ::memcmp(bytes, buffer, length) == 0;
-+		}
-+		catch (...)
-+		{
-+			m_stream->seek(initialPos);
-+			throw;
-+		}
-+	}
-+
-+	const string extract(const size_type begin, const size_type end) const;
-+
-+	/** Skips bytes matching a predicate from the current position.
-+	  * The current position is updated to the next following byte
-+	  * which does not match the predicate.
-+	  *
-+	  * @param pred predicate
-+	  * @param endPosition stop at this position (or at end of the stream,
-+	  * whichever comes first)
-+	  * @return number of bytes skipped
-+	  */
-+	template <typename PREDICATE>
-+	size_type skipIf(PREDICATE pred, const size_type endPosition)
-+	{
-+		const size_type initialPos = getPosition();
-+		size_type pos = initialPos;
-+
-+		while (!m_stream->eof() && pos < endPosition && pred(getByte()))
-+			++pos;
-+
-+		m_stream->seek(pos);
-+
-+		return pos - initialPos;
-+	}
-+
-+	size_type findNext(const std::string& token, const size_type startPosition = 0);
-+
-+private:
-+
-+	mutable ref <seekableInputStream> m_stream;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/seekableInputStream.hpp b/vmime/utility/seekableInputStream.hpp
-new file mode 100644
-index 0000000..c2ab1bb
---- /dev/null
-+++ b/vmime/utility/seekableInputStream.hpp
-@@ -0,0 +1,64 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_SEEKABLEINPUTSTREAM_HPP_INCLUDED
-+#define VMIME_UTILITY_SEEKABLEINPUTSTREAM_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/inputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An input stream that allows seeking within the input.
-+  */
-+
-+class seekableInputStream : public inputStream
-+{
-+public:
-+
-+	/** Returns the current position in this stream.
-+	  *
-+	  * @return the offset from the beginning of the stream, in bytes,
-+	  * at which the next read occurs
-+	  */
-+	virtual size_type getPosition() const = 0;
-+
-+	/** Sets the position, measured from the beginning of this stream,
-+	  * at which the next read occurs.
-+	  *
-+	  * @param pos the offset position, measured in bytes from the
-+	  * beginning of the stream, at which to set the stream pointer.
-+	  */
-+	virtual void seek(const size_type pos) = 0;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_SEEKABLEINPUTSTREAM_HPP_INCLUDED
-+
-diff --git a/vmime/utility/seekableInputStreamRegionAdapter.hpp b/vmime/utility/seekableInputStreamRegionAdapter.hpp
-new file mode 100644
-index 0000000..5ebccc6
---- /dev/null
-+++ b/vmime/utility/seekableInputStreamRegionAdapter.hpp
-@@ -0,0 +1,71 @@
-+//
-+// VMime library (http://www.vmime.org)
-+// Copyright (C) 2002-2012 Vincent Richard <vincent@vincent-richard.net>
-+//
-+// 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 3 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_UTILITY_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED
-+#define VMIME_UTILITY_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED
-+
-+
-+#include "vmime/utility/seekableInputStream.hpp"
-+
-+
-+namespace vmime {
-+namespace utility {
-+
-+
-+/** An adapter for reading a limited region of a seekable input stream.
-+  */
-+
-+class seekableInputStreamRegionAdapter : public seekableInputStream
-+{
-+public:
-+
-+	/** Creates a new adapter for a seekableInputStream.
-+	  *
-+	  * @param stream source stream
-+	  * @param begin start position in source stream
-+	  * @param length region length in source stream
-+	  */
-+	seekableInputStreamRegionAdapter(ref <seekableInputStream> stream,
-+		const size_type begin, const size_type length);
-+
-+	bool eof() const;
-+	void reset();
-+	size_type read(value_type* const data, const size_type count);
-+	size_type skip(const size_type count);
-+	size_type getPosition() const;
-+	void seek(const size_type pos);
-+
-+private:
-+
-+	ref <seekableInputStream> m_stream;
-+	size_type m_begin;
-+	size_type m_length;
-+};
-+
-+
-+} // utility
-+} // vmime
-+
-+
-+#endif // VMIME_UTILITY_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED
-+
-diff --git a/vmime/utility/stream.hpp b/vmime/utility/stream.hpp
-index 566ab9d..78be827 100644
---- a/vmime/utility/stream.hpp
-+++ b/vmime/utility/stream.hpp
-@@ -54,6 +54,10 @@ public:
- 	  */
- 	typedef string::size_type size_type;
- 
-+	/** Constant value with the greatest possible value for an element of type size_type.
-+	  */
-+	static const size_type npos;
-+
- 	/** Return the preferred maximum block size when reading
- 	  * from or writing to this stream.
- 	  *
-diff --git a/vmime/utility/streamUtils.hpp b/vmime/utility/streamUtils.hpp
-index cdf70aa..87c8fc5 100644
---- a/vmime/utility/streamUtils.hpp
-+++ b/vmime/utility/streamUtils.hpp
-@@ -45,6 +45,19 @@ namespace utility {
- stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os);
- 
- /** Copy data from one stream into another stream using a buffered method
-+  * and copying only a specified range of data.
-+  *
-+  * @param is input stream (source data)
-+  * @param os output stream (destination for data)
-+  * @param start number of bytes to ignore before starting copying
-+  * @param length maximum number of bytes to copy
-+  * @return number of bytes copied
-+  */
-+
-+stream::size_type bufferedStreamCopyRange(inputStream& is, outputStream& os,
-+	const stream::size_type start, const stream::size_type length);
-+
-+/** Copy data from one stream into another stream using a buffered method
-   * and notify progress state of the operation.
-   *
-   * @param is input stream (source data)
-diff --git a/vmime/word.hpp b/vmime/word.hpp
-index ad848ec..492aab5 100644
---- a/vmime/word.hpp
-+++ b/vmime/word.hpp
-@@ -128,21 +128,52 @@ public:
- #endif
- 
- 
--	using component::parse;
--	using component::generate;
-+protected:
- 
--	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;
-+	void parseImpl
-+		(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, const string::size_type curLinePos, string::size_type* newLinePos, const int flags, generatorState* state) const;
-+	void generateImpl
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength = lineLengthLimits::infinite,
-+		 const string::size_type curLinePos = 0,
-+		 string::size_type* newLinePos = NULL) const;
- 
--	const std::vector <ref <const component> > getChildComponents() const;
-+public:
- 
--private:
-+	using component::generate;
- 
--	static ref <word> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition, bool prevIsEncoded, bool* isEncoded, bool isFirst);
-+#ifndef VMIME_BUILDING_DOC
-+	void generate
-+		(utility::outputStream& os,
-+		 const string::size_type maxLineLength,
-+		 const string::size_type curLinePos,
-+		 string::size_type* newLinePos,
-+		 const int flags,
-+		 generatorState* state) const;
-+#endif
-+
-+	const std::vector <ref <component> > getChildComponents();
-+
-+private:
- 
--	static const std::vector <ref <word> > parseMultiple(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition);
-+	static ref <word> parseNext
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition,
-+		 bool prevIsEncoded,
-+		 bool* isEncoded,
-+		 bool isFirst);
-+
-+	static const std::vector <ref <word> > parseMultiple
-+		(const string& buffer,
-+		 const string::size_type position,
-+		 const string::size_type end,
-+		 string::size_type* newPosition);
- 
- 
- 	// The "m_buffer" of this word holds the data, and this data is encoded
--- 
-1.7.10.4
-
-
-From 2e05e574fde890c7ec6dd9f3930d06b1b492ea80 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 27 Apr 2012 08:34:26 +0200
-Subject: [PATCH 38/47] Fixed duplicate file reference (thanks to Enes Albay).
-
-
-diff --git a/SConstruct b/SConstruct
-index 2690172..1f3c7c9 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -137,7 +137,6 @@ libvmime_sources = [
- 	'utility/childProcess.hpp',
- 	'utility/file.hpp',
- 	'utility/datetimeUtils.cpp', 'utility/datetimeUtils.hpp',
--	'utility/filteredStream.cpp', 'utility/filteredStream.hpp',
- 	'utility/path.cpp', 'utility/path.hpp',
- 	'utility/progressListener.cpp', 'utility/progressListener.hpp',
- 	'utility/random.cpp', 'utility/random.hpp',
--- 
-1.7.10.4
-
-
-From 799629fd8b21a716f3e3abc6e6a5264555470d85 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Fri, 6 Jul 2012 18:45:02 +0200
-Subject: [PATCH 39/47] Fixed issue #10.
-
-
-diff --git a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp
-index 702d5f2..8006920 100644
---- a/src/net/imap/IMAPMessage.cpp
-+++ b/src/net/imap/IMAPMessage.cpp
-@@ -279,8 +279,6 @@ void IMAPMessage::extract(ref <const part> p, utility::outputStream& os,
- 	{
- 		if (headerOnly)
- 			command << "HEADER";
--		else
--			command << "TEXT";
- 	}
- 	else
- 	{
--- 
-1.7.10.4
-
-
-From 72cf7a025f7764998609683904eea1046a766d97 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Sat, 28 Jul 2012 13:01:48 +0200
-Subject: [PATCH 40/47] Added functions to get messages by UID (IMAP only for
- now).
-
-
-diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp
-index 81bf386..3d8c17e 100644
---- a/src/net/imap/IMAPFolder.cpp
-+++ b/src/net/imap/IMAPFolder.cpp
-@@ -208,7 +208,7 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable)
- 					{
- 					case IMAPParser::resp_text_code::UIDVALIDITY:
- 
--						m_uidValidity = code->nz_number()->value();
-+						m_uidValidity = static_cast <unsigned int>(code->nz_number()->value());
- 						break;
- 
- 					default:
-@@ -550,6 +550,109 @@ std::vector <ref <message> > IMAPFolder::getMessages(const std::vector <int>& nu
- }
- 
- 
-+ref <message> IMAPFolder::getMessageByUID(const message::uid& uid)
-+{
-+	std::vector <message::uid> uids;
-+	uids.push_back(uid);
-+
-+	std::vector <ref <message> > msgs = getMessagesByUID(uids);
-+
-+	if (msgs.size() == 0)
-+		throw exceptions::message_not_found();
-+
-+	return msgs[0];
-+}
-+
-+
-+std::vector <ref <message> > IMAPFolder::getMessagesByUID(const std::vector <message::uid>& uids)
-+{
-+	if (!isOpen())
-+		throw exceptions::illegal_state("Folder not open");
-+
-+	if (uids.size() == 0)
-+		return std::vector <ref <message> >();
-+
-+	//     C: . UID FETCH uuuu1,uuuu2,uuuu3 UID
-+	//     S: * nnnn1 FETCH (UID uuuu1)
-+	//     S: * nnnn2 FETCH (UID uuuu2)
-+	//     S: * nnnn3 FETCH (UID uuuu3)
-+	//     S: . OK UID FETCH completed
-+
-+	// Prepare command and arguments
-+	std::ostringstream cmd;
-+	cmd.imbue(std::locale::classic());
-+
-+	cmd << "UID FETCH " << IMAPUtils::extractUIDFromGlobalUID(uids[0]);
-+
-+	for (unsigned int i = 1, n = uids.size() ; i < n ; ++i)
-+		cmd << "," << IMAPUtils::extractUIDFromGlobalUID(uids[i]);
-+
-+	cmd << " UID";
-+
-+	// Send the request
-+	m_connection->send(true, cmd.str(), true);
-+
-+	// Get the response
-+	utility::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
-+
-+	if (resp->isBad() || resp->response_done()->response_tagged()->
-+			resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
-+	{
-+		throw exceptions::command_error("UID FETCH ... UID", m_connection->getParser()->lastLine(), "bad response");
-+	}
-+
-+	// Process the response
-+	const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
-+		resp->continue_req_or_response_data();
-+
-+	std::vector <ref <message> > messages;
-+
-+	for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
-+	     it = respDataList.begin() ; it != respDataList.end() ; ++it)
-+	{
-+		if ((*it)->response_data() == NULL)
-+		{
-+			throw exceptions::command_error("UID FETCH ... UID",
-+				m_connection->getParser()->lastLine(), "invalid response");
-+		}
-+
-+		const IMAPParser::message_data* messageData =
-+			(*it)->response_data()->message_data();
-+
-+		// We are only interested in responses of type "FETCH"
-+		if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH)
-+			continue;
-+
-+		// Get Process fetch response for this message
-+		const int msgNum = static_cast <int>(messageData->number());
-+		message::uid msgUID, msgFullUID;
-+
-+		// Find UID in message attributes
-+		const std::vector <IMAPParser::msg_att_item*> atts = messageData->msg_att()->items();
-+
-+		for (std::vector <IMAPParser::msg_att_item*>::const_iterator
-+		     it = atts.begin() ; it != atts.end() ; ++it)
-+		{
-+			if ((*it)->type() == IMAPParser::msg_att_item::UID)
-+			{
-+				msgFullUID = IMAPUtils::makeGlobalUID(m_uidValidity, (*it)->unique_id()->value());
-+				msgUID = (*it)->unique_id()->value();
-+
-+				break;
-+			}
-+		}
-+
-+		if (!msgUID.empty())
-+		{
-+			ref <IMAPFolder> thisFolder = thisRef().dynamicCast <IMAPFolder>();
-+			messages.push_back(vmime::create <IMAPMessage>(thisFolder, msgNum, msgFullUID));
-+		}
-+	}
-+
-+	return messages;
-+}
-+
-+
- int IMAPFolder::getMessageCount()
- {
- 	if (!isOpen())
-@@ -730,7 +833,7 @@ void IMAPFolder::fetchMessages(std::vector <ref <message> >& msg, const int opti
- 
- 			if (msg != numberToMsg.end())
- 			{
--				(*msg).second->processFetchResponse(options, messageData->msg_att());
-+				(*msg).second->processFetchResponse(options, messageData);
- 
- 				if (progress)
- 					progress->progress(++current, total);
-@@ -1781,7 +1884,7 @@ std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid&
- 	std::ostringstream command;
- 	command.imbue(std::locale::classic());
- 
--	command << "SEARCH UID " << uid;
-+	command << "SEARCH UID " << uid << ":*";
- 
- 	// Send the request
- 	m_connection->send(true, command.str(), true);
-diff --git a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp
-index 8006920..7202a7d 100644
---- a/src/net/imap/IMAPMessage.cpp
-+++ b/src/net/imap/IMAPMessage.cpp
-@@ -98,6 +98,14 @@ IMAPMessage::IMAPMessage(ref <IMAPFolder> folder, const int num)
- }
- 
- 
-+IMAPMessage::IMAPMessage(ref <IMAPFolder> folder, const int num, const uid& uniqueId)
-+	: m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED),
-+	  m_expunged(false), m_uid(uniqueId), m_structure(NULL)
-+{
-+	folder->registerMessage(this);
-+}
-+
-+
- IMAPMessage::~IMAPMessage()
- {
- 	ref <IMAPFolder> folder = m_folder.acquire();
-@@ -271,7 +279,11 @@ void IMAPMessage::extract(ref <const part> p, utility::outputStream& os,
- 	std::ostringstream command;
- 	command.imbue(std::locale::classic());
- 
--	command << "FETCH " << m_num << " BODY";
-+	if (m_uid.empty())
-+		command << "FETCH " << m_num << " BODY";
-+	else
-+		command << "UID FETCH " << IMAPUtils::extractUIDFromGlobalUID(m_uid) << " BODY";
-+
- 	if (peek) command << ".PEEK";
- 	command << "[";
- 
-@@ -361,19 +373,18 @@ void IMAPMessage::fetch(ref <IMAPFolder> msgFolder, const int options)
- 			continue;
- 
- 		// Process fetch response for this message
--		processFetchResponse(options, messageData->msg_att());
-+		processFetchResponse(options, messageData);
- 	}
- }
- 
- 
- void IMAPMessage::processFetchResponse
--	(const int options, const IMAPParser::msg_att* msgAtt)
-+	(const int options, const IMAPParser::message_data* msgData)
- {
- 	ref <IMAPFolder> folder = m_folder.acquire();
- 
- 	// Get message attributes
--	const std::vector <IMAPParser::msg_att_item*> atts =
--		msgAtt->items();
-+	const std::vector <IMAPParser::msg_att_item*> atts = msgData->msg_att()->items();
- 
- 	int flags = 0;
- 
-@@ -389,12 +400,7 @@ void IMAPMessage::processFetchResponse
- 		}
- 		case IMAPParser::msg_att_item::UID:
- 		{
--			std::ostringstream oss;
--			oss.imbue(std::locale::classic());
--
--			oss << folder->m_uidValidity << ":" << (*it)->unique_id()->value();
--
--			m_uid = oss.str();
-+			m_uid = IMAPUtils::makeGlobalUID(folder->m_uidValidity, (*it)->unique_id()->value());
- 			break;
- 		}
- 		case IMAPParser::msg_att_item::ENVELOPE:
-diff --git a/src/net/imap/IMAPUtils.cpp b/src/net/imap/IMAPUtils.cpp
-index 0d6fc47..eceac16 100644
---- a/src/net/imap/IMAPUtils.cpp
-+++ b/src/net/imap/IMAPUtils.cpp
-@@ -540,6 +540,24 @@ const string IMAPUtils::listToSet(const std::vector <int>& list, const int max,
- 
- 
- // static
-+const string IMAPUtils::listToSet(const std::vector <message::uid>& list)
-+{
-+	if (list.size() == 0)
-+		return "";
-+
-+	std::ostringstream res;
-+	res.imbue(std::locale::classic());
-+
-+	res << extractUIDFromGlobalUID(list[0]);
-+
-+	for (unsigned int i = 1, n = list.size() ; i < n ; ++i)
-+		res << "," << extractUIDFromGlobalUID(list[i]);
-+
-+	return res.str();
-+}
-+
-+
-+// static
- const string IMAPUtils::dateTime(const vmime::datetime& date)
- {
- 	std::ostringstream res;
-@@ -609,7 +627,8 @@ const string IMAPUtils::dateTime(const vmime::datetime& date)
- 
- 
- // static
--const string IMAPUtils::buildFetchRequest(const std::vector <int>& list, const int options)
-+const string IMAPUtils::buildFetchRequestImpl
-+	(const std::string& mode, const std::string& set, const int options)
- {
- 	// Example:
- 	//   C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
-@@ -671,7 +690,10 @@ const string IMAPUtils::buildFetchRequest(const std::vector <int>& list, const i
- 	std::ostringstream command;
- 	command.imbue(std::locale::classic());
- 
--	command << "FETCH " << listToSet(list, -1, false) << " (";
-+	if (mode == "uid")
-+		command << "UID FETCH " << set << " (";
-+	else
-+		command << "FETCH " << set << " (";
- 
- 	for (std::vector <string>::const_iterator it = items.begin() ;
- 	     it != items.end() ; ++it)
-@@ -687,6 +709,20 @@ const string IMAPUtils::buildFetchRequest(const std::vector <int>& list, const i
- 
- 
- // static
-+const string IMAPUtils::buildFetchRequest(const std::vector <int>& list, const int options)
-+{
-+	return buildFetchRequestImpl("number", listToSet(list, -1, false), options);
-+}
-+
-+
-+// static
-+const string IMAPUtils::buildFetchRequest(const std::vector <message::uid>& list, const int options)
-+{
-+	return buildFetchRequestImpl("uid", listToSet(list), options);
-+}
-+
-+
-+// static
- void IMAPUtils::convertAddressList
- 	(const IMAPParser::address_list& src, mailboxList& dest)
- {
-@@ -706,6 +742,46 @@ void IMAPUtils::convertAddressList
- }
- 
- 
-+// static
-+unsigned int IMAPUtils::extractUIDFromGlobalUID(const message::uid& uid)
-+{
-+	message::uid::size_type colonPos = uid.find(':');
-+
-+	if (colonPos == message::uid::npos)
-+	{
-+		std::istringstream iss(uid);
-+		iss.imbue(std::locale::classic());
-+
-+		unsigned int n = 0;
-+		iss >> n;
-+
-+		return n;
-+	}
-+	else
-+	{
-+		std::istringstream iss(uid.substr(colonPos + 1));
-+		iss.imbue(std::locale::classic());
-+
-+		unsigned int n = 0;
-+		iss >> n;
-+
-+		return n;
-+	}
-+}
-+
-+
-+// static
-+const message::uid IMAPUtils::makeGlobalUID(const unsigned int UIDValidity, const unsigned int messageUID)
-+{
-+	std::ostringstream oss;
-+	oss.imbue(std::locale::classic());
-+
-+	oss << UIDValidity << ":" << messageUID;
-+
-+	return message::uid(oss.str());
-+}
-+
-+
- } // imap
- } // net
- } // vmime
-diff --git a/src/net/maildir/maildirFolder.cpp b/src/net/maildir/maildirFolder.cpp
-index 8c4b275..b606cda 100644
---- a/src/net/maildir/maildirFolder.cpp
-+++ b/src/net/maildir/maildirFolder.cpp
-@@ -444,6 +444,18 @@ std::vector <ref <message> > maildirFolder::getMessages(const std::vector <int>&
- }
- 
- 
-+ref <message> maildirFolder::getMessageByUID(const message::uid& /* uid */)
-+{
-+	throw exceptions::operation_not_supported();
-+}
-+
-+
-+std::vector <ref <message> > maildirFolder::getMessagesByUID(const std::vector <message::uid>& /* uids */)
-+{
-+	throw exceptions::operation_not_supported();
-+}
-+
-+
- int maildirFolder::getMessageCount()
- {
- 	return (m_messageCount);
-diff --git a/src/net/pop3/POP3Folder.cpp b/src/net/pop3/POP3Folder.cpp
-index e085609..21e7a8b 100644
---- a/src/net/pop3/POP3Folder.cpp
-+++ b/src/net/pop3/POP3Folder.cpp
-@@ -249,6 +249,18 @@ std::vector <ref <message> > POP3Folder::getMessages(const int from, const int t
- }
- 
- 
-+ref <message> POP3Folder::getMessageByUID(const message::uid& /* uid */)
-+{
-+	throw exceptions::operation_not_supported();
-+}
-+
-+
-+std::vector <ref <message> > POP3Folder::getMessagesByUID(const std::vector <message::uid>& /* uids */)
-+{
-+	throw exceptions::operation_not_supported();
-+}
-+
-+
- std::vector <ref <message> > POP3Folder::getMessages(const std::vector <int>& nums)
- {
- 	ref <POP3Store> store = m_store.acquire();
-diff --git a/vmime/net/folder.hpp b/vmime/net/folder.hpp
-index df9cbaf..a50ee0e 100644
---- a/vmime/net/folder.hpp
-+++ b/vmime/net/folder.hpp
-@@ -169,7 +169,7 @@ public:
- 	  */
- 	virtual bool isOpen() const = 0;
- 
--	/** Get a new reference to a message in this folder.
-+	/** Get a new reference to a message in this folder, given its number.
- 	  *
- 	  * @param num message sequence number
- 	  * @return a new object referencing the specified message
-@@ -177,7 +177,7 @@ public:
- 	  */
- 	virtual ref <message> getMessage(const int num) = 0;
- 
--	/** Get new references to messages in this folder.
-+	/** Get new references to messages in this folder, given their numbers.
- 	  *
- 	  * @param from sequence number of the first message to get
- 	  * @param to sequence number of the last message to get
-@@ -186,14 +186,30 @@ public:
- 	  */
- 	virtual std::vector <ref <message> > getMessages(const int from = 1, const int to = -1) = 0;
- 
--	/** Get new references to messages in this folder.
-+	/** Get new references to messages in this folder, given their numbers.
- 	  *
--	  * @param nums sequence numbers of the messages to delete
-+	  * @param nums sequence numbers of the messages to retrieve
- 	  * @return new objects referencing the specified messages
- 	  * @throw net_exception if an error occurs
- 	  */
- 	virtual std::vector <ref <message> > getMessages(const std::vector <int>& nums) = 0;
- 
-+	/** Get message in this folder, given its UID.
-+	  *
-+	  * @param uid UID of message to retrieve
-+	  * @return a new object referencing the specified message
-+	  * @throw net_exception if an error occurs
-+	  */
-+	virtual ref <message> getMessageByUID(const message::uid& uid) = 0;
-+
-+	/** Get messages in this folder, given their UIDs.
-+	  *
-+	  * @param uids UIDs of messages to retrieve
-+	  * @return new objects referencing the specified messages
-+	  * @throw net_exception if an error occurs
-+	  */
-+	virtual std::vector <ref <message> > getMessagesByUID(const std::vector <message::uid>& uids) = 0;
-+
- 	/** Return the number of messages in this folder.
- 	  *
- 	  * @return number of messages in the folder
-diff --git a/vmime/net/imap/IMAPFolder.hpp b/vmime/net/imap/IMAPFolder.hpp
-index cc52596..3337858 100644
---- a/vmime/net/imap/IMAPFolder.hpp
-+++ b/vmime/net/imap/IMAPFolder.hpp
-@@ -84,6 +84,12 @@ public:
- 	ref <message> getMessage(const int num);
- 	std::vector <ref <message> > getMessages(const int from = 1, const int to = -1);
- 	std::vector <ref <message> > getMessages(const std::vector <int>& nums);
-+
-+	ref <message> getMessageByUID(const message::uid& uid);
-+	std::vector <ref <message> > getMessagesByUID(const std::vector <message::uid>& uids);
-+
-+	std::vector <int> getMessageNumbersStartingOnUID(const message::uid& uid);
-+
- 	int getMessageCount();
- 
- 	ref <folder> getFolder(const folder::path::component& name);
-@@ -120,8 +126,6 @@ public:
- 
- 	int getFetchCapabilities() const;
- 
--	std::vector <int> getMessageNumbersStartingOnUID(const message::uid& uid);
--
- private:
- 
- 	void registerMessage(IMAPMessage* msg);
-@@ -152,7 +156,7 @@ private:
- 
- 	int m_messageCount;
- 
--	int m_uidValidity;
-+	unsigned int m_uidValidity;
- 
- 	std::vector <IMAPMessage*> m_messages;
- };
-diff --git a/vmime/net/imap/IMAPMessage.hpp b/vmime/net/imap/IMAPMessage.hpp
-index edbf69f..fbba6e7 100644
---- a/vmime/net/imap/IMAPMessage.hpp
-+++ b/vmime/net/imap/IMAPMessage.hpp
-@@ -50,6 +50,7 @@ private:
- 	friend class vmime::creator;  // vmime::create <IMAPMessage>
- 
- 	IMAPMessage(ref <IMAPFolder> folder, const int num);
-+	IMAPMessage(ref <IMAPFolder> folder, const int num, const uid& uniqueId);
- 	IMAPMessage(const IMAPMessage&) : message() { }
- 
- 	~IMAPMessage();
-@@ -83,7 +84,7 @@ private:
- 
- 	void fetch(ref <IMAPFolder> folder, const int options);
- 
--	void processFetchResponse(const int options, const IMAPParser::msg_att* msgAtt);
-+	void processFetchResponse(const int options, const IMAPParser::message_data* msgData);
- 
- 	/** Recursively fetch part header for all parts in the structure.
- 	  *
-diff --git a/vmime/net/imap/IMAPUtils.hpp b/vmime/net/imap/IMAPUtils.hpp
-index d1ed5c8..9c9c420 100644
---- a/vmime/net/imap/IMAPUtils.hpp
-+++ b/vmime/net/imap/IMAPUtils.hpp
-@@ -29,6 +29,7 @@
- #include "vmime/dateTime.hpp"
- 
- #include "vmime/net/folder.hpp"
-+#include "vmime/net/message.hpp"
- #include "vmime/net/imap/IMAPParser.hpp"
- 
- #include "vmime/mailboxList.hpp"
-@@ -65,8 +66,8 @@ public:
- 
- 	static const string messageFlagList(const int flags);
- 
--	/** Build an "IMAP set" given a list. The function tries to group
--	  * consecutive message numbers to reduce the list.
-+	/** Build an "IMAP set" given a list of message numbers. The function tries
-+	  * to group consecutive message numbers to reduce the list.
- 	  *
- 	  * Example:
- 	  *    IN  = "1,2,3,4,5,7,8,13,15,16,17"
-@@ -81,6 +82,13 @@ public:
- 	static const string listToSet(const std::vector <int>& list,
- 		const int max = -1, const bool alreadySorted = false);
- 
-+	/** Build an "IMAP set" set given a list of message UIDs.
-+	  *
-+	  * @param list list of message UIDs
-+	  * @return a set corresponding to the list
-+	  */
-+	static const string listToSet(const std::vector <message::uid>& list);
-+
- 	/** Format a date/time to IMAP date/time format.
- 	  *
- 	  * @param date date/time to format
-@@ -88,7 +96,7 @@ public:
- 	  */
- 	static const string dateTime(const vmime::datetime& date);
- 
--	/** Construct a fetch request for the specified messages.
-+	/** Construct a fetch request for the specified messages, designated by their sequence numbers.
- 	  *
- 	  * @param list list of message numbers
- 	  * @param options fetch options
-@@ -96,12 +104,40 @@ public:
- 	  */
- 	static const string buildFetchRequest(const std::vector <int>& list, const int options);
- 
-+	/** Construct a fetch request for the specified messages, designated by their UIDs.
-+	  *
-+	  * @param list list of message UIDs
-+	  * @param options fetch options
-+	  * @return fetch request
-+	  */
-+	static const string buildFetchRequest(const std::vector <message::uid>& list, const int options);
-+
- 	/** Convert a parser-style address list to a mailbox list.
- 	  *
- 	  * @param src input address list
- 	  * @param dest output mailbox list
- 	  */
- 	static void convertAddressList(const IMAPParser::address_list& src, mailboxList& dest);
-+
-+	/** Extract the message UID from a globally unique UID.
-+	  *
-+	  * @param uid globally unique UID (as returned by makeGlobalUID(), for example)
-+	  * @return message UID
-+	  */
-+	static unsigned int extractUIDFromGlobalUID(const message::uid& uid);
-+
-+	/** Construct a globally unique UID from UID Validity and a message UID.
-+	  *
-+	  * @param UIDValidity UID Validity of the folder
-+	  * @param messageUID UID of the message
-+	  * @return global UID
-+	  */
-+	static const message::uid makeGlobalUID(const unsigned int UIDValidity, const unsigned int messageUID);
-+
-+private:
-+
-+	static const string buildFetchRequestImpl
-+		(const std::string& mode, const std::string& set, const int options);
- };
- 
- 
-diff --git a/vmime/net/maildir/maildirFolder.hpp b/vmime/net/maildir/maildirFolder.hpp
-index 68b5b89..c9ba899 100644
---- a/vmime/net/maildir/maildirFolder.hpp
-+++ b/vmime/net/maildir/maildirFolder.hpp
-@@ -85,6 +85,10 @@ public:
- 	ref <message> getMessage(const int num);
- 	std::vector <ref <message> > getMessages(const int from = 1, const int to = -1);
- 	std::vector <ref <message> > getMessages(const std::vector <int>& nums);
-+
-+	ref <message> getMessageByUID(const message::uid& uid);
-+	std::vector <ref <message> > getMessagesByUID(const std::vector <message::uid>& uids);
-+
- 	int getMessageCount();
- 
- 	ref <folder> getFolder(const folder::path::component& name);
-diff --git a/vmime/net/pop3/POP3Folder.hpp b/vmime/net/pop3/POP3Folder.hpp
-index c482908..090f948 100644
---- a/vmime/net/pop3/POP3Folder.hpp
-+++ b/vmime/net/pop3/POP3Folder.hpp
-@@ -83,6 +83,10 @@ public:
- 	ref <message> getMessage(const int num);
- 	std::vector <ref <message> > getMessages(const int from = 1, const int to = -1);
- 	std::vector <ref <message> > getMessages(const std::vector <int>& nums);
-+
-+	ref <message> getMessageByUID(const message::uid& uid);
-+	std::vector <ref <message> > getMessagesByUID(const std::vector <message::uid>& uids);
-+
- 	int getMessageCount();
- 
- 	ref <folder> getFolder(const folder::path::component& name);
--- 
-1.7.10.4
-
-
-From 7501f61214b06a35c8fce7772fd48dded2cad335 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Mon, 30 Jul 2012 11:23:23 +0200
-Subject: [PATCH 41/47] Fixed compilation warning.
-
-
-diff --git a/vmime/utility/parserInputStreamAdapter.hpp b/vmime/utility/parserInputStreamAdapter.hpp
-index c24fa44..861e75b 100644
---- a/vmime/utility/parserInputStreamAdapter.hpp
-+++ b/vmime/utility/parserInputStreamAdapter.hpp
-@@ -82,7 +82,7 @@ public:
- 
- 			m_stream->seek(initialPos);
- 
--			return (readBytes == 1 ? buffer[0] : 0);
-+			return (readBytes == 1 ? buffer[0] : static_cast <value_type>(0));
- 		}
- 		catch (...)
- 		{
-@@ -101,7 +101,7 @@ public:
- 		value_type buffer[1];
- 		const size_type readBytes = m_stream->read(buffer, 1);
- 
--		return (readBytes == 1 ? buffer[0] : 0);
-+		return (readBytes == 1 ? buffer[0] : static_cast <value_type>(0));
- 	}
- 
- 	/** Check whether the bytes following the current position match
--- 
-1.7.10.4
-
-
-From f9f9b3bf52c76e1803855d1c44147f68ec9f62f2 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Mon, 30 Jul 2012 20:45:17 +0200
-Subject: [PATCH 42/47] Fixed body part extraction (only body should be
- extracted).
-
-
-diff --git a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp
-index 7202a7d..808f7d1 100644
---- a/src/net/imap/IMAPMessage.cpp
-+++ b/src/net/imap/IMAPMessage.cpp
-@@ -192,7 +192,7 @@ void IMAPMessage::extract(utility::outputStream& os, utility::progressListener*
- 	if (!folder)
- 		throw exceptions::folder_not_found();
- 
--	extract(NULL, os, progress, start, length, false, peek);
-+	extractImpl(NULL, os, progress, start, length, EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0));
- }
- 
- 
-@@ -205,7 +205,7 @@ void IMAPMessage::extractPart
- 	if (!folder)
- 		throw exceptions::folder_not_found();
- 
--	extract(p, os, progress, start, length, false, peek);
-+	extractImpl(p, os, progress, start, length, EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0));
- }
- 
- 
-@@ -219,7 +219,7 @@ void IMAPMessage::fetchPartHeader(ref <part> p)
- 	std::ostringstream oss;
- 	utility::outputStreamAdapter ossAdapter(oss);
- 
--	extract(p, ossAdapter, NULL, 0, -1, true, true);
-+	extractImpl(p, ossAdapter, NULL, 0, -1, EXTRACT_HEADER | EXTRACT_PEEK);
- 
- 	p.dynamicCast <IMAPPart>()->getOrCreateHeader().parse(oss.str());
- }
-@@ -240,9 +240,9 @@ void IMAPMessage::fetchPartHeaderForStructure(ref <structure> str)
- }
- 
- 
--void IMAPMessage::extract(ref <const part> p, utility::outputStream& os,
-+void IMAPMessage::extractImpl(ref <const part> p, utility::outputStream& os,
- 	utility::progressListener* progress, const int start,
--	const int length, const bool headerOnly, const bool peek) const
-+	const int length, const int extractFlags) const
- {
- 	ref <const IMAPFolder> folder = m_folder.acquire();
- 
-@@ -284,18 +284,45 @@ void IMAPMessage::extract(ref <const part> p, utility::outputStream& os,
- 	else
- 		command << "UID FETCH " << IMAPUtils::extractUIDFromGlobalUID(m_uid) << " BODY";
- 
--	if (peek) command << ".PEEK";
-+	/*
-+	   BODY[]               header + body
-+	   BODY.PEEK[]          header + body (peek)
-+	   BODY[HEADER]         header
-+	   BODY.PEEK[HEADER]    header (peek)
-+	   BODY[TEXT]           body
-+	   BODY.PEEK[TEXT]      body (peek)
-+	*/
-+
-+	if (extractFlags & EXTRACT_PEEK)
-+		command << ".PEEK";
-+
- 	command << "[";
- 
- 	if (section.str().empty())
- 	{
--		if (headerOnly)
-+		// header + body
-+		if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY))
-+			command << "";
-+		// body only
-+		else if (extractFlags & EXTRACT_BODY)
-+			command << "TEXT";
-+		// header only
-+		else if (extractFlags & EXTRACT_HEADER)
- 			command << "HEADER";
- 	}
- 	else
- 	{
- 		command << section.str();
--		if (headerOnly) command << ".MIME";   // "MIME" not "HEADER" for parts
-+
-+		// header + body
-+		if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY))
-+			*((int *) 0)=42;//throw exceptions::operation_not_supported();
-+		// body only
-+		else if (extractFlags & EXTRACT_BODY)
-+			command << ".TEXT";
-+		// header only
-+		else if (extractFlags & EXTRACT_HEADER)
-+			command << ".MIME";   // "MIME" not "HEADER" for parts
- 	}
- 
- 	command << "]";
-@@ -318,7 +345,7 @@ void IMAPMessage::extract(ref <const part> p, utility::outputStream& os,
- 	}
- 
- 
--	if (!headerOnly)
-+	if (extractFlags & EXTRACT_BODY)
- 	{
- 		// TODO: update the flags (eg. flag "\Seen" may have been set)
- 	}
-diff --git a/src/net/imap/IMAPMessagePartContentHandler.cpp b/src/net/imap/IMAPMessagePartContentHandler.cpp
-index 85c6ec2..c2cd647 100644
---- a/src/net/imap/IMAPMessagePartContentHandler.cpp
-+++ b/src/net/imap/IMAPMessagePartContentHandler.cpp
-@@ -121,7 +121,7 @@ void IMAPMessagePartContentHandler::extract
- 	// No decoding to perform
- 	if (!isEncoded())
- 	{
--		msg->extractPart(part, os, progress);
-+		msg->extractImpl(part, os, progress, 0, -1, IMAPMessage::EXTRACT_BODY);
- 	}
- 	// Need to decode data
- 	else
-@@ -130,7 +130,7 @@ void IMAPMessagePartContentHandler::extract
- 		std::ostringstream oss;
- 		utility::outputStreamAdapter tmp(oss);
- 
--		msg->extractPart(part, tmp, NULL);
-+		msg->extractImpl(part, tmp, NULL, 0, -1, IMAPMessage::EXTRACT_BODY);
- 
- 		// Encode temporary buffer to output stream
- 		utility::inputStreamStringAdapter is(oss.str());
-diff --git a/vmime/net/imap/IMAPMessage.hpp b/vmime/net/imap/IMAPMessage.hpp
-index fbba6e7..06f8091 100644
---- a/vmime/net/imap/IMAPMessage.hpp
-+++ b/vmime/net/imap/IMAPMessage.hpp
-@@ -47,6 +47,7 @@ class IMAPMessage : public message
- private:
- 
- 	friend class IMAPFolder;
-+	friend class IMAPMessagePartContentHandler;
- 	friend class vmime::creator;  // vmime::create <IMAPMessage>
- 
- 	IMAPMessage(ref <IMAPFolder> folder, const int num);
-@@ -101,7 +102,16 @@ private:
- 	  */
- 	void constructParsedMessage(ref <bodyPart> parentPart, ref <structure> str, int level = 0);
- 
--	void extract(ref <const part> p, utility::outputStream& os, utility::progressListener* progress, const int start, const int length, const bool headerOnly, const bool peek) const;
-+
-+	enum ExtractFlags
-+	{
-+		EXTRACT_HEADER = 0x1,
-+		EXTRACT_BODY = 0x2,
-+		EXTRACT_PEEK = 0x10
-+	};
-+
-+	void extractImpl(ref <const part> p, utility::outputStream& os, utility::progressListener* progress,
-+		const int start, const int length, const int extractFlags) const;
- 
- 
- 	ref <header> getOrCreateHeader();
--- 
-1.7.10.4
-
-
-From 1c58fc9735c9832c8e849d4f37f4f502b1fc895c Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Mon, 30 Jul 2012 21:28:59 +0200
-Subject: [PATCH 43/47] Added README about autotools scripts. (cherry picked
- from commit 99908ce889eaa7ea6ba917255f11bf9969515793)
-
-
-diff --git a/README.autotools b/README.autotools
-new file mode 100644
-index 0000000..4b83a22
---- /dev/null
-+++ b/README.autotools
-@@ -0,0 +1,8 @@
-+Where are the ./configure script and the Makefile's?
-+
-+Configure and Make scripts are not included in the git source tree. They are
-+automatically generated by the SConstruct script.
-+
-+Just type "scons autotools" to generate everything needed for the traditional
-+./configure, make, make install build process.
-+
--- 
-1.7.10.4
-
-
-From 1e3ba8c5d520a4b6ab85478672e96f219b9f6135 Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Mon, 15 Oct 2012 11:19:53 +0200
-Subject: [PATCH 45/47] Do not fail if charset is not recognized. (cherry
- picked from commit
- e4102b4374e3acde31c9d320166ef37855834c72)
-
-
-diff --git a/src/word.cpp b/src/word.cpp
-index 2876ddf..1ea2293 100644
---- a/src/word.cpp
-+++ b/src/word.cpp
-@@ -695,7 +695,16 @@ const string word::getConvertedText(const charset& dest) const
- {
- 	string out;
- 
--	charset::convert(m_buffer, out, m_charset, dest);
-+	try
-+	{
-+		charset::convert(m_buffer, out, m_charset, dest);
-+	}
-+	catch (vmime::exceptions::charset_conv_error& e)
-+	{
-+		// Do not fail if charset is not recognized:
-+		// copy 'word' as raw text
-+		out = m_buffer;
-+	}
- 
- 	return (out);
- }
--- 
-1.7.10.4
-
-
-From 927c052cafd65b14036834e9cb91a4b453aa2c5c Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Mon, 15 Oct 2012 11:23:22 +0200
-Subject: [PATCH 46/47] Support for bogus encoding name 'bmoted-printable'
- (Zarafa). (cherry picked from commit
- 2b09c6ea6cfad29682976ea7748721551dd3db64)
-
-
-diff --git a/src/utility/encoder/encoderFactory.cpp b/src/utility/encoder/encoderFactory.cpp
-index 2237178..1798ffa 100644
---- a/src/utility/encoder/encoderFactory.cpp
-+++ b/src/utility/encoder/encoderFactory.cpp
-@@ -50,6 +50,9 @@ encoderFactory::encoderFactory()
- 	// Also register some non-standard encoding names
- 	registerName <sevenBitEncoder>("7-bit");
- 	registerName <eightBitEncoder>("8-bit");
-+
-+	// Finally, register some bogus encoding names, for compatibility
-+	registerName <qpEncoder>("bmoted-printable");
- }
- 
- 
--- 
-1.7.10.4
-
-
-From fe3114a41e2803b2a6993e8dd03e1ed685e4570c Mon Sep 17 00:00:00 2001
-From: Vincent Richard <vincent@vincent-richard.net>
-Date: Mon, 15 Oct 2012 11:48:14 +0200
-Subject: [PATCH 47/47] Added support for timeout when receiving data from a
- socket (POSIX platform). (cherry picked from commit
- 794afe9a1b5ee36a5de8f90f3d789ca46f393bb7)
-
-
-diff --git a/src/platforms/posix/posixSocket.cpp b/src/platforms/posix/posixSocket.cpp
-index b8bb8b1..f280dad 100644
---- a/src/platforms/posix/posixSocket.cpp
-+++ b/src/platforms/posix/posixSocket.cpp
-@@ -336,7 +336,45 @@ void posixSocket::receive(vmime::string& buffer)
- 
- posixSocket::size_type posixSocket::receiveRaw(char* buffer, const size_type count)
- {
--	const int ret = ::recv(m_desc, buffer, count, 0);
-+	// Check whether data is available
-+	fd_set fds;
-+	FD_ZERO(&fds);
-+	FD_SET(m_desc, &fds);
-+
-+	struct timeval tv;
-+	tv.tv_sec = 1;
-+	tv.tv_usec = 0;
-+
-+	int ret = ::select(m_desc + 1, &fds, NULL, NULL, &tv);
-+
-+	if (ret < 0)
-+	{
-+		if (errno != EAGAIN)
-+			throwSocketError(errno);
-+
-+		// No data available at this time
-+		// Check if we are timed out
-+		if (m_timeoutHandler &&
-+		    m_timeoutHandler->isTimeOut())
-+		{
-+			if (!m_timeoutHandler->handleTimeOut())
-+			{
-+				// Server did not react within timeout delay
-+				throwSocketError(errno);
-+			}
-+			else
-+			{
-+				// Reset timeout
-+				m_timeoutHandler->resetTimeOut();
-+			}
-+		}
-+
-+		// Continue waiting for data
-+		return 0;
-+	}
-+
-+	// Read available data
-+	ret = ::recv(m_desc, buffer, count, 0);
- 
- 	if (ret < 0)
- 	{
-@@ -351,6 +389,12 @@ posixSocket::size_type posixSocket::receiveRaw(char* buffer, const size_type cou
- 		// Host shutdown
- 		throwSocketError(ENOTCONN);
- 	}
-+	else
-+	{
-+		// Data received, reset timeout
-+		if (m_timeoutHandler)
-+			m_timeoutHandler->resetTimeOut();
-+	}
- 
- 	return ret;
- }
-@@ -383,6 +427,10 @@ void posixSocket::sendRaw(const char* buffer, const size_type count)
- 			size -= ret;
- 		}
- 	}
-+
-+	// Reset timeout
-+	if (m_timeoutHandler)
-+		m_timeoutHandler->resetTimeOut();
- }
- 
- 
--- 
-1.7.10.4
-
--- a/src/vmime.mk	Sat Nov 10 11:50:40 2012 +0100
+++ b/src/vmime.mk	Mon Nov 12 21:56:00 2012 +0100
@@ -3,16 +3,16 @@
 
 PKG             := vmime
 $(PKG)_IGNORE   :=
-$(PKG)_CHECKSUM := 3e8dd8855e423db438d465777efeb523c4abb5f3
-$(PKG)_SUBDIR   := lib$(PKG)-$($(PKG)_VERSION)
-$(PKG)_FILE     := lib$(PKG)-$($(PKG)_VERSION).tar.bz2
-$(PKG)_URL      := http://$(SOURCEFORGE_MIRROR)/project/$(PKG)/$(PKG)/$(call SHORT_PKG_VERSION,$(PKG))/$($(PKG)_FILE)
+$(PKG)_CHECKSUM := 24a32dcc2eaf78d4a53541936ef72e4cf4f0a6ff
+$(PKG)_SUBDIR   := kisli-vmime-$($(PKG)_VERSION)
+$(PKG)_FILE     := $(PKG)-$($(PKG)_VERSION).tar.gz
+$(PKG)_URL      := https://github.com/kisli/vmime/tarball/$($(PKG)_VERSION)/$(PKG)_FILE
 $(PKG)_DEPS     := gcc libiconv gnutls libgsasl pthreads zlib
 
 define $(PKG)_UPDATE
-    $(WGET) -q -O- 'http://sourceforge.net/projects/vmime/files/vmime/' | \
-    $(SED) -n 's,.*libvmime-\([0-9][^>]*\)\.tar.*,\1,p' | \
-    tail -1
+    $(WGET) -q -O- 'https://github.com/kisli/vmime/commits/master' | \
+    $(SED) -n 's#.*<span class="sha">\([^<]\{7\}\)[^<]\{3\}<.*#\1#p' | \
+    head -1
 endef
 
 define $(PKG)_BUILD