1 // Copyright 2014 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/base/filename_util.h" 6 7 #include "base/files/file_path.h" 8 #include "base/files/file_util.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "base/test/test_file_util.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "url/gurl.h" 14 15 namespace net { 16 17 namespace { 18 19 struct FileCase { 20 const wchar_t* file; 21 const char* url; 22 }; 23 24 struct GenerateFilenameCase { 25 int lineno; 26 const char* url; 27 const char* content_disp_header; 28 const char* referrer_charset; 29 const char* suggested_filename; 30 const char* mime_type; 31 const wchar_t* default_filename; 32 const wchar_t* expected_filename; 33 }; 34 35 // The expected filenames are coded as wchar_t for convenience. 36 std::wstring FilePathAsWString(const base::FilePath& path) { 37 #if defined(OS_WIN) 38 return path.value(); 39 #else 40 return base::UTF8ToWide(path.value()); 41 #endif 42 } 43 base::FilePath WStringAsFilePath(const std::wstring& str) { 44 #if defined(OS_WIN) 45 return base::FilePath(str); 46 #else 47 return base::FilePath(base::WideToUTF8(str)); 48 #endif 49 } 50 51 void RunGenerateFileNameTestCase(const GenerateFilenameCase* test_case) { 52 std::string default_filename(base::WideToUTF8(test_case->default_filename)); 53 base::FilePath file_path = GenerateFileName( 54 GURL(test_case->url), test_case->content_disp_header, 55 test_case->referrer_charset, test_case->suggested_filename, 56 test_case->mime_type, default_filename); 57 EXPECT_EQ(test_case->expected_filename, FilePathAsWString(file_path)) 58 << "test case at line number: " << test_case->lineno; 59 } 60 61 } // namespace 62 63 static const base::FilePath::CharType* kSafePortableBasenames[] = { 64 FILE_PATH_LITERAL("a"), 65 FILE_PATH_LITERAL("a.txt"), 66 FILE_PATH_LITERAL("a b.txt"), 67 FILE_PATH_LITERAL("a-b.txt"), 68 FILE_PATH_LITERAL("My Computer"), 69 FILE_PATH_LITERAL(" Computer"), 70 }; 71 72 static const base::FilePath::CharType* kUnsafePortableBasenames[] = { 73 FILE_PATH_LITERAL(""), 74 FILE_PATH_LITERAL("."), 75 FILE_PATH_LITERAL(".."), 76 FILE_PATH_LITERAL("..."), 77 FILE_PATH_LITERAL("con"), 78 FILE_PATH_LITERAL("con.zip"), 79 FILE_PATH_LITERAL("NUL"), 80 FILE_PATH_LITERAL("NUL.zip"), 81 FILE_PATH_LITERAL(".a"), 82 FILE_PATH_LITERAL("a."), 83 FILE_PATH_LITERAL("a\"a"), 84 FILE_PATH_LITERAL("a<a"), 85 FILE_PATH_LITERAL("a>a"), 86 FILE_PATH_LITERAL("a?a"), 87 FILE_PATH_LITERAL("a/"), 88 FILE_PATH_LITERAL("a\\"), 89 FILE_PATH_LITERAL("a "), 90 FILE_PATH_LITERAL("a . ."), 91 FILE_PATH_LITERAL("My Computer.{a}"), 92 FILE_PATH_LITERAL("My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}"), 93 #if !defined(OS_WIN) 94 FILE_PATH_LITERAL("a\\a"), 95 #endif 96 }; 97 98 static const base::FilePath::CharType* kSafePortableRelativePaths[] = { 99 FILE_PATH_LITERAL("a/a"), 100 #if defined(OS_WIN) 101 FILE_PATH_LITERAL("a\\a"), 102 #endif 103 }; 104 105 TEST(FilenameUtilTest, IsSafePortablePathComponent) { 106 for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) { 107 EXPECT_TRUE(IsSafePortablePathComponent(base::FilePath( 108 kSafePortableBasenames[i]))) << kSafePortableBasenames[i]; 109 } 110 for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) { 111 EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath( 112 kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i]; 113 } 114 for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) { 115 EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath( 116 kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i]; 117 } 118 } 119 120 TEST(FilenameUtilTest, IsSafePortableRelativePath) { 121 base::FilePath safe_dirname(FILE_PATH_LITERAL("a")); 122 for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) { 123 EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath( 124 kSafePortableBasenames[i]))) << kSafePortableBasenames[i]; 125 EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath( 126 kSafePortableBasenames[i])))) << kSafePortableBasenames[i]; 127 } 128 for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) { 129 EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath( 130 kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i]; 131 EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath( 132 kSafePortableRelativePaths[i])))) << kSafePortableRelativePaths[i]; 133 } 134 for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) { 135 EXPECT_FALSE(IsSafePortableRelativePath(base::FilePath( 136 kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i]; 137 if (!base::FilePath::StringType(kUnsafePortableBasenames[i]).empty()) { 138 EXPECT_FALSE(IsSafePortableRelativePath(safe_dirname.Append( 139 base::FilePath(kUnsafePortableBasenames[i])))) 140 << kUnsafePortableBasenames[i]; 141 } 142 } 143 } 144 145 TEST(FilenameUtilTest, FileURLConversion) { 146 // a list of test file names and the corresponding URLs 147 const FileCase round_trip_cases[] = { 148 #if defined(OS_WIN) 149 {L"C:\\foo\\bar.txt", "file:///C:/foo/bar.txt"}, 150 {L"\\\\some computer\\foo\\bar.txt", 151 "file://some%20computer/foo/bar.txt"}, // UNC 152 {L"D:\\Name;with%some symbols*#", 153 "file:///D:/Name%3Bwith%25some%20symbols*%23"}, 154 // issue 14153: To be tested with the OS default codepage other than 1252. 155 {L"D:\\latin1\\caf\x00E9\x00DD.txt", 156 "file:///D:/latin1/caf%C3%A9%C3%9D.txt"}, 157 {L"D:\\otherlatin\\caf\x0119.txt", 158 "file:///D:/otherlatin/caf%C4%99.txt"}, 159 {L"D:\\greek\\\x03B1\x03B2\x03B3.txt", 160 "file:///D:/greek/%CE%B1%CE%B2%CE%B3.txt"}, 161 {L"D:\\Chinese\\\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc", 162 "file:///D:/Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD%91" 163 "%E9%A1%B5.doc"}, 164 {L"D:\\plane1\\\xD835\xDC00\xD835\xDC01.txt", // Math alphabet "AB" 165 "file:///D:/plane1/%F0%9D%90%80%F0%9D%90%81.txt"}, 166 #elif defined(OS_POSIX) 167 {L"/foo/bar.txt", "file:///foo/bar.txt"}, 168 {L"/foo/BAR.txt", "file:///foo/BAR.txt"}, 169 {L"/C:/foo/bar.txt", "file:///C:/foo/bar.txt"}, 170 {L"/foo/bar?.txt", "file:///foo/bar%3F.txt"}, 171 {L"/some computer/foo/bar.txt", "file:///some%20computer/foo/bar.txt"}, 172 {L"/Name;with%some symbols*#", "file:///Name%3Bwith%25some%20symbols*%23"}, 173 {L"/latin1/caf\x00E9\x00DD.txt", "file:///latin1/caf%C3%A9%C3%9D.txt"}, 174 {L"/otherlatin/caf\x0119.txt", "file:///otherlatin/caf%C4%99.txt"}, 175 {L"/greek/\x03B1\x03B2\x03B3.txt", "file:///greek/%CE%B1%CE%B2%CE%B3.txt"}, 176 {L"/Chinese/\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc", 177 "file:///Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD" 178 "%91%E9%A1%B5.doc"}, 179 {L"/plane1/\x1D400\x1D401.txt", // Math alphabet "AB" 180 "file:///plane1/%F0%9D%90%80%F0%9D%90%81.txt"}, 181 #endif 182 }; 183 184 // First, we'll test that we can round-trip all of the above cases of URLs 185 base::FilePath output; 186 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(round_trip_cases); i++) { 187 // convert to the file URL 188 GURL file_url(FilePathToFileURL( 189 WStringAsFilePath(round_trip_cases[i].file))); 190 EXPECT_EQ(round_trip_cases[i].url, file_url.spec()); 191 192 // Back to the filename. 193 EXPECT_TRUE(FileURLToFilePath(file_url, &output)); 194 EXPECT_EQ(round_trip_cases[i].file, FilePathAsWString(output)); 195 } 196 197 // Test that various file: URLs get decoded into the correct file type 198 FileCase url_cases[] = { 199 #if defined(OS_WIN) 200 {L"C:\\foo\\bar.txt", "file:c|/foo\\bar.txt"}, 201 {L"C:\\foo\\bar.txt", "file:/c:/foo/bar.txt"}, 202 {L"\\\\foo\\bar.txt", "file://foo\\bar.txt"}, 203 {L"C:\\foo\\bar.txt", "file:///c:/foo/bar.txt"}, 204 {L"\\\\foo\\bar.txt", "file:////foo\\bar.txt"}, 205 {L"\\\\foo\\bar.txt", "file:/foo/bar.txt"}, 206 {L"\\\\foo\\bar.txt", "file://foo\\bar.txt"}, 207 {L"C:\\foo\\bar.txt", "file:\\\\\\c:/foo/bar.txt"}, 208 #elif defined(OS_POSIX) 209 {L"/c:/foo/bar.txt", "file:/c:/foo/bar.txt"}, 210 {L"/c:/foo/bar.txt", "file:///c:/foo/bar.txt"}, 211 {L"/foo/bar.txt", "file:/foo/bar.txt"}, 212 {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"}, 213 {L"/foo/bar.txt", "file:foo/bar.txt"}, 214 {L"/bar.txt", "file://foo/bar.txt"}, 215 {L"/foo/bar.txt", "file:///foo/bar.txt"}, 216 {L"/foo/bar.txt", "file:////foo/bar.txt"}, 217 {L"/foo/bar.txt", "file:////foo//bar.txt"}, 218 {L"/foo/bar.txt", "file:////foo///bar.txt"}, 219 {L"/foo/bar.txt", "file:////foo////bar.txt"}, 220 {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"}, 221 {L"/c:/foo/bar.txt", "file:c:/foo/bar.txt"}, 222 // We get these wrong because GURL turns back slashes into forward 223 // slashes. 224 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"}, 225 //{L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"}, 226 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"}, 227 //{L"/foo%5Cbar.txt", "file:////foo\\bar.txt"}, 228 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"}, 229 #endif 230 }; 231 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_cases); i++) { 232 FileURLToFilePath(GURL(url_cases[i].url), &output); 233 EXPECT_EQ(url_cases[i].file, FilePathAsWString(output)); 234 } 235 236 // Unfortunately, UTF8ToWide discards invalid UTF8 input. 237 #ifdef BUG_878908_IS_FIXED 238 // Test that no conversion happens if the UTF-8 input is invalid, and that 239 // the input is preserved in UTF-8 240 const char invalid_utf8[] = "file:///d:/Blah/\xff.doc"; 241 const wchar_t invalid_wide[] = L"D:\\Blah\\\xff.doc"; 242 EXPECT_TRUE(FileURLToFilePath( 243 GURL(std::string(invalid_utf8)), &output)); 244 EXPECT_EQ(std::wstring(invalid_wide), output); 245 #endif 246 247 // Test that if a file URL is malformed, we get a failure 248 EXPECT_FALSE(FileURLToFilePath(GURL("filefoobar"), &output)); 249 } 250 251 #if defined(OS_WIN) 252 #define JPEG_EXT L".jpg" 253 #define HTML_EXT L".htm" 254 #elif defined(OS_MACOSX) 255 #define JPEG_EXT L".jpeg" 256 #define HTML_EXT L".html" 257 #else 258 #define JPEG_EXT L".jpg" 259 #define HTML_EXT L".html" 260 #endif 261 #define TXT_EXT L".txt" 262 #define TAR_EXT L".tar" 263 264 TEST(FilenameUtilTest, GenerateSafeFileName) { 265 const struct { 266 const char* mime_type; 267 const base::FilePath::CharType* filename; 268 const base::FilePath::CharType* expected_filename; 269 } safe_tests[] = { 270 #if defined(OS_WIN) 271 { 272 "text/html", 273 FILE_PATH_LITERAL("C:\\foo\\bar.htm"), 274 FILE_PATH_LITERAL("C:\\foo\\bar.htm") 275 }, 276 { 277 "text/html", 278 FILE_PATH_LITERAL("C:\\foo\\bar.html"), 279 FILE_PATH_LITERAL("C:\\foo\\bar.html") 280 }, 281 { 282 "text/html", 283 FILE_PATH_LITERAL("C:\\foo\\bar"), 284 FILE_PATH_LITERAL("C:\\foo\\bar.htm") 285 }, 286 { 287 "image/png", 288 FILE_PATH_LITERAL("C:\\bar.html"), 289 FILE_PATH_LITERAL("C:\\bar.html") 290 }, 291 { 292 "image/png", 293 FILE_PATH_LITERAL("C:\\bar"), 294 FILE_PATH_LITERAL("C:\\bar.png") 295 }, 296 { 297 "text/html", 298 FILE_PATH_LITERAL("C:\\foo\\bar.exe"), 299 FILE_PATH_LITERAL("C:\\foo\\bar.exe") 300 }, 301 { 302 "image/gif", 303 FILE_PATH_LITERAL("C:\\foo\\bar.exe"), 304 FILE_PATH_LITERAL("C:\\foo\\bar.exe") 305 }, 306 { 307 "text/html", 308 FILE_PATH_LITERAL("C:\\foo\\google.com"), 309 FILE_PATH_LITERAL("C:\\foo\\google.com") 310 }, 311 { 312 "text/html", 313 FILE_PATH_LITERAL("C:\\foo\\con.htm"), 314 FILE_PATH_LITERAL("C:\\foo\\_con.htm") 315 }, 316 { 317 "text/html", 318 FILE_PATH_LITERAL("C:\\foo\\con"), 319 FILE_PATH_LITERAL("C:\\foo\\_con.htm") 320 }, 321 { 322 "text/html", 323 FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"), 324 FILE_PATH_LITERAL("C:\\foo\\harmless.download") 325 }, 326 { 327 "text/html", 328 FILE_PATH_LITERAL("C:\\foo\\harmless.local"), 329 FILE_PATH_LITERAL("C:\\foo\\harmless.download") 330 }, 331 { 332 "text/html", 333 FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"), 334 FILE_PATH_LITERAL("C:\\foo\\harmless.download") 335 }, 336 { 337 "text/html", 338 FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"), 339 FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-") 340 }, 341 // Allow extension synonyms. 342 { 343 "image/jpeg", 344 FILE_PATH_LITERAL("C:\\foo\\bar.jpg"), 345 FILE_PATH_LITERAL("C:\\foo\\bar.jpg") 346 }, 347 { 348 "image/jpeg", 349 FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"), 350 FILE_PATH_LITERAL("C:\\foo\\bar.jpeg") 351 }, 352 #else // !defined(OS_WIN) 353 { 354 "text/html", 355 FILE_PATH_LITERAL("/foo/bar.htm"), 356 FILE_PATH_LITERAL("/foo/bar.htm") 357 }, 358 { 359 "text/html", 360 FILE_PATH_LITERAL("/foo/bar.html"), 361 FILE_PATH_LITERAL("/foo/bar.html") 362 }, 363 { 364 "text/html", 365 FILE_PATH_LITERAL("/foo/bar"), 366 FILE_PATH_LITERAL("/foo/bar.html") 367 }, 368 { 369 "image/png", 370 FILE_PATH_LITERAL("/bar.html"), 371 FILE_PATH_LITERAL("/bar.html") 372 }, 373 { 374 "image/png", 375 FILE_PATH_LITERAL("/bar"), 376 FILE_PATH_LITERAL("/bar.png") 377 }, 378 { 379 "image/gif", 380 FILE_PATH_LITERAL("/foo/bar.exe"), 381 FILE_PATH_LITERAL("/foo/bar.exe") 382 }, 383 { 384 "text/html", 385 FILE_PATH_LITERAL("/foo/google.com"), 386 FILE_PATH_LITERAL("/foo/google.com") 387 }, 388 { 389 "text/html", 390 FILE_PATH_LITERAL("/foo/con.htm"), 391 FILE_PATH_LITERAL("/foo/con.htm") 392 }, 393 { 394 "text/html", 395 FILE_PATH_LITERAL("/foo/con"), 396 FILE_PATH_LITERAL("/foo/con.html") 397 }, 398 // Allow extension synonyms. 399 { 400 "image/jpeg", 401 FILE_PATH_LITERAL("/bar.jpg"), 402 FILE_PATH_LITERAL("/bar.jpg") 403 }, 404 { 405 "image/jpeg", 406 FILE_PATH_LITERAL("/bar.jpeg"), 407 FILE_PATH_LITERAL("/bar.jpeg") 408 }, 409 #endif // !defined(OS_WIN) 410 }; 411 412 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(safe_tests); ++i) { 413 base::FilePath file_path(safe_tests[i].filename); 414 GenerateSafeFileName(safe_tests[i].mime_type, false, &file_path); 415 EXPECT_EQ(safe_tests[i].expected_filename, file_path.value()) 416 << "Iteration " << i; 417 } 418 } 419 420 TEST(FilenameUtilTest, GenerateFileName) { 421 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 422 // This test doesn't run when the locale is not UTF-8 because some of the 423 // string conversions fail. This is OK (we have the default value) but they 424 // don't match our expectations. 425 std::string locale = setlocale(LC_CTYPE, NULL); 426 base::StringToLowerASCII(&locale); 427 EXPECT_TRUE(locale.find("utf-8") != std::string::npos || 428 locale.find("utf8") != std::string::npos) 429 << "Your locale (" << locale << ") must be set to UTF-8 " 430 << "for this test to pass!"; 431 #endif 432 433 // Tests whether the correct filename is selected from the the given 434 // parameters and that Content-Disposition headers are properly 435 // handled including failovers when the header is malformed. 436 const GenerateFilenameCase selection_tests[] = { 437 { 438 __LINE__, 439 "http://www.google.com/", 440 "attachment; filename=test.html", 441 "", 442 "", 443 "", 444 L"", 445 L"test.html" 446 }, 447 { 448 __LINE__, 449 "http://www.google.com/", 450 "attachment; filename=\"test.html\"", 451 "", 452 "", 453 "", 454 L"", 455 L"test.html" 456 }, 457 { 458 __LINE__, 459 "http://www.google.com/", 460 "attachment; filename= \"test.html\"", 461 "", 462 "", 463 "", 464 L"", 465 L"test.html" 466 }, 467 { 468 __LINE__, 469 "http://www.google.com/", 470 "attachment; filename = \"test.html\"", 471 "", 472 "", 473 "", 474 L"", 475 L"test.html" 476 }, 477 { // filename is whitespace. Should failover to URL host 478 __LINE__, 479 "http://www.google.com/", 480 "attachment; filename= ", 481 "", 482 "", 483 "", 484 L"", 485 L"www.google.com" 486 }, 487 { // No filename. 488 __LINE__, 489 "http://www.google.com/path/test.html", 490 "attachment", 491 "", 492 "", 493 "", 494 L"", 495 L"test.html" 496 }, 497 { // Ditto 498 __LINE__, 499 "http://www.google.com/path/test.html", 500 "attachment;", 501 "", 502 "", 503 "", 504 L"", 505 L"test.html" 506 }, 507 { // No C-D 508 __LINE__, 509 "http://www.google.com/", 510 "", 511 "", 512 "", 513 "", 514 L"", 515 L"www.google.com" 516 }, 517 { 518 __LINE__, 519 "http://www.google.com/test.html", 520 "", 521 "", 522 "", 523 "", 524 L"", 525 L"test.html" 526 }, 527 { // Now that we use src/url's ExtractFileName, this case falls back to 528 // the hostname. If this behavior is not desirable, we'd better change 529 // ExtractFileName (in url_parse.cc). 530 __LINE__, 531 "http://www.google.com/path/", 532 "", 533 "", 534 "", 535 "", 536 L"", 537 L"www.google.com" 538 }, 539 { 540 __LINE__, 541 "http://www.google.com/path", 542 "", 543 "", 544 "", 545 "", 546 L"", 547 L"path" 548 }, 549 { 550 __LINE__, 551 "file:///", 552 "", 553 "", 554 "", 555 "", 556 L"", 557 L"download" 558 }, 559 { 560 __LINE__, 561 "file:///path/testfile", 562 "", 563 "", 564 "", 565 "", 566 L"", 567 L"testfile" 568 }, 569 { 570 __LINE__, 571 "non-standard-scheme:", 572 "", 573 "", 574 "", 575 "", 576 L"", 577 L"download" 578 }, 579 { // C-D should override default 580 __LINE__, 581 "http://www.google.com/", 582 "attachment; filename =\"test.html\"", 583 "", 584 "", 585 "", 586 L"download", 587 L"test.html" 588 }, 589 { // But the URL shouldn't 590 __LINE__, 591 "http://www.google.com/", 592 "", 593 "", 594 "", 595 "", 596 L"download", 597 L"download" 598 }, 599 { 600 __LINE__, 601 "http://www.google.com/", 602 "attachment; filename=\"../test.html\"", 603 "", 604 "", 605 "", 606 L"", 607 L"-test.html" 608 }, 609 { 610 __LINE__, 611 "http://www.google.com/", 612 "attachment; filename=\"..\\test.html\"", 613 "", 614 "", 615 "", 616 L"", 617 L"test.html" 618 }, 619 { 620 __LINE__, 621 "http://www.google.com/", 622 "attachment; filename=\"..\\\\test.html\"", 623 "", 624 "", 625 "", 626 L"", 627 L"-test.html" 628 }, 629 { // Filename disappears after leading and trailing periods are removed. 630 __LINE__, 631 "http://www.google.com/", 632 "attachment; filename=\"..\"", 633 "", 634 "", 635 "", 636 L"default", 637 L"default" 638 }, 639 { // C-D specified filename disappears. Failover to final filename. 640 __LINE__, 641 "http://www.google.com/test.html", 642 "attachment; filename=\"..\"", 643 "", 644 "", 645 "", 646 L"default", 647 L"default" 648 }, 649 // Below is a small subset of cases taken from HttpContentDisposition tests. 650 { 651 __LINE__, 652 "http://www.google.com/", 653 "attachment; filename=\"%EC%98%88%EC%88%A0%20" 654 "%EC%98%88%EC%88%A0.jpg\"", 655 "", 656 "", 657 "", 658 L"", 659 L"\uc608\uc220 \uc608\uc220.jpg" 660 }, 661 { 662 __LINE__, 663 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg", 664 "", 665 "", 666 "", 667 "", 668 L"download", 669 L"\uc608\uc220 \uc608\uc220.jpg" 670 }, 671 { 672 __LINE__, 673 "http://www.google.com/", 674 "attachment;", 675 "", 676 "", 677 "", 678 L"\uB2E4\uC6B4\uB85C\uB4DC", 679 L"\uB2E4\uC6B4\uB85C\uB4DC" 680 }, 681 { 682 __LINE__, 683 "http://www.google.com/", 684 "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD=" 685 "D13=2Epng?=\"", 686 "", 687 "", 688 "", 689 L"download", 690 L"\u82b8\u88533.png" 691 }, 692 { 693 __LINE__, 694 "http://www.example.com/images?id=3", 695 "attachment; filename=caf\xc3\xa9.png", 696 "iso-8859-1", 697 "", 698 "", 699 L"", 700 L"caf\u00e9.png" 701 }, 702 { 703 __LINE__, 704 "http://www.example.com/images?id=3", 705 "attachment; filename=caf\xe5.png", 706 "windows-1253", 707 "", 708 "", 709 L"", 710 L"caf\u03b5.png" 711 }, 712 { 713 __LINE__, 714 "http://www.example.com/file?id=3", 715 "attachment; name=\xcf\xc2\xd4\xd8.zip", 716 "GBK", 717 "", 718 "", 719 L"", 720 L"\u4e0b\u8f7d.zip" 721 }, 722 { // Invalid C-D header. Extracts filename from url. 723 __LINE__, 724 "http://www.google.com/test.html", 725 "attachment; filename==?iiso88591?Q?caf=EG?=", 726 "", 727 "", 728 "", 729 L"", 730 L"test.html" 731 }, 732 // about: and data: URLs 733 { 734 __LINE__, 735 "about:chrome", 736 "", 737 "", 738 "", 739 "", 740 L"", 741 L"download" 742 }, 743 { 744 __LINE__, 745 "data:,looks/like/a.path", 746 "", 747 "", 748 "", 749 "", 750 L"", 751 L"download" 752 }, 753 { 754 __LINE__, 755 "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=", 756 "", 757 "", 758 "", 759 "", 760 L"", 761 L"download" 762 }, 763 { 764 __LINE__, 765 "data:,looks/like/a.path", 766 "", 767 "", 768 "", 769 "", 770 L"default_filename_is_given", 771 L"default_filename_is_given" 772 }, 773 { 774 __LINE__, 775 "data:,looks/like/a.path", 776 "", 777 "", 778 "", 779 "", 780 L"\u65e5\u672c\u8a9e", // Japanese Kanji. 781 L"\u65e5\u672c\u8a9e" 782 }, 783 { // The filename encoding is specified by the referrer charset. 784 __LINE__, 785 "http://example.com/V%FDvojov%E1%20psychologie.doc", 786 "", 787 "iso-8859-1", 788 "", 789 "", 790 L"", 791 L"V\u00fdvojov\u00e1 psychologie.doc" 792 }, 793 { // Suggested filename takes precedence over URL 794 __LINE__, 795 "http://www.google.com/test", 796 "", 797 "", 798 "suggested", 799 "", 800 L"", 801 L"suggested" 802 }, 803 { // The content-disposition has higher precedence over the suggested name. 804 __LINE__, 805 "http://www.google.com/test", 806 "attachment; filename=test.html", 807 "", 808 "suggested", 809 "", 810 L"", 811 L"test.html" 812 }, 813 #if 0 814 { // The filename encoding doesn't match the referrer charset, the system 815 // charset, or UTF-8. 816 // TODO(jshin): we need to handle this case. 817 __LINE__, 818 "http://example.com/V%FDvojov%E1%20psychologie.doc", 819 "", 820 "utf-8", 821 "", 822 "", 823 L"", 824 L"V\u00fdvojov\u00e1 psychologie.doc", 825 }, 826 #endif 827 // Raw 8bit characters in C-D 828 { 829 __LINE__, 830 "http://www.example.com/images?id=3", 831 "attachment; filename=caf\xc3\xa9.png", 832 "iso-8859-1", 833 "", 834 "image/png", 835 L"", 836 L"caf\u00e9.png" 837 }, 838 { 839 __LINE__, 840 "http://www.example.com/images?id=3", 841 "attachment; filename=caf\xe5.png", 842 "windows-1253", 843 "", 844 "image/png", 845 L"", 846 L"caf\u03b5.png" 847 }, 848 { // No 'filename' keyword in the disposition, use the URL 849 __LINE__, 850 "http://www.evil.com/my_download.txt", 851 "a_file_name.txt", 852 "", 853 "", 854 "text/plain", 855 L"download", 856 L"my_download.txt" 857 }, 858 { // Spaces in the disposition file name 859 __LINE__, 860 "http://www.frontpagehacker.com/a_download.exe", 861 "filename=My Downloaded File.exe", 862 "", 863 "", 864 "application/octet-stream", 865 L"download", 866 L"My Downloaded File.exe" 867 }, 868 { // % encoded 869 __LINE__, 870 "http://www.examples.com/", 871 "attachment; " 872 "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"", 873 "", 874 "", 875 "image/jpeg", 876 L"download", 877 L"\uc608\uc220 \uc608\uc220.jpg" 878 }, 879 { // name= parameter 880 __LINE__, 881 "http://www.examples.com/q.cgi?id=abc", 882 "attachment; name=abc de.pdf", 883 "", 884 "", 885 "application/octet-stream", 886 L"download", 887 L"abc de.pdf" 888 }, 889 { 890 __LINE__, 891 "http://www.example.com/path", 892 "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"", 893 "", 894 "", 895 "image/png", 896 L"download", 897 L"\x82b8\x8853" L"3.png" 898 }, 899 { // The following two have invalid CD headers and filenames come from the 900 // URL. 901 __LINE__, 902 "http://www.example.com/test%20123", 903 "attachment; filename==?iiso88591?Q?caf=EG?=", 904 "", 905 "", 906 "image/jpeg", 907 L"download", 908 L"test 123" JPEG_EXT 909 }, 910 { 911 __LINE__, 912 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg", 913 "malformed_disposition", 914 "", 915 "", 916 "image/jpeg", 917 L"download", 918 L"\uc608\uc220 \uc608\uc220.jpg" 919 }, 920 { // Invalid C-D. No filename from URL. Falls back to 'download'. 921 __LINE__, 922 "http://www.google.com/path1/path2/", 923 "attachment; filename==?iso88591?Q?caf=E3?", 924 "", 925 "", 926 "image/jpeg", 927 L"download", 928 L"download" JPEG_EXT 929 }, 930 }; 931 932 // Tests filename generation. Once the correct filename is 933 // selected, they should be passed through the validation steps and 934 // a correct extension should be added if necessary. 935 const GenerateFilenameCase generation_tests[] = { 936 // Dotfiles. Ensures preceeding period(s) stripped. 937 { 938 __LINE__, 939 "http://www.google.com/.test.html", 940 "", 941 "", 942 "", 943 "", 944 L"", 945 L"test.html" 946 }, 947 { 948 __LINE__, 949 "http://www.google.com/.test", 950 "", 951 "", 952 "", 953 "", 954 L"", 955 L"test" 956 }, 957 { 958 __LINE__, 959 "http://www.google.com/..test", 960 "", 961 "", 962 "", 963 "", 964 L"", 965 L"test" 966 }, 967 { // Disposition has relative paths, remove directory separators 968 __LINE__, 969 "http://www.evil.com/my_download.txt", 970 "filename=../../../../././../a_file_name.txt", 971 "", 972 "", 973 "text/plain", 974 L"download", 975 L"-..-..-..-.-.-..-a_file_name.txt" 976 }, 977 { // Disposition has parent directories, remove directory separators 978 __LINE__, 979 "http://www.evil.com/my_download.txt", 980 "filename=dir1/dir2/a_file_name.txt", 981 "", 982 "", 983 "text/plain", 984 L"download", 985 L"dir1-dir2-a_file_name.txt" 986 }, 987 { // Disposition has relative paths, remove directory separators 988 __LINE__, 989 "http://www.evil.com/my_download.txt", 990 "filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt", 991 "", 992 "", 993 "text/plain", 994 L"download", 995 L"-..-..-..-.-.-..-a_file_name.txt" 996 }, 997 { // Disposition has parent directories, remove directory separators 998 __LINE__, 999 "http://www.evil.com/my_download.txt", 1000 "filename=dir1\\dir2\\a_file_name.txt", 1001 "", 1002 "", 1003 "text/plain", 1004 L"download", 1005 L"dir1-dir2-a_file_name.txt" 1006 }, 1007 { // No useful information in disposition or URL, use default 1008 __LINE__, 1009 "http://www.truncated.com/path/", 1010 "", 1011 "", 1012 "", 1013 "text/plain", 1014 L"download", 1015 L"download" TXT_EXT 1016 }, 1017 { // Filename looks like HTML? 1018 __LINE__, 1019 "http://www.evil.com/get/malware/here", 1020 "filename=\"<blink>Hello kitty</blink>\"", 1021 "", 1022 "", 1023 "text/plain", 1024 L"default", 1025 L"-blink-Hello kitty--blink-" TXT_EXT 1026 }, 1027 { // A normal avi should get .avi and not .avi.avi 1028 __LINE__, 1029 "https://blah.google.com/misc/2.avi", 1030 "", 1031 "", 1032 "", 1033 "video/x-msvideo", 1034 L"download", 1035 L"2.avi" 1036 }, 1037 { // Extension generation 1038 __LINE__, 1039 "http://www.example.com/my-cat", 1040 "filename=my-cat", 1041 "", 1042 "", 1043 "image/jpeg", 1044 L"download", 1045 L"my-cat" JPEG_EXT 1046 }, 1047 { 1048 __LINE__, 1049 "http://www.example.com/my-cat", 1050 "filename=my-cat", 1051 "", 1052 "", 1053 "text/plain", 1054 L"download", 1055 L"my-cat.txt" 1056 }, 1057 { 1058 __LINE__, 1059 "http://www.example.com/my-cat", 1060 "filename=my-cat", 1061 "", 1062 "", 1063 "text/html", 1064 L"download", 1065 L"my-cat" HTML_EXT 1066 }, 1067 { // Unknown MIME type 1068 __LINE__, 1069 "http://www.example.com/my-cat", 1070 "filename=my-cat", 1071 "", 1072 "", 1073 "dance/party", 1074 L"download", 1075 L"my-cat" 1076 }, 1077 { 1078 __LINE__, 1079 "http://www.example.com/my-cat.jpg", 1080 "filename=my-cat.jpg", 1081 "", 1082 "", 1083 "text/plain", 1084 L"download", 1085 L"my-cat.jpg" 1086 }, 1087 // Windows specific tests 1088 #if defined(OS_WIN) 1089 { 1090 __LINE__, 1091 "http://www.goodguy.com/evil.exe", 1092 "filename=evil.exe", 1093 "", 1094 "", 1095 "image/jpeg", 1096 L"download", 1097 L"evil.exe" 1098 }, 1099 { 1100 __LINE__, 1101 "http://www.goodguy.com/ok.exe", 1102 "filename=ok.exe", 1103 "", 1104 "", 1105 "binary/octet-stream", 1106 L"download", 1107 L"ok.exe" 1108 }, 1109 { 1110 __LINE__, 1111 "http://www.goodguy.com/evil.dll", 1112 "filename=evil.dll", 1113 "", 1114 "", 1115 "dance/party", 1116 L"download", 1117 L"evil.dll" 1118 }, 1119 { 1120 __LINE__, 1121 "http://www.goodguy.com/evil.exe", 1122 "filename=evil", 1123 "", 1124 "", 1125 "application/rss+xml", 1126 L"download", 1127 L"evil" 1128 }, 1129 // Test truncation of trailing dots and spaces 1130 { 1131 __LINE__, 1132 "http://www.goodguy.com/evil.exe ", 1133 "filename=evil.exe ", 1134 "", 1135 "", 1136 "binary/octet-stream", 1137 L"download", 1138 L"evil.exe" 1139 }, 1140 { 1141 __LINE__, 1142 "http://www.goodguy.com/evil.exe.", 1143 "filename=evil.exe.", 1144 "", 1145 "", 1146 "binary/octet-stream", 1147 L"download", 1148 L"evil.exe-" 1149 }, 1150 { 1151 __LINE__, 1152 "http://www.goodguy.com/evil.exe. . .", 1153 "filename=evil.exe. . .", 1154 "", 1155 "", 1156 "binary/octet-stream", 1157 L"download", 1158 L"evil.exe-------" 1159 }, 1160 { 1161 __LINE__, 1162 "http://www.goodguy.com/evil.", 1163 "filename=evil.", 1164 "", 1165 "", 1166 "binary/octet-stream", 1167 L"download", 1168 L"evil-" 1169 }, 1170 { 1171 __LINE__, 1172 "http://www.goodguy.com/. . . . .", 1173 "filename=. . . . .", 1174 "", 1175 "", 1176 "binary/octet-stream", 1177 L"download", 1178 L"download" 1179 }, 1180 { 1181 __LINE__, 1182 "http://www.badguy.com/attachment?name=meh.exe%C2%A0", 1183 "attachment; filename=\"meh.exe\xC2\xA0\"", 1184 "", 1185 "", 1186 "binary/octet-stream", 1187 L"", 1188 L"meh.exe-" 1189 }, 1190 #endif // OS_WIN 1191 { 1192 __LINE__, 1193 "http://www.goodguy.com/utils.js", 1194 "filename=utils.js", 1195 "", 1196 "", 1197 "application/x-javascript", 1198 L"download", 1199 L"utils.js" 1200 }, 1201 { 1202 __LINE__, 1203 "http://www.goodguy.com/contacts.js", 1204 "filename=contacts.js", 1205 "", 1206 "", 1207 "application/json", 1208 L"download", 1209 L"contacts.js" 1210 }, 1211 { 1212 __LINE__, 1213 "http://www.goodguy.com/utils.js", 1214 "filename=utils.js", 1215 "", 1216 "", 1217 "text/javascript", 1218 L"download", 1219 L"utils.js" 1220 }, 1221 { 1222 __LINE__, 1223 "http://www.goodguy.com/utils.js", 1224 "filename=utils.js", 1225 "", 1226 "", 1227 "text/javascript;version=2", 1228 L"download", 1229 L"utils.js" 1230 }, 1231 { 1232 __LINE__, 1233 "http://www.goodguy.com/utils.js", 1234 "filename=utils.js", 1235 "", 1236 "", 1237 "application/ecmascript", 1238 L"download", 1239 L"utils.js" 1240 }, 1241 { 1242 __LINE__, 1243 "http://www.goodguy.com/utils.js", 1244 "filename=utils.js", 1245 "", 1246 "", 1247 "application/ecmascript;version=4", 1248 L"download", 1249 L"utils.js" 1250 }, 1251 { 1252 __LINE__, 1253 "http://www.goodguy.com/program.exe", 1254 "filename=program.exe", 1255 "", 1256 "", 1257 "application/foo-bar", 1258 L"download", 1259 L"program.exe" 1260 }, 1261 { 1262 __LINE__, 1263 "http://www.evil.com/../foo.txt", 1264 "filename=../foo.txt", 1265 "", 1266 "", 1267 "text/plain", 1268 L"download", 1269 L"-foo.txt" 1270 }, 1271 { 1272 __LINE__, 1273 "http://www.evil.com/..\\foo.txt", 1274 "filename=..\\foo.txt", 1275 "", 1276 "", 1277 "text/plain", 1278 L"download", 1279 L"-foo.txt" 1280 }, 1281 { 1282 __LINE__, 1283 "http://www.evil.com/.hidden", 1284 "filename=.hidden", 1285 "", 1286 "", 1287 "text/plain", 1288 L"download", 1289 L"hidden" TXT_EXT 1290 }, 1291 { 1292 __LINE__, 1293 "http://www.evil.com/trailing.", 1294 "filename=trailing.", 1295 "", 1296 "", 1297 "dance/party", 1298 L"download", 1299 #if defined(OS_WIN) 1300 L"trailing-" 1301 #else 1302 L"trailing" 1303 #endif 1304 }, 1305 { 1306 __LINE__, 1307 "http://www.evil.com/trailing.", 1308 "filename=trailing.", 1309 "", 1310 "", 1311 "text/plain", 1312 L"download", 1313 #if defined(OS_WIN) 1314 L"trailing-" TXT_EXT 1315 #else 1316 L"trailing" TXT_EXT 1317 #endif 1318 }, 1319 { 1320 __LINE__, 1321 "http://www.evil.com/.", 1322 "filename=.", 1323 "", 1324 "", 1325 "dance/party", 1326 L"download", 1327 L"download" 1328 }, 1329 { 1330 __LINE__, 1331 "http://www.evil.com/..", 1332 "filename=..", 1333 "", 1334 "", 1335 "dance/party", 1336 L"download", 1337 L"download" 1338 }, 1339 { 1340 __LINE__, 1341 "http://www.evil.com/...", 1342 "filename=...", 1343 "", 1344 "", 1345 "dance/party", 1346 L"download", 1347 L"download" 1348 }, 1349 { // Note that this one doesn't have "filename=" on it. 1350 __LINE__, 1351 "http://www.evil.com/", 1352 "a_file_name.txt", 1353 "", 1354 "", 1355 "image/jpeg", 1356 L"download", 1357 L"download" JPEG_EXT 1358 }, 1359 { 1360 __LINE__, 1361 "http://www.evil.com/", 1362 "filename=", 1363 "", 1364 "", 1365 "image/jpeg", 1366 L"download", 1367 L"download" JPEG_EXT 1368 }, 1369 { 1370 __LINE__, 1371 "http://www.example.com/simple", 1372 "filename=simple", 1373 "", 1374 "", 1375 "application/octet-stream", 1376 L"download", 1377 L"simple" 1378 }, 1379 // Reserved words on Windows 1380 { 1381 __LINE__, 1382 "http://www.goodguy.com/COM1", 1383 "filename=COM1", 1384 "", 1385 "", 1386 "application/foo-bar", 1387 L"download", 1388 #if defined(OS_WIN) 1389 L"_COM1" 1390 #else 1391 L"COM1" 1392 #endif 1393 }, 1394 { 1395 __LINE__, 1396 "http://www.goodguy.com/COM4.txt", 1397 "filename=COM4.txt", 1398 "", 1399 "", 1400 "text/plain", 1401 L"download", 1402 #if defined(OS_WIN) 1403 L"_COM4.txt" 1404 #else 1405 L"COM4.txt" 1406 #endif 1407 }, 1408 { 1409 __LINE__, 1410 "http://www.goodguy.com/lpt1.TXT", 1411 "filename=lpt1.TXT", 1412 "", 1413 "", 1414 "text/plain", 1415 L"download", 1416 #if defined(OS_WIN) 1417 L"_lpt1.TXT" 1418 #else 1419 L"lpt1.TXT" 1420 #endif 1421 }, 1422 { 1423 __LINE__, 1424 "http://www.goodguy.com/clock$.txt", 1425 "filename=clock$.txt", 1426 "", 1427 "", 1428 "text/plain", 1429 L"download", 1430 #if defined(OS_WIN) 1431 L"_clock$.txt" 1432 #else 1433 L"clock$.txt" 1434 #endif 1435 }, 1436 { // Validation should also apply to sugested name 1437 __LINE__, 1438 "http://www.goodguy.com/blah$.txt", 1439 "filename=clock$.txt", 1440 "", 1441 "clock$.txt", 1442 "text/plain", 1443 L"download", 1444 #if defined(OS_WIN) 1445 L"_clock$.txt" 1446 #else 1447 L"clock$.txt" 1448 #endif 1449 }, 1450 { 1451 __LINE__, 1452 "http://www.goodguy.com/mycom1.foo", 1453 "filename=mycom1.foo", 1454 "", 1455 "", 1456 "text/plain", 1457 L"download", 1458 L"mycom1.foo" 1459 }, 1460 { 1461 __LINE__, 1462 "http://www.badguy.com/Setup.exe.local", 1463 "filename=Setup.exe.local", 1464 "", 1465 "", 1466 "application/foo-bar", 1467 L"download", 1468 #if defined(OS_WIN) 1469 L"Setup.exe.download" 1470 #else 1471 L"Setup.exe.local" 1472 #endif 1473 }, 1474 { 1475 __LINE__, 1476 "http://www.badguy.com/Setup.exe.local", 1477 "filename=Setup.exe.local.local", 1478 "", 1479 "", 1480 "application/foo-bar", 1481 L"download", 1482 #if defined(OS_WIN) 1483 L"Setup.exe.local.download" 1484 #else 1485 L"Setup.exe.local.local" 1486 #endif 1487 }, 1488 { 1489 __LINE__, 1490 "http://www.badguy.com/Setup.exe.lnk", 1491 "filename=Setup.exe.lnk", 1492 "", 1493 "", 1494 "application/foo-bar", 1495 L"download", 1496 #if defined(OS_WIN) 1497 L"Setup.exe.download" 1498 #else 1499 L"Setup.exe.lnk" 1500 #endif 1501 }, 1502 { 1503 __LINE__, 1504 "http://www.badguy.com/Desktop.ini", 1505 "filename=Desktop.ini", 1506 "", 1507 "", 1508 "application/foo-bar", 1509 L"download", 1510 #if defined(OS_WIN) 1511 L"_Desktop.ini" 1512 #else 1513 L"Desktop.ini" 1514 #endif 1515 }, 1516 { 1517 __LINE__, 1518 "http://www.badguy.com/Thumbs.db", 1519 "filename=Thumbs.db", 1520 "", 1521 "", 1522 "application/foo-bar", 1523 L"download", 1524 #if defined(OS_WIN) 1525 L"_Thumbs.db" 1526 #else 1527 L"Thumbs.db" 1528 #endif 1529 }, 1530 { 1531 __LINE__, 1532 "http://www.hotmail.com", 1533 "filename=source.jpg", 1534 "", 1535 "", 1536 "application/x-javascript", 1537 L"download", 1538 L"source.jpg" 1539 }, 1540 { // http://crbug.com/5772. 1541 __LINE__, 1542 "http://www.example.com/foo.tar.gz", 1543 "", 1544 "", 1545 "", 1546 "application/x-tar", 1547 L"download", 1548 L"foo.tar.gz" 1549 }, 1550 { // http://crbug.com/52250. 1551 __LINE__, 1552 "http://www.example.com/foo.tgz", 1553 "", 1554 "", 1555 "", 1556 "application/x-tar", 1557 L"download", 1558 L"foo.tgz" 1559 }, 1560 { // http://crbug.com/7337. 1561 __LINE__, 1562 "http://maged.lordaeron.org/blank.reg", 1563 "", 1564 "", 1565 "", 1566 "text/x-registry", 1567 L"download", 1568 L"blank.reg" 1569 }, 1570 { 1571 __LINE__, 1572 "http://www.example.com/bar.tar", 1573 "", 1574 "", 1575 "", 1576 "application/x-tar", 1577 L"download", 1578 L"bar.tar" 1579 }, 1580 { 1581 __LINE__, 1582 "http://www.example.com/bar.bogus", 1583 "", 1584 "", 1585 "", 1586 "application/x-tar", 1587 L"download", 1588 L"bar.bogus" 1589 }, 1590 { // http://crbug.com/20337 1591 __LINE__, 1592 "http://www.example.com/.download.txt", 1593 "filename=.download.txt", 1594 "", 1595 "", 1596 "text/plain", 1597 L"-download", 1598 L"download.txt" 1599 }, 1600 { // http://crbug.com/56855. 1601 __LINE__, 1602 "http://www.example.com/bar.sh", 1603 "", 1604 "", 1605 "", 1606 "application/x-sh", 1607 L"download", 1608 L"bar.sh" 1609 }, 1610 { // http://crbug.com/61571 1611 __LINE__, 1612 "http://www.example.com/npdf.php?fn=foobar.pdf", 1613 "", 1614 "", 1615 "", 1616 "text/plain", 1617 L"download", 1618 L"npdf" TXT_EXT 1619 }, 1620 { // Shouldn't overwrite C-D specified extension. 1621 __LINE__, 1622 "http://www.example.com/npdf.php?fn=foobar.pdf", 1623 "filename=foobar.jpg", 1624 "", 1625 "", 1626 "text/plain", 1627 L"download", 1628 L"foobar.jpg" 1629 }, 1630 { // http://crbug.com/87719 1631 __LINE__, 1632 "http://www.example.com/image.aspx?id=blargh", 1633 "", 1634 "", 1635 "", 1636 "image/jpeg", 1637 L"download", 1638 L"image" JPEG_EXT 1639 }, 1640 #if defined(OS_CHROMEOS) 1641 { // http://crosbug.com/26028 1642 __LINE__, 1643 "http://www.example.com/fooa%cc%88.txt", 1644 "", 1645 "", 1646 "", 1647 "image/jpeg", 1648 L"foo\xe4", 1649 L"foo\xe4.txt" 1650 }, 1651 #endif 1652 }; 1653 1654 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(selection_tests); ++i) 1655 RunGenerateFileNameTestCase(&selection_tests[i]); 1656 1657 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i) 1658 RunGenerateFileNameTestCase(&generation_tests[i]); 1659 1660 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i) { 1661 GenerateFilenameCase test_case = generation_tests[i]; 1662 test_case.referrer_charset = "GBK"; 1663 RunGenerateFileNameTestCase(&test_case); 1664 } 1665 } 1666 1667 } // namespace net 1668