// Copyright 2026 Google LLC
//
// 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
//
//    https://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 "formats/zip/reader.h"

#include <algorithm>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/nullability.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/types/span.h"
#include "formats/zip/constants.h"
#include "riegeli/base/types.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/endian/endian_reading.h"

namespace credentio {
namespace {

// Holds information from the End of Central Directory Record (EOCD) needed to
// locate and read the central directory.
struct CentralDirectoryLocator {
  // Offset of the start of the central directory.
  uint32_t offset;
  // Total number of entries in the central directory.
  uint16_t entry_count;
};

// Reads the End of Central Directory (EOCD) record from the end of the input
// to locate the central directory.
absl::StatusOr<CentralDirectoryLocator> FindCentralDirectory(
    riegeli::Reader& input) {
  if (!input.SupportsSize() || !input.Size().has_value()) {
    return absl::InvalidArgumentError(
        "Input does not support size or size is unknown.");
  }
  int64_t file_size = *input.Size();

  if (file_size < kEocdRecordSize) {
    return absl::InvalidArgumentError("Input is too small to be a ZIP file.");
  }
  if (!input.Seek(file_size - kEocdRecordSize)) {
    return absl::InvalidArgumentError(
        "Failed to seek to the end of the input.");
  }

  CentralDirectoryLocator locator;
  std::string eocd_signature;
  if (!input.Read(kZipEndOfCentralDirectorySignature.size(), eocd_signature) ||
      eocd_signature != kZipEndOfCentralDirectorySignature) {
    return absl::InvalidArgumentError(absl::Substitute(
        "Invalid End of Central Directory record signature: $0",
        eocd_signature));
  }

  // Skip the following fields since they are not needed for locating the
  // central directory:
  //   - Number of this disk (2 bytes)
  //   - Number of the disk with the start of the central directory (2 bytes)
  //   - Total number of entries in the central directory on this disk (2 bytes)
  if (!input.Skip(6)) {
    return absl::InvalidArgumentError(
        "Failed to skip fields in the End of Central Directory record.");
  }

  // Total number of entries in the central directory (2 bytes, little-endian)
  if (!riegeli::ReadLittleEndian<uint16_t>(input, locator.entry_count)) {
    return absl::InvalidArgumentError(
        "Failed to read the total number of entries in the central directory.");
  }
  if (locator.entry_count == 0xffff) {
    return absl::UnimplementedError(
        "ZIP64 format is not supported. Central directory entry "
        "count must "
        "not be 0xffff.");
  }

  // Skip the size of the central directory (4 bytes)
  if (!input.Skip(4)) {
    return absl::InvalidArgumentError(
        "Failed to skip the size of the central directory.");
  }

  // Offset of the start of the central directory (4 bytes, little-endian)
  if (!riegeli::ReadLittleEndian<uint32_t>(input, locator.offset)) {
    return absl::InvalidArgumentError(
        "Failed to read the offset of the start of the central directory.");
  }
  if (locator.offset == 0xffffffff) {
    return absl::UnimplementedError(
        "ZIP64 format is not supported. Central Directory offset "
        "must not be "
        "0xffffffff.");
  }

  return locator;
}

// Reads the central directory entries, and extracts file header information.
absl::StatusOr<std::vector<ZipReader::FileEntry>>
ExtractFileEntriesFromCentralDirectory(riegeli::Reader& input,
                                       const CentralDirectoryLocator& locator) {
  if (!input.Seek(locator.offset) || input.pos() != locator.offset) {
    return absl::InvalidArgumentError(
        "Failed to seek to the start of the central directory.");
  }
  std::vector<ZipReader::FileEntry> file_entries;
  file_entries.reserve(locator.entry_count);

  for (int i = 0; i < locator.entry_count; ++i) {
    ZipReader::FileEntry entry;
    entry.central_directory_header_offset = input.pos();

    // Central directory signature (4 bytes)
    std::string central_directory_signature;
    if (!input.Read(kZipCentralDirectorySignature.size(),
                    central_directory_signature) ||
        central_directory_signature != kZipCentralDirectorySignature) {
      return absl::InvalidArgumentError(
          "Central directory signature not found.");
    }

    // Skip the following fields since they are not needed:
    //   - Version made by (2 bytes)
    //   - Version needed to extract (2 bytes)
    if (!input.Skip(4)) {
      return absl::InvalidArgumentError(
          "Failed to skip version fields in the central directory entry.");
    }

    // General purpose bit flag (2 bytes, little-endian)
    uint16_t general_purpose_bit_flag;
    if (!riegeli::ReadLittleEndian<uint16_t>(input, general_purpose_bit_flag)) {
      return absl::InvalidArgumentError(
          "Failed to read the general purpose bit flag.");
    }
    // Bit 3 in the general purpose bit flag indicates whether the file has a
    // data descriptor.
    entry.has_data_descriptor = general_purpose_bit_flag & 0x0008;
    entry.general_purpose_bit_flag = general_purpose_bit_flag;

    // Compression method (2 bytes, little-endian)
    if (!riegeli::ReadLittleEndian<uint16_t>(input, entry.compression_method)) {
      return absl::InvalidArgumentError(
          "Failed to read the compression method.");
    }

    // Skip the following fields since they are not needed:
    //   - Last mod file time (2 bytes)
    //   - Last mod file date (2 bytes)
    //   - CRC-32 (4 bytes)
    if (!input.Skip(8)) {
      return absl::InvalidArgumentError(
          "Failed to skip fields in the central directory entry.");
    }

    // Compressed size (4 bytes, little-endian)
    uint32_t compressed_size;
    if (!riegeli::ReadLittleEndian<uint32_t>(input, compressed_size)) {
      return absl::InvalidArgumentError("Failed to read the compressed size.");
    }
    if (compressed_size == 0xffffffff) {
      return absl::UnimplementedError(
          "ZIP64 format is not supported. Compressed size must "
          "not be "
          "0xffffffff.");
    }
    std::optional<riegeli::Position> input_size = input.Size();
    if (input_size.has_value() && compressed_size > *input_size) {
      return absl::InvalidArgumentError("Compressed size exceeds file limits.");
    }
    entry.file_range.length = compressed_size;

    // Uncompressed size (4 bytes, little-endian)
    if (!riegeli::ReadLittleEndian<uint32_t>(input, entry.uncompressed_size)) {
      return absl::InvalidArgumentError(
          "Failed to read the uncompressed size.");
    }

    // File name length (2 bytes, little-endian)
    uint16_t file_name_length;
    if (!riegeli::ReadLittleEndian<uint16_t>(input, file_name_length)) {
      return absl::InvalidArgumentError("Failed to read the file name length.");
    }

    // Extra field length (2 bytes, little-endian)
    uint16_t extra_field_length;
    if (!riegeli::ReadLittleEndian<uint16_t>(input, extra_field_length)) {
      return absl::InvalidArgumentError(
          "Failed to read the extra field length.");
    }
    entry.extra_field_length = extra_field_length;

    // File comment length (2 bytes, little-endian)
    uint16_t file_comment_length;
    if (!riegeli::ReadLittleEndian<uint16_t>(input, file_comment_length)) {
      return absl::InvalidArgumentError(
          "Failed to read the file comment length.");
    }
    entry.file_comment_length = file_comment_length;

    // Skip the following fields since they are not needed:
    //   - Disk number (2 bytes)
    //   - Internal file attributes (2 bytes)
    //   - External file attributes (4 bytes)
    if (!input.Skip(8)) {
      return absl::InvalidArgumentError(
          "Failed to skip fields in the central directory entry.");
    }

    // Local file header offset (4 bytes, little-endian)
    uint32_t local_file_header_offset;
    if (!riegeli::ReadLittleEndian<uint32_t>(input, local_file_header_offset)) {
      return absl::InvalidArgumentError(
          "Failed to read the local file header offset.");
    }
    entry.local_file_header_offset = local_file_header_offset;

    // File name (length is determined by `file_name_length`)
    if (!input.Read(file_name_length, entry.file_name)) {
      return absl::InvalidArgumentError("Failed to read the file name.");
    }

    // Skip extra field and file comment in central directory
    if (!input.Skip(extra_field_length + file_comment_length)) {
      return absl::InvalidArgumentError(
          "Failed to skip extra field and file comment in central directory.");
    }

    // The file data starts immediately after the local file header, which
    // consists of:
    //   - Fixed length fields (in total of 30 bytes)
    //   - File name (variable length)
    //   - Extra field (variable length)
    entry.file_range.offset = entry.local_file_header_offset +
                              kLocalFileHeaderFixedSize +
                              entry.file_name.size() + entry.extra_field_length;

    file_entries.push_back(entry);
  }

  // Reads and validates LFH signatures and ensures that the LFH
  // extra_field_length matches the Central Directory requirement.
  const int64_t cd_end_pos = input.pos();
  ABSL_ASSIGN_OR_RETURN(auto sorted_entries,
                        ZipReader::SortFileEntries(file_entries));

  for (const auto& entry : sorted_entries) {
    if (!input.Seek(entry.local_file_header_offset) ||
        input.pos() != entry.local_file_header_offset) {
      return absl::InvalidArgumentError(
          "Failed to seek to local file header offset.");
    }
    std::string lfh_sig;
    if (!input.Read(kZipLocalFileHeaderSignature.size(), lfh_sig) ||
        lfh_sig != kZipLocalFileHeaderSignature) {
      return absl::InvalidArgumentError("Invalid local file header signature.");
    }
    if (!input.Skip(2)) {
      return absl::InvalidArgumentError(
          "Failed to skip fields in local file header.");
    }
    uint16_t lfh_general_purpose_bit_flag;
    if (!riegeli::ReadLittleEndian<uint16_t>(input,
                                             lfh_general_purpose_bit_flag)) {
      return absl::InvalidArgumentError(
          "Failed to read general purpose bit flag from local file header.");
    }
    if ((entry.general_purpose_bit_flag & 0x0808) !=
        (lfh_general_purpose_bit_flag & 0x0808)) {
      return absl::InvalidArgumentError(
          "Local File Header bit flag does not match Central Directory.");
    }
    uint16_t lfh_compression_method;
    if (!riegeli::ReadLittleEndian<uint16_t>(input, lfh_compression_method)) {
      return absl::InvalidArgumentError(
          "Failed to read compression method from local file header.");
    }
    if (lfh_compression_method != entry.compression_method) {
      return absl::InvalidArgumentError(
          "Local File Header compression method does not match Central "
          "Directory.");
    }
    if (!input.Skip(8)) {
      return absl::InvalidArgumentError(
          "Failed to skip fields in local file header.");
    }
    uint32_t lfh_compressed_size;
    if (!riegeli::ReadLittleEndian<uint32_t>(input, lfh_compressed_size)) {
      return absl::InvalidArgumentError(
          "Failed to read compressed size from local file header.");
    }
    uint32_t lfh_uncompressed_size;
    if (!riegeli::ReadLittleEndian<uint32_t>(input, lfh_uncompressed_size)) {
      return absl::InvalidArgumentError(
          "Failed to read uncompressed size from local file header.");
    }
    if (!entry.has_data_descriptor) {
      if (lfh_compressed_size != entry.file_range.length ||
          lfh_uncompressed_size != entry.uncompressed_size) {
        return absl::InvalidArgumentError(
            "Local File Header sizes do not match Central Directory.");
      }
    } else {
      if ((lfh_compressed_size != 0 &&
           lfh_compressed_size != entry.file_range.length) ||
          (lfh_uncompressed_size != 0 &&
           lfh_uncompressed_size != entry.uncompressed_size)) {
        return absl::InvalidArgumentError(
            "Local File Header sizes do not match Central Directory.");
      }
    }
    uint16_t lfh_file_name_length;
    if (!riegeli::ReadLittleEndian<uint16_t>(input, lfh_file_name_length)) {
      return absl::InvalidArgumentError(
          "Failed to read file name length from local file header.");
    }
    if (lfh_file_name_length != entry.file_name.size()) {
      return absl::InvalidArgumentError(
          "Local File Header file name length does not match Central "
          "Directory.");
    }
    uint16_t lfh_extra_field_length;
    if (!riegeli::ReadLittleEndian<uint16_t>(input, lfh_extra_field_length)) {
      return absl::InvalidArgumentError(
          "Failed to read extra field length from local file header.");
    }
    if (lfh_extra_field_length != entry.extra_field_length) {
      return absl::InvalidArgumentError(
          "Local File Header extra field length does not match Central "
          "Directory.");
    }
  }

  if (!input.Seek(cd_end_pos) || input.pos() != cd_end_pos) {
    return absl::InvalidArgumentError(
        "Failed to seek back to central directory position.");
  }

  return sorted_entries;
}

}  // namespace

// Sorts ZIP file entries by header offset and checks that they do not have
// duplicate offsets or overlapping ranges to prevent ZIP bomb conditions.
absl::StatusOr<std::vector<ZipReader::FileEntry>> ZipReader::SortFileEntries(
    absl::Span<const ZipReader::FileEntry> file_entries) {
  std::vector<ZipReader::FileEntry> sorted_entries(file_entries.begin(),
                                                   file_entries.end());
  std::sort(sorted_entries.begin(), sorted_entries.end(),
            [](const ZipReader::FileEntry& a, const ZipReader::FileEntry& b) {
              return a.local_file_header_offset < b.local_file_header_offset;
            });

  int64_t previous_entry_end = 0;
  for (const auto& entry : sorted_entries) {
    if (entry.local_file_header_offset < previous_entry_end) {
      return absl::InvalidArgumentError(
          "Overlapping or duplicate ZIP entries detected.");
    }
    previous_entry_end = entry.file_range.offset + entry.file_range.length;
  }
  return sorted_entries;
}

absl::StatusOr<std::unique_ptr<ZipReader>> ZipReader::Create(
    riegeli::Reader* absl_nonnull input) {
  ABSL_ASSIGN_OR_RETURN(CentralDirectoryLocator locator,
                        FindCentralDirectory(*input));

  ABSL_ASSIGN_OR_RETURN(
      std::vector<FileEntry> file_entries,
      ExtractFileEntriesFromCentralDirectory(*input, locator));

  auto reader =
      absl::WrapUnique(new ZipReader(std::move(file_entries), locator.offset));
  return std::move(reader);
}

absl::StatusOr<ZipReader::FileEntry> ZipReader::Next() {
  if (!HasNext()) {
    return absl::OutOfRangeError("No more file entries to read.");
  }
  return *current_it_++;
}
}  // namespace credentio
