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