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