Index: net/base/net_util.cc |
=================================================================== |
--- net/base/net_util.cc (revision 64006) |
+++ net/base/net_util.cc (working copy) |
@@ -369,9 +369,7 @@ |
// it should be Ok because we're not an email client but a |
// web browser. |
- // What IE6/7 does: %-escaped UTF-8. We could extend this to |
- // support a rudimentary form of RFC 2231 with charset label, but |
- // it'd gain us little in terms of compatibility. |
+ // What IE6/7 does: %-escaped UTF-8. |
tmp = UnescapeURLComponent(encoded_word, UnescapeRule::SPACES); |
if (IsStringUTF8(tmp)) { |
output->swap(tmp); |
@@ -420,7 +418,8 @@ |
// TODO(mpcomplete): This is a quick and dirty implementation for now. I'm |
// sure this doesn't properly handle all (most?) cases. |
template<typename STR> |
-STR GetHeaderParamValueT(const STR& header, const STR& param_name) { |
+STR GetHeaderParamValueT(const STR& header, const STR& param_name, |
+ QuoteRule::Type quote_rule) { |
// This assumes args are formatted exactly like "bla; arg1=value; arg2=value". |
typename STR::const_iterator param_begin = |
search(header.begin(), header.end(), param_name.begin(), param_name.end(), |
@@ -443,7 +442,7 @@ |
return STR(); |
typename STR::const_iterator param_end; |
- if (*param_begin == '"') { |
+ if (*param_begin == '"' && quote_rule == QuoteRule::REMOVE_OUTER_QUOTES) { |
param_end = find(param_begin+1, header.end(), '"'); |
if (param_end == header.end()) |
return STR(); // poorly formatted param? |
@@ -1091,29 +1090,86 @@ |
return GetSpecificHeaderT(headers, name); |
} |
+bool DecodeCharset(const std::string& input, |
+ std::string* decoded_charset, |
+ std::string* value) { |
+ StringTokenizer t(input, "'"); |
+ t.set_options(StringTokenizer::RETURN_DELIMS); |
+ std::string temp_charset; |
+ std::string temp_value; |
+ int numDelimsSeen = 0; |
+ while (t.GetNext()) { |
+ if (t.token_is_delim()) { |
+ ++numDelimsSeen; |
+ continue; |
+ } else { |
+ switch (numDelimsSeen) { |
+ case 0: |
+ temp_charset = t.token(); |
+ break; |
+ case 1: |
+ // Language is ignored. |
+ break; |
+ case 2: |
+ temp_value = t.token(); |
+ break; |
+ default: |
+ return false; |
+ } |
+ } |
+ } |
+ if (numDelimsSeen != 2) |
+ return false; |
+ if (temp_charset.empty() || temp_value.empty()) |
+ return false; |
+ decoded_charset->swap(temp_charset); |
+ value->swap(temp_value); |
+ return true; |
+} |
+ |
std::string GetFileNameFromCD(const std::string& header, |
const std::string& referrer_charset) { |
- std::string param_value = GetHeaderParamValue(header, "filename"); |
+ std::string decoded; |
+ std::string param_value = GetHeaderParamValue(header, "filename*", |
+ QuoteRule::KEEP_OUTER_QUOTES); |
+ if (!param_value.empty()) { |
+ if (param_value.find('"') == std::string::npos) { |
+ std::string charset; |
+ std::string value; |
+ if (DecodeCharset(param_value, &charset, &value)) { |
+ // RFC 5987 value should be ASCII-only. |
+ if (!IsStringASCII(value)) |
+ return std::string(); |
+ std::string tmp = UnescapeURLComponent(value, UnescapeRule::SPACES); |
+ if (base::ConvertToUtf8AndNormalize(tmp, charset, &decoded)) |
+ return decoded; |
+ } |
+ } |
+ } |
+ param_value = GetHeaderParamValue(header, "filename", |
+ QuoteRule::REMOVE_OUTER_QUOTES); |
if (param_value.empty()) { |
// Some servers use 'name' parameter. |
- param_value = GetHeaderParamValue(header, "name"); |
+ param_value = GetHeaderParamValue(header, "name", |
+ QuoteRule::REMOVE_OUTER_QUOTES); |
} |
if (param_value.empty()) |
return std::string(); |
- std::string decoded; |
if (DecodeParamValue(param_value, referrer_charset, &decoded)) |
return decoded; |
return std::string(); |
} |
std::wstring GetHeaderParamValue(const std::wstring& field, |
- const std::wstring& param_name) { |
- return GetHeaderParamValueT(field, param_name); |
+ const std::wstring& param_name, |
+ QuoteRule::Type quote_rule) { |
+ return GetHeaderParamValueT(field, param_name, quote_rule); |
} |
std::string GetHeaderParamValue(const std::string& field, |
- const std::string& param_name) { |
- return GetHeaderParamValueT(field, param_name); |
+ const std::string& param_name, |
+ QuoteRule::Type quote_rule) { |
+ return GetHeaderParamValueT(field, param_name, quote_rule); |
} |
// TODO(brettw) bug 734373: check the scripts for each host component and |