diff options
-rw-r--r-- | src/vmime/text.cpp | 91 | ||||
-rw-r--r-- | src/vmime/word.cpp | 3 | ||||
-rw-r--r-- | tests/parser/mailboxTest.cpp | 10 | ||||
-rw-r--r-- | tests/parser/textTest.cpp | 10 |
4 files changed, 48 insertions, 66 deletions
diff --git a/src/vmime/text.cpp b/src/vmime/text.cpp index a6172633..08d27bb9 100644 --- a/src/vmime/text.cpp +++ b/src/vmime/text.cpp @@ -285,84 +285,53 @@ void text::createFromString(const string& in, const charset& ch) { asciiPercent = (in.length() == 0 ? 100 : (100 * asciiCount) / in.length()); } - // If there are "too much" non-ASCII chars, encode everything + // If there are "too much" non-ASCII chars, produce just one + // vmime::word. Because encoding happens word-wise, all of the input + // gets encoded. + if (alwaysEncode || asciiPercent < 60) { // less than 60% ASCII chars appendWord(make_shared <word>(in, ch)); + return; - // Else, only encode words which need it - } else { - - bool is8bit = false; // is the current word 8-bit? - bool prevIs8bit = false; // is previous word 8-bit? - unsigned int count = 0; // total number of words - - for (size_t end = in.size(), pos = 0, start = 0 ; ; ) { - - if (pos == end || parserHelpers::isSpace(in[pos])) { - - const string chunk(in.begin() + start, in.begin() + pos); - - if (pos != end) { - ++pos; - } - - if (is8bit) { - - if (count && prevIs8bit) { - - // No need to create a new encoded word, just append - // the current word to the previous one. - shared_ptr <word> w = getWordAt(getWordCount() - 1); - w->getBuffer() += " " + chunk; - - } else { - - if (count) { - shared_ptr <word> w = getWordAt(getWordCount() - 1); - w->getBuffer() += ' '; - } - - appendWord(make_shared <word>(chunk, ch)); + } - prevIs8bit = true; - ++count; - } + // Else, only encode words which need it - } else { + size_t end = in.size(), pos = 0; + bool is8bit = false; // is the current word 8-bit? + bool prevIs8bit = false; // is previous word 8-bit? + unsigned int count = 0; // total number of words - if (count && !prevIs8bit) { + do { + size_t start = pos; - shared_ptr <word> w = getWordAt(getWordCount() - 1); - w->getBuffer() += " " + chunk; + for (; parserHelpers::isSpace(in[pos]); ) + ++pos; - } else { + for (; pos < end && !parserHelpers::isSpace(in[pos]); ++pos) + is8bit |= !parserHelpers::isAscii(in[pos]); - appendWord(make_shared <word>(chunk, charset(charsets::US_ASCII))); + // All chunks will have whitespace (if any) at front, never at the end + const string chunk(in.begin() + start, in.begin() + pos); - prevIs8bit = false; - ++count; - } - } + if (prevIs8bit == is8bit && count > 0) { - if (pos == end) { - break; - } + // same bitness as previous word; merge + auto w = getWordAt(getWordCount() - 1); + w->getBuffer() += chunk; - is8bit = false; - start = pos; + } else { - } else if (!parserHelpers::isAscii(in[pos])) { + appendWord(make_shared <word>(chunk, charset(is8bit ? ch : charsets::US_ASCII))); + ++count; - is8bit = true; - ++pos; + } - } else { + prevIs8bit = is8bit; + is8bit = false; - ++pos; - } - } - } + } while (pos < end); } diff --git a/src/vmime/word.cpp b/src/vmime/word.cpp index d4bf85cf..a16b4b51 100644 --- a/src/vmime/word.cpp +++ b/src/vmime/word.cpp @@ -755,6 +755,9 @@ void word::generate( if (!startNewLine && !state->isFirstWord && !state->lastCharIsSpace) { os << " "; // Separate from previous word + if (!state->prevWordIsEncoded && m_buffer[0] == ' ') + wordEnc.getNextChunk(1); + ++curLineLength; state->lastCharIsSpace = true; diff --git a/tests/parser/mailboxTest.cpp b/tests/parser/mailboxTest.cpp index 997a6a38..d1af23f2 100644 --- a/tests/parser/mailboxTest.cpp +++ b/tests/parser/mailboxTest.cpp @@ -32,6 +32,7 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest) VMIME_TEST(testSeparatorInComment) VMIME_TEST(testMalformations) VMIME_TEST(testExcessiveQuoting) + VMIME_TEST(testSpacing) VMIME_TEST_LIST_END @@ -184,4 +185,13 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest) VASSERT_EQ("generate", "=?utf-8?Q?Foo_B=40r?= <[email protected]>", a->generate()); } + void testSpacing() { + + vmime::text t("Foo B\xc3\xa4renstark Baz", vmime::charsets::UTF_8); + vmime::mailbox m(t, "[email protected]"); + VASSERT_EQ("1", "Foo =?utf-8?Q?B=C3=A4renstark?= Baz", t.generate()); + VASSERT_EQ("2", "=?us-ascii?Q?Foo?= =?utf-8?Q?_B=C3=A4renstark?= =?us-ascii?Q?_Baz?= <[email protected]>", m.generate()); + + } + VMIME_TEST_SUITE_END diff --git a/tests/parser/textTest.cpp b/tests/parser/textTest.cpp index 6d7fe44d..cbb1740a 100644 --- a/tests/parser/textTest.cpp +++ b/tests/parser/textTest.cpp @@ -189,11 +189,11 @@ VMIME_TEST_SUITE_BEGIN(textTest) t2.createFromString(s2, c2); VASSERT_EQ("2.1", 3, t2.getWordCount()); - VASSERT_EQ("2.2", "some ASCII characters and special chars: ", t2.getWordAt(0)->getBuffer()); + VASSERT_EQ("2.2", "some ASCII characters and special chars:", t2.getWordAt(0)->getBuffer()); VASSERT_EQ("2.3", vmime::charset(vmime::charsets::US_ASCII), t2.getWordAt(0)->getCharset()); VASSERT_EQ("2.4", "\xc3\xa4\xd0\xb0", t2.getWordAt(1)->getBuffer()); VASSERT_EQ("2.5", c2, t2.getWordAt(1)->getCharset()); - VASSERT_EQ("2.6", "and then more ASCII chars.", t2.getWordAt(2)->getBuffer()); + VASSERT_EQ("2.6", " and then more ASCII chars.", t2.getWordAt(2)->getBuffer()); VASSERT_EQ("2.7", vmime::charset(vmime::charsets::US_ASCII), t2.getWordAt(2)->getCharset()); } @@ -512,9 +512,9 @@ VMIME_TEST_SUITE_BEGIN(textTest) text.createFromString("Achim Br\xc3\xa4ndt", vmime::charsets::UTF_8); VASSERT_EQ("1", 2, text.getWordCount()); - VASSERT_EQ("2", "Achim ", text.getWordAt(0)->getBuffer()); + VASSERT_EQ("2", "Achim", text.getWordAt(0)->getBuffer()); VASSERT_EQ("3", "us-ascii", text.getWordAt(0)->getCharset()); - VASSERT_EQ("4", "Br\xc3\xa4ndt", text.getWordAt(1)->getBuffer()); + VASSERT_EQ("4", " Br\xc3\xa4ndt", text.getWordAt(1)->getBuffer()); VASSERT_EQ("5", "utf-8", text.getWordAt(1)->getCharset()); // Generate @@ -534,7 +534,7 @@ VMIME_TEST_SUITE_BEGIN(textTest) // Space MUST be encoded inside a word vmime::mailbox mbox(vmime::text("Achim Br\xc3\xa4ndt", vmime::charsets::UTF_8), "[email protected]"); - VASSERT_EQ("generate1", "=?us-ascii?Q?Achim_?= =?utf-8?Q?Br=C3=A4ndt?= <[email protected]>", mbox.generate()); + VASSERT_EQ("generate1", "=?us-ascii?Q?Achim?= =?utf-8?Q?_Br=C3=A4ndt?= <[email protected]>", mbox.generate()); vmime::text txt; txt.appendWord(vmime::make_shared <vmime::word>("Achim ", "us-ascii")); |