Mercurial > thymian
comparison 3rdparty/vmime/tests/parser/parameterTest.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(parameterTest) | |
| 31 | |
| 32 VMIME_TEST_LIST_BEGIN | |
| 33 VMIME_TEST(testParse) | |
| 34 VMIME_TEST(testParseRFC2231) | |
| 35 VMIME_TEST(testGenerate) | |
| 36 VMIME_TEST(testGenerateRFC2231) | |
| 37 VMIME_TEST(testNonStandardEncodedParam) | |
| 38 VMIME_TEST(testParseNonSignificantWS) | |
| 39 VMIME_TEST(testEncodeTSpecials) | |
| 40 VMIME_TEST(testEncodeTSpecialsInRFC2231) | |
| 41 VMIME_TEST(testWhitespaceBreaksTheValue) | |
| 42 VMIME_TEST_LIST_END | |
| 43 | |
| 44 | |
| 45 // HACK: parameterizedHeaderField constructor is private | |
| 46 class parameterizedHeaderField : public vmime::parameterizedHeaderField | |
| 47 { | |
| 48 public: | |
| 49 | |
| 50 parameterizedHeaderField() | |
| 51 { | |
| 52 setName("F"); | |
| 53 setValue(vmime::headerFieldFactory::getInstance()->createValue(getName())); | |
| 54 setValue(vmime::word("X")); | |
| 55 } | |
| 56 | |
| 57 using vmime::parameterizedHeaderField::generate; | |
| 58 | |
| 59 const vmime::string generate | |
| 60 (const vmime::generationContext::EncodedParameterValueModes genMode, | |
| 61 const vmime::size_t maxLineLength = 0) const | |
| 62 { | |
| 63 vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); | |
| 64 ctx.setEncodedParameterValueMode(genMode); | |
| 65 | |
| 66 if (maxLineLength != 0) | |
| 67 ctx.setMaxLineLength(maxLineLength); | |
| 68 | |
| 69 std::ostringstream oss; | |
| 70 vmime::utility::outputStreamAdapter adapter(oss); | |
| 71 | |
| 72 vmime::parameterizedHeaderField::generate(ctx, adapter); | |
| 73 | |
| 74 return oss.str(); | |
| 75 } | |
| 76 }; | |
| 77 | |
| 78 | |
| 79 #define FIELD_VALUE(f) (f.getValue()->generate()) | |
| 80 #define PARAM_VALUE(p, n) (p.getParameterAt(n)->getValue().generate()) | |
| 81 #define PARAM_NAME(p, n) (p.getParameterAt(n)->getName()) | |
| 82 #define PARAM_CHARSET(p, n) \ | |
| 83 (p.getParameterAt(n)->getValue().getCharset().generate()) | |
| 84 #define PARAM_LANG(p, n) \ | |
| 85 (p.getParameterAt(n)->getValue().getLanguage()) | |
| 86 #define PARAM_BUFFER(p, n) \ | |
| 87 (p.getParameterAt(n)->getValue().getBuffer()) | |
| 88 | |
| 89 | |
| 90 void setUp() | |
| 91 { | |
| 92 // Set the global C and C++ locale to the user-configured locale. | |
| 93 // The locale should use UTF-8 encoding for these tests to run successfully. | |
| 94 try | |
| 95 { | |
| 96 std::locale::global(std::locale("")); | |
| 97 } | |
| 98 catch (std::exception &) | |
| 99 { | |
| 100 std::setlocale(LC_ALL, ""); | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 void tearDown() | |
| 105 { | |
| 106 // Restore default locale | |
| 107 std::locale::global(std::locale("C")); | |
| 108 } | |
| 109 | |
| 110 | |
| 111 void testParse() | |
| 112 { | |
| 113 // Simple parameter | |
| 114 parameterizedHeaderField p1; | |
| 115 p1.parse("X; param1=value1;\r\n"); | |
| 116 | |
| 117 VASSERT_EQ("1.1", 1, p1.getParameterCount()); | |
| 118 VASSERT_EQ("1.2", "param1", PARAM_NAME(p1, 0)); | |
| 119 VASSERT_EQ("1.3", "value1", PARAM_VALUE(p1, 0)); | |
| 120 | |
| 121 // Multi-section parameters (1/2) | |
| 122 parameterizedHeaderField p2a; | |
| 123 p2a.parse("X; param1=value1;\r\n" | |
| 124 " param2*0=\"val\";\r\n" | |
| 125 " param2*1=\"ue2\";"); | |
| 126 | |
| 127 VASSERT_EQ("2a.1", 2, p2a.getParameterCount()); | |
| 128 VASSERT_EQ("2a.2", "param1", PARAM_NAME(p2a, 0)); | |
| 129 VASSERT_EQ("2a.3", "value1", PARAM_VALUE(p2a, 0)); | |
| 130 VASSERT_EQ("2a.4", "param2", PARAM_NAME(p2a, 1)); | |
| 131 VASSERT_EQ("2a.5", "value2", PARAM_VALUE(p2a, 1)); | |
| 132 | |
| 133 // Multi-section parameters (2/2) | |
| 134 parameterizedHeaderField p2b; | |
| 135 p2b.parse("X; param1=value1;\r\n" | |
| 136 " param2=\"should be ignored\";\r\n" | |
| 137 " param2*0=\"val\";\r\n" | |
| 138 " param2*1=\"ue2\";"); | |
| 139 | |
| 140 VASSERT_EQ("2b.1", 2, p2b.getParameterCount()); | |
| 141 VASSERT_EQ("2b.2", "param1", PARAM_NAME(p2b, 0)); | |
| 142 VASSERT_EQ("2b.3", "value1", PARAM_VALUE(p2b, 0)); | |
| 143 VASSERT_EQ("2b.4", "param2", PARAM_NAME(p2b, 1)); | |
| 144 VASSERT_EQ("2b.5", "value2", PARAM_VALUE(p2b, 1)); | |
| 145 | |
| 146 // Extended parameter (charset and language information) | |
| 147 parameterizedHeaderField p3; | |
| 148 p3.parse("X; param1*=charset'language'value1;\r\n"); | |
| 149 | |
| 150 VASSERT_EQ("3.1", 1, p3.getParameterCount()); | |
| 151 VASSERT_EQ("3.2", "param1", PARAM_NAME(p3, 0)); | |
| 152 VASSERT_EQ("3.3", "charset", PARAM_CHARSET(p3, 0)); | |
| 153 VASSERT_EQ("3.4", "value1", PARAM_BUFFER(p3, 0)); | |
| 154 | |
| 155 // Encoded characters in extended parameter values | |
| 156 parameterizedHeaderField p4; | |
| 157 p4.parse("X; param1*=a%20value%20with%20multiple%20word%73"); // 0x73 = 's' | |
| 158 | |
| 159 VASSERT_EQ("4.1", 1, p4.getParameterCount()); | |
| 160 VASSERT_EQ("4.2", "param1", PARAM_NAME(p4, 0)); | |
| 161 VASSERT_EQ("4.3", "a value with multiple words", PARAM_VALUE(p4, 0)); | |
| 162 | |
| 163 // Invalid encoded character | |
| 164 parameterizedHeaderField p5; | |
| 165 p5.parse("X; param1*=test%20value%"); | |
| 166 | |
| 167 VASSERT_EQ("5.1", 1, p5.getParameterCount()); | |
| 168 VASSERT_EQ("5.2", "param1", PARAM_NAME(p5, 0)); | |
| 169 VASSERT_EQ("5.3", "test value%", PARAM_VALUE(p5, 0)); | |
| 170 | |
| 171 // Spaces before and after '=' | |
| 172 parameterizedHeaderField p6; | |
| 173 p6.parse("X; param1\t= \"value1\""); | |
| 174 | |
| 175 VASSERT_EQ("6.1", 1, p6.getParameterCount()); | |
| 176 VASSERT_EQ("6.2", "param1", PARAM_NAME(p6, 0)); | |
| 177 VASSERT_EQ("6.3", "value1", PARAM_VALUE(p6, 0)); | |
| 178 | |
| 179 // Quoted strings and escaped chars | |
| 180 parameterizedHeaderField p7; | |
| 181 p7.parse("X; param1=\"this is a slash: \\\"\\\\\\\"\""); // \"\\\" | |
| 182 | |
| 183 VASSERT_EQ("7.1", 1, p7.getParameterCount()); | |
| 184 VASSERT_EQ("7.2", "param1", PARAM_NAME(p7, 0)); | |
| 185 VASSERT_EQ("7.3", "this is a slash: \"\\\"", PARAM_VALUE(p7, 0)); | |
| 186 } | |
| 187 | |
| 188 void testParseRFC2231() | |
| 189 { | |
| 190 // Extended parameter with charset specified in more than one | |
| 191 // section (this is forbidden by RFC, but is should not fail) | |
| 192 parameterizedHeaderField p1; | |
| 193 p1.parse("X; param1*0*=charset1'language1'value1;\r\n" | |
| 194 " param1*1*=charset2'language2'value2;"); | |
| 195 | |
| 196 VASSERT_EQ("1.1", 1, p1.getParameterCount()); | |
| 197 VASSERT_EQ("1.2", "param1", PARAM_NAME(p1, 0)); | |
| 198 VASSERT_EQ("1.3", "charset1", PARAM_CHARSET(p1, 0)); | |
| 199 VASSERT_EQ("1.4", "value1charset2'language2'value2", PARAM_BUFFER(p1, 0)); | |
| 200 | |
| 201 // Charset not specified in the first section (that is not encoded), | |
| 202 // but specified in the second one (legal) | |
| 203 parameterizedHeaderField p2; | |
| 204 p2.parse("X; param1*0=value1;\r\n" | |
| 205 " param1*1*=charset'language'value2;"); | |
| 206 | |
| 207 VASSERT_EQ("2.1", 1, p2.getParameterCount()); | |
| 208 VASSERT_EQ("2.2", "param1", PARAM_NAME(p2, 0)); | |
| 209 VASSERT_EQ("2.3", "charset", PARAM_CHARSET(p2, 0)); | |
| 210 VASSERT_EQ("2.4", "value1value2", PARAM_BUFFER(p2, 0)); | |
| 211 | |
| 212 // Characters prefixed with '%' in a simple (not extended) section | |
| 213 // should not be decoded | |
| 214 parameterizedHeaderField p3; | |
| 215 p3.parse("X; param1=val%20ue1"); | |
| 216 | |
| 217 VASSERT_EQ("3.1", 1, p3.getParameterCount()); | |
| 218 VASSERT_EQ("3.2", "param1", PARAM_NAME(p3, 0)); | |
| 219 VASSERT_EQ("3.3", "val%20ue1", PARAM_VALUE(p3, 0)); | |
| 220 | |
| 221 // Multiple sections + charset specified and encoding | |
| 222 parameterizedHeaderField p4; | |
| 223 p4.parse("X; param1*0*=charset'language'value1a%20;" | |
| 224 " param1*1*=value1b%20;" | |
| 225 " param1*2=value1c"); | |
| 226 | |
| 227 VASSERT_EQ("4.1", 1, p4.getParameterCount()); | |
| 228 VASSERT_EQ("4.2", "param1", PARAM_NAME(p4, 0)); | |
| 229 VASSERT_EQ("4.3", "charset", PARAM_CHARSET(p4, 0)); | |
| 230 VASSERT_EQ("4.4", "value1a value1b value1c", PARAM_BUFFER(p4, 0)); | |
| 231 | |
| 232 // No charset specified: defaults to US-ASCII | |
| 233 parameterizedHeaderField p5; | |
| 234 p5.parse("X; param1*='language'value1"); | |
| 235 | |
| 236 VASSERT_EQ("5.1", 1, p5.getParameterCount()); | |
| 237 VASSERT_EQ("5.2", "param1", PARAM_NAME(p5, 0)); | |
| 238 VASSERT_EQ("5.3", "us-ascii", PARAM_CHARSET(p5, 0)); | |
| 239 VASSERT_EQ("5.4", "value1", PARAM_BUFFER(p5, 0)); | |
| 240 | |
| 241 // Language specification | |
| 242 parameterizedHeaderField p6; | |
| 243 p6.parse("X; param1*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A"); | |
| 244 | |
| 245 VASSERT_EQ("6.1", 1, p6.getParameterCount()); | |
| 246 VASSERT_EQ("6.2", "param1", PARAM_NAME(p6, 0)); | |
| 247 VASSERT_EQ("6.3", "us-ascii", PARAM_CHARSET(p6, 0)); | |
| 248 VASSERT_EQ("6.4", "en-us", PARAM_LANG(p6, 0)); | |
| 249 VASSERT_EQ("6.5", "This is ***fun***", PARAM_BUFFER(p6, 0)); | |
| 250 } | |
| 251 | |
| 252 void testGenerate() | |
| 253 { | |
| 254 // Simple parameter/value | |
| 255 parameterizedHeaderField p1; | |
| 256 p1.appendParameter(vmime::make_shared <vmime::parameter>("param1", "value1")); | |
| 257 | |
| 258 VASSERT_EQ("1", "F: X; param1=value1", p1.generate()); | |
| 259 | |
| 260 // Value that needs quoting (1/2) | |
| 261 parameterizedHeaderField p2a; | |
| 262 p2a.appendParameter(vmime::make_shared <vmime::parameter>("param1", "value1a;value1b")); | |
| 263 | |
| 264 VASSERT_EQ("2a", "F: X; param1=\"value1a;value1b\"", p2a.generate()); | |
| 265 | |
| 266 // Value that needs quoting (2/2) | |
| 267 parameterizedHeaderField p2b; | |
| 268 p2b.appendParameter(vmime::make_shared <vmime::parameter>("param1", "va\\lue\"1")); | |
| 269 | |
| 270 VASSERT_EQ("2b", "F: X; param1=\"va\\\\lue\\\"1\"", p2b.generate()); | |
| 271 } | |
| 272 | |
| 273 void testGenerateRFC2231() | |
| 274 { | |
| 275 // Extended parameter with charset specifier | |
| 276 parameterizedHeaderField p1; | |
| 277 p1.appendParameter(vmime::make_shared <vmime::parameter>("param1", | |
| 278 vmime::word("value 1\xe9", vmime::charset("charset")))); | |
| 279 | |
| 280 VASSERT_EQ("1.no-encoding", "F: X; param1=\"value 1\"", | |
| 281 p1.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING)); | |
| 282 | |
| 283 VASSERT_EQ("1.rfc2047", "F: X; param1=\"=?charset?Q?value_1=E9?=\"", | |
| 284 p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY)); | |
| 285 | |
| 286 VASSERT_EQ("1.rfc2231", "F: X; param1*=charset''value%201%E9", | |
| 287 p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY)); | |
| 288 | |
| 289 VASSERT_EQ("1.both", "F: X; param1=\"=?charset?Q?value_1=E9?=\";param1*=charset''value%201%E9", | |
| 290 p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)); | |
| 291 | |
| 292 // Value that spans on multiple lines | |
| 293 parameterizedHeaderField p2; | |
| 294 p2.appendParameter(vmime::make_shared <vmime::parameter>("param1", | |
| 295 vmime::word("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", | |
| 296 vmime::charset("charset")))); | |
| 297 | |
| 298 VASSERT_EQ("2.no-encoding", "F: X; \r\n " | |
| 299 "param1=abcdefghijkl", | |
| 300 p2.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING, 25)); // max line length = 25 | |
| 301 | |
| 302 VASSERT_EQ("2.rfc2047", "F: X; \r\n " | |
| 303 "param1=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", | |
| 304 p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY, 25)); // max line length = 25 | |
| 305 | |
| 306 VASSERT_EQ("2.rfc2231", "F: X; \r\n " | |
| 307 "param1*0*=charset''abc;\r\n " | |
| 308 "param1*1*=defghijkl;\r\n " | |
| 309 "param1*2*=mnopqrstu;\r\n " | |
| 310 "param1*3*=vwxyzABCD;\r\n " | |
| 311 "param1*4*=EFGHIJKLM;\r\n " | |
| 312 "param1*5*=NOPQRSTUV;\r\n " | |
| 313 "param1*6*=WXYZ", | |
| 314 p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY, 25)); // max line length = 25 | |
| 315 | |
| 316 VASSERT_EQ("2.both", "F: X; \r\n " | |
| 317 "param1=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;\r\n " | |
| 318 "param1*0*=charset''abc;\r\n " | |
| 319 "param1*1*=defghijkl;\r\n " | |
| 320 "param1*2*=mnopqrstu;\r\n " | |
| 321 "param1*3*=vwxyzABCD;\r\n " | |
| 322 "param1*4*=EFGHIJKLM;\r\n " | |
| 323 "param1*5*=NOPQRSTUV;\r\n " | |
| 324 "param1*6*=WXYZ", | |
| 325 p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047, 25)); // max line length = 25 | |
| 326 | |
| 327 // Non-ASCII parameter value | |
| 328 parameterizedHeaderField p3; | |
| 329 p3.appendParameter(vmime::make_shared <vmime::parameter>("param1", | |
| 330 vmime::word("δσσσσσσσσσσσσσσσσσσσσδσδα δσαδσδσαδσαδασδασ δσαδασδσα δσαδασδσα δασδασδασ δασαχφδδσα 2008.doc", | |
| 331 vmime::charset("utf-8")))); | |
| 332 | |
| 333 VASSERT_EQ("3.no-encoding", "F: X; \r\n " | |
| 334 "param1=\" 2008.doc\"", | |
| 335 p3.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING, 80)); // max line length = 80 | |
| 336 | |
| 337 VASSERT_EQ("3.7bit-only", "F: X; \r\n " | |
| 338 "param1=\"=?utf-8?B?zrTPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+DzrTPg860?=\r\n " | |
| 339 "=?utf-8?B?zrEgzrTPg86xzrTPg860z4POsc60z4POsc60zrHPg860zrHPgyDOtM+DzrHOtM6x?=\r\n " | |
| 340 "=?utf-8?B?z4POtM+DzrEgzrTPg86xzrTOsc+DzrTPg86xIM60zrHPg860zrHPg860zrHPgyDOtA==?=\r\n " | |
| 341 "=?utf-8?B?zrHPg86xz4fPhs60zrTPg86xIDIwMDguZG9j?=\"", | |
| 342 p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY, 80)); // max line length = 80 | |
| 343 | |
| 344 VASSERT_EQ("3.both", "F: X; \r\n " | |
| 345 "param1=\"=?utf-8?B?zrTPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+DzrTPg860?=\r\n " | |
| 346 "=?utf-8?B?zrEgzrTPg86xzrTPg860z4POsc60z4POsc60zrHPg860zrHPgyDOtM+DzrHOtM6x?=\r\n " | |
| 347 "=?utf-8?B?z4POtM+DzrEgzrTPg86xzrTOsc+DzrTPg86xIM60zrHPg860zrHPg860zrHPgyDOtA==?=\r\n " | |
| 348 "=?utf-8?B?zrHPg86xz4fPhs60zrTPg86xIDIwMDguZG9j?=\";\r\n " | |
| 349 "param1*0*=utf-8''%CE%B4%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83;\r\n " | |
| 350 "param1*1*=%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83;\r\n " | |
| 351 "param1*2*=%CE%B4%CF%83%CE%B4%CE%B1%20%CE%B4%CF%83%CE%B1%CE%B4%CF%83%CE%B4%CF;\r\n " | |
| 352 "param1*3*=%83%CE%B1%CE%B4%CF%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CE%B1%CF%83%20;\r\n " | |
| 353 "param1*4*=%CE%B4%CF%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CF%83%CE%B1%20%CE%B4%CF;\r\n " | |
| 354 "param1*5*=%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CF%83%CE%B1%20%CE%B4%CE%B1%CF%83;\r\n " | |
| 355 "param1*6*=%CE%B4%CE%B1%CF%83%CE%B4%CE%B1%CF%83%20%CE%B4%CE%B1%CF%83%CE%B1%CF;\r\n " | |
| 356 "param1*7*=%87%CF%86%CE%B4%CE%B4%CF%83%CE%B1%202008.doc", | |
| 357 p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047, 80)); // max line length = 80 | |
| 358 | |
| 359 VASSERT_EQ("3.either", "F: X; param1*0*=utf-8''%CE%B4%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83;\r\n " | |
| 360 "param1*1*=%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83;\r\n " | |
| 361 "param1*2*=%CE%B4%CF%83%CE%B4%CE%B1%20%CE%B4%CF%83%CE%B1%CE%B4%CF%83%CE%B4%CF;\r\n " | |
| 362 "param1*3*=%83%CE%B1%CE%B4%CF%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CE%B1%CF%83%20;\r\n " | |
| 363 "param1*4*=%CE%B4%CF%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CF%83%CE%B1%20%CE%B4%CF;\r\n " | |
| 364 "param1*5*=%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CF%83%CE%B1%20%CE%B4%CE%B1%CF%83;\r\n " | |
| 365 "param1*6*=%CE%B4%CE%B1%CF%83%CE%B4%CE%B1%CF%83%20%CE%B4%CE%B1%CF%83%CE%B1%CF;\r\n " | |
| 366 "param1*7*=%87%CF%86%CE%B4%CE%B4%CF%83%CE%B1%202008.doc", | |
| 367 p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY, 80)); // max line length = 80 | |
| 368 | |
| 369 // No encoding needed | |
| 370 parameterizedHeaderField p4; | |
| 371 p4.appendParameter(vmime::make_shared <vmime::parameter>("param1", | |
| 372 vmime::word("va lue", vmime::charset("charset")))); | |
| 373 | |
| 374 VASSERT_EQ("4.no-encoding", "F: X; param1=\"va lue\"", | |
| 375 p4.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING)); | |
| 376 | |
| 377 VASSERT_EQ("4.rfc2047", "F: X; param1=\"va lue\"", | |
| 378 p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY)); | |
| 379 | |
| 380 VASSERT_EQ("4.rfc2231", "F: X; param1=\"va lue\"", | |
| 381 p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY)); | |
| 382 | |
| 383 VASSERT_EQ("4.both", "F: X; param1=\"va lue\"", | |
| 384 p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)); | |
| 385 | |
| 386 // Language specification | |
| 387 parameterizedHeaderField p5; | |
| 388 p5.appendParameter(vmime::make_shared <vmime::parameter>("param1", | |
| 389 vmime::word("This is ***fun***", vmime::charset("us-ascii"), "en-us"))); | |
| 390 | |
| 391 VASSERT_EQ("5.no-encoding", "F: X; param1=\"This is ***fun***\"", | |
| 392 p5.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING)); | |
| 393 | |
| 394 VASSERT_EQ("5.rfc2047", "F: X; param1=\"=?us-ascii*en-us?Q?This_is_***fun***?=\"", | |
| 395 p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY)); | |
| 396 | |
| 397 VASSERT_EQ("5.rfc2231", "F: X; param1*=us-ascii''This%20is%20***fun***", | |
| 398 p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY)); | |
| 399 | |
| 400 VASSERT_EQ("5.both", "F: X; " | |
| 401 "param1=\"=?us-ascii*en-us?Q?This_is_***fun***?=\";\r\n " | |
| 402 "param1*=us-ascii''This%20is%20***fun***", | |
| 403 p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)); | |
| 404 } | |
| 405 | |
| 406 void testNonStandardEncodedParam() | |
| 407 { | |
| 408 // This syntax is non-standard (expressly prohibited | |
| 409 // by RFC-2047), but is used by Mozilla: | |
| 410 // | |
| 411 // Content-Type: image/png; | |
| 412 // name="=?us-ascii?Q?Logo_VMime=2Epng?=" | |
| 413 | |
| 414 parameterizedHeaderField p1; | |
| 415 p1.parse("image/png; name=\"=?us-ascii?Q?Logo_VMime=2Epng?=\""); | |
| 416 | |
| 417 VASSERT_EQ("1.1", 1, p1.getParameterCount()); | |
| 418 VASSERT_EQ("1.2", "name", PARAM_NAME(p1, 0)); | |
| 419 VASSERT_EQ("1.3", "Logo VMime.png", PARAM_VALUE(p1, 0)); | |
| 420 | |
| 421 parameterizedHeaderField p2; | |
| 422 p2.parse("image/png; name=\"Logo =?us-ascii?Q?VMime=2Epng?=\""); | |
| 423 | |
| 424 VASSERT_EQ("2.1", 1, p2.getParameterCount()); | |
| 425 VASSERT_EQ("2.2", "name", PARAM_NAME(p2, 0)); | |
| 426 VASSERT_EQ("2.3", "Logo VMime.png", PARAM_VALUE(p2, 0)); | |
| 427 } | |
| 428 | |
| 429 // Parse parameters with non-significant whitespaces | |
| 430 void testParseNonSignificantWS() | |
| 431 { | |
| 432 parameterizedHeaderField p1; | |
| 433 p1.parse(" \t X \r\n"); | |
| 434 | |
| 435 VASSERT_EQ("1.1", "X", FIELD_VALUE(p1)); | |
| 436 | |
| 437 parameterizedHeaderField p2; | |
| 438 p2.parse(" X ; param1 = value1 \r\n"); | |
| 439 | |
| 440 VASSERT_EQ("2.1", 1, p2.getParameterCount()); | |
| 441 VASSERT_EQ("2.2", "X", FIELD_VALUE(p2)); | |
| 442 VASSERT_EQ("2.3", "param1", PARAM_NAME(p2, 0)); | |
| 443 VASSERT_EQ("2.4", "value1", PARAM_VALUE(p2, 0)); | |
| 444 } | |
| 445 | |
| 446 // Encode "tspecials" | |
| 447 void testEncodeTSpecials() | |
| 448 { | |
| 449 VASSERT_EQ(" 1", "p=\"val(ue\"", vmime::make_shared <vmime::parameter>("p", "val(ue")->generate()); | |
| 450 VASSERT_EQ(" 2", "p=\"val)ue\"", vmime::make_shared <vmime::parameter>("p", "val)ue")->generate()); | |
| 451 VASSERT_EQ(" 3", "p=\"val<ue\"", vmime::make_shared <vmime::parameter>("p", "val<ue")->generate()); | |
| 452 VASSERT_EQ(" 4", "p=\"val>ue\"", vmime::make_shared <vmime::parameter>("p", "val>ue")->generate()); | |
| 453 VASSERT_EQ(" 5", "p=\"val@ue\"", vmime::make_shared <vmime::parameter>("p", "val@ue")->generate()); | |
| 454 VASSERT_EQ(" 6", "p=\"val,ue\"", vmime::make_shared <vmime::parameter>("p", "val,ue")->generate()); | |
| 455 VASSERT_EQ(" 7", "p=\"val;ue\"", vmime::make_shared <vmime::parameter>("p", "val;ue")->generate()); | |
| 456 VASSERT_EQ(" 8", "p=\"val:ue\"", vmime::make_shared <vmime::parameter>("p", "val:ue")->generate()); | |
| 457 VASSERT_EQ(" 9", "p=\"val/ue\"", vmime::make_shared <vmime::parameter>("p", "val/ue")->generate()); | |
| 458 VASSERT_EQ("10", "p=\"val[ue\"", vmime::make_shared <vmime::parameter>("p", "val[ue")->generate()); | |
| 459 VASSERT_EQ("11", "p=\"val]ue\"", vmime::make_shared <vmime::parameter>("p", "val]ue")->generate()); | |
| 460 VASSERT_EQ("12", "p=\"val?ue\"", vmime::make_shared <vmime::parameter>("p", "val?ue")->generate()); | |
| 461 VASSERT_EQ("13", "p=\"val=ue\"", vmime::make_shared <vmime::parameter>("p", "val=ue")->generate()); | |
| 462 VASSERT_EQ("14", "p=\"val ue\"", vmime::make_shared <vmime::parameter>("p", "val ue")->generate()); | |
| 463 VASSERT_EQ("15", "p=\"val\tue\"", vmime::make_shared <vmime::parameter>("p", "val\tue")->generate()); | |
| 464 } | |
| 465 | |
| 466 // http://sourceforge.net/projects/vmime/forums/forum/237356/topic/3812278 | |
| 467 void testEncodeTSpecialsInRFC2231() | |
| 468 { | |
| 469 VASSERT_EQ("1", "filename*=UTF-8''my_file_name_%C3%B6%C3%A4%C3%BC_%281%29.txt", | |
| 470 vmime::make_shared <vmime::parameter>("filename", "my_file_name_\xc3\xb6\xc3\xa4\xc3\xbc_(1).txt")->generate()); | |
| 471 } | |
| 472 | |
| 473 void testWhitespaceBreaksTheValue() | |
| 474 { | |
| 475 parameterizedHeaderField p; | |
| 476 p.parse("xxx yyy; param1=value1 \r\n"); | |
| 477 | |
| 478 VASSERT_EQ("count", 1, p.getParameterCount()); | |
| 479 VASSERT_EQ("value", "xxx", FIELD_VALUE(p)); | |
| 480 VASSERT_EQ("param1.name", "param1", PARAM_NAME(p, 0)); | |
| 481 VASSERT_EQ("param1.value", "value1", PARAM_VALUE(p, 0)); | |
| 482 } | |
| 483 | |
| 484 VMIME_TEST_SUITE_END | |
| 485 |
