view src/vmime-0.9.1-svn-r551-20100520.patch @ 998:1b1c09973721

upgrade package vmime to 0.9.1-svn-r551 Also added missing zlib dependency for test-vmime.exe. r551 merges our previously used patch. r547 | vincent-richard | 2010-05-18 15:52:27 +0200 (Tue, 18 May 2010) | 1 line Added helper function to construct parsed message from net message. Splitted IMAP source files. r548 | vincent-richard | 2010-05-20 11:57:51 +0200 (Thu, 20 May 2010) | 1 line Fixed type size. r549 | vincent-richard | 2010-05-20 12:00:19 +0200 (Thu, 20 May 2010) | 1 line Fixed unit tests build on OSX. r550 | vincent-richard | 2010-05-20 17:28:51 +0200 (Thu, 20 May 2010) | 1 line Fixed case-sensitive include. r551 | vincent-richard | 2010-05-21 08:01:33 +0200 (Fri, 21 May 2010) | 1 line Fixed missing #include.
author Mark Brand <mabrand@mabrand.nl>
date Fri, 21 May 2010 09:26:45 +0200
parents
children
line wrap: on
line source

This file is part of mingw-cross-env.
See doc/index.html for further information.

diff -urN a/ChangeLog b/ChangeLog
--- a/ChangeLog	2010-05-21 09:06:26.955934365 +0200
+++ b/ChangeLog	2010-05-21 09:07:53.363928193 +0200
@@ -2,6 +2,11 @@
 VERSION 0.9.1svn
 ================
 
+2010-05-18  Vincent Richard  <vincent@vincent-richard.net>
+
+ * net/*: added helper function vmime::net::message::getParsedMessage()
+   to construct a RFC-822 parsed message from a net message.
+
 2009-09-06  Vincent Richard  <vincent@vincent-richard.net>
 
  * Relicensed VMime under the GNU GPL license version 3. Dual licensing
diff -urN a/SConstruct b/SConstruct
--- a/SConstruct	2010-05-21 09:06:27.116428601 +0200
+++ b/SConstruct	2010-05-21 09:07:53.367948000 +0200
@@ -261,6 +261,9 @@
 			'net/imap/IMAPMessage.cpp',      'net/imap/IMAPMessage.hpp',
 			'net/imap/IMAPTag.cpp',          'net/imap/IMAPTag.hpp',
 			'net/imap/IMAPUtils.cpp',        'net/imap/IMAPUtils.hpp',
+			'net/imap/IMAPMessagePartContentHandler.cpp', 'net/imap/IMAPMessagePartContentHandler.hpp',
+			'net/imap/IMAPStructure.cpp',    'net/imap/IMAPStructure.hpp',
+			'net/imap/IMAPPart.cpp',         'net/imap/IMAPPart.hpp',
 			'net/imap/IMAPParser.hpp',
 		]
 	],
@@ -959,6 +962,10 @@
 		env = env.Clone()
 		env.Append(LIBS = ['cppunit', 'dl', packageVersionedGenericName + '-debug', 'pthread'])
 		env.Append(LIBPATH=['.'])
+
+		if sys.platform == "mac" or sys.platform == "darwin":
+			env.Append(LIBS = ['iconv', 'gcrypt'])
+
 		Default(
 			env.Program(
 				target = 'run-tests',
diff -urN a/src/bodyPart.cpp b/src/bodyPart.cpp
--- a/src/bodyPart.cpp	2010-05-21 09:06:26.964428162 +0200
+++ b/src/bodyPart.cpp	2010-05-21 09:07:53.367948000 +0200
@@ -37,6 +37,15 @@
 }
 
 
+bodyPart::bodyPart(weak_ref <vmime::bodyPart> parentPart)
+	: m_header(vmime::create <header>()),
+	  m_body(vmime::create <body>()),
+	  m_parent(parentPart)
+{
+	m_body->setParentPart(thisRef().dynamicCast <bodyPart>());
+}
+
+
 void bodyPart::parse(const string& buffer, const string::size_type position,
 	const string::size_type end, string::size_type* newPosition)
 {
diff -urN a/src/headerField.cpp b/src/headerField.cpp
--- a/src/headerField.cpp	2010-05-21 09:06:27.120433672 +0200
+++ b/src/headerField.cpp	2010-05-21 09:07:53.367948000 +0200
@@ -300,7 +300,8 @@
 {
 	std::vector <ref <const component> > list;
 
-	list.push_back(m_value);
+	if (m_value)
+		list.push_back(m_value);
 
 	return (list);
 }
diff -urN a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp
--- a/src/net/imap/IMAPMessage.cpp	2010-05-21 09:06:26.984436060 +0200
+++ b/src/net/imap/IMAPMessage.cpp	2010-05-21 09:07:53.363928193 +0200
@@ -27,6 +27,9 @@
 #include "vmime/net/imap/IMAPStore.hpp"
 #include "vmime/net/imap/IMAPConnection.hpp"
 #include "vmime/net/imap/IMAPUtils.hpp"
+#include "vmime/net/imap/IMAPStructure.hpp"
+#include "vmime/net/imap/IMAPPart.hpp"
+#include "vmime/net/imap/IMAPMessagePartContentHandler.hpp"
 
 #include <sstream>
 #include <iterator>
@@ -38,198 +41,6 @@
 namespace imap {
 
 
-//
-// IMAPpart
-//
-
-class IMAPstructure;
-
-class IMAPpart : public part
-{
-private:
-
-	friend class vmime::creator;
-
-	IMAPpart(ref <IMAPpart> parent, const int number, const IMAPParser::body_type_mpart* mpart);
-	IMAPpart(ref <IMAPpart> parent, const int number, const IMAPParser::body_type_1part* part);
-
-public:
-
-	ref <const structure> getStructure() const;
-	ref <structure> getStructure();
-
-	ref <const IMAPpart> getParent() const { return m_parent.acquire(); }
-
-	const mediaType& getType() const { return (m_mediaType); }
-	int getSize() const { return (m_size); }
-	int getNumber() const { return (m_number); }
-
-	ref <const header> getHeader() const
-	{
-		if (m_header == NULL)
-			throw exceptions::unfetched_object();
-		else
-			return m_header;
-	}
-
-
-	static ref <IMAPpart> create
-		(ref <IMAPpart> parent, const int number, const IMAPParser::body* body)
-	{
-		if (body->body_type_mpart())
-		{
-			ref <IMAPpart> part = vmime::create <IMAPpart>(parent, number, body->body_type_mpart());
-			part->m_structure = vmime::create <IMAPstructure>(part, body->body_type_mpart()->list());
-
-			return part;
-		}
-		else
-		{
-			return vmime::create <IMAPpart>(parent, number, body->body_type_1part());
-		}
-	}
-
-
-	header& getOrCreateHeader()
-	{
-		if (m_header != NULL)
-			return (*m_header);
-		else
-			return (*(m_header = vmime::create <header>()));
-	}
-
-private:
-
-	ref <IMAPstructure> m_structure;
-	weak_ref <IMAPpart> m_parent;
-	ref <header> m_header;
-
-	int m_number;
-	int m_size;
-	mediaType m_mediaType;
-};
-
-
-
-//
-// IMAPstructure
-//
-
-class IMAPstructure : public structure
-{
-public:
-
-	IMAPstructure()
-	{
-	}
-
-	IMAPstructure(const IMAPParser::body* body)
-	{
-		m_parts.push_back(IMAPpart::create(NULL, 0, body));
-	}
-
-	IMAPstructure(ref <IMAPpart> parent, const std::vector <IMAPParser::body*>& list)
-	{
-		int number = 0;
-
-		for (std::vector <IMAPParser::body*>::const_iterator
-		     it = list.begin() ; it != list.end() ; ++it, ++number)
-		{
-			m_parts.push_back(IMAPpart::create(parent, number, *it));
-		}
-	}
-
-
-	ref <const part> getPartAt(const int x) const
-	{
-		return m_parts[x];
-	}
-
-	ref <part> getPartAt(const int x)
-	{
-		return m_parts[x];
-	}
-
-	int getPartCount() const
-	{
-		return m_parts.size();
-	}
-
-
-	static ref <IMAPstructure> emptyStructure()
-	{
-		return (m_emptyStructure);
-	}
-
-private:
-
-	static ref <IMAPstructure> m_emptyStructure;
-
-	std::vector <ref <IMAPpart> > m_parts;
-};
-
-
-ref <IMAPstructure> IMAPstructure::m_emptyStructure = vmime::create <IMAPstructure>();
-
-
-
-IMAPpart::IMAPpart(ref <IMAPpart> parent, const int number, const IMAPParser::body_type_mpart* mpart)
-	: m_parent(parent), m_header(NULL), m_number(number), m_size(0)
-{
-	m_mediaType = vmime::mediaType
-		("multipart", mpart->media_subtype()->value());
-}
-
-
-IMAPpart::IMAPpart(ref <IMAPpart> parent, const int number, const IMAPParser::body_type_1part* part)
-	: m_parent(parent), m_header(NULL), m_number(number), m_size(0)
-{
-	if (part->body_type_text())
-	{
-		m_mediaType = vmime::mediaType
-			("text", part->body_type_text()->
-				media_text()->media_subtype()->value());
-
-		m_size = part->body_type_text()->body_fields()->body_fld_octets()->value();
-	}
-	else if (part->body_type_msg())
-	{
-		m_mediaType = vmime::mediaType
-			("message", part->body_type_msg()->
-				media_message()->media_subtype()->value());
-	}
-	else
-	{
-		m_mediaType = vmime::mediaType
-			(part->body_type_basic()->media_basic()->media_type()->value(),
-			 part->body_type_basic()->media_basic()->media_subtype()->value());
-
-		m_size = part->body_type_basic()->body_fields()->body_fld_octets()->value();
-	}
-
-	m_structure = NULL;
-}
-
-
-ref <const structure> IMAPpart::getStructure() const
-{
-	if (m_structure != NULL)
-		return (m_structure);
-	else
-		return (IMAPstructure::emptyStructure());
-}
-
-
-ref <structure> IMAPpart::getStructure()
-{
-	if (m_structure != NULL)
-		return (m_structure);
-	else
-		return (IMAPstructure::emptyStructure());
-}
-
-
-
 #ifndef VMIME_BUILDING_DOC
 
 //
@@ -400,7 +211,22 @@
 
 	extract(p, ossAdapter, NULL, 0, -1, true, true);
 
-	p.dynamicCast <IMAPpart>()->getOrCreateHeader().parse(oss.str());
+	p.dynamicCast <IMAPPart>()->getOrCreateHeader().parse(oss.str());
+}
+
+
+void IMAPMessage::fetchPartHeaderForStructure(ref <structure> str)
+{
+	for (int i = 0, n = str->getPartCount() ; i < n ; ++i)
+	{
+		ref <class part> part = str->getPartAt(i);
+
+		// Fetch header of current part
+		fetchPartHeader(part);
+
+		// Fetch header of sub-parts
+		fetchPartHeaderForStructure(part->getStructure());
+	}
 }
 
 
@@ -418,7 +244,7 @@
 
 	if (p != NULL)
 	{
-		ref <const IMAPpart> currentPart = p.dynamicCast <const IMAPpart>();
+		ref <const IMAPPart> currentPart = p.dynamicCast <const IMAPPart>();
 		std::vector <int> numbers;
 
 		numbers.push_back(currentPart->getNumber());
@@ -446,8 +272,17 @@
 	command << "FETCH " << m_num << " BODY";
 	if (peek) command << ".PEEK";
 	command << "[";
-	command << section.str();
-	if (headerOnly) command << ".MIME";   // "MIME" not "HEADER" for parts
+
+	if (section.str().empty() && headerOnly)
+	{
+		command << "HEADER";
+	}
+	else
+	{
+		command << section.str();
+		if (headerOnly) command << ".MIME";   // "MIME" not "HEADER" for parts
+	}
+
 	command << "]";
 
 	if (start != 0 || length != -1)
@@ -621,7 +456,7 @@
 		}
 		case IMAPParser::msg_att_item::BODY_STRUCTURE:
 		{
-			m_structure = vmime::create <IMAPstructure>((*it)->body());
+			m_structure = vmime::create <IMAPStructure>((*it)->body());
 			break;
 		}
 		case IMAPParser::msg_att_item::RFC822_HEADER:
@@ -796,6 +631,80 @@
 }
 
 
+void IMAPMessage::constructParsedMessage(ref <bodyPart> parentPart, ref <structure> str, int level)
+{
+	if (level == 0)
+	{
+		ref <class part> part = str->getPartAt(0);
+
+		// Copy header
+		ref <const header> hdr = part->getHeader();
+		parentPart->getHeader()->copyFrom(*hdr);
+
+		// Initialize body
+		parentPart->getBody()->setContents
+			(vmime::create <IMAPMessagePartContentHandler>
+				(thisRef().dynamicCast <IMAPMessage>(),
+				 part, parentPart->getBody()->getEncoding()));
+
+		constructParsedMessage(parentPart, part->getStructure(), 1);
+	}
+	else
+	{
+		for (int i = 0, n = str->getPartCount() ; i < n ; ++i)
+		{
+			ref <class part> part = str->getPartAt(i);
+
+			ref <bodyPart> childPart = vmime::create <bodyPart>();
+
+			// Copy header
+			ref <const header> hdr = part->getHeader();
+			childPart->getHeader()->copyFrom(*hdr);
+
+			// Initialize body
+			childPart->getBody()->setContents
+				(vmime::create <IMAPMessagePartContentHandler>
+					(thisRef().dynamicCast <IMAPMessage>(),
+					 part, childPart->getBody()->getEncoding()));
+
+			// Add child part
+			parentPart->getBody()->appendPart(childPart);
+
+			// Construct sub parts
+			constructParsedMessage(childPart, part->getStructure(), ++level);
+		}
+	}
+}
+
+
+ref <vmime::message> IMAPMessage::getParsedMessage()
+{
+	// Fetch structure
+	ref <structure> structure = NULL;
+
+	try
+	{
+		structure = getStructure();
+	}
+	catch (exceptions::unfetched_object&)
+	{
+		fetch(m_folder.acquire(), IMAPFolder::FETCH_STRUCTURE);
+		structure = getStructure();
+	}
+
+	// Fetch header for each part
+	fetchPartHeaderForStructure(structure);
+
+	// Construct message from structure
+	ref <vmime::message> msg = vmime::create <vmime::message>();
+
+	constructParsedMessage(msg, structure);
+
+	return msg;
+}
+
+
 } // imap
 } // net
 } // vmime
+
diff -urN a/src/net/imap/IMAPMessagePartContentHandler.cpp b/src/net/imap/IMAPMessagePartContentHandler.cpp
--- a/src/net/imap/IMAPMessagePartContentHandler.cpp	1970-01-01 01:00:00.000000000 +0100
+++ b/src/net/imap/IMAPMessagePartContentHandler.cpp	2010-05-21 09:07:53.363928193 +0200
@@ -0,0 +1,179 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2009 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/net/imap/IMAPMessagePartContentHandler.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPMessagePartContentHandler::IMAPMessagePartContentHandler
+	(ref <IMAPMessage> msg, ref <class part> part, const vmime::encoding& encoding)
+	: m_message(msg), m_part(part), m_encoding(encoding)
+{
+}
+
+
+ref <contentHandler> IMAPMessagePartContentHandler::clone() const
+{
+	return create <IMAPMessagePartContentHandler>
+		(m_message.acquire().constCast <IMAPMessage>(),
+		 m_part.acquire().constCast <part>(),
+		 m_encoding);
+}
+
+
+void IMAPMessagePartContentHandler::generate
+	(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength) const
+{
+	ref <IMAPMessage> msg = m_message.acquire().constCast <IMAPMessage>();
+	ref <part> part = m_part.acquire().constCast <class part>();
+
+	// Data is already encoded
+	if (isEncoded())
+	{
+		// The data is already encoded but the encoding specified for
+		// the generation is different from the current one. We need
+		// to re-encode data: decode from input buffer to temporary
+		// buffer, and then re-encode to output stream...
+		if (m_encoding != enc)
+		{
+			// Extract part contents to temporary buffer
+			std::ostringstream oss;
+			utility::outputStreamAdapter tmp(oss);
+
+			msg->extractPart(part, tmp, NULL);
+
+			// Decode to another temporary buffer
+			utility::inputStreamStringProxyAdapter in(oss.str());
+
+			std::ostringstream oss2;
+			utility::outputStreamAdapter tmp2(oss2);
+
+			ref <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
+			theDecoder->decode(in, tmp2);
+
+			// Reencode to output stream
+			string str = oss2.str();
+			utility::inputStreamStringAdapter tempIn(str);
+
+			ref <utility::encoder::encoder> theEncoder = enc.getEncoder();
+			theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+			theEncoder->encode(tempIn, os);
+		}
+		// No encoding to perform
+		else
+		{
+			msg->extractPart(part, os);
+		}
+	}
+	// Need to encode data before
+	else
+	{
+		// Extract part contents to temporary buffer
+		std::ostringstream oss;
+		utility::outputStreamAdapter tmp(oss);
+
+		msg->extractPart(part, tmp, NULL);
+
+		// Encode temporary buffer to output stream
+		ref <utility::encoder::encoder> theEncoder = enc.getEncoder();
+		theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+
+		utility::inputStreamStringAdapter is(oss.str());
+
+		theEncoder->encode(is, os);
+	}
+}
+
+
+void IMAPMessagePartContentHandler::extract
+	(utility::outputStream& os, utility::progressListener* progress) const
+{
+	ref <IMAPMessage> msg = m_message.acquire().constCast <IMAPMessage>();
+	ref <part> part = m_part.acquire().constCast <class part>();
+
+	// No decoding to perform
+	if (!isEncoded())
+	{
+		msg->extractPart(part, os, progress);
+	}
+	// Need to decode data
+	else
+	{
+		// Extract part contents to temporary buffer
+		std::ostringstream oss;
+		utility::outputStreamAdapter tmp(oss);
+
+		msg->extractPart(part, tmp, NULL);
+
+		// Encode temporary buffer to output stream
+		utility::inputStreamStringAdapter is(oss.str());
+		utility::progressListenerSizeAdapter plsa(progress, getLength());
+
+		ref <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
+		theDecoder->decode(is, os, &plsa);
+	}
+}
+
+
+void IMAPMessagePartContentHandler::extractRaw
+	(utility::outputStream& os, utility::progressListener* progress) const
+{
+	ref <IMAPMessage> msg = m_message.acquire().constCast <IMAPMessage>();
+	ref <part> part = m_part.acquire().constCast <class part>();
+
+	msg->extractPart(part, os, progress);
+}
+
+
+string::size_type IMAPMessagePartContentHandler::getLength() const
+{
+	return m_part.acquire()->getSize();
+}
+
+
+bool IMAPMessagePartContentHandler::isEncoded() const
+{
+	return m_encoding != NO_ENCODING;
+}
+
+
+const vmime::encoding& IMAPMessagePartContentHandler::getEncoding() const
+{
+	return m_encoding;
+}
+
+
+bool IMAPMessagePartContentHandler::isEmpty() const
+{
+	return getLength() == 0;
+}
+
+
+} // imap
+} // net
+} // vmime
+
diff -urN a/src/net/imap/IMAPPart.cpp b/src/net/imap/IMAPPart.cpp
--- a/src/net/imap/IMAPPart.cpp	1970-01-01 01:00:00.000000000 +0100
+++ b/src/net/imap/IMAPPart.cpp	2010-05-21 09:07:53.367948000 +0200
@@ -0,0 +1,152 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2009 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/net/imap/IMAPPart.hpp"
+#include "vmime/net/imap/IMAPStructure.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPPart::IMAPPart(ref <IMAPPart> parent, const int number, const IMAPParser::body_type_mpart* mpart)
+	: m_parent(parent), m_header(NULL), m_number(number), m_size(0)
+{
+	m_mediaType = vmime::mediaType
+		("multipart", mpart->media_subtype()->value());
+}
+
+
+IMAPPart::IMAPPart(ref <IMAPPart> parent, const int number, const IMAPParser::body_type_1part* part)
+	: m_parent(parent), m_header(NULL), m_number(number), m_size(0)
+{
+	if (part->body_type_text())
+	{
+		m_mediaType = vmime::mediaType
+			("text", part->body_type_text()->
+				media_text()->media_subtype()->value());
+
+		m_size = part->body_type_text()->body_fields()->body_fld_octets()->value();
+	}
+	else if (part->body_type_msg())
+	{
+		m_mediaType = vmime::mediaType
+			("message", part->body_type_msg()->
+				media_message()->media_subtype()->value());
+	}
+	else
+	{
+		m_mediaType = vmime::mediaType
+			(part->body_type_basic()->media_basic()->media_type()->value(),
+			 part->body_type_basic()->media_basic()->media_subtype()->value());
+
+		m_size = part->body_type_basic()->body_fields()->body_fld_octets()->value();
+	}
+
+	m_structure = NULL;
+}
+
+
+ref <const structure> IMAPPart::getStructure() const
+{
+	if (m_structure != NULL)
+		return m_structure;
+	else
+		return IMAPStructure::emptyStructure();
+}
+
+
+ref <structure> IMAPPart::getStructure()
+{
+	if (m_structure != NULL)
+		return m_structure;
+	else
+		return IMAPStructure::emptyStructure();
+}
+
+
+ref <const IMAPPart> IMAPPart::getParent() const
+{
+	return m_parent.acquire();
+}
+
+
+const mediaType& IMAPPart::getType() const
+{
+	return m_mediaType;
+}
+
+
+int IMAPPart::getSize() const
+{
+	return m_size;
+}
+
+
+int IMAPPart::getNumber() const
+{
+	return m_number;
+}
+
+
+ref <const header> IMAPPart::getHeader() const
+{
+	if (m_header == NULL)
+		throw exceptions::unfetched_object();
+	else
+		return m_header;
+}
+
+
+// static
+ref <IMAPPart> IMAPPart::create
+	(ref <IMAPPart> parent, const int number, const IMAPParser::body* body)
+{
+	if (body->body_type_mpart())
+	{
+		ref <IMAPPart> part = vmime::create <IMAPPart>(parent, number, body->body_type_mpart());
+		part->m_structure = vmime::create <IMAPStructure>(part, body->body_type_mpart()->list());
+
+		return part;
+	}
+	else
+	{
+		return vmime::create <IMAPPart>(parent, number, body->body_type_1part());
+	}
+}
+
+
+header& IMAPPart::getOrCreateHeader()
+{
+	if (m_header != NULL)
+		return *m_header;
+	else
+		return *(m_header = vmime::create <header>());
+}
+
+
+} // imap
+} // net
+} // vmime
+
diff -urN a/src/net/imap/IMAPStructure.cpp b/src/net/imap/IMAPStructure.cpp
--- a/src/net/imap/IMAPStructure.cpp	1970-01-01 01:00:00.000000000 +0100
+++ b/src/net/imap/IMAPStructure.cpp	2010-05-21 09:07:53.363928193 +0200
@@ -0,0 +1,85 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2009 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/net/imap/IMAPStructure.hpp"
+#include "vmime/net/imap/IMAPPart.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPStructure::IMAPStructure()
+{
+}
+
+
+IMAPStructure::IMAPStructure(const IMAPParser::body* body)
+{
+	m_parts.push_back(IMAPPart::create(NULL, 0, body));
+}
+
+
+IMAPStructure::IMAPStructure(ref <IMAPPart> parent, const std::vector <IMAPParser::body*>& list)
+{
+	int number = 0;
+
+	for (std::vector <IMAPParser::body*>::const_iterator
+	     it = list.begin() ; it != list.end() ; ++it, ++number)
+	{
+		m_parts.push_back(IMAPPart::create(parent, number, *it));
+	}
+}
+
+
+ref <const part> IMAPStructure::getPartAt(const int x) const
+{
+	return m_parts[x];
+}
+
+
+ref <part> IMAPStructure::getPartAt(const int x)
+{
+	return m_parts[x];
+}
+
+
+int IMAPStructure::getPartCount() const
+{
+	return m_parts.size();
+}
+
+
+// static
+ref <IMAPStructure> IMAPStructure::emptyStructure()
+{
+	static ref <IMAPStructure> emptyStructure = vmime::create <IMAPStructure>();
+	return emptyStructure;
+}
+
+
+} // imap
+} // net
+} // vmime
+
diff -urN a/src/net/maildir/maildirMessage.cpp b/src/net/maildir/maildirMessage.cpp
--- a/src/net/maildir/maildirMessage.cpp	2010-05-21 09:06:26.988432541 +0200
+++ b/src/net/maildir/maildirMessage.cpp	2010-05-21 09:07:53.363928193 +0200
@@ -524,6 +524,20 @@
 }
 
 
+ref <vmime::message> maildirMessage::getParsedMessage()
+{
+	std::ostringstream oss;
+	utility::outputStreamAdapter os(oss);
+
+	extract(os);
+
+	vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
+	msg->parse(oss.str());
+
+	return msg;
+}
+
+
 } // maildir
 } // net
 } // vmime
diff -urN a/src/net/pop3/POP3Message.cpp b/src/net/pop3/POP3Message.cpp
--- a/src/net/pop3/POP3Message.cpp	2010-05-21 09:06:26.991933216 +0200
+++ b/src/net/pop3/POP3Message.cpp	2010-05-21 09:07:53.363928193 +0200
@@ -218,6 +218,20 @@
 }
 
 
+ref <vmime::message> POP3Message::getParsedMessage()
+{
+	std::ostringstream oss;
+	utility::outputStreamAdapter os(oss);
+
+	extract(os);
+
+	vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
+	msg->parse(oss.str());
+
+	return msg;
+}
+
+
 } // pop3
 } // net
 } // vmime
diff -urN a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp
--- a/src/net/tls/TLSSession.cpp	2010-05-21 09:06:26.999930787 +0200
+++ b/src/net/tls/TLSSession.cpp	2010-05-21 09:07:53.367948000 +0200
@@ -27,6 +27,7 @@
 #include "vmime/config.hpp"
 
 #if VMIME_HAVE_PTHREAD
+#	include <pthread.h>
 #	include <gcrypt.h>
 #	include <errno.h>
 #endif // VMIME_HAVE_PTHREAD
diff -urN a/src/security/digest/sha1/sha1MessageDigest.cpp b/src/security/digest/sha1/sha1MessageDigest.cpp
--- a/src/security/digest/sha1/sha1MessageDigest.cpp	2010-05-21 09:06:27.012432100 +0200
+++ b/src/security/digest/sha1/sha1MessageDigest.cpp	2010-05-21 09:07:53.367948000 +0200
@@ -135,7 +135,7 @@
 
 void sha1MessageDigest::finalize()
 {
-	unsigned long i, j;
+	unsigned int i, j;
 	unsigned char finalcount[8];
 
 	for (i = 0 ; i < 8 ; i++)
@@ -162,8 +162,8 @@
 	i = j = 0;
 
 	std::memset(m_buffer, 0, 64);
-	std::memset(m_state, 0, 5 * sizeof(unsigned long));
-	std::memset(m_count, 0, 2 * sizeof(unsigned long));
+	std::memset(m_state, 0, 5 * sizeof(unsigned int));
+	std::memset(m_count, 0, 2 * sizeof(unsigned int));
 	std::memset(&finalcount, 0, 8);
 }
 
@@ -192,17 +192,17 @@
   * This is the core of the algorithm.
   */
 void sha1MessageDigest::transform
-	(unsigned long state[5], const unsigned char buffer[64])
+	(unsigned int state[5], const unsigned char buffer[64])
 {
-	unsigned long a, b, c, d, e;
+	unsigned int a, b, c, d, e;
 
 	typedef union
 	{
 		unsigned char c[64];
-		unsigned long l[16];
+		unsigned int l[16];
 	} CHAR64LONG16;
 
-	assert(sizeof(unsigned long) == 4);
+	assert(sizeof(unsigned int) == 4);
 
 	CHAR64LONG16* block;
 	static unsigned char workspace[64];
diff -urN a/vmime/bodyPart.hpp b/vmime/bodyPart.hpp
--- a/vmime/bodyPart.hpp	2010-05-21 09:06:27.043934681 +0200
+++ b/vmime/bodyPart.hpp	2010-05-21 09:07:53.375934467 +0200
@@ -46,6 +46,7 @@
 public:
 
 	bodyPart();
+	bodyPart(weak_ref <vmime::bodyPart> parentPart);
 
 	/** Return the header section of this part.
 	  *
diff -urN a/vmime/contentHandler.hpp b/vmime/contentHandler.hpp
--- a/vmime/contentHandler.hpp	2010-05-21 09:06:27.043934681 +0200
+++ b/vmime/contentHandler.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -87,7 +87,8 @@
 	virtual void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const = 0;
 
 	/** Returns the actual length of data. WARNING: this can return 0 if no
-	  * length was specified when setting data of this object.
+	  * length was specified when setting data of this object, or if the
+	  * length is not known).
 	  *
 	  * @return length of data
 	  */
diff -urN a/vmime/net/imap/IMAPMessage.hpp b/vmime/net/imap/IMAPMessage.hpp
--- a/vmime/net/imap/IMAPMessage.hpp	2010-05-21 09:06:27.060431845 +0200
+++ b/vmime/net/imap/IMAPMessage.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -28,6 +28,8 @@
 #include "vmime/net/message.hpp"
 #include "vmime/net/folder.hpp"
 
+#include "vmime/net/imap/IMAPParser.hpp"
+
 
 namespace vmime {
 namespace net {
@@ -75,12 +77,29 @@
 
 	void fetchPartHeader(ref <part> p);
 
+	ref <vmime::message> getParsedMessage();
+
 private:
 
 	void fetch(ref <IMAPFolder> folder, const int options);
 
 	void processFetchResponse(const int options, const IMAPParser::msg_att* msgAtt);
 
+	/** Recursively fetch part header for all parts in the structure.
+	  *
+	  * @param str structure for which to fetch parts headers
+	  */
+	void fetchPartHeaderForStructure(ref <structure> str);
+
+	/** Recursively contruct parsed message from structure.
+	  * Called by getParsedMessage().
+	  *
+	  * @param parentPart root body part (the message)
+	  * @param str structure for which to construct part
+	  * @param level current nesting level (0 is root)
+	  */
+	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;
 
 
diff -urN a/vmime/net/imap/IMAPMessagePartContentHandler.hpp b/vmime/net/imap/IMAPMessagePartContentHandler.hpp
--- a/vmime/net/imap/IMAPMessagePartContentHandler.hpp	1970-01-01 01:00:00.000000000 +0100
+++ b/vmime/net/imap/IMAPMessagePartContentHandler.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -0,0 +1,73 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2009 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_NET_IMAP_IMAPMESSAGEPARTCONTENTHANDLER_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPMESSAGEPARTCONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/contentHandler.hpp"
+#include "vmime/net/imap/IMAPMessage.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPMessagePartContentHandler : public contentHandler
+{
+public:
+
+	IMAPMessagePartContentHandler(ref <IMAPMessage> msg, ref <class part> part, const vmime::encoding& encoding);
+
+	ref <contentHandler> clone() const;
+
+	void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
+
+	void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const;
+	void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const;
+
+	string::size_type getLength() const;
+
+	bool isEncoded() const;
+
+	const vmime::encoding& getEncoding() const;
+
+	bool isEmpty() const;
+
+private:
+
+	weak_ref <IMAPMessage> m_message;
+	weak_ref <part> m_part;
+
+	vmime::encoding m_encoding;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_NET_IMAP_IMAPMESSAGEPARTCONTENTHANDLER_HPP_INCLUDED
+
diff -urN a/vmime/net/imap/IMAPPart.hpp b/vmime/net/imap/IMAPPart.hpp
--- a/vmime/net/imap/IMAPPart.hpp	1970-01-01 01:00:00.000000000 +0100
+++ b/vmime/net/imap/IMAPPart.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -0,0 +1,88 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2009 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_NET_IMAP_IMAPPART_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPPART_HPP_INCLUDED
+
+
+#include "vmime/net/message.hpp"
+
+#include "vmime/net/imap/IMAPParser.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPStructure;
+
+
+class IMAPPart : public part
+{
+private:
+
+	friend class vmime::creator;
+
+	IMAPPart(ref <IMAPPart> parent, const int number, const IMAPParser::body_type_mpart* mpart);
+	IMAPPart(ref <IMAPPart> parent, const int number, const IMAPParser::body_type_1part* part);
+
+public:
+
+	ref <const structure> getStructure() const;
+	ref <structure> getStructure();
+
+	ref <const IMAPPart> getParent() const;
+
+	const mediaType& getType() const;
+	int getSize() const;
+	int getNumber() const;
+
+	ref <const header> getHeader() const;
+
+
+	static ref <IMAPPart> create
+		(ref <IMAPPart> parent, const int number, const IMAPParser::body* body);
+
+
+	header& getOrCreateHeader();
+
+private:
+
+	ref <IMAPStructure> m_structure;
+	weak_ref <IMAPPart> m_parent;
+	ref <header> m_header;
+
+	int m_number;
+	int m_size;
+	mediaType m_mediaType;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_NET_IMAP_IMAPPART_HPP_INCLUDED
+
diff -urN a/vmime/net/imap/IMAPStructure.hpp b/vmime/net/imap/IMAPStructure.hpp
--- a/vmime/net/imap/IMAPStructure.hpp	1970-01-01 01:00:00.000000000 +0100
+++ b/vmime/net/imap/IMAPStructure.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -0,0 +1,67 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2009 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_NET_IMAP_IMAPSTRUCTURE_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPSTRUCTURE_HPP_INCLUDED
+
+
+#include "vmime/net/message.hpp"
+
+#include "vmime/net/imap/IMAPParser.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPPart;
+
+
+class IMAPStructure : public structure
+{
+public:
+
+	IMAPStructure();
+	IMAPStructure(const IMAPParser::body* body);
+	IMAPStructure(ref <IMAPPart> parent, const std::vector <IMAPParser::body*>& list);
+
+	ref <const part> getPartAt(const int x) const;
+	ref <part> getPartAt(const int x);
+	int getPartCount() const;
+
+	static ref <IMAPStructure> emptyStructure();
+
+private:
+
+	std::vector <ref <IMAPPart> > m_parts;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_NET_IMAP_IMAPSTRUCTURE_HPP_INCLUDED
+
diff -urN a/vmime/net/maildir/maildirMessage.hpp b/vmime/net/maildir/maildirMessage.hpp
--- a/vmime/net/maildir/maildirMessage.hpp	2010-05-21 09:06:27.064432936 +0200
+++ b/vmime/net/maildir/maildirMessage.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -75,6 +75,8 @@
 
 	void fetchPartHeader(ref <part> p);
 
+	ref <vmime::message> getParsedMessage();
+
 private:
 
 	void fetch(ref <maildirFolder> folder, const int options);
diff -urN a/vmime/net/message.hpp b/vmime/net/message.hpp
--- a/vmime/net/message.hpp	2010-05-21 09:06:27.067930607 +0200
+++ b/vmime/net/message.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -31,6 +31,8 @@
 #include "vmime/utility/progressListener.hpp"
 #include "vmime/utility/stream.hpp"
 
+#include "vmime/message.hpp"
+
 
 namespace vmime {
 namespace net {
@@ -286,6 +288,16 @@
 	  * @param p the part for which to fetch the header
 	  */
 	virtual void fetchPartHeader(ref <part> p) = 0;
+
+	/** Get the RFC-822 message for this abstract message.
+	  * Warning: This may require getting some data (ie: structure and headers) from
+	  * the server, which is done automatically. Actual message contents (ie: body)
+	  * will not be fetched if possible (IMAP allows it, whereas POP3 will require
+	  * to fetch the whole message).
+	  *
+	  * @return a RFC-822-parsed message
+	  */
+	virtual ref <vmime::message> getParsedMessage() = 0;
 };
 
 
diff -urN a/vmime/net/pop3/POP3Message.hpp b/vmime/net/pop3/POP3Message.hpp
--- a/vmime/net/pop3/POP3Message.hpp	2010-05-21 09:06:27.067930607 +0200
+++ b/vmime/net/pop3/POP3Message.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -77,6 +77,8 @@
 
 	void fetchPartHeader(ref <part> p);
 
+	ref <vmime::message> getParsedMessage();
+
 private:
 
 	void fetch(ref <POP3Folder> folder, const int options);
diff -urN a/vmime/security/digest/sha1/sha1MessageDigest.hpp b/vmime/security/digest/sha1/sha1MessageDigest.hpp
--- a/vmime/security/digest/sha1/sha1MessageDigest.hpp	2010-05-21 09:06:27.088435636 +0200
+++ b/vmime/security/digest/sha1/sha1MessageDigest.hpp	2010-05-21 09:07:53.371933656 +0200
@@ -59,10 +59,10 @@
 
 	void init();
 
-	static void transform(unsigned long state[5], const byte_t buffer[64]);
+	static void transform(unsigned int state[5], const byte_t buffer[64]);
 
-	unsigned long m_state[5];
-	unsigned long m_count[2];
+	unsigned int m_state[5];
+	unsigned int m_count[2];
 	byte_t m_buffer[64];
 
 	byte_t m_digest[20];