File vmime-all4debian.diff of Package libvmime_zarafa7

---
 src/base.cpp                           |    2 
 src/constants.cpp                      |    1 
 src/headerField.cpp                    |   21 ++-------
 src/mailboxList.cpp                    |   30 +++++++++++++
 src/parameter.cpp                      |   16 ++++++-
 src/parameterizedHeaderField.cpp       |    6 ++
 src/platforms/posix/posixHandler.cpp   |    6 --
 src/utility/encoder/encoderFactory.cpp |    1 
 src/word.cpp                           |   73 ++++++++++++++++++++++++++-------
 src/wordEncoder.cpp                    |    7 +++
 vmime/address.hpp                      |    1 
 vmime/word.hpp                         |   23 +++++++++-
 13 files changed, 152 insertions(+), 53 deletions(-)

Index: vmime/src/base.cpp
===================================================================
--- vmime.orig/src/base.cpp
+++ vmime/src/base.cpp
@@ -74,7 +74,7 @@ const string libname() { return (VMIME_P
   *
   * @return library version
   */
-const string libversion() { return (VMIME_VERSION " (" __DATE__ " " __TIME__ ")"); }
+const string libversion() { return (VMIME_VERSION " ()"); }
 
 /** Return the library API version (eg: "6:1:6").
   *
Index: vmime/src/constants.cpp
===================================================================
--- vmime.orig/src/constants.cpp
+++ vmime/src/constants.cpp
@@ -80,6 +80,7 @@ namespace encodingTypes
 	const string::value_type* const QUOTED_PRINTABLE = "quoted-printable";
 	const string::value_type* const BINARY = "binary";
 	const string::value_type* const UUENCODE = "uuencode";
+	const string::value_type* const X_UUENCODE = "x-uuencode";
 }
 
 
Index: vmime/src/headerField.cpp
===================================================================
--- vmime.orig/src/headerField.cpp
+++ vmime/src/headerField.cpp
@@ -132,7 +132,9 @@ ref <headerField> headerField::parseNext
 				                  buffer.begin() + nameEnd);
 
 				// Skip ':' character
-				++pos;
+				// Patch: don't just skip one colon, but any and all, if available. NS 2 December 2013
+				while ((pos < end) && (buffer[pos] == ':'))
+				    ++pos;
 
 				// Skip spaces between ':' and the field contents
 				while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t'))
@@ -157,14 +159,12 @@ ref <headerField> headerField::parseNext
 					{
 						contentsEnd = pos;
 						pos += 2;
-						break;
 					}
 					else if (c == '\n')
 					{
 						contentsEnd = pos;
 						++pos;
-						break;
-					}
+					} else {
 
 					while (pos < end)
 					{
@@ -186,24 +186,13 @@ ref <headerField> headerField::parseNext
 
 						++pos;
 					}
+					}
 
 					// Handle the case of folded lines
 					if (buffer[pos] == ' ' || buffer[pos] == '\t')
 					{
 						// This is a folding white-space: we keep it as is and
 						// we continue with contents parsing...
-
-						// If the line contains only space characters, we assume it is
-						// the end of the headers. This is not strictly standard-compliant
-						// but, hey, we can't fail when parsing some malformed mails...
-						while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t'))
-							++pos;
-
-						if ((pos < end && buffer[pos] == '\n') ||
-						    (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] == '\n'))
-						{
-							break;
-						}
 					}
 					else
 					{
Index: vmime/src/mailboxList.cpp
===================================================================
--- vmime.orig/src/mailboxList.cpp
+++ vmime/src/mailboxList.cpp
@@ -22,6 +22,7 @@
 //
 
 #include "vmime/mailboxList.hpp"
+#include "vmime/mailboxGroup.hpp"
 #include "vmime/exception.hpp"
 
 
@@ -199,7 +200,34 @@ const std::vector <ref <const component>
 void mailboxList::parse(const string& buffer, const string::size_type position,
 	const string::size_type end, string::size_type* newPosition)
 {
-	m_list.parse(buffer, position, end, newPosition);
+	string::size_type pos = position;
+
+	while (pos < end)
+	{
+		ref <address> parsedAddress = address::parseNext(buffer, pos, end, &pos);
+
+		if (parsedAddress != NULL)
+		{
+			if (parsedAddress->isGroup())
+			{
+				ref <mailboxGroup> group = parsedAddress.staticCast <mailboxGroup>();
+
+				for (size_t i = 0 ; i < group->getMailboxCount() ; ++i)
+				{
+					m_list.appendAddress(group->getMailboxAt(i));
+				}
+			}
+			else
+			{
+				m_list.appendAddress(parsedAddress);
+			}
+		}
+	}
+
+	setParsedBounds(position, end);
+
+	if (newPosition)
+		*newPosition = end;
 }
 
 
Index: vmime/src/parameter.cpp
===================================================================
--- vmime.orig/src/parameter.cpp
+++ vmime/src/parameter.cpp
@@ -240,7 +240,17 @@ void parameter::parse(const std::vector
 				value << t.getWholeBuffer();
 
 				if (!foundCharsetChunk)
-					ch = t.getWordAt(0)->getCharset();
+					// this is still wrong. each word can have its
+					// own charset, and can be mixed (eg. iso-8859-1
+					// and iso-2022-jp), but very unlikely.
+					// real fix is to have parameters store a
+					// vmime::text instead of a vmime::word in
+					// m_value.  but that changes the interface
+					for (size_t i = 0; i < t.getWordCount(); i++)
+						if (t.getWordAt(i)->getCharset() != ch && ch == charsets::US_ASCII) {
+							ch = t.getWordAt(i)->getCharset();
+							break;
+						}
 			}
 		}
 	}
@@ -390,7 +400,9 @@ void parameter::generate(utility::output
 
 	// Also generate an extended parameter if the value contains 8-bit characters
 	// or is too long for a single line
-	if (extended || cutValue)
+
+	// Disable RFC-2231 header generation. Some email clients have bad reactions to it.
+	if ((extended || cutValue) && false)
 	{
 
 #if VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
Index: vmime/src/parameterizedHeaderField.cpp
===================================================================
--- vmime.orig/src/parameterizedHeaderField.cpp
+++ vmime/src/parameterizedHeaderField.cpp
@@ -97,7 +97,7 @@ void parameterizedHeaderField::parse(con
 	// Advance up to ';', if any
 	string::size_type valueLength = 0;
 
-	while (p < pend && *p != ';')  // FIXME: support ";" inside quoted or RFC-2047-encoded text
+	while (p < pend && *p != ';' && (!parserHelpers::isSpace(*p)))  // FIXME: support ";" inside quoted or RFC-2047-encoded text
 	{
 		++p;
 		++valueLength;
@@ -118,6 +118,10 @@ void parameterizedHeaderField::parse(con
 	{
 		std::map <string, paramInfo> params;
 
+		if (*p != ';')
+			while (p < pend && *p != ';')  // FIXME: support ";" inside quoted or RFC-2047-encoded text
+				++p;
+
 		while (*p == ';')
 		{
 			// Skip ';'
Index: vmime/src/platforms/posix/posixHandler.cpp
===================================================================
--- vmime.orig/src/platforms/posix/posixHandler.cpp
+++ vmime/src/platforms/posix/posixHandler.cpp
@@ -153,11 +153,7 @@ const vmime::charset posixHandler::getLo
 {
 	const PLockHelper lock;
 
-	const char* prevLocale = ::setlocale(LC_ALL, "");
-	vmime::charset ch(::nl_langinfo(CODESET));
-	::setlocale(LC_ALL, prevLocale);
-
-	return (ch);
+	return vmime::charset(::nl_langinfo(CODESET));
 }
 
 
Index: vmime/src/utility/encoder/encoderFactory.cpp
===================================================================
--- vmime.orig/src/utility/encoder/encoderFactory.cpp
+++ vmime/src/utility/encoder/encoderFactory.cpp
@@ -43,6 +43,7 @@ encoderFactory::encoderFactory()
 	registerName <b64Encoder>("base64");
 	registerName <qpEncoder>("quoted-printable");
 	registerName <uuEncoder>("uuencode");
+	registerName <uuEncoder>("x-uuencode");
 	registerName <sevenBitEncoder>("7bit");
 	registerName <eightBitEncoder>("8bit");
 	registerName <binaryEncoder>("binary");
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;
 
@@ -73,11 +72,14 @@ ref <word> word::parseNext(const string&
 	//   - before the first word
 	//   - between two encoded words
 	//   - after the last word
+	// Always ignore newlines
 	string whiteSpaces;
 
 	while (pos < end && parserHelpers::isSpace(buffer[pos]))
 	{
 		whiteSpaces += buffer[pos];
+		if(buffer[pos] != '\r' && buffer[pos] != '\n') // do not include newlines
+			whiteSpaces += buffer[pos];
 		++pos;
 	}
 
@@ -118,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));
@@ -127,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);
 			}
@@ -179,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);
 		}
@@ -193,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)
@@ -208,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);
 	}
@@ -226,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)
@@ -241,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] == '?')
 	{
@@ -287,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;
@@ -303,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;
 					}
 				}
@@ -690,9 +723,19 @@ bool word::operator!=(const word& w) con
 
 const string word::getConvertedText(const charset& dest) const
 {
+        if (dest == m_charset) {
+                return m_buffer;  // no conversion needed
+        }
+
 	string out;
 
+	try {
 	charset::convert(m_buffer, out, m_charset, dest);
+	}
+	catch (vmime::exception &e) {
+		// copy 'word' as text
+		out = m_buffer;
+	}
 
 	return (out);
 }
Index: vmime/src/wordEncoder.cpp
===================================================================
--- vmime.orig/src/wordEncoder.cpp
+++ vmime/src/wordEncoder.cpp
@@ -239,6 +239,13 @@ bool wordEncoder::isEncodingNeeded(const
 	if (buffer.find_first_of("\n\r") != string::npos)
 		return true;
 
+	// If the string contains a QP string, we need to encode this.
+	// Not a 100% check, but we'd only get more encoded strings.
+	std::string::size_type pos = buffer.find("=?");
+	std::string::size_type end = buffer.find("?=");
+	if (pos != string::npos && end != string::npos && end > pos)
+		return true;
+
 	return false;
 }
 
Index: vmime/vmime/address.hpp
===================================================================
--- vmime.orig/vmime/address.hpp
+++ vmime/vmime/address.hpp
@@ -65,7 +65,6 @@ public:
 
 	virtual ref <component> clone() const = 0;
 
-protected:
 
 	/** Parse an address from an input buffer.
 	  *
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