| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_content_disposition.h" | 5 #include "net/http/http_content_disposition.h" |
| 6 | 6 |
| 7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 9 | 9 |
| 10 namespace net { | 10 namespace net { |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 struct FileNameCDCase { | 14 struct FileNameCDCase { |
| 15 const char* header; | 15 const char* header; |
| 16 const char* referrer_charset; | 16 const char* referrer_charset; |
| 17 const wchar_t* expected; | 17 const wchar_t* expected; |
| 18 }; | 18 }; |
| 19 | 19 |
| 20 } // anonymous namespace | 20 } // anonymous namespace |
| 21 | 21 |
| 22 TEST(HttpContentDispositionTest, Filename) { | 22 TEST(HttpContentDispositionTest, Filename) { |
| 23 const FileNameCDCase tests[] = { | 23 const FileNameCDCase tests[] = { |
| 24 // Test various forms of C-D header fields emitted by web servers. | 24 // Test various forms of C-D header fields emitted by web servers. |
| 25 {"inline; filename=\"abcde.pdf\"", "", L"abcde.pdf"}, | 25 {"inline; filename=\"abcde.pdf\"", "", L"abcde.pdf"}, |
| 26 {"inline; name=\"abcde.pdf\"", "", L"abcde.pdf"}, | |
| 27 {"attachment; filename=abcde.pdf", "", L"abcde.pdf"}, | 26 {"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"}, | 27 {"attachment; filename=abc,de.pdf", "", L"abc,de.pdf"}, |
| 30 {"filename=abcde.pdf", "", L"abcde.pdf"}, | 28 {"filename=abcde.pdf", "", L"abcde.pdf"}, |
| 31 {"filename= abcde.pdf", "", L"abcde.pdf"}, | 29 {"filename= abcde.pdf", "", L"abcde.pdf"}, |
| 32 {"filename =abcde.pdf", "", L"abcde.pdf"}, | 30 {"filename =abcde.pdf", "", L"abcde.pdf"}, |
| 33 {"filename = abcde.pdf", "", L"abcde.pdf"}, | 31 {"filename = abcde.pdf", "", L"abcde.pdf"}, |
| 34 {"filename\t=abcde.pdf", "", L"abcde.pdf"}, | 32 {"filename\t=abcde.pdf", "", L"abcde.pdf"}, |
| 35 {"filename \t\t =abcde.pdf", "", L"abcde.pdf"}, | 33 {"filename \t\t =abcde.pdf", "", L"abcde.pdf"}, |
| 36 {"name=abcde.pdf", "", L"abcde.pdf"}, | |
| 37 {"inline; filename=\"abc%20de.pdf\"", "", | 34 {"inline; filename=\"abc%20de.pdf\"", "", |
| 38 L"abc de.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""}, |
| 39 // Unbalanced quotation mark | 40 // Unbalanced quotation mark |
| 40 {"filename=\"abcdef.pdf", "", L"abcdef.pdf"}, | 41 {"filename=\"abcdef.pdf", "", L"abcdef.pdf"}, |
| 41 // Whitespaces are converted to a space. | 42 // Whitespaces are converted to a space. |
| 42 {"inline; filename=\"abc \t\nde.pdf\"", "", | 43 {"inline; filename=\"abc \t\nde.pdf\"", "", |
| 43 L"abc de.pdf"}, | 44 L"abc de.pdf"}, |
| 44 // %-escaped UTF-8 | 45 // %-escaped UTF-8 |
| 45 {"attachment; filename=\"%EC%98%88%EC%88%A0%20" | 46 {"attachment; filename=\"%EC%98%88%EC%88%A0%20" |
| 46 "%EC%98%88%EC%88%A0.jpg\"", "", L"\xc608\xc220 \xc608\xc220.jpg"}, | 47 "%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 {"attachment; filename=\"%F0%90%8C%B0%F0%90%8C%B1" |
| 48 "abc.jpg\"", "", L"\U00010330\U00010331abc.jpg"}, | 49 "abc.jpg\"", "", L"\U00010330\U00010331abc.jpg"}, |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 {"attachment; filename=\"50%.html\"", | 309 {"attachment; filename=\"50%.html\"", |
| 309 HttpContentDisposition::ATTACHMENT, | 310 HttpContentDisposition::ATTACHMENT, |
| 310 L"50%.html"}, | 311 L"50%.html"}, |
| 311 // http://greenbytes.de/tech/tc2231/#attwithfnrawpctencaq | 312 // http://greenbytes.de/tech/tc2231/#attwithfnrawpctencaq |
| 312 { | 313 { |
| 313 "attachment; filename=\"foo-%\\41.html\"", | 314 "attachment; filename=\"foo-%\\41.html\"", |
| 314 HttpContentDisposition::ATTACHMENT, | 315 HttpContentDisposition::ATTACHMENT, |
| 315 L"foo-A.html" // Should be L"foo-%41.html" | 316 L"foo-A.html" // Should be L"foo-%41.html" |
| 316 }, | 317 }, |
| 317 // http://greenbytes.de/tech/tc2231/#attwithnamepct | 318 // http://greenbytes.de/tech/tc2231/#attwithnamepct |
| 319 // Value is skipped like other UAs. |
| 318 { | 320 { |
| 319 "attachment; name=\"foo-%41.html\"", | 321 "attachment; name=\"foo-%41.html\"", |
| 320 HttpContentDisposition::ATTACHMENT, | 322 HttpContentDisposition::ATTACHMENT, |
| 321 L"foo-A.html" // Should be L"foo-%41.html" | 323 L"" |
| 322 }, | 324 }, |
| 323 #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER | 325 #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER |
| 324 // http://greenbytes.de/tech/tc2231/#attwithfilenamepctandiso | 326 // http://greenbytes.de/tech/tc2231/#attwithfilenamepctandiso |
| 325 { | 327 { |
| 326 "attachment; filename=\"\xE4-%41.html\"", | 328 "attachment; filename=\"\xE4-%41.html\"", |
| 327 HttpContentDisposition::ATTACHMENT, | 329 HttpContentDisposition::ATTACHMENT, |
| 328 L"" // Should be L"\xE4-%41.htm" | 330 L"" // Should be L"\xE4-%41.htm" |
| 329 }, | 331 }, |
| 330 #endif | 332 #endif |
| 331 // http://greenbytes.de/tech/tc2231/#attwithfnrawpctenclong | 333 // http://greenbytes.de/tech/tc2231/#attwithfnrawpctenclong |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 { "filename=x", HttpContentDisposition::HAS_FILENAME }, | 474 { "filename=x", HttpContentDisposition::HAS_FILENAME }, |
| 473 { "example; filename=x", | 475 { "example; filename=x", |
| 474 HttpContentDisposition::HAS_DISPOSITION_TYPE | | 476 HttpContentDisposition::HAS_DISPOSITION_TYPE | |
| 475 HttpContentDisposition::HAS_UNKNOWN_DISPOSITION_TYPE | | 477 HttpContentDisposition::HAS_UNKNOWN_DISPOSITION_TYPE | |
| 476 HttpContentDisposition::HAS_FILENAME}, | 478 HttpContentDisposition::HAS_FILENAME}, |
| 477 { "attachment; filename=x", | 479 { "attachment; filename=x", |
| 478 HttpContentDisposition::HAS_DISPOSITION_TYPE | | 480 HttpContentDisposition::HAS_DISPOSITION_TYPE | |
| 479 HttpContentDisposition::HAS_FILENAME }, | 481 HttpContentDisposition::HAS_FILENAME }, |
| 480 { "attachment; filename=x; name=y", | 482 { "attachment; filename=x; name=y", |
| 481 HttpContentDisposition::HAS_DISPOSITION_TYPE | | 483 HttpContentDisposition::HAS_DISPOSITION_TYPE | |
| 482 HttpContentDisposition::HAS_FILENAME | | 484 HttpContentDisposition::HAS_FILENAME }, |
| 483 HttpContentDisposition::HAS_NAME }, | |
| 484 { "attachment; name=y; filename*=utf-8''foo; name=x", | 485 { "attachment; name=y; filename*=utf-8''foo; name=x", |
| 485 HttpContentDisposition::HAS_DISPOSITION_TYPE | | 486 HttpContentDisposition::HAS_DISPOSITION_TYPE | |
| 486 HttpContentDisposition::HAS_EXT_FILENAME | | 487 HttpContentDisposition::HAS_EXT_FILENAME }, |
| 487 HttpContentDisposition::HAS_NAME }, | |
| 488 | 488 |
| 489 // Feature tests for 'filename' attribute. | 489 // Feature tests for 'filename' attribute. |
| 490 { "filename=foo\xcc\x88", | 490 { "filename=foo\xcc\x88", |
| 491 HttpContentDisposition::HAS_FILENAME | | 491 HttpContentDisposition::HAS_FILENAME | |
| 492 HttpContentDisposition::HAS_NON_ASCII_STRINGS }, | 492 HttpContentDisposition::HAS_NON_ASCII_STRINGS }, |
| 493 { "filename=foo%cc%88", | 493 { "filename=foo%cc%88", |
| 494 HttpContentDisposition::HAS_FILENAME | | 494 HttpContentDisposition::HAS_FILENAME | |
| 495 HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS }, | 495 HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS }, |
| 496 { "filename==?utf-8?Q?foo?=", | 496 { "filename==?utf-8?Q?foo?=", |
| 497 HttpContentDisposition::HAS_FILENAME | | 497 HttpContentDisposition::HAS_FILENAME | |
| 498 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS }, | 498 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS }, |
| 499 { "filename=\"=?utf-8?Q?foo?=\"", | 499 { "filename=\"=?utf-8?Q?foo?=\"", |
| 500 HttpContentDisposition::HAS_FILENAME | | 500 HttpContentDisposition::HAS_FILENAME | |
| 501 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS }, | 501 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS }, |
| 502 { "filename==?utf-8?Q?foo?", HttpContentDisposition::INVALID }, | 502 { "filename==?utf-8?Q?foo?", HttpContentDisposition::INVALID }, |
| 503 { "name=foo\xcc\x88", | 503 |
| 504 HttpContentDisposition::HAS_NAME }, | 504 // Test 'name' isn't a synonym for 'filename'. |
| 505 { "name=foo\xcc\x88", HttpContentDisposition::INVALID }, |
| 505 | 506 |
| 506 // Shouldn't set |has_non_ascii_strings| based on 'name' attribute. | 507 // Shouldn't set |has_non_ascii_strings| based on 'name' attribute. |
| 507 { "filename=x; name=foo\xcc\x88", | 508 { "filename=x; name=foo\xcc\x88", |
| 508 HttpContentDisposition::HAS_FILENAME | | 509 HttpContentDisposition::HAS_FILENAME }, |
| 509 HttpContentDisposition::HAS_NAME }, | |
| 510 { "filename=foo\xcc\x88 foo%cc%88 =?utf-8?Q?foo?=", | 510 { "filename=foo\xcc\x88 foo%cc%88 =?utf-8?Q?foo?=", |
| 511 HttpContentDisposition::HAS_FILENAME | | 511 HttpContentDisposition::HAS_FILENAME | |
| 512 HttpContentDisposition::HAS_NON_ASCII_STRINGS | | 512 HttpContentDisposition::HAS_NON_ASCII_STRINGS | |
| 513 HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS | | 513 HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS | |
| 514 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS }, | 514 HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS }, |
| 515 | 515 |
| 516 // If 'filename' attribute is invalid, should set any flags based on it. | 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?", | 517 { "filename=foo\xcc\x88 foo%cc%88 =?utf-8?Q?foo?", |
| 518 HttpContentDisposition::INVALID }, | 518 HttpContentDisposition::INVALID }, |
| 519 { "filename=foo\xcc\x88 foo%cc%88 =?utf-8?Q?foo?; name=x", | 519 { "filename=foo\xcc\x88 foo%cc%88 =?utf-8?Q?foo?; name=x", |
| 520 HttpContentDisposition::HAS_NAME }, | 520 HttpContentDisposition::INVALID }, |
| 521 }; | 521 }; |
| 522 | 522 |
| 523 for (size_t i = 0; i < arraysize(kTestCases); ++i) { | 523 for (size_t i = 0; i < arraysize(kTestCases); ++i) { |
| 524 const ParseResultTestCase& test_case = kTestCases[i]; | 524 const ParseResultTestCase& test_case = kTestCases[i]; |
| 525 HttpContentDisposition content_disposition(test_case.header, "utf-8"); | 525 HttpContentDisposition content_disposition(test_case.header, "utf-8"); |
| 526 int result = content_disposition.parse_result_flags(); | 526 int result = content_disposition.parse_result_flags(); |
| 527 | 527 |
| 528 SCOPED_TRACE(testing::Message() << "Test case " << i | 528 SCOPED_TRACE(testing::Message() << "Test case " << i |
| 529 << " with header " << test_case.header); | 529 << " with header " << test_case.header); |
| 530 EXPECT_EQ(test_case.expected_flags, result); | 530 EXPECT_EQ(test_case.expected_flags, result); |
| 531 } | 531 } |
| 532 } | 532 } |
| 533 | 533 |
| 534 } // namespace net | 534 } // namespace net |
| OLD | NEW |