comparison 3rdparty/vmime/tests/parser/textTest.cpp @ 0:a4671277546c tip

created the repository for the thymian project
author ferencd
date Tue, 17 Aug 2021 11:19:54 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:a4671277546c
1 //
2 // VMime library (http://www.vmime.org)
3 // Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 3 of
8 // the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // Linking this library statically or dynamically with other modules is making
20 // a combined work based on this library. Thus, the terms and conditions of
21 // the GNU General Public License cover the whole combination.
22 //
23
24 #include "tests/testUtils.hpp"
25
26 #include <locale>
27 #include <clocale>
28
29
30 VMIME_TEST_SUITE_BEGIN(textTest)
31
32 VMIME_TEST_LIST_BEGIN
33 VMIME_TEST(testConstructors)
34 VMIME_TEST(testCopy)
35 VMIME_TEST(testNewFromString)
36 VMIME_TEST(testDisplayForm)
37 VMIME_TEST(testParse)
38 VMIME_TEST(testGenerate)
39
40 VMIME_TEST(testWordConstructors)
41 VMIME_TEST(testWordParse)
42 VMIME_TEST(testWordGenerate)
43 VMIME_TEST(testWordGenerateSpace)
44 VMIME_TEST(testWordGenerateSpace2)
45 VMIME_TEST(testWordGenerateMultiBytes)
46 VMIME_TEST(testWordGenerateQuote)
47 VMIME_TEST(testWordGenerateSpecialCharsets)
48 VMIME_TEST(testWordGenerateSpecials)
49
50 VMIME_TEST(testWhitespace)
51 VMIME_TEST(testWhitespaceMBox)
52
53 VMIME_TEST(testFoldingAscii)
54 VMIME_TEST(testForcedNonEncoding)
55
56 VMIME_TEST(testBugFix20110511)
57
58 VMIME_TEST(testInternationalizedEmail_specialChars)
59 VMIME_TEST(testInternationalizedEmail_UTF8)
60 VMIME_TEST(testInternationalizedEmail_nonUTF8)
61 VMIME_TEST(testInternationalizedEmail_folding)
62 VMIME_TEST_LIST_END
63
64
65 static const vmime::string getDisplayText(const vmime::text& t)
66 {
67 return t.getWholeBuffer();
68 }
69
70 static const vmime::string cleanGeneratedWords(const std::string& str)
71 {
72 std::istringstream iss(str);
73
74 std::string res;
75 std::string x;
76
77 while (std::getline(iss, x))
78 res += vmime::utility::stringUtils::trim(x);
79
80 return res;
81 }
82
83
84 void setUp()
85 {
86 // Set the global C and C++ locale to the user-configured locale.
87 // The locale should use UTF-8 encoding for these tests to run successfully.
88 try
89 {
90 std::locale::global(std::locale(""));
91 }
92 catch (std::exception &)
93 {
94 std::setlocale(LC_ALL, "");
95 }
96 }
97
98 void tearDown()
99 {
100 // Restore default locale
101 std::locale::global(std::locale("C"));
102 }
103
104
105 void testConstructors()
106 {
107 vmime::text t1;
108
109 VASSERT_EQ("1.1", 0, t1.getWordCount());
110
111 vmime::text t2("Test\xa9\xc3");
112
113 VASSERT_EQ("2.1", 1, t2.getWordCount());
114 VASSERT_EQ("2.2", "Test\xa9\xc3", t2.getWordAt(0)->getBuffer());
115 VASSERT_EQ("2.3", vmime::charset::getLocalCharset(), t2.getWordAt(0)->getCharset());
116
117 vmime::text t3("Test\xa9\xc3", vmime::charset(vmime::charsets::ISO8859_13));
118
119 VASSERT_EQ("3.1", 1, t3.getWordCount());
120 VASSERT_EQ("3.2", "Test\xa9\xc3", t3.getWordAt(0)->getBuffer());
121 VASSERT_EQ("3.3", vmime::charset(vmime::charsets::ISO8859_13), t3.getWordAt(0)->getCharset());
122
123 vmime::word w1("Test", vmime::charset(vmime::charsets::UTF_8));
124 vmime::text t4(w1);
125
126 VASSERT_EQ("4.1", 1, t4.getWordCount());
127 VASSERT_EQ("4.2", w1.getBuffer(), t4.getWordAt(0)->getBuffer());
128 VASSERT_EQ("4.3", w1.getCharset(), t4.getWordAt(0)->getCharset());
129
130 vmime::word w2("Other", vmime::charset(vmime::charsets::US_ASCII));
131 t4.appendWord(vmime::make_shared <vmime::word>(w2));
132
133 vmime::text t5(t4);
134
135 VASSERT_EQ("5.1", 2, t5.getWordCount());
136 VASSERT_EQ("5.2", w1.getBuffer(), t5.getWordAt(0)->getBuffer());
137 VASSERT_EQ("5.3", w1.getCharset(), t5.getWordAt(0)->getCharset());
138 VASSERT_EQ("5.4", w2.getBuffer(), t5.getWordAt(1)->getBuffer());
139 VASSERT_EQ("5.5", w2.getCharset(), t5.getWordAt(1)->getCharset());
140 }
141
142 void testCopy()
143 {
144 vmime::text t1("Test: \xa9\xc3");
145
146 VASSERT("operator==", t1 == t1);
147 VASSERT("clone", *vmime::clone(t1) == t1);
148
149 vmime::text t2;
150 t2.copyFrom(t1);
151
152 VASSERT("copyFrom", t1 == t2);
153 }
154
155 void testNewFromString()
156 {
157 vmime::string s1 = "only ASCII characters";
158 vmime::charset c1("test");
159 vmime::text t1;
160
161 t1.createFromString(s1, c1);
162
163 VASSERT_EQ("1.1", 1, t1.getWordCount());
164 VASSERT_EQ("1.2", s1, t1.getWordAt(0)->getBuffer());
165 VASSERT_EQ("1.3", vmime::charset(vmime::charsets::US_ASCII), t1.getWordAt(0)->getCharset());
166
167 vmime::string s2_1 = "some ASCII characters and special chars: ";
168 vmime::string s2_2 = "\xf1\xf2\xf3\xf4 ";
169 vmime::string s2_3 = "and then more ASCII chars.";
170 vmime::string s2 = s2_1 + s2_2 + s2_3;
171 vmime::charset c2("test");
172 vmime::text t2;
173
174 t2.createFromString(s2, c2);
175
176 VASSERT_EQ("2.1", 3, t2.getWordCount());
177 VASSERT_EQ("2.2", "some ASCII characters and special chars: ", t2.getWordAt(0)->getBuffer());
178 VASSERT_EQ("2.3", vmime::charset(vmime::charsets::US_ASCII), t2.getWordAt(0)->getCharset());
179 VASSERT_EQ("2.4", "\xf1\xf2\xf3\xf4", t2.getWordAt(1)->getBuffer());
180 VASSERT_EQ("2.5", c2, t2.getWordAt(1)->getCharset());
181 VASSERT_EQ("2.6", "and then more ASCII chars.", t2.getWordAt(2)->getBuffer());
182 VASSERT_EQ("2.7", vmime::charset(vmime::charsets::US_ASCII), t2.getWordAt(2)->getCharset());
183 }
184
185 static const vmime::string parseText(const vmime::string& buffer)
186 {
187 vmime::text t;
188 t.parse(buffer);
189
190 std::ostringstream oss;
191 oss << t;
192
193 return (oss.str());
194 }
195
196 void testParse()
197 {
198 // From RFC-2047
199 VASSERT_EQ("1", "[text: [[word: charset=US-ASCII, buffer=Keith Moore]]]",
200 parseText("=?US-ASCII?Q?Keith_Moore?="));
201
202 VASSERT_EQ("2", "[text: [[word: charset=ISO-8859-1, buffer=Keld J\xf8rn Simonsen]]]",
203 parseText("=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?="));
204
205 VASSERT_EQ("3", "[text: [[word: charset=ISO-8859-1, buffer=Andr\xe9]," \
206 "[word: charset=us-ascii, buffer= Pirard]]]",
207 parseText("=?ISO-8859-1?Q?Andr=E9?= Pirard"));
208
209 VASSERT_EQ("4", "[text: [[word: charset=ISO-8859-1, buffer=If you can read this yo]," \
210 "[word: charset=ISO-8859-2, buffer=u understand the example.]]]",
211 parseText("=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\r\n " \
212 "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?="));
213
214 // Bugfix: in "=?charset?q?=XX=YY?=", the "?=" finish
215 // sequence was not correctly found (should be the one
216 // after '=YY' and not the one after '?q').
217 VASSERT_EQ("5", "[text: [[word: charset=abc, buffer=\xe9\xe9]]]",
218 parseText("=?abc?q?=E9=E9?="));
219
220 // Question marks (?) in the middle of the string
221 VASSERT_EQ("6", "[text: [[word: charset=iso-8859-1, buffer=Know wh\xe4t? It works!]]]",
222 parseText("=?iso-8859-1?Q?Know_wh=E4t?_It_works!?="));
223
224 // With language specifier
225 VASSERT_EQ("7", "[text: [[word: charset=US-ASCII, buffer=Keith Moore, lang=EN]]]",
226 parseText("=?US-ASCII*EN?Q?Keith_Moore?="));
227 }
228
229 void testGenerate()
230 {
231 // TODO
232
233 // With language specifier
234 vmime::word wlang1("Émeline", vmime::charset("UTF-8"), "FR");
235 VASSERT_EQ("lang1", "=?UTF-8*FR?Q?=C3=89meline?=", wlang1.generate());
236
237 vmime::word wlang2("Keith Moore", vmime::charset("US-ASCII"), "EN");
238 VASSERT_EQ("lang2", "=?US-ASCII*EN?Q?Keith_Moore?=", wlang2.generate());
239 }
240
241 void testDisplayForm()
242 {
243 #define DISPLAY_FORM(x) getDisplayText(*vmime::text::decodeAndUnfold(x))
244
245 // From RFC-2047
246 VASSERT_EQ("1", "a", DISPLAY_FORM("=?ISO-8859-1?Q?a?="));
247 VASSERT_EQ("2", "a b", DISPLAY_FORM("=?ISO-8859-1?Q?a?= b"));
248 VASSERT_EQ("3", "ab", DISPLAY_FORM("=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?="));
249 VASSERT_EQ("4", "ab", DISPLAY_FORM("=?ISO-8859-1?Q?a?= \t =?ISO-8859-1?Q?b?="));
250 VASSERT_EQ("5", "ab", DISPLAY_FORM("=?ISO-8859-1?Q?a?= \r\n \t =?ISO-8859-1?Q?b?="));
251 VASSERT_EQ("6", "a b", DISPLAY_FORM("=?ISO-8859-1?Q?a_b?="));
252 VASSERT_EQ("7", "a b", DISPLAY_FORM("=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?="));
253
254 // Some more tests...
255 VASSERT_EQ("8", "a b", DISPLAY_FORM(" a =?ISO-8859-1?Q?b?= "));
256 VASSERT_EQ("9", "a b ", DISPLAY_FORM(" \t =?ISO-8859-1?Q?a?= b "));
257 VASSERT_EQ("10", "a b", DISPLAY_FORM(" a\r\n\t b"));
258
259 VASSERT_EQ("11", "a b c", DISPLAY_FORM("a =?ISO-8859-1?Q?b?= c"));
260 VASSERT_EQ("12", "a b c ", DISPLAY_FORM("a =?ISO-8859-1?Q?b?= c "));
261 VASSERT_EQ("13", "a b c ", DISPLAY_FORM(" a =?ISO-8859-1?Q?b?= c "));
262 VASSERT_EQ("14", "a b c d", DISPLAY_FORM("a =?ISO-8859-1?Q?b?= c =?ISO-8859-1?Q?d?= "));
263 VASSERT_EQ("15", "a b c d e", DISPLAY_FORM("a =?ISO-8859-1?Q?b?= c =?ISO-8859-1?Q?d?= e"));
264
265 // Whitespaces and multiline
266 VASSERT_EQ("16", "a b c d e", DISPLAY_FORM("=?ISO-8859-1?Q?a_b_?=c\n\t=?ISO-8859-1?Q?d_?=e"));
267
268 #undef DISPLAY_FORM
269 }
270
271 void testWordConstructors()
272 {
273 VASSERT_EQ("1.1", vmime::charset::getLocalCharset(), vmime::word().getCharset());
274 VASSERT_EQ("1.2", "", vmime::word().getBuffer());
275
276 VASSERT_EQ("2.1", vmime::charset::getLocalCharset(), vmime::word("foo").getCharset());
277 VASSERT_EQ("2.2", "foo", vmime::word("foo").getBuffer());
278
279 VASSERT_EQ("3.1", "bar", vmime::word("foo", vmime::charset("bar")).getCharset().getName());
280 VASSERT_EQ("3.2", "foo", vmime::word("foo", vmime::charset("bar")).getBuffer());
281 }
282
283 void testWordParse()
284 {
285 // Simple encoded word
286 vmime::word w1;
287 w1.parse("=?foo?q?bar=E9 baz?=");
288
289 VASSERT_EQ("1.1", "foo", w1.getCharset().getName());
290 VASSERT_EQ("1.2", "bar\xe9 baz", w1.getBuffer());
291
292 // Unencoded text
293 vmime::word w2;
294 w2.parse(" foo bar \tbaz...");
295
296 VASSERT_EQ("2.1", vmime::charset(vmime::charsets::US_ASCII), w2.getCharset());
297 VASSERT_EQ("2.2", " foo bar \tbaz...", w2.getBuffer());
298
299 // Malformed word
300 vmime::word w3;
301 w3.parse("=?foo bar");
302
303 VASSERT_EQ("3.1", vmime::charset(vmime::charsets::US_ASCII), w3.getCharset());
304 VASSERT_EQ("3.2", "=?foo bar", w3.getBuffer());
305
306 // Unknown encoding
307 vmime::word w4;
308 w4.parse("=?whatever?not_q_or_b?whatever?=");
309
310 VASSERT_EQ("4.1", vmime::charset(vmime::charsets::US_ASCII), w4.getCharset());
311 VASSERT_EQ("4.2", "=?whatever?not_q_or_b?whatever?=", w4.getBuffer());
312 }
313
314 void testWordGenerate()
315 {
316 VASSERT_EQ("1", "=?foo?Q?bar=E9_baz?=",
317 vmime::word("bar\xe9 baz", vmime::charset("foo")).generate());
318
319 VASSERT_EQ("2", "=?foo?B?8fLz9PU=?=",
320 vmime::word("\xf1\xf2\xf3\xf4\xf5", vmime::charset("foo")).generate());
321 }
322
323 void testWordGenerateSpace()
324 {
325 // No white-space between an unencoded word and a encoded one
326 VASSERT_EQ("1", "Bonjour =?utf-8?Q?Fran=C3=A7ois?=",
327 vmime::text::newFromString("Bonjour Fran\xc3\xa7ois",
328 vmime::charset("utf-8"))->generate());
329
330 // White-space between two encoded words
331 vmime::text txt;
332 txt.appendWord(vmime::make_shared <vmime::word>("\xc3\x89t\xc3\xa9", "utf-8"));
333 txt.appendWord(vmime::make_shared <vmime::word>("Fran\xc3\xa7ois", "utf-8"));
334
335 const vmime::string decoded = "\xc3\x89t\xc3\xa9""Fran\xc3\xa7ois";
336 const vmime::string encoded = "=?utf-8?B?w4l0w6k=?= =?utf-8?Q?Fran=C3=A7ois?=";
337
338 // -- test encoding
339 VASSERT_EQ("2", encoded, txt.generate());
340
341 // -- ensure no space is added when decoding
342 vmime::text txt2;
343 txt2.parse(encoded, 0, encoded.length());
344
345 VASSERT_EQ("3", decoded, txt2.getWholeBuffer());
346
347 // -- test rencoding
348 VASSERT_EQ("4", encoded, txt2.generate());
349 }
350
351 void testWordGenerateSpace2()
352 {
353 // White-space between two encoded words (#2)
354 vmime::text txt;
355 txt.appendWord(vmime::make_shared <vmime::word>("Facture ", "utf-8"));
356 txt.appendWord(vmime::make_shared <vmime::word>("\xc3\xa0", "utf-8"));
357 txt.appendWord(vmime::make_shared <vmime::word>(" envoyer ", "utf-8"));
358 txt.appendWord(vmime::make_shared <vmime::word>("\xc3\xa0", "utf-8"));
359 txt.appendWord(vmime::make_shared <vmime::word>(" Martine", "utf-8"));
360
361 const vmime::string decoded = "Facture ""\xc3\xa0"" envoyer ""\xc3\xa0"" Martine";
362 const vmime::string encoded = "Facture =?utf-8?B?w6A=?= envoyer =?utf-8?B?w6A=?= Martine";
363
364 // -- test encoding
365 VASSERT_EQ("1", encoded, txt.generate());
366
367 // -- ensure no space is added when decoding
368 vmime::text txt2;
369 txt2.parse(encoded, 0, encoded.length());
370
371 VASSERT_EQ("2", decoded, txt2.getWholeBuffer());
372
373 // -- test rencoding
374 VASSERT_EQ("3", encoded, txt2.generate());
375 }
376
377 void testWordGenerateMultiBytes()
378 {
379 // Ensure we don't encode a non-integral number of characters
380 VASSERT_EQ("1", "=?utf-8?Q?aaa?==?utf-8?Q?=C3=A9?==?utf-8?Q?zzz?=",
381 cleanGeneratedWords(vmime::word("aaa\xc3\xa9zzz", vmime::charset("utf-8")).generate(16)));
382
383 VASSERT_EQ("2", "=?utf-8?Q?aaa=C3=A9?==?utf-8?Q?zzz?=",
384 cleanGeneratedWords(vmime::word("aaa\xc3\xa9zzz", vmime::charset("utf-8")).generate(17)));
385 }
386
387 void testWordGenerateQuote()
388 {
389 std::string str;
390 vmime::utility::outputStreamStringAdapter os(str);
391
392 vmime::generationContext ctx;
393 ctx.setMaxLineLength(1000);
394
395 // ASCII-only text is quotable
396 str.clear();
397 vmime::word("Quoted text").generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL);
398 VASSERT_EQ("1", "\"Quoted text\"", cleanGeneratedWords(str));
399
400 // Text with CR/LF is not quotable
401 str.clear();
402 vmime::word("Non-quotable\ntext", "us-ascii").generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL);
403 VASSERT_EQ("2", "=?us-ascii?Q?Non-quotable=0Atext?=", cleanGeneratedWords(str));
404
405 // Text with non-ASCII chars is not quotable
406 str.clear();
407 vmime::word("Non-quotable text \xc3\xa9").generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL);
408 VASSERT_EQ("3", "=?UTF-8?Q?Non-quotable_text_=C3=A9?=", cleanGeneratedWords(str));
409 }
410
411 void testWordGenerateSpecialCharsets()
412 {
413 // ISO-2022-JP only uses 7-bit chars but should be encoded in Base64
414 VASSERT_EQ("1", "=?iso-2022-jp?B?XlskQiVRITwlPSVKJWshJiU9JVUlSCUmJSclIl5bKEI=?=",
415 cleanGeneratedWords(vmime::word("^[$B%Q!<%=%J%k!&%=%U%H%&%'%\"^[(B",
416 vmime::charset("iso-2022-jp")).generate(100)));
417 }
418
419 void testWordGenerateSpecials()
420 {
421 // In RFC-2047, quotation marks (ASCII 22h) should be encoded
422 VASSERT_EQ("1", "=?UTF-8?Q?=22=C3=9Cml=C3=A4ute=22?=",
423 vmime::word("\x22\xC3\x9Cml\xC3\xA4ute\x22", vmime::charset("UTF-8")).generate());
424 }
425
426 void testWhitespace()
427 {
428 // Create
429 vmime::text text;
430 text.createFromString("Achim Br\xc3\xa4ndt", vmime::charsets::UTF_8);
431
432 VASSERT_EQ("1", 2, text.getWordCount());
433 VASSERT_EQ("2", "Achim ", text.getWordAt(0)->getBuffer());
434 VASSERT_EQ("3", "us-ascii", text.getWordAt(0)->getCharset());
435 VASSERT_EQ("4", "Br\xc3\xa4ndt", text.getWordAt(1)->getBuffer());
436 VASSERT_EQ("5", "utf-8", text.getWordAt(1)->getCharset());
437
438 // Generate
439 VASSERT_EQ("6", "Achim =?utf-8?Q?Br=C3=A4ndt?=", text.generate());
440
441 // Parse
442 text.parse("=?us-ascii?Q?Achim_?= =?utf-8?Q?Br=C3=A4ndt?=");
443
444 VASSERT_EQ("7", 2, text.getWordCount());
445 VASSERT_EQ("8", "Achim ", text.getWordAt(0)->getBuffer());
446 VASSERT_EQ("9", "us-ascii", text.getWordAt(0)->getCharset());
447 VASSERT_EQ("10", "Br\xc3\xa4ndt", text.getWordAt(1)->getBuffer());
448 VASSERT_EQ("11", "utf-8", text.getWordAt(1)->getCharset());
449 }
450
451 void testWhitespaceMBox()
452 {
453 // Space MUST be encoded inside a word
454 vmime::mailbox mbox(vmime::text("Achim Br\xc3\xa4ndt", vmime::charsets::UTF_8), "me@vmime.org");
455 VASSERT_EQ("generate1", "=?us-ascii?Q?Achim_?= =?utf-8?Q?Br=C3=A4ndt?= <me@vmime.org>", mbox.generate());
456
457 vmime::text txt;
458 txt.appendWord(vmime::make_shared <vmime::word>("Achim ", "us-ascii"));
459 txt.appendWord(vmime::make_shared <vmime::word>("Br\xc3\xa4ndt", "utf-8"));
460 mbox = vmime::mailbox(txt, "me@vmime.org");
461 VASSERT_EQ("generate2", "=?us-ascii?Q?Achim_?= =?utf-8?Q?Br=C3=A4ndt?= <me@vmime.org>", mbox.generate());
462
463 mbox.parse("=?us-ascii?Q?Achim?= =?utf-8?Q?Br=C3=A4ndt?= <me@vmime.org>");
464 VASSERT_EQ("parse.name.count", 2, mbox.getName().getWordCount());
465 VASSERT_EQ("parse.name.word1.buffer", "Achim", mbox.getName().getWordAt(0)->getBuffer());
466 VASSERT_EQ("parse.name.word1.charset", "us-ascii", mbox.getName().getWordAt(0)->getCharset());
467 VASSERT_EQ("parse.name.word2.buffer", "Br\xc3\xa4ndt", mbox.getName().getWordAt(1)->getBuffer());
468 VASSERT_EQ("parse.name.word2.charset", "utf-8", mbox.getName().getWordAt(1)->getCharset());
469
470 VASSERT_EQ("parse.email", "me@vmime.org", mbox.getEmail());
471 }
472
473 void testFoldingAscii()
474 {
475 // In this test, no encoding is needed, but line should be folded anyway
476 vmime::word w("01234567890123456789012345678901234567890123456789"
477 "01234567890123456789012345678901234567890123456789", vmime::charset("us-ascii"));
478
479 VASSERT_EQ("fold.ascii",
480 "=?us-ascii?Q?01234567890123456789012345678901234?=\r\n"
481 " =?us-ascii?Q?5678901234567890123456789012345678?=\r\n"
482 " =?us-ascii?Q?9012345678901234567890123456789?=", w.generate(50));
483 }
484
485 void testForcedNonEncoding()
486 {
487 // Testing long unbreakable and unencodable header
488 vmime::relay r;
489 r.parse(" from User (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1]) by servername.hostname.com\n\t"
490 "with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009 09:23:49 +0100");
491
492 VASSERT_EQ("received.long", "from User\r\n (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1])\r\n by servername.hostname.com with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009\r\n 09:23:49 +0100", r.generate(78));
493 }
494
495 void testBugFix20110511()
496 {
497 /*
498
499 Using the latest version of vmime (0.9.1), encoding the following string: Jean
500 Gwenaël Dutourd will result in:
501 Jean =?utf-8?Q?Gwena=C3=ABl_?= Dutourd
502 However, decoding this will result in Jean Gwenaël Dutourd (notice two spaces
503 between the last 2 words). The encoder adds a _ after the second word, but
504 since the last word is not encoded, the space between them is not ignored, and
505 is decoded into an additional space.
506
507 See: http://sourceforge.net/projects/vmime/forums/forum/237357/topic/4531365
508
509 */
510
511 const std::string DECODED_TEXT = "Jean Gwenaël Dutourd";
512 const std::string ENCODED_TEXT = "Jean =?utf-8?Q?Gwena=C3=ABl?= Dutourd";
513
514 // Encode
515 VASSERT_EQ("encode", ENCODED_TEXT,
516 vmime::text::newFromString(DECODED_TEXT, vmime::charset("utf-8"))->generate());
517
518 // Decode
519 vmime::text t;
520 t.parse(ENCODED_TEXT);
521
522 // -- words
523 std::ostringstream oss; oss << t;
524 VASSERT_EQ("decode1",
525 "[text: [[word: charset=us-ascii, buffer=Jean ],"
526 "[word: charset=utf-8, buffer=Gwenaël],"
527 "[word: charset=us-ascii, buffer= Dutourd]]]", oss.str());
528
529 // -- getWholeBuffer
530 VASSERT_EQ("decode2", DECODED_TEXT, t.getWholeBuffer());
531 }
532
533 void testInternationalizedEmail_specialChars()
534 {
535 vmime::generationContext ctx(vmime::generationContext::getDefaultContext());
536 ctx.setInternationalizedEmailSupport(true);
537
538 vmime::generationContext::switcher <vmime::generationContext> contextSwitcher(ctx);
539
540 // Special sequence/chars should still be encoded
541 VASSERT_EQ("1", "=?us-ascii?Q?Test=3D=3Frfc2047_sequence?=",
542 vmime::word("Test=?rfc2047 sequence", vmime::charset("us-ascii")).generate());
543
544 VASSERT_EQ("2", "=?us-ascii?Q?Line_One=0ALine_Two?=",
545 vmime::word("Line One\nLine Two", vmime::charset("us-ascii")).generate());
546 }
547
548 void testInternationalizedEmail_UTF8()
549 {
550 vmime::generationContext ctx(vmime::generationContext::getDefaultContext());
551 ctx.setInternationalizedEmailSupport(true);
552
553 vmime::generationContext::switcher <vmime::generationContext> contextSwitcher(ctx);
554
555 // Already UTF-8 encoded text should be left as is
556 VASSERT_EQ("1", "Achim Br\xc3\xa4ndt",
557 vmime::word("Achim Br\xc3\xa4ndt", vmime::charset("utf-8")).generate());
558 }
559
560 void testInternationalizedEmail_nonUTF8()
561 {
562 vmime::generationContext ctx(vmime::generationContext::getDefaultContext());
563 ctx.setInternationalizedEmailSupport(true);
564
565 vmime::generationContext::switcher <vmime::generationContext> contextSwitcher(ctx);
566
567 // Non UTF-8 encoded text should first be converted to UTF-8
568 VASSERT_EQ("1", "Achim Br\xc3\xa4ndt",
569 vmime::word("Achim Br\xe4ndt", vmime::charset("iso-8859-1")).generate());
570 }
571
572 void testInternationalizedEmail_folding()
573 {
574 vmime::generationContext ctx(vmime::generationContext::getDefaultContext());
575 ctx.setInternationalizedEmailSupport(true);
576
577 vmime::generationContext::switcher <vmime::generationContext> contextSwitcher(ctx);
578
579 // RFC-2047 encoding must be performed, as line folding is needed
580 vmime::word w1("01234567890123456789\xc3\xa0x012345678901234567890123456789"
581 "01234567890123456789\xc3\xa0x012345678901234567890123456789", vmime::charset("utf-8"));
582
583 VASSERT_EQ("1",
584 "=?utf-8?Q?01234567890123456789=C3=A0x01234567890?=\r\n"
585 " =?utf-8?Q?1234567890123456789012345678901234567?=\r\n"
586 " =?utf-8?Q?89=C3=A0x0123456789012345678901234567?=\r\n"
587 " =?utf-8?Q?89?=", w1.generate(50));
588
589 // RFC-2047 encoding will not be forced, as words can be wrapped in a new line
590 vmime::word w2("bla bla bla This is some '\xc3\xa0\xc3\xa7' UTF-8 encoded text", vmime::charset("utf-8"));
591
592 VASSERT_EQ("2",
593 "bla bla bla This is\r\n"
594 " some '\xc3\xa0\xc3\xa7' UTF-8\r\n"
595 " encoded text", w2.generate(20));
596 }
597
598 VMIME_TEST_SUITE_END
599