Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:42.2
libvmime_zarafa7
15-vmime-wrongly-padded-B64-words.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
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);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor