/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <algorithm>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "androidfw/AssetManager2.h"
#include "utils/String16.h"
#include "utils/String8.h"

#include "idmap2/Idmap.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
#include "idmap2/SysTrace.h"
#include "idmap2/ZipFile.h"

namespace android::idmap2 {

namespace {

#define EXTRACT_TYPE(resid) ((0x00ff0000 & (resid)) >> 16)

#define EXTRACT_ENTRY(resid) (0x0000ffff & (resid))

class MatchingResources {
 public:
  void Add(ResourceId target_resid, ResourceId overlay_resid) {
    TypeId target_typeid = EXTRACT_TYPE(target_resid);
    if (map_.find(target_typeid) == map_.end()) {
      map_.emplace(target_typeid, std::set<std::pair<ResourceId, ResourceId>>());
    }
    map_[target_typeid].insert(std::make_pair(target_resid, overlay_resid));
  }

  inline const std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>>& Map() const {
    return map_;
  }

 private:
  // target type id -> set { pair { overlay entry id, overlay entry id } }
  std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>> map_;
};

bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
  uint16_t value;
  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint16_t))) {
    *out = dtohl(value);
    return true;
  }
  return false;
}

bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
  uint32_t value;
  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint32_t))) {
    *out = dtohl(value);
    return true;
  }
  return false;
}

// a string is encoded as a kIdmapStringLength char array; the array is always null-terminated
bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
  char buf[kIdmapStringLength];
  memset(buf, 0, sizeof(buf));
  if (!stream.read(buf, sizeof(buf))) {
    return false;
  }
  if (buf[sizeof(buf) - 1] != '\0') {
    return false;
  }
  memcpy(out, buf, sizeof(buf));
  return true;
}

ResourceId NameToResid(const AssetManager2& am, const std::string& name) {
  return am.GetResourceId(name);
}

// TODO(martenkongstad): scan for package name instead of assuming package at index 0
//
// idmap version 0x01 naively assumes that the package to use is always the first ResTable_package
// in the resources.arsc blob. In most cases, there is only a single ResTable_package anyway, so
// this assumption tends to work out. That said, the correct thing to do is to scan
// resources.arsc for a package with a given name as read from the package manifest instead of
// relying on a hard-coded index. This however requires storing the package name in the idmap
// header, which in turn requires incrementing the idmap version. Because the initial version of
// idmap2 is compatible with idmap, this will have to wait for now.
const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
  const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc.GetPackages();
  if (packages.empty()) {
    return nullptr;
  }
  int id = packages[0]->GetPackageId();
  return loaded_arsc.GetPackageById(id);
}

Result<uint32_t> GetCrc(const ZipFile& zip) {
  const Result<uint32_t> a = zip.Crc("resources.arsc");
  const Result<uint32_t> b = zip.Crc("AndroidManifest.xml");
  return a && b ? Result<uint32_t>(*a ^ *b) : kResultError;
}

}  // namespace

std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) {
  std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader());

  if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) ||
      !Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) ||
      !ReadString(stream, idmap_header->target_path_) ||
      !ReadString(stream, idmap_header->overlay_path_)) {
    return nullptr;
  }

  return std::move(idmap_header);
}

bool IdmapHeader::IsUpToDate(std::ostream& out_error) const {
  if (magic_ != kIdmapMagic) {
    out_error << base::StringPrintf("error: bad magic: actual 0x%08x, expected 0x%08x", magic_,
                                    kIdmapMagic)
              << std::endl;
    return false;
  }

  if (version_ != kIdmapCurrentVersion) {
    out_error << base::StringPrintf("error: bad version: actual 0x%08x, expected 0x%08x", version_,
                                    kIdmapCurrentVersion)
              << std::endl;
    return false;
  }

  const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_path_);
  if (!target_zip) {
    out_error << "error: failed to open target " << target_path_ << std::endl;
    return false;
  }

  Result<uint32_t> target_crc = GetCrc(*target_zip);
  if (!target_crc) {
    out_error << "error: failed to get target crc" << std::endl;
    return false;
  }

  if (target_crc_ != *target_crc) {
    out_error << base::StringPrintf(
                     "error: bad target crc: idmap version 0x%08x, file system version 0x%08x",
                     target_crc_, *target_crc)
              << std::endl;
    return false;
  }

  const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_path_);
  if (!overlay_zip) {
    out_error << "error: failed to open overlay " << overlay_path_ << std::endl;
    return false;
  }

  Result<uint32_t> overlay_crc = GetCrc(*overlay_zip);
  if (!overlay_crc) {
    out_error << "error: failed to get overlay crc" << std::endl;
    return false;
  }

  if (overlay_crc_ != *overlay_crc) {
    out_error << base::StringPrintf(
                     "error: bad overlay crc: idmap version 0x%08x, file system version 0x%08x",
                     overlay_crc_, *overlay_crc)
              << std::endl;
    return false;
  }

  return true;
}

std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) {
  std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());

  uint16_t target_package_id16;
  if (!Read16(stream, &target_package_id16) || !Read16(stream, &idmap_data_header->type_count_)) {
    return nullptr;
  }
  idmap_data_header->target_package_id_ = target_package_id16;

  return std::move(idmap_data_header);
}

std::unique_ptr<const IdmapData::TypeEntry> IdmapData::TypeEntry::FromBinaryStream(
    std::istream& stream) {
  std::unique_ptr<IdmapData::TypeEntry> data(new IdmapData::TypeEntry());
  uint16_t target_type16;
  uint16_t overlay_type16;
  uint16_t entry_count;
  if (!Read16(stream, &target_type16) || !Read16(stream, &overlay_type16) ||
      !Read16(stream, &entry_count) || !Read16(stream, &data->entry_offset_)) {
    return nullptr;
  }
  data->target_type_id_ = target_type16;
  data->overlay_type_id_ = overlay_type16;
  for (uint16_t i = 0; i < entry_count; i++) {
    ResourceId resid;
    if (!Read32(stream, &resid)) {
      return nullptr;
    }
    data->entries_.push_back(resid);
  }

  return std::move(data);
}

std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& stream) {
  std::unique_ptr<IdmapData> data(new IdmapData());
  data->header_ = IdmapData::Header::FromBinaryStream(stream);
  if (!data->header_) {
    return nullptr;
  }
  for (size_t type_count = 0; type_count < data->header_->GetTypeCount(); type_count++) {
    std::unique_ptr<const TypeEntry> type = IdmapData::TypeEntry::FromBinaryStream(stream);
    if (!type) {
      return nullptr;
    }
    data->type_entries_.push_back(std::move(type));
  }
  return std::move(data);
}

std::string Idmap::CanonicalIdmapPathFor(const std::string& absolute_dir,
                                         const std::string& absolute_apk_path) {
  assert(absolute_dir.size() > 0 && absolute_dir[0] == "/");
  assert(absolute_apk_path.size() > 0 && absolute_apk_path[0] == "/");
  std::string copy(++absolute_apk_path.cbegin(), absolute_apk_path.cend());
  replace(copy.begin(), copy.end(), '/', '@');
  return absolute_dir + "/" + copy + "@idmap";
}

std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream,
                                                     std::ostream& out_error) {
  SYSTRACE << "Idmap::FromBinaryStream";
  std::unique_ptr<Idmap> idmap(new Idmap());

  idmap->header_ = IdmapHeader::FromBinaryStream(stream);
  if (!idmap->header_) {
    out_error << "error: failed to parse idmap header" << std::endl;
    return nullptr;
  }

  // idmap version 0x01 does not specify the number of data blocks that follow
  // the idmap header; assume exactly one data block
  for (int i = 0; i < 1; i++) {
    std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
    if (!data) {
      out_error << "error: failed to parse data block " << i << std::endl;
      return nullptr;
    }
    idmap->data_.push_back(std::move(data));
  }

  return std::move(idmap);
}

bool CheckOverlayable(const LoadedPackage& target_package,
                      const utils::OverlayManifestInfo& overlay_info,
                      const PolicyBitmask& fulfilled_polices, const ResourceId& resid) {
  const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid);
  if (overlayable_info == nullptr) {
    // If the resource does not have an overlayable definition, allow the resource to be overlaid.
    // Once overlayable enforcement is turned on, this check will return false.
    return !target_package.DefinesOverlayable();
  }

  if (overlay_info.target_name != overlayable_info->name) {
    // If the overlay supplies a target overlayable name, the resource must belong to the
    // overlayable defined with the specified name to be overlaid.
    return false;
  }

  // Enforce policy restrictions if the resource is declared as overlayable.
  return (overlayable_info->policy_flags & fulfilled_polices) != 0;
}

std::unique_ptr<const Idmap> Idmap::FromApkAssets(
    const std::string& target_apk_path, const ApkAssets& target_apk_assets,
    const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets,
    const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error) {
  SYSTRACE << "Idmap::FromApkAssets";
  AssetManager2 target_asset_manager;
  if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true, false)) {
    out_error << "error: failed to create target asset manager" << std::endl;
    return nullptr;
  }

  AssetManager2 overlay_asset_manager;
  if (!overlay_asset_manager.SetApkAssets({&overlay_apk_assets}, true, false)) {
    out_error << "error: failed to create overlay asset manager" << std::endl;
    return nullptr;
  }

  const LoadedArsc* target_arsc = target_apk_assets.GetLoadedArsc();
  if (target_arsc == nullptr) {
    out_error << "error: failed to load target resources.arsc" << std::endl;
    return nullptr;
  }

  const LoadedArsc* overlay_arsc = overlay_apk_assets.GetLoadedArsc();
  if (overlay_arsc == nullptr) {
    out_error << "error: failed to load overlay resources.arsc" << std::endl;
    return nullptr;
  }

  const LoadedPackage* target_pkg = GetPackageAtIndex0(*target_arsc);
  if (target_pkg == nullptr) {
    out_error << "error: failed to load target package from resources.arsc" << std::endl;
    return nullptr;
  }

  const LoadedPackage* overlay_pkg = GetPackageAtIndex0(*overlay_arsc);
  if (overlay_pkg == nullptr) {
    out_error << "error: failed to load overlay package from resources.arsc" << std::endl;
    return nullptr;
  }

  const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_apk_path);
  if (!target_zip) {
    out_error << "error: failed to open target as zip" << std::endl;
    return nullptr;
  }

  const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_apk_path);
  if (!overlay_zip) {
    out_error << "error: failed to open overlay as zip" << std::endl;
    return nullptr;
  }

  Result<utils::OverlayManifestInfo> overlay_info =
      utils::ExtractOverlayManifestInfo(overlay_apk_path, out_error);
  if (!overlay_info) {
    return nullptr;
  }

  std::unique_ptr<IdmapHeader> header(new IdmapHeader());
  header->magic_ = kIdmapMagic;
  header->version_ = kIdmapCurrentVersion;

  Result<uint32_t> crc = GetCrc(*target_zip);
  if (!crc) {
    out_error << "error: failed to get zip crc for target" << std::endl;
    return nullptr;
  }
  header->target_crc_ = *crc;

  crc = GetCrc(*overlay_zip);
  if (!crc) {
    out_error << "error: failed to get zip crc for overlay" << std::endl;
    return nullptr;
  }
  header->overlay_crc_ = *crc;

  if (target_apk_path.size() > sizeof(header->target_path_)) {
    out_error << "error: target apk path \"" << target_apk_path << "\" longer that maximum size "
              << sizeof(header->target_path_) << std::endl;
    return nullptr;
  }
  memset(header->target_path_, 0, sizeof(header->target_path_));
  memcpy(header->target_path_, target_apk_path.data(), target_apk_path.size());

  if (overlay_apk_path.size() > sizeof(header->overlay_path_)) {
    out_error << "error: overlay apk path \"" << overlay_apk_path << "\" longer that maximum size "
              << sizeof(header->overlay_path_) << std::endl;
    return nullptr;
  }
  memset(header->overlay_path_, 0, sizeof(header->overlay_path_));
  memcpy(header->overlay_path_, overlay_apk_path.data(), overlay_apk_path.size());

  std::unique_ptr<Idmap> idmap(new Idmap());
  idmap->header_ = std::move(header);

  // find the resources that exist in both packages
  MatchingResources matching_resources;
  const auto end = overlay_pkg->end();
  for (auto iter = overlay_pkg->begin(); iter != end; ++iter) {
    const ResourceId overlay_resid = *iter;
    Result<std::string> name = utils::ResToTypeEntryName(overlay_asset_manager, overlay_resid);
    if (!name) {
      continue;
    }
    // prepend "<package>:" to turn name into "<package>:<type>/<name>"
    const std::string full_name =
        base::StringPrintf("%s:%s", target_pkg->GetPackageName().c_str(), name->c_str());
    const ResourceId target_resid = NameToResid(target_asset_manager, full_name);
    if (target_resid == 0) {
      continue;
    }

    if (enforce_overlayable &&
        !CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid)) {
      LOG(WARNING) << "overlay \"" << overlay_apk_path << "\" is not allowed to overlay resource \""
                   << full_name << "\"" << std::endl;
      continue;
    }

    matching_resources.Add(target_resid, overlay_resid);
  }

  // encode idmap data
  std::unique_ptr<IdmapData> data(new IdmapData());
  const auto types_end = matching_resources.Map().cend();
  for (auto ti = matching_resources.Map().cbegin(); ti != types_end; ++ti) {
    auto ei = ti->second.cbegin();
    std::unique_ptr<IdmapData::TypeEntry> type(new IdmapData::TypeEntry());
    type->target_type_id_ = EXTRACT_TYPE(ei->first);
    type->overlay_type_id_ = EXTRACT_TYPE(ei->second);
    type->entry_offset_ = EXTRACT_ENTRY(ei->first);
    EntryId last_target_entry = kNoEntry;
    for (; ei != ti->second.cend(); ++ei) {
      if (last_target_entry != kNoEntry) {
        int count = EXTRACT_ENTRY(ei->first) - last_target_entry - 1;
        type->entries_.insert(type->entries_.end(), count, kNoEntry);
      }
      type->entries_.push_back(EXTRACT_ENTRY(ei->second));
      last_target_entry = EXTRACT_ENTRY(ei->first);
    }
    data->type_entries_.push_back(std::move(type));
  }

  std::unique_ptr<IdmapData::Header> data_header(new IdmapData::Header());
  data_header->target_package_id_ = target_pkg->GetPackageId();
  data_header->type_count_ = data->type_entries_.size();
  data->header_ = std::move(data_header);

  idmap->data_.push_back(std::move(data));

  return std::move(idmap);
}

void IdmapHeader::accept(Visitor* v) const {
  assert(v != nullptr);
  v->visit(*this);
}

void IdmapData::Header::accept(Visitor* v) const {
  assert(v != nullptr);
  v->visit(*this);
}

void IdmapData::TypeEntry::accept(Visitor* v) const {
  assert(v != nullptr);
  v->visit(*this);
}

void IdmapData::accept(Visitor* v) const {
  assert(v != nullptr);
  v->visit(*this);
  header_->accept(v);
  auto end = type_entries_.cend();
  for (auto iter = type_entries_.cbegin(); iter != end; ++iter) {
    (*iter)->accept(v);
  }
}

void Idmap::accept(Visitor* v) const {
  assert(v != nullptr);
  v->visit(*this);
  header_->accept(v);
  auto end = data_.cend();
  for (auto iter = data_.cbegin(); iter != end; ++iter) {
    (*iter)->accept(v);
  }
}

}  // namespace android::idmap2
