1*6777b538SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/base/filename_util.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/i18n/file_util_icu.h"
12*6777b538SAndroid Build Coastguard Worker #include "build/chromeos_buildflags.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/base/filename_util_internal.h"
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker class GURL;
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker namespace net {
18*6777b538SAndroid Build Coastguard Worker
IsSafePortablePathComponent(const base::FilePath & component)19*6777b538SAndroid Build Coastguard Worker bool IsSafePortablePathComponent(const base::FilePath& component) {
20*6777b538SAndroid Build Coastguard Worker std::u16string component16;
21*6777b538SAndroid Build Coastguard Worker base::FilePath::StringType sanitized = component.value();
22*6777b538SAndroid Build Coastguard Worker SanitizeGeneratedFileName(&sanitized, true);
23*6777b538SAndroid Build Coastguard Worker base::FilePath::StringType extension = component.Extension();
24*6777b538SAndroid Build Coastguard Worker if (!extension.empty())
25*6777b538SAndroid Build Coastguard Worker extension.erase(extension.begin()); // Erase preceding '.'.
26*6777b538SAndroid Build Coastguard Worker return !component.empty() && (component == component.BaseName()) &&
27*6777b538SAndroid Build Coastguard Worker (component == component.StripTrailingSeparators()) &&
28*6777b538SAndroid Build Coastguard Worker FilePathToString16(component, &component16) &&
29*6777b538SAndroid Build Coastguard Worker base::i18n::IsFilenameLegal(component16) &&
30*6777b538SAndroid Build Coastguard Worker !IsShellIntegratedExtension(extension) &&
31*6777b538SAndroid Build Coastguard Worker (sanitized == component.value()) &&
32*6777b538SAndroid Build Coastguard Worker !IsReservedNameOnWindows(component.value());
33*6777b538SAndroid Build Coastguard Worker }
34*6777b538SAndroid Build Coastguard Worker
IsSafePortableRelativePath(const base::FilePath & path)35*6777b538SAndroid Build Coastguard Worker bool IsSafePortableRelativePath(const base::FilePath& path) {
36*6777b538SAndroid Build Coastguard Worker if (path.empty() || path.IsAbsolute() || path.EndsWithSeparator())
37*6777b538SAndroid Build Coastguard Worker return false;
38*6777b538SAndroid Build Coastguard Worker std::vector<base::FilePath::StringType> components = path.GetComponents();
39*6777b538SAndroid Build Coastguard Worker if (components.empty())
40*6777b538SAndroid Build Coastguard Worker return false;
41*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < components.size() - 1; ++i) {
42*6777b538SAndroid Build Coastguard Worker if (!IsSafePortablePathComponent(base::FilePath(components[i])))
43*6777b538SAndroid Build Coastguard Worker return false;
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker return IsSafePortablePathComponent(path.BaseName());
46*6777b538SAndroid Build Coastguard Worker }
47*6777b538SAndroid Build Coastguard Worker
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 std::string & default_name)48*6777b538SAndroid Build Coastguard Worker std::u16string GetSuggestedFilename(const GURL& url,
49*6777b538SAndroid Build Coastguard Worker const std::string& content_disposition,
50*6777b538SAndroid Build Coastguard Worker const std::string& referrer_charset,
51*6777b538SAndroid Build Coastguard Worker const std::string& suggested_name,
52*6777b538SAndroid Build Coastguard Worker const std::string& mime_type,
53*6777b538SAndroid Build Coastguard Worker const std::string& default_name) {
54*6777b538SAndroid Build Coastguard Worker return GetSuggestedFilenameImpl(url, content_disposition, referrer_charset,
55*6777b538SAndroid Build Coastguard Worker suggested_name, mime_type, default_name,
56*6777b538SAndroid Build Coastguard Worker false, /* should_replace_extension */
57*6777b538SAndroid Build Coastguard Worker &base::i18n::ReplaceIllegalCharactersInPath);
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker
GenerateFileName(const GURL & url,const std::string & content_disposition,const std::string & referrer_charset,const std::string & suggested_name,const std::string & mime_type,const std::string & default_file_name)60*6777b538SAndroid Build Coastguard Worker base::FilePath GenerateFileName(const GURL& url,
61*6777b538SAndroid Build Coastguard Worker const std::string& content_disposition,
62*6777b538SAndroid Build Coastguard Worker const std::string& referrer_charset,
63*6777b538SAndroid Build Coastguard Worker const std::string& suggested_name,
64*6777b538SAndroid Build Coastguard Worker const std::string& mime_type,
65*6777b538SAndroid Build Coastguard Worker const std::string& default_file_name) {
66*6777b538SAndroid Build Coastguard Worker return GenerateFileName(url, content_disposition, referrer_charset,
67*6777b538SAndroid Build Coastguard Worker suggested_name, mime_type, default_file_name,
68*6777b538SAndroid Build Coastguard Worker false /* should_replace_extension */);
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker
GenerateFileName(const GURL & url,const std::string & content_disposition,const std::string & referrer_charset,const std::string & suggested_name,const std::string & mime_type,const std::string & default_file_name,bool should_replace_extension)71*6777b538SAndroid Build Coastguard Worker base::FilePath GenerateFileName(const GURL& url,
72*6777b538SAndroid Build Coastguard Worker const std::string& content_disposition,
73*6777b538SAndroid Build Coastguard Worker const std::string& referrer_charset,
74*6777b538SAndroid Build Coastguard Worker const std::string& suggested_name,
75*6777b538SAndroid Build Coastguard Worker const std::string& mime_type,
76*6777b538SAndroid Build Coastguard Worker const std::string& default_file_name,
77*6777b538SAndroid Build Coastguard Worker bool should_replace_extension) {
78*6777b538SAndroid Build Coastguard Worker base::FilePath generated_name(GenerateFileNameImpl(
79*6777b538SAndroid Build Coastguard Worker url, content_disposition, referrer_charset, suggested_name, mime_type,
80*6777b538SAndroid Build Coastguard Worker default_file_name, should_replace_extension,
81*6777b538SAndroid Build Coastguard Worker &base::i18n::ReplaceIllegalCharactersInPath));
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS_ASH)
84*6777b538SAndroid Build Coastguard Worker // When doing file manager operations on ChromeOS, the file paths get
85*6777b538SAndroid Build Coastguard Worker // normalized in WebKit layer, so let's ensure downloaded files have
86*6777b538SAndroid Build Coastguard Worker // normalized names. Otherwise, we won't be able to handle files with NFD
87*6777b538SAndroid Build Coastguard Worker // utf8 encoded characters in name.
88*6777b538SAndroid Build Coastguard Worker base::i18n::NormalizeFileNameEncoding(&generated_name);
89*6777b538SAndroid Build Coastguard Worker #endif
90*6777b538SAndroid Build Coastguard Worker
91*6777b538SAndroid Build Coastguard Worker DCHECK(!generated_name.empty());
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker return generated_name;
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker } // namespace net
97