Index: npl/overig/libvmime/vmime-wrongly-padded-B64-words.diff
===================================================================
--- npl/overig/libvmime/vmime-wrongly-padded-B64-words.diff	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
+++ npl/overig/libvmime/vmime-wrongly-padded-B64-words.diff	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
@@ -0,0 +1,188 @@
+diff -urb libvmime-0.9.2-patched/src/word.cpp libvmime-0.9.2/src/word.cpp
+--- libvmime-0.9.2-patched/src/word.cpp	2015-01-16 15:04:04.124264216 +0100
++++ libvmime-0.9.2/src/word.cpp	2015-01-16 15:05:13.672262038 +0100
+@@ -64,8 +64,7 @@
+ 
+ 
+ ref <word> 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)
++	const string::size_type end, string::size_type* newPosition, parserState* state)
+ {
+ 	string::size_type pos = position;
+ 
+@@ -120,7 +119,7 @@
+ 
+ 			if (!unencoded.empty())
+ 			{
+-				if (prevIsEncoded)
++				if (state->prevIsEncoded && !state->isFirst)
+ 					unencoded = whiteSpaces + unencoded;
+ 
+ 				ref <word> w = vmime::create <word>(unencoded, charset(charsets::US_ASCII));
+@@ -129,8 +128,8 @@
+ 				if (newPosition)
+ 					*newPosition = pos;
+ 
+-				if (isEncoded)
+-					*isEncoded = false;
++				state->prevIsEncoded = false;
++				state->isFirst = false;
+ 
+ 				return (w);
+ 			}
+@@ -181,13 +180,13 @@
+ 			pos += 2; // ?=
+ 
+ 			ref <word> w = vmime::create <word>();
+-			w->parse(buffer, wordStart, pos, NULL);
++			w->parseWithState(buffer, wordStart, pos, NULL, state);
+ 
+ 			if (newPosition)
+ 				*newPosition = pos;
+ 
+-			if (isEncoded)
+-				*isEncoded = true;
++			state->prevIsEncoded = true;
++			state->isFirst = false;
+ 
+ 			return (w);
+ 		}
+@@ -195,7 +194,7 @@
+ 		++pos;
+ 	}
+ 
+-	if (startPos != end && !isFirst && prevIsEncoded)
++	if (startPos != end && !state->isFirst && state->prevIsEncoded)
+ 		unencoded += whiteSpaces;
+ 
+ 	if (startPos != end)
+@@ -210,8 +209,8 @@
+ 		if (newPosition)
+ 			*newPosition = end;
+ 
+-		if (isEncoded)
+-			*isEncoded = false;
++		state->prevIsEncoded = false;
++		state->isFirst = false;
+ 
+ 		return (w);
+ 	}
+@@ -228,9 +227,9 @@
+ 
+ 	string::size_type pos = position;
+ 
+-	bool prevIsEncoded = false;
++	parserState state;
+ 
+-	while ((w = word::parseNext(buffer, pos, end, &pos, prevIsEncoded, &prevIsEncoded, (w == NULL))) != NULL)
++	while ((w = word::parseNext(buffer, pos, end, &pos, &state)) != NULL)
+ 		res.push_back(w);
+ 
+ 	if (newPosition)
+@@ -243,6 +242,14 @@
+ void word::parse(const string& buffer, const string::size_type position,
+ 	const string::size_type end, string::size_type* newPosition)
+ {
++	parseWithState(buffer, position, end, newPosition, NULL);
++}
++
++
++void word::parseWithState
++	(const string& buffer, const size_t position,
++	 const size_t end, size_t* newPosition, parserState* state)
++{
+ 	if (position + 6 < end && // 6 = "=?(.+)?(.*)?="
+ 	    buffer[position] == '=' && buffer[position + 1] == '?')
+ 	{
+@@ -289,12 +296,20 @@
+ 					if (theEncoder)
+ 					{
+ 						// Decode text
++						string encodedBuffer(dataPos, dataEnd);
+ 						string decodedBuffer;
+ 
+-						utility::inputStreamStringAdapter ein(string(dataPos, dataEnd));
++
++                                                if (state && !state->undecodedBytes.empty())
++                                                {
++                                                        encodedBuffer = state->undecodedBytes + encodedBuffer;
++                                                        state->undecodedBytes.clear();
++                                                }
++ 
++                                                utility::inputStreamStringAdapter ein(encodedBuffer);
+ 						utility::outputStreamStringAdapter eout(decodedBuffer);
+ 
+-						theEncoder->decode(ein, eout);
++						const size_t decodedLen = theEncoder->decode(ein, eout);
+ 						delete (theEncoder);
+ 
+ 						m_buffer = decodedBuffer;
+@@ -305,6 +320,21 @@
+ 						if (newPosition)
+ 							*newPosition = (p - buffer.begin());
+ 
++						// For Base64 encoding, ensure all bytes have been decoded.
++						// If there are remaining bytes, keep them for the next run.
++						//
++						// This allows decoding some insanities like:
++						//     =?utf-8?B?5Lit5?= =?utf-8?B?paH?=
++						if (*encPos == 'B' || *encPos == 'b')
++						{
++							const size_t actualEncodedLen = encodedBuffer.length();
++							const size_t theoricalEncodedLen =
++								((decodedLen + ((decodedLen % 3) ? (3 - (decodedLen % 3)) : 0) ) / 3) * 4;
++
++							if (state && actualEncodedLen != theoricalEncodedLen)
++								state->undecodedBytes.assign(dataPos + theoricalEncodedLen, dataEnd);
++						}
++
+ 						return;
+ 					}
+ 				}
+diff -urb libvmime-0.9.2-patched/vmime/word.hpp libvmime-0.9.2/vmime/word.hpp
+--- libvmime-0.9.2-patched/vmime/word.hpp	2015-01-16 15:04:04.128264216 +0100
++++ libvmime-0.9.2/vmime/word.hpp	2015-01-16 15:05:13.672262038 +0100
+@@ -125,6 +125,20 @@
+ 		bool prevWordIsEncoded;
+ 		bool lastCharIsSpace;
+ 	};
++
++	class parserState
++	{
++	public:
++
++		parserState()
++			: prevIsEncoded(false), isFirst(true)
++		{
++		}
++
++		bool prevIsEncoded;
++		bool isFirst;
++		std::string undecodedBytes;
++	};
+ #endif
+ 
+ 
+@@ -134,13 +148,20 @@
+ 	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 parseWithState
++               (const string& buffer,
++                const size_t position,
++                const size_t end,
++                size_t* newPosition,
++                parserState* state);
++
+ 	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;
+ 
+ 	const std::vector <ref <const component> > getChildComponents() const;
+ 
+ private:
+ 
+-	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 ref <word> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition, parserState* state);
+ 
+ 	static const std::vector <ref <word> > parseMultiple(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition);
+ 
