| Index: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| index 4ce196e90d0f9b09a116cba7e9cf05843cb41df2..93212e77c1039f819c02509a0a896bd1314df664 100644
|
| --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| @@ -15,6 +15,7 @@
|
| #include "../../../include/fpdfapi/fpdf_parser.h"
|
| #include "../../../include/fxcrt/fx_safe_types.h"
|
| #include "../fpdf_page/pageint.h"
|
| +#include "parser_int.h"
|
|
|
| namespace {
|
|
|
| @@ -2679,22 +2680,28 @@ void CPDF_SyntaxParser::GetBinary(uint8_t* buffer, FX_DWORD size) {
|
|
|
| class CPDF_DataAvail final : public IPDF_DataAvail {
|
| public:
|
| - CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead);
|
| + CPDF_DataAvail(IFX_FileAvail* pFileAvail,
|
| + IFX_FileRead* pFileRead,
|
| + FX_BOOL bSupportHintTable);
|
| ~CPDF_DataAvail() override;
|
|
|
| - FX_BOOL IsDocAvail(IFX_DownloadHints* pHints) override;
|
| + int IsDocAvail(IFX_DownloadHints* pHints) override;
|
|
|
| void SetDocument(CPDF_Document* pDoc) override;
|
|
|
| - FX_BOOL IsPageAvail(int iPage, IFX_DownloadHints* pHints) override;
|
| + int IsPageAvail(int iPage, IFX_DownloadHints* pHints) override;
|
|
|
| - int32_t IsFormAvail(IFX_DownloadHints* pHints) override;
|
| + int IsFormAvail(IFX_DownloadHints* pHints) override;
|
|
|
| - int32_t IsLinearizedPDF() override;
|
| + int IsLinearizedPDF() override;
|
|
|
| FX_BOOL IsLinearized() override { return m_bLinearized; }
|
|
|
| void GetLinearizedMainXRefInfo(FX_FILESIZE* pPos, FX_DWORD* pSize) override;
|
| + int GetPageCount() const;
|
| + CPDF_Dictionary* GetPage(int index);
|
| +
|
| + friend class CPDF_HintTables;
|
|
|
| protected:
|
| static const int kMaxDataAvailRecursionDepth = 64;
|
| @@ -2709,6 +2716,7 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
|
| FX_BOOL CheckDocStatus(IFX_DownloadHints* pHints);
|
| FX_BOOL CheckHeader(IFX_DownloadHints* pHints);
|
| FX_BOOL CheckFirstPage(IFX_DownloadHints* pHints);
|
| + FX_BOOL CheckHintTables(IFX_DownloadHints* pHints);
|
| FX_BOOL CheckEnd(IFX_DownloadHints* pHints);
|
| FX_BOOL CheckCrossRef(IFX_DownloadHints* pHints);
|
| FX_BOOL CheckCrossRefItem(IFX_DownloadHints* pHints);
|
| @@ -2731,7 +2739,9 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
|
| void SetStartOffset(FX_FILESIZE dwOffset);
|
| FX_BOOL GetNextToken(CFX_ByteString& token);
|
| FX_BOOL GetNextChar(uint8_t& ch);
|
| - CPDF_Object* ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD objnum);
|
| + CPDF_Object* ParseIndirectObjectAt(FX_FILESIZE pos,
|
| + FX_DWORD objnum,
|
| + CPDF_IndirectObjects* pObjList = NULL);
|
| CPDF_Object* GetObject(FX_DWORD objnum,
|
| IFX_DownloadHints* pHints,
|
| FX_BOOL* pExistInFile);
|
| @@ -2740,7 +2750,7 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
|
| FX_BOOL LoadPages(IFX_DownloadHints* pHints);
|
| FX_BOOL LoadAllXref(IFX_DownloadHints* pHints);
|
| FX_BOOL LoadAllFile(IFX_DownloadHints* pHints);
|
| - FX_BOOL CheckLinearizedData(IFX_DownloadHints* pHints);
|
| + int32_t CheckLinearizedData(IFX_DownloadHints* pHints);
|
| FX_BOOL CheckFileResources(IFX_DownloadHints* pHints);
|
| FX_BOOL CheckPageAnnots(int iPage, IFX_DownloadHints* pHints);
|
|
|
| @@ -2763,6 +2773,9 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
|
| FX_BOOL CheckPageCount(IFX_DownloadHints* pHints);
|
| FX_BOOL IsFirstCheck(int iPage);
|
| void ResetFirstCheck(int iPage);
|
| + FX_BOOL IsDataAvail(FX_FILESIZE offset,
|
| + FX_DWORD size,
|
| + IFX_DownloadHints* pHints);
|
|
|
| CPDF_Parser m_parser;
|
|
|
| @@ -2876,6 +2889,9 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
|
|
|
| std::set<FX_DWORD> m_pageMapCheckState;
|
| std::set<FX_DWORD> m_pagesLoadState;
|
| +
|
| + nonstd::unique_ptr<CPDF_HintTables> m_pHintTables;
|
| + FX_BOOL m_bSupportHintTable;
|
| };
|
|
|
| IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail,
|
| @@ -2885,14 +2901,15 @@ IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail,
|
| // static
|
| IPDF_DataAvail* IPDF_DataAvail::Create(IFX_FileAvail* pFileAvail,
|
| IFX_FileRead* pFileRead) {
|
| - return new CPDF_DataAvail(pFileAvail, pFileRead);
|
| + return new CPDF_DataAvail(pFileAvail, pFileRead, TRUE);
|
| }
|
|
|
| // static
|
| int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0;
|
|
|
| CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail,
|
| - IFX_FileRead* pFileRead)
|
| + IFX_FileRead* pFileRead,
|
| + FX_BOOL bSupportHintTable)
|
| : IPDF_DataAvail(pFileAvail, pFileRead) {
|
| m_Pos = 0;
|
| m_dwFileLen = 0;
|
| @@ -2938,6 +2955,7 @@ CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail,
|
| m_bTotalLoadPageTree = FALSE;
|
| m_bCurPageDictLoadOK = FALSE;
|
| m_bLinearedDataOK = FALSE;
|
| + m_bSupportHintTable = bSupportHintTable;
|
| }
|
| CPDF_DataAvail::~CPDF_DataAvail() {
|
| if (m_pLinearized) {
|
| @@ -2949,9 +2967,9 @@ CPDF_DataAvail::~CPDF_DataAvail() {
|
| if (m_pTrailer) {
|
| m_pTrailer->Release();
|
| }
|
| - int32_t i = 0;
|
| - int32_t iSize = m_arrayAcroforms.GetSize();
|
| - for (i = 0; i < iSize; ++i) {
|
| +
|
| + int iSize = m_arrayAcroforms.GetSize();
|
| + for (int i = 0; i < iSize; ++i) {
|
| static_cast<CPDF_Object*>(m_arrayAcroforms.GetAt(i))->Release();
|
| }
|
| }
|
| @@ -3033,28 +3051,11 @@ FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array,
|
| CPDF_Reference* pRef = pObj->AsReference();
|
| FX_DWORD dwNum = pRef->GetRefObjNum();
|
| FX_FILESIZE offset;
|
| - FX_DWORD original_size = GetObjectSize(dwNum, offset);
|
| - pdfium::base::CheckedNumeric<FX_DWORD> size = original_size;
|
| - if (size.ValueOrDefault(0) == 0 || offset < 0 ||
|
| - offset >= m_dwFileLen) {
|
| - break;
|
| - }
|
| -
|
| - size += offset;
|
| - size += 512;
|
| - if (!size.IsValid()) {
|
| - break;
|
| - }
|
| - if (size.ValueOrDie() > m_dwFileLen) {
|
| - size = m_dwFileLen - offset;
|
| - } else {
|
| - size = original_size + 512;
|
| - }
|
| - if (!size.IsValid()) {
|
| + FX_DWORD size = GetObjectSize(dwNum, offset);
|
| + if (size == 0 || offset < 0 || offset >= m_dwFileLen) {
|
| break;
|
| }
|
| - if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
|
| - pHints->AddSegment(offset, size.ValueOrDie());
|
| + if (!IsDataAvail(offset, size, pHints)) {
|
| ret_array.Add(pObj);
|
| count++;
|
| } else if (!m_objnum_array.Find(dwNum)) {
|
| @@ -3086,19 +3087,19 @@ FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array,
|
| obj_array.Append(new_obj_array);
|
| return IsObjectsAvail(obj_array, FALSE, pHints, ret_array);
|
| }
|
| -FX_BOOL CPDF_DataAvail::IsDocAvail(IFX_DownloadHints* pHints) {
|
| +int CPDF_DataAvail::IsDocAvail(IFX_DownloadHints* pHints) {
|
| if (!m_dwFileLen && m_pFileRead) {
|
| m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
|
| if (!m_dwFileLen) {
|
| - return TRUE;
|
| + return PDF_DATA_ERROR;
|
| }
|
| }
|
| while (!m_bDocAvail) {
|
| if (!CheckDocStatus(pHints)) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| }
|
| - return TRUE;
|
| + return PDF_DATA_AVAIL;
|
| }
|
| FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints) {
|
| if (!m_objs_array.GetSize()) {
|
| @@ -3151,6 +3152,8 @@ FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints* pHints) {
|
| case PDF_DATAAVAIL_FIRSTPAGE:
|
| case PDF_DATAAVAIL_FIRSTPAGE_PREPARE:
|
| return CheckFirstPage(pHints);
|
| + case PDF_DATAAVAIL_HINTTABLE:
|
| + return CheckHintTables(pHints);
|
| case PDF_DATAAVAIL_END:
|
| return CheckEnd(pHints);
|
| case PDF_DATAAVAIL_CROSSREF:
|
| @@ -3235,53 +3238,24 @@ FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints) {
|
| CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum,
|
| IFX_DownloadHints* pHints,
|
| FX_BOOL* pExistInFile) {
|
| - CPDF_Object* pRet = NULL;
|
| - FX_DWORD original_size = 0;
|
| + CPDF_Object* pRet = nullptr;
|
| + FX_DWORD size = 0;
|
| FX_FILESIZE offset = 0;
|
| - CPDF_Parser* pParser = NULL;
|
| -
|
| - if (pExistInFile) {
|
| + CPDF_Parser* pParser = nullptr;
|
| + if (pExistInFile)
|
| *pExistInFile = TRUE;
|
| - }
|
|
|
| if (m_pDocument == NULL) {
|
| - original_size = (FX_DWORD)m_parser.GetObjectSize(objnum);
|
| + size = (FX_DWORD)m_parser.GetObjectSize(objnum);
|
| offset = m_parser.GetObjectOffset(objnum);
|
| pParser = &m_parser;
|
| } else {
|
| - original_size = GetObjectSize(objnum, offset);
|
| + size = GetObjectSize(objnum, offset);
|
| pParser = (CPDF_Parser*)(m_pDocument->GetParser());
|
| }
|
| -
|
| - pdfium::base::CheckedNumeric<FX_DWORD> size = original_size;
|
| - if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) {
|
| - if (pExistInFile)
|
| - *pExistInFile = FALSE;
|
| -
|
| - return NULL;
|
| - }
|
| -
|
| - size += offset;
|
| - size += 512;
|
| - if (!size.IsValid()) {
|
| - return NULL;
|
| - }
|
| -
|
| - if (size.ValueOrDie() > m_dwFileLen) {
|
| - size = m_dwFileLen - offset;
|
| - } else {
|
| - size = original_size + 512;
|
| - }
|
| -
|
| - if (!size.IsValid()) {
|
| - return NULL;
|
| - }
|
| -
|
| - if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
|
| - pHints->AddSegment(offset, size.ValueOrDie());
|
| - return NULL;
|
| + if (!IsDataAvail(offset, size, pHints)) {
|
| + return nullptr;
|
| }
|
| -
|
| if (pParser) {
|
| pRet = pParser->ParseIndirectObject(NULL, objnum, NULL);
|
| }
|
| @@ -3576,15 +3550,82 @@ FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints* pHints) {
|
| } else {
|
| m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
|
| }
|
| - if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
|
| + if (bNeedDownLoad || m_docStatus != PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
|
| + m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
|
| + return FALSE;
|
| + }
|
| + m_docStatus =
|
| + m_bSupportHintTable ? PDF_DATAAVAIL_HINTTABLE : PDF_DATAAVAIL_DONE;
|
| + return TRUE;
|
| +}
|
| +FX_BOOL CPDF_DataAvail::IsDataAvail(FX_FILESIZE offset,
|
| + FX_DWORD size,
|
| + IFX_DownloadHints* pHints) {
|
| + if (offset > m_dwFileLen)
|
| + return TRUE;
|
| + FX_SAFE_DWORD safeSize = pdfium::base::checked_cast<FX_DWORD>(offset);
|
| + safeSize += size;
|
| + safeSize += 512;
|
| + if (!safeSize.IsValid() || safeSize.ValueOrDie() > m_dwFileLen)
|
| + size = m_dwFileLen - offset;
|
| + else
|
| + size += 512;
|
| + if (!m_pFileAvail->IsDataAvail(offset, size)) {
|
| + pHints->AddSegment(offset, size);
|
| + return FALSE;
|
| + }
|
| + return TRUE;
|
| +}
|
| +FX_BOOL CPDF_DataAvail::CheckHintTables(IFX_DownloadHints* pHints) {
|
| + CPDF_Dictionary* pDict = m_pLinearized->GetDict();
|
| + if (!pDict) {
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + return FALSE;
|
| + }
|
| + if (!pDict->KeyExist(FX_BSTRC("H")) || !pDict->KeyExist(FX_BSTRC("O")) ||
|
| + !pDict->KeyExist(FX_BSTRC("N"))) {
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + return FALSE;
|
| + }
|
| + int nPageCount = pDict->GetElementValue(FX_BSTRC("N"))->GetInteger();
|
| + if (nPageCount <= 1) {
|
| m_docStatus = PDF_DATAAVAIL_DONE;
|
| return TRUE;
|
| }
|
| - m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
|
| - return FALSE;
|
| + CPDF_Array* pHintStreamRange = pDict->GetArray(FX_BSTRC("H"));
|
| + FX_FILESIZE szHSStart =
|
| + pHintStreamRange->GetElementValue(0)
|
| + ? pHintStreamRange->GetElementValue(0)->GetInteger()
|
| + : 0;
|
| + FX_FILESIZE szHSLength =
|
| + pHintStreamRange->GetElementValue(1)
|
| + ? pHintStreamRange->GetElementValue(1)->GetInteger()
|
| + : 0;
|
| + if (szHSStart < 0 || szHSLength <= 0) {
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + return FALSE;
|
| + }
|
| + if (!IsDataAvail(szHSStart, szHSLength, pHints)) {
|
| + return FALSE;
|
| + }
|
| + m_syntaxParser.InitParser(m_pFileRead, m_dwHeaderOffset);
|
| + nonstd::unique_ptr<CPDF_HintTables> pHintTables(
|
| + new CPDF_HintTables(this, pDict));
|
| + CPDF_Stream* pHintStream = (CPDF_Stream*)ParseIndirectObjectAt(szHSStart, 0);
|
| + FX_BOOL bLoaded = FALSE;
|
| + if (pHintTables && pHintStream && pHintStream->GetType() == PDFOBJ_STREAM) {
|
| + bLoaded = pHintTables->LoadHintStream(pHintStream);
|
| + }
|
| + if (!bLoaded) {
|
| + m_pHintTables.reset(pHintTables.release());
|
| + }
|
| + m_docStatus = PDF_DATAAVAIL_DONE;
|
| + return TRUE;
|
| }
|
| -CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos,
|
| - FX_DWORD objnum) {
|
| +CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(
|
| + FX_FILESIZE pos,
|
| + FX_DWORD objnum,
|
| + CPDF_IndirectObjects* pObjList) {
|
| FX_FILESIZE SavedPos = m_syntaxParser.SavePos();
|
| m_syntaxParser.RestorePos(pos);
|
| FX_BOOL bIsNumber;
|
| @@ -3605,26 +3646,27 @@ CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos,
|
| m_syntaxParser.RestorePos(SavedPos);
|
| return NULL;
|
| }
|
| - CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0);
|
| + CPDF_Object* pObj =
|
| + m_syntaxParser.GetObject(pObjList, parser_objnum, gennum, 0);
|
| m_syntaxParser.RestorePos(SavedPos);
|
| return pObj;
|
| }
|
| -int32_t CPDF_DataAvail::IsLinearizedPDF() {
|
| +int CPDF_DataAvail::IsLinearizedPDF() {
|
| FX_DWORD req_size = 1024;
|
| if (!m_pFileAvail->IsDataAvail(0, req_size)) {
|
| - return PDF_UNKNOW_LINEARIZED;
|
| + return PDF_LINEARIZATION_UNKNOWN;
|
| }
|
| if (!m_pFileRead) {
|
| return PDF_NOT_LINEARIZED;
|
| }
|
| FX_FILESIZE dwSize = m_pFileRead->GetSize();
|
| if (dwSize < (FX_FILESIZE)req_size) {
|
| - return PDF_UNKNOW_LINEARIZED;
|
| + return PDF_LINEARIZATION_UNKNOWN;
|
| }
|
| uint8_t buffer[1024];
|
| m_pFileRead->ReadBlock(buffer, 0, req_size);
|
| if (IsLinearizedFile(buffer, req_size)) {
|
| - return PDF_IS_LINEARIZED;
|
| + return PDF_LINEARIZED;
|
| }
|
| return PDF_NOT_LINEARIZED;
|
| }
|
| @@ -4241,36 +4283,35 @@ FX_BOOL CPDF_DataAvail::LoadPages(IFX_DownloadHints* pHints) {
|
| m_pDocument->LoadPages();
|
| return FALSE;
|
| }
|
| -FX_BOOL CPDF_DataAvail::CheckLinearizedData(IFX_DownloadHints* pHints) {
|
| +int CPDF_DataAvail::CheckLinearizedData(IFX_DownloadHints* pHints) {
|
| if (m_bLinearedDataOK) {
|
| - return TRUE;
|
| + return PDF_DATA_AVAIL;
|
| }
|
|
|
| if (!m_bMainXRefLoadTried) {
|
| FX_SAFE_DWORD data_size = m_dwFileLen;
|
| data_size -= m_dwLastXRefOffset;
|
| if (!data_size.IsValid()) {
|
| - return FALSE;
|
| + return PDF_DATA_ERROR;
|
| }
|
| if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset,
|
| data_size.ValueOrDie())) {
|
| pHints->AddSegment(m_dwLastXRefOffset, data_size.ValueOrDie());
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| - FX_DWORD dwRet =
|
| - ((CPDF_Parser*)m_pDocument->GetParser())->LoadLinearizedMainXRefTable();
|
| + FX_DWORD dwRet = (m_pDocument->GetParser())->LoadLinearizedMainXRefTable();
|
| m_bMainXRefLoadTried = TRUE;
|
| if (dwRet != PDFPARSE_ERROR_SUCCESS) {
|
| - return FALSE;
|
| + return PDF_DATA_ERROR;
|
| }
|
| if (!PreparePageItem()) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| m_bMainXRefLoadedOK = TRUE;
|
| m_bLinearedDataOK = TRUE;
|
| }
|
|
|
| - return m_bLinearedDataOK;
|
| + return m_bLinearedDataOK ? PDF_DATA_AVAIL : PDF_DATA_NOTAVAIL;
|
| }
|
| FX_BOOL CPDF_DataAvail::CheckPageAnnots(int32_t iPage,
|
| IFX_DownloadHints* pHints) {
|
| @@ -4336,9 +4377,9 @@ FX_BOOL CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary* pDict) {
|
| }
|
| return HaveResourceAncestor(pParentDict);
|
| }
|
| -FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) {
|
| +int CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) {
|
| if (!m_pDocument) {
|
| - return FALSE;
|
| + return PDF_DATA_ERROR;
|
| }
|
| if (IsFirstCheck(iPage)) {
|
| m_bCurPageDictLoadOK = FALSE;
|
| @@ -4349,44 +4390,52 @@ FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) {
|
| m_objnum_array.RemoveAll();
|
| }
|
| if (m_pagesLoadState.find(iPage) != m_pagesLoadState.end()) {
|
| - return TRUE;
|
| + return PDF_DATA_AVAIL;
|
| }
|
| if (m_bLinearized) {
|
| if ((FX_DWORD)iPage == m_dwFirstPageNo) {
|
| m_pagesLoadState.insert(iPage);
|
| - return TRUE;
|
| + return PDF_DATA_AVAIL;
|
| }
|
| - if (!CheckLinearizedData(pHints)) {
|
| - return FALSE;
|
| + int32_t nResult = CheckLinearizedData(pHints);
|
| + if (nResult != PDF_DATA_AVAIL) {
|
| + return nResult;
|
| + }
|
| + if (m_pHintTables) {
|
| + nResult = m_pHintTables->CheckPage(iPage, pHints);
|
| + if (nResult != PDF_DATA_AVAIL)
|
| + return nResult;
|
| + m_pagesLoadState.insert(iPage);
|
| + return PDF_DATA_AVAIL;
|
| }
|
| if (m_bMainXRefLoadedOK) {
|
| if (m_bTotalLoadPageTree) {
|
| if (!LoadPages(pHints)) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| } else {
|
| if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| }
|
| } else {
|
| if (!LoadAllFile(pHints)) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| ((CPDF_Parser*)m_pDocument->GetParser())->RebuildCrossRef();
|
| ResetFirstCheck(iPage);
|
| - return TRUE;
|
| + return PDF_DATA_AVAIL;
|
| }
|
| } else {
|
| if (!m_bTotalLoadPageTree) {
|
| if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| }
|
| }
|
| if (m_bHaveAcroForm && !m_bAcroFormLoad) {
|
| if (!CheckAcroFormSubObject(pHints)) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| m_bAcroFormLoad = TRUE;
|
| }
|
| @@ -4397,7 +4446,7 @@ FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) {
|
| m_pPageDict = m_pDocument->GetPage(iPage);
|
| if (!m_pPageDict) {
|
| ResetFirstCheck(iPage);
|
| - return TRUE;
|
| + return PDF_DATA_AVAIL;
|
| }
|
| CFX_PtrArray obj_array;
|
| obj_array.Add(m_pPageDict);
|
| @@ -4417,14 +4466,14 @@ FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) {
|
| m_bPageLoadedOK = TRUE;
|
| } else {
|
| m_objs_array.Append(new_objs_array);
|
| - return bRet;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| }
|
| }
|
| if (m_bPageLoadedOK) {
|
| if (!m_bAnnotsLoad) {
|
| if (!CheckPageAnnots(iPage, pHints)) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| m_bAnnotsLoad = TRUE;
|
| }
|
| @@ -4440,7 +4489,7 @@ FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) {
|
| if (m_bNeedDownLoadResource) {
|
| FX_BOOL bRet = CheckResources(pHints);
|
| if (!bRet) {
|
| - return FALSE;
|
| + return PDF_DATA_NOTAVAIL;
|
| }
|
| m_bNeedDownLoadResource = FALSE;
|
| }
|
| @@ -4449,7 +4498,7 @@ FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) {
|
| m_bCurPageDictLoadOK = FALSE;
|
| ResetFirstCheck(iPage);
|
| m_pagesLoadState.insert(iPage);
|
| - return TRUE;
|
| + return PDF_DATA_AVAIL;
|
| }
|
| FX_BOOL CPDF_DataAvail::CheckResources(IFX_DownloadHints* pHints) {
|
| if (!m_objs_array.GetSize()) {
|
| @@ -4479,21 +4528,57 @@ void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE* pPos,
|
| *pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset);
|
| }
|
| }
|
| -int32_t CPDF_DataAvail::IsFormAvail(IFX_DownloadHints* pHints) {
|
| +int CPDF_DataAvail::GetPageCount() const {
|
| + if (m_pLinearized) {
|
| + CPDF_Dictionary* pDict = m_pLinearized->GetDict();
|
| + CPDF_Object* pObj = pDict ? pDict->GetElementValue(FX_BSTRC("N")) : nullptr;
|
| + return pObj ? pObj->GetInteger() : 0;
|
| + }
|
| + return m_pDocument ? m_pDocument->GetPageCount() : 0;
|
| +}
|
| +CPDF_Dictionary* CPDF_DataAvail::GetPage(int index) {
|
| + if (!m_pDocument || index < 0 || index >= this->GetPageCount()) {
|
| + return nullptr;
|
| + }
|
| + if (m_pLinearized) {
|
| + CPDF_Dictionary* pDict = m_pLinearized->GetDict();
|
| + CPDF_Object* pObj = pDict ? pDict->GetElementValue(FX_BSTRC("P")) : nullptr;
|
| + int pageNum = pObj ? pObj->GetInteger() : 0;
|
| + if (m_pHintTables && index != pageNum) {
|
| + FX_FILESIZE szPageStartPos = 0;
|
| + FX_FILESIZE szPageLength = 0;
|
| + FX_DWORD dwObjNum = 0;
|
| + FX_BOOL bPagePosGot = m_pHintTables->GetPagePos(index, szPageStartPos,
|
| + szPageLength, dwObjNum);
|
| + if (!bPagePosGot) {
|
| + return nullptr;
|
| + }
|
| + m_syntaxParser.InitParser(m_pFileRead, (FX_DWORD)szPageStartPos);
|
| + CPDF_Object* pPageDict = ParseIndirectObjectAt(0, dwObjNum, m_pDocument);
|
| + if (!pPageDict) {
|
| + return nullptr;
|
| + }
|
| + m_pDocument->InsertIndirectObject(dwObjNum, pPageDict);
|
| + return pPageDict->GetDict();
|
| + }
|
| + }
|
| + return m_pDocument->GetPage(index);
|
| +}
|
| +int CPDF_DataAvail::IsFormAvail(IFX_DownloadHints* pHints) {
|
| if (!m_pDocument) {
|
| - return PDFFORM_AVAIL;
|
| + return PDF_FORM_AVAIL;
|
| }
|
| if (!m_bLinearizedFormParamLoad) {
|
| CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
|
| if (!pRoot) {
|
| - return PDFFORM_AVAIL;
|
| + return PDF_FORM_AVAIL;
|
| }
|
| CPDF_Object* pAcroForm = pRoot->GetElement(FX_BSTRC("AcroForm"));
|
| if (!pAcroForm) {
|
| - return PDFFORM_NOTEXIST;
|
| + return PDF_FORM_NOTEXIST;
|
| }
|
| if (!CheckLinearizedData(pHints)) {
|
| - return PDFFORM_NOTAVAIL;
|
| + return PDF_FORM_NOTAVAIL;
|
| }
|
| if (!m_objs_array.GetSize()) {
|
| m_objs_array.Add(pAcroForm->GetDict());
|
| @@ -4505,9 +4590,9 @@ int32_t CPDF_DataAvail::IsFormAvail(IFX_DownloadHints* pHints) {
|
| m_objs_array.RemoveAll();
|
| if (!bRet) {
|
| m_objs_array.Append(new_objs_array);
|
| - return PDFFORM_NOTAVAIL;
|
| + return PDF_FORM_NOTAVAIL;
|
| }
|
| - return PDFFORM_AVAIL;
|
| + return PDF_FORM_AVAIL;
|
| }
|
| void CPDF_SortObjNumArray::AddObjNum(FX_DWORD dwObjNum) {
|
| int32_t iNext = 0;
|
| @@ -4546,3 +4631,332 @@ CPDF_PageNode::~CPDF_PageNode() {
|
| }
|
| m_childNode.RemoveAll();
|
| }
|
| +CPDF_HintTables::~CPDF_HintTables() {
|
| + m_dwDeltaNObjsArray.RemoveAll();
|
| + m_dwNSharedObjsArray.RemoveAll();
|
| + m_dwSharedObjNumArray.RemoveAll();
|
| + m_dwIdentifierArray.RemoveAll();
|
| + m_szPageOffsetArray.RemoveAll();
|
| + m_szSharedObjOffsetArray.RemoveAll();
|
| +}
|
| +FX_DWORD CPDF_HintTables::GetItemLength(int index,
|
| + const CFX_FileSizeArray& szArray) {
|
| + if (index < 0 || szArray.GetSize() < 2 || index > szArray.GetSize() - 2 ||
|
| + szArray[index] > szArray[index + 1])
|
| + return 0;
|
| + return szArray[index + 1] - szArray[index];
|
| +}
|
| +FX_BOOL CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
|
| + if (!hStream)
|
| + return FALSE;
|
| + int nStreamOffset = ReadPrimaryHintStreamOffset();
|
| + int nStreamLen = ReadPrimaryHintStreamLength();
|
| + if (nStreamOffset < 0 || nStreamLen < 1)
|
| + return FALSE;
|
| + // Item 1: The least number of objects in a page.
|
| + FX_DWORD dwObjLeastNum = hStream->GetBits(32);
|
| + // Item 2: The location of the first page's page object.
|
| + FX_DWORD dwFirstObjLoc = hStream->GetBits(32);
|
| + if (dwFirstObjLoc > nStreamOffset) {
|
| + FX_SAFE_DWORD safeLoc = pdfium::base::checked_cast<FX_DWORD>(nStreamLen);
|
| + safeLoc += dwFirstObjLoc;
|
| + if (!safeLoc.IsValid())
|
| + return FALSE;
|
| + m_szFirstPageObjOffset =
|
| + pdfium::base::checked_cast<FX_FILESIZE>(safeLoc.ValueOrDie());
|
| + } else {
|
| + m_szFirstPageObjOffset =
|
| + pdfium::base::checked_cast<FX_FILESIZE>(dwFirstObjLoc);
|
| + }
|
| + // Item 3: The number of bits needed to represent the difference
|
| + // between the greatest and least number of objects in a page.
|
| + FX_DWORD dwDeltaObjectsBits = hStream->GetBits(16);
|
| + // Item 4: The least length of a page in bytes.
|
| + FX_DWORD dwPageLeastLen = hStream->GetBits(32);
|
| + // Item 5: The number of bits needed to represent the difference
|
| + // between the greatest and least length of a page, in bytes.
|
| + FX_DWORD dwDeltaPageLenBits = hStream->GetBits(16);
|
| + // Skip Item 6, 7, 8, 9 total 96 bits.
|
| + hStream->SkipBits(96);
|
| + // Item 10: The number of bits needed to represent the greatest
|
| + // number of shared object references.
|
| + FX_DWORD dwSharedObjBits = hStream->GetBits(16);
|
| + // Item 11: The number of bits needed to represent the numerically
|
| + // greatest shared object identifier used by the pages.
|
| + FX_DWORD dwSharedIdBits = hStream->GetBits(16);
|
| + // Item 12: The number of bits needed to represent the numerator of
|
| + // the fractional position for each shared object reference. For each
|
| + // shared object referenced from a page, there is an indication of
|
| + // where in the page's content stream the object is first referenced.
|
| + FX_DWORD dwSharedNumeratorBits = hStream->GetBits(16);
|
| + // Item 13: Skip Item 13 which has 16 bits.
|
| + FX_DWORD dwSharedDenominator = hStream->GetBits(16);
|
| + CPDF_Object* pPageNum = m_pLinearizedDict->GetElementValue(FX_BSTRC("N"));
|
| + int nPages = pPageNum ? pPageNum->GetInteger() : 0;
|
| + if (nPages < 1)
|
| + return FALSE;
|
| + for (int i = 0; i < nPages; ++i) {
|
| + FX_SAFE_DWORD safeDeltaObj = hStream->GetBits(dwDeltaObjectsBits);
|
| + safeDeltaObj += dwObjLeastNum;
|
| + if (!safeDeltaObj.IsValid())
|
| + return FALSE;
|
| + m_dwDeltaNObjsArray.Add(safeDeltaObj.ValueOrDie());
|
| + }
|
| + hStream->ByteAlign();
|
| + CFX_DWordArray dwPageLenArray;
|
| + for (int i = 0; i < nPages; ++i) {
|
| + FX_SAFE_DWORD safePageLen = hStream->GetBits(dwDeltaPageLenBits);
|
| + safePageLen += dwPageLeastLen;
|
| + if (!safePageLen.IsValid())
|
| + return FALSE;
|
| + dwPageLenArray.Add(safePageLen.ValueOrDie());
|
| + }
|
| + CPDF_Object* pOffsetE = m_pLinearizedDict->GetElementValue(FX_BSTRC("E"));
|
| + int nOffsetE = pOffsetE ? pOffsetE->GetInteger() : -1;
|
| + if (nOffsetE < 0)
|
| + return FALSE;
|
| + CPDF_Object* pFirstPageNum =
|
| + m_pLinearizedDict->GetElementValue(FX_BSTRC("P"));
|
| + int nFirstPageNum = pFirstPageNum ? pFirstPageNum->GetInteger() : 0;
|
| + for (int i = 0; i < nPages; ++i) {
|
| + if (i == nFirstPageNum) {
|
| + m_szPageOffsetArray.Add(m_szFirstPageObjOffset);
|
| + } else if (i == nFirstPageNum + 1) {
|
| + if (i == 1) {
|
| + m_szPageOffsetArray.Add(nOffsetE);
|
| + } else {
|
| + m_szPageOffsetArray.Add(m_szPageOffsetArray[i - 2] +
|
| + dwPageLenArray[i - 2]);
|
| + }
|
| + } else {
|
| + if (i == 0) {
|
| + m_szPageOffsetArray.Add(nOffsetE);
|
| + } else {
|
| + m_szPageOffsetArray.Add(m_szPageOffsetArray[i - 1] +
|
| + dwPageLenArray[i - 1]);
|
| + }
|
| + }
|
| + }
|
| + if (nPages > 0) {
|
| + m_szPageOffsetArray.Add(m_szPageOffsetArray[nPages - 1] +
|
| + dwPageLenArray[nPages - 1]);
|
| + }
|
| + hStream->ByteAlign();
|
| + // number of shared objects
|
| + for (int i = 0; i < nPages; i++) {
|
| + m_dwNSharedObjsArray.Add(hStream->GetBits(dwSharedObjBits));
|
| + }
|
| + hStream->ByteAlign();
|
| + // array of identifier, sizes = nshared_objects
|
| + for (int i = 0; i < nPages; i++) {
|
| + for (int j = 0; j < m_dwNSharedObjsArray[i]; j++) {
|
| + m_dwIdentifierArray.Add(hStream->GetBits(dwSharedIdBits));
|
| + }
|
| + }
|
| + hStream->ByteAlign();
|
| + for (int i = 0; i < nPages; i++) {
|
| + FX_SAFE_DWORD safeSize = m_dwNSharedObjsArray[i];
|
| + safeSize *= dwSharedNumeratorBits;
|
| + if (!safeSize.IsValid())
|
| + return FALSE;
|
| + hStream->SkipBits(safeSize.ValueOrDie());
|
| + }
|
| + hStream->ByteAlign();
|
| + FX_SAFE_DWORD safeTotalPageLen = pdfium::base::checked_cast<FX_DWORD>(nPages);
|
| + safeTotalPageLen *= dwDeltaPageLenBits;
|
| + if (!safeTotalPageLen.IsValid())
|
| + return FALSE;
|
| + hStream->SkipBits(safeTotalPageLen.ValueOrDie());
|
| + hStream->ByteAlign();
|
| + return TRUE;
|
| +}
|
| +FX_BOOL CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream) {
|
| + if (!hStream)
|
| + return FALSE;
|
| + int nStreamOffset = ReadPrimaryHintStreamOffset();
|
| + int nStreamLen = ReadPrimaryHintStreamLength();
|
| + if (nStreamOffset < 0 || nStreamLen < 1)
|
| + return FALSE;
|
| + // Item 1: The object number of the first object in the shared objects
|
| + // section.
|
| + FX_DWORD dwFirstSharedObjNum = hStream->GetBits(32);
|
| + // Item 2: The location of the first object in the shared objects section.
|
| + FX_DWORD dwFirstSharedObjLoc = hStream->GetBits(32);
|
| + if (dwFirstSharedObjLoc > nStreamOffset)
|
| + dwFirstSharedObjLoc += nStreamLen;
|
| + // Item 3: The number of shared object entries for the first page.
|
| + m_nFirstPageSharedObjs = hStream->GetBits(32);
|
| + // Item 4: The number of shared object entries for the shared objects
|
| + // section, including the number of shared object entries for the first page.
|
| + FX_DWORD dwSharedObjTotal = hStream->GetBits(32);
|
| + // Item 5: The number of bits needed to represent the greatest number of
|
| + // objects in a shared object group. Skipped.
|
| + hStream->SkipBits(16);
|
| + // Item 6: The least length of a shared object group in bytes.
|
| + FX_DWORD dwGroupLeastLen = hStream->GetBits(32);
|
| + // Item 7: The number of bits needed to represent the difference between the
|
| + // greatest and least length of a shared object group, in bytes.
|
| + FX_DWORD dwDeltaGroupLen = hStream->GetBits(16);
|
| + CPDF_Object* pFirstPageObj =
|
| + m_pLinearizedDict->GetElementValue(FX_BSTRC("O"));
|
| + int nFirstPageObjNum = pFirstPageObj ? pFirstPageObj->GetInteger() : -1;
|
| + if (nFirstPageObjNum < 0)
|
| + return FALSE;
|
| + FX_DWORD dwPrevObjLen = 0;
|
| + FX_DWORD dwCurObjLen = 0;
|
| + for (int i = 0; i < dwSharedObjTotal; ++i) {
|
| + dwPrevObjLen = dwCurObjLen;
|
| + FX_SAFE_DWORD safeObjLen = hStream->GetBits(dwDeltaGroupLen);
|
| + safeObjLen += dwGroupLeastLen;
|
| + if (!safeObjLen.IsValid())
|
| + return FALSE;
|
| + dwCurObjLen = safeObjLen.ValueOrDie();
|
| + if (i < m_nFirstPageSharedObjs) {
|
| + m_dwSharedObjNumArray.Add(nFirstPageObjNum + i);
|
| + if (i == 0)
|
| + m_szSharedObjOffsetArray.Add(m_szFirstPageObjOffset);
|
| + } else {
|
| + FX_SAFE_DWORD safeObjNum = dwFirstSharedObjNum;
|
| + safeObjNum += i - m_nFirstPageSharedObjs;
|
| + if (!safeObjNum.IsValid())
|
| + return FALSE;
|
| + m_dwSharedObjNumArray.Add(safeObjNum.ValueOrDie());
|
| + if (i == m_nFirstPageSharedObjs)
|
| + m_szSharedObjOffsetArray.Add(
|
| + pdfium::base::checked_cast<int32_t>(dwFirstSharedObjLoc));
|
| + }
|
| + if (i != 0 && i != m_nFirstPageSharedObjs) {
|
| + FX_SAFE_INT32 safeLoc = pdfium::base::checked_cast<int32_t>(dwPrevObjLen);
|
| + safeLoc += m_szSharedObjOffsetArray[i - 1];
|
| + if (!safeLoc.IsValid())
|
| + return FALSE;
|
| + m_szSharedObjOffsetArray.Add(safeLoc.ValueOrDie());
|
| + }
|
| + }
|
| + if (dwSharedObjTotal > 0) {
|
| + FX_SAFE_INT32 safeLoc = pdfium::base::checked_cast<int32_t>(dwCurObjLen);
|
| + safeLoc += m_szSharedObjOffsetArray[dwSharedObjTotal - 1];
|
| + if (!safeLoc.IsValid())
|
| + return FALSE;
|
| + m_szSharedObjOffsetArray.Add(safeLoc.ValueOrDie());
|
| + }
|
| + hStream->ByteAlign();
|
| + hStream->SkipBits(dwSharedObjTotal);
|
| + hStream->ByteAlign();
|
| + return TRUE;
|
| +}
|
| +FX_BOOL CPDF_HintTables::GetPagePos(int index,
|
| + FX_FILESIZE& szPageStartPos,
|
| + FX_FILESIZE& szPageLength,
|
| + FX_DWORD& dwObjNum) {
|
| + if (!m_pLinearizedDict)
|
| + return FALSE;
|
| + szPageStartPos = m_szPageOffsetArray[index];
|
| + szPageLength = GetItemLength(index, m_szPageOffsetArray);
|
| + CPDF_Object* pFirstPageNum =
|
| + m_pLinearizedDict->GetElementValue(FX_BSTRC("P"));
|
| + int nFirstPageNum = pFirstPageNum ? pFirstPageNum->GetInteger() : 0;
|
| + CPDF_Object* pFirstPageObjNum =
|
| + m_pLinearizedDict->GetElementValue(FX_BSTRC("O"));
|
| + if (!pFirstPageObjNum)
|
| + return FALSE;
|
| + int nFirstPageObjNum = pFirstPageObjNum->GetInteger();
|
| + if (index == nFirstPageNum) {
|
| + dwObjNum = nFirstPageObjNum;
|
| + return TRUE;
|
| + }
|
| + // The object number of remaining pages starts from 1.
|
| + dwObjNum = 1;
|
| + for (int i = 0; i < index; ++i) {
|
| + if (i == nFirstPageNum)
|
| + continue;
|
| + dwObjNum += m_dwDeltaNObjsArray[i];
|
| + }
|
| + return TRUE;
|
| +}
|
| +int32_t CPDF_HintTables::CheckPage(int index, IFX_DownloadHints* pHints) {
|
| + if (!m_pLinearizedDict || !pHints)
|
| + return PDF_DATA_ERROR;
|
| + CPDF_Object* pFirstAvailPage =
|
| + m_pLinearizedDict->GetElementValue(FX_BSTRC("P"));
|
| + int nFirstAvailPage = pFirstAvailPage ? pFirstAvailPage->GetInteger() : 0;
|
| + if (index == nFirstAvailPage)
|
| + return PDF_DATA_AVAIL;
|
| + FX_DWORD dwLength = GetItemLength(index, m_szPageOffsetArray);
|
| + if (!dwLength ||
|
| + !m_pDataAvail->IsDataAvail(m_szPageOffsetArray[index], dwLength,
|
| + pHints)) {
|
| + return PDF_DATA_NOTAVAIL;
|
| + }
|
| + // Download data of shared objects in the page.
|
| + FX_DWORD offset = 0;
|
| + for (int i = 0; i < index; ++i) {
|
| + offset += m_dwNSharedObjsArray[i];
|
| + }
|
| + CPDF_Object* pFirstPageObj =
|
| + m_pLinearizedDict->GetElementValue(FX_BSTRC("O"));
|
| + int nFirstPageObjNum = pFirstPageObj ? pFirstPageObj->GetInteger() : -1;
|
| + if (nFirstPageObjNum < 0)
|
| + return FALSE;
|
| + FX_DWORD dwIndex = 0;
|
| + FX_DWORD dwObjNum = 0;
|
| + for (int j = 0; j < m_dwNSharedObjsArray[index]; ++j) {
|
| + dwIndex = m_dwIdentifierArray[offset + j];
|
| + dwObjNum = m_dwSharedObjNumArray[dwIndex];
|
| + if (dwObjNum >= nFirstPageObjNum &&
|
| + dwObjNum < nFirstPageObjNum + m_nFirstPageSharedObjs) {
|
| + continue;
|
| + }
|
| + dwLength = GetItemLength(dwIndex, m_szSharedObjOffsetArray);
|
| + if (!dwLength ||
|
| + !m_pDataAvail->IsDataAvail(m_szSharedObjOffsetArray[dwIndex], dwLength,
|
| + pHints)) {
|
| + return PDF_DATA_NOTAVAIL;
|
| + }
|
| + }
|
| + return PDF_DATA_AVAIL;
|
| +}
|
| +FX_BOOL CPDF_HintTables::LoadHintStream(CPDF_Stream* pHintStream) {
|
| + if (!pHintStream || !m_pLinearizedDict)
|
| + return FALSE;
|
| + CPDF_Dictionary* pDict = pHintStream->GetDict();
|
| + CPDF_Object* pOffset = pDict ? pDict->GetElement(FX_BSTRC("S")) : nullptr;
|
| + if (!pOffset || pOffset->GetType() != PDFOBJ_NUMBER)
|
| + return FALSE;
|
| + CPDF_StreamAcc acc;
|
| + acc.LoadAllData(pHintStream);
|
| + FX_DWORD size = acc.GetSize();
|
| + // The header section of page offset hint table is 36 bytes.
|
| + // The header section of shared object hint table is 24 bytes.
|
| + // Hint table has at least 60 bytes.
|
| + const FX_DWORD MIN_STREAM_LEN = 60;
|
| + if (size < MIN_STREAM_LEN || size < pOffset->GetInteger() ||
|
| + !pOffset->GetInteger()) {
|
| + return FALSE;
|
| + }
|
| + CFX_BitStream bs;
|
| + bs.Init(acc.GetData(), size);
|
| + return ReadPageHintTable(&bs) && ReadSharedObjHintTable(&bs);
|
| +}
|
| +int CPDF_HintTables::ReadPrimaryHintStreamOffset() const {
|
| + if (!m_pLinearizedDict)
|
| + return -1;
|
| + CPDF_Array* pRange = m_pLinearizedDict->GetArray(FX_BSTRC("H"));
|
| + if (!pRange)
|
| + return -1;
|
| + CPDF_Object* pStreamOffset = pRange->GetElementValue(0);
|
| + if (!pStreamOffset)
|
| + return -1;
|
| + return pStreamOffset->GetInteger();
|
| +}
|
| +int CPDF_HintTables::ReadPrimaryHintStreamLength() const {
|
| + if (!m_pLinearizedDict)
|
| + return -1;
|
| + CPDF_Array* pRange = m_pLinearizedDict->GetArray(FX_BSTRC("H"));
|
| + if (!pRange)
|
| + return -1;
|
| + CPDF_Object* pStreamLen = pRange->GetElementValue(1);
|
| + if (!pStreamLen)
|
| + return -1;
|
| + return pStreamLen->GetInteger();
|
| +}
|
|
|