xref: /aosp_15_r20/external/cronet/net/base/filename_util_icu.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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