Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(858)

Unified Diff: net/base/net_util.cc

Issue 7607013: Call GenerateSafeFilename() from GetSuggestedFilename(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/net_util.h ('k') | net/base/net_util_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/net_util.cc
diff --git a/net/base/net_util.cc b/net/base/net_util.cc
index ef8eb534d12792c4ae76978f1425470acce9cd00..0be8daa9932f5bdda87cb0dd4de2406a5ce2a771 100644
--- a/net/base/net_util.cc
+++ b/net/base/net_util.cc
@@ -922,6 +922,52 @@ char* do_strdup(const char* src) {
#endif
}
+void SanitizeGeneratedFileName(std::string& filename) {
+ if (!filename.empty()) {
+ // Remove "." from the beginning and end of the file name to avoid tricks
+ // with hidden files, "..", and "."
+ TrimString(filename, ".", &filename);
+#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);
+#endif
+ // Replace any path information by changing path separators with
+ // underscores.
+ ReplaceSubstringsAfterOffset(&filename, 0, "/", "_");
+ ReplaceSubstringsAfterOffset(&filename, 0, "\\", "_");
+ }
+}
+
+std::string GetFileNameFromURL(const GURL& url,
+ const std::string& referrer_charset) {
+ // about: and data: URLs don't have file names, but esp. data: URLs may
+ // contain parts that look like ones (i.e., contain a slash). Therefore we
+ // don't attempt to divine a file name out of them.
+ if (!url.is_valid() || url.SchemeIs("about") || url.SchemeIs("data"))
+ return std::string();
+
+ const std::string unescaped_url_filename = UnescapeURLComponent(
+ url.ExtractFileName(),
+ UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
+
+ // The URL's path should be escaped UTF-8, but may not be.
+ std::string decoded_filename = unescaped_url_filename;
+ if (!IsStringASCII(decoded_filename)) {
+ bool ignore;
+ // TODO(jshin): this is probably not robust enough. To be sure, we need
+ // encoding detection.
+ DecodeWord(unescaped_url_filename, referrer_charset, &ignore,
+ &decoded_filename);
+ }
+
+ return decoded_filename;
+}
+
#if defined(OS_WIN)
// Returns whether the specified extension is automatically integrated into the
// windows shell.
@@ -1379,99 +1425,57 @@ string16 GetSuggestedFilename(const GURL& url,
const std::string& content_disposition,
const std::string& referrer_charset,
const std::string& suggested_name,
+ const std::string& mime_type,
const string16& default_name) {
// TODO: this function to be updated to match the httpbis recommendations.
// Talk to abarth for the latest news.
// We don't translate this fallback string, "download". If localization is
- // needed, the caller should provide localized fallback default_name.
+ // needed, the caller should provide localized fallback in |default_name|.
static const char* kFinalFallbackName = "download";
+ std::string filename; // In UTF-8
- std::string filename;
-
- // Try to extract from content-disposition first.
+ // Try to extract a filename from content-disposition first.
if (!content_disposition.empty())
filename = GetFileNameFromCD(content_disposition, referrer_charset);
- // Then try to use suggested name.
+ // Then try to use the suggested name.
if (filename.empty() && !suggested_name.empty())
filename = suggested_name;
- if (!filename.empty()) {
- // Replace any path information the server may have sent, by changing
- // path separators with underscores.
- ReplaceSubstringsAfterOffset(&filename, 0, "/", "_");
- ReplaceSubstringsAfterOffset(&filename, 0, "\\", "_");
-
- // Next, remove "." from the beginning and end of the file name to avoid
- // tricks with hidden files, "..", and "."
- TrimString(filename, ".", &filename);
- }
-
- if (filename.empty()) {
- // about: and data: URLs don't have file names, but esp. data: URLs may
- // contain parts that look like ones (i.e., contain a slash).
- // Therefore we don't attempt to divine a file name out of them.
- if (url.SchemeIs("about") || url.SchemeIs("data")) {
- return default_name.empty() ? ASCIIToUTF16(kFinalFallbackName)
- : default_name;
- }
-
- if (url.is_valid()) {
- const std::string unescaped_url_filename = UnescapeURLComponent(
- url.ExtractFileName(),
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
-
- // The URL's path should be escaped UTF-8, but may not be.
- std::string decoded_filename = unescaped_url_filename;
- if (!IsStringASCII(decoded_filename)) {
- bool ignore;
- // TODO(jshin): this is probably not robust enough. To be sure, we
- // need encoding detection.
- DecodeWord(unescaped_url_filename, referrer_charset, &ignore,
- &decoded_filename);
- }
+ // Now try extracting the filename from the URL. GetFileNameFromURL() only
+ // looks at the last component of the URL and doesn't return the hostname as a
+ // failover.
+ if (filename.empty())
+ filename = GetFileNameFromURL(url, referrer_charset);
- filename = decoded_filename;
- }
+ // Finally try the URL hostname, but only if there's no default specified in
+ // |default_name|. Some schemes (e.g.: file:, about:, data:) do not have a
+ // host name.
+ if (filename.empty() && default_name.empty() &&
+ url.is_valid() && !url.host().empty()) {
+ // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451)
+ filename = url.host();
}
-#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);
- }
-#endif
- // Trim '.' once more.
- TrimString(filename, ".", &filename);
-
- // If there's no filename or it gets trimed to be empty, use
- // the URL hostname or default_name
- if (filename.empty()) {
- if (!default_name.empty()) {
- return default_name;
- } else if (url.is_valid()) {
- // Some schemes (e.g. file) do not have a hostname. Even though it's
- // not likely to reach here, let's hardcode the last fallback name.
- // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451)
- filename = url.host().empty() ? kFinalFallbackName : url.host();
- } else {
- NOTREACHED();
- }
- }
+ SanitizeGeneratedFileName(filename);
+ // Sanitization can cause the filename to disappear (e.g.: if the filename
+ // consisted entirely of spaces and '.'s), in which case we use the default.
+ if (filename.empty() && default_name.empty())
+ filename = kFinalFallbackName;
#if defined(OS_WIN)
- string16 path = UTF8ToUTF16(filename);
+ string16 path = (filename.empty())? default_name : UTF8ToUTF16(filename);
file_util::ReplaceIllegalCharactersInPath(&path, '-');
- return path;
+ FilePath result(path);
+ GenerateSafeFileName(mime_type, &result);
+ return result.value();
#else
- std::string path = filename;
+ std::string path = (filename.empty())? UTF16ToUTF8(default_name) : filename;
file_util::ReplaceIllegalCharactersInPath(&path, '-');
- return UTF8ToUTF16(path);
+ FilePath result(path);
+ GenerateSafeFileName(mime_type, &result);
+ return UTF8ToUTF16(result.value());
#endif
}
@@ -1481,26 +1485,20 @@ FilePath GenerateFileName(const GURL& url,
const std::string& suggested_name,
const std::string& mime_type,
const string16& default_file_name) {
- string16 new_name = GetSuggestedFilename(GURL(url),
- content_disposition,
- referrer_charset,
- suggested_name,
- default_file_name);
-
- // TODO(evan): this code is totally wrong -- we should just generate
- // Unicode filenames and do all this encoding switching at the end.
- // However, I'm just shuffling wrong code around, at least not adding
- // to it.
+ string16 file_name = GetSuggestedFilename(url,
+ content_disposition,
+ referrer_charset,
+ suggested_name,
+ mime_type,
+ default_file_name);
+
#if defined(OS_WIN)
- FilePath generated_name = FilePath(new_name);
+ FilePath generated_name(file_name);
#else
- FilePath generated_name = FilePath(
- base::SysWideToNativeMB(UTF16ToWide(new_name)));
+ FilePath generated_name(base::SysWideToNativeMB(UTF16ToWide(file_name)));
#endif
-
DCHECK(!generated_name.empty());
- GenerateSafeFileName(mime_type, &generated_name);
return generated_name;
}
« no previous file with comments | « net/base/net_util.h ('k') | net/base/net_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698