// 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 {
  // The following paths are allowed:
  //     /home/chronos/user/Downloads/...<file>
  //     /home/chronos/user/GCache/...<file>
  //     /home/chronos/u-<user-id>/Downloads/...<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<base::FilePath::StringType> components;
    file_path.StripTrailingSeparators().GetComponents(&components);
    // The file path of an image file under a user's Downloads or GCache
    // directory path is split into the following components:
    //   '/', 'home', 'chronos', 'user', 'Downloads', ..., <file>
    //   '/', 'home', 'chronos', 'user', 'GCache', ..., <file>
    //   '/', 'home', 'chronos', 'u-<userid>', 'Downloads', ..., <file>
    //   '/', 'home', 'chronos', 'u-<userid>', 'GCache', ..., <file>
    if (components.size() > 5 && IsUserOrUserHash(components[3]) &&
        (components[4] == "Downloads" || components[4] == "GCache")) {
      return true;
    }
  }

  if (base::FilePath(kMediaDirectory).IsParent(file_path)) {
    std::vector<base::FilePath::StringType> 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
