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