OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/base/filename_util.h" | 5 #include "net/base/filename_util.h" |
6 | 6 |
7 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 #elif defined(OS_MACOSX) | 280 #elif defined(OS_MACOSX) |
281 #define JPEG_EXT L".jpeg" | 281 #define JPEG_EXT L".jpeg" |
282 #define HTML_EXT L".html" | 282 #define HTML_EXT L".html" |
283 #else | 283 #else |
284 #define JPEG_EXT L".jpg" | 284 #define JPEG_EXT L".jpg" |
285 #define HTML_EXT L".html" | 285 #define HTML_EXT L".html" |
286 #endif | 286 #endif |
287 #define TXT_EXT L".txt" | 287 #define TXT_EXT L".txt" |
288 #define TAR_EXT L".tar" | 288 #define TAR_EXT L".tar" |
289 | 289 |
290 TEST(FilenameUtilTest, GenerateSafeFileName) { | 290 TEST(FilenameUtilTest, EnsureSafePortableFileName) { |
291 const struct { | 291 const struct { |
292 const char* mime_type; | 292 const char* mime_type; |
293 const base::FilePath::CharType* filename; | 293 const base::FilePath::CharType* filename; |
294 const base::FilePath::CharType* expected_filename; | 294 const base::FilePath::CharType* expected_filename; |
295 } safe_tests[] = { | 295 } safe_tests[] = { |
296 #if defined(OS_WIN) | 296 #if defined(OS_WIN) |
297 {"text/html", | 297 {"text/html", |
298 FILE_PATH_LITERAL("C:\\foo\\bar.htm"), | 298 FILE_PATH_LITERAL("C:\\foo\\bar.htm"), |
299 FILE_PATH_LITERAL("C:\\foo\\bar.htm")}, | 299 FILE_PATH_LITERAL("C:\\foo\\bar.htm")}, |
300 {"text/html", | 300 {"text/html", |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 FILE_PATH_LITERAL("/bar.html")}, | 358 FILE_PATH_LITERAL("/bar.html")}, |
359 {"image/png", FILE_PATH_LITERAL("/bar"), FILE_PATH_LITERAL("/bar.png")}, | 359 {"image/png", FILE_PATH_LITERAL("/bar"), FILE_PATH_LITERAL("/bar.png")}, |
360 {"image/gif", | 360 {"image/gif", |
361 FILE_PATH_LITERAL("/foo/bar.exe"), | 361 FILE_PATH_LITERAL("/foo/bar.exe"), |
362 FILE_PATH_LITERAL("/foo/bar.exe")}, | 362 FILE_PATH_LITERAL("/foo/bar.exe")}, |
363 {"text/html", | 363 {"text/html", |
364 FILE_PATH_LITERAL("/foo/google.com"), | 364 FILE_PATH_LITERAL("/foo/google.com"), |
365 FILE_PATH_LITERAL("/foo/google.com")}, | 365 FILE_PATH_LITERAL("/foo/google.com")}, |
366 {"text/html", | 366 {"text/html", |
367 FILE_PATH_LITERAL("/foo/con.htm"), | 367 FILE_PATH_LITERAL("/foo/con.htm"), |
368 FILE_PATH_LITERAL("/foo/con.htm")}, | 368 FILE_PATH_LITERAL("/foo/_con.htm")}, |
369 {"text/html", | 369 {"text/html", |
370 FILE_PATH_LITERAL("/foo/con"), | 370 FILE_PATH_LITERAL("/foo/con"), |
371 FILE_PATH_LITERAL("/foo/con.html")}, | 371 FILE_PATH_LITERAL("/foo/_con.html")}, |
372 // Allow extension synonyms. | 372 // Allow extension synonyms. |
373 {"image/jpeg", | 373 {"image/jpeg", |
374 FILE_PATH_LITERAL("/bar.jpg"), | 374 FILE_PATH_LITERAL("/bar.jpg"), |
375 FILE_PATH_LITERAL("/bar.jpg")}, | 375 FILE_PATH_LITERAL("/bar.jpg")}, |
376 {"image/jpeg", | 376 {"image/jpeg", |
377 FILE_PATH_LITERAL("/bar.jpeg"), | 377 FILE_PATH_LITERAL("/bar.jpeg"), |
378 FILE_PATH_LITERAL("/bar.jpeg")}, | 378 FILE_PATH_LITERAL("/bar.jpeg")}, |
379 #endif // !defined(OS_WIN) | 379 #endif // !defined(OS_WIN) |
380 }; | 380 }; |
381 | 381 |
382 for (size_t i = 0; i < arraysize(safe_tests); ++i) { | 382 for (size_t i = 0; i < arraysize(safe_tests); ++i) { |
383 base::FilePath file_path(safe_tests[i].filename); | 383 base::FilePath file_path(safe_tests[i].filename); |
384 GenerateSafeFileName(safe_tests[i].mime_type, false, &file_path); | 384 EnsureSafePortableFileName(safe_tests[i].mime_type, |
| 385 EXTENSION_OPTION_GENERATE_IF_MISSING, |
| 386 &file_path); |
385 EXPECT_EQ(safe_tests[i].expected_filename, file_path.value()) | 387 EXPECT_EQ(safe_tests[i].expected_filename, file_path.value()) |
386 << "Iteration " << i; | 388 << "Iteration " << i; |
387 } | 389 } |
388 } | 390 } |
389 | 391 |
390 TEST(FilenameUtilTest, GenerateFileName) { | 392 TEST(FilenameUtilTest, GenerateFileName) { |
391 // Tests whether the correct filename is selected from the the given | 393 // Tests whether the correct filename is selected from the the given |
392 // parameters and that Content-Disposition headers are properly | 394 // parameters and that Content-Disposition headers are properly |
393 // handled including failovers when the header is malformed. | 395 // handled including failovers when the header is malformed. |
394 const GenerateFilenameCase selection_tests[] = { | 396 static const GenerateFilenameCase kSelectionTests[] = { |
395 {__LINE__, | 397 {__LINE__, |
396 "http://www.google.com/", | 398 "http://www.google.com/", |
397 "attachment; filename=test.html", | 399 "attachment; filename=test.html", |
398 "", | 400 "", |
399 "", | 401 "", |
400 "", | 402 "", |
401 L"", | 403 L"", |
402 L"test.html"}, | 404 L"test.html"}, |
403 {__LINE__, | 405 {__LINE__, |
404 "http://www.google.com/", | 406 "http://www.google.com/", |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 __LINE__, | 448 __LINE__, |
447 "http://www.google.com/path/test.html", | 449 "http://www.google.com/path/test.html", |
448 "attachment;", | 450 "attachment;", |
449 "", | 451 "", |
450 "", | 452 "", |
451 "", | 453 "", |
452 L"", | 454 L"", |
453 L"test.html"}, | 455 L"test.html"}, |
454 {// No C-D | 456 {// No C-D |
455 __LINE__, | 457 __LINE__, |
456 "http://www.google.com/", | 458 "http://example.com/V%FDvojov%E1%20psychologie.doc", |
457 "", | 459 "", |
458 "", | 460 "utf-8", |
459 "", | 461 "", |
460 "", | 462 "", |
461 L"", | 463 L"", |
462 L"www.google.com"}, | 464 L"example.com"}, |
463 {__LINE__, | 465 {__LINE__, |
464 "http://www.google.com/test.html", | 466 "http://www.google.com/test.html", |
465 "", | 467 "", |
466 "", | 468 "", |
467 "", | 469 "", |
468 "", | 470 "", |
469 L"", | 471 L"", |
470 L"test.html"}, | 472 L"test.html"}, |
471 {// Now that we use src/url's ExtractFileName, this case falls back to | 473 {// Now that we use src/url's ExtractFileName, this case falls back to |
472 // the hostname. If this behavior is not desirable, we'd better change | 474 // the hostname. If this behavior is not desirable, we'd better change |
(...skipping 28 matching lines...) Expand all Loading... |
501 "", | 503 "", |
502 L"download", | 504 L"download", |
503 L"download"}, | 505 L"download"}, |
504 {__LINE__, | 506 {__LINE__, |
505 "http://www.google.com/", | 507 "http://www.google.com/", |
506 "attachment; filename=\"../test.html\"", | 508 "attachment; filename=\"../test.html\"", |
507 "", | 509 "", |
508 "", | 510 "", |
509 "", | 511 "", |
510 L"", | 512 L"", |
511 L"-test.html"}, | 513 L"_._test.html"}, |
512 {__LINE__, | 514 {__LINE__, |
513 "http://www.google.com/", | 515 "http://www.google.com/", |
514 "attachment; filename=\"..\\test.html\"", | 516 "attachment; filename=\"..//test.html\"", |
515 "", | 517 "", |
516 "", | 518 "", |
517 "", | 519 "", |
518 L"", | 520 L"", |
519 L"test.html"}, | 521 L"_.__test.html"}, |
520 {__LINE__, | 522 {__LINE__, |
521 "http://www.google.com/", | 523 "http://www.google.com/", |
522 "attachment; filename=\"..\\\\test.html\"", | 524 "attachment; filename=\"..\\\\test.html\"", |
523 "", | 525 "", |
524 "", | 526 "", |
525 "", | 527 "", |
526 L"", | 528 L"", |
527 L"-test.html"}, | 529 L"_._test.html"}, |
528 {// Filename disappears after leading and trailing periods are removed. | 530 {__LINE__, |
529 __LINE__, | |
530 "http://www.google.com/", | 531 "http://www.google.com/", |
531 "attachment; filename=\"..\"", | 532 "attachment; filename=\"..\\\\\\\\test.html\"", |
532 "", | 533 "", |
533 "", | 534 "", |
534 "", | 535 "", |
535 L"default", | 536 L"", |
536 L"default"}, | 537 L"_.__test.html"}, |
537 {// C-D specified filename disappears. Failover to final filename. | 538 {// Content-Disposition specifies an empty filename. |
538 __LINE__, | 539 __LINE__, |
539 "http://www.google.com/test.html", | 540 "http://www.google.com/", |
540 "attachment; filename=\"..\"", | 541 "attachment; filename=", |
541 "", | 542 "", |
542 "", | 543 "", |
543 "", | 544 "", |
544 L"default", | 545 L"default", |
545 L"default"}, | 546 L"default"}, |
546 // Below is a small subset of cases taken from HttpContentDisposition tests. | 547 // Below is a small subset of cases taken from HttpContentDisposition tests. |
547 {__LINE__, | 548 {__LINE__, |
548 "http://www.google.com/", | 549 "http://www.google.com/", |
549 "attachment; filename=\"%EC%98%88%EC%88%A0%20" | 550 "attachment; filename=\"%EC%98%88%EC%88%A0%20" |
550 "%EC%98%88%EC%88%A0.jpg\"", | 551 "%EC%98%88%EC%88%A0.jpg\"", |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 {__LINE__, | 700 {__LINE__, |
700 "http://www.example.com/images?id=3", | 701 "http://www.example.com/images?id=3", |
701 "attachment; filename=caf\xe5.png", | 702 "attachment; filename=caf\xe5.png", |
702 "windows-1253", | 703 "windows-1253", |
703 "", | 704 "", |
704 "image/png", | 705 "image/png", |
705 L"", | 706 L"", |
706 L"caf\u03b5.png"}, | 707 L"caf\u03b5.png"}, |
707 {// No 'filename' keyword in the disposition, use the URL | 708 {// No 'filename' keyword in the disposition, use the URL |
708 __LINE__, | 709 __LINE__, |
709 "http://www.evil.com/my_download.txt", | 710 "http://www.example.com/my_download.txt", |
710 "a_file_name.txt", | 711 "a_file_name.txt", |
711 "", | 712 "", |
712 "", | 713 "", |
713 "text/plain", | 714 "text/plain", |
714 L"download", | 715 L"download", |
715 L"my_download.txt"}, | 716 L"my_download.txt"}, |
716 {// Spaces in the disposition file name | 717 {// Spaces in the disposition file name |
717 __LINE__, | 718 __LINE__, |
718 "http://www.frontpagehacker.com/a_download.exe", | 719 "http://www.frontpagehacker.com/a_download.exe", |
719 "filename=My Downloaded File.exe", | 720 "filename=My Downloaded File.exe", |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
775 "", | 776 "", |
776 "", | 777 "", |
777 "image/jpeg", | 778 "image/jpeg", |
778 L"download", | 779 L"download", |
779 L"download" JPEG_EXT}, | 780 L"download" JPEG_EXT}, |
780 }; | 781 }; |
781 | 782 |
782 // Tests filename generation. Once the correct filename is | 783 // Tests filename generation. Once the correct filename is |
783 // selected, they should be passed through the validation steps and | 784 // selected, they should be passed through the validation steps and |
784 // a correct extension should be added if necessary. | 785 // a correct extension should be added if necessary. |
785 const GenerateFilenameCase generation_tests[] = { | 786 static const GenerateFilenameCase kGenerationTests[] = { |
786 // Dotfiles. Ensures preceeding period(s) stripped. | 787 {// Dotfiles. Ensures preceeding period(s) escaped. |
787 {__LINE__, | 788 __LINE__, |
788 "http://www.google.com/.test.html", | 789 "http://www.google.com/.test", |
789 "", | 790 "", |
790 "", | 791 "", |
791 "", | 792 "", |
792 "", | 793 "", |
793 L"", | 794 L"", |
794 L"test.html"}, | 795 L"_test"}, |
795 {__LINE__, "http://www.google.com/.test", "", "", "", "", L"", L"test"}, | 796 {// Multiple dots. It's only necessary to escape the first one. |
796 {__LINE__, "http://www.google.com/..test", "", "", "", "", L"", L"test"}, | |
797 {// Disposition has relative paths, remove directory separators | |
798 __LINE__, | 797 __LINE__, |
799 "http://www.evil.com/my_download.txt", | 798 "http://www.google.com/..test", |
| 799 "", |
| 800 "", |
| 801 "", |
| 802 "", |
| 803 L"", |
| 804 L"_.test"}, |
| 805 {// Disposition has relative paths, escape path separators |
| 806 __LINE__, |
| 807 "http://www.example.com/my_download.txt", |
800 "filename=../../../../././../a_file_name.txt", | 808 "filename=../../../../././../a_file_name.txt", |
801 "", | 809 "", |
802 "", | 810 "", |
803 "text/plain", | 811 "", |
804 L"download", | 812 L"", |
805 L"-..-..-..-.-.-..-a_file_name.txt"}, | 813 L"_._.._.._.._._._.._a_file_name.txt"}, |
806 {// Disposition has parent directories, remove directory separators | 814 {// Disposition has parent directories, remove directory separators |
807 __LINE__, | 815 __LINE__, |
808 "http://www.evil.com/my_download.txt", | 816 "http://www.example.com/my_download.txt", |
809 "filename=dir1/dir2/a_file_name.txt", | 817 "filename=dir1/dir2/a_file_name.txt", |
810 "", | 818 "", |
811 "", | 819 "", |
812 "text/plain", | 820 "", |
813 L"download", | 821 L"", |
814 L"dir1-dir2-a_file_name.txt"}, | 822 L"dir1_dir2_a_file_name.txt"}, |
815 {// Disposition has relative paths, remove directory separators | 823 {// Disposition has relative paths, remove directory separators |
816 __LINE__, | 824 __LINE__, |
817 "http://www.evil.com/my_download.txt", | 825 "http://www.example.com/my_download.txt", |
818 "filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt", | 826 "filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt", |
819 "", | 827 "", |
820 "", | 828 "", |
821 "text/plain", | 829 "", |
822 L"download", | 830 L"", |
823 L"-..-..-..-.-.-..-a_file_name.txt"}, | 831 L"_._.._.._.._._._.._a_file_name.txt"}, |
824 {// Disposition has parent directories, remove directory separators | 832 {// Disposition has parent directories, remove directory separators |
825 __LINE__, | 833 __LINE__, |
826 "http://www.evil.com/my_download.txt", | 834 "http://www.example.com/my_download.txt", |
827 "filename=dir1\\dir2\\a_file_name.txt", | 835 "filename=dir1\\dir2\\a_file_name.txt", |
828 "", | 836 "", |
829 "", | 837 "", |
830 "text/plain", | 838 "text/plain", |
831 L"download", | 839 L"download", |
832 L"dir1-dir2-a_file_name.txt"}, | 840 L"dir1_dir2_a_file_name.txt"}, |
833 {// No useful information in disposition or URL, use default | 841 {// No useful information in disposition or URL, use default |
834 __LINE__, | 842 __LINE__, |
835 "http://www.truncated.com/path/", | 843 "http://www.truncated.com/path/", |
836 "", | 844 "", |
837 "", | 845 "", |
838 "", | 846 "", |
839 "text/plain", | 847 "text/plain", |
840 L"download", | 848 L"default", |
841 L"download" TXT_EXT}, | 849 L"default" TXT_EXT}, |
842 {// Filename looks like HTML? | 850 {// No useful information in disposition or URL, use default. Don't |
| 851 // generate an extension since the default filename already has one. |
843 __LINE__, | 852 __LINE__, |
844 "http://www.evil.com/get/malware/here", | 853 "http://www.truncated.com/path/", |
| 854 "", |
| 855 "", |
| 856 "", |
| 857 "text/plain", |
| 858 L"default.ext", |
| 859 L"default.ext"}, |
| 860 {// Filename looks like HTML. |
| 861 __LINE__, |
| 862 "http://www.example.com/get/malware/here", |
845 "filename=\"<blink>Hello kitty</blink>\"", | 863 "filename=\"<blink>Hello kitty</blink>\"", |
846 "", | 864 "", |
847 "", | 865 "", |
848 "text/plain", | 866 "text/plain", |
849 L"default", | 867 L"default", |
850 L"-blink-Hello kitty--blink-"}, | 868 L"_blink_Hello kitty__blink_"}, |
851 {// A normal avi should get .avi and not .avi.avi | 869 {// A normal avi should get .avi and not .avi.avi |
852 __LINE__, | 870 __LINE__, |
853 "https://blah.google.com/misc/2.avi", | 871 "https://blah.google.com/misc/2.avi", |
854 "", | 872 "", |
855 "", | 873 "", |
856 "", | 874 "", |
857 "video/x-msvideo", | 875 "video/x-msvideo", |
858 L"download", | 876 L"download", |
859 L"2.avi"}, | 877 L"2.avi"}, |
860 {// Extension generation | 878 {// No extensions should be generated if the filename was from a |
| 879 // Content-Disposition header. |
861 __LINE__, | 880 __LINE__, |
862 "http://www.example.com/my-cat", | 881 "http://www.example.com/", |
863 "filename=my-cat", | 882 "filename=my-cat", |
864 "", | 883 "", |
865 "", | 884 "", |
866 "image/jpeg", | 885 "image/jpeg", |
867 L"download", | 886 L"download", |
868 L"my-cat"}, | 887 L"my-cat"}, |
869 {__LINE__, | 888 {__LINE__, |
| 889 "http://www.example.com/", |
| 890 "filename=my-cat", |
| 891 "", |
| 892 "", |
| 893 "text/plain", |
| 894 L"download", |
| 895 L"my-cat"}, |
| 896 {// An extension should be generated for a URL derived filename. |
| 897 __LINE__, |
870 "http://www.example.com/my-cat", | 898 "http://www.example.com/my-cat", |
871 "filename=my-cat", | 899 "", |
872 "", | 900 "", |
873 "", | 901 "", |
874 "text/plain", | 902 "text/plain", |
| 903 L"", |
| 904 L"my-cat" TXT_EXT}, |
| 905 {// Unknown MIME type. No extension generated. |
| 906 __LINE__, |
| 907 "http://www.example.com/my-cat", |
| 908 "", |
| 909 "", |
| 910 "", |
| 911 "dance/party", |
875 L"download", | 912 L"download", |
876 L"my-cat"}, | 913 L"my-cat"}, |
877 {__LINE__, | 914 {// Trailing spaces. |
878 "http://www.example.com/my-cat", | 915 __LINE__, |
879 "filename=my-cat", | 916 "http://www.example.com/", |
880 "", | 917 "filename=\"evil.exe \"", |
881 "", | 918 "", |
882 "text/html", | 919 "", |
883 L"download", | 920 "", |
884 L"my-cat"}, | 921 L"download", |
885 {// Unknown MIME type | 922 L"evil.exe_"}, |
886 __LINE__, | 923 {// Trailing dots. |
887 "http://www.example.com/my-cat", | 924 __LINE__, |
888 "filename=my-cat", | 925 "http://www.example.com/", |
889 "", | |
890 "", | |
891 "dance/party", | |
892 L"download", | |
893 L"my-cat"}, | |
894 {__LINE__, | |
895 "http://www.example.com/my-cat.jpg", | |
896 "filename=my-cat.jpg", | |
897 "", | |
898 "", | |
899 "text/plain", | |
900 L"download", | |
901 L"my-cat.jpg"}, | |
902 // Windows specific tests | |
903 #if defined(OS_WIN) | |
904 {__LINE__, | |
905 "http://www.goodguy.com/evil.exe", | |
906 "filename=evil.exe", | |
907 "", | |
908 "", | |
909 "image/jpeg", | |
910 L"download", | |
911 L"evil.exe"}, | |
912 {__LINE__, | |
913 "http://www.goodguy.com/ok.exe", | |
914 "filename=ok.exe", | |
915 "", | |
916 "", | |
917 "binary/octet-stream", | |
918 L"download", | |
919 L"ok.exe"}, | |
920 {__LINE__, | |
921 "http://www.goodguy.com/evil.dll", | |
922 "filename=evil.dll", | |
923 "", | |
924 "", | |
925 "dance/party", | |
926 L"download", | |
927 L"evil.dll"}, | |
928 {__LINE__, | |
929 "http://www.goodguy.com/evil.exe", | |
930 "filename=evil", | |
931 "", | |
932 "", | |
933 "application/rss+xml", | |
934 L"download", | |
935 L"evil"}, | |
936 // Test truncation of trailing dots and spaces | |
937 {__LINE__, | |
938 "http://www.goodguy.com/evil.exe ", | |
939 "filename=evil.exe ", | |
940 "", | |
941 "", | |
942 "binary/octet-stream", | |
943 L"download", | |
944 L"evil.exe"}, | |
945 {__LINE__, | |
946 "http://www.goodguy.com/evil.exe.", | |
947 "filename=evil.exe.", | 926 "filename=evil.exe.", |
948 "", | 927 "", |
949 "", | 928 "", |
950 "binary/octet-stream", | 929 "binary/octet-stream", |
951 L"download", | 930 L"download", |
952 L"evil.exe-"}, | 931 L"evil.exe_"}, |
953 {__LINE__, | 932 {// Multiple trailing dots and spaces. |
954 "http://www.goodguy.com/evil.exe. . .", | 933 __LINE__, |
| 934 "http://www.example.com/", |
955 "filename=evil.exe. . .", | 935 "filename=evil.exe. . .", |
956 "", | 936 "", |
957 "", | 937 "", |
958 "binary/octet-stream", | 938 "binary/octet-stream", |
959 L"download", | 939 L"download", |
960 L"evil.exe-------"}, | 940 L"evil.exe. . _"}, |
961 {__LINE__, | 941 {__LINE__, |
962 "http://www.goodguy.com/evil.", | 942 "http://www.example.com/", |
963 "filename=evil.", | |
964 "", | |
965 "", | |
966 "binary/octet-stream", | |
967 L"download", | |
968 L"evil-"}, | |
969 {__LINE__, | |
970 "http://www.goodguy.com/. . . . .", | |
971 "filename=. . . . .", | 943 "filename=. . . . .", |
972 "", | 944 "", |
973 "", | 945 "", |
974 "binary/octet-stream", | 946 "binary/octet-stream", |
975 L"download", | 947 L"download", |
976 L"download"}, | 948 L"_ . . . _"}, |
977 {__LINE__, | 949 {__LINE__, |
978 "http://www.badguy.com/attachment?name=meh.exe%C2%A0", | 950 "http://www.example.com/", |
979 "attachment; filename=\"meh.exe\xC2\xA0\"", | 951 "filename=.", |
980 "", | 952 "", |
981 "", | 953 "", |
982 "binary/octet-stream", | 954 "binary/octet-stream", |
| 955 L"download", |
| 956 L"_"}, |
| 957 {__LINE__, |
| 958 "http://www.example.com/", |
| 959 "filename=..", |
| 960 "", |
| 961 "", |
| 962 "binary/octet-stream", |
| 963 L"download", |
| 964 L"__"}, |
| 965 {__LINE__, |
| 966 "http://www.example.com/", |
| 967 "filename=\"meh.exe\xC2\xA0\"", |
| 968 "", |
| 969 "", |
| 970 "", |
983 L"", | 971 L"", |
984 L"meh.exe-"}, | 972 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
985 #endif // OS_WIN | 973 // On Linux, \xA0 is allowed in the filename. |
986 {__LINE__, | 974 L"meh.exe\xA0" |
987 "http://www.goodguy.com/utils.js", | |
988 "filename=utils.js", | |
989 "", | |
990 "", | |
991 "application/x-javascript", | |
992 L"download", | |
993 L"utils.js"}, | |
994 {__LINE__, | |
995 "http://www.goodguy.com/contacts.js", | |
996 "filename=contacts.js", | |
997 "", | |
998 "", | |
999 "application/json", | |
1000 L"download", | |
1001 L"contacts.js"}, | |
1002 {__LINE__, | |
1003 "http://www.goodguy.com/utils.js", | |
1004 "filename=utils.js", | |
1005 "", | |
1006 "", | |
1007 "text/javascript", | |
1008 L"download", | |
1009 L"utils.js"}, | |
1010 {__LINE__, | |
1011 "http://www.goodguy.com/utils.js", | |
1012 "filename=utils.js", | |
1013 "", | |
1014 "", | |
1015 "text/javascript;version=2", | |
1016 L"download", | |
1017 L"utils.js"}, | |
1018 {__LINE__, | |
1019 "http://www.goodguy.com/utils.js", | |
1020 "filename=utils.js", | |
1021 "", | |
1022 "", | |
1023 "application/ecmascript", | |
1024 L"download", | |
1025 L"utils.js"}, | |
1026 {__LINE__, | |
1027 "http://www.goodguy.com/utils.js", | |
1028 "filename=utils.js", | |
1029 "", | |
1030 "", | |
1031 "application/ecmascript;version=4", | |
1032 L"download", | |
1033 L"utils.js"}, | |
1034 {__LINE__, | |
1035 "http://www.goodguy.com/program.exe", | |
1036 "filename=program.exe", | |
1037 "", | |
1038 "", | |
1039 "application/foo-bar", | |
1040 L"download", | |
1041 L"program.exe"}, | |
1042 {__LINE__, | |
1043 "http://www.evil.com/../foo.txt", | |
1044 "filename=../foo.txt", | |
1045 "", | |
1046 "", | |
1047 "text/plain", | |
1048 L"download", | |
1049 L"-foo.txt"}, | |
1050 {__LINE__, | |
1051 "http://www.evil.com/..\\foo.txt", | |
1052 "filename=..\\foo.txt", | |
1053 "", | |
1054 "", | |
1055 "text/plain", | |
1056 L"download", | |
1057 L"-foo.txt"}, | |
1058 {__LINE__, | |
1059 "http://www.evil.com/.hidden", | |
1060 "filename=.hidden", | |
1061 "", | |
1062 "", | |
1063 "text/plain", | |
1064 L"download", | |
1065 L"hidden"}, | |
1066 {__LINE__, | |
1067 "http://www.evil.com/trailing.", | |
1068 "filename=trailing.", | |
1069 "", | |
1070 "", | |
1071 "dance/party", | |
1072 L"download", | |
1073 #if defined(OS_WIN) | |
1074 L"trailing-" | |
1075 #else | 975 #else |
1076 L"trailing" | 976 L"meh.exe_" |
1077 #endif | 977 #endif |
1078 }, | 978 }, |
1079 {__LINE__, | 979 {// user.js should be left alone because the final extension matches the |
1080 "http://www.evil.com/trailing.", | 980 // MIME type. |
1081 "filename=trailing.", | 981 __LINE__, |
1082 "", | 982 "http://www.example.com/utils.user.js?foo", |
1083 "", | 983 "", |
1084 "text/plain", | 984 "", |
1085 L"download", | 985 "", |
1086 #if defined(OS_WIN) | 986 "application/javascript", |
1087 L"trailing-" | 987 L"", |
1088 #else | 988 L"utils.user.js"}, |
1089 L"trailing" | |
1090 #endif | |
1091 }, | |
1092 {__LINE__, | |
1093 "http://www.evil.com/.", | |
1094 "filename=.", | |
1095 "", | |
1096 "", | |
1097 "dance/party", | |
1098 L"download", | |
1099 L"download"}, | |
1100 {__LINE__, | |
1101 "http://www.evil.com/..", | |
1102 "filename=..", | |
1103 "", | |
1104 "", | |
1105 "dance/party", | |
1106 L"download", | |
1107 L"download"}, | |
1108 {__LINE__, | |
1109 "http://www.evil.com/...", | |
1110 "filename=...", | |
1111 "", | |
1112 "", | |
1113 "dance/party", | |
1114 L"download", | |
1115 L"download"}, | |
1116 {// Note that this one doesn't have "filename=" on it. | 989 {// Note that this one doesn't have "filename=" on it. |
1117 __LINE__, | 990 __LINE__, |
1118 "http://www.evil.com/", | 991 "http://www.example.com/", |
1119 "a_file_name.txt", | 992 "a_file_name.txt", |
1120 "", | 993 "", |
1121 "", | 994 "", |
1122 "image/jpeg", | 995 "image/jpeg", |
1123 L"download", | 996 L"default", |
1124 L"download" JPEG_EXT}, | 997 L"default" JPEG_EXT}, |
1125 {__LINE__, | 998 {// Content-Disposition specifies an empty filename. |
1126 "http://www.evil.com/", | 999 __LINE__, |
| 1000 "http://www.example.com/", |
1127 "filename=", | 1001 "filename=", |
1128 "", | 1002 "", |
1129 "", | 1003 "", |
1130 "image/jpeg", | 1004 "image/jpeg", |
1131 L"download", | 1005 L"default", |
1132 L"download" JPEG_EXT}, | 1006 L"default" JPEG_EXT}, |
1133 {__LINE__, | |
1134 "http://www.example.com/simple", | |
1135 "filename=simple", | |
1136 "", | |
1137 "", | |
1138 "application/octet-stream", | |
1139 L"download", | |
1140 L"simple"}, | |
1141 // Reserved words on Windows | 1007 // Reserved words on Windows |
1142 {__LINE__, | 1008 {__LINE__, |
1143 "http://www.goodguy.com/COM1", | 1009 "http://www.example.com/", |
1144 "filename=COM1", | 1010 "filename=COM1", |
1145 "", | 1011 "", |
1146 "", | 1012 "", |
1147 "application/foo-bar", | 1013 "application/foo-bar", |
1148 L"download", | 1014 L"download", |
1149 #if defined(OS_WIN) | 1015 L"_COM1"}, |
1150 L"_COM1" | 1016 {__LINE__, |
1151 #else | 1017 "http://www.example.com/", |
1152 L"COM1" | |
1153 #endif | |
1154 }, | |
1155 {__LINE__, | |
1156 "http://www.goodguy.com/COM4.txt", | |
1157 "filename=COM4.txt", | 1018 "filename=COM4.txt", |
1158 "", | 1019 "", |
1159 "", | 1020 "", |
1160 "text/plain", | 1021 "text/plain", |
1161 L"download", | 1022 L"download", |
1162 #if defined(OS_WIN) | 1023 L"_COM4.txt"}, |
1163 L"_COM4.txt" | 1024 {__LINE__, |
1164 #else | 1025 "http://www.example.com/", |
1165 L"COM4.txt" | |
1166 #endif | |
1167 }, | |
1168 {__LINE__, | |
1169 "http://www.goodguy.com/lpt1.TXT", | |
1170 "filename=lpt1.TXT", | 1026 "filename=lpt1.TXT", |
1171 "", | 1027 "", |
1172 "", | 1028 "", |
1173 "text/plain", | 1029 "text/plain", |
1174 L"download", | 1030 L"download", |
1175 #if defined(OS_WIN) | 1031 L"_lpt1.TXT"}, |
1176 L"_lpt1.TXT" | 1032 {__LINE__, |
1177 #else | 1033 "http://www.example.com/", |
1178 L"lpt1.TXT" | |
1179 #endif | |
1180 }, | |
1181 {__LINE__, | |
1182 "http://www.goodguy.com/clock$.txt", | |
1183 "filename=clock$.txt", | 1034 "filename=clock$.txt", |
1184 "", | 1035 "", |
1185 "", | 1036 "", |
1186 "text/plain", | 1037 "text/plain", |
1187 L"download", | 1038 L"download", |
1188 #if defined(OS_WIN) | 1039 L"_clock$.txt"}, |
1189 L"_clock$.txt" | |
1190 #else | |
1191 L"clock$.txt" | |
1192 #endif | |
1193 }, | |
1194 {// Validation should also apply to sugested name | 1040 {// Validation should also apply to sugested name |
1195 __LINE__, | 1041 __LINE__, |
1196 "http://www.goodguy.com/blah$.txt", | 1042 "http://www.example.com/", |
1197 "filename=clock$.txt", | 1043 "", |
1198 "", | 1044 "", |
1199 "clock$.txt", | 1045 "clock$.txt", |
1200 "text/plain", | 1046 "text/plain", |
1201 L"download", | 1047 L"download", |
1202 #if defined(OS_WIN) | 1048 L"_clock$.txt"}, |
1203 L"_clock$.txt" | 1049 {// Shouldn't match substrings. |
1204 #else | 1050 __LINE__, |
1205 L"clock$.txt" | 1051 "http://www.example.com/", |
1206 #endif | |
1207 }, | |
1208 {__LINE__, | |
1209 "http://www.goodguy.com/mycom1.foo", | |
1210 "filename=mycom1.foo", | 1052 "filename=mycom1.foo", |
1211 "", | 1053 "", |
1212 "", | 1054 "", |
1213 "text/plain", | 1055 "text/plain", |
1214 L"download", | 1056 L"download", |
1215 L"mycom1.foo"}, | 1057 L"mycom1.foo"}, |
1216 {__LINE__, | 1058 {// Shell integrated extensions. |
1217 "http://www.badguy.com/Setup.exe.local", | 1059 __LINE__, |
| 1060 "http://www.example.com/Setup.exe.local", |
1218 "filename=Setup.exe.local", | 1061 "filename=Setup.exe.local", |
1219 "", | 1062 "", |
1220 "", | 1063 "", |
1221 "application/foo-bar", | 1064 "application/foo-bar", |
1222 L"download", | 1065 L"download", |
1223 #if defined(OS_WIN) | 1066 L"Setup.exe.download"}, |
1224 L"Setup.exe.download" | 1067 {__LINE__, |
1225 #else | 1068 "http://www.example.com/Setup.exe.local", |
1226 L"Setup.exe.local" | |
1227 #endif | |
1228 }, | |
1229 {__LINE__, | |
1230 "http://www.badguy.com/Setup.exe.local", | |
1231 "filename=Setup.exe.local.local", | 1069 "filename=Setup.exe.local.local", |
1232 "", | 1070 "", |
1233 "", | 1071 "", |
1234 "application/foo-bar", | 1072 "application/foo-bar", |
1235 L"download", | 1073 L"download", |
1236 #if defined(OS_WIN) | 1074 L"Setup.exe.local.download"}, |
1237 L"Setup.exe.local.download" | 1075 {__LINE__, |
1238 #else | 1076 "http://www.example.com/Setup.exe.lnk", |
1239 L"Setup.exe.local.local" | |
1240 #endif | |
1241 }, | |
1242 {__LINE__, | |
1243 "http://www.badguy.com/Setup.exe.lnk", | |
1244 "filename=Setup.exe.lnk", | 1077 "filename=Setup.exe.lnk", |
1245 "", | 1078 "", |
1246 "", | 1079 "", |
1247 "application/foo-bar", | 1080 "application/foo-bar", |
1248 L"download", | 1081 L"download", |
1249 #if defined(OS_WIN) | 1082 L"Setup.exe.download"}, |
1250 L"Setup.exe.download" | 1083 {__LINE__, |
1251 #else | 1084 "http://www.example.com/Desktop.ini", |
1252 L"Setup.exe.lnk" | |
1253 #endif | |
1254 }, | |
1255 {__LINE__, | |
1256 "http://www.badguy.com/Desktop.ini", | |
1257 "filename=Desktop.ini", | 1085 "filename=Desktop.ini", |
1258 "", | 1086 "", |
1259 "", | 1087 "", |
1260 "application/foo-bar", | 1088 "application/foo-bar", |
1261 L"download", | 1089 L"download", |
1262 #if defined(OS_WIN) | 1090 L"_Desktop.ini"}, |
1263 L"_Desktop.ini" | 1091 {__LINE__, |
1264 #else | 1092 "http://www.example.com/Thumbs.db", |
1265 L"Desktop.ini" | |
1266 #endif | |
1267 }, | |
1268 {__LINE__, | |
1269 "http://www.badguy.com/Thumbs.db", | |
1270 "filename=Thumbs.db", | 1093 "filename=Thumbs.db", |
1271 "", | 1094 "", |
1272 "", | 1095 "", |
1273 "application/foo-bar", | 1096 "application/foo-bar", |
1274 L"download", | 1097 L"download", |
1275 #if defined(OS_WIN) | 1098 L"_Thumbs.db"}, |
1276 L"_Thumbs.db" | |
1277 #else | |
1278 L"Thumbs.db" | |
1279 #endif | |
1280 }, | |
1281 {__LINE__, | |
1282 "http://www.hotmail.com", | |
1283 "filename=source.jpg", | |
1284 "", | |
1285 "", | |
1286 "application/x-javascript", | |
1287 L"download", | |
1288 L"source.jpg"}, | |
1289 {// http://crbug.com/5772. | 1099 {// http://crbug.com/5772. |
1290 __LINE__, | 1100 __LINE__, |
1291 "http://www.example.com/foo.tar.gz", | 1101 "http://www.example.com/foo.tar.gz", |
1292 "", | 1102 "", |
1293 "", | 1103 "", |
1294 "", | 1104 "", |
1295 "application/x-tar", | 1105 "application/x-tar", |
1296 L"download", | 1106 L"download", |
1297 L"foo.tar.gz"}, | 1107 L"foo.tar.gz"}, |
1298 {// http://crbug.com/52250. | 1108 {// http://crbug.com/52250. |
1299 __LINE__, | 1109 __LINE__, |
1300 "http://www.example.com/foo.tgz", | 1110 "http://www.example.com/foo.tgz", |
1301 "", | 1111 "", |
1302 "", | 1112 "", |
1303 "", | 1113 "", |
1304 "application/x-tar", | 1114 "application/x-tar", |
1305 L"download", | 1115 L"download", |
1306 L"foo.tgz"}, | 1116 L"foo.tgz"}, |
1307 {// http://crbug.com/7337. | 1117 {// http://crbug.com/7337. |
1308 __LINE__, | 1118 __LINE__, |
1309 "http://maged.lordaeron.org/blank.reg", | 1119 "http://example.com/blank.reg", |
1310 "", | 1120 "", |
1311 "", | 1121 "", |
1312 "", | 1122 "", |
1313 "text/x-registry", | 1123 "text/x-registry", |
1314 L"download", | 1124 L"download", |
1315 L"blank.reg"}, | 1125 L"blank.reg"}, |
1316 {__LINE__, | 1126 {__LINE__, |
1317 "http://www.example.com/bar.tar", | 1127 "http://www.example.com/bar.tar", |
1318 "", | 1128 "", |
1319 "", | 1129 "", |
1320 "", | 1130 "", |
1321 "application/x-tar", | 1131 "application/x-tar", |
1322 L"download", | 1132 L"download", |
1323 L"bar.tar"}, | 1133 L"bar.tar"}, |
1324 {__LINE__, | 1134 {__LINE__, |
1325 "http://www.example.com/bar.bogus", | 1135 "http://www.example.com/bar.bogus", |
1326 "", | 1136 "", |
1327 "", | 1137 "", |
1328 "", | 1138 "", |
1329 "application/x-tar", | 1139 "application/x-tar", |
1330 L"download", | 1140 L"download", |
1331 L"bar.bogus"}, | 1141 L"bar.bogus"}, |
1332 {// http://crbug.com/20337 | 1142 {// http://crbug.com/20337 |
1333 __LINE__, | 1143 __LINE__, |
1334 "http://www.example.com/.download.txt", | 1144 "http://www.example.com/.download.txt", |
1335 "filename=.download.txt", | 1145 "filename=.foo.txt", |
1336 "", | 1146 "", |
1337 "", | 1147 "", |
1338 "text/plain", | 1148 "text/plain", |
1339 L"-download", | 1149 L"download", |
1340 L"download.txt"}, | 1150 L"_foo.txt"}, |
1341 {// http://crbug.com/56855. | 1151 {// http://crbug.com/56855. |
1342 __LINE__, | 1152 __LINE__, |
1343 "http://www.example.com/bar.sh", | 1153 "http://www.example.com/bar.sh", |
1344 "", | 1154 "", |
1345 "", | 1155 "", |
1346 "", | 1156 "", |
1347 "application/x-sh", | 1157 "application/x-sh", |
1348 L"download", | 1158 L"download", |
1349 L"bar.sh"}, | 1159 L"bar.sh"}, |
1350 {// http://crbug.com/61571 | 1160 {// http://crbug.com/61571 |
1351 __LINE__, | 1161 __LINE__, |
1352 "http://www.example.com/npdf.php?fn=foobar.pdf", | 1162 "http://www.example.com/npdf.php?fn=foobar.pdf", |
1353 "", | 1163 "", |
1354 "", | 1164 "", |
1355 "", | 1165 "", |
1356 "text/plain", | 1166 "text/plain", |
1357 L"download", | 1167 L"download", |
1358 L"npdf" TXT_EXT}, | 1168 L"npdf" TXT_EXT}, |
| 1169 {// The "extension" of the URL derived filename is going to be .tar.gz, |
| 1170 // whereas the extension mapped to application/gzip is .gz. Despite this |
| 1171 // the extension should be left as-is because the FinalExtension() of the |
| 1172 // filename matches .gz. |
| 1173 __LINE__, |
| 1174 "http://www.example.com/x.tar.gz?query", |
| 1175 "", |
| 1176 "", |
| 1177 "", |
| 1178 "application/gzip", |
| 1179 L"download", |
| 1180 L"x.tar.gz"}, |
| 1181 {// A MIME type can map to multiple extensions. Any of these should be |
| 1182 // accepted as the extension and should be overwritten only if there is no |
| 1183 // match. |
| 1184 __LINE__, |
| 1185 "http://www.example.com/foo.htm?query", |
| 1186 "", |
| 1187 "", |
| 1188 "", |
| 1189 "text/html", |
| 1190 L"download", |
| 1191 L"foo.htm"}, |
| 1192 {// A MIME type can map to multiple extensions. Any of these should be |
| 1193 // accepted as the extension and should be overwritten only if there is no |
| 1194 // match. |
| 1195 __LINE__, |
| 1196 "http://www.example.com/foo.html?query", |
| 1197 "", |
| 1198 "", |
| 1199 "", |
| 1200 "text/html", |
| 1201 L"download", |
| 1202 L"foo.html"}, |
| 1203 {// A MIME type can map to multiple extensions. Any of these should be |
| 1204 // accepted as the extension and should be overwritten only if there is no |
| 1205 // match. |
| 1206 __LINE__, |
| 1207 "http://www.example.com/foo.bar?query", |
| 1208 "", |
| 1209 "", |
| 1210 "", |
| 1211 "text/html", |
| 1212 L"download", |
| 1213 L"foo" HTML_EXT}, |
1359 {// Shouldn't overwrite C-D specified extension. | 1214 {// Shouldn't overwrite C-D specified extension. |
1360 __LINE__, | 1215 __LINE__, |
1361 "http://www.example.com/npdf.php?fn=foobar.pdf", | 1216 "http://www.example.com/npdf.php?fn=foobar.pdf", |
1362 "filename=foobar.jpg", | 1217 "filename=foobar.jpg", |
1363 "", | 1218 "", |
1364 "", | 1219 "", |
1365 "text/plain", | 1220 "text/plain", |
1366 L"download", | 1221 L"download", |
1367 L"foobar.jpg"}, | 1222 L"foobar.jpg"}, |
1368 {// http://crbug.com/87719 | 1223 {// http://crbug.com/87719 |
1369 __LINE__, | 1224 __LINE__, |
1370 "http://www.example.com/image.aspx?id=blargh", | 1225 "http://www.example.com/image.aspx?id=blargh", |
1371 "", | 1226 "", |
1372 "", | 1227 "", |
1373 "", | 1228 "", |
1374 "image/jpeg", | 1229 "image/jpeg", |
1375 L"download", | 1230 L"download", |
1376 L"image" JPEG_EXT}, | 1231 L"image" JPEG_EXT}, |
| 1232 {// Hostname derived filenames should have extensions appended. |
| 1233 __LINE__, |
| 1234 "http://www.example.com", |
| 1235 "", |
| 1236 "", |
| 1237 "", |
| 1238 "text/html", |
| 1239 L"", |
| 1240 L"www.example.com" HTML_EXT}, |
| 1241 {// IDN |
| 1242 __LINE__, |
| 1243 "http://xn--fzc2c9eoa8e.example.com", |
| 1244 "", |
| 1245 "", |
| 1246 "", |
| 1247 "", |
| 1248 L"", |
| 1249 L"\u0dbd\u0d82\u0d9a\u0dcf\u0dc0.example.com"}, |
1377 {__LINE__, | 1250 {__LINE__, |
1378 "http://www.example.com/image.aspx?id=blargh", | 1251 "http://www.example.com/image.aspx?id=blargh", |
1379 "", | 1252 "", |
1380 "", | 1253 "", |
1381 " .foo", | 1254 " .foo", |
1382 "", | 1255 "", |
1383 L"download", | 1256 L"download", |
1384 L"-.foo"}, | 1257 L"_.foo"}, |
1385 #if defined(OS_CHROMEOS) | 1258 #if defined(OS_CHROMEOS) |
1386 {// http://crosbug.com/26028 | 1259 {// http://crosbug.com/26028 |
1387 __LINE__, | 1260 __LINE__, |
1388 "http://www.example.com/fooa%cc%88.txt", | 1261 "http://www.example.com/fooa%cc%88.txt", |
1389 "", | 1262 "", |
1390 "", | 1263 "", |
1391 "", | 1264 "", |
1392 "image/jpeg", | 1265 "image/jpeg", |
1393 L"foo\xe4", | 1266 L"foo\xe4", |
1394 L"foo\xe4.txt"}, | 1267 L"foo\xe4.txt"}, |
1395 #endif | 1268 #endif |
1396 }; | 1269 }; |
1397 | 1270 |
1398 for (size_t i = 0; i < arraysize(selection_tests); ++i) | 1271 for (const auto& test_case : kSelectionTests) |
1399 RunGenerateFileNameTestCase(&selection_tests[i]); | 1272 RunGenerateFileNameTestCase(&test_case); |
1400 | 1273 |
1401 for (size_t i = 0; i < arraysize(generation_tests); ++i) | 1274 for (const auto& test_case : kGenerationTests) |
1402 RunGenerateFileNameTestCase(&generation_tests[i]); | 1275 RunGenerateFileNameTestCase(&test_case); |
1403 | 1276 |
1404 for (size_t i = 0; i < arraysize(generation_tests); ++i) { | 1277 for (const auto& const_test_case : kGenerationTests) { |
1405 GenerateFilenameCase test_case = generation_tests[i]; | 1278 GenerateFilenameCase test_case = const_test_case; |
1406 test_case.referrer_charset = "GBK"; | 1279 test_case.referrer_charset = "GBK"; |
1407 RunGenerateFileNameTestCase(&test_case); | 1280 RunGenerateFileNameTestCase(&test_case); |
1408 } | 1281 } |
1409 } | 1282 } |
1410 | 1283 |
1411 } // namespace net | 1284 } // namespace net |
OLD | NEW |