// Copyright 2019 The Fuchsia 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 "src/developer/feedback/utils/archive.h"

#include "src/lib/files/file.h"
#include "src/lib/files/scoped_temp_dir.h"
#include "src/lib/fsl/vmo/file.h"
#include "src/lib/fsl/vmo/sized_vmo.h"
#include "src/lib/fsl/vmo/vector.h"
#include "src/lib/fxl/strings/substitute.h"
#include "src/lib/syslog/cpp/logger.h"
#include "third_party/zlib/contrib/minizip/unzip.h"
#include "third_party/zlib/contrib/minizip/zip.h"

namespace feedback {
namespace {

using fuchsia::feedback::Attachment;
using fuchsia::mem::Buffer;

bool Archive(const std::vector<Attachment>& attachments, Buffer* archive, zipFile* zf) {
  for (const auto& attachment : attachments) {
    const std::string& filename = attachment.key;

    zip_fileinfo zf_info = {};
    if (int status = zipOpenNewFileInZip64(*zf, filename.c_str(), &zf_info, nullptr, 0, nullptr, 0,
                                           nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION, /*zip64=*/1);
        status != ZIP_OK) {
      FX_LOGS(ERROR) << fxl::Substitute("cannot create $0 in output zip archive: ", filename)
                     << status;
      return false;
    }

    std::vector<uint8_t> content;
    if (!fsl::VectorFromVmo(attachment.value, &content)) {
      FX_LOGS(ERROR) << "failed to read VMO for " << filename;
      return false;
    }

    if (int status = zipWriteInFileInZip(*zf, content.data(), content.size()); status != ZIP_OK) {
      FX_LOGS(ERROR) << fxl::Substitute("cannot write $0 in output zip archive: ", filename)
                     << status;
      return false;
    }

    if (int status = zipCloseFileInZip(*zf); status != ZIP_OK) {
      FX_LOGS(WARNING) << fxl::Substitute("cannot close $0 in output zip archive: ", filename)
                       << status;
    }
  }

  return true;
}

}  // namespace

bool Archive(const std::vector<Attachment>& attachments, Buffer* archive) {
  // We write the archive to a temporary file because in-memory archiving in minizip is complicated.
  files::ScopedTempDir tmp_dir;
  std::string archive_filename;
  tmp_dir.NewTempFile(&archive_filename);

  zipFile zf = zipOpen64(archive_filename.c_str(), APPEND_STATUS_CREATE);
  if (zf == nullptr) {
    FX_LOGS(ERROR) << "cannot create output zip archive";
    return false;
  }

  bool success = Archive(attachments, archive, &zf);

  // We always close the archive regardless of the success status.
  if (int status = zipClose(zf, nullptr); status != ZIP_OK) {
    FX_LOGS(WARNING) << "cannot close output zip archive: " << status;
  }

  if (!success) {
    return false;
  }

  fsl::SizedVmo vmo;
  if (!fsl::VmoFromFilename(archive_filename, &vmo)) {
    FX_LOGS(ERROR) << "error loading output zip archive into VMO";
    return false;
  }
  *archive = std::move(vmo).ToTransport();

  return true;
}

namespace {

bool Unpack(const Buffer& archive, std::vector<Attachment>* attachments, unzFile* uf) {
  unz_global_info archive_info;
  if (int status = unzGetGlobalInfo(*uf, &archive_info); status != UNZ_OK) {
    FX_LOGS(ERROR) << "cannot read input zip archive info: " << status;
    return false;
  }

  const auto num_files = archive_info.number_entry;
  if (num_files <= 0) {
    FX_LOGS(ERROR) << "input zip archive contains no files";
    return false;
  }

  for (uint64_t current_file_index = 1; current_file_index <= num_files; ++current_file_index) {
    unz_file_info64 file_info;
    char filename[256];
    if (int status = unzGetCurrentFileInfo64(*uf, &file_info, filename, sizeof(filename), nullptr,
                                             0, nullptr, 0);
        status != UNZ_OK) {
      FX_LOGS(ERROR) << "cannot read current file info in input zip archive: " << status;
      return false;
    }

    const std::string filename_str = std::string(filename);

    if (int status = unzOpenCurrentFile(*uf); status != UNZ_OK) {
      FX_LOGS(ERROR) << fxl::Substitute("cannot open $0 in input zip archive: ", filename_str)
                     << status;
      return false;
    }

    std::vector<uint8_t> data;
    data.reserve(static_cast<size_t>(file_info.uncompressed_size));
    const size_t kBufferSize = 512;
    std::vector<uint8_t> buffer(kBufferSize);
    int num_bytes_or_status;
    do {
      num_bytes_or_status = unzReadCurrentFile(*uf, buffer.data(), kBufferSize);
      if (num_bytes_or_status < 0) {
        FX_LOGS(ERROR) << fxl::Substitute("cannot read $0 in input zip archive: ", filename_str)
                       << num_bytes_or_status;
        return false;
      } else if (num_bytes_or_status > 0) {
        data.insert(data.end(), buffer.data(), buffer.data() + num_bytes_or_status);
      }  // num_bytes_or_status == 0 means EOF
    } while (num_bytes_or_status > 0);

    if (int status = unzCloseCurrentFile(*uf); status != UNZ_OK) {
      FX_LOGS(WARNING) << fxl::Substitute("cannot close $0 in input zip archive: ", filename_str)
                       << status;
    }

    fsl::SizedVmo sized_vmo;
    if (!fsl::VmoFromVector(data, &sized_vmo)) {
      FX_LOGS(ERROR) << "cannot write output VMO for " << filename_str;
      return false;
    }
    Attachment attachment;
    attachment.key = std::move(filename_str);
    attachment.value = std::move(sized_vmo).ToTransport();
    attachments->push_back(std::move(attachment));

    if (current_file_index == num_files) {  // last file, bail out.
      break;
    }

    if (int status = unzGoToNextFile(*uf); status != UNZ_OK) {
      FX_LOGS(ERROR) << "cannot read next file in input zip archive: " << status;
      return false;
    }
  }

  return true;
}

}  // namespace

bool Unpack(const Buffer& archive, std::vector<Attachment>* attachments) {
  // We write the archive to a temporary file because minizip doesn't support unpacking an in-memory
  // archive.
  files::ScopedTempDir tmp_dir;
  std::string archive_filename;
  tmp_dir.NewTempFile(&archive_filename);

  auto data = std::make_unique<uint8_t[]>(archive.size);
  if (zx_status_t status = archive.vmo.read(data.get(), 0u, archive.size); status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "failed to read input zip archive VMO";
    return false;
  }

  if (!files::WriteFile(archive_filename, reinterpret_cast<const char*>(data.get()),
                        archive.size)) {
    FX_LOGS(ERROR) << "failed to write input zip archive VMO to temporary file";
    return false;
  }

  unzFile uf = unzOpen64(archive_filename.c_str());
  if (uf == nullptr) {
    FX_LOGS(ERROR) << "cannot open input zip archive at " << archive_filename;
    return false;
  }

  bool success = Unpack(archive, attachments, &uf);

  // We always close the archive regardless of the success status.
  if (int status = unzClose(uf); status != ZIP_OK) {
    FX_LOGS(WARNING) << "cannot close input zip archive: " << status;
  }

  return success;
}

}  // namespace feedback
