[c5c522c] | 1 | diff -urb libvmime-0.9.2-patched/src/word.cpp libvmime-0.9.2/src/word.cpp |
---|
| 2 | --- libvmime-0.9.2-patched/src/word.cpp 2015-01-16 15:04:04.124264216 +0100 |
---|
| 3 | +++ libvmime-0.9.2/src/word.cpp 2015-01-16 15:05:13.672262038 +0100 |
---|
| 4 | @@ -64,8 +64,7 @@ |
---|
| 5 | |
---|
| 6 | |
---|
| 7 | ref <word> word::parseNext(const string& buffer, const string::size_type position, |
---|
| 8 | - const string::size_type end, string::size_type* newPosition, |
---|
| 9 | - bool prevIsEncoded, bool* isEncoded, bool isFirst) |
---|
| 10 | + const string::size_type end, string::size_type* newPosition, parserState* state) |
---|
| 11 | { |
---|
| 12 | string::size_type pos = position; |
---|
| 13 | |
---|
| 14 | @@ -120,7 +119,7 @@ |
---|
| 15 | |
---|
| 16 | if (!unencoded.empty()) |
---|
| 17 | { |
---|
| 18 | - if (prevIsEncoded) |
---|
| 19 | + if (state->prevIsEncoded && !state->isFirst) |
---|
| 20 | unencoded = whiteSpaces + unencoded; |
---|
| 21 | |
---|
| 22 | ref <word> w = vmime::create <word>(unencoded, charset(charsets::US_ASCII)); |
---|
| 23 | @@ -129,8 +128,8 @@ |
---|
| 24 | if (newPosition) |
---|
| 25 | *newPosition = pos; |
---|
| 26 | |
---|
| 27 | - if (isEncoded) |
---|
| 28 | - *isEncoded = false; |
---|
| 29 | + state->prevIsEncoded = false; |
---|
| 30 | + state->isFirst = false; |
---|
| 31 | |
---|
| 32 | return (w); |
---|
| 33 | } |
---|
| 34 | @@ -181,13 +180,13 @@ |
---|
| 35 | pos += 2; // ?= |
---|
| 36 | |
---|
| 37 | ref <word> w = vmime::create <word>(); |
---|
| 38 | - w->parse(buffer, wordStart, pos, NULL); |
---|
| 39 | + w->parseWithState(buffer, wordStart, pos, NULL, state); |
---|
| 40 | |
---|
| 41 | if (newPosition) |
---|
| 42 | *newPosition = pos; |
---|
| 43 | |
---|
| 44 | - if (isEncoded) |
---|
| 45 | - *isEncoded = true; |
---|
| 46 | + state->prevIsEncoded = true; |
---|
| 47 | + state->isFirst = false; |
---|
| 48 | |
---|
| 49 | return (w); |
---|
| 50 | } |
---|
| 51 | @@ -195,7 +194,7 @@ |
---|
| 52 | ++pos; |
---|
| 53 | } |
---|
| 54 | |
---|
| 55 | - if (startPos != end && !isFirst && prevIsEncoded) |
---|
| 56 | + if (startPos != end && !state->isFirst && state->prevIsEncoded) |
---|
| 57 | unencoded += whiteSpaces; |
---|
| 58 | |
---|
| 59 | if (startPos != end) |
---|
| 60 | @@ -210,8 +209,8 @@ |
---|
| 61 | if (newPosition) |
---|
| 62 | *newPosition = end; |
---|
| 63 | |
---|
| 64 | - if (isEncoded) |
---|
| 65 | - *isEncoded = false; |
---|
| 66 | + state->prevIsEncoded = false; |
---|
| 67 | + state->isFirst = false; |
---|
| 68 | |
---|
| 69 | return (w); |
---|
| 70 | } |
---|
| 71 | @@ -228,9 +227,9 @@ |
---|
| 72 | |
---|
| 73 | string::size_type pos = position; |
---|
| 74 | |
---|
| 75 | - bool prevIsEncoded = false; |
---|
| 76 | + parserState state; |
---|
| 77 | |
---|
| 78 | - while ((w = word::parseNext(buffer, pos, end, &pos, prevIsEncoded, &prevIsEncoded, (w == NULL))) != NULL) |
---|
| 79 | + while ((w = word::parseNext(buffer, pos, end, &pos, &state)) != NULL) |
---|
| 80 | res.push_back(w); |
---|
| 81 | |
---|
| 82 | if (newPosition) |
---|
| 83 | @@ -243,6 +242,14 @@ |
---|
| 84 | void word::parse(const string& buffer, const string::size_type position, |
---|
| 85 | const string::size_type end, string::size_type* newPosition) |
---|
| 86 | { |
---|
| 87 | + parseWithState(buffer, position, end, newPosition, NULL); |
---|
| 88 | +} |
---|
| 89 | + |
---|
| 90 | + |
---|
| 91 | +void word::parseWithState |
---|
| 92 | + (const string& buffer, const size_t position, |
---|
| 93 | + const size_t end, size_t* newPosition, parserState* state) |
---|
| 94 | +{ |
---|
| 95 | if (position + 6 < end && // 6 = "=?(.+)?(.*)?=" |
---|
| 96 | buffer[position] == '=' && buffer[position + 1] == '?') |
---|
| 97 | { |
---|
| 98 | @@ -289,12 +296,20 @@ |
---|
| 99 | if (theEncoder) |
---|
| 100 | { |
---|
| 101 | // Decode text |
---|
| 102 | + string encodedBuffer(dataPos, dataEnd); |
---|
| 103 | string decodedBuffer; |
---|
| 104 | |
---|
| 105 | - utility::inputStreamStringAdapter ein(string(dataPos, dataEnd)); |
---|
| 106 | + |
---|
| 107 | + if (state && !state->undecodedBytes.empty()) |
---|
| 108 | + { |
---|
| 109 | + encodedBuffer = state->undecodedBytes + encodedBuffer; |
---|
| 110 | + state->undecodedBytes.clear(); |
---|
| 111 | + } |
---|
| 112 | + |
---|
| 113 | + utility::inputStreamStringAdapter ein(encodedBuffer); |
---|
| 114 | utility::outputStreamStringAdapter eout(decodedBuffer); |
---|
| 115 | |
---|
| 116 | - theEncoder->decode(ein, eout); |
---|
| 117 | + const size_t decodedLen = theEncoder->decode(ein, eout); |
---|
| 118 | delete (theEncoder); |
---|
| 119 | |
---|
| 120 | m_buffer = decodedBuffer; |
---|
| 121 | @@ -305,6 +320,21 @@ |
---|
| 122 | if (newPosition) |
---|
| 123 | *newPosition = (p - buffer.begin()); |
---|
| 124 | |
---|
| 125 | + // For Base64 encoding, ensure all bytes have been decoded. |
---|
| 126 | + // If there are remaining bytes, keep them for the next run. |
---|
| 127 | + // |
---|
| 128 | + // This allows decoding some insanities like: |
---|
| 129 | + // =?utf-8?B?5Lit5?= =?utf-8?B?paH?= |
---|
| 130 | + if (*encPos == 'B' || *encPos == 'b') |
---|
| 131 | + { |
---|
| 132 | + const size_t actualEncodedLen = encodedBuffer.length(); |
---|
| 133 | + const size_t theoricalEncodedLen = |
---|
| 134 | + ((decodedLen + ((decodedLen % 3) ? (3 - (decodedLen % 3)) : 0) ) / 3) * 4; |
---|
| 135 | + |
---|
| 136 | + if (state && actualEncodedLen != theoricalEncodedLen) |
---|
| 137 | + state->undecodedBytes.assign(dataPos + theoricalEncodedLen, dataEnd); |
---|
| 138 | + } |
---|
| 139 | + |
---|
| 140 | return; |
---|
| 141 | } |
---|
| 142 | } |
---|
| 143 | diff -urb libvmime-0.9.2-patched/vmime/word.hpp libvmime-0.9.2/vmime/word.hpp |
---|
| 144 | --- libvmime-0.9.2-patched/vmime/word.hpp 2015-01-16 15:04:04.128264216 +0100 |
---|
| 145 | +++ libvmime-0.9.2/vmime/word.hpp 2015-01-16 15:05:13.672262038 +0100 |
---|
| 146 | @@ -125,6 +125,20 @@ |
---|
| 147 | bool prevWordIsEncoded; |
---|
| 148 | bool lastCharIsSpace; |
---|
| 149 | }; |
---|
| 150 | + |
---|
| 151 | + class parserState |
---|
| 152 | + { |
---|
| 153 | + public: |
---|
| 154 | + |
---|
| 155 | + parserState() |
---|
| 156 | + : prevIsEncoded(false), isFirst(true) |
---|
| 157 | + { |
---|
| 158 | + } |
---|
| 159 | + |
---|
| 160 | + bool prevIsEncoded; |
---|
| 161 | + bool isFirst; |
---|
| 162 | + std::string undecodedBytes; |
---|
| 163 | + }; |
---|
| 164 | #endif |
---|
| 165 | |
---|
| 166 | |
---|
| 167 | @@ -134,13 +148,20 @@ |
---|
| 168 | void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL); |
---|
| 169 | void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const; |
---|
| 170 | |
---|
| 171 | + void parseWithState |
---|
| 172 | + (const string& buffer, |
---|
| 173 | + const size_t position, |
---|
| 174 | + const size_t end, |
---|
| 175 | + size_t* newPosition, |
---|
| 176 | + parserState* state); |
---|
| 177 | + |
---|
| 178 | 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; |
---|
| 179 | |
---|
| 180 | const std::vector <ref <const component> > getChildComponents() const; |
---|
| 181 | |
---|
| 182 | private: |
---|
| 183 | |
---|
| 184 | - 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); |
---|
| 185 | + static ref <word> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition, parserState* state); |
---|
| 186 | |
---|
| 187 | static const std::vector <ref <word> > parseMultiple(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition); |
---|
| 188 | |
---|