10de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
20de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
30de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// found in the LICENSE file.
40de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
50de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "net/base/filename_util.h"
60de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
70de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "base/bind.h"
80de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "base/files/file_path.h"
90de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "base/i18n/file_util_icu.h"
100de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "base/strings/string16.h"
110de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "net/base/filename_util_internal.h"
120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)class GURL;
140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)namespace net {
160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)bool IsSafePortablePathComponent(const base::FilePath& component) {
180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  base::string16 component16;
190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  base::FilePath::StringType sanitized = component.value();
200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  SanitizeGeneratedFileName(&sanitized, true);
210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  base::FilePath::StringType extension = component.Extension();
220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!extension.empty())
230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    extension.erase(extension.begin());  // Erase preceding '.'.
240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  return !component.empty() && (component == component.BaseName()) &&
250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)         (component == component.StripTrailingSeparators()) &&
260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)         FilePathToString16(component, &component16) &&
270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)         file_util::IsFilenameLegal(component16) &&
280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)         !IsShellIntegratedExtension(extension) &&
290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)         (sanitized == component.value()) && !IsReservedName(component.value());
300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)bool IsSafePortableRelativePath(const base::FilePath& path) {
330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (path.empty() || path.IsAbsolute() || path.EndsWithSeparator())
340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    return false;
350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  std::vector<base::FilePath::StringType> components;
360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  path.GetComponents(&components);
370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (components.empty())
380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    return false;
390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  for (size_t i = 0; i < components.size() - 1; ++i) {
400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    if (!IsSafePortablePathComponent(base::FilePath(components[i])))
410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      return false;
420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  return IsSafePortablePathComponent(path.BaseName());
440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)base::string16 GetSuggestedFilename(const GURL& url,
470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                    const std::string& content_disposition,
480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                    const std::string& referrer_charset,
490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                    const std::string& suggested_name,
500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                    const std::string& mime_type,
510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                    const std::string& default_name) {
520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  return GetSuggestedFilenameImpl(
530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      url,
540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      content_disposition,
550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      referrer_charset,
560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      suggested_name,
570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      mime_type,
580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      default_name,
590de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      base::Bind(&file_util::ReplaceIllegalCharactersInPath));
600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)base::FilePath GenerateFileName(const GURL& url,
630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                const std::string& content_disposition,
640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                const std::string& referrer_charset,
650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                const std::string& suggested_name,
660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                const std::string& mime_type,
670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                                const std::string& default_file_name) {
680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  base::FilePath generated_name(GenerateFileNameImpl(
690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      url,
700de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      content_disposition,
710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      referrer_charset,
720de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      suggested_name,
730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      mime_type,
740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      default_file_name,
750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      base::Bind(&file_util::ReplaceIllegalCharactersInPath)));
760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#if defined(OS_CHROMEOS)
780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // When doing file manager operations on ChromeOS, the file paths get
790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // normalized in WebKit layer, so let's ensure downloaded files have
800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // normalized names. Otherwise, we won't be able to handle files with NFD
810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // utf8 encoded characters in name.
820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  file_util::NormalizeFileNameEncoding(&generated_name);
830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#endif
840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(!generated_name.empty());
860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  return generated_name;
880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}  // namespace net
91