| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 <algorithm> | 5 #include <algorithm> |
| 6 #include <unicode/ucnv.h> | 6 #include <unicode/ucnv.h> |
| 7 #include <unicode/uidna.h> | 7 #include <unicode/uidna.h> |
| 8 #include <unicode/ulocdata.h> | 8 #include <unicode/ulocdata.h> |
| 9 #include <unicode/uniset.h> | 9 #include <unicode/uniset.h> |
| 10 #include <unicode/uscript.h> | 10 #include <unicode/uscript.h> |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 decoded.data(), length, &err); | 240 decoded.data(), length, &err); |
| 241 ucnv_close(converter); | 241 ucnv_close(converter); |
| 242 if (U_FAILURE(err)) { | 242 if (U_FAILURE(err)) { |
| 243 return false; | 243 return false; |
| 244 } | 244 } |
| 245 output->resize(length); | 245 output->resize(length); |
| 246 return true; | 246 return true; |
| 247 } | 247 } |
| 248 | 248 |
| 249 bool DecodeWord(const std::string& encoded_word, | 249 bool DecodeWord(const std::string& encoded_word, |
| 250 const std::string& referrer_charset, |
| 250 bool *is_rfc2047, | 251 bool *is_rfc2047, |
| 251 std::string* output) { | 252 std::string* output) { |
| 252 // TODO(jungshik) : Revisit this later. Do we want to pass through non-ASCII | |
| 253 // strings which can be mozibake? WinHTTP converts a raw 8bit string | |
| 254 // UTF-16 assuming it's in the OS default encoding. | |
| 255 if (!IsStringASCII(encoded_word)) { | 253 if (!IsStringASCII(encoded_word)) { |
| 256 // Try falling back to the NativeMB encoding if the raw input is not UTF-8. | 254 // Try UTF-8, referrer_charset and the native OS default charset in turn. |
| 257 if (IsStringUTF8(encoded_word)) { | 255 if (IsStringUTF8(encoded_word)) { |
| 258 *output = encoded_word; | 256 *output = encoded_word; |
| 259 } else { | 257 } else { |
| 260 *output = WideToUTF8(base::SysNativeMBToWide(encoded_word)); | 258 std::wstring wide_output; |
| 259 if (!referrer_charset.empty() && |
| 260 CodepageToWide(encoded_word, referrer_charset.c_str(), |
| 261 OnStringUtilConversionError::FAIL, &wide_output)) { |
| 262 *output = WideToUTF8(wide_output); |
| 263 } else { |
| 264 *output = WideToUTF8(base::SysNativeMBToWide(encoded_word)); |
| 265 } |
| 261 } | 266 } |
| 262 *is_rfc2047 = false; | 267 *is_rfc2047 = false; |
| 263 return true; | 268 return true; |
| 264 } | 269 } |
| 265 | 270 |
| 266 // RFC 2047 : one of encoding methods supported by Firefox and relatively | 271 // RFC 2047 : one of encoding methods supported by Firefox and relatively |
| 267 // widely used by web servers. | 272 // widely used by web servers. |
| 268 // =?charset?<E>?<encoded string>?= where '<E>' is either 'B' or 'Q'. | 273 // =?charset?<E>?<encoded string>?= where '<E>' is either 'B' or 'Q'. |
| 269 // We don't care about the length restriction (72 bytes) because | 274 // We don't care about the length restriction (72 bytes) because |
| 270 // many web servers generate encoded words longer than the limit. | 275 // many web servers generate encoded words longer than the limit. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 return true; | 355 return true; |
| 351 // We can try either the OS default charset or 'origin charset' here, | 356 // We can try either the OS default charset or 'origin charset' here, |
| 352 // As far as I can tell, IE does not support it. However, I've seen | 357 // As far as I can tell, IE does not support it. However, I've seen |
| 353 // web servers emit %-escaped string in a legacy encoding (usually | 358 // web servers emit %-escaped string in a legacy encoding (usually |
| 354 // origin charset). | 359 // origin charset). |
| 355 // TODO(jungshik) : Test IE further and consider adding a fallback here. | 360 // TODO(jungshik) : Test IE further and consider adding a fallback here. |
| 356 } | 361 } |
| 357 return false; | 362 return false; |
| 358 } | 363 } |
| 359 | 364 |
| 360 bool DecodeParamValue(const std::string& input, std::string* output) { | 365 bool DecodeParamValue(const std::string& input, |
| 366 const std::string& referrer_charset, |
| 367 std::string* output) { |
| 361 std::string tmp; | 368 std::string tmp; |
| 362 // Tokenize with whitespace characters. | 369 // Tokenize with whitespace characters. |
| 363 StringTokenizer t(input, " \t\n\r"); | 370 StringTokenizer t(input, " \t\n\r"); |
| 364 t.set_options(StringTokenizer::RETURN_DELIMS); | 371 t.set_options(StringTokenizer::RETURN_DELIMS); |
| 365 bool is_previous_token_rfc2047 = true; | 372 bool is_previous_token_rfc2047 = true; |
| 366 while (t.GetNext()) { | 373 while (t.GetNext()) { |
| 367 if (t.token_is_delim()) { | 374 if (t.token_is_delim()) { |
| 368 // If the previous non-delimeter token is not RFC2047-encoded, | 375 // If the previous non-delimeter token is not RFC2047-encoded, |
| 369 // put in a space in its place. Otheriwse, skip over it. | 376 // put in a space in its place. Otheriwse, skip over it. |
| 370 if (!is_previous_token_rfc2047) { | 377 if (!is_previous_token_rfc2047) { |
| 371 tmp.push_back(' '); | 378 tmp.push_back(' '); |
| 372 } | 379 } |
| 373 continue; | 380 continue; |
| 374 } | 381 } |
| 375 // We don't support a single multibyte character split into | 382 // We don't support a single multibyte character split into |
| 376 // adjacent encoded words. Some broken mail clients emit headers | 383 // adjacent encoded words. Some broken mail clients emit headers |
| 377 // with that problem, but most web servers usually encode a filename | 384 // with that problem, but most web servers usually encode a filename |
| 378 // in a single encoded-word. Firefox/Thunderbird do not support | 385 // in a single encoded-word. Firefox/Thunderbird do not support |
| 379 // it, either. | 386 // it, either. |
| 380 std::string decoded; | 387 std::string decoded; |
| 381 if (!DecodeWord(t.token(), &is_previous_token_rfc2047, &decoded)) | 388 if (!DecodeWord(t.token(), referrer_charset, &is_previous_token_rfc2047, |
| 389 &decoded)) |
| 382 return false; | 390 return false; |
| 383 tmp.append(decoded); | 391 tmp.append(decoded); |
| 384 } | 392 } |
| 385 output->swap(tmp); | 393 output->swap(tmp); |
| 386 return true; | 394 return true; |
| 387 } | 395 } |
| 388 | 396 |
| 389 // TODO(mpcomplete): This is a quick and dirty implementation for now. I'm | 397 // TODO(mpcomplete): This is a quick and dirty implementation for now. I'm |
| 390 // sure this doesn't properly handle all (most?) cases. | 398 // sure this doesn't properly handle all (most?) cases. |
| 391 template<typename STR> | 399 template<typename STR> |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 std::wstring GetSpecificHeader(const std::wstring& headers, | 684 std::wstring GetSpecificHeader(const std::wstring& headers, |
| 677 const std::wstring& name) { | 685 const std::wstring& name) { |
| 678 return GetSpecificHeaderT(headers, name); | 686 return GetSpecificHeaderT(headers, name); |
| 679 } | 687 } |
| 680 | 688 |
| 681 std::string GetSpecificHeader(const std::string& headers, | 689 std::string GetSpecificHeader(const std::string& headers, |
| 682 const std::string& name) { | 690 const std::string& name) { |
| 683 return GetSpecificHeaderT(headers, name); | 691 return GetSpecificHeaderT(headers, name); |
| 684 } | 692 } |
| 685 | 693 |
| 686 std::wstring GetFileNameFromCD(const std::string& header) { | 694 std::wstring GetFileNameFromCD(const std::string& header, |
| 695 const std::string& referrer_charset) { |
| 687 std::string param_value = GetHeaderParamValue(header, "filename"); | 696 std::string param_value = GetHeaderParamValue(header, "filename"); |
| 688 if (param_value.empty()) { | 697 if (param_value.empty()) { |
| 689 // Some servers use 'name' parameter. | 698 // Some servers use 'name' parameter. |
| 690 param_value = GetHeaderParamValue(header, "name"); | 699 param_value = GetHeaderParamValue(header, "name"); |
| 691 } | 700 } |
| 692 if (param_value.empty()) | 701 if (param_value.empty()) |
| 693 return std::wstring(); | 702 return std::wstring(); |
| 694 std::string decoded; | 703 std::string decoded; |
| 695 if (DecodeParamValue(param_value, &decoded)) | 704 if (DecodeParamValue(param_value, referrer_charset, &decoded)) |
| 696 return UTF8ToWide(decoded); | 705 return UTF8ToWide(decoded); |
| 697 return std::wstring(); | 706 return std::wstring(); |
| 698 } | 707 } |
| 699 | 708 |
| 700 std::wstring GetHeaderParamValue(const std::wstring& field, | 709 std::wstring GetHeaderParamValue(const std::wstring& field, |
| 701 const std::wstring& param_name) { | 710 const std::wstring& param_name) { |
| 702 return GetHeaderParamValueT(field, param_name); | 711 return GetHeaderParamValueT(field, param_name); |
| 703 } | 712 } |
| 704 | 713 |
| 705 std::string GetHeaderParamValue(const std::string& field, | 714 std::string GetHeaderParamValue(const std::string& field, |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 } | 865 } |
| 857 | 866 |
| 858 std::wstring StripWWW(const std::wstring& text) { | 867 std::wstring StripWWW(const std::wstring& text) { |
| 859 const std::wstring www(L"www."); | 868 const std::wstring www(L"www."); |
| 860 return (text.compare(0, www.length(), www) == 0) ? | 869 return (text.compare(0, www.length(), www) == 0) ? |
| 861 text.substr(www.length()) : text; | 870 text.substr(www.length()) : text; |
| 862 } | 871 } |
| 863 | 872 |
| 864 std::wstring GetSuggestedFilename(const GURL& url, | 873 std::wstring GetSuggestedFilename(const GURL& url, |
| 865 const std::string& content_disposition, | 874 const std::string& content_disposition, |
| 875 const std::string& referrer_charset, |
| 866 const std::wstring& default_name) { | 876 const std::wstring& default_name) { |
| 867 std::wstring filename = GetFileNameFromCD(content_disposition); | 877 std::wstring filename = GetFileNameFromCD(content_disposition, |
| 878 referrer_charset); |
| 868 if (!filename.empty()) { | 879 if (!filename.empty()) { |
| 869 // Remove any path information the server may have sent, take the name | 880 // Remove any path information the server may have sent, take the name |
| 870 // only. | 881 // only. |
| 871 filename = file_util::GetFilenameFromPath(filename); | 882 filename = file_util::GetFilenameFromPath(filename); |
| 872 // Next, remove "." from the beginning and end of the file name to avoid | 883 // Next, remove "." from the beginning and end of the file name to avoid |
| 873 // tricks with hidden files, "..", and "." | 884 // tricks with hidden files, "..", and "." |
| 874 TrimString(filename, L".", &filename); | 885 TrimString(filename, L".", &filename); |
| 875 } | 886 } |
| 876 if (filename.empty()) { | 887 if (filename.empty()) { |
| 877 if (url.is_valid()) { | 888 if (url.is_valid()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 894 // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451) | 905 // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451) |
| 895 filename = url.host().empty() ? L"download" : UTF8ToWide(url.host()); | 906 filename = url.host().empty() ? L"download" : UTF8ToWide(url.host()); |
| 896 } else | 907 } else |
| 897 NOTREACHED(); | 908 NOTREACHED(); |
| 898 } | 909 } |
| 899 | 910 |
| 900 file_util::ReplaceIllegalCharacters(&filename, '-'); | 911 file_util::ReplaceIllegalCharacters(&filename, '-'); |
| 901 return filename; | 912 return filename; |
| 902 } | 913 } |
| 903 | 914 |
| 904 std::wstring GetSuggestedFilename(const GURL& url, | |
| 905 const std::wstring& content_disposition, | |
| 906 const std::wstring& default_name) { | |
| 907 return GetSuggestedFilename( | |
| 908 url, WideToUTF8(content_disposition), default_name); | |
| 909 } | |
| 910 | |
| 911 bool IsPortAllowedByDefault(int port) { | 915 bool IsPortAllowedByDefault(int port) { |
| 912 int array_size = arraysize(kRestrictedPorts); | 916 int array_size = arraysize(kRestrictedPorts); |
| 913 for (int i = 0; i < array_size; i++) { | 917 for (int i = 0; i < array_size; i++) { |
| 914 if (kRestrictedPorts[i] == port) { | 918 if (kRestrictedPorts[i] == port) { |
| 915 return false; | 919 return false; |
| 916 } | 920 } |
| 917 } | 921 } |
| 918 return true; | 922 return true; |
| 919 } | 923 } |
| 920 | 924 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1021 char buffer[256]; | 1025 char buffer[256]; |
| 1022 int result = gethostname(buffer, sizeof(buffer)); | 1026 int result = gethostname(buffer, sizeof(buffer)); |
| 1023 if (result != 0) { | 1027 if (result != 0) { |
| 1024 DLOG(INFO) << "gethostname() failed with " << result; | 1028 DLOG(INFO) << "gethostname() failed with " << result; |
| 1025 buffer[0] = '\0'; | 1029 buffer[0] = '\0'; |
| 1026 } | 1030 } |
| 1027 return std::string(buffer); | 1031 return std::string(buffer); |
| 1028 } | 1032 } |
| 1029 | 1033 |
| 1030 } // namespace net | 1034 } // namespace net |
| OLD | NEW |