// Copyright (c) 2011 The Chromium OS 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 "image-burner/image_burner_impl.h"

#include <ctype.h>
#include <regex.h>
#include <stdint.h>

#include <memory>
#include <vector>

#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <brillo/cryptohome.h>

namespace imageburn {

namespace {

const int kBurningBlockSize = 4 * 1024;  // 4 KiB

const char* kFilePathPatterns[] = {"^/dev/sd[a-z]+$", "^/dev/mmcblk[0-9]+$"};
const int kFilePathPatternCount = 2;

const char kMediaDirectory[] = "/media";
const char kUserRootDirectory[] = "/home/chronos";

bool IsUserOrUserHash(const std::string& path) {
  if (path == "user")
    return true;

  if (base::StartsWith(path, "u-", base::CompareCase::INSENSITIVE_ASCII) &&
      brillo::cryptohome::home::IsSanitizedUserName(path.substr(2))) {
    return true;
  }

  return false;
}

}  // namespace

BurnerImpl::BurnerImpl(FileSystemWriter* writer,
                       FileSystemReader* reader,
                       SignalSender* signal_sender,
                       PathGetter* path_getter)
    : writer_(writer),
      reader_(reader),
      signal_sender_(signal_sender),
      path_getter_(path_getter),
      data_block_size_(kBurningBlockSize) {}

ErrorCode BurnerImpl::BurnImage(const char* from_path, const char* to_path) {
  ErrorCode err = IMAGEBURN_OK;

  if (!writer_ || !reader_ || !signal_sender_ || !path_getter_)
    err = IMAGEBURN_ERROR_BURNER_NOT_INITIALIZED;

  if (!err)
    ValidateTargetPath(to_path, &err);

  std::string resolved_from_path;
  if (!err)
    ValidateSourcePath(from_path, &resolved_from_path, &err);

  if (!err)
    DoBurn(resolved_from_path.c_str(), to_path, &err);

  // TODO(tbarzic) send error specific error message.
  signal_sender_->SendFinishedSignal(to_path, !err,
                                     (!err ? "" : "Error during burn"));
  return err;
}

void BurnerImpl::InitSignalSender(SignalSender* signal_sender) {
  signal_sender_ = signal_sender;
}

bool BurnerImpl::ValidateTargetPath(const char* path, ErrorCode* error) {
  if (!path) {
    *error = IMAGEBURN_ERROR_NULL_TARGET_PATH;
    LOG(ERROR) << "Target path set to NULL.";
    return false;
  }

  // Check if path conforms to a valid regex.
  bool is_pattern_valid = false;
  for (int i = 0; i < kFilePathPatternCount; ++i) {
    regex_t re;
    int status = regcomp(&re, kFilePathPatterns[i], REG_EXTENDED);
    DCHECK_EQ(0, status);
    status = regexec(&re, path, 0, NULL, 0);
    regfree(&re);
    if (status == 0) {
      is_pattern_valid = true;
      break;
    }
  }

  if (!is_pattern_valid) {
    *error = IMAGEBURN_ERROR_INVALID_TARGET_PATH;
    LOG(ERROR) << "Target path does not have a valid file path pattern.";
    return false;
  }

  std::string root_path;
  // This will return roots file path, so we can compare target path, which
  // should also be devices file path, to it.
  bool got_root_path = path_getter_->GetRootPath(&root_path);
  if (!got_root_path ||
      strncmp(root_path.c_str(), path, root_path.length()) == 0) {
    *error = IMAGEBURN_ERROR_TARGET_PATH_ON_ROOT;
    LOG(ERROR) << "Target path is on root device.";
    return false;
  }

  return true;
}

bool BurnerImpl::ValidateSourcePath(const char* path,
                                    std::string* resolved_path,
                                    ErrorCode* error) {
  resolved_path->clear();
  if (!path) {
    *error = IMAGEBURN_ERROR_NULL_SOURCE_PATH;
    LOG(ERROR) << "Source path set to NULL.";
    return false;
  }

  if (!path_getter_->GetRealPath(path, resolved_path)) {
    *error = IMAGEBURN_ERROR_SOURCE_REAL_PATH_NOT_DETERMINED;
    return false;
  }

  if (!IsSourcePathAllowed(*resolved_path)) {
    *error = IMAGEBURN_ERROR_SOURCE_PATH_NOT_ALLOWED;
    LOG(ERROR) << "Source path is not from one of the allowed locations.";
    return false;
  }

  return true;
}

bool BurnerImpl::DoBurn(const char* from_path,
                        const char* to_path,
                        ErrorCode* error) {
  LOG(INFO) << "Burning " << from_path << " to " << to_path;
  *error = IMAGEBURN_OK;

  bool success = reader_->Open(from_path);
  if (success) {
    if (!(success = writer_->Open(to_path)))
      *error = IMAGEBURN_ERROR_CANNOT_OPEN_TARGET;
  } else {
    *error = IMAGEBURN_ERROR_CANNOT_OPEN_SOURCE;
  }

  if (success) {
    std::unique_ptr<char[]> buffer(new char[data_block_size_]);

    int64_t total_burnt = 0;
    int64_t image_size = reader_->GetSize();

    int len = 0;
    while ((len = reader_->Read(buffer.get(), data_block_size_)) > 0) {
      if (writer_->Write(buffer.get(), len) == len) {
        total_burnt += static_cast<int64_t>(len);
        signal_sender_->SendProgressSignal(total_burnt, image_size, to_path);
      } else {
        success = false;
        *error = IMAGEBURN_ERROR_FAILED_WRITING_TO_TARGET;
        break;
      }
    }
    if (len < 0) {
      success = false;
      *error = IMAGEBURN_ERROR_FAILED_READING_SOURCE;
    }
  }

  if (!writer_->Close() && success) {
    // We set this only when there is no previous error.
    success = false;
    *error = IMAGEBURN_ERROR_CANNOT_CLOSE_TARGET;
  }

  if (!reader_->Close() && success) {
    // We set this only when there is no previous error.
    success = false;
    *error = IMAGEBURN_ERROR_CANNOT_CLOSE_SOURCE;
  }
  return success;
}

// Derived from cros-disks::ArchiveManager::CanMount().
bool BurnerImpl::IsSourcePathAllowed(const std::string& source_path) const {
  // TODO(benchan): Revisit the need to allow .../Downloads once the MyFiles
  // migration (chromium:873539) is complete.
  //
  // The following paths are allowed:
  //     /home/chronos/user/Downloads/...<file>
  //     /home/chronos/user/MyFiles/...<file>
  //     /home/chronos/user/GCache/...<file>
  //     /home/chronos/u-<user-id>/Downloads/...<file>
  //     /home/chronos/u-<user-id>/MyFiles/...<file>
  //     /home/chronos/u-<user-id>/GCache/...<file>
  //     /media/<dir>/<dir>/...<file>
  //
  base::FilePath file_path(source_path);
  if (base::FilePath(kUserRootDirectory).IsParent(file_path)) {
    std::vector<std::string> components;
    file_path.StripTrailingSeparators().GetComponents(&components);
    // The file path of an image file under a user's Downloads, MyFiles or
    // GCache directory path is split into the following components:
    //   '/', 'home', 'chronos', 'user', 'Downloads', ..., <file>
    //   '/', 'home', 'chronos', 'user', 'MyFiles', ..., <file>
    //   '/', 'home', 'chronos', 'user', 'GCache', ..., <file>
    //   '/', 'home', 'chronos', 'u-<userid>', 'Downloads', ..., <file>
    //   '/', 'home', 'chronos', 'u-<userid>', 'MyFiles', ..., <file>
    //   '/', 'home', 'chronos', 'u-<userid>', 'GCache', ..., <file>
    if (components.size() > 5 && IsUserOrUserHash(components[3]) &&
        (components[4] == "Downloads" || components[4] == "MyFiles" ||
         components[4] == "GCache")) {
      return true;
    }
  }

  if (base::FilePath(kMediaDirectory).IsParent(file_path)) {
    std::vector<std::string> components;
    file_path.StripTrailingSeparators().GetComponents(&components);
    // A mount directory is always created under /media/<sub type>/<mount dir>,
    // so the file path of an image file under a mount directory is split
    // into more than 4 components:
    //   '/', 'media', 'removable', 'usb', ..., <file>
    if (components.size() > 4)
      return true;
  }
  return false;
}

}  // namespace imageburn
