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