// Copyright 2017 PDFium 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 "core/fpdfapi/parser/cpdf_cross_ref_avail.h"

#include <algorithm>
#include <memory>

#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_read_validator.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_syntax_parser.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"

namespace {

constexpr char kCrossRefKeyword[] = "xref";
constexpr char kTrailerKeyword[] = "trailer";
constexpr char kPrevCrossRefFieldKey[] = "Prev";
constexpr char kTypeFieldKey[] = "Type";
constexpr char kPrevCrossRefStreamOffsetFieldKey[] = "XRefStm";
constexpr char kXRefKeyword[] = "XRef";
constexpr char kEncryptKey[] = "Encrypt";

}  // namespace

CPDF_CrossRefAvail::CPDF_CrossRefAvail(CPDF_SyntaxParser* parser,
                                       FX_FILESIZE last_crossref_offset)
    : parser_(parser), last_crossref_offset_(last_crossref_offset) {
  ASSERT(parser_);
  AddCrossRefForCheck(last_crossref_offset);
}

CPDF_CrossRefAvail::~CPDF_CrossRefAvail() = default;

CPDF_DataAvail::DocAvailStatus CPDF_CrossRefAvail::CheckAvail() {
  if (current_status_ == CPDF_DataAvail::DataAvailable)
    return CPDF_DataAvail::DataAvailable;

  const CPDF_ReadValidator::Session read_session(GetValidator());
  while (true) {
    bool check_result = false;
    switch (current_state_) {
      case State::kCrossRefCheck:
        check_result = CheckCrossRef();
        break;
      case State::kCrossRefV4ItemCheck:
        check_result = CheckCrossRefV4Item();
        break;
      case State::kCrossRefV4TrailerCheck:
        check_result = CheckCrossRefV4Trailer();
        break;
      case State::kDone:
        break;
      default: {
        current_status_ = CPDF_DataAvail::DataError;
        NOTREACHED();
        break;
      }
    }
    if (!check_result)
      break;

    ASSERT(!GetValidator()->has_read_problems());
  }
  return current_status_;
}

bool CPDF_CrossRefAvail::CheckReadProblems() {
  if (GetValidator()->read_error()) {
    current_status_ = CPDF_DataAvail::DataError;
    return true;
  }
  return GetValidator()->has_unavailable_data();
}

bool CPDF_CrossRefAvail::CheckCrossRef() {
  if (cross_refs_for_check_.empty()) {
    // All cross refs were checked.
    current_state_ = State::kDone;
    current_status_ = CPDF_DataAvail::DataAvailable;
    return true;
  }
  parser_->SetPos(cross_refs_for_check_.front());

  const ByteString first_word = parser_->PeekNextWord(nullptr);
  if (CheckReadProblems())
    return false;

  const bool result = (first_word == kCrossRefKeyword) ? CheckCrossRefV4()
                                                       : CheckCrossRefStream();

  if (result)
    cross_refs_for_check_.pop();

  return result;
}

bool CPDF_CrossRefAvail::CheckCrossRefV4() {
  const ByteString keyword = parser_->GetKeyword();
  if (CheckReadProblems())
    return false;

  if (keyword != kCrossRefKeyword) {
    current_status_ = CPDF_DataAvail::DataError;
    return false;
  }

  current_state_ = State::kCrossRefV4ItemCheck;
  current_offset_ = parser_->GetPos();
  return true;
}

bool CPDF_CrossRefAvail::CheckCrossRefV4Item() {
  parser_->SetPos(current_offset_);
  const ByteString keyword = parser_->GetKeyword();
  if (CheckReadProblems())
    return false;

  if (keyword.IsEmpty()) {
    current_status_ = CPDF_DataAvail::DataError;
    return false;
  }

  if (keyword == kTrailerKeyword)
    current_state_ = State::kCrossRefV4TrailerCheck;

  // Go to next item.
  current_offset_ = parser_->GetPos();
  return true;
}

bool CPDF_CrossRefAvail::CheckCrossRefV4Trailer() {
  parser_->SetPos(current_offset_);

  RetainPtr<CPDF_Dictionary> trailer =
      ToDictionary(parser_->GetObjectBody(nullptr));
  if (CheckReadProblems())
    return false;

  if (!trailer) {
    current_status_ = CPDF_DataAvail::DataError;
    return false;
  }

  if (ToReference(trailer->GetObjectFor(kEncryptKey))) {
    current_status_ = CPDF_DataAvail::DataError;
    return false;
  }

  const int32_t xrefpos =
      GetDirectInteger(trailer.Get(), kPrevCrossRefFieldKey);
  if (xrefpos &&
      pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(xrefpos))
    AddCrossRefForCheck(static_cast<FX_FILESIZE>(xrefpos));

  const int32_t stream_xref_offset =
      GetDirectInteger(trailer.Get(), kPrevCrossRefStreamOffsetFieldKey);
  if (stream_xref_offset &&
      pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(
          stream_xref_offset))
    AddCrossRefForCheck(static_cast<FX_FILESIZE>(stream_xref_offset));

  // Goto check next crossref
  current_state_ = State::kCrossRefCheck;
  return true;
}

bool CPDF_CrossRefAvail::CheckCrossRefStream() {
  auto cross_ref =
      parser_->GetIndirectObject(nullptr, CPDF_SyntaxParser::ParseType::kLoose);
  if (CheckReadProblems())
    return false;

  const CPDF_Dictionary* trailer =
      cross_ref && cross_ref->IsStream() ? cross_ref->GetDict() : nullptr;
  if (!trailer) {
    current_status_ = CPDF_DataAvail::DataError;
    return false;
  }

  if (ToReference(trailer->GetObjectFor(kEncryptKey))) {
    current_status_ = CPDF_DataAvail::DataError;
    return false;
  }

  if (trailer->GetNameFor(kTypeFieldKey) == kXRefKeyword) {
    const int32_t xrefpos = trailer->GetIntegerFor(kPrevCrossRefFieldKey);
    if (xrefpos &&
        pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(xrefpos)) {
      AddCrossRefForCheck(static_cast<FX_FILESIZE>(xrefpos));
    }
  }
  // Goto check next crossref
  current_state_ = State::kCrossRefCheck;
  return true;
}

void CPDF_CrossRefAvail::AddCrossRefForCheck(FX_FILESIZE crossref_offset) {
  if (registered_crossrefs_.count(crossref_offset))
    return;

  cross_refs_for_check_.push(crossref_offset);
  registered_crossrefs_.insert(crossref_offset);
}

RetainPtr<CPDF_ReadValidator> CPDF_CrossRefAvail::GetValidator() {
  return parser_->GetValidator();
}
