| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <map> | 9 #include <map> |
| 10 | 10 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 output_length = ucnv_toAlgorithmic(UCNV_UTF8, converter, buf, output_length, | 232 output_length = ucnv_toAlgorithmic(UCNV_UTF8, converter, buf, output_length, |
| 233 decoded.data(), decoded.length(), &err); | 233 decoded.data(), decoded.length(), &err); |
| 234 ucnv_close(converter); | 234 ucnv_close(converter); |
| 235 if (U_FAILURE(err)) | 235 if (U_FAILURE(err)) |
| 236 return false; | 236 return false; |
| 237 output->resize(output_length); | 237 output->resize(output_length); |
| 238 return true; | 238 return true; |
| 239 } | 239 } |
| 240 | 240 |
| 241 bool DecodeWord(const std::string& encoded_word, | 241 bool DecodeWord(const std::string& encoded_word, |
| 242 const std::string& referrer_charset, | 242 const std::string& default_charset, |
| 243 bool* is_rfc2047, | 243 bool* is_rfc2047, |
| 244 std::string* output) { | 244 std::string* output) { |
| 245 *is_rfc2047 = false; | 245 *is_rfc2047 = false; |
| 246 output->clear(); | 246 output->clear(); |
| 247 if (encoded_word.empty()) | 247 if (encoded_word.empty()) |
| 248 return true; | 248 return true; |
| 249 | 249 |
| 250 if (!IsStringASCII(encoded_word)) { | 250 if (!IsStringASCII(encoded_word)) { |
| 251 // Try UTF-8, referrer_charset and the native OS default charset in turn. | 251 // Try UTF-8, default_charset and the native OS default charset in turn. |
| 252 if (IsStringUTF8(encoded_word)) { | 252 if (IsStringUTF8(encoded_word)) { |
| 253 *output = encoded_word; | 253 *output = encoded_word; |
| 254 } else { | 254 } else { |
| 255 string16 utf16_output; | 255 string16 utf16_output; |
| 256 if (!referrer_charset.empty() && | 256 if (!default_charset.empty() && |
| 257 base::CodepageToUTF16(encoded_word, referrer_charset.c_str(), | 257 base::CodepageToUTF16(encoded_word, default_charset.c_str(), |
| 258 base::OnStringConversionError::FAIL, | 258 base::OnStringConversionError::FAIL, |
| 259 &utf16_output)) { | 259 &utf16_output)) { |
| 260 *output = UTF16ToUTF8(utf16_output); | 260 *output = UTF16ToUTF8(utf16_output); |
| 261 } else { | 261 } else { |
| 262 *output = WideToUTF8(base::SysNativeMBToWide(encoded_word)); | 262 *output = WideToUTF8(base::SysNativeMBToWide(encoded_word)); |
| 263 } | 263 } |
| 264 } | 264 } |
| 265 | 265 |
| 266 return true; | 266 return true; |
| 267 } | 267 } |
| (...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 ReplaceSubstringsAfterOffset(&filename, 0, "\\", "_"); | 919 ReplaceSubstringsAfterOffset(&filename, 0, "\\", "_"); |
| 920 } | 920 } |
| 921 } | 921 } |
| 922 | 922 |
| 923 // Returns the filename determined from the last component of the path portion | 923 // Returns the filename determined from the last component of the path portion |
| 924 // of the URL. Returns an empty string if the URL doesn't have a path or is | 924 // of the URL. Returns an empty string if the URL doesn't have a path or is |
| 925 // invalid. If the generated filename is not reliable, | 925 // invalid. If the generated filename is not reliable, |
| 926 // |should_overwrite_extension| will be set to true, in which case a better | 926 // |should_overwrite_extension| will be set to true, in which case a better |
| 927 // extension should be determined based on the content type. | 927 // extension should be determined based on the content type. |
| 928 std::string GetFileNameFromURL(const GURL& url, | 928 std::string GetFileNameFromURL(const GURL& url, |
| 929 const std::string& referrer_charset, | 929 const std::string& default_charset, |
| 930 bool* should_overwrite_extension) { | 930 bool* should_overwrite_extension) { |
| 931 // about: and data: URLs don't have file names, but esp. data: URLs may | 931 // about: and data: URLs don't have file names, but esp. data: URLs may |
| 932 // contain parts that look like ones (i.e., contain a slash). Therefore we | 932 // contain parts that look like ones (i.e., contain a slash). Therefore we |
| 933 // don't attempt to divine a file name out of them. | 933 // don't attempt to divine a file name out of them. |
| 934 if (!url.is_valid() || url.SchemeIs("about") || url.SchemeIs("data")) | 934 if (!url.is_valid() || url.SchemeIs("about") || url.SchemeIs("data")) |
| 935 return std::string(); | 935 return std::string(); |
| 936 | 936 |
| 937 const std::string unescaped_url_filename = UnescapeURLComponent( | 937 const std::string unescaped_url_filename = UnescapeURLComponent( |
| 938 url.ExtractFileName(), | 938 url.ExtractFileName(), |
| 939 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); | 939 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); |
| 940 | 940 |
| 941 // The URL's path should be escaped UTF-8, but may not be. | 941 // The URL's path should be escaped UTF-8, but may not be. |
| 942 std::string decoded_filename = unescaped_url_filename; | 942 std::string decoded_filename = unescaped_url_filename; |
| 943 if (!IsStringASCII(decoded_filename)) { | 943 if (!IsStringASCII(decoded_filename)) { |
| 944 bool ignore; | 944 bool ignore; |
| 945 // TODO(jshin): this is probably not robust enough. To be sure, we need | 945 // TODO(jshin): this is probably not robust enough. To be sure, we need |
| 946 // encoding detection. | 946 // encoding detection. |
| 947 DecodeWord(unescaped_url_filename, referrer_charset, &ignore, | 947 DecodeWord(unescaped_url_filename, default_charset, &ignore, |
| 948 &decoded_filename); | 948 &decoded_filename); |
| 949 } | 949 } |
| 950 // If the URL contains a (possibly empty) query, assume it is a generator, and | 950 // If the URL contains a (possibly empty) query, assume it is a generator, and |
| 951 // allow the determined extension to be overwritten. | 951 // allow the determined extension to be overwritten. |
| 952 *should_overwrite_extension = !decoded_filename.empty() && url.has_query(); | 952 *should_overwrite_extension = !decoded_filename.empty() && url.has_query(); |
| 953 | 953 |
| 954 return decoded_filename; | 954 return decoded_filename; |
| 955 } | 955 } |
| 956 | 956 |
| 957 #if defined(OS_WIN) | 957 #if defined(OS_WIN) |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 if (numDelimsSeen != 2) | 1180 if (numDelimsSeen != 2) |
| 1181 return false; | 1181 return false; |
| 1182 if (temp_charset.empty() || temp_value.empty()) | 1182 if (temp_charset.empty() || temp_value.empty()) |
| 1183 return false; | 1183 return false; |
| 1184 decoded_charset->swap(temp_charset); | 1184 decoded_charset->swap(temp_charset); |
| 1185 value->swap(temp_value); | 1185 value->swap(temp_value); |
| 1186 return true; | 1186 return true; |
| 1187 } | 1187 } |
| 1188 | 1188 |
| 1189 bool DecodeFilenameValue(const std::string& input, | 1189 bool DecodeFilenameValue(const std::string& input, |
| 1190 const std::string& referrer_charset, | 1190 const std::string& default_charset, |
| 1191 std::string* output) { | 1191 std::string* output) { |
| 1192 std::string tmp; | 1192 std::string tmp; |
| 1193 // Tokenize with whitespace characters. | 1193 // Tokenize with whitespace characters. |
| 1194 StringTokenizer t(input, " \t\n\r"); | 1194 StringTokenizer t(input, " \t\n\r"); |
| 1195 t.set_options(StringTokenizer::RETURN_DELIMS); | 1195 t.set_options(StringTokenizer::RETURN_DELIMS); |
| 1196 bool is_previous_token_rfc2047 = true; | 1196 bool is_previous_token_rfc2047 = true; |
| 1197 while (t.GetNext()) { | 1197 while (t.GetNext()) { |
| 1198 if (t.token_is_delim()) { | 1198 if (t.token_is_delim()) { |
| 1199 // If the previous non-delimeter token is not RFC2047-encoded, | 1199 // If the previous non-delimeter token is not RFC2047-encoded, |
| 1200 // put in a space in its place. Otheriwse, skip over it. | 1200 // put in a space in its place. Otheriwse, skip over it. |
| 1201 if (!is_previous_token_rfc2047) { | 1201 if (!is_previous_token_rfc2047) { |
| 1202 tmp.push_back(' '); | 1202 tmp.push_back(' '); |
| 1203 } | 1203 } |
| 1204 continue; | 1204 continue; |
| 1205 } | 1205 } |
| 1206 // We don't support a single multibyte character split into | 1206 // We don't support a single multibyte character split into |
| 1207 // adjacent encoded words. Some broken mail clients emit headers | 1207 // adjacent encoded words. Some broken mail clients emit headers |
| 1208 // with that problem, but most web servers usually encode a filename | 1208 // with that problem, but most web servers usually encode a filename |
| 1209 // in a single encoded-word. Firefox/Thunderbird do not support | 1209 // in a single encoded-word. Firefox/Thunderbird do not support |
| 1210 // it, either. | 1210 // it, either. |
| 1211 std::string decoded; | 1211 std::string decoded; |
| 1212 if (!DecodeWord(t.token(), referrer_charset, &is_previous_token_rfc2047, | 1212 if (!DecodeWord(t.token(), default_charset, &is_previous_token_rfc2047, |
| 1213 &decoded)) | 1213 &decoded)) |
| 1214 return false; | 1214 return false; |
| 1215 tmp.append(decoded); | 1215 tmp.append(decoded); |
| 1216 } | 1216 } |
| 1217 output->swap(tmp); | 1217 output->swap(tmp); |
| 1218 return true; | 1218 return true; |
| 1219 } | 1219 } |
| 1220 | 1220 |
| 1221 bool DecodeExtValue(const std::string& param_value, std::string* decoded) { | 1221 bool DecodeExtValue(const std::string& param_value, std::string* decoded) { |
| 1222 if (param_value.find('"') != std::string::npos) | 1222 if (param_value.find('"') != std::string::npos) |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1394 *file_path = FilePath(leaf_name); | 1394 *file_path = FilePath(leaf_name); |
| 1395 } else { | 1395 } else { |
| 1396 *file_path = file_path->Append(leaf_name); | 1396 *file_path = file_path->Append(leaf_name); |
| 1397 } | 1397 } |
| 1398 } | 1398 } |
| 1399 #endif | 1399 #endif |
| 1400 } | 1400 } |
| 1401 | 1401 |
| 1402 string16 GetSuggestedFilename(const GURL& url, | 1402 string16 GetSuggestedFilename(const GURL& url, |
| 1403 const std::string& content_disposition, | 1403 const std::string& content_disposition, |
| 1404 const std::string& referrer_charset, | 1404 const std::string& default_charset, |
| 1405 const std::string& suggested_name, | 1405 const std::string& suggested_name, |
| 1406 const std::string& mime_type, | 1406 const std::string& mime_type, |
| 1407 const std::string& default_name) { | 1407 const std::string& default_name) { |
| 1408 // TODO: this function to be updated to match the httpbis recommendations. | 1408 // TODO: this function to be updated to match the httpbis recommendations. |
| 1409 // Talk to abarth for the latest news. | 1409 // Talk to abarth for the latest news. |
| 1410 | 1410 |
| 1411 // We don't translate this fallback string, "download". If localization is | 1411 // We don't translate this fallback string, "download". If localization is |
| 1412 // needed, the caller should provide localized fallback in |default_name|. | 1412 // needed, the caller should provide localized fallback in |default_name|. |
| 1413 static const char* kFinalFallbackName = "download"; | 1413 static const char* kFinalFallbackName = "download"; |
| 1414 std::string filename; // In UTF-8 | 1414 std::string filename; // In UTF-8 |
| 1415 bool overwrite_extension = false; | 1415 bool overwrite_extension = false; |
| 1416 | 1416 |
| 1417 // Try to extract a filename from content-disposition first. | 1417 // Try to extract a filename from content-disposition first. |
| 1418 if (!content_disposition.empty()) { | 1418 if (!content_disposition.empty()) { |
| 1419 HttpContentDisposition header(content_disposition, referrer_charset); | 1419 HttpContentDisposition header(content_disposition, default_charset); |
| 1420 filename = header.filename(); | 1420 filename = header.filename(); |
| 1421 } | 1421 } |
| 1422 | 1422 |
| 1423 // Then try to use the suggested name. | 1423 // Then try to use the suggested name. |
| 1424 if (filename.empty() && !suggested_name.empty()) | 1424 if (filename.empty() && !suggested_name.empty()) |
| 1425 filename = suggested_name; | 1425 filename = suggested_name; |
| 1426 | 1426 |
| 1427 // Now try extracting the filename from the URL. GetFileNameFromURL() only | 1427 // Now try extracting the filename from the URL. GetFileNameFromURL() only |
| 1428 // looks at the last component of the URL and doesn't return the hostname as a | 1428 // looks at the last component of the URL and doesn't return the hostname as a |
| 1429 // failover. | 1429 // failover. |
| 1430 if (filename.empty()) | 1430 if (filename.empty()) |
| 1431 filename = GetFileNameFromURL(url, referrer_charset, &overwrite_extension); | 1431 filename = GetFileNameFromURL(url, default_charset, &overwrite_extension); |
| 1432 | 1432 |
| 1433 // Finally try the URL hostname, but only if there's no default specified in | 1433 // Finally try the URL hostname, but only if there's no default specified in |
| 1434 // |default_name|. Some schemes (e.g.: file:, about:, data:) do not have a | 1434 // |default_name|. Some schemes (e.g.: file:, about:, data:) do not have a |
| 1435 // host name. | 1435 // host name. |
| 1436 if (filename.empty() && default_name.empty() && | 1436 if (filename.empty() && default_name.empty() && |
| 1437 url.is_valid() && !url.host().empty()) { | 1437 url.is_valid() && !url.host().empty()) { |
| 1438 // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451) | 1438 // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451) |
| 1439 filename = url.host(); | 1439 filename = url.host(); |
| 1440 } | 1440 } |
| 1441 | 1441 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1473 std::string path = filename.empty() ? default_name : filename; | 1473 std::string path = filename.empty() ? default_name : filename; |
| 1474 file_util::ReplaceIllegalCharactersInPath(&path, '-'); | 1474 file_util::ReplaceIllegalCharactersInPath(&path, '-'); |
| 1475 FilePath result(path); | 1475 FilePath result(path); |
| 1476 GenerateSafeFileName(mime_type, overwrite_extension, &result); | 1476 GenerateSafeFileName(mime_type, overwrite_extension, &result); |
| 1477 return UTF8ToUTF16(result.value()); | 1477 return UTF8ToUTF16(result.value()); |
| 1478 #endif | 1478 #endif |
| 1479 } | 1479 } |
| 1480 | 1480 |
| 1481 FilePath GenerateFileName(const GURL& url, | 1481 FilePath GenerateFileName(const GURL& url, |
| 1482 const std::string& content_disposition, | 1482 const std::string& content_disposition, |
| 1483 const std::string& referrer_charset, | 1483 const std::string& default_charset, |
| 1484 const std::string& suggested_name, | 1484 const std::string& suggested_name, |
| 1485 const std::string& mime_type, | 1485 const std::string& mime_type, |
| 1486 const std::string& default_file_name) { | 1486 const std::string& default_file_name) { |
| 1487 string16 file_name = GetSuggestedFilename(url, | 1487 string16 file_name = GetSuggestedFilename(url, |
| 1488 content_disposition, | 1488 content_disposition, |
| 1489 referrer_charset, | 1489 default_charset, |
| 1490 suggested_name, | 1490 suggested_name, |
| 1491 mime_type, | 1491 mime_type, |
| 1492 default_file_name); | 1492 default_file_name); |
| 1493 | 1493 |
| 1494 #if defined(OS_WIN) | 1494 #if defined(OS_WIN) |
| 1495 FilePath generated_name(file_name); | 1495 FilePath generated_name(file_name); |
| 1496 #else | 1496 #else |
| 1497 FilePath generated_name(base::SysWideToNativeMB(UTF16ToWide(file_name))); | 1497 FilePath generated_name(base::SysWideToNativeMB(UTF16ToWide(file_name))); |
| 1498 #endif | 1498 #endif |
| 1499 DCHECK(!generated_name.empty()); | 1499 DCHECK(!generated_name.empty()); |
| (...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2403 | 2403 |
| 2404 NetworkInterface::NetworkInterface(const std::string& name, | 2404 NetworkInterface::NetworkInterface(const std::string& name, |
| 2405 const IPAddressNumber& address) | 2405 const IPAddressNumber& address) |
| 2406 : name(name), address(address) { | 2406 : name(name), address(address) { |
| 2407 } | 2407 } |
| 2408 | 2408 |
| 2409 NetworkInterface::~NetworkInterface() { | 2409 NetworkInterface::~NetworkInterface() { |
| 2410 } | 2410 } |
| 2411 | 2411 |
| 2412 } // namespace net | 2412 } // namespace net |
| OLD | NEW |