netwerk/test/unit/test_MIME_params.js

changeset 1
ca08bd8f51b2
equal deleted inserted replaced
-1:000000000000 0:466de17ae361
1 /**
2 * Tests for parsing header fields using the syntax used in
3 * Content-Disposition and Content-Type
4 *
5 * See also https://bugzilla.mozilla.org/show_bug.cgi?id=609667
6 */
7
8 var BS = '\\';
9 var DQUOTE = '"';
10
11 // Test array:
12 // - element 0: "Content-Disposition" header to test
13 // under MIME (email):
14 // - element 1: correct value returned for disposition-type (empty param name)
15 // - element 2: correct value for filename returned
16 // under HTTP:
17 // (currently supports continuations; expected results without continuations
18 // are commented out for now)
19 // - element 3: correct value returned for disposition-type (empty param name)
20 // - element 4: correct value for filename returned
21 //
22 // 3 and 4 may be left out if they are identical
23
24 var tests = [
25 // No filename parameter: return nothing
26 ["attachment;",
27 "attachment", Cr.NS_ERROR_INVALID_ARG],
28
29 // basic
30 ["attachment; filename=basic",
31 "attachment", "basic"],
32
33 // extended
34 ["attachment; filename*=UTF-8''extended",
35 "attachment", "extended"],
36
37 // prefer extended to basic (bug 588781)
38 ["attachment; filename=basic; filename*=UTF-8''extended",
39 "attachment", "extended"],
40
41 // prefer extended to basic (bug 588781)
42 ["attachment; filename*=UTF-8''extended; filename=basic",
43 "attachment", "extended"],
44
45 // use first basic value (invalid; error recovery)
46 ["attachment; filename=first; filename=wrong",
47 "attachment", "first"],
48
49 // old school bad HTTP servers: missing 'attachment' or 'inline'
50 // (invalid; error recovery)
51 ["filename=old",
52 "filename=old", "old"],
53
54 ["attachment; filename*=UTF-8''extended",
55 "attachment", "extended"],
56
57 // continuations not part of RFC 5987 (bug 610054)
58 ["attachment; filename*0=foo; filename*1=bar",
59 "attachment", "foobar",
60 /* "attachment", Cr.NS_ERROR_INVALID_ARG */],
61
62 // Return first continuation (invalid; error recovery)
63 ["attachment; filename*0=first; filename*0=wrong; filename=basic",
64 "attachment", "first",
65 /* "attachment", "basic" */],
66
67 // Only use correctly ordered continuations (invalid; error recovery)
68 ["attachment; filename*0=first; filename*1=second; filename*0=wrong",
69 "attachment", "firstsecond",
70 /* "attachment", Cr.NS_ERROR_INVALID_ARG */],
71
72 // prefer continuation to basic (unless RFC 5987)
73 ["attachment; filename=basic; filename*0=foo; filename*1=bar",
74 "attachment", "foobar",
75 /* "attachment", "basic" */],
76
77 // Prefer extended to basic and/or (broken or not) continuation
78 // (invalid; error recovery)
79 ["attachment; filename=basic; filename*0=first; filename*0=wrong; filename*=UTF-8''extended",
80 "attachment", "extended"],
81
82 // RFC 2231 not clear on correct outcome: we prefer non-continued extended
83 // (invalid; error recovery)
84 ["attachment; filename=basic; filename*=UTF-8''extended; filename*0=foo; filename*1=bar",
85 "attachment", "extended"],
86
87 // Gaps should result in returning only value until gap hit
88 // (invalid; error recovery)
89 ["attachment; filename*0=foo; filename*2=bar",
90 "attachment", "foo",
91 /* "attachment", Cr.NS_ERROR_INVALID_ARG */],
92
93 // Don't allow leading 0's (*01) (invalid; error recovery)
94 ["attachment; filename*0=foo; filename*01=bar",
95 "attachment", "foo",
96 /* "attachment", Cr.NS_ERROR_INVALID_ARG */],
97
98 // continuations should prevail over non-extended (unless RFC 5987)
99 ["attachment; filename=basic; filename*0*=UTF-8''multi;\r\n"
100 + " filename*1=line;\r\n"
101 + " filename*2*=%20extended",
102 "attachment", "multiline extended",
103 /* "attachment", "basic" */],
104
105 // Gaps should result in returning only value until gap hit
106 // (invalid; error recovery)
107 ["attachment; filename=basic; filename*0*=UTF-8''multi;\r\n"
108 + " filename*1=line;\r\n"
109 + " filename*3*=%20extended",
110 "attachment", "multiline",
111 /* "attachment", "basic" */],
112
113 // First series, only please, and don't slurp up higher elements (*2 in this
114 // case) from later series into earlier one (invalid; error recovery)
115 ["attachment; filename=basic; filename*0*=UTF-8''multi;\r\n"
116 + " filename*1=line;\r\n"
117 + " filename*0*=UTF-8''wrong;\r\n"
118 + " filename*1=bad;\r\n"
119 + " filename*2=evil",
120 "attachment", "multiline",
121 /* "attachment", "basic" */],
122
123 // RFC 2231 not clear on correct outcome: we prefer non-continued extended
124 // (invalid; error recovery)
125 ["attachment; filename=basic; filename*0=UTF-8''multi\r\n;"
126 + " filename*=UTF-8''extended;\r\n"
127 + " filename*1=line;\r\n"
128 + " filename*2*=%20extended",
129 "attachment", "extended"],
130
131 // sneaky: if unescaped, make sure we leave UTF-8'' in value
132 ["attachment; filename*0=UTF-8''unescaped;\r\n"
133 + " filename*1*=%20so%20includes%20UTF-8''%20in%20value",
134 "attachment", "UTF-8''unescaped so includes UTF-8'' in value",
135 /* "attachment", Cr.NS_ERROR_INVALID_ARG */],
136
137 // sneaky: if unescaped, make sure we leave UTF-8'' in value
138 ["attachment; filename=basic; filename*0=UTF-8''unescaped;\r\n"
139 + " filename*1*=%20so%20includes%20UTF-8''%20in%20value",
140 "attachment", "UTF-8''unescaped so includes UTF-8'' in value",
141 /* "attachment", "basic" */],
142
143 // Prefer basic over invalid continuation
144 // (invalid; error recovery)
145 ["attachment; filename=basic; filename*1=multi;\r\n"
146 + " filename*2=line;\r\n"
147 + " filename*3*=%20extended",
148 "attachment", "basic"],
149
150 // support digits over 10
151 ["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
152 + " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
153 + " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
154 + " filename*11=b; filename*12=c;filename*13=d;filename*14=e;filename*15=f\r\n",
155 "attachment", "0123456789abcdef",
156 /* "attachment", "basic" */],
157
158 // support digits over 10 (detect gaps)
159 ["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
160 + " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
161 + " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
162 + " filename*11=b; filename*12=c;filename*14=e\r\n",
163 "attachment", "0123456789abc",
164 /* "attachment", "basic" */],
165
166 // return nothing: invalid
167 // (invalid; error recovery)
168 ["attachment; filename*1=multi;\r\n"
169 + " filename*2=line;\r\n"
170 + " filename*3*=%20extended",
171 "attachment", Cr.NS_ERROR_INVALID_ARG],
172
173 // Bug 272541: Empty disposition type treated as "attachment"
174
175 // sanity check
176 ["attachment; filename=foo.html",
177 "attachment", "foo.html",
178 "attachment", "foo.html"],
179
180 // the actual bug
181 ["; filename=foo.html",
182 Cr.NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY, "foo.html",
183 Cr.NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY, "foo.html"],
184
185 // regression check, but see bug 671204
186 ["filename=foo.html",
187 "filename=foo.html", "foo.html",
188 "filename=foo.html", "foo.html"],
189
190 // Bug 384571: RFC 2231 parameters not decoded when appearing in reversed order
191
192 // check ordering
193 ["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
194 + " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
195 + " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
196 + " filename*11=b; filename*12=c;filename*13=d;filename*15=f;filename*14=e;\r\n",
197 "attachment", "0123456789abcdef",
198 /* "attachment", "basic" */],
199
200 // check non-digits in sequence numbers
201 ["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
202 + " filename*1a=1\r\n",
203 "attachment", "0",
204 /* "attachment", "basic" */],
205
206 // check duplicate sequence numbers
207 ["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
208 + " filename*0=bad; filename*1=1;\r\n",
209 "attachment", "0",
210 /* "attachment", "basic" */],
211
212 // check overflow
213 ["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
214 + " filename*11111111111111111111111111111111111111111111111111111111111=1",
215 "attachment", "0",
216 /* "attachment", "basic" */],
217
218 // check underflow
219 ["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
220 + " filename*-1=1",
221 "attachment", "0",
222 /* "attachment", "basic" */],
223
224 // check mixed token/quoted-string
225 ["attachment; filename=basic; filename*0=\"0\";\r\n"
226 + " filename*1=1;\r\n"
227 + " filename*2*=%32",
228 "attachment", "012",
229 /* "attachment", "basic" */],
230
231 // check empty sequence number
232 ["attachment; filename=basic; filename**=UTF-8''0\r\n",
233 "attachment", "basic",
234 "attachment", "basic"],
235
236
237 // Bug 419157: ensure that a MIME parameter with no charset information
238 // fallbacks to Latin-1
239
240 ["attachment;filename=IT839\x04\xB5(m8)2.pdf;",
241 "attachment", "IT839\u0004\u00b5(m8)2.pdf"],
242
243 // Bug 588389: unescaping backslashes in quoted string parameters
244
245 // '\"', should be parsed as '"'
246 ["attachment; filename=" + DQUOTE + (BS + DQUOTE) + DQUOTE,
247 "attachment", DQUOTE],
248
249 // 'a\"b', should be parsed as 'a"b'
250 ["attachment; filename=" + DQUOTE + 'a' + (BS + DQUOTE) + 'b' + DQUOTE,
251 "attachment", "a" + DQUOTE + "b"],
252
253 // '\x', should be parsed as 'x'
254 ["attachment; filename=" + DQUOTE + (BS + "x") + DQUOTE,
255 "attachment", "x"],
256
257 // test empty param (quoted-string)
258 ["attachment; filename=" + DQUOTE + DQUOTE,
259 "attachment", ""],
260
261 // test empty param
262 ["attachment; filename=",
263 "attachment", ""],
264
265 // Bug 601933: RFC 2047 does not apply to parameters (at least in HTTP)
266 ["attachment; filename==?ISO-8859-1?Q?foo-=E4.html?=",
267 "attachment", "foo-\u00e4.html",
268 /* "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" */],
269
270 ["attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"",
271 "attachment", "foo-\u00e4.html",
272 /* "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" */],
273
274 // format sent by GMail as of 2012-07-23 (5987 overrides 2047)
275 ["attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"; filename*=UTF-8''5987",
276 "attachment", "5987"],
277
278 // Bug 651185: double quotes around 2231/5987 encoded param
279 // Change reverted to backwards compat issues with various web services,
280 // such as OWA (Bug 703015), plus similar problems in Thunderbird. If this
281 // is tried again in the future, email probably needs to be special-cased.
282
283 // sanity check
284 ["attachment; filename*=utf-8''%41",
285 "attachment", "A"],
286
287 // the actual bug
288 ["attachment; filename*=" + DQUOTE + "utf-8''%41" + DQUOTE,
289 "attachment", "A"],
290 // previously with the fix for 651185:
291 // "attachment", Cr.NS_ERROR_INVALID_ARG],
292
293 // Bug 670333: Content-Disposition parser does not require presence of "="
294 // in params
295
296 // sanity check
297 ["attachment; filename*=UTF-8''foo-%41.html",
298 "attachment", "foo-A.html"],
299
300 // the actual bug
301 ["attachment; filename *=UTF-8''foo-%41.html",
302 "attachment", Cr.NS_ERROR_INVALID_ARG],
303
304 // the actual bug, without 2231/5987 encoding
305 ["attachment; filename X",
306 "attachment", Cr.NS_ERROR_INVALID_ARG],
307
308 // sanity check with WS on both sides
309 ["attachment; filename = foo-A.html",
310 "attachment", "foo-A.html"],
311
312 // Bug 685192: in RFC2231/5987 encoding, a missing charset field should be
313 // treated as error
314
315 // the actual bug
316 ["attachment; filename*=''foo",
317 "attachment", "foo"],
318 // previously with the fix for 692574:
319 // "attachment", Cr.NS_ERROR_INVALID_ARG],
320
321 // sanity check
322 ["attachment; filename*=a''foo",
323 "attachment", "foo"],
324
325 // Bug 692574: RFC2231/5987 decoding should not tolerate missing single
326 // quotes
327
328 // one missing
329 ["attachment; filename*=UTF-8'foo-%41.html",
330 "attachment", "foo-A.html"],
331 // previously with the fix for 692574:
332 // "attachment", Cr.NS_ERROR_INVALID_ARG],
333
334 // both missing
335 ["attachment; filename*=foo-%41.html",
336 "attachment","foo-A.html"],
337 // previously with the fix for 692574:
338 // "attachment", Cr.NS_ERROR_INVALID_ARG],
339
340 // make sure fallback works
341 ["attachment; filename*=UTF-8'foo-%41.html; filename=bar.html",
342 "attachment", "foo-A.html"],
343 // previously with the fix for 692574:
344 // "attachment", "bar.html"],
345
346 // Bug 693806: RFC2231/5987 encoding: charset information should be treated
347 // as authoritative
348
349 // UTF-8 labeled ISO-8859-1
350 ["attachment; filename*=ISO-8859-1''%c3%a4",
351 "attachment", "\u00c3\u00a4"],
352
353 // UTF-8 labeled ISO-8859-1, but with octets not allowed in ISO-8859-1
354 // accepts x82, understands it as Win1252, maps it to Unicode \u20a1
355 ["attachment; filename*=ISO-8859-1''%e2%82%ac",
356 "attachment", "\u00e2\u201a\u00ac"],
357
358 // defective UTF-8
359 ["attachment; filename*=UTF-8''A%e4B",
360 "attachment", Cr.NS_ERROR_INVALID_ARG],
361
362 // defective UTF-8, with fallback
363 ["attachment; filename*=UTF-8''A%e4B; filename=fallback",
364 "attachment", "fallback"],
365
366 // defective UTF-8 (continuations), with fallback
367 ["attachment; filename*0*=UTF-8''A%e4B; filename=fallback",
368 "attachment", "fallback"],
369
370 // check that charsets aren't mixed up
371 ["attachment; filename*0*=ISO-8859-15''euro-sign%3d%a4; filename*=ISO-8859-1''currency-sign%3d%a4",
372 "attachment", "currency-sign=\u00a4"],
373
374 // same as above, except reversed
375 ["attachment; filename*=ISO-8859-1''currency-sign%3d%a4; filename*0*=ISO-8859-15''euro-sign%3d%a4",
376 "attachment", "currency-sign=\u00a4"],
377
378 // Bug 704989: add workaround for broken Outlook Web App (OWA)
379 // attachment handling
380
381 ["attachment; filename*=\"a%20b\"",
382 "attachment", "a b"],
383
384 // Bug 717121: crash nsMIMEHeaderParamImpl::DoParameterInternal
385
386 ["attachment; filename=\"",
387 "attachment", ""],
388
389 // We used to read past string if last param w/o = and ;
390 // Note: was only detected on windows PGO builds
391 ["attachment; filename=foo; trouble",
392 "attachment", "foo"],
393
394 // Same, followed by space, hits another case
395 ["attachment; filename=foo; trouble ",
396 "attachment", "foo"],
397
398 ["attachment",
399 "attachment", Cr.NS_ERROR_INVALID_ARG],
400
401 // Bug 730574: quoted-string in RFC2231-continuations not handled
402
403 ['attachment; filename=basic; filename*0="foo"; filename*1="\\b\\a\\r.html"',
404 "attachment", "foobar.html",
405 /* "attachment", "basic" */],
406
407 // unmatched escape char
408 ['attachment; filename=basic; filename*0="foo"; filename*1="\\b\\a\\',
409 "attachment", "fooba\\",
410 /* "attachment", "basic" */],
411
412 // Bug 732369: Content-Disposition parser does not require presence of ";" between params
413 // optimally, this would not even return the disposition type "attachment"
414
415 ["attachment; extension=bla filename=foo",
416 "attachment", Cr.NS_ERROR_INVALID_ARG],
417
418 ["attachment; filename=foo extension=bla",
419 "attachment", "foo"],
420
421 ["attachment filename=foo",
422 "attachment", Cr.NS_ERROR_INVALID_ARG],
423
424 // Bug 777687: handling of broken %escapes
425
426 ["attachment; filename*=UTF-8''f%oo; filename=bar",
427 "attachment", "bar"],
428
429 ["attachment; filename*=UTF-8''foo%; filename=bar",
430 "attachment", "bar"],
431
432 // Bug 783502 - xpcshell test netwerk/test/unit/test_MIME_params.js fails on AddressSanitizer
433 ['attachment; filename="\\b\\a\\',
434 "attachment", "ba\\"],
435 ];
436
437 var rfc5987paramtests = [
438 [ // basic test
439 "UTF-8'language'value", "value", "language", Cr.NS_OK ],
440 [ // percent decoding
441 "UTF-8''1%202", "1 2", "", Cr.NS_OK ],
442 [ // UTF-8
443 "UTF-8''%c2%a3%20and%20%e2%82%ac%20rates", "\u00a3 and \u20ac rates", "", Cr.NS_OK ],
444 [ // missing charset
445 "''abc", "", "", Cr.NS_ERROR_INVALID_ARG ],
446 [ // ISO-8859-1: unsupported
447 "ISO-8859-1''%A3%20rates", "", "", Cr.NS_ERROR_INVALID_ARG ],
448 [ // unknown charset
449 "foo''abc", "", "", Cr.NS_ERROR_INVALID_ARG ],
450 [ // missing component
451 "abc", "", "", Cr.NS_ERROR_INVALID_ARG ],
452 [ // missing component
453 "'abc", "", "", Cr.NS_ERROR_INVALID_ARG ],
454 [ // illegal chars
455 "UTF-8''a b", "", "", Cr.NS_ERROR_INVALID_ARG ],
456 [ // broken % escapes
457 "UTF-8''a%zz", "", "", Cr.NS_ERROR_INVALID_ARG ],
458 [ // broken % escapes
459 "UTF-8''a%b", "", "", Cr.NS_ERROR_INVALID_ARG ],
460 [ // broken % escapes
461 "UTF-8''a%", "", "", Cr.NS_ERROR_INVALID_ARG ],
462 [ // broken UTF-8
463 "UTF-8''%A3%20rates", "", "", 0x8050000E /* NS_ERROR_UDEC_ILLEGALINPUT */ ],
464 ];
465
466 function do_tests(whichRFC)
467 {
468 var mhp = Components.classes["@mozilla.org/network/mime-hdrparam;1"]
469 .getService(Components.interfaces.nsIMIMEHeaderParam);
470
471 var unused = { value : null };
472
473 for (var i = 0; i < tests.length; ++i) {
474 dump("Testing #" + i + ": " + tests[i] + "\n");
475
476 // check disposition type
477 var expectedDt = tests[i].length == 3 || whichRFC == 0 ? tests[i][1] : tests[i][3];
478
479 try {
480 var result;
481
482 if (whichRFC == 0)
483 result = mhp.getParameter(tests[i][0], "", "UTF-8", true, unused);
484 else
485 result = mhp.getParameterHTTP(tests[i][0], "", "UTF-8", true, unused);
486
487 do_check_eq(result, expectedDt);
488 }
489 catch (e) {
490 // Tests can also succeed by expecting to fail with given error code
491 if (e.result) {
492 // Allow following tests to run by catching exception from do_check_eq()
493 try {
494 do_check_eq(e.result, expectedDt);
495 } catch(e) {}
496 }
497 continue;
498 }
499
500 // check filename parameter
501 var expectedFn = tests[i].length == 3 || whichRFC == 0 ? tests[i][2] : tests[i][4];
502
503 try {
504 var result;
505
506 if (whichRFC == 0)
507 result = mhp.getParameter(tests[i][0], "filename", "UTF-8", true, unused);
508 else
509 result = mhp.getParameterHTTP(tests[i][0], "filename", "UTF-8", true, unused);
510
511 do_check_eq(result, expectedFn);
512 }
513 catch (e) {
514 // Tests can also succeed by expecting to fail with given error code
515 if (e.result) {
516 // Allow following tests to run by catching exception from do_check_eq()
517 try {
518 do_check_eq(e.result, expectedFn);
519 } catch(e) {}
520 }
521 continue;
522 }
523 }
524 }
525
526 function test_decode5987Param() {
527 var mhp = Components.classes["@mozilla.org/network/mime-hdrparam;1"]
528 .getService(Components.interfaces.nsIMIMEHeaderParam);
529
530 for (var i = 0; i < rfc5987paramtests.length; ++i) {
531 dump("Testing #" + i + ": " + rfc5987paramtests[i] + "\n");
532
533 var lang = {};
534 try {
535 var decoded = mhp.decodeRFC5987Param(rfc5987paramtests[i][0], lang);
536 if (rfc5987paramtests[i][3] == Cr.NS_OK) {
537 do_check_eq(rfc5987paramtests[i][1], decoded);
538 do_check_eq(rfc5987paramtests[i][2], lang.value);
539 }
540 else {
541 do_check_eq(rfc5987paramtests[i][3], "instead got: " + decoded);
542 }
543 }
544 catch (e) {
545 do_check_eq(rfc5987paramtests[i][3], e.result);
546 }
547 }
548 }
549
550 function run_test() {
551
552 // Test RFC 2231 (complete header field values)
553 do_tests(0);
554
555 // Test RFC 5987 (complete header field values)
556 do_tests(1);
557
558 // tests for RFC5987 parameter parsing
559 test_decode5987Param();
560 }

mercurial