Mercurial > thymian
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 |
