Index: net/base/net_util.cc |
=================================================================== |
--- net/base/net_util.cc (revision 16437) |
+++ net/base/net_util.cc (working copy) |
@@ -655,6 +655,15 @@ |
namespace net { |
+// Appends the substring |in_component| inside of the URL |spec| to |output|, |
+// and the resulting range will be filled into |out_component|. Calls the |
+// unescaper for the substring if |unescape| is true. |
+static void AppendFormattedComponent(const std::string& spec, |
+ const url_parse::Component& in_component, |
+ bool unescape, |
+ std::wstring* output, |
+ url_parse::Component* out_component); |
+ |
GURL FilePathToFileURL(const FilePath& path) { |
// Produce a URL like "file:///C:/foo" for a regular file, or |
// "file://///server/path" for UNC. The URL canonicalizer will fix up the |
@@ -1031,4 +1040,139 @@ |
return std::string(buffer); |
} |
+void AppendFormattedHost(const GURL& url, |
+ const std::wstring& languages, |
+ std::wstring* output, |
+ url_parse::Parsed* new_parsed) { |
+ const url_parse::Component& host = |
+ url.parsed_for_possibly_invalid_spec().host; |
+ |
+ if (host.is_nonempty()) { |
+ // Handle possible IDN in the host name. |
+ if (new_parsed) |
+ new_parsed->host.begin = static_cast<int>(output->length()); |
+ |
+ const std::string& spec = url.possibly_invalid_spec(); |
+ DCHECK(host.begin >= 0 && |
+ ((spec.length() == 0 && host.begin == 0) || |
+ host.begin < static_cast<int>(spec.length()))); |
+ net::IDNToUnicode(&spec[host.begin], host.len, languages, output); |
+ |
+ if (new_parsed) { |
+ new_parsed->host.len = |
+ static_cast<int>(output->length()) - new_parsed->host.begin; |
+ } |
+ } else if (new_parsed) { |
+ new_parsed->host.reset(); |
+ } |
+} |
+ |
+/* static */ |
+void AppendFormattedComponent(const std::string& spec, |
+ const url_parse::Component& in_component, |
+ bool unescape, |
+ std::wstring* output, |
+ url_parse::Component* out_component) { |
+ if (in_component.is_nonempty()) { |
+ out_component->begin = static_cast<int>(output->length()); |
+ if (unescape) { |
+ output->append(UnescapeAndDecodeUTF8URLComponent( |
+ spec.substr(in_component.begin, in_component.len), |
+ UnescapeRule::NORMAL)); |
+ } else { |
+ output->append(UTF8ToWide(spec.substr( |
+ in_component.begin, in_component.len))); |
+ } |
+ out_component->len = |
+ static_cast<int>(output->length()) - out_component->begin; |
+ } else { |
+ out_component->reset(); |
+ } |
+} |
+ |
+std::wstring FormatUrl( |
+ const GURL& url, const std::wstring& languages, bool omit_username_password, |
+ bool unescape, url_parse::Parsed* new_parsed, size_t* prefix_end) { |
+ url_parse::Parsed parsed_temp; |
+ if (!new_parsed) |
+ new_parsed = &parsed_temp; |
+ |
+ std::wstring url_string; |
+ |
+ // Check for empty URLs or 0 available text width. |
+ if (url.is_empty()) { |
+ if (prefix_end) |
+ *prefix_end = 0; |
+ return url_string; |
+ } |
+ |
+ // We handle both valid and invalid URLs (this will give us the spec |
+ // regardless of validity). |
+ const std::string& spec = url.possibly_invalid_spec(); |
+ const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec(); |
+ |
+ // Copy everything before the username (the scheme and the separators.) |
+ // These are ASCII. |
+ int pre_end = parsed.CountCharactersBefore(url_parse::Parsed::USERNAME, true); |
+ for (int i = 0; i < pre_end; ++i) |
+ url_string.push_back(spec[i]); |
+ new_parsed->scheme = parsed.scheme; |
+ |
+ if (omit_username_password) { |
+ // Remove the username and password fields. We don't want to display those |
+ // to the user since they can be used for attacks, |
+ // e.g. "http://google.com:search@evil.ru/" |
+ new_parsed->username.reset(); |
+ new_parsed->password.reset(); |
+ } else { |
+ AppendFormattedComponent( |
+ spec, parsed.username, unescape, &url_string, &new_parsed->username); |
+ if (parsed.password.is_valid()) { |
+ url_string.push_back(':'); |
+ } |
+ AppendFormattedComponent( |
+ spec, parsed.password, unescape, &url_string, &new_parsed->password); |
+ if (parsed.username.is_valid() || parsed.password.is_valid()) { |
+ url_string.push_back('@'); |
+ } |
+ } |
+ if (prefix_end) |
+ *prefix_end = static_cast<size_t>(url_string.length()); |
+ |
+ AppendFormattedHost(url, languages, &url_string, new_parsed); |
+ |
+ // Port. |
+ if (parsed.port.is_nonempty()) { |
+ url_string.push_back(':'); |
+ int begin = url_string.length(); |
+ for (int i = parsed.port.begin; i < parsed.port.end(); ++i) |
+ url_string.push_back(spec[i]); |
+ new_parsed->port.begin = begin; |
+ new_parsed->port.len = url_string.length() - begin; |
+ } else { |
+ new_parsed->port.reset(); |
+ } |
+ |
+ // Path and query both get the same general unescape & convert treatment. |
+ AppendFormattedComponent( |
+ spec, parsed.path, unescape, &url_string, &new_parsed->path); |
+ if (parsed.query.is_valid()) |
+ url_string.push_back('?'); |
+ AppendFormattedComponent( |
+ spec, parsed.query, unescape, &url_string, &new_parsed->query); |
+ |
+ // Reference is stored in valid, unescaped UTF-8, so we can just convert. |
+ if (parsed.ref.is_valid()) { |
+ url_string.push_back('#'); |
+ int begin = url_string.length(); |
+ if (parsed.ref.len > 0) |
+ url_string.append(UTF8ToWide(std::string(&spec[parsed.ref.begin], |
+ parsed.ref.len))); |
+ new_parsed->ref.begin = begin; |
+ new_parsed->ref.len = url_string.length() - begin; |
+ } |
+ |
+ return url_string; |
+} |
+ |
} // namespace net |