source: npl/overig/libvmime/vmime-wrongly-padded-B64-words.diff @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 6.1 KB
  • src/word.cpp

    diff -urb libvmime-0.9.2-patched/src/word.cpp libvmime-0.9.2/src/word.cpp
    old new  
    6464
    6565
    6666ref <word> word::parseNext(const string& buffer, const string::size_type position,
    67         const string::size_type end, string::size_type* newPosition,
    68         bool prevIsEncoded, bool* isEncoded, bool isFirst)
     67        const string::size_type end, string::size_type* newPosition, parserState* state)
    6968{
    7069        string::size_type pos = position;
    7170
     
    120119
    121120                        if (!unencoded.empty())
    122121                        {
    123                                 if (prevIsEncoded)
     122                                if (state->prevIsEncoded && !state->isFirst)
    124123                                        unencoded = whiteSpaces + unencoded;
    125124
    126125                                ref <word> w = vmime::create <word>(unencoded, charset(charsets::US_ASCII));
     
    129128                                if (newPosition)
    130129                                        *newPosition = pos;
    131130
    132                                 if (isEncoded)
    133                                         *isEncoded = false;
     131                                state->prevIsEncoded = false;
     132                                state->isFirst = false;
    134133
    135134                                return (w);
    136135                        }
     
    181180                        pos += 2; // ?=
    182181
    183182                        ref <word> w = vmime::create <word>();
    184                         w->parse(buffer, wordStart, pos, NULL);
     183                        w->parseWithState(buffer, wordStart, pos, NULL, state);
    185184
    186185                        if (newPosition)
    187186                                *newPosition = pos;
    188187
    189                         if (isEncoded)
    190                                 *isEncoded = true;
     188                        state->prevIsEncoded = true;
     189                        state->isFirst = false;
    191190
    192191                        return (w);
    193192                }
     
    195194                ++pos;
    196195        }
    197196
    198         if (startPos != end && !isFirst && prevIsEncoded)
     197        if (startPos != end && !state->isFirst && state->prevIsEncoded)
    199198                unencoded += whiteSpaces;
    200199
    201200        if (startPos != end)
     
    210209                if (newPosition)
    211210                        *newPosition = end;
    212211
    213                 if (isEncoded)
    214                         *isEncoded = false;
     212                state->prevIsEncoded = false;
     213                state->isFirst = false;
    215214
    216215                return (w);
    217216        }
     
    228227
    229228        string::size_type pos = position;
    230229
    231         bool prevIsEncoded = false;
     230        parserState state;
    232231
    233         while ((w = word::parseNext(buffer, pos, end, &pos, prevIsEncoded, &prevIsEncoded, (w == NULL))) != NULL)
     232        while ((w = word::parseNext(buffer, pos, end, &pos, &state)) != NULL)
    234233                res.push_back(w);
    235234
    236235        if (newPosition)
     
    243242void word::parse(const string& buffer, const string::size_type position,
    244243        const string::size_type end, string::size_type* newPosition)
    245244{
     245        parseWithState(buffer, position, end, newPosition, NULL);
     246}
     247
     248
     249void word::parseWithState
     250        (const string& buffer, const size_t position,
     251         const size_t end, size_t* newPosition, parserState* state)
     252{
    246253        if (position + 6 < end && // 6 = "=?(.+)?(.*)?="
    247254            buffer[position] == '=' && buffer[position + 1] == '?')
    248255        {
     
    289296                                        if (theEncoder)
    290297                                        {
    291298                                                // Decode text
     299                                                string encodedBuffer(dataPos, dataEnd);
    292300                                                string decodedBuffer;
    293301
    294                                                 utility::inputStreamStringAdapter ein(string(dataPos, dataEnd));
     302
     303                                                if (state && !state->undecodedBytes.empty())
     304                                                {
     305                                                        encodedBuffer = state->undecodedBytes + encodedBuffer;
     306                                                        state->undecodedBytes.clear();
     307                                                }
     308 
     309                                                utility::inputStreamStringAdapter ein(encodedBuffer);
    295310                                                utility::outputStreamStringAdapter eout(decodedBuffer);
    296311
    297                                                 theEncoder->decode(ein, eout);
     312                                                const size_t decodedLen = theEncoder->decode(ein, eout);
    298313                                                delete (theEncoder);
    299314
    300315                                                m_buffer = decodedBuffer;
     
    305320                                                if (newPosition)
    306321                                                        *newPosition = (p - buffer.begin());
    307322
     323                                                // For Base64 encoding, ensure all bytes have been decoded.
     324                                                // If there are remaining bytes, keep them for the next run.
     325                                                //
     326                                                // This allows decoding some insanities like:
     327                                                //     =?utf-8?B?5Lit5?= =?utf-8?B?paH?=
     328                                                if (*encPos == 'B' || *encPos == 'b')
     329                                                {
     330                                                        const size_t actualEncodedLen = encodedBuffer.length();
     331                                                        const size_t theoricalEncodedLen =
     332                                                                ((decodedLen + ((decodedLen % 3) ? (3 - (decodedLen % 3)) : 0) ) / 3) * 4;
     333
     334                                                        if (state && actualEncodedLen != theoricalEncodedLen)
     335                                                                state->undecodedBytes.assign(dataPos + theoricalEncodedLen, dataEnd);
     336                                                }
     337
    308338                                                return;
    309339                                        }
    310340                                }
  • vmime/word.hpp

    diff -urb libvmime-0.9.2-patched/vmime/word.hpp libvmime-0.9.2/vmime/word.hpp
    old new  
    125125                bool prevWordIsEncoded;
    126126                bool lastCharIsSpace;
    127127        };
     128
     129        class parserState
     130        {
     131        public:
     132
     133                parserState()
     134                        : prevIsEncoded(false), isFirst(true)
     135                {
     136                }
     137
     138                bool prevIsEncoded;
     139                bool isFirst;
     140                std::string undecodedBytes;
     141        };
    128142#endif
    129143
    130144
     
    134148        void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
    135149        void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
    136150
     151       void parseWithState
     152               (const string& buffer,
     153                const size_t position,
     154                const size_t end,
     155                size_t* newPosition,
     156                parserState* state);
     157
    137158        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;
    138159
    139160        const std::vector <ref <const component> > getChildComponents() const;
    140161
    141162private:
    142163
    143         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);
     164        static ref <word> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition, parserState* state);
    144165
    145166        static const std::vector <ref <word> > parseMultiple(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition);
    146167
Note: See TracBrowser for help on using the repository browser.