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);