// Copyright 2016 The Bazel Authors. All rights reserved.
//
// 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 "src/tools/singlejar/input_jar.h"

bool InputJar::Open(const std::string &path) {
  if (!path_.empty()) {
    diag_errx(1, "%s:%d: This instance is already handling %s\n", __FILE__,
              __LINE__, path_.c_str());
  }
  if (!mapped_file_.Open(path)) {
    diag_warn("%s:%d: Cannot open input jar %s", __FILE__, __LINE__,
              path.c_str());
    mapped_file_.Close();
    return false;
  }
  if (mapped_file_.size() < sizeof(ECD)) {
    diag_warnx(
        "%s:%d: %s is only 0x%lx"
        " bytes long, should be at least 0x%lx bytes long",
        __FILE__, __LINE__, path.c_str(), mapped_file_.size(), sizeof(ECD));
    mapped_file_.Close();
    return false;
  }

  // Now locate End of Central Directory (ECD) record.
  auto ecd_min = mapped_file_.end() - 65536 - sizeof(ECD);
  if (ecd_min < mapped_file_.start()) {
    ecd_min = mapped_file_.start();
  }

  const ECD *ecd = nullptr;
  for (auto ecd_ptr = mapped_file_.end() - sizeof(ECD); ecd_ptr >= ecd_min;
       --ecd_ptr) {
    if (reinterpret_cast<const ECD *>(ecd_ptr)->is()) {
      ecd = reinterpret_cast<const ECD *>(ecd_ptr);
      break;
    }
  }
  if (ecd == nullptr) {
    diag_warnx("%s:%d: Cannot locate  ECD record in %s", __FILE__, __LINE__,
               path.c_str());
    mapped_file_.Close();
    return false;
  }

  /* Find Central Directory and preamble size. We want to handle the case
   * where a Jar/Zip file contains a preamble (an arbitrary data before the
   * first entry) and 'zip -A' was not called to adjust the offsets, so all
   * the offsets are off by the preamble size. In the 32-bit case (that is,
   * there is no ECD64Locator+ECD64), ECD immediately follows the last CDH,
   * ECD immediately follows the Central Directory, and contains its size, so
   * Central Directory can be found reliably. We then use its stated location,
   * which ECD contains, too, to calculate the preamble size.  In the 64-bit
   * case, there are ECD64 and ECD64Locator records between the end of the
   * Central Directory and the ECD, the calculation is similar, with the
   * exception of the logic to find the actual start of the ECD64.
   * ECD64Locator contains only its position in the file, which is off by
   * preamble size, but does not contain the actual size of ECD64, which in
   * theory is variable (the fixed fields may be followed by some custom data,
   * with the total size saved in ECD64::remaining_size and thus unavailable
   * until we find ECD64.  We assume that the custom data is missing.
   */

  // First, sanity checks.
  uint32_t cen_position = ecd->cen_offset32();
  if (!ziph::zfield_has_ext64(cen_position)) {
    if (!mapped_file_.mapped(mapped_file_.address(cen_position))) {
      diag_warnx("%s:%d: %s is corrupt: Central Directory location 0x%" PRIx32
                 " is invalid",
                 __FILE__, __LINE__, path.c_str(), cen_position);
      mapped_file_.Close();
      return false;
    }
    if (mapped_file_.offset(ecd) < cen_position) {
      diag_warnx("%s:%d: %s is corrupt: End of Central Directory at 0x%" PRIx64
                 " precedes Central Directory at 0x%" PRIx32,
                 __FILE__, __LINE__, path.c_str(), mapped_file_.offset(ecd),
                 cen_position);
      mapped_file_.Close();
      return false;
    }
  }
  uint32_t cen_size = ecd->cen_size32();
  if (!ziph::zfield_has_ext64(cen_size)) {
    if (cen_size > mapped_file_.offset(ecd)) {
      diag_warnx("%s:%d: %s is corrupt: Central Directory size 0x%" PRIx32
                 " is too large",
                 __FILE__, __LINE__, path.c_str(), cen_size);
      mapped_file_.Close();
      return false;
    }
  }
  if (cen_size == 0) {
    // Empty archive, let cdh_ point to End of Central Directory.
    cdh_ = reinterpret_cast<const CDH *>(ecd);
    preamble_size_ = mapped_file_.offset(cdh_) - cen_position;
  } else {
    auto ecd64loc = reinterpret_cast<const ECD64Locator *>(
        ziph::byte_ptr(ecd) - sizeof(ECD64Locator));
    if (ecd64loc->is()) {
      auto ecd64 = reinterpret_cast<const ECD64 *>(ziph::byte_ptr(ecd64loc) -
                                                   sizeof(ECD64));
      if (!ecd64->is()) {
        diag_warnx(
            "%s:%d: %s is corrupt, expected ECD64 record at offset 0x%" PRIx64
            " is missing",
            __FILE__, __LINE__, path.c_str(), mapped_file_.offset(ecd64));
        mapped_file_.Close();
        return false;
      }
      cdh_ = reinterpret_cast<const CDH *>(ziph::byte_ptr(ecd64) -
                                           ecd64->cen_size());
      preamble_size_ = mapped_file_.offset(cdh_) - ecd64->cen_offset();
      // Find CEN and preamble size.
    } else {
      if (ziph::zfield_has_ext64(cen_size) ||
          ziph::zfield_has_ext64(cen_position)) {
        diag_warnx(
            "%s:%d: %s is corrupt, expected ECD64 locator record at "
            "offset 0x%" PRIx64 " is missing",
            __FILE__, __LINE__, path.c_str(), mapped_file_.offset(ecd64loc));
        return false;
      }
      cdh_ = reinterpret_cast<const CDH *>(ziph::byte_ptr(ecd) - cen_size);
      preamble_size_ = mapped_file_.offset(cdh_) - cen_position;
    }
    if (!cdh_->is()) {
      diag_warnx(
          "%s:%d: In %s, expected central file header signature at "
          "offset0x%" PRIx64,
          __FILE__, __LINE__, path.c_str(), mapped_file_.offset(cdh_));
      mapped_file_.Close();
      return false;
    }
  }
  path_ = path;
  return true;
}

bool InputJar::Close() {
  mapped_file_.Close();
  path_.clear();
  return true;
}
