File 15-vmime-wrongly-padded-B64-words.diff of Package libvmime_zarafa7

---
 src/word.cpp   |   60 ++++++++++++++++++++++++++++++++++++++++++---------------
 vmime/word.hpp |   23 ++++++++++++++++++++-
 2 files changed, 67 insertions(+), 16 deletions(-)

Index: vmime/src/word.cpp
===================================================================
--- vmime.orig/src/word.cpp
+++ vmime/src/word.cpp
@@ -64,8 +64,7 @@ word::word(const string& buffer, const c
 
 
 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;
 
@@ -121,7 +120,7 @@ ref <word> word::parseNext(const string&
 
 			if (!unencoded.empty())
 			{
-				if (prevIsEncoded)
+				if (state->prevIsEncoded && !state->isFirst)
 					unencoded = whiteSpaces + unencoded;
 
 				ref <word> w = vmime::create <word>(unencoded, charset(charsets::US_ASCII));
@@ -130,8 +129,8 @@ ref <word> word::parseNext(const string&
 				if (newPosition)
 					*newPosition = pos;
 
-				if (isEncoded)
-					*isEncoded = false;
+				state->prevIsEncoded = false;
+				state->isFirst = false;
 
 				return (w);
 			}
@@ -182,13 +181,13 @@ ref <word> word::parseNext(const string&
 			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);
 		}
@@ -196,7 +195,7 @@ ref <word> word::parseNext(const string&
 		++pos;
 	}
 
-	if (startPos != end && !isFirst && prevIsEncoded)
+	if (startPos != end && !state->isFirst && state->prevIsEncoded)
 		unencoded += whiteSpaces;
 
 	if (startPos != end)
@@ -211,8 +210,8 @@ ref <word> word::parseNext(const string&
 		if (newPosition)
 			*newPosition = end;
 
-		if (isEncoded)
-			*isEncoded = false;
+		state->prevIsEncoded = false;
+		state->isFirst = false;
 
 		return (w);
 	}
@@ -229,9 +228,9 @@ const std::vector <ref <word> > word::pa
 
 	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)
@@ -244,6 +243,14 @@ const std::vector <ref <word> > word::pa
 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] == '?')
 	{
@@ -290,12 +297,20 @@ void word::parse(const string& buffer, c
 					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;
@@ -306,6 +321,21 @@ void word::parse(const string& buffer, c
 						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;
 					}
 				}
Index: vmime/vmime/word.hpp
===================================================================
--- vmime.orig/vmime/word.hpp
+++ vmime/vmime/word.hpp
@@ -125,6 +125,20 @@ public:
 		bool prevWordIsEncoded;
 		bool lastCharIsSpace;
 	};
+
+	class parserState
+	{
+	public:
+
+		parserState()
+			: prevIsEncoded(false), isFirst(true)
+		{
+		}
+
+		bool prevIsEncoded;
+		bool isFirst;
+		std::string undecodedBytes;
+	};
 #endif
 
 
@@ -134,13 +148,20 @@ public:
 	void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
 	void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
 
+       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);
 
openSUSE Build Service is sponsored by