blob: 227d5b1b40db9cd80024265cd03e39131f26ddb2 [file] [log] [blame]
// Copyright 2016 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.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#ifndef CORE_FPDFAPI_PARSER_CPDF_DATA_AVAIL_H_
#define CORE_FPDFAPI_PARSER_CPDF_DATA_AVAIL_H_
#include <map>
#include <memory>
#include <set>
#include <utility>
#include <vector>
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_parser.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
class CPDF_CrossRefAvail;
class CPDF_Dictionary;
class CPDF_HintTables;
class CPDF_IndirectObjectHolder;
class CPDF_LinearizedHeader;
class CPDF_PageObjectAvail;
class CPDF_ReadValidator;
class CPDF_SyntaxParser;
class CPDF_DataAvail final : public Observable::ObserverIface {
public:
// Must match PDF_DATA_* definitions in public/fpdf_dataavail.h, but cannot
// #include that header. fpdfsdk/fpdf_dataavail.cpp has static_asserts
// to make sure the two sets of values match.
enum DocAvailStatus {
kDataError = -1, // PDF_DATA_ERROR
kDataNotAvailable = 0, // PDF_DATA_NOTAVAIL
kDataAvailable = 1, // PDF_DATA_AVAIL
};
// Must match PDF_*LINEAR* definitions in public/fpdf_dataavail.h, but cannot
// #include that header. fpdfsdk/fpdf_dataavail.cpp has static_asserts
// to make sure the two sets of values match.
enum DocLinearizationStatus {
kLinearizationUnknown = -1, // PDF_LINEARIZATION_UNKNOWN
kNotLinearized = 0, // PDF_NOT_LINEARIZED
kLinearized = 1, // PDF_LINEARIZED
};
// Must match PDF_FORM_* definitions in public/fpdf_dataavail.h, but cannot
// #include that header. fpdfsdk/fpdf_dataavail.cpp has static_asserts
// to make sure the two sets of values match.
enum DocFormStatus {
kFormError = -1, // PDF_FORM_ERROR
kFormNotAvailable = 0, // PDF_FORM_NOTAVAIL
kFormAvailable = 1, // PDF_FORM_AVAIL
kFormNotExist = 2, // PDF_FORM_NOTEXIST
};
class FileAvail {
public:
virtual ~FileAvail();
virtual bool IsDataAvail(FX_FILESIZE offset, size_t size) = 0;
};
class DownloadHints {
public:
virtual ~DownloadHints();
virtual void AddSegment(FX_FILESIZE offset, size_t size) = 0;
};
CPDF_DataAvail(FileAvail* pFileAvail,
const RetainPtr<IFX_SeekableReadStream>& pFileRead);
~CPDF_DataAvail() override;
// Observable::ObserverIface:
void OnObservableDestroyed() override;
DocAvailStatus IsDocAvail(DownloadHints* pHints);
DocAvailStatus IsPageAvail(uint32_t dwPage, DownloadHints* pHints);
DocFormStatus IsFormAvail(DownloadHints* pHints);
DocLinearizationStatus IsLinearizedPDF();
int GetPageCount() const;
CPDF_Dictionary* GetPageDictionary(int index) const;
RetainPtr<CPDF_ReadValidator> GetValidator() const;
std::pair<CPDF_Parser::Error, std::unique_ptr<CPDF_Document>> ParseDocument(
std::unique_ptr<CPDF_Document::RenderDataIface> pRenderData,
std::unique_ptr<CPDF_Document::PageDataIface> pPageData,
const ByteString& password);
const CPDF_HintTables* GetHintTables() const { return m_pHintTables.get(); }
private:
enum class InternalStatus : uint8_t {
kHeader = 0,
kFirstPage,
kHintTable,
kLoadAllCrossRef,
kRoot,
kInfo,
kPageTree,
kPage,
kPageLaterLoad,
kResources,
kDone,
kError,
kLoadAllFile,
};
class PageNode {
public:
enum class Type { kUnknown = 0, kPage, kPages, kArray };
PageNode();
~PageNode();
Type m_type = Type::kUnknown;
uint32_t m_dwPageNo = 0;
std::vector<std::unique_ptr<PageNode>> m_ChildNodes;
};
static constexpr int kMaxPageRecursionDepth = 1024;
bool CheckDocStatus();
bool CheckHeader();
bool CheckFirstPage();
bool CheckHintTables();
bool CheckRoot();
bool CheckInfo();
bool CheckPages();
bool CheckPage();
DocAvailStatus CheckResources(CPDF_Dictionary* page);
DocFormStatus CheckAcroForm();
bool CheckPageStatus();
DocAvailStatus CheckHeaderAndLinearized();
RetainPtr<CPDF_Object> ParseIndirectObjectAt(
FX_FILESIZE pos,
uint32_t objnum,
CPDF_IndirectObjectHolder* pObjList) const;
RetainPtr<CPDF_Object> GetObject(uint32_t objnum, bool* pExistInFile);
bool GetPageKids(CPDF_Object* pPages);
bool PreparePageItem();
bool LoadPages();
bool CheckAndLoadAllXref();
bool LoadAllFile();
DocAvailStatus CheckLinearizedData();
bool CheckPage(uint32_t dwPage);
bool LoadDocPages();
bool LoadDocPage(uint32_t dwPage);
bool CheckPageNode(const PageNode& pageNode,
int32_t iPage,
int32_t& iCount,
int level);
bool CheckUnknownPageNode(uint32_t dwPageNo, PageNode* pPageNode);
bool CheckArrayPageNode(uint32_t dwPageNo, PageNode* pPageNode);
bool CheckPageCount();
bool IsFirstCheck(uint32_t dwPage);
void ResetFirstCheck(uint32_t dwPage);
bool ValidatePage(uint32_t dwPage) const;
CPDF_SyntaxParser* GetSyntaxParser() const;
RetainPtr<CPDF_ReadValidator> m_pFileRead;
CPDF_Parser m_parser;
RetainPtr<CPDF_Dictionary> m_pRoot;
std::unique_ptr<CPDF_LinearizedHeader> m_pLinearized;
bool m_bDocAvail = false;
InternalStatus m_internalStatus = InternalStatus::kHeader;
std::unique_ptr<CPDF_CrossRefAvail> m_pCrossRefAvail;
const FX_FILESIZE m_dwFileLen;
UnownedPtr<CPDF_Document> m_pDocument;
std::vector<uint32_t> m_PageObjList;
std::set<uint32_t> m_SeenPageObjList;
uint32_t m_PagesObjNum = 0;
bool m_bLinearedDataOK = false;
bool m_bMainXRefLoadTried = false;
bool m_bMainXRefLoadedOK = false;
bool m_bPagesTreeLoad = false;
bool m_bPagesLoad = false;
std::unique_ptr<CPDF_PageObjectAvail> m_pFormAvail;
std::vector<RetainPtr<CPDF_Object>> m_PagesArray;
bool m_bTotalLoadPageTree = false;
bool m_bCurPageDictLoadOK = false;
PageNode m_PageNode;
std::set<uint32_t> m_pageMapCheckState;
std::set<uint32_t> m_pagesLoadState;
std::unique_ptr<CPDF_HintTables> m_pHintTables;
std::map<uint32_t, std::unique_ptr<CPDF_PageObjectAvail>> m_PagesObjAvail;
std::map<const CPDF_Object*, std::unique_ptr<CPDF_PageObjectAvail>>
m_PagesResourcesAvail;
bool m_bHeaderAvail = false;
};
#endif // CORE_FPDFAPI_PARSER_CPDF_DATA_AVAIL_H_