aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vmime/text.cpp91
-rw-r--r--src/vmime/word.cpp3
-rw-r--r--tests/parser/mailboxTest.cpp10
-rw-r--r--tests/parser/textTest.cpp10
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"));