diff options
author | Vincent Richard <[email protected]> | 2006-10-02 13:44:00 +0000 |
---|---|---|
committer | Vincent Richard <[email protected]> | 2006-10-02 13:44:00 +0000 |
commit | b79a6ad89013e4aba947df043ad26cbe7fbab5a5 (patch) | |
tree | 352ecfc74b409c71f68e906630940bda71350083 /src/word.cpp | |
parent | Attachment [file]name. (diff) | |
download | vmime-b79a6ad89013e4aba947df043ad26cbe7fbab5a5.tar.gz vmime-b79a6ad89013e4aba947df043ad26cbe7fbab5a5.zip |
Fixed bug #1096610: non-integral number of chars in RFC-2047 encoded words.
Diffstat (limited to 'src/word.cpp')
-rw-r--r-- | src/word.cpp | 128 |
1 files changed, 22 insertions, 106 deletions
diff --git a/src/word.cpp b/src/word.cpp index 58133577..39059dc0 100644 --- a/src/word.cpp +++ b/src/word.cpp @@ -32,6 +32,8 @@ #include "vmime/encoderB64.hpp" #include "vmime/encoderQP.hpp" +#include "vmime/wordEncoder.hpp" + namespace vmime { @@ -481,12 +483,11 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe ? maxLineLength : std::min(maxLineLength, static_cast <string::size_type>(76)); - // Base64 if more than 60% non-ascii, quoted-printable else (default) - const string::size_type asciiPercent = (m_buffer.length() == 0 ? 100 : (100 * asciiCount) / m_buffer.length()); - const string::value_type encoding = (asciiPercent <= 40) ? 'B' : 'Q'; + wordEncoder wordEnc(m_buffer, m_charset); - string wordStart("=?" + m_charset.getName() + "?" + encoding + "?"); - string wordEnd("?="); + const string wordStart("=?" + m_charset.getName() + "?" + + (wordEnc.getEncoding() == wordEncoder::ENCODING_B64 ? 'B' : 'Q') + "?"); + const string wordEnd("?="); const string::size_type minWordLength = wordStart.length() + wordEnd.length(); const string::size_type maxLineLength2 = (maxLineLength3 < minWordLength + 1) @@ -520,125 +521,40 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe } // Encode and fold input buffer - string::const_iterator pos = m_buffer.begin(); - string::size_type remaining = m_buffer.length(); - - encoder* theEncoder = NULL; - - if (encoding == 'B') theEncoder = new encoderB64; - else theEncoder = new encoderQP; - - string qpEncodedBuffer; - - if (encoding == 'Q') - { - theEncoder->getProperties()["rfc2047"] = true; - - // In the case of Quoted-Printable encoding, we cannot simply encode input - // buffer line by line. So, we encode the whole buffer and we will fold it - // in the next loop... - utility::inputStreamStringAdapter in(m_buffer); - utility::outputStreamStringAdapter out(qpEncodedBuffer); - - theEncoder->encode(in, out); - - pos = qpEncodedBuffer.begin(); - remaining = qpEncodedBuffer.length(); - } - -#if 1 if (curLineLength != 1 && !isFirstWord) { os << " "; // Separate from previous word ++curLineLength; } -#endif - for ( ; remaining ; ) + for (unsigned int i = 0 ; ; ++i) { - // Start a new encoded word - os << wordStart; - curLineLength += minWordLength; - // Compute the number of encoded chars that will fit on this line - const string::size_type fit = maxLineLength2 - curLineLength; - - // Base-64 encoding - if (encoding == 'B') - { - // TODO: WARNING! "Any encoded word which encodes a non-integral - // number of characters or octets is incorrectly formed." - - // Here, we have a formula to compute the maximum number of source - // characters to encode knowing the maximum number of encoded chars - // (with Base64, 3 bytes of input provide 4 bytes of output). - string::size_type count = (fit > 1) ? ((fit - 1) * 3) / 4 : 1; - if (count > remaining) count = remaining; + const string::size_type fit = maxLineLength2 - minWordLength + - (i == 0 ? curLineLength : NEW_LINE_SEQUENCE_LENGTH); - utility::inputStreamStringAdapter in - (m_buffer, pos - m_buffer.begin(), pos - m_buffer.begin() + count); + // Get the next encoded chunk + const string chunk = wordEnc.getNextChunk(fit); - curLineLength += theEncoder->encode(in, os); + if (chunk.empty()) + break; - pos += count; - remaining -= count; - } - // Quoted-Printable encoding - else + // Start a new encoded word + if (i != 0) { - // TODO: WARNING! "Any encoded word which encodes a non-integral - // number of characters or octets is incorrectly formed." - - // All we have to do here is to take a certain number of character - // (that is less than or equal to "fit") from the QP encoded buffer, - // but we also make sure not to fold a "=XY" encoded char. - const string::const_iterator qpEnd = qpEncodedBuffer.end(); - string::const_iterator lastFoldPos = pos; - string::const_iterator p = pos; - string::size_type n = 0; - - while (n < fit && p != qpEnd) - { - if (*p == '=') - { - if (n + 3 >= fit) - { - lastFoldPos = p; - break; - } - - p += 3; - n += 3; - } - else - { - ++p; - ++n; - } - } - - if (lastFoldPos == pos) - lastFoldPos = p; - - os << string(pos, lastFoldPos); + os << NEW_LINE_SEQUENCE; + curLineLength = NEW_LINE_SEQUENCE_LENGTH; + } - curLineLength += (lastFoldPos - pos) + 1; + os << wordStart; + curLineLength += minWordLength; - pos += n; - remaining -= n; - } + os << chunk; + curLineLength += chunk.length(); // End of the encoded word os << wordEnd; - - if (remaining) - { - os << NEW_LINE_SEQUENCE; - curLineLength = NEW_LINE_SEQUENCE_LENGTH; - } } - - delete (theEncoder); } if (newLinePos) |