// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/common/file_util.h"

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_file_value_serializer.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_icon_set.h"
#include "extensions/common/extension_l10n_util.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/image_util.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handler.h"
#include "extensions/common/manifest_handlers/default_locale_handler.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/strings/grit/extensions_strings.h"
#include "net/base/escape.h"
#include "net/base/filename_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

namespace extensions {
namespace file_util {
namespace {

enum SafeInstallationFlag {
  DEFAULT,   // Default case, controlled by a field trial.
  DISABLED,  // Safe installation is disabled.
  ENABLED,   // Safe installation is enabled.
};
SafeInstallationFlag g_use_safe_installation = DEFAULT;

bool g_report_error_for_invisible_icon = false;

// Returns true if the given file path exists and is not zero-length.
bool ValidateFilePath(const base::FilePath& path) {
  int64_t size = 0;
  return base::PathExists(path) && base::GetFileSize(path, &size) && size != 0;
}

// Returns true if the extension installation should flush all files and the
// directory.
bool UseSafeInstallation() {
  if (g_use_safe_installation == DEFAULT) {
    const char kFieldTrialName[] = "ExtensionUseSafeInstallation";
    const char kEnable[] = "Enable";
    return base::FieldTrialList::FindFullName(kFieldTrialName) == kEnable;
  }

  return g_use_safe_installation == ENABLED;
}

enum FlushOneOrAllFiles {
   ONE_FILE_ONLY,
   ALL_FILES
};

// Flush all files in a directory or just one.  When flushing all files, it
// makes sure every file is on disk.  When flushing one file only, it ensures
// all parent directories are on disk.
void FlushFilesInDir(const base::FilePath& path,
                     FlushOneOrAllFiles one_or_all_files) {
  if (!UseSafeInstallation()) {
    return;
  }
  base::FileEnumerator temp_traversal(path,
                                      true,  // recursive
                                      base::FileEnumerator::FILES);
  for (base::FilePath current = temp_traversal.Next(); !current.empty();
      current = temp_traversal.Next()) {
    base::File currentFile(current,
                           base::File::FLAG_OPEN | base::File::FLAG_WRITE);
    currentFile.Flush();
    currentFile.Close();
    if (one_or_all_files == ONE_FILE_ONLY) {
      break;
    }
  }
}

}  // namespace

const base::FilePath::CharType kTempDirectoryName[] = FILE_PATH_LITERAL("Temp");

void SetUseSafeInstallation(bool use_safe_installation) {
  g_use_safe_installation = use_safe_installation ? ENABLED : DISABLED;
}

base::FilePath InstallExtension(const base::FilePath& unpacked_source_dir,
                                const std::string& id,
                                const std::string& version,
                                const base::FilePath& extensions_dir) {
  base::FilePath extension_dir = extensions_dir.AppendASCII(id);
  base::FilePath version_dir;

  // Create the extension directory if it doesn't exist already.
  if (!base::PathExists(extension_dir)) {
    if (!base::CreateDirectory(extension_dir))
      return base::FilePath();
  }

  // Get a temp directory on the same file system as the profile.
  base::FilePath install_temp_dir = GetInstallTempDir(extensions_dir);
  base::ScopedTempDir extension_temp_dir;
  if (install_temp_dir.empty() ||
      !extension_temp_dir.CreateUniqueTempDirUnderPath(install_temp_dir)) {
    LOG(ERROR) << "Creating of temp dir under in the profile failed.";
    return base::FilePath();
  }
  base::FilePath crx_temp_source =
      extension_temp_dir.GetPath().Append(unpacked_source_dir.BaseName());
  if (!base::Move(unpacked_source_dir, crx_temp_source)) {
    LOG(ERROR) << "Moving extension from : " << unpacked_source_dir.value()
               << " to : " << crx_temp_source.value() << " failed.";
    return base::FilePath();
  }

  // Try to find a free directory. There can be legitimate conflicts in the case
  // of overinstallation of the same version.
  const int kMaxAttempts = 100;
  for (int i = 0; i < kMaxAttempts; ++i) {
    base::FilePath candidate = extension_dir.AppendASCII(
        base::StringPrintf("%s_%u", version.c_str(), i));
    if (!base::PathExists(candidate)) {
      version_dir = candidate;
      break;
    }
  }

  if (version_dir.empty()) {
    LOG(ERROR) << "Could not find a home for extension " << id << " with "
               << "version " << version << ".";
    return base::FilePath();
  }

  // Flush the source dir completely before moving to make sure everything is
  // on disk. Otherwise a sudden power loss could cause the newly installed
  // extension to be in a corrupted state. Note that empty sub-directories
  // may still be lost.
  FlushFilesInDir(crx_temp_source, ALL_FILES);

  // The target version_dir does not exists yet, so base::Move() is using
  // rename() on POSIX systems. It is atomic in the sense that it will
  // either complete successfully or in the event of data loss be reverted.
  if (!base::Move(crx_temp_source, version_dir)) {
    LOG(ERROR) << "Installing extension from : " << crx_temp_source.value()
               << " into : " << version_dir.value() << " failed.";
    return base::FilePath();
  }

  // Flush one file in the new version_dir to make sure the dir move above is
  // persisted on disk. This is guaranteed on POSIX systems. ExtensionPrefs
  // is going to be updated with the new version_dir later. In the event of
  // data loss ExtensionPrefs should be pointing to the previous version which
  // is still fine.
  FlushFilesInDir(version_dir, ONE_FILE_ONLY);

  return version_dir;
}

void UninstallExtension(const base::FilePath& extensions_dir,
                        const std::string& id) {
  // We don't care about the return value. If this fails (and it can, due to
  // plugins that aren't unloaded yet), it will get cleaned up by
  // ExtensionGarbageCollector::GarbageCollectExtensions.
  base::DeleteFileRecursively(extensions_dir.AppendASCII(id));
}

scoped_refptr<Extension> LoadExtension(const base::FilePath& extension_path,
                                       Manifest::Location location,
                                       int flags,
                                       std::string* error) {
  return LoadExtension(extension_path, std::string(), location, flags, error);
}

scoped_refptr<Extension> LoadExtension(const base::FilePath& extension_path,
                                       const std::string& extension_id,
                                       Manifest::Location location,
                                       int flags,
                                       std::string* error) {
  std::unique_ptr<base::DictionaryValue> manifest =
      LoadManifest(extension_path, error);
  if (!manifest.get())
    return nullptr;
  if (!extension_l10n_util::LocalizeExtension(
          extension_path, manifest.get(),
          extension_l10n_util::GzippedMessagesPermission::kDisallow, error)) {
    return nullptr;
  }

  scoped_refptr<Extension> extension(Extension::Create(
      extension_path, location, *manifest, flags, extension_id, error));
  if (!extension.get())
    return nullptr;

  std::vector<InstallWarning> warnings;
  if (!ValidateExtension(extension.get(), error, &warnings))
    return nullptr;
  extension->AddInstallWarnings(std::move(warnings));

  return extension;
}

std::unique_ptr<base::DictionaryValue> LoadManifest(
    const base::FilePath& extension_path,
    std::string* error) {
  return LoadManifest(extension_path, kManifestFilename, error);
}

std::unique_ptr<base::DictionaryValue> LoadManifest(
    const base::FilePath& extension_path,
    const base::FilePath::CharType* manifest_filename,
    std::string* error) {
  base::FilePath manifest_path = extension_path.Append(manifest_filename);
  if (!base::PathExists(manifest_path)) {
    *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE);
    return nullptr;
  }

  JSONFileValueDeserializer deserializer(manifest_path);
  std::unique_ptr<base::Value> root(deserializer.Deserialize(nullptr, error));
  if (!root.get()) {
    if (error->empty()) {
      // If |error| is empty, than the file could not be read.
      // It would be cleaner to have the JSON reader give a specific error
      // in this case, but other code tests for a file error with
      // error->empty().  For now, be consistent.
      *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE);
    } else {
      *error = base::StringPrintf(
          "%s  %s", manifest_errors::kManifestParseError, error->c_str());
    }
    return nullptr;
  }

  if (!root->is_dict()) {
    *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_INVALID);
    return nullptr;
  }

  return base::DictionaryValue::From(std::move(root));
}

bool ValidateExtension(const Extension* extension,
                       std::string* error,
                       std::vector<InstallWarning>* warnings) {
  // Ask registered manifest handlers to validate their paths.
  if (!ManifestHandler::ValidateExtension(extension, error, warnings))
    return false;

  // Check children of extension root to see if any of them start with _ and is
  // not on the reserved list. We only warn, and do not block the loading of the
  // extension.
  std::string warning;
  if (!CheckForIllegalFilenames(extension->path(), &warning))
    warnings->push_back(InstallWarning(warning));

  // Check that the extension does not include any Windows reserved filenames.
  std::string windows_reserved_warning;
  if (!CheckForWindowsReservedFilenames(extension->path(),
                                        &windows_reserved_warning)) {
    warnings->push_back(InstallWarning(windows_reserved_warning));
  }

  // Check that extensions don't include private key files.
  std::vector<base::FilePath> private_keys =
      FindPrivateKeyFiles(extension->path());
  if (extension->creation_flags() & Extension::ERROR_ON_PRIVATE_KEY) {
    if (!private_keys.empty()) {
      // Only print one of the private keys because l10n_util doesn't have a way
      // to translate a list of strings.
      *error =
          l10n_util::GetStringFUTF8(IDS_EXTENSION_CONTAINS_PRIVATE_KEY,
                                    private_keys.front().LossyDisplayName());
      return false;
    }
  } else {
    for (size_t i = 0; i < private_keys.size(); ++i) {
      warnings->push_back(InstallWarning(
          l10n_util::GetStringFUTF8(IDS_EXTENSION_CONTAINS_PRIVATE_KEY,
                                    private_keys[i].LossyDisplayName())));
    }
    // Only warn; don't block loading the extension.
  }
  return true;
}

std::vector<base::FilePath> FindPrivateKeyFiles(
    const base::FilePath& extension_dir) {
  std::vector<base::FilePath> result;
  // Pattern matching only works at the root level, so filter manually.
  base::FileEnumerator traversal(
      extension_dir, /*recursive=*/true, base::FileEnumerator::FILES);
  for (base::FilePath current = traversal.Next(); !current.empty();
       current = traversal.Next()) {
    if (!current.MatchesExtension(kExtensionKeyFileExtension))
      continue;

    std::string key_contents;
    if (!base::ReadFileToString(current, &key_contents)) {
      // If we can't read the file, assume it's not a private key.
      continue;
    }
    std::string key_bytes;
    if (!Extension::ParsePEMKeyBytes(key_contents, &key_bytes)) {
      // If we can't parse the key, assume it's ok too.
      continue;
    }

    result.push_back(current);
  }
  return result;
}

bool CheckForIllegalFilenames(const base::FilePath& extension_path,
                              std::string* error) {
  // Enumerate all files and directories in the extension root.
  // There is a problem when using pattern "_*" with FileEnumerator, so we have
  // to cheat with find_first_of and match all.
  const int kFilesAndDirectories =
      base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES;
  base::FileEnumerator all_files(extension_path, false, kFilesAndDirectories);

  base::FilePath file;
  while (!(file = all_files.Next()).empty()) {
    base::FilePath::StringType filename = file.BaseName().value();

    // Skip all filenames that don't start with "_".
    if (filename.find_first_of(FILE_PATH_LITERAL("_")) != 0)
      continue;

    // Some filenames are special and allowed to start with "_".
    if (filename == kLocaleFolder || filename == kPlatformSpecificFolder ||
        filename == FILE_PATH_LITERAL("__MACOSX")) {
      continue;
    }

    *error = base::StringPrintf(
        "Cannot load extension with file or directory name %s. "
        "Filenames starting with \"_\" are reserved for use by the system.",
        file.BaseName().AsUTF8Unsafe().c_str());
    return false;
  }

  return true;
}

bool CheckForWindowsReservedFilenames(const base::FilePath& extension_dir,
                                      std::string* error) {
  const int kFilesAndDirectories =
      base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES;
  base::FileEnumerator traversal(extension_dir, true, kFilesAndDirectories);

  for (base::FilePath current = traversal.Next(); !current.empty();
       current = traversal.Next()) {
    base::FilePath::StringType filename = current.BaseName().value();
    bool is_reserved_filename = net::IsReservedNameOnWindows(filename);
    if (is_reserved_filename) {
      *error = base::StringPrintf(
          "Cannot load extension with file or directory name %s. "
          "The filename is illegal.",
          current.BaseName().AsUTF8Unsafe().c_str());
      return false;
    }
  }

  return true;
}

base::FilePath GetInstallTempDir(const base::FilePath& extensions_dir) {
  // We do file IO in this function, but only when the current profile's
  // Temp directory has never been used before, or in a rare error case.
  // Developers are not likely to see these situations often.

  // Create the temp directory as a sub-directory of the Extensions directory.
  // This guarantees it is on the same file system as the extension's eventual
  // install target.
  base::FilePath temp_path = extensions_dir.Append(kTempDirectoryName);
  if (base::PathExists(temp_path)) {
    if (!base::DirectoryExists(temp_path)) {
      DLOG(WARNING) << "Not a directory: " << temp_path.value();
      return base::FilePath();
    }
    if (!base::PathIsWritable(temp_path)) {
      DLOG(WARNING) << "Can't write to path: " << temp_path.value();
      return base::FilePath();
    }
    // This is a directory we can write to.
    return temp_path;
  }

  // Directory doesn't exist, so create it.
  if (!base::CreateDirectory(temp_path)) {
    DLOG(WARNING) << "Couldn't create directory: " << temp_path.value();
    return base::FilePath();
  }
  return temp_path;
}

void DeleteFile(const base::FilePath& path, bool recursive) {
  base::DeleteFile(path, recursive);
}

base::FilePath ExtensionURLToRelativeFilePath(const GURL& url) {
  base::StringPiece url_path = url.path_piece();
  if (url_path.empty() || url_path[0] != '/')
    return base::FilePath();

  // Convert %-encoded UTF8 to regular UTF8.
  std::string file_path;
  if (!net::UnescapeBinaryURLComponentSafe(
          url_path, true /* fail_on_path_separators */, &file_path)) {
    // There shouldn't be any escaped path separators or control characters in
    // the path. However, if there are, it's best to just fail.
    return base::FilePath();
  }

  // Drop the leading slashes.
  size_t skip = file_path.find_first_not_of("/\\");
  if (skip != file_path.npos)
    file_path = file_path.substr(skip);

  base::FilePath path = base::FilePath::FromUTF8Unsafe(file_path);

  // It's still possible for someone to construct an annoying URL whose path
  // would still wind up not being considered relative at this point.
  // For example: chrome-extension://id/c:////foo.html
  if (path.IsAbsolute())
    return base::FilePath();

  return path;
}

void SetReportErrorForInvisibleIconForTesting(bool value) {
  g_report_error_for_invisible_icon = value;
}

bool ValidateExtensionIconSet(const ExtensionIconSet& icon_set,
                              const Extension* extension,
                              int error_message_id,
                              SkColor background_color,
                              std::string* error) {
  for (const auto& entry : icon_set.map()) {
    const base::FilePath path =
        extension->GetResource(entry.second).GetFilePath();
    if (!ValidateFilePath(path)) {
      *error = l10n_util::GetStringFUTF8(error_message_id,
                                         base::UTF8ToUTF16(entry.second));
      return false;
    }

    if (extension->location() == Manifest::UNPACKED) {
      const bool is_sufficiently_visible =
          image_util::IsIconAtPathSufficientlyVisible(path);
      const bool is_sufficiently_visible_rendered =
          image_util::IsRenderedIconAtPathSufficientlyVisible(path,
                                                              background_color);
      UMA_HISTOGRAM_BOOLEAN(
          "Extensions.ManifestIconSetIconWasVisibleForUnpacked",
          is_sufficiently_visible);
      UMA_HISTOGRAM_BOOLEAN(
          "Extensions.ManifestIconSetIconWasVisibleForUnpackedRendered",
          is_sufficiently_visible_rendered);
      if (!is_sufficiently_visible && g_report_error_for_invisible_icon) {
        *error = l10n_util::GetStringFUTF8(
            IDS_EXTENSION_LOAD_ICON_NOT_SUFFICIENTLY_VISIBLE,
            base::UTF8ToUTF16(entry.second));
        return false;
      }
    }
  }
  return true;
}

MessageBundle* LoadMessageBundle(
    const base::FilePath& extension_path,
    const std::string& default_locale,
    extension_l10n_util::GzippedMessagesPermission gzip_permission,
    std::string* error) {
  error->clear();
  // Load locale information if available.
  base::FilePath locale_path = extension_path.Append(kLocaleFolder);
  if (!base::PathExists(locale_path))
    return nullptr;

  std::set<std::string> chrome_locales;
  extension_l10n_util::GetAllLocales(&chrome_locales);

  base::FilePath default_locale_path = locale_path.AppendASCII(default_locale);
  if (default_locale.empty() ||
      chrome_locales.find(default_locale) == chrome_locales.end() ||
      !base::PathExists(default_locale_path)) {
    *error = l10n_util::GetStringUTF8(
        IDS_EXTENSION_LOCALES_NO_DEFAULT_LOCALE_SPECIFIED);
    return nullptr;
  }

  MessageBundle* message_bundle = extension_l10n_util::LoadMessageCatalogs(
      locale_path, default_locale, gzip_permission, error);

  return message_bundle;
}

MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMap(
    const base::FilePath& extension_path,
    const std::string& extension_id,
    const std::string& default_locale) {
  return LoadMessageBundleSubstitutionMapFromPaths(
      {extension_path}, extension_id, default_locale);
}

MessageBundle::SubstitutionMap* LoadNonLocalizedMessageBundleSubstitutionMap(
    const std::string& extension_id) {
  MessageBundle::SubstitutionMap* return_value =
      new MessageBundle::SubstitutionMap();

  // Add @@extension_id reserved message here.
  return_value->insert(
      std::make_pair(MessageBundle::kExtensionIdKey, extension_id));

  return return_value;
}

MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapFromPaths(
    const std::vector<base::FilePath>& paths,
    const std::string& extension_id,
    const std::string& default_locale) {
  MessageBundle::SubstitutionMap* return_value =
      LoadNonLocalizedMessageBundleSubstitutionMap(extension_id);

  // Touch disk only if extension is localized.
  if (default_locale.empty())
    return return_value;

  std::string error;
  for (const base::FilePath& path : paths) {
    std::unique_ptr<MessageBundle> bundle(LoadMessageBundle(
        path, default_locale,
        extension_l10n_util::GzippedMessagesPermission::kDisallow, &error));
    if (bundle) {
      for (const auto& iter : *bundle->dictionary()) {
        // |insert| only adds new entries, and does not replace entries in
        // the main extension or previously processed imports.
        return_value->insert(std::make_pair(iter.first, iter.second));
      }
    }
  }

  return return_value;
}

base::FilePath GetVerifiedContentsPath(const base::FilePath& extension_path) {
  return extension_path.Append(kMetadataFolder)
      .Append(kVerifiedContentsFilename);
}
base::FilePath GetComputedHashesPath(const base::FilePath& extension_path) {
  return extension_path.Append(kMetadataFolder).Append(kComputedHashesFilename);
}
base::FilePath GetIndexedRulesetPath(const base::FilePath& extension_path) {
  return extension_path.Append(kMetadataFolder).Append(kIndexedRulesetFilename);
}

std::vector<base::FilePath> GetReservedMetadataFilePaths(
    const base::FilePath& extension_path) {
  return {
      GetVerifiedContentsPath(extension_path),
      GetComputedHashesPath(extension_path),
      GetIndexedRulesetPath(extension_path),
  };
}

}  // namespace file_util
}  // namespace extensions
