// 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 "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"
#include "third_party/base/numerics/safe_conversions.h"
#include "third_party/base/stl_util.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 (status_ == CPDF_DataAvail::DataAvailable)
    return CPDF_DataAvail::DataAvailable;

  const CPDF_ReadValidator::Session read_session(GetValidator());
  while (true) {
    bool check_result = false;
    switch (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: {
        status_ = CPDF_DataAvail::DataError;
        NOTREACHED();
        break;
      }
    }
    if (!check_result)
      break;

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

bool CPDF_CrossRefAvail::CheckReadProblems() {
  if (GetValidator()->read_error()) {
    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.
    state_ = State::kDone;
    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) {
    status_ = CPDF_DataAvail::DataError;
    return false;
  }

  state_ = State::kCrossRefV4ItemCheck;
  offset_ = parser_->GetPos();
  return true;
}

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

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

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

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

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

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

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

  if (ToReference(trailer->GetObjectFor(kEncryptKey))) {
    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
  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) {
    status_ = CPDF_DataAvail::DataError;
    return false;
  }

  if (ToReference(trailer->GetObjectFor(kEncryptKey))) {
    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
  state_ = State::kCrossRefCheck;
  return true;
}

void CPDF_CrossRefAvail::AddCrossRefForCheck(FX_FILESIZE crossref_offset) {
  if (pdfium::Contains(registered_crossrefs_, crossref_offset))
    return;

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

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