Chromium Code Reviews| Index: net/base/net_util.cc |
| diff --git a/net/base/net_util.cc b/net/base/net_util.cc |
| index ef8eb534d12792c4ae76978f1425470acce9cd00..5918b5db55f23807e241705e133fe4f6e60c7b37 100644 |
| --- a/net/base/net_util.cc |
| +++ b/net/base/net_util.cc |
| @@ -158,6 +158,103 @@ static const int kAllowedFtpPorts[] = { |
| 22, // ssh |
| }; |
| +// This list should generally match the one in string_util.cc |
| +const char16 kWhitespaceUTF16[] = { |
|
jschuh
2011/08/17 14:38:46
Seems like we should add missed whitespace charact
|
| + 0x0009, /* <control-0009> to <control-000D> */ \ |
| + 0x000A, \ |
| + 0x000B, \ |
| + 0x000C, \ |
| + 0x000D, \ |
| + 0x0020, /* Space */ \ |
| + 0x0085, /* <control-0085> */ \ |
| + 0x00A0, /* No-Break Space */ \ |
| + 0x1680, /* Ogham Space Mark */ \ |
| + 0x180E, /* Mongolian Vowel Separator */ \ |
| + 0x2000, /* En Quad to Hair Space */ \ |
| + 0x2001, \ |
| + 0x2002, \ |
| + 0x2003, \ |
| + 0x2004, \ |
| + 0x2005, \ |
| + 0x2006, \ |
| + 0x2007, \ |
| + 0x2008, \ |
| + 0x2009, \ |
| + 0x200A, \ |
| + 0x200C, /* Zero Width Non-Joiner */ \ |
| + 0x2028, /* Line Separator */ \ |
| + 0x2029, /* Paragraph Separator */ \ |
| + 0x202F, /* Narrow No-Break Space */ \ |
| + 0x205F, /* Medium Mathematical Space */ \ |
| + 0x3000, /* Ideographic Space */ \ |
| + 0 |
| +}; |
| + |
| +static const char* const kHexString = "0123456789ABCDEF"; |
| +inline char IntToHex(int i) { |
| + return kHexString[i & 0xf]; |
| +} |
| + |
| +std::string EscapeCharsInString(const std::string& input) { |
| + std::string escaped_string; |
| + |
| + escaped_string.reserve(input.length() * 3); |
| + for (unsigned int i = 0; i < input.length(); i++) { |
| + unsigned char c = static_cast<unsigned char>(input[i]); |
| + escaped_string.push_back('%'); |
| + escaped_string.push_back(IntToHex(c >> 4)); |
| + escaped_string.push_back(IntToHex(c & 0xf)); |
| + } |
| + return escaped_string; |
| +} |
| + |
| +string16 EscapeCharsInString(const string16& input) { |
| + string16 escaped_string; |
| + |
| + escaped_string.reserve(input.length() * 6); |
| + for (unsigned int i = 0; i < input.length(); i++) { |
| + char16 c = static_cast<char16>(input[i]); |
| + escaped_string.push_back('%'); |
| + escaped_string.push_back('u'); |
| + escaped_string.push_back(IntToHex(c >> 12)); |
| + escaped_string.push_back(IntToHex((c >> 8) & 0xf)); |
| + escaped_string.push_back(IntToHex((c >> 4) & 0xf)); |
| + escaped_string.push_back(IntToHex(c & 0xf)); |
| + } |
| + return escaped_string; |
| +} |
| + |
| +template<typename STR> |
| +void EscapeTrimChars(const STR& input, |
| + const typename STR::value_type escape_chars[], |
| + TrimPositions positions, |
| + STR* output) { |
| + // Find the edges of leading/trailing whitespace as desired. |
| + const typename STR::size_type last_char = input.length() - 1; |
| + const typename STR::size_type first_good_char = (positions & TRIM_LEADING) ? |
| + input.find_first_not_of(escape_chars) : 0; |
| + const typename STR::size_type last_good_char = (positions & TRIM_TRAILING) ? |
| + input.find_last_not_of(escape_chars) : last_char; |
| + STR temp_string; |
| + |
| + if (input.empty()) |
| + return; |
| + |
| + if ((first_good_char == STR::npos) || (last_good_char == STR::npos)) { |
| + // Escapery magic on whole string |
| + return; |
| + } |
| + |
| + temp_string = EscapeCharsInString(input.substr(0,first_good_char)); |
| + temp_string += input.substr(first_good_char, last_good_char - |
| + first_good_char + 1); |
| + if (last_good_char < last_char) |
| + temp_string += EscapeCharsInString(input.substr(last_good_char+1)); |
| + *output = temp_string; |
| + |
| + return; |
| +} |
| + |
| // Similar to Base64Decode. Decodes a Q-encoded string to a sequence |
| // of bytes. If input is invalid, return false. |
| bool QPDecode(const std::string& input, std::string* output) { |
| @@ -1405,7 +1502,11 @@ string16 GetSuggestedFilename(const GURL& url, |
| // Next, remove "." from the beginning and end of the file name to avoid |
| // tricks with hidden files, "..", and "." |
| +#if defined(OS_WIN) |
| + EscapeTrimChars(filename, ".", TRIM_ALL, &filename); |
| +#else |
| TrimString(filename, ".", &filename); |
| +#endif |
| } |
| if (filename.empty()) { |
| @@ -1439,11 +1540,7 @@ string16 GetSuggestedFilename(const GURL& url, |
| #if defined(OS_WIN) |
| { // Handle CreateFile() stripping trailing dots and spaces on filenames |
| // http://support.microsoft.com/kb/115827 |
| - std::string::size_type pos = filename.find_last_not_of(" ."); |
| - if (pos == std::string::npos) |
| - filename.resize(0); |
| - else |
| - filename.resize(++pos); |
| + EscapeTrimChars(filename, " .", TRIM_TRAILING, &filename); |
| } |
| #endif |
| // Trim '.' once more. |
| @@ -1466,6 +1563,11 @@ string16 GetSuggestedFilename(const GURL& url, |
| #if defined(OS_WIN) |
| string16 path = UTF8ToUTF16(filename); |
| + // On Windows we want to preserve or replace all characters including |
| + // whitespace to prevent file extension obfuscation on trusted websites |
| + // e.g. Gmail might think evil.exe. is safe, so we don't want it to become |
| + // evil.exe when we download it |
| + EscapeTrimChars(path, kWhitespaceUTF16, TRIM_ALL, &path); |
| file_util::ReplaceIllegalCharactersInPath(&path, '-'); |
| return path; |
| #else |