Roll src/third_party/WebKit 57aef96:a1089e6 (svn 201978:201979)
[chromium-blink-merge.git] / net / http / http_content_disposition_unittest.cc
blobd3e4c33571ec891024ac03dfcdffe1939bb63d6b
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_content_disposition.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "testing/gtest/include/gtest/gtest.h"
10 namespace net {
12 namespace {
14 struct FileNameCDCase {
15 const char* header;
16 const char* referrer_charset;
17 const wchar_t* expected;
20 } // anonymous namespace
22 TEST(HttpContentDispositionTest, Filename) {
23 const FileNameCDCase tests[] = {
24 // Test various forms of C-D header fields emitted by web servers.
25 {"inline; filename=\"abcde.pdf\"", "", L"abcde.pdf"},
26 {"attachment; filename=abcde.pdf", "", L"abcde.pdf"},
27 {"attachment; filename=abc,de.pdf", "", L"abc,de.pdf"},
28 {"filename=abcde.pdf", "", L"abcde.pdf"},
29 {"filename= abcde.pdf", "", L"abcde.pdf"},
30 {"filename =abcde.pdf", "", L"abcde.pdf"},
31 {"filename = abcde.pdf", "", L"abcde.pdf"},
32 {"filename\t=abcde.pdf", "", L"abcde.pdf"},
33 {"filename \t\t =abcde.pdf", "", L"abcde.pdf"},
34 {"inline; filename=\"abc%20de.pdf\"", "",
35 L"abc de.pdf"},
36 // Name values are no longer synonyms for filename.
37 {"inline; name=\"abcde.pdf\"", "", L""},
38 {"attachment; name=abcde.pdf", "", L""},
39 {"name=abcde.pdf", "", L""},
40 // Unbalanced quotation mark
41 {"filename=\"abcdef.pdf", "", L"abcdef.pdf"},
42 // Whitespaces are converted to a space.
43 {"inline; filename=\"abc \t\nde.pdf\"", "",
44 L"abc de.pdf"},
45 // %-escaped UTF-8
46 {"attachment; filename=\"%EC%98%88%EC%88%A0%20"
47 "%EC%98%88%EC%88%A0.jpg\"", "", L"\xc608\xc220 \xc608\xc220.jpg"},
48 {"attachment; filename=\"%F0%90%8C%B0%F0%90%8C%B1"
49 "abc.jpg\"", "", L"\U00010330\U00010331abc.jpg"},
50 {"attachment; filename=\"%EC%98%88%EC%88%A0 \n"
51 "%EC%98%88%EC%88%A0.jpg\"", "", L"\xc608\xc220 \xc608\xc220.jpg"},
52 // RFC 2047 with various charsets and Q/B encodings
53 {"attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
54 "D13=2Epng?=\"", "", L"\x82b8\x8853" L"3.png"},
55 {"attachment; filename==?eUc-Kr?b?v7m8+iAzLnBuZw==?=",
56 "", L"\xc608\xc220 3.png"},
57 {"attachment; filename==?utf-8?Q?=E8=8A=B8=E8"
58 "=A1=93_3=2Epng?=", "", L"\x82b8\x8853 3.png"},
59 {"attachment; filename==?utf-8?Q?=F0=90=8C=B0"
60 "_3=2Epng?=", "", L"\U00010330 3.png"},
61 {"inline; filename=\"=?iso88591?Q?caf=e9_=2epng?=\"",
62 "", L"caf\x00e9 .png"},
63 // Space after an encoded word should be removed.
64 {"inline; filename=\"=?iso88591?Q?caf=E9_?= .png\"",
65 "", L"caf\x00e9 .png"},
66 // Two encoded words with different charsets (not very likely to be emitted
67 // by web servers in the wild). Spaces between them are removed.
68 {"inline; filename=\"=?euc-kr?b?v7m8+iAz?="
69 " =?ksc5601?q?=BF=B9=BC=FA=2Epng?=\"", "",
70 L"\xc608\xc220 3\xc608\xc220.png"},
71 {"attachment; filename=\"=?windows-1252?Q?caf=E9?="
72 " =?iso-8859-7?b?4eI=?= .png\"", "", L"caf\x00e9\x03b1\x03b2.png"},
73 // Non-ASCII string is passed through and treated as UTF-8 as long as
74 // it's valid as UTF-8 and regardless of |referrer_charset|.
75 {"attachment; filename=caf\xc3\xa9.png",
76 "iso-8859-1", L"caf\x00e9.png"},
77 {"attachment; filename=caf\xc3\xa9.png",
78 "", L"caf\x00e9.png"},
79 // Non-ASCII/Non-UTF-8 string. Fall back to the referrer charset.
80 {"attachment; filename=caf\xe5.png",
81 "windows-1253", L"caf\x03b5.png"},
82 #if 0
83 // Non-ASCII/Non-UTF-8 string. Fall back to the native codepage.
84 // TODO(jungshik): We need to set the OS default codepage
85 // to a specific value before testing. On Windows, we can use
86 // SetThreadLocale().
87 {"attachment; filename=\xb0\xa1\xb0\xa2.png",
88 "", L"\xac00\xac01.png"},
89 #endif
90 // Failure cases
91 // Invalid hex-digit "G"
92 {"attachment; filename==?iiso88591?Q?caf=EG?=", "",
93 L""},
94 // Incomplete RFC 2047 encoded-word (missing '='' at the end)
95 {"attachment; filename==?iso88591?Q?caf=E3?", "", L""},
96 // Extra character at the end of an encoded word
97 {"attachment; filename==?iso88591?Q?caf=E3?==",
98 "", L""},
99 // Extra token at the end of an encoded word
100 {"attachment; filename==?iso88591?Q?caf=E3?=?",
101 "", L""},
102 {"attachment; filename==?iso88591?Q?caf=E3?=?=",
103 "", L""},
104 // Incomplete hex-escaped chars
105 {"attachment; filename==?windows-1252?Q?=63=61=E?=",
106 "", L""},
107 {"attachment; filename=%EC%98%88%EC%88%A", "", L""},
108 // %-escaped non-UTF-8 encoding is an "error"
109 {"attachment; filename=%B7%DD%BD%D1.png", "", L""},
110 // Two RFC 2047 encoded words in a row without a space is an error.
111 {"attachment; filename==?windows-1252?Q?caf=E3?="
112 "=?iso-8859-7?b?4eIucG5nCg==?=", "", L""},
114 // RFC 5987 tests with Filename* : see http://tools.ietf.org/html/rfc5987
115 {"attachment; filename*=foo.html", "", L""},
116 {"attachment; filename*=foo'.html", "", L""},
117 {"attachment; filename*=''foo'.html", "", L""},
118 {"attachment; filename*=''foo.html'", "", L""},
119 {"attachment; filename*=''f\"oo\".html'", "", L""},
120 {"attachment; filename*=bogus_charset''foo.html'",
121 "", L""},
122 {"attachment; filename*='en'foo.html'", "", L""},
123 {"attachment; filename*=iso-8859-1'en'foo.html", "",
124 L"foo.html"},
125 {"attachment; filename*=utf-8'en'foo.html", "",
126 L"foo.html"},
127 // charset cannot be omitted.
128 {"attachment; filename*='es'f\xfa.html'", "", L""},
129 // Non-ASCII bytes are not allowed.
130 {"attachment; filename*=iso-8859-1'es'f\xfa.html", "",
131 L""},
132 {"attachment; filename*=utf-8'es'f\xce\xba.html", "",
133 L""},
134 // TODO(jshin): Space should be %-encoded, but currently, we allow
135 // spaces.
136 {"inline; filename*=iso88591''cafe foo.png", "",
137 L"cafe foo.png"},
139 // Filename* tests converted from Q-encoded tests above.
140 {"attachment; filename*=EUC-JP''%B7%DD%BD%D13%2Epng",
141 "", L"\x82b8\x8853" L"3.png"},
142 {"attachment; filename*=utf-8''"
143 "%E8%8A%B8%E8%A1%93%203%2Epng", "", L"\x82b8\x8853 3.png"},
144 {"attachment; filename*=utf-8''%F0%90%8C%B0 3.png", "",
145 L"\U00010330 3.png"},
146 {"inline; filename*=Euc-Kr'ko'%BF%B9%BC%FA%2Epng", "",
147 L"\xc608\xc220.png"},
148 {"attachment; filename*=windows-1252''caf%E9.png", "",
149 L"caf\x00e9.png"},
151 // Multiple filename, filename*, name parameters specified.
152 {"attachment; name=\"foo\"; filename=\"bar\"", "", L"bar"},
153 {"attachment; filename=\"bar\"; name=\"foo\"", "", L"bar"},
154 {"attachment; filename=\"bar\"; filename*=utf-8''baz", "", L"baz"},
156 // http://greenbytes.de/tech/tc2231/ filename* test cases.
157 // attwithisofn2231iso
158 {"attachment; filename*=iso-8859-1''foo-%E4.html", "",
159 L"foo-\xe4.html"},
160 // attwithfn2231utf8
161 {"attachment; filename*="
162 "UTF-8''foo-%c3%a4-%e2%82%ac.html", "", L"foo-\xe4-\x20ac.html"},
163 // attwithfn2231noc : no encoding specified but UTF-8 is used.
164 {"attachment; filename*=''foo-%c3%a4-%e2%82%ac.html",
165 "", L""},
166 // attwithfn2231utf8comp
167 {"attachment; filename*=UTF-8''foo-a%cc%88.html", "",
168 L"foo-\xe4.html"},
169 #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER
170 // This does not work because we treat ISO-8859-1 synonymous with
171 // Windows-1252 per HTML5. For HTTP, in theory, we're not
172 // supposed to.
173 // attwithfn2231utf8-bad
174 {"attachment; filename*="
175 "iso-8859-1''foo-%c3%a4-%e2%82%ac.html", "", L""},
176 #endif
177 // attwithfn2231ws1
178 {"attachment; filename *=UTF-8''foo-%c3%a4.html", "",
179 L""},
180 // attwithfn2231ws2
181 {"attachment; filename*= UTF-8''foo-%c3%a4.html", "",
182 L"foo-\xe4.html"},
183 // attwithfn2231ws3
184 {"attachment; filename* =UTF-8''foo-%c3%a4.html", "",
185 L"foo-\xe4.html"},
186 // attwithfn2231quot
187 {"attachment; filename*=\"UTF-8''foo-%c3%a4.html\"",
188 "", L""},
189 // attfnboth
190 {"attachment; filename=\"foo-ae.html\"; "
191 "filename*=UTF-8''foo-%c3%a4.html", "", L"foo-\xe4.html"},
192 // attfnboth2
193 {"attachment; filename*=UTF-8''foo-%c3%a4.html; "
194 "filename=\"foo-ae.html\"", "", L"foo-\xe4.html"},
195 // attnewandfn
196 {"attachment; foobar=x; filename=\"foo.html\"", "",
197 L"foo.html"},
199 for (size_t i = 0; i < arraysize(tests); ++i) {
200 HttpContentDisposition header(tests[i].header, tests[i].referrer_charset);
201 EXPECT_EQ(tests[i].expected,
202 base::UTF8ToWide(header.filename()))
203 << "Failed on input: " << tests[i].header;
207 // Test cases from http://greenbytes.de/tech/tc2231/
208 TEST(HttpContentDispositionTest, tc2231) {
209 const struct FileNameCDCase {
210 const char* header;
211 HttpContentDisposition::Type expected_type;
212 const wchar_t* expected_filename;
213 } tests[] = {
214 // http://greenbytes.de/tech/tc2231/#inlonly
215 {"inline", HttpContentDisposition::INLINE, L""},
216 // http://greenbytes.de/tech/tc2231/#inlonlyquoted
217 {"\"inline\"", HttpContentDisposition::INLINE, L""},
218 // http://greenbytes.de/tech/tc2231/#inlwithasciifilename
219 {"inline; filename=\"foo.html\"",
220 HttpContentDisposition::INLINE,
221 L"foo.html"},
222 // http://greenbytes.de/tech/tc2231/#inlwithfnattach
223 {"inline; filename=\"Not an attachment!\"",
224 HttpContentDisposition::INLINE,
225 L"Not an attachment!"},
226 // http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf
227 {"inline; filename=\"foo.pdf\"",
228 HttpContentDisposition::INLINE,
229 L"foo.pdf"},
230 // http://greenbytes.de/tech/tc2231/#attonly
231 {"attachment", HttpContentDisposition::ATTACHMENT, L""},
232 // http://greenbytes.de/tech/tc2231/#attonlyquoted
233 {"\"attachment\"", HttpContentDisposition::INLINE, L""},
234 // http://greenbytes.de/tech/tc2231/#attonly403
235 // TODO(abarth): This isn't testable in this unit test.
236 // http://greenbytes.de/tech/tc2231/#attonlyucase
237 {"ATTACHMENT", HttpContentDisposition::ATTACHMENT, L""},
238 // http://greenbytes.de/tech/tc2231/#attwithasciifilename
239 {"attachment; filename=\"foo.html\"",
240 HttpContentDisposition::ATTACHMENT,
241 L"foo.html"},
242 // http://greenbytes.de/tech/tc2231/#attwithasciifnescapedchar
243 {"attachment; filename=\"f\\oo.html\"",
244 HttpContentDisposition::ATTACHMENT,
245 L"foo.html"},
246 // http://greenbytes.de/tech/tc2231/#attwithasciifnescapedquote
247 {"attachment; filename=\"\\\"quoting\\\" tested.html\"",
248 HttpContentDisposition::ATTACHMENT,
249 L"\"quoting\" tested.html"},
250 // http://greenbytes.de/tech/tc2231/#attwithquotedsemicolon
251 {"attachment; filename=\"Here's a semicolon;.html\"",
252 HttpContentDisposition::ATTACHMENT,
253 L"Here's a semicolon;.html"},
254 // http://greenbytes.de/tech/tc2231/#attwithfilenameandextparam
255 {"attachment; foo=\"bar\"; filename=\"foo.html\"",
256 HttpContentDisposition::ATTACHMENT,
257 L"foo.html"},
258 // http://greenbytes.de/tech/tc2231/#attwithfilenameandextparamescaped
259 {"attachment; foo=\"\\\"\\\\\";filename=\"foo.html\"",
260 HttpContentDisposition::ATTACHMENT,
261 L"foo.html"},
262 // http://greenbytes.de/tech/tc2231/#attwithasciifilenameucase
263 {"attachment; FILENAME=\"foo.html\"",
264 HttpContentDisposition::ATTACHMENT,
265 L"foo.html"},
266 // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenq
267 {"attachment; filename=foo.html",
268 HttpContentDisposition::ATTACHMENT,
269 L"foo.html"},
270 // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenqs
271 // Note: tc2231 says we should fail to parse this header.
272 {"attachment; filename=foo.html ;",
273 HttpContentDisposition::ATTACHMENT,
274 L"foo.html"},
275 // http://greenbytes.de/tech/tc2231/#attemptyparam
276 // Note: tc2231 says we should fail to parse this header.
277 {"attachment; ;filename=foo", HttpContentDisposition::ATTACHMENT, L"foo"},
278 // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenqws
279 // Note: tc2231 says we should fail to parse this header.
280 {"attachment; filename=foo bar.html",
281 HttpContentDisposition::ATTACHMENT,
282 L"foo bar.html"},
283 // http://greenbytes.de/tech/tc2231/#attwithfntokensq
285 "attachment; filename='foo.bar'",
286 HttpContentDisposition::ATTACHMENT,
287 L"foo.bar" // Should be L"'foo.bar'"
289 #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER
290 // http://greenbytes.de/tech/tc2231/#attwithisofnplain
292 "attachment; filename=\"foo-\xE4html\"",
293 HttpContentDisposition::ATTACHMENT,
294 L"" // Should be L"foo-\xE4.html"
296 #endif
297 // http://greenbytes.de/tech/tc2231/#attwithutf8fnplain
298 // Note: We'll UTF-8 decode the file name, even though tc2231 says not to.
299 {"attachment; filename=\"foo-\xC3\xA4.html\"",
300 HttpContentDisposition::ATTACHMENT,
301 L"foo-\xE4.html"},
302 // http://greenbytes.de/tech/tc2231/#attwithfnrawpctenca
304 "attachment; filename=\"foo-%41.html\"",
305 HttpContentDisposition::ATTACHMENT,
306 L"foo-A.html" // Should be L"foo-%41.html"
308 // http://greenbytes.de/tech/tc2231/#attwithfnusingpct
309 {"attachment; filename=\"50%.html\"",
310 HttpContentDisposition::ATTACHMENT,
311 L"50%.html"},
312 // http://greenbytes.de/tech/tc2231/#attwithfnrawpctencaq
314 "attachment; filename=\"foo-%\\41.html\"",
315 HttpContentDisposition::ATTACHMENT,
316 L"foo-A.html" // Should be L"foo-%41.html"
318 // http://greenbytes.de/tech/tc2231/#attwithnamepct
319 // Value is skipped like other UAs.
321 "attachment; name=\"foo-%41.html\"",
322 HttpContentDisposition::ATTACHMENT,
325 #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER
326 // http://greenbytes.de/tech/tc2231/#attwithfilenamepctandiso
328 "attachment; filename=\"\xE4-%41.html\"",
329 HttpContentDisposition::ATTACHMENT,
330 L"" // Should be L"\xE4-%41.htm"
332 #endif
333 // http://greenbytes.de/tech/tc2231/#attwithfnrawpctenclong
335 "attachment; filename=\"foo-%c3%a4-%e2%82%ac.html\"",
336 HttpContentDisposition::ATTACHMENT,
337 L"foo-\xE4-\u20AC.html" // Should be L"foo-%c3%a4-%e2%82%ac.html"
339 // http://greenbytes.de/tech/tc2231/#attwithasciifilenamews1
340 {"attachment; filename =\"foo.html\"",
341 HttpContentDisposition::ATTACHMENT,
342 L"foo.html"},
343 // http://greenbytes.de/tech/tc2231/#attwith2filenames
344 // Note: tc2231 says we should fail to parse this header.
345 {"attachment; filename=\"foo.html\"; filename=\"bar.html\"",
346 HttpContentDisposition::ATTACHMENT,
347 L"foo.html"},
348 // http://greenbytes.de/tech/tc2231/#attfnbrokentoken
349 // Note: tc2231 says we should fail to parse this header.
350 {"attachment; filename=foo[1](2).html",
351 HttpContentDisposition::ATTACHMENT,
352 L"foo[1](2).html"},
353 #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER
354 // http://greenbytes.de/tech/tc2231/#attfnbrokentokeniso
355 // Note: tc2231 says we should fail to parse this header.
356 {"attachment; filename=foo-\xE4.html",
357 HttpContentDisposition::ATTACHMENT,
358 L""},
359 #endif
360 // http://greenbytes.de/tech/tc2231/#attfnbrokentokenutf
361 // Note: tc2231 says we should fail to parse this header.
362 {"attachment; filename=foo-\xC3\xA4.html",
363 HttpContentDisposition::ATTACHMENT,
364 L"foo-\xE4.html"},
365 // http://greenbytes.de/tech/tc2231/#attmissingdisposition
366 // Note: tc2231 says we should fail to parse this header.
367 {"filename=foo.html", HttpContentDisposition::INLINE, L"foo.html"},
368 // http://greenbytes.de/tech/tc2231/#attmissingdisposition2
369 // Note: tc2231 says we should fail to parse this header.
370 {"x=y; filename=foo.html", HttpContentDisposition::INLINE, L"foo.html"},
371 // http://greenbytes.de/tech/tc2231/#attmissingdisposition3
372 // Note: tc2231 says we should fail to parse this header.
374 "\"foo; filename=bar;baz\"; filename=qux",
375 HttpContentDisposition::INLINE,
376 L"" // Firefox gets qux
378 // http://greenbytes.de/tech/tc2231/#attmissingdisposition4
379 // Note: tc2231 says we should fail to parse this header.
380 {"filename=foo.html, filename=bar.html",
381 HttpContentDisposition::INLINE,
382 L"foo.html, filename=bar.html"},
383 // http://greenbytes.de/tech/tc2231/#emptydisposition
384 // Note: tc2231 says we should fail to parse this header.
385 {"; filename=foo.html", HttpContentDisposition::INLINE, L"foo.html"},
386 // http://greenbytes.de/tech/tc2231/#attandinline
387 // Note: tc2231 says we should fail to parse this header.
388 {"inline; attachment; filename=foo.html",
389 HttpContentDisposition::INLINE,
390 L""},
391 // http://greenbytes.de/tech/tc2231/#attandinline2
392 // Note: tc2231 says we should fail to parse this header.
393 {"attachment; inline; filename=foo.html",
394 HttpContentDisposition::ATTACHMENT,
395 L""},
396 // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn
397 // Note: tc2231 says we should fail to parse this header.
398 {"attachment; filename=\"foo.html\".txt",
399 HttpContentDisposition::ATTACHMENT,
400 L"foo.html\".txt"},
401 // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn2
402 // Note: tc2231 says we should fail to parse this header.
403 {"attachment; filename=\"bar",
404 HttpContentDisposition::ATTACHMENT,
405 L"bar"},
406 // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn3
407 // Note: tc2231 says we should fail to parse this header.
408 {"attachment; filename=foo\"bar;baz\"qux",
409 HttpContentDisposition::ATTACHMENT,
410 L"foo\"bar;baz\"qux"},
411 // http://greenbytes.de/tech/tc2231/#attmultinstances
412 // Note: tc2231 says we should fail to parse this header.
413 {"attachment; filename=foo.html, attachment; filename=bar.html",
414 HttpContentDisposition::ATTACHMENT,
415 L"foo.html, attachment"},
416 // http://greenbytes.de/tech/tc2231/#attmissingdelim
417 {"attachment; foo=foo filename=bar",
418 HttpContentDisposition::ATTACHMENT,
419 L""},
420 // http://greenbytes.de/tech/tc2231/#attreversed
421 // Note: tc2231 says we should fail to parse this header.
422 {"filename=foo.html; attachment",
423 HttpContentDisposition::INLINE,
424 L"foo.html"},
425 // http://greenbytes.de/tech/tc2231/#attconfusedparam
426 {"attachment; xfilename=foo.html",
427 HttpContentDisposition::ATTACHMENT,
428 L""},
429 // http://greenbytes.de/tech/tc2231/#attabspath
430 {"attachment; filename=\"/foo.html\"",
431 HttpContentDisposition::ATTACHMENT,
432 L"/foo.html"},
433 // http://greenbytes.de/tech/tc2231/#attabspathwin
434 {"attachment; filename=\"\\\\foo.html\"",
435 HttpContentDisposition::ATTACHMENT,
436 L"\\foo.html"},
437 // http://greenbytes.de/tech/tc2231/#dispext
438 {"foobar", HttpContentDisposition::ATTACHMENT, L""},
439 // http://greenbytes.de/tech/tc2231/#dispextbadfn
440 {"attachment; example=\"filename=example.txt\"",
441 HttpContentDisposition::ATTACHMENT,
442 L""},
443 // http://greenbytes.de/tech/tc2231/#attnewandfn
444 {"attachment; foobar=x; filename=\"foo.html\"",
445 HttpContentDisposition::ATTACHMENT,
446 L"foo.html"},
447 // TODO(abarth): Add the filename* tests, but check
448 // HttpContentDispositionTest.Filename for overlap.
449 // TODO(abarth): http://greenbytes.de/tech/tc2231/#attrfc2047token
450 // TODO(abarth): http://greenbytes.de/tech/tc2231/#attrfc2047quoted
452 for (size_t i = 0; i < arraysize(tests); ++i) {
453 HttpContentDisposition header(tests[i].header, std::string());
454 EXPECT_EQ(tests[i].expected_type, header.type())
455 << "Failed on input: " << tests[i].header;
456 EXPECT_EQ(tests[i].expected_filename, base::UTF8ToWide(header.filename()))
457 << "Failed on input: " << tests[i].header;
461 TEST(HttpContentDispositionTest, ParseResult) {
462 const struct ParseResultTestCase {
463 const char* header;
464 int expected_flags;
465 } kTestCases[] = {
466 // Basic feature tests
467 { "", HttpContentDisposition::INVALID },
468 { "example=x", HttpContentDisposition::INVALID },
469 { "attachment; filename=", HttpContentDisposition::HAS_DISPOSITION_TYPE },
470 { "attachment; name=", HttpContentDisposition::HAS_DISPOSITION_TYPE },
471 { "attachment; filename*=", HttpContentDisposition::HAS_DISPOSITION_TYPE },
472 { "attachment; filename==?utf-8?Q?\?=",
473 HttpContentDisposition::HAS_DISPOSITION_TYPE },
474 { "filename=x", HttpContentDisposition::HAS_FILENAME },
475 { "example; filename=x",
476 HttpContentDisposition::HAS_DISPOSITION_TYPE |
477 HttpContentDisposition::HAS_UNKNOWN_DISPOSITION_TYPE |
478 HttpContentDisposition::HAS_FILENAME},
479 { "attachment; filename=x",
480 HttpContentDisposition::HAS_DISPOSITION_TYPE |
481 HttpContentDisposition::HAS_FILENAME },
482 { "attachment; filename=x; name=y",
483 HttpContentDisposition::HAS_DISPOSITION_TYPE |
484 HttpContentDisposition::HAS_FILENAME },
485 { "attachment; name=y; filename*=utf-8''foo; name=x",
486 HttpContentDisposition::HAS_DISPOSITION_TYPE |
487 HttpContentDisposition::HAS_EXT_FILENAME },
489 // Feature tests for 'filename' attribute.
490 { "filename=foo\xcc\x88",
491 HttpContentDisposition::HAS_FILENAME |
492 HttpContentDisposition::HAS_NON_ASCII_STRINGS },
493 { "filename=foo%cc%88",
494 HttpContentDisposition::HAS_FILENAME |
495 HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS },
496 { "filename==?utf-8?Q?foo?=",
497 HttpContentDisposition::HAS_FILENAME |
498 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS },
499 { "filename=\"=?utf-8?Q?foo?=\"",
500 HttpContentDisposition::HAS_FILENAME |
501 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS },
502 { "filename==?utf-8?Q?foo?", HttpContentDisposition::INVALID },
504 // Test 'name' isn't a synonym for 'filename'.
505 { "name=foo\xcc\x88", HttpContentDisposition::INVALID },
507 // Shouldn't set |has_non_ascii_strings| based on 'name' attribute.
508 { "filename=x; name=foo\xcc\x88",
509 HttpContentDisposition::HAS_FILENAME },
510 { "filename=foo\xcc\x88 foo%cc%88 =?utf-8?Q?foo?=",
511 HttpContentDisposition::HAS_FILENAME |
512 HttpContentDisposition::HAS_NON_ASCII_STRINGS |
513 HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS |
514 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS },
516 // If 'filename' attribute is invalid, should set any flags based on it.
517 { "filename=foo\xcc\x88 foo%cc%88 =?utf-8?Q?foo?",
518 HttpContentDisposition::INVALID },
519 { "filename=foo\xcc\x88 foo%cc%88 =?utf-8?Q?foo?; name=x",
520 HttpContentDisposition::INVALID },
523 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
524 const ParseResultTestCase& test_case = kTestCases[i];
525 HttpContentDisposition content_disposition(test_case.header, "utf-8");
526 int result = content_disposition.parse_result_flags();
528 SCOPED_TRACE(testing::Message() << "Test case " << i
529 << " with header " << test_case.header);
530 EXPECT_EQ(test_case.expected_flags, result);
534 } // namespace net