| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/net_util.h" | 5 #include "net/base/net_util.h" |
| 6 | 6 |
| 7 #include <unicode/regex.h> | 7 #include <unicode/regex.h> |
| 8 #include <unicode/ucnv.h> | 8 #include <unicode/ucnv.h> |
| 9 #include <unicode/uidna.h> | 9 #include <unicode/uidna.h> |
| 10 #include <unicode/ulocdata.h> | 10 #include <unicode/ulocdata.h> |
| (...skipping 904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 915 } | 915 } |
| 916 | 916 |
| 917 char* do_strdup(const char* src) { | 917 char* do_strdup(const char* src) { |
| 918 #if defined(OS_WIN) | 918 #if defined(OS_WIN) |
| 919 return _strdup(src); | 919 return _strdup(src); |
| 920 #else | 920 #else |
| 921 return strdup(src); | 921 return strdup(src); |
| 922 #endif | 922 #endif |
| 923 } | 923 } |
| 924 | 924 |
| 925 void SanitizeGeneratedFileName(std::string& filename) { |
| 926 if (!filename.empty()) { |
| 927 // Remove "." from the beginning and end of the file name to avoid tricks |
| 928 // with hidden files, "..", and "." |
| 929 TrimString(filename, ".", &filename); |
| 930 #if defined(OS_WIN) |
| 931 // Handle CreateFile() stripping trailing dots and spaces on filenames |
| 932 // http://support.microsoft.com/kb/115827 |
| 933 std::string::size_type pos = filename.find_last_not_of(" ."); |
| 934 if (pos == std::string::npos) |
| 935 filename.resize(0); |
| 936 else |
| 937 filename.resize(++pos); |
| 938 #endif |
| 939 // Replace any path information by changing path separators with |
| 940 // underscores. |
| 941 ReplaceSubstringsAfterOffset(&filename, 0, "/", "_"); |
| 942 ReplaceSubstringsAfterOffset(&filename, 0, "\\", "_"); |
| 943 } |
| 944 } |
| 945 |
| 946 std::string GetFileNameFromURL(const GURL& url, |
| 947 const std::string& referrer_charset) { |
| 948 // about: and data: URLs don't have file names, but esp. data: URLs may |
| 949 // contain parts that look like ones (i.e., contain a slash). Therefore we |
| 950 // don't attempt to divine a file name out of them. |
| 951 if (!url.is_valid() || url.SchemeIs("about") || url.SchemeIs("data")) |
| 952 return std::string(); |
| 953 |
| 954 const std::string unescaped_url_filename = UnescapeURLComponent( |
| 955 url.ExtractFileName(), |
| 956 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); |
| 957 |
| 958 // The URL's path should be escaped UTF-8, but may not be. |
| 959 std::string decoded_filename = unescaped_url_filename; |
| 960 if (!IsStringASCII(decoded_filename)) { |
| 961 bool ignore; |
| 962 // TODO(jshin): this is probably not robust enough. To be sure, we need |
| 963 // encoding detection. |
| 964 DecodeWord(unescaped_url_filename, referrer_charset, &ignore, |
| 965 &decoded_filename); |
| 966 } |
| 967 |
| 968 return decoded_filename; |
| 969 } |
| 970 |
| 925 #if defined(OS_WIN) | 971 #if defined(OS_WIN) |
| 926 // Returns whether the specified extension is automatically integrated into the | 972 // Returns whether the specified extension is automatically integrated into the |
| 927 // windows shell. | 973 // windows shell. |
| 928 bool IsShellIntegratedExtension(const string16& extension) { | 974 bool IsShellIntegratedExtension(const string16& extension) { |
| 929 string16 extension_lower = StringToLowerASCII(extension); | 975 string16 extension_lower = StringToLowerASCII(extension); |
| 930 | 976 |
| 931 static const wchar_t* const integrated_extensions[] = { | 977 static const wchar_t* const integrated_extensions[] = { |
| 932 // See <http://msdn.microsoft.com/en-us/library/ms811694.aspx>. | 978 // See <http://msdn.microsoft.com/en-us/library/ms811694.aspx>. |
| 933 L"local", | 979 L"local", |
| 934 // Right-clicking on shortcuts can be magical. | 980 // Right-clicking on shortcuts can be magical. |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1372 *file_path = file_path->Append(leaf_name); | 1418 *file_path = file_path->Append(leaf_name); |
| 1373 } | 1419 } |
| 1374 } | 1420 } |
| 1375 #endif | 1421 #endif |
| 1376 } | 1422 } |
| 1377 | 1423 |
| 1378 string16 GetSuggestedFilename(const GURL& url, | 1424 string16 GetSuggestedFilename(const GURL& url, |
| 1379 const std::string& content_disposition, | 1425 const std::string& content_disposition, |
| 1380 const std::string& referrer_charset, | 1426 const std::string& referrer_charset, |
| 1381 const std::string& suggested_name, | 1427 const std::string& suggested_name, |
| 1428 const std::string& mime_type, |
| 1382 const string16& default_name) { | 1429 const string16& default_name) { |
| 1383 // TODO: this function to be updated to match the httpbis recommendations. | 1430 // TODO: this function to be updated to match the httpbis recommendations. |
| 1384 // Talk to abarth for the latest news. | 1431 // Talk to abarth for the latest news. |
| 1385 | 1432 |
| 1386 // We don't translate this fallback string, "download". If localization is | 1433 // We don't translate this fallback string, "download". If localization is |
| 1387 // needed, the caller should provide localized fallback default_name. | 1434 // needed, the caller should provide localized fallback in |default_name|. |
| 1388 static const char* kFinalFallbackName = "download"; | 1435 static const char* kFinalFallbackName = "download"; |
| 1436 std::string filename; // In UTF-8 |
| 1389 | 1437 |
| 1390 std::string filename; | 1438 // Try to extract a filename from content-disposition first. |
| 1391 | |
| 1392 // Try to extract from content-disposition first. | |
| 1393 if (!content_disposition.empty()) | 1439 if (!content_disposition.empty()) |
| 1394 filename = GetFileNameFromCD(content_disposition, referrer_charset); | 1440 filename = GetFileNameFromCD(content_disposition, referrer_charset); |
| 1395 | 1441 |
| 1396 // Then try to use suggested name. | 1442 // Then try to use the suggested name. |
| 1397 if (filename.empty() && !suggested_name.empty()) | 1443 if (filename.empty() && !suggested_name.empty()) |
| 1398 filename = suggested_name; | 1444 filename = suggested_name; |
| 1399 | 1445 |
| 1400 if (!filename.empty()) { | 1446 // Now try extracting the filename from the URL. GetFileNameFromURL() only |
| 1401 // Replace any path information the server may have sent, by changing | 1447 // looks at the last component of the URL and doesn't return the hostname as a |
| 1402 // path separators with underscores. | 1448 // failover. |
| 1403 ReplaceSubstringsAfterOffset(&filename, 0, "/", "_"); | 1449 if (filename.empty()) |
| 1404 ReplaceSubstringsAfterOffset(&filename, 0, "\\", "_"); | 1450 filename = GetFileNameFromURL(url, referrer_charset); |
| 1405 | 1451 |
| 1406 // Next, remove "." from the beginning and end of the file name to avoid | 1452 // Finally try the URL hostname, but only if there's no default specified in |
| 1407 // tricks with hidden files, "..", and "." | 1453 // |default_name|. Some schemes (e.g.: file:, about:, data:) do not have a |
| 1408 TrimString(filename, ".", &filename); | 1454 // host name. |
| 1455 if (filename.empty() && default_name.empty() && |
| 1456 url.is_valid() && !url.host().empty()) { |
| 1457 // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451) |
| 1458 filename = url.host(); |
| 1409 } | 1459 } |
| 1410 | 1460 |
| 1411 if (filename.empty()) { | 1461 SanitizeGeneratedFileName(filename); |
| 1412 // about: and data: URLs don't have file names, but esp. data: URLs may | 1462 // Sanitization can cause the filename to disappear (e.g.: if the filename |
| 1413 // contain parts that look like ones (i.e., contain a slash). | 1463 // consisted entirely of spaces and '.'s), in which case we use the default. |
| 1414 // Therefore we don't attempt to divine a file name out of them. | 1464 if (filename.empty() && default_name.empty()) |
| 1415 if (url.SchemeIs("about") || url.SchemeIs("data")) { | 1465 filename = kFinalFallbackName; |
| 1416 return default_name.empty() ? ASCIIToUTF16(kFinalFallbackName) | |
| 1417 : default_name; | |
| 1418 } | |
| 1419 | |
| 1420 if (url.is_valid()) { | |
| 1421 const std::string unescaped_url_filename = UnescapeURLComponent( | |
| 1422 url.ExtractFileName(), | |
| 1423 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); | |
| 1424 | |
| 1425 // The URL's path should be escaped UTF-8, but may not be. | |
| 1426 std::string decoded_filename = unescaped_url_filename; | |
| 1427 if (!IsStringASCII(decoded_filename)) { | |
| 1428 bool ignore; | |
| 1429 // TODO(jshin): this is probably not robust enough. To be sure, we | |
| 1430 // need encoding detection. | |
| 1431 DecodeWord(unescaped_url_filename, referrer_charset, &ignore, | |
| 1432 &decoded_filename); | |
| 1433 } | |
| 1434 | |
| 1435 filename = decoded_filename; | |
| 1436 } | |
| 1437 } | |
| 1438 | 1466 |
| 1439 #if defined(OS_WIN) | 1467 #if defined(OS_WIN) |
| 1440 { // Handle CreateFile() stripping trailing dots and spaces on filenames | 1468 string16 path = (filename.empty())? default_name : UTF8ToUTF16(filename); |
| 1441 // http://support.microsoft.com/kb/115827 | |
| 1442 std::string::size_type pos = filename.find_last_not_of(" ."); | |
| 1443 if (pos == std::string::npos) | |
| 1444 filename.resize(0); | |
| 1445 else | |
| 1446 filename.resize(++pos); | |
| 1447 } | |
| 1448 #endif | |
| 1449 // Trim '.' once more. | |
| 1450 TrimString(filename, ".", &filename); | |
| 1451 | |
| 1452 // If there's no filename or it gets trimed to be empty, use | |
| 1453 // the URL hostname or default_name | |
| 1454 if (filename.empty()) { | |
| 1455 if (!default_name.empty()) { | |
| 1456 return default_name; | |
| 1457 } else if (url.is_valid()) { | |
| 1458 // Some schemes (e.g. file) do not have a hostname. Even though it's | |
| 1459 // not likely to reach here, let's hardcode the last fallback name. | |
| 1460 // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451) | |
| 1461 filename = url.host().empty() ? kFinalFallbackName : url.host(); | |
| 1462 } else { | |
| 1463 NOTREACHED(); | |
| 1464 } | |
| 1465 } | |
| 1466 | |
| 1467 #if defined(OS_WIN) | |
| 1468 string16 path = UTF8ToUTF16(filename); | |
| 1469 file_util::ReplaceIllegalCharactersInPath(&path, '-'); | 1469 file_util::ReplaceIllegalCharactersInPath(&path, '-'); |
| 1470 return path; | 1470 FilePath result(path); |
| 1471 GenerateSafeFileName(mime_type, &result); |
| 1472 return result.value(); |
| 1471 #else | 1473 #else |
| 1472 std::string path = filename; | 1474 std::string path = (filename.empty())? UTF16ToUTF8(default_name) : filename; |
| 1473 file_util::ReplaceIllegalCharactersInPath(&path, '-'); | 1475 file_util::ReplaceIllegalCharactersInPath(&path, '-'); |
| 1474 return UTF8ToUTF16(path); | 1476 FilePath result(path); |
| 1477 GenerateSafeFileName(mime_type, &result); |
| 1478 return UTF8ToUTF16(result.value()); |
| 1475 #endif | 1479 #endif |
| 1476 } | 1480 } |
| 1477 | 1481 |
| 1478 FilePath GenerateFileName(const GURL& url, | 1482 FilePath GenerateFileName(const GURL& url, |
| 1479 const std::string& content_disposition, | 1483 const std::string& content_disposition, |
| 1480 const std::string& referrer_charset, | 1484 const std::string& referrer_charset, |
| 1481 const std::string& suggested_name, | 1485 const std::string& suggested_name, |
| 1482 const std::string& mime_type, | 1486 const std::string& mime_type, |
| 1483 const string16& default_file_name) { | 1487 const string16& default_file_name) { |
| 1484 string16 new_name = GetSuggestedFilename(GURL(url), | 1488 string16 file_name = GetSuggestedFilename(url, |
| 1485 content_disposition, | 1489 content_disposition, |
| 1486 referrer_charset, | 1490 referrer_charset, |
| 1487 suggested_name, | 1491 suggested_name, |
| 1488 default_file_name); | 1492 mime_type, |
| 1493 default_file_name); |
| 1489 | 1494 |
| 1490 // TODO(evan): this code is totally wrong -- we should just generate | |
| 1491 // Unicode filenames and do all this encoding switching at the end. | |
| 1492 // However, I'm just shuffling wrong code around, at least not adding | |
| 1493 // to it. | |
| 1494 #if defined(OS_WIN) | 1495 #if defined(OS_WIN) |
| 1495 FilePath generated_name = FilePath(new_name); | 1496 FilePath generated_name(file_name); |
| 1496 #else | 1497 #else |
| 1497 FilePath generated_name = FilePath( | 1498 FilePath generated_name(base::SysWideToNativeMB(UTF16ToWide(file_name))); |
| 1498 base::SysWideToNativeMB(UTF16ToWide(new_name))); | |
| 1499 #endif | 1499 #endif |
| 1500 | |
| 1501 DCHECK(!generated_name.empty()); | 1500 DCHECK(!generated_name.empty()); |
| 1502 | 1501 |
| 1503 GenerateSafeFileName(mime_type, &generated_name); | |
| 1504 return generated_name; | 1502 return generated_name; |
| 1505 } | 1503 } |
| 1506 | 1504 |
| 1507 bool IsPortAllowedByDefault(int port) { | 1505 bool IsPortAllowedByDefault(int port) { |
| 1508 int array_size = arraysize(kRestrictedPorts); | 1506 int array_size = arraysize(kRestrictedPorts); |
| 1509 for (int i = 0; i < array_size; i++) { | 1507 for (int i = 0; i < array_size; i++) { |
| 1510 if (kRestrictedPorts[i] == port) { | 1508 if (kRestrictedPorts[i] == port) { |
| 1511 return false; | 1509 return false; |
| 1512 } | 1510 } |
| 1513 } | 1511 } |
| (...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2403 | 2401 |
| 2404 NetworkInterface::NetworkInterface(const std::string& name, | 2402 NetworkInterface::NetworkInterface(const std::string& name, |
| 2405 const IPAddressNumber& address) | 2403 const IPAddressNumber& address) |
| 2406 : name(name), address(address) { | 2404 : name(name), address(address) { |
| 2407 } | 2405 } |
| 2408 | 2406 |
| 2409 NetworkInterface::~NetworkInterface() { | 2407 NetworkInterface::~NetworkInterface() { |
| 2410 } | 2408 } |
| 2411 | 2409 |
| 2412 } // namespace net | 2410 } // namespace net |
| OLD | NEW |