From 98b4d91d013ba8d6ef70a9601d6b46bde9db872a Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Wed, 9 Mar 2011 18:03:31 +0000 Subject: [PATCH] Fixed bug #3174903. Fixed word parsing when buffer does not end with NL. Fixed 'no encoding' when forced. --- src/body.cpp | 14 +++++-- src/word.cpp | 25 +++++++----- tests/parser/bodyPartTest.cpp | 76 +++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 14 deletions(-) diff --git a/src/body.cpp b/src/body.cpp index 738d3e71..85968330 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -153,7 +153,10 @@ void body::parse(const string& buffer, const string::size_type position, if (pos != string::npos && pos < end) { - m_prologText = string(buffer.begin() + position, buffer.begin() + pos); + vmime::text text; + text.parse(buffer, position, pos); + + m_prologText = text.getWholeBuffer(); } for (int index = 0 ; !lastPart && (pos != string::npos) && (pos < end) ; ++index) @@ -246,7 +249,10 @@ void body::parse(const string& buffer, const string::size_type position, // Treat remaining text as epilog else if (partStart < end) { - m_epilogText = string(buffer.begin() + partStart, buffer.begin() + end); + vmime::text text; + text.parse(buffer, partStart, end); + + m_epilogText = text.getWholeBuffer(); } } // Treat the contents as 'simple' data @@ -333,7 +339,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe if (!prologText.empty()) { - text prolog(word(prologText, getCharset())); + text prolog(prologText, vmime::charset("us-ascii")); prolog.encodeAndFold(os, maxLineLength, 0, NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE); @@ -356,7 +362,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe if (!epilogText.empty()) { - text epilog(word(epilogText, getCharset())); + text epilog(epilogText, vmime::charset("us-ascii")); epilog.encodeAndFold(os, maxLineLength, 0, NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE); diff --git a/src/word.cpp b/src/word.cpp index fa08d33f..aeaa7371 100644 --- a/src/word.cpp +++ b/src/word.cpp @@ -102,7 +102,9 @@ ref word::parseNext(const string& buffer, const string::size_type positio ++pos; unencoded += buffer.substr(startPos, endPos - startPos); - unencoded += ' '; + + if (pos != end) // ignore white-spaces at end + unencoded += ' '; startPos = pos; continue; @@ -191,14 +193,15 @@ ref word::parseNext(const string& buffer, const string::size_type positio ++pos; } - // Treat unencoded text at the end of the buffer - if (end != startPos) - { - if (startPos != pos && !isFirst && prevIsEncoded) - unencoded += whiteSpaces; + if (startPos != end && !isFirst && prevIsEncoded) + unencoded += whiteSpaces; + if (startPos != end) unencoded += buffer.substr(startPos, end - startPos); + // Treat unencoded text at the end of the buffer + if (!unencoded.empty()) + { ref w = vmime::create (unencoded, charset(charsets::US_ASCII)); w->setParsedBounds(position, end); @@ -337,12 +340,14 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe state = &defaultGeneratorState; // Find out if encoding is forced or required by contents + charset - bool encodingNeeded = (flags & text::FORCE_ENCODING) != 0; + bool encodingNeeded = false; - if (encodingNeeded == false) - encodingNeeded = wordEncoder::isEncodingNeeded(m_buffer, m_charset); - else if ((flags & text::FORCE_NO_ENCODING) != 0) + if ((flags & text::FORCE_NO_ENCODING) != 0) encodingNeeded = false; + else if ((flags & text::FORCE_ENCODING) != 0) + encodingNeeded = true; + else // auto-detect + encodingNeeded = wordEncoder::isEncodingNeeded(m_buffer, m_charset); // If possible and requested (with flag), quote the buffer (no folding is performed). // Quoting is possible if and only if: diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp index df2bf851..b129913d 100644 --- a/tests/parser/bodyPartTest.cpp +++ b/tests/parser/bodyPartTest.cpp @@ -34,6 +34,8 @@ VMIME_TEST_SUITE_BEGIN VMIME_TEST(testParse) VMIME_TEST(testGenerate) VMIME_TEST(testParseMissingLastBoundary) + VMIME_TEST(testPrologEpilog) + VMIME_TEST(testPrologEncoding) VMIME_TEST_LIST_END @@ -105,5 +107,79 @@ VMIME_TEST_SUITE_BEGIN VASSERT_EQ("1", "Foo: bar\r\n\r\nBaz", p1.generate()); } + void testPrologEpilog() + { + const char testMail[] = + "To: test@vmime.org\r\n" + "From: test@vmime.org\r\n" + "Subject: Prolog and epilog test\r\n" + "Content-Type: multipart/mixed; \r\n" + " boundary=\"=_boundary\"\r\n" + "\r\n" + "Prolog text\r\n" + "--=_boundary\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "Part1\r\n" + "--=_boundary--\r\n" + "Epilog text"; + + vmime::bodyPart part; + part.parse(testMail); + + VASSERT_EQ("prolog", "Prolog text", part.getBody()->getPrologText()); + VASSERT_EQ("epilog", "Epilog text", part.getBody()->getEpilogText()); + } + + // Test for bug fix: prolog should not be encoded + // http://sourceforge.net/tracker/?func=detail&atid=525568&aid=3174903&group_id=69724 + void testPrologEncoding() + { + const char testmail[] = + "To: test@vmime.org\r\n" + "From: test@vmime.org\r\n" + "Subject: Prolog encoding test\r\n" + "Content-Type: multipart/mixed; \r\n" + " boundary=\"=_+ZWjySayKqSf2CyrfnNpaAcO6-G1HpoXdHZ4YyswAWqEY39Q\"\r\n" + "\r\n" + "This is a multi-part message in MIME format. Your mail reader does not\r\n" + "understand MIME message format.\r\n" + "--=_+ZWjySayKqSf2CyrfnNpaAcO6-G1HpoXdHZ4YyswAWqEY39Q\r\n" + "Content-Type: text/html; charset=windows-1251\r\n" + "Content-Transfer-Encoding: quoted-printable\r\n" + "\r\n" + "=DD=F2=EE =F2=E5=EA=F1=F2=EE=E2=E0=FF =F7=E0=F1=F2=FC =F1=EB=EE=E6=ED=EE=E3=\r\n" + "=EE =F1=EE=EE=E1=F9=E5=ED=E8=FF\r\n" + "--=_+ZWjySayKqSf2CyrfnNpaAcO6-G1HpoXdHZ4YyswAWqEY39Q\r\n" + "Content-Type: application/octet-stream; charset=windows-1251\r\n" + "Content-Disposition: attachment; filename=FNS.zip\r\n" + "Content-Transfer-Encoding: base64\r\n" + "\r\n" + "UEsDBB...snap...EEAAAAAA==\r\n" + "--=_+ZWjySayKqSf2CyrfnNpaAcO6-G1HpoXdHZ4YyswAWqEY39Q--\r\n" + "Epilog text"; + + vmime::ref msg = vmime::create(); + + std::string istr(testmail); + + std::string ostr; + vmime::utility::outputStreamStringAdapter out(ostr); + + for (int i = 0 ; i < 10 ; ++i) + { + ostr.clear(); + + msg->parse(istr); + msg->generate(out); + + istr = ostr; + } + + VASSERT_EQ("prolog", "This is a multi-part message in MIME format. Your mail reader" + " does not understand MIME message format.", msg->getBody()->getPrologText()); + VASSERT_EQ("epilog", "Epilog text", msg->getBody()->getEpilogText()); + } + VMIME_TEST_SUITE_END