Home | History | Annotate | Download | only in base
      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