// Copyright 2018 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 <memory>
#include <utility>

#include <base/check.h>
#include <base/json/json_reader.h>
#include <base/strings/string_number_conversions.h>
#include <base/values.h>

#include "imageloader/manifest.h"

namespace imageloader {

namespace {
// The current version of the manifest file.
constexpr int kCurrentManifestVersion = 1;
// The name of the version field in the manifest.
constexpr char kManifestVersionField[] = "manifest-version";
// The name of the component version field in the manifest.
constexpr char kVersionField[] = "version";
// The name of the field containing the image hash.
constexpr char kImageHashField[] = "image-sha256-hash";
// The name of the bool field indicating whether component is removable.
constexpr char kIsRemovableField[] = "is-removable";
// The name of the metadata field.
constexpr char kMetadataField[] = "metadata";
// The name of the field containing the table hash.
constexpr char kTableHashField[] = "table-sha256-hash";
// Optional manifest fields.
constexpr char kFSType[] = "fs-type";
constexpr char kId[] = "id";
constexpr char kPackage[] = "package";
constexpr char kName[] = "name";
constexpr char kImageType[] = "image-type";
constexpr char kPreallocatedSize[] = "pre-allocated-size";
constexpr char kSize[] = "size";
constexpr char kPreloadAllowed[] = "preload-allowed";
constexpr char kMountFileRequired[] = "mount-file-required";
constexpr char kUsedBy[] = "used-by";
constexpr char kDaysToPurge[] = "days-to-purge";
constexpr char kDescription[] = "description";

bool GetSHA256FromString(const std::string& hash_str,
                         std::vector<uint8_t>* bytes) {
  if (!base::HexStringToBytes(hash_str, bytes))
    return false;
  return bytes->size() == 32;
}

// Ensure the metadata entry is a dictionary mapping strings to strings and
// parse it into |out_metadata| and return true if so.
bool ParseMetadata(const base::Value& metadata_dict,
                   std::map<std::string, std::string>* out_metadata) {
  DCHECK(out_metadata);

  if (!metadata_dict.is_dict()) {
    return false;
  }

  for (const auto& item : metadata_dict.DictItems()) {
    if (!item.second.is_string()) {
      LOG(ERROR) << "Key \"" << item.first << "\" did not map to string value";
      return false;
    }

    (*out_metadata)[item.first] = item.second.GetString();
  }

  return true;
}

}  // namespace

Manifest::Manifest()
    : manifest_version_(0),
      fs_type_(FileSystem::kExt4),
      preallocated_size_(0),
      size_(0),
      is_removable_(false),
      days_to_purge_(0) {}

bool Manifest::ParseManifest(const std::string& manifest_raw) {
  // Now deserialize the manifest json and read out the rest of the component.
  auto manifest_value = base::JSONReader::ReadAndReturnValueWithError(
      manifest_raw, base::JSON_PARSE_RFC);
  if (!manifest_value.value) {
    LOG(ERROR) << "Could not parse the manifest file as JSON. Error: "
               << manifest_value.error_message;
    return false;
  }

  if (!manifest_value.value->is_dict()) {
    LOG(ERROR) << "Manifest file is not dictionary.";
    return false;
  }
  base::Value manifest_dict = std::move(*manifest_value.value);

  // This will have to be changed if the manifest version is bumped.
  base::Optional<int> manifest_version =
      manifest_dict.FindIntKey(kManifestVersionField);
  if (!manifest_version.has_value()) {
    LOG(ERROR) << "Could not parse manifest version field from manifest.";
    return false;
  }
  if (manifest_version != kCurrentManifestVersion) {
    LOG(ERROR) << "Unsupported version of the manifest.";
    return false;
  }
  manifest_version_ = *manifest_version;

  const std::string* image_hash_str =
      manifest_dict.FindStringKey(kImageHashField);
  if (!image_hash_str) {
    LOG(ERROR) << "Could not parse image hash from manifest.";
    return false;
  }

  if (!GetSHA256FromString(*image_hash_str, &(image_sha256_))) {
    LOG(ERROR) << "Could not convert image hash to bytes.";
    return false;
  }

  const std::string* table_hash_str =
      manifest_dict.FindStringKey(kTableHashField);
  if (table_hash_str == nullptr) {
    LOG(ERROR) << "Could not parse table hash from manifest.";
    return false;
  }

  if (!GetSHA256FromString(*table_hash_str, &(table_sha256_))) {
    LOG(ERROR) << "Could not convert table hash to bytes.";
    return false;
  }

  const std::string* version = manifest_dict.FindStringKey(kVersionField);
  if (!version) {
    LOG(ERROR) << "Could not parse component version from manifest.";
    return false;
  }
  version_ = *version;

  // The fs_type field is optional, and squashfs by default.
  const std::string* fs_type = manifest_dict.FindStringKey(kFSType);
  if (fs_type) {
    if (*fs_type == "ext4") {
      fs_type_ = FileSystem::kExt4;
    } else if (*fs_type == "squashfs") {
      fs_type_ = FileSystem::kSquashFS;
    } else {
      LOG(ERROR) << "Unsupported file system type: " << *fs_type;
      return false;
    }
  } else {
    fs_type_ = FileSystem::kSquashFS;
  }

  base::Optional<bool> is_removable =
      manifest_dict.FindBoolKey(kIsRemovableField);
  // If |is-removable| field does not exist, by default it is false.
  is_removable_ = is_removable.value_or(false);

  base::Optional<bool> preload_allowed =
      manifest_dict.FindBoolKey(kPreloadAllowed);
  // If |preaload-allowed| field does not exist, by default it is false.
  preload_allowed_ = preload_allowed.value_or(false);

  base::Optional<bool> mount_file_required =
      manifest_dict.FindBoolKey(kMountFileRequired);
  // If 'mount-file-required' field does not exist, by default it is false.
  mount_file_required_ = mount_file_required.value_or(false);

  // All of these fields are optional.
  const std::string* id = manifest_dict.FindStringKey(kId);
  if (id)
    id_ = *id;
  const std::string* package = manifest_dict.FindStringKey(kPackage);
  if (package)
    package_ = *package;
  const std::string* name = manifest_dict.FindStringKey(kName);
  if (name)
    name_ = *name;
  const std::string* image_type = manifest_dict.FindStringKey(kImageType);
  if (image_type)
    image_type_ = *image_type;
  const std::string* used_by = manifest_dict.FindStringKey(kUsedBy);
  if (used_by)
    used_by_ = *used_by;
  const std::string* days_to_purge_str =
      manifest_dict.FindStringKey(kDaysToPurge);
  if (days_to_purge_str) {
    if (!base::StringToInt64(*days_to_purge_str, &days_to_purge_)) {
      LOG(ERROR) << "Days to purge is malformed: " << *days_to_purge_str;
      return false;
    }
  }
  const std::string* description = manifest_dict.FindStringKey(kDescription);
  if (description)
    description_ = *description;

  const std::string* preallocated_size_str =
      manifest_dict.FindStringKey(kPreallocatedSize);
  if (preallocated_size_str) {
    if (!base::StringToInt64(*preallocated_size_str, &preallocated_size_)) {
      LOG(ERROR) << "Manifest pre-allocated-size was malformed: "
                 << *preallocated_size_str;
      return false;
    }
  }

  const std::string* size_str = manifest_dict.FindStringKey(kSize);
  if (size_str) {
    if (!base::StringToInt64(*size_str, &size_)) {
      LOG(ERROR) << "Manifest size was malformed: " << *size_str;
      return false;
    }
  }

  // Copy out the metadata, if it's there.
  const base::Value* metadata = manifest_dict.FindKey(kMetadataField);
  if (metadata) {
    if (!ParseMetadata(*metadata, &metadata_)) {
      LOG(ERROR) << "Manifest metadata was malformed";
      return false;
    }
  }

  return true;
}

}  // namespace imageloader
