// 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/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 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) {}

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* 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
