From 9d8ec5a6e37e8d1d4d4edca9040de234e2d4728f Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Tue, 4 Aug 2015 13:00:21 -0700 Subject: XFA: clang-format all pdfium code. No behavior change. Generated by: find . -name '*.cpp' -o -name '*.h' | \ grep -E -v 'third_party|thirdparties|lpng_v163|tiff_v403' | \ xargs ../../buildtools/mac/clang-format -i Then manually merged https://codereview.chromium.org/1269223002/ See thread "tabs vs spaces" on pdfium@googlegroups.com for discussion. BUG=none --- .../src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp | 8430 ++++++++++---------- 1 file changed, 4243 insertions(+), 4187 deletions(-) (limited to '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 e4d3571eee..ad4d45908d 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp @@ -13,4600 +13,4656 @@ #include "../../../include/fxcrt/fx_safe_types.h" #include "../fpdf_page/pageint.h" -FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict) -{ - CPDF_Object* pType = pDict->GetElementValue(FX_BSTRC("Type")); +FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict) { + CPDF_Object* pType = pDict->GetElementValue(FX_BSTRC("Type")); + if (!pType) { + pType = pDict->GetElementValue(FX_BSTRC("FT")); if (!pType) { - pType = pDict->GetElementValue(FX_BSTRC("FT")); - if (!pType) { - return FALSE; - } - } - if (pType->GetString() == FX_BSTRC("Sig")) { - return TRUE; + return FALSE; } - return FALSE; + } + if (pType->GetString() == FX_BSTRC("Sig")) { + return TRUE; + } + return FALSE; } -static int32_t _CompareDWord(const void* p1, const void* p2) -{ - return (*(FX_DWORD*)p1) - (*(FX_DWORD*)p2); +static int32_t _CompareDWord(const void* p1, const void* p2) { + return (*(FX_DWORD*)p1) - (*(FX_DWORD*)p2); } -static int _CompareFileSize(const void* p1, const void* p2) -{ - FX_FILESIZE ret = (*(FX_FILESIZE*)p1) - (*(FX_FILESIZE*)p2); - if (ret > 0) { - return 1; - } - if (ret < 0) { - return -1; - } - return 0; +static int _CompareFileSize(const void* p1, const void* p2) { + FX_FILESIZE ret = (*(FX_FILESIZE*)p1) - (*(FX_FILESIZE*)p2); + if (ret > 0) { + return 1; + } + if (ret < 0) { + return -1; + } + return 0; } -CPDF_Parser::CPDF_Parser() -{ - m_pDocument = NULL; - m_pTrailer = NULL; - m_pEncryptDict = NULL; - m_pSecurityHandler = NULL; - m_pLinearized = NULL; - m_dwFirstPageNo = 0; - m_dwXrefStartObjNum = 0; - m_bOwnFileRead = TRUE; - m_FileVersion = 0; - m_bForceUseSecurityHandler = FALSE; +CPDF_Parser::CPDF_Parser() { + m_pDocument = NULL; + m_pTrailer = NULL; + m_pEncryptDict = NULL; + m_pSecurityHandler = NULL; + m_pLinearized = NULL; + m_dwFirstPageNo = 0; + m_dwXrefStartObjNum = 0; + m_bOwnFileRead = TRUE; + m_FileVersion = 0; + m_bForceUseSecurityHandler = FALSE; } -CPDF_Parser::~CPDF_Parser() -{ - CloseParser(FALSE); +CPDF_Parser::~CPDF_Parser() { + CloseParser(FALSE); } -FX_DWORD CPDF_Parser::GetLastObjNum() -{ - FX_DWORD dwSize = m_CrossRef.GetSize(); - return dwSize ? dwSize - 1 : 0; +FX_DWORD CPDF_Parser::GetLastObjNum() { + FX_DWORD dwSize = m_CrossRef.GetSize(); + return dwSize ? dwSize - 1 : 0; } -void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) -{ - m_pEncryptDict = pDict; +void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) { + m_pEncryptDict = pDict; } -void CPDF_Parser::CloseParser(FX_BOOL bReParse) -{ - m_bVersionUpdated = FALSE; - if (!bReParse) { - delete m_pDocument; - m_pDocument = NULL; - } - if (m_pTrailer) { - m_pTrailer->Release(); - m_pTrailer = NULL; - } - ReleaseEncryptHandler(); - SetEncryptDictionary(NULL); - if (m_bOwnFileRead && m_Syntax.m_pFileAccess) { - m_Syntax.m_pFileAccess->Release(); - m_Syntax.m_pFileAccess = NULL; - } - FX_POSITION pos = m_ObjectStreamMap.GetStartPosition(); - while (pos) { - void* objnum; - CPDF_StreamAcc* pStream; - m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream); - delete pStream; - } - m_ObjectStreamMap.RemoveAll(); - m_SortedOffset.RemoveAll(); - m_CrossRef.RemoveAll(); - m_V5Type.RemoveAll(); - m_ObjVersion.RemoveAll(); - int32_t iLen = m_Trailers.GetSize(); - for (int32_t i = 0; i < iLen; ++i) { - if (CPDF_Dictionary* trailer = m_Trailers.GetAt(i)) - trailer->Release(); - } - m_Trailers.RemoveAll(); - if (m_pLinearized) { - m_pLinearized->Release(); - m_pLinearized = NULL; - } +void CPDF_Parser::CloseParser(FX_BOOL bReParse) { + m_bVersionUpdated = FALSE; + if (!bReParse) { + delete m_pDocument; + m_pDocument = NULL; + } + if (m_pTrailer) { + m_pTrailer->Release(); + m_pTrailer = NULL; + } + ReleaseEncryptHandler(); + SetEncryptDictionary(NULL); + if (m_bOwnFileRead && m_Syntax.m_pFileAccess) { + m_Syntax.m_pFileAccess->Release(); + m_Syntax.m_pFileAccess = NULL; + } + FX_POSITION pos = m_ObjectStreamMap.GetStartPosition(); + while (pos) { + void* objnum; + CPDF_StreamAcc* pStream; + m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream); + delete pStream; + } + m_ObjectStreamMap.RemoveAll(); + m_SortedOffset.RemoveAll(); + m_CrossRef.RemoveAll(); + m_V5Type.RemoveAll(); + m_ObjVersion.RemoveAll(); + int32_t iLen = m_Trailers.GetSize(); + for (int32_t i = 0; i < iLen; ++i) { + if (CPDF_Dictionary* trailer = m_Trailers.GetAt(i)) + trailer->Release(); + } + m_Trailers.RemoveAll(); + if (m_pLinearized) { + m_pLinearized->Release(); + m_pLinearized = NULL; + } } -static int32_t GetHeaderOffset(IFX_FileRead* pFile) -{ - FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025); - uint8_t buf[4]; - int32_t offset = 0; - while (1) { - if (!pFile->ReadBlock(buf, offset, 4)) { - return -1; - } - if (*(FX_DWORD*)buf == tag) { - return offset; - } - offset ++; - if (offset > 1024) { - return -1; - } - } - return -1; +static int32_t GetHeaderOffset(IFX_FileRead* pFile) { + FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025); + uint8_t buf[4]; + int32_t offset = 0; + while (1) { + if (!pFile->ReadBlock(buf, offset, 4)) { + return -1; + } + if (*(FX_DWORD*)buf == tag) { + return offset; + } + offset++; + if (offset > 1024) { + return -1; + } + } + return -1; } -FX_DWORD CPDF_Parser::StartParse(const FX_CHAR* filename, FX_BOOL bReParse) -{ - IFX_FileRead* pFileAccess = FX_CreateFileRead(filename); - if (!pFileAccess) { - return PDFPARSE_ERROR_FILE; - } - return StartParse(pFileAccess, bReParse); +FX_DWORD CPDF_Parser::StartParse(const FX_CHAR* filename, FX_BOOL bReParse) { + IFX_FileRead* pFileAccess = FX_CreateFileRead(filename); + if (!pFileAccess) { + return PDFPARSE_ERROR_FILE; + } + return StartParse(pFileAccess, bReParse); } -FX_DWORD CPDF_Parser::StartParse(const FX_WCHAR* filename, FX_BOOL bReParse) -{ - IFX_FileRead* pFileAccess = FX_CreateFileRead(filename); - if (!pFileAccess) { - return PDFPARSE_ERROR_FILE; - } - return StartParse(pFileAccess, bReParse); +FX_DWORD CPDF_Parser::StartParse(const FX_WCHAR* filename, FX_BOOL bReParse) { + IFX_FileRead* pFileAccess = FX_CreateFileRead(filename); + if (!pFileAccess) { + return PDFPARSE_ERROR_FILE; + } + return StartParse(pFileAccess, bReParse); } CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler(); CPDF_SecurityHandler* FPDF_CreatePubKeyHandler(void*); -FX_DWORD CPDF_Parser::StartParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead) -{ - CloseParser(bReParse); - m_bXRefStream = FALSE; - m_LastXRefOffset = 0; - m_bOwnFileRead = bOwnFileRead; - int32_t offset = GetHeaderOffset(pFileAccess); - if (offset == -1) { - if (bOwnFileRead && pFileAccess) { - pFileAccess->Release(); - } - return PDFPARSE_ERROR_FORMAT; - } - m_Syntax.InitParser(pFileAccess, offset); - uint8_t ch; - if (!m_Syntax.GetCharAt(5, ch)) { - return PDFPARSE_ERROR_FORMAT; - } - if (ch >= '0' && ch <= '9') { - m_FileVersion = (ch - '0') * 10; - } - if (!m_Syntax.GetCharAt(7, ch)) { - return PDFPARSE_ERROR_FORMAT; +FX_DWORD CPDF_Parser::StartParse(IFX_FileRead* pFileAccess, + FX_BOOL bReParse, + FX_BOOL bOwnFileRead) { + CloseParser(bReParse); + m_bXRefStream = FALSE; + m_LastXRefOffset = 0; + m_bOwnFileRead = bOwnFileRead; + int32_t offset = GetHeaderOffset(pFileAccess); + if (offset == -1) { + if (bOwnFileRead && pFileAccess) { + pFileAccess->Release(); + } + return PDFPARSE_ERROR_FORMAT; + } + m_Syntax.InitParser(pFileAccess, offset); + uint8_t ch; + if (!m_Syntax.GetCharAt(5, ch)) { + return PDFPARSE_ERROR_FORMAT; + } + if (ch >= '0' && ch <= '9') { + m_FileVersion = (ch - '0') * 10; + } + if (!m_Syntax.GetCharAt(7, ch)) { + return PDFPARSE_ERROR_FORMAT; + } + if (ch >= '0' && ch <= '9') { + m_FileVersion += ch - '0'; + } + if (m_Syntax.m_FileLen < m_Syntax.m_HeaderOffset + 9) { + return PDFPARSE_ERROR_FORMAT; + } + m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9); + if (!bReParse) { + m_pDocument = new CPDF_Document(this); + } + FX_BOOL bXRefRebuilt = FALSE; + if (m_Syntax.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, 4096)) { + FX_FILESIZE startxref_offset = m_Syntax.SavePos(); + void* pResult = FXSYS_bsearch(&startxref_offset, m_SortedOffset.GetData(), + m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), + _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(startxref_offset); } - if (ch >= '0' && ch <= '9') { - m_FileVersion += ch - '0'; + m_Syntax.GetKeyword(); + FX_BOOL bNumber; + CFX_ByteString xrefpos_str = m_Syntax.GetNextWord(bNumber); + if (!bNumber) { + return PDFPARSE_ERROR_FORMAT; } - if (m_Syntax.m_FileLen < m_Syntax.m_HeaderOffset + 9) { + m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str); + if (!LoadAllCrossRefV4(m_LastXRefOffset) && + !LoadAllCrossRefV5(m_LastXRefOffset)) { + if (!RebuildCrossRef()) { return PDFPARSE_ERROR_FORMAT; + } + bXRefRebuilt = TRUE; + m_LastXRefOffset = 0; + } + } else { + if (!RebuildCrossRef()) { + return PDFPARSE_ERROR_FORMAT; + } + bXRefRebuilt = TRUE; + } + FX_DWORD dwRet = SetEncryptHandler(); + if (dwRet != PDFPARSE_ERROR_SUCCESS) { + return dwRet; + } + m_pDocument->LoadDoc(); + if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) { + if (bXRefRebuilt) { + return PDFPARSE_ERROR_FORMAT; } - m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9); - if (!bReParse) { - m_pDocument = new CPDF_Document(this); - } - FX_BOOL bXRefRebuilt = FALSE; - if (m_Syntax.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, 4096)) { - FX_FILESIZE startxref_offset = m_Syntax.SavePos(); - void* pResult = FXSYS_bsearch(&startxref_offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_SortedOffset.Add(startxref_offset); - } - m_Syntax.GetKeyword(); - FX_BOOL bNumber; - CFX_ByteString xrefpos_str = m_Syntax.GetNextWord(bNumber); - if (!bNumber) { - return PDFPARSE_ERROR_FORMAT; - } - m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str); - if (!LoadAllCrossRefV4(m_LastXRefOffset) && !LoadAllCrossRefV5(m_LastXRefOffset)) { - if (!RebuildCrossRef()) { - return PDFPARSE_ERROR_FORMAT; - } - bXRefRebuilt = TRUE; - m_LastXRefOffset = 0; - } - } else { - if (!RebuildCrossRef()) { - return PDFPARSE_ERROR_FORMAT; - } - bXRefRebuilt = TRUE; + ReleaseEncryptHandler(); + if (!RebuildCrossRef()) { + return PDFPARSE_ERROR_FORMAT; } - FX_DWORD dwRet = SetEncryptHandler(); + dwRet = SetEncryptHandler(); if (dwRet != PDFPARSE_ERROR_SUCCESS) { - return dwRet; + return dwRet; } m_pDocument->LoadDoc(); - if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) { - if (bXRefRebuilt) { - return PDFPARSE_ERROR_FORMAT; - } - ReleaseEncryptHandler(); - if (!RebuildCrossRef()) { - return PDFPARSE_ERROR_FORMAT; - } - dwRet = SetEncryptHandler(); - if (dwRet != PDFPARSE_ERROR_SUCCESS) { - return dwRet; - } - m_pDocument->LoadDoc(); - if (m_pDocument->GetRoot() == NULL) { - return PDFPARSE_ERROR_FORMAT; - } - } - FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - FX_DWORD RootObjNum = GetRootObjNum(); + if (m_pDocument->GetRoot() == NULL) { + return PDFPARSE_ERROR_FORMAT; + } + } + FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + FX_DWORD RootObjNum = GetRootObjNum(); + if (RootObjNum == 0) { + ReleaseEncryptHandler(); + RebuildCrossRef(); + RootObjNum = GetRootObjNum(); if (RootObjNum == 0) { - ReleaseEncryptHandler(); - RebuildCrossRef(); - RootObjNum = GetRootObjNum(); - if (RootObjNum == 0) { - return PDFPARSE_ERROR_FORMAT; - } - dwRet = SetEncryptHandler(); - if (dwRet != PDFPARSE_ERROR_SUCCESS) { - return dwRet; - } - } - if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) { - CPDF_Reference* pMetadata = (CPDF_Reference*)m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata")); - if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) { - m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum(); - } + return PDFPARSE_ERROR_FORMAT; } - return PDFPARSE_ERROR_SUCCESS; + dwRet = SetEncryptHandler(); + if (dwRet != PDFPARSE_ERROR_SUCCESS) { + return dwRet; + } + } + if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) { + CPDF_Reference* pMetadata = + (CPDF_Reference*)m_pDocument->GetRoot()->GetElement( + FX_BSTRC("Metadata")); + if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) { + m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum(); + } + } + return PDFPARSE_ERROR_SUCCESS; } -FX_DWORD CPDF_Parser::SetEncryptHandler() -{ - ReleaseEncryptHandler(); - SetEncryptDictionary(NULL); - if (m_pTrailer == NULL) { - return PDFPARSE_ERROR_FORMAT; - } - CPDF_Object* pEncryptObj = m_pTrailer->GetElement(FX_BSTRC("Encrypt")); - if (pEncryptObj) { - if (pEncryptObj->GetType() == PDFOBJ_DICTIONARY) { - SetEncryptDictionary((CPDF_Dictionary*)pEncryptObj); - } else if (pEncryptObj->GetType() == PDFOBJ_REFERENCE) { - pEncryptObj = m_pDocument->GetIndirectObject(((CPDF_Reference*)pEncryptObj)->GetRefObjNum()); - if (pEncryptObj) { - SetEncryptDictionary(pEncryptObj->GetDict()); - } - } - } - if (m_bForceUseSecurityHandler) { - FX_DWORD err = PDFPARSE_ERROR_HANDLER; - if (m_pSecurityHandler == NULL) { - return PDFPARSE_ERROR_HANDLER; - } - if (!m_pSecurityHandler->OnInit(this, m_pEncryptDict)) { - return err; - } - CPDF_CryptoHandler* pCryptoHandler = m_pSecurityHandler->CreateCryptoHandler(); - if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) { - delete pCryptoHandler; - pCryptoHandler = NULL; - return PDFPARSE_ERROR_HANDLER; - } - m_Syntax.SetEncrypt(pCryptoHandler); - } else if (m_pEncryptDict) { - CFX_ByteString filter = m_pEncryptDict->GetString(FX_BSTRC("Filter")); - CPDF_SecurityHandler* pSecurityHandler = NULL; - FX_DWORD err = PDFPARSE_ERROR_HANDLER; - if (filter == FX_BSTRC("Standard")) { - pSecurityHandler = FPDF_CreateStandardSecurityHandler(); - err = PDFPARSE_ERROR_PASSWORD; - } - if (pSecurityHandler == NULL) { - return PDFPARSE_ERROR_HANDLER; - } - if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) { - delete pSecurityHandler; - pSecurityHandler = NULL; - return err; - } - m_pSecurityHandler = pSecurityHandler; - CPDF_CryptoHandler* pCryptoHandler = pSecurityHandler->CreateCryptoHandler(); - if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) { - delete pCryptoHandler; - pCryptoHandler = NULL; - return PDFPARSE_ERROR_HANDLER; - } - m_Syntax.SetEncrypt(pCryptoHandler); +FX_DWORD CPDF_Parser::SetEncryptHandler() { + ReleaseEncryptHandler(); + SetEncryptDictionary(NULL); + if (m_pTrailer == NULL) { + return PDFPARSE_ERROR_FORMAT; + } + CPDF_Object* pEncryptObj = m_pTrailer->GetElement(FX_BSTRC("Encrypt")); + if (pEncryptObj) { + if (pEncryptObj->GetType() == PDFOBJ_DICTIONARY) { + SetEncryptDictionary((CPDF_Dictionary*)pEncryptObj); + } else if (pEncryptObj->GetType() == PDFOBJ_REFERENCE) { + pEncryptObj = m_pDocument->GetIndirectObject( + ((CPDF_Reference*)pEncryptObj)->GetRefObjNum()); + if (pEncryptObj) { + SetEncryptDictionary(pEncryptObj->GetDict()); + } + } + } + if (m_bForceUseSecurityHandler) { + FX_DWORD err = PDFPARSE_ERROR_HANDLER; + if (m_pSecurityHandler == NULL) { + return PDFPARSE_ERROR_HANDLER; + } + if (!m_pSecurityHandler->OnInit(this, m_pEncryptDict)) { + return err; + } + CPDF_CryptoHandler* pCryptoHandler = + m_pSecurityHandler->CreateCryptoHandler(); + if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) { + delete pCryptoHandler; + pCryptoHandler = NULL; + return PDFPARSE_ERROR_HANDLER; + } + m_Syntax.SetEncrypt(pCryptoHandler); + } else if (m_pEncryptDict) { + CFX_ByteString filter = m_pEncryptDict->GetString(FX_BSTRC("Filter")); + CPDF_SecurityHandler* pSecurityHandler = NULL; + FX_DWORD err = PDFPARSE_ERROR_HANDLER; + if (filter == FX_BSTRC("Standard")) { + pSecurityHandler = FPDF_CreateStandardSecurityHandler(); + err = PDFPARSE_ERROR_PASSWORD; + } + if (pSecurityHandler == NULL) { + return PDFPARSE_ERROR_HANDLER; + } + if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) { + delete pSecurityHandler; + pSecurityHandler = NULL; + return err; } - return PDFPARSE_ERROR_SUCCESS; + m_pSecurityHandler = pSecurityHandler; + CPDF_CryptoHandler* pCryptoHandler = + pSecurityHandler->CreateCryptoHandler(); + if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) { + delete pCryptoHandler; + pCryptoHandler = NULL; + return PDFPARSE_ERROR_HANDLER; + } + m_Syntax.SetEncrypt(pCryptoHandler); + } + return PDFPARSE_ERROR_SUCCESS; } -void CPDF_Parser::ReleaseEncryptHandler() -{ - delete m_Syntax.m_pCryptoHandler; - m_Syntax.m_pCryptoHandler = NULL; - if (!m_bForceUseSecurityHandler) { - delete m_pSecurityHandler; - m_pSecurityHandler = NULL; - } +void CPDF_Parser::ReleaseEncryptHandler() { + delete m_Syntax.m_pCryptoHandler; + m_Syntax.m_pCryptoHandler = NULL; + if (!m_bForceUseSecurityHandler) { + delete m_pSecurityHandler; + m_pSecurityHandler = NULL; + } } -FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum) -{ - if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { - return 0; - } - if (m_V5Type[objnum] == 1) { - return m_CrossRef[objnum]; - } - if (m_V5Type[objnum] == 2) { - return m_CrossRef[(int32_t)m_CrossRef[objnum]]; - } +FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum) { + if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { return 0; + } + if (m_V5Type[objnum] == 1) { + return m_CrossRef[objnum]; + } + if (m_V5Type[objnum] == 2) { + return m_CrossRef[(int32_t)m_CrossRef[objnum]]; + } + return 0; } -static int32_t GetDirectInteger(CPDF_Dictionary* pDict, const CFX_ByteStringC& key) -{ - CPDF_Object* pObj = pDict->GetElement(key); - if (pObj == NULL) { - return 0; - } - if (pObj->GetType() == PDFOBJ_NUMBER) { - return ((CPDF_Number*)pObj)->GetInteger(); - } +static int32_t GetDirectInteger(CPDF_Dictionary* pDict, + const CFX_ByteStringC& key) { + CPDF_Object* pObj = pDict->GetElement(key); + if (pObj == NULL) { return 0; + } + if (pObj->GetType() == PDFOBJ_NUMBER) { + return ((CPDF_Number*)pObj)->GetInteger(); + } + return 0; } -static FX_BOOL CheckDirectType(CPDF_Dictionary* pDict, const CFX_ByteStringC& key, int32_t iType) -{ - CPDF_Object* pObj = pDict->GetElement(key); - if (!pObj) { - return TRUE; - } - return pObj->GetType() == iType; +static FX_BOOL CheckDirectType(CPDF_Dictionary* pDict, + const CFX_ByteStringC& key, + int32_t iType) { + CPDF_Object* pObj = pDict->GetElement(key); + if (!pObj) { + return TRUE; + } + return pObj->GetType() == iType; } -FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) -{ - if (!LoadCrossRefV4(xrefpos, 0, TRUE, FALSE)) { - return FALSE; - } - m_pTrailer = LoadTrailerV4(); - if (m_pTrailer == NULL) { - return FALSE; - } - int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); - if (xrefsize <= 0 || xrefsize > (1 << 20)) { - return FALSE; - } - m_CrossRef.SetSize(xrefsize); - m_V5Type.SetSize(xrefsize); - CFX_FileSizeArray CrossRefList, XRefStreamList; - CrossRefList.Add(xrefpos); - XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm"))); - if (!CheckDirectType(m_pTrailer, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) { - return FALSE; - } - FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev")); +FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { + if (!LoadCrossRefV4(xrefpos, 0, TRUE, FALSE)) { + return FALSE; + } + m_pTrailer = LoadTrailerV4(); + if (m_pTrailer == NULL) { + return FALSE; + } + int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); + if (xrefsize <= 0 || xrefsize > (1 << 20)) { + return FALSE; + } + m_CrossRef.SetSize(xrefsize); + m_V5Type.SetSize(xrefsize); + CFX_FileSizeArray CrossRefList, XRefStreamList; + CrossRefList.Add(xrefpos); + XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm"))); + if (!CheckDirectType(m_pTrailer, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) { + return FALSE; + } + FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev")); + if (newxrefpos == xrefpos) { + return FALSE; + } + xrefpos = newxrefpos; + while (xrefpos) { + CrossRefList.InsertAt(0, xrefpos); + LoadCrossRefV4(xrefpos, 0, TRUE, FALSE); + CPDF_Dictionary* pDict = LoadTrailerV4(); + if (pDict == NULL) { + return FALSE; + } + if (!CheckDirectType(pDict, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) { + pDict->Release(); + return FALSE; + } + newxrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev")); if (newxrefpos == xrefpos) { - return FALSE; + pDict->Release(); + return FALSE; } xrefpos = newxrefpos; - while (xrefpos) { - CrossRefList.InsertAt(0, xrefpos); - LoadCrossRefV4(xrefpos, 0, TRUE, FALSE); - CPDF_Dictionary* pDict = LoadTrailerV4(); - if (pDict == NULL) { - return FALSE; - } - if (!CheckDirectType(pDict, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) { - pDict->Release(); - return FALSE; - } - newxrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev")); - if (newxrefpos == xrefpos) { - pDict->Release(); - return FALSE; - } - xrefpos = newxrefpos; - XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm"))); - m_Trailers.Add(pDict); - } - for (int32_t i = 0; i < CrossRefList.GetSize(); i ++) - if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) { - return FALSE; - } - return TRUE; + XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm"))); + m_Trailers.Add(pDict); + } + for (int32_t i = 0; i < CrossRefList.GetSize(); i++) + if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) { + return FALSE; + } + return TRUE; } -FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, FX_DWORD dwObjCount) -{ - if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) { - return FALSE; - } - m_pTrailer = LoadTrailerV4(); - if (m_pTrailer == NULL) { - return FALSE; - } - int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); - if (xrefsize == 0) { - return FALSE; - } - CFX_FileSizeArray CrossRefList, XRefStreamList; - CrossRefList.Add(xrefpos); - XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm"))); - xrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev")); - while (xrefpos) { - CrossRefList.InsertAt(0, xrefpos); - LoadCrossRefV4(xrefpos, 0, TRUE, FALSE); - CPDF_Dictionary* pDict = LoadTrailerV4(); - if (pDict == NULL) { - return FALSE; - } - xrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev")); - XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm"))); - m_Trailers.Add(pDict); - } - for (int32_t i = 1; i < CrossRefList.GetSize(); i ++) - if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) { - return FALSE; - } - return TRUE; +FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, + FX_DWORD dwObjCount) { + if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) { + return FALSE; + } + m_pTrailer = LoadTrailerV4(); + if (m_pTrailer == NULL) { + return FALSE; + } + int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); + if (xrefsize == 0) { + return FALSE; + } + CFX_FileSizeArray CrossRefList, XRefStreamList; + CrossRefList.Add(xrefpos); + XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm"))); + xrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev")); + while (xrefpos) { + CrossRefList.InsertAt(0, xrefpos); + LoadCrossRefV4(xrefpos, 0, TRUE, FALSE); + CPDF_Dictionary* pDict = LoadTrailerV4(); + if (pDict == NULL) { + return FALSE; + } + xrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev")); + XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm"))); + m_Trailers.Add(pDict); + } + for (int32_t i = 1; i < CrossRefList.GetSize(); i++) + if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) { + return FALSE; + } + return TRUE; } -FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, FX_DWORD dwObjCount) -{ - FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset; - m_Syntax.RestorePos(dwStartPos); - void* pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); +FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, + FX_DWORD dwObjCount) { + FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset; + m_Syntax.RestorePos(dwStartPos); + void* pResult = + FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(pos); + } + FX_DWORD start_objnum = 0; + FX_DWORD count = dwObjCount; + FX_FILESIZE SavedPos = m_Syntax.SavePos(); + int32_t recordsize = 20; + char* pBuf = FX_Alloc(char, 1024 * recordsize + 1); + pBuf[1024 * recordsize] = '\0'; + int32_t nBlocks = count / 1024 + 1; + for (int32_t block = 0; block < nBlocks; block++) { + int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; + FX_DWORD dwReadSize = block_size * recordsize; + if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_Syntax.m_FileLen) { + FX_Free(pBuf); + return FALSE; + } + if (!m_Syntax.ReadBlock((uint8_t*)pBuf, dwReadSize)) { + FX_Free(pBuf); + return FALSE; + } + for (int32_t i = 0; i < block_size; i++) { + FX_DWORD objnum = start_objnum + block * 1024 + i; + char* pEntry = pBuf + i * recordsize; + if (pEntry[17] == 'f') { + m_CrossRef.SetAtGrow(objnum, 0); + m_V5Type.SetAtGrow(objnum, 0); + } else { + int32_t offset = FXSYS_atoi(pEntry); + if (offset == 0) { + for (int32_t c = 0; c < 10; c++) { + if (pEntry[c] < '0' || pEntry[c] > '9') { + FX_Free(pBuf); + return FALSE; + } + } + } + m_CrossRef.SetAtGrow(objnum, offset); + int32_t version = FXSYS_atoi(pEntry + 11); + if (version >= 1) { + m_bVersionUpdated = TRUE; + } + m_ObjVersion.SetAtGrow(objnum, version); + if (m_CrossRef[objnum] < m_Syntax.m_FileLen) { + void* pResult = FXSYS_bsearch( + &m_CrossRef[objnum], m_SortedOffset.GetData(), + m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(m_CrossRef[objnum]); + } + } + m_V5Type.SetAtGrow(objnum, 1); + } + } + } + FX_Free(pBuf); + m_Syntax.RestorePos(SavedPos + count * recordsize); + return TRUE; +} +FX_BOOL CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, + FX_FILESIZE streampos, + FX_BOOL bSkip, + FX_BOOL bFirst) { + m_Syntax.RestorePos(pos); + if (m_Syntax.GetKeyword() != FX_BSTRC("xref")) { + return FALSE; + } + void* pResult = + FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(pos); + } + if (streampos) { + void* pResult = FXSYS_bsearch(&streampos, m_SortedOffset.GetData(), + m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), + _CompareFileSize); if (pResult == NULL) { - m_SortedOffset.Add(pos); + m_SortedOffset.Add(streampos); } - FX_DWORD start_objnum = 0; - FX_DWORD count = dwObjCount; + } + while (1) { FX_FILESIZE SavedPos = m_Syntax.SavePos(); + FX_BOOL bIsNumber; + CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); + if (word.IsEmpty()) { + return FALSE; + } + if (!bIsNumber) { + m_Syntax.RestorePos(SavedPos); + break; + } + FX_DWORD start_objnum = FXSYS_atoi(word); + if (start_objnum >= (1 << 20)) { + return FALSE; + } + FX_DWORD count = m_Syntax.GetDirectNum(); + m_Syntax.ToNextWord(); + SavedPos = m_Syntax.SavePos(); + FX_BOOL bFirstItem = FALSE; int32_t recordsize = 20; - char* pBuf = FX_Alloc(char, 1024 * recordsize + 1); - pBuf[1024 * recordsize] = '\0'; - int32_t nBlocks = count / 1024 + 1; - for (int32_t block = 0; block < nBlocks; block ++) { + if (bFirst) { + bFirstItem = TRUE; + } + m_dwXrefStartObjNum = start_objnum; + if (!bSkip) { + char* pBuf = FX_Alloc(char, 1024 * recordsize + 1); + pBuf[1024 * recordsize] = '\0'; + int32_t nBlocks = count / 1024 + 1; + FX_BOOL bFirstBlock = TRUE; + for (int32_t block = 0; block < nBlocks; block++) { int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; - FX_DWORD dwReadSize = block_size * recordsize; - if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_Syntax.m_FileLen) { - FX_Free(pBuf); - return FALSE; - } - if (!m_Syntax.ReadBlock((uint8_t*)pBuf, dwReadSize)) { - FX_Free(pBuf); - return FALSE; - } - for (int32_t i = 0; i < block_size; i ++) { - FX_DWORD objnum = start_objnum + block * 1024 + i; - char* pEntry = pBuf + i * recordsize; - if (pEntry[17] == 'f') { - m_CrossRef.SetAtGrow(objnum, 0); - m_V5Type.SetAtGrow(objnum, 0); - } else { - int32_t offset = FXSYS_atoi(pEntry); - if (offset == 0) { - for (int32_t c = 0; c < 10; c ++) { - if (pEntry[c] < '0' || pEntry[c] > '9') { - FX_Free(pBuf); - return FALSE; - } - } - } - m_CrossRef.SetAtGrow(objnum, offset); - int32_t version = FXSYS_atoi(pEntry + 11); - if (version >= 1) { - m_bVersionUpdated = TRUE; - } - m_ObjVersion.SetAtGrow(objnum, version); - if (m_CrossRef[objnum] < m_Syntax.m_FileLen) { - void* pResult = FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_SortedOffset.Add(m_CrossRef[objnum]); - } + m_Syntax.ReadBlock((uint8_t*)pBuf, block_size * recordsize); + for (int32_t i = 0; i < block_size; i++) { + FX_DWORD objnum = start_objnum + block * 1024 + i; + char* pEntry = pBuf + i * recordsize; + if (pEntry[17] == 'f') { + if (bFirstItem) { + objnum = 0; + bFirstItem = FALSE; + } + if (bFirstBlock) { + FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); + int32_t version = FXSYS_atoi(pEntry + 11); + if (offset == 0 && version == 65535 && start_objnum != 0) { + start_objnum--; + objnum = 0; + } + } + m_CrossRef.SetAtGrow(objnum, 0); + m_V5Type.SetAtGrow(objnum, 0); + } else { + FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); + if (offset == 0) { + for (int32_t c = 0; c < 10; c++) { + if (pEntry[c] < '0' || pEntry[c] > '9') { + FX_Free(pBuf); + return FALSE; } - m_V5Type.SetAtGrow(objnum, 1); + } + } + m_CrossRef.SetAtGrow(objnum, offset); + int32_t version = FXSYS_atoi(pEntry + 11); + if (version >= 1) { + m_bVersionUpdated = TRUE; + } + m_ObjVersion.SetAtGrow(objnum, version); + if (m_CrossRef[objnum] < m_Syntax.m_FileLen) { + void* pResult = + FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), + m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), + _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(m_CrossRef[objnum]); + } } + m_V5Type.SetAtGrow(objnum, 1); + } + if (bFirstBlock) { + bFirstBlock = FALSE; + } } + } + FX_Free(pBuf); } - FX_Free(pBuf); m_Syntax.RestorePos(SavedPos + count * recordsize); - return TRUE; -} -FX_BOOL CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, FX_FILESIZE streampos, FX_BOOL bSkip, FX_BOOL bFirst) -{ - m_Syntax.RestorePos(pos); - if (m_Syntax.GetKeyword() != FX_BSTRC("xref")) { - return FALSE; + } + if (streampos) + if (!LoadCrossRefV5(streampos, streampos, FALSE)) { + return FALSE; } - void* pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_SortedOffset.Add(pos); - } - if (streampos) { - void* pResult = FXSYS_bsearch(&streampos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_SortedOffset.Add(streampos); - } + return TRUE; +} +FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { + if (!LoadCrossRefV5(xrefpos, xrefpos, TRUE)) { + return FALSE; + } + while (xrefpos) + if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { + return FALSE; } - while (1) { - FX_FILESIZE SavedPos = m_Syntax.SavePos(); - FX_BOOL bIsNumber; - CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); - if (word.IsEmpty()) { - return FALSE; - } - if (!bIsNumber) { - m_Syntax.RestorePos(SavedPos); + m_ObjectStreamMap.InitHashTable(101, FALSE); + m_bXRefStream = TRUE; + return TRUE; +} +FX_BOOL CPDF_Parser::RebuildCrossRef() { + m_CrossRef.RemoveAll(); + m_V5Type.RemoveAll(); + m_SortedOffset.RemoveAll(); + m_ObjVersion.RemoveAll(); + if (m_pTrailer) { + m_pTrailer->Release(); + m_pTrailer = NULL; + } + int32_t status = 0; + int32_t inside_index = 0; + FX_DWORD objnum = 0, gennum = 0; + int32_t depth = 0; + uint8_t* buffer = FX_Alloc(uint8_t, 4096); + FX_FILESIZE pos = m_Syntax.m_HeaderOffset; + FX_FILESIZE start_pos = 0, start_pos1 = 0; + FX_FILESIZE last_obj = -1, last_xref = -1, last_trailer = -1; + while (pos < m_Syntax.m_FileLen) { + FX_BOOL bOverFlow = FALSE; + FX_DWORD size = (FX_DWORD)(m_Syntax.m_FileLen - pos); + if (size > 4096) { + size = 4096; + } + if (!m_Syntax.m_pFileAccess->ReadBlock(buffer, pos, size)) { + break; + } + for (FX_DWORD i = 0; i < size; i++) { + uint8_t byte = buffer[i]; + switch (status) { + case 0: + if (PDF_CharType[byte] == 'W') { + status = 1; + } + if (byte <= '9' && byte >= '0') { + --i; + status = 1; + } + if (byte == '%') { + inside_index = 0; + status = 9; + } + if (byte == '(') { + status = 10; + depth = 1; + } + if (byte == '<') { + inside_index = 1; + status = 11; + } + if (byte == '\\') { + status = 13; + } + if (byte == 't') { + status = 7; + inside_index = 1; + } + break; + case 1: + if (PDF_CharType[byte] == 'W') { break; - } - FX_DWORD start_objnum = FXSYS_atoi(word); - if (start_objnum >= (1 << 20)) { - return FALSE; - } - FX_DWORD count = m_Syntax.GetDirectNum(); - m_Syntax.ToNextWord(); - SavedPos = m_Syntax.SavePos(); - FX_BOOL bFirstItem = FALSE; - int32_t recordsize = 20; - if (bFirst) { - bFirstItem = TRUE; - } - m_dwXrefStartObjNum = start_objnum; - if (!bSkip) { - char* pBuf = FX_Alloc(char, 1024 * recordsize + 1); - pBuf[1024 * recordsize] = '\0'; - int32_t nBlocks = count / 1024 + 1; - FX_BOOL bFirstBlock = TRUE; - for (int32_t block = 0; block < nBlocks; block ++) { - int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; - m_Syntax.ReadBlock((uint8_t*)pBuf, block_size * recordsize); - for (int32_t i = 0; i < block_size; i ++) { - FX_DWORD objnum = start_objnum + block * 1024 + i; - char* pEntry = pBuf + i * recordsize; - if (pEntry[17] == 'f') { - if (bFirstItem) { - objnum = 0; - bFirstItem = FALSE; - } - if (bFirstBlock) { - FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); - int32_t version = FXSYS_atoi(pEntry + 11); - if (offset == 0 && version == 65535 && start_objnum != 0) { - start_objnum--; - objnum = 0; - } - } - m_CrossRef.SetAtGrow(objnum, 0); - m_V5Type.SetAtGrow(objnum, 0); - } else { - FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); - if (offset == 0) { - for (int32_t c = 0; c < 10; c ++) { - if (pEntry[c] < '0' || pEntry[c] > '9') { - FX_Free(pBuf); - return FALSE; - } + } else if (byte <= '9' && byte >= '0') { + start_pos = pos + i; + status = 2; + objnum = byte - '0'; + } else if (byte == 't') { + status = 7; + inside_index = 1; + } else if (byte == 'x') { + status = 8; + inside_index = 1; + } else { + --i; + status = 0; + } + break; + case 2: + if (byte <= '9' && byte >= '0') { + objnum = objnum * 10 + byte - '0'; + break; + } else if (PDF_CharType[byte] == 'W') { + status = 3; + } else { + --i; + status = 14; + inside_index = 0; + } + break; + case 3: + if (byte <= '9' && byte >= '0') { + start_pos1 = pos + i; + status = 4; + gennum = byte - '0'; + } else if (PDF_CharType[byte] == 'W') { + break; + } else if (byte == 't') { + status = 7; + inside_index = 1; + } else { + --i; + status = 0; + } + break; + case 4: + if (byte <= '9' && byte >= '0') { + gennum = gennum * 10 + byte - '0'; + break; + } else if (PDF_CharType[byte] == 'W') { + status = 5; + } else { + --i; + status = 0; + } + break; + case 5: + if (byte == 'o') { + status = 6; + inside_index = 1; + } else if (PDF_CharType[byte] == 'W') { + break; + } else if (byte <= '9' && byte >= '0') { + objnum = gennum; + gennum = byte - '0'; + start_pos = start_pos1; + start_pos1 = pos + i; + status = 4; + } else if (byte == 't') { + status = 7; + inside_index = 1; + } else { + --i; + status = 0; + } + break; + case 6: + switch (inside_index) { + case 1: + if (byte != 'b') { + --i; + status = 0; + } else { + inside_index++; + } + break; + case 2: + if (byte != 'j') { + --i; + status = 0; + } else { + inside_index++; + } + break; + case 3: + if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') { + if (objnum > 0x1000000) { + status = 0; + break; + } + FX_FILESIZE obj_pos = start_pos - m_Syntax.m_HeaderOffset; + last_obj = start_pos; + void* pResult = + FXSYS_bsearch(&obj_pos, m_SortedOffset.GetData(), + m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), + _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(obj_pos); + } + FX_FILESIZE obj_end = 0; + CPDF_Object* pObject = ParseIndirectObjectAtByStrict( + m_pDocument, obj_pos, objnum, NULL, &obj_end); + if (pObject) { + int iType = pObject->GetType(); + if (iType == PDFOBJ_STREAM) { + CPDF_Stream* pStream = (CPDF_Stream*)pObject; + CPDF_Dictionary* pDict = pStream->GetDict(); + if (pDict) { + if (pDict->KeyExist(FX_BSTRC("Type"))) { + CFX_ByteString bsValue = + pDict->GetString(FX_BSTRC("Type")); + if (bsValue == FX_BSTRC("XRef") && + pDict->KeyExist(FX_BSTRC("Size"))) { + CPDF_Object* pRoot = + pDict->GetElement(FX_BSTRC("Root")); + if (pRoot && pRoot->GetDict() && + pRoot->GetDict()->GetElement(FX_BSTRC("Pages"))) { + if (m_pTrailer) { + m_pTrailer->Release(); } + m_pTrailer = (CPDF_Dictionary*)pDict->Clone(); + } } - m_CrossRef.SetAtGrow(objnum, offset); - int32_t version = FXSYS_atoi(pEntry + 11); - if (version >= 1) { - m_bVersionUpdated = TRUE; + } + } + } + } + FX_FILESIZE offset = 0; + m_Syntax.RestorePos(obj_pos); + offset = m_Syntax.FindTag(FX_BSTRC("obj"), 0); + if (offset == -1) { + offset = 0; + } else { + offset += 3; + } + FX_FILESIZE nLen = obj_end - obj_pos - offset; + if ((FX_DWORD)nLen > size - i) { + pos = obj_end + m_Syntax.m_HeaderOffset; + bOverFlow = TRUE; + } else { + i += (FX_DWORD)nLen; + } + if (m_CrossRef.GetSize() > (int32_t)objnum && + m_CrossRef[objnum]) { + if (pObject) { + FX_DWORD oldgen = m_ObjVersion.GetAt(objnum); + m_CrossRef[objnum] = obj_pos; + m_ObjVersion.SetAt(objnum, (int16_t)gennum); + if (oldgen != gennum) { + m_bVersionUpdated = TRUE; + } + } + } else { + m_CrossRef.SetAtGrow(objnum, obj_pos); + m_V5Type.SetAtGrow(objnum, 1); + m_ObjVersion.SetAtGrow(objnum, (int16_t)gennum); + } + if (pObject) { + pObject->Release(); + } + } + --i; + status = 0; + break; + } + break; + case 7: + if (inside_index == 7) { + if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') { + last_trailer = pos + i - 7; + m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset); + CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0); + if (pObj) { + if (pObj->GetType() != PDFOBJ_DICTIONARY && + pObj->GetType() != PDFOBJ_STREAM) { + pObj->Release(); + } else { + CPDF_Dictionary* pTrailer = NULL; + if (pObj->GetType() == PDFOBJ_STREAM) { + pTrailer = ((CPDF_Stream*)pObj)->GetDict(); + } else { + pTrailer = (CPDF_Dictionary*)pObj; + } + if (pTrailer) { + if (m_pTrailer) { + CPDF_Object* pRoot = + pTrailer->GetElement(FX_BSTRC("Root")); + if (pRoot == NULL || + (pRoot->GetType() == PDFOBJ_REFERENCE && + (FX_DWORD)m_CrossRef.GetSize() > + ((CPDF_Reference*)pRoot)->GetRefObjNum() && + m_CrossRef.GetAt(((CPDF_Reference*)pRoot) + ->GetRefObjNum()) != 0)) { + FX_POSITION pos = pTrailer->GetStartPos(); + while (pos) { + CFX_ByteString key; + CPDF_Object* pObj = + pTrailer->GetNextElement(pos, key); + m_pTrailer->SetAt(key, pObj->Clone(), m_pDocument); } - m_ObjVersion.SetAtGrow(objnum, version); - if (m_CrossRef[objnum] < m_Syntax.m_FileLen) { - void* pResult = FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_SortedOffset.Add(m_CrossRef[objnum]); - } + pObj->Release(); + } else { + pObj->Release(); + } + } else { + if (pObj->GetType() == PDFOBJ_STREAM) { + m_pTrailer = (CPDF_Dictionary*)pTrailer->Clone(); + pObj->Release(); + } else { + m_pTrailer = pTrailer; + } + FX_FILESIZE dwSavePos = m_Syntax.SavePos(); + CFX_ByteString strWord = m_Syntax.GetKeyword(); + if (!strWord.Compare(FX_BSTRC("startxref"))) { + FX_BOOL bNumber = FALSE; + CFX_ByteString bsOffset = m_Syntax.GetNextWord(bNumber); + if (bNumber) { + m_LastXRefOffset = FXSYS_atoi(bsOffset); } - m_V5Type.SetAtGrow(objnum, 1); - } - if (bFirstBlock) { - bFirstBlock = FALSE; + } + m_Syntax.RestorePos(dwSavePos); } + } else { + pObj->Release(); + } } + } } - FX_Free(pBuf); - } - m_Syntax.RestorePos(SavedPos + count * recordsize); + --i; + status = 0; + } else if (byte == "trailer"[inside_index]) { + inside_index++; + } else { + --i; + status = 0; + } + break; + case 8: + if (inside_index == 4) { + last_xref = pos + i - 4; + status = 1; + } else if (byte == "xref"[inside_index]) { + inside_index++; + } else { + --i; + status = 0; + } + break; + case 9: + if (byte == '\r' || byte == '\n') { + status = 0; + } + break; + case 10: + if (byte == ')') { + if (depth > 0) { + depth--; + } + } else if (byte == '(') { + depth++; + } + if (!depth) { + status = 0; + } + break; + case 11: + if (byte == '<' && inside_index == 1) { + status = 12; + } else if (byte == '>') { + status = 0; + } + inside_index = 0; + break; + case 12: + --i; + status = 0; + break; + case 13: + if (PDF_CharType[byte] == 'D' || PDF_CharType[byte] == 'W') { + --i; + status = 0; + } + break; + case 14: + if (PDF_CharType[byte] == 'W') { + status = 0; + } else if (byte == '%' || byte == '(' || byte == '<' || + byte == '\\') { + status = 0; + --i; + } else if (inside_index == 6) { + status = 0; + --i; + } else if (byte == "endobj"[inside_index]) { + inside_index++; + } + break; + } + if (bOverFlow) { + size = 0; + break; + } + } + pos += size; + } + if (last_xref != -1 && last_xref > last_obj) { + last_trailer = last_xref; + } else if (last_trailer == -1 || last_xref < last_obj) { + last_trailer = m_Syntax.m_FileLen; + } + FX_FILESIZE offset = last_trailer - m_Syntax.m_HeaderOffset; + void* pResult = + FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(offset); + } + FX_Free(buffer); + return TRUE; +} +static FX_DWORD _GetVarInt(const uint8_t* p, int32_t n) { + FX_DWORD result = 0; + for (int32_t i = 0; i < n; i++) { + result = result * 256 + p[i]; + } + return result; +} +FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, + FX_FILESIZE& prev, + FX_BOOL bMainXRef) { + CPDF_Stream* pStream = + (CPDF_Stream*)ParseIndirectObjectAt(m_pDocument, pos, 0, NULL); + if (!pStream) { + return FALSE; + } + if (m_pDocument) { + CPDF_Dictionary* pDict = m_pDocument->GetRoot(); + if (!pDict || pDict->GetObjNum() != pStream->m_ObjNum) { + m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream); + } else { + if (pStream->GetType() == PDFOBJ_STREAM) { + pStream->Release(); + } + return FALSE; } - if (streampos) - if (!LoadCrossRefV5(streampos, streampos, FALSE)) { + } + if (pStream->GetType() != PDFOBJ_STREAM) { + return FALSE; + } + prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev")); + int32_t size = pStream->GetDict()->GetInteger(FX_BSTRC("Size")); + if (size < 0) { + pStream->Release(); + return FALSE; + } + if (bMainXRef) { + m_pTrailer = (CPDF_Dictionary*)pStream->GetDict()->Clone(); + m_CrossRef.SetSize(size); + if (m_V5Type.SetSize(size)) { + FXSYS_memset(m_V5Type.GetData(), 0, size); + } + } else { + m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone()); + } + std::vector > arrIndex; + CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index")); + if (pArray) { + FX_DWORD nPairSize = pArray->GetCount() / 2; + for (FX_DWORD i = 0; i < nPairSize; i++) { + CPDF_Object* pStartNumObj = pArray->GetElement(i * 2); + CPDF_Object* pCountObj = pArray->GetElement(i * 2 + 1); + if (pStartNumObj && pStartNumObj->GetType() == PDFOBJ_NUMBER && + pCountObj && pCountObj->GetType() == PDFOBJ_NUMBER) { + int nStartNum = pStartNumObj->GetInteger(); + int nCount = pCountObj->GetInteger(); + if (nStartNum >= 0 && nCount > 0) { + arrIndex.push_back(std::make_pair(nStartNum, nCount)); + } + } + } + } + if (arrIndex.size() == 0) { + arrIndex.push_back(std::make_pair(0, size)); + } + pArray = pStream->GetDict()->GetArray(FX_BSTRC("W")); + if (pArray == NULL) { + pStream->Release(); + return FALSE; + } + CFX_DWordArray WidthArray; + FX_SAFE_DWORD dwAccWidth = 0; + for (FX_DWORD i = 0; i < pArray->GetCount(); i++) { + WidthArray.Add(pArray->GetInteger(i)); + dwAccWidth += WidthArray[i]; + } + if (!dwAccWidth.IsValid() || WidthArray.GetSize() < 3) { + pStream->Release(); + return FALSE; + } + FX_DWORD totalWidth = dwAccWidth.ValueOrDie(); + CPDF_StreamAcc acc; + acc.LoadAllData(pStream); + const uint8_t* pData = acc.GetData(); + FX_DWORD dwTotalSize = acc.GetSize(); + FX_DWORD segindex = 0; + for (FX_DWORD i = 0; i < arrIndex.size(); i++) { + int32_t startnum = arrIndex[i].first; + if (startnum < 0) { + continue; + } + m_dwXrefStartObjNum = + pdfium::base::checked_cast(startnum); + FX_DWORD count = + pdfium::base::checked_cast(arrIndex[i].second); + FX_SAFE_DWORD dwCaculatedSize = segindex; + dwCaculatedSize += count; + dwCaculatedSize *= totalWidth; + if (!dwCaculatedSize.IsValid() || + dwCaculatedSize.ValueOrDie() > dwTotalSize) { + continue; + } + const uint8_t* segstart = pData + segindex * totalWidth; + FX_SAFE_DWORD dwMaxObjNum = startnum; + dwMaxObjNum += count; + FX_DWORD dwV5Size = + pdfium::base::checked_cast(m_V5Type.GetSize()); + if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size) { + continue; + } + for (FX_DWORD j = 0; j < count; j++) { + int32_t type = 1; + const uint8_t* entrystart = segstart + j * totalWidth; + if (WidthArray[0]) { + type = _GetVarInt(entrystart, WidthArray[0]); + } + if (m_V5Type[startnum + j] == 255) { + FX_FILESIZE offset = + _GetVarInt(entrystart + WidthArray[0], WidthArray[1]); + m_CrossRef[startnum + j] = offset; + void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), + m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(offset); + } + continue; + } + if (m_V5Type[startnum + j]) { + continue; + } + m_V5Type[startnum + j] = type; + if (type == 0) { + m_CrossRef[startnum + j] = 0; + } else { + FX_FILESIZE offset = + _GetVarInt(entrystart + WidthArray[0], WidthArray[1]); + m_CrossRef[startnum + j] = offset; + if (type == 1) { + void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), + m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { + m_SortedOffset.Add(offset); + } + } else { + if (offset < 0 || offset >= m_V5Type.GetSize()) { + pStream->Release(); return FALSE; + } + m_V5Type[offset] = 255; } + } + } + segindex += count; + } + pStream->Release(); + return TRUE; +} +CPDF_Array* CPDF_Parser::GetIDArray() { + CPDF_Object* pID = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("ID")) : NULL; + if (pID == NULL) { + return NULL; + } + if (pID->GetType() == PDFOBJ_REFERENCE) { + pID = ParseIndirectObject(NULL, ((CPDF_Reference*)pID)->GetRefObjNum()); + m_pTrailer->SetAt(FX_BSTRC("ID"), pID); + } + if (pID == NULL || pID->GetType() != PDFOBJ_ARRAY) { + return NULL; + } + return (CPDF_Array*)pID; +} +FX_DWORD CPDF_Parser::GetRootObjNum() { + CPDF_Object* pRef = + m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Root")) : NULL; + if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { + return 0; + } + return ((CPDF_Reference*)pRef)->GetRefObjNum(); +} +FX_DWORD CPDF_Parser::GetInfoObjNum() { + CPDF_Object* pRef = + m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Info")) : NULL; + if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { + return 0; + } + return ((CPDF_Reference*)pRef)->GetRefObjNum(); +} +FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) { + bForm = FALSE; + if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { + return TRUE; + } + if (m_V5Type[objnum] == 0) { + return TRUE; + } + if (m_V5Type[objnum] == 2) { + return TRUE; + } + FX_FILESIZE pos = m_CrossRef[objnum]; + void* pResult = + FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { return TRUE; + } + if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == + m_SortedOffset.GetSize() - 1) { + return FALSE; + } + FX_FILESIZE size = ((FX_FILESIZE*)pResult)[1] - pos; + FX_FILESIZE SavedPos = m_Syntax.SavePos(); + m_Syntax.RestorePos(pos); + bForm = m_Syntax.SearchMultiWord(FX_BSTRC("/Form\0stream"), TRUE, size) == 0; + m_Syntax.RestorePos(SavedPos); + return TRUE; } -FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) -{ - if (!LoadCrossRefV5(xrefpos, xrefpos, TRUE)) { - return FALSE; +CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList, + FX_DWORD objnum, + PARSE_CONTEXT* pContext) { + if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { + return NULL; + } + if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) { + FX_FILESIZE pos = m_CrossRef[objnum]; + if (pos <= 0) { + return NULL; + } + return ParseIndirectObjectAt(pObjList, pos, objnum, pContext); + } + if (m_V5Type[objnum] == 2) { + CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]); + if (pObjStream == NULL) { + return NULL; + } + int32_t n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N")); + int32_t offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First")); + CPDF_SyntaxParser syntax; + CFX_SmartPointer file(FX_CreateMemoryStream( + (uint8_t*)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE)); + syntax.InitParser(file.Get(), 0); + CPDF_Object* pRet = NULL; + while (n) { + FX_DWORD thisnum = syntax.GetDirectNum(); + FX_DWORD thisoff = syntax.GetDirectNum(); + if (thisnum == objnum) { + syntax.RestorePos(offset + thisoff); + pRet = syntax.GetObject(pObjList, 0, 0, pContext); + break; + } + n--; } - while (xrefpos) - if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { - return FALSE; - } - m_ObjectStreamMap.InitHashTable(101, FALSE); - m_bXRefStream = TRUE; - return TRUE; + return pRet; + } + return NULL; } -FX_BOOL CPDF_Parser::RebuildCrossRef() -{ - m_CrossRef.RemoveAll(); - m_V5Type.RemoveAll(); - m_SortedOffset.RemoveAll(); - m_ObjVersion.RemoveAll(); - if (m_pTrailer) { - m_pTrailer->Release(); - m_pTrailer = NULL; - } - int32_t status = 0; - int32_t inside_index = 0; - FX_DWORD objnum = 0, gennum = 0; - int32_t depth = 0; - uint8_t* buffer = FX_Alloc(uint8_t, 4096); - FX_FILESIZE pos = m_Syntax.m_HeaderOffset; - FX_FILESIZE start_pos = 0, start_pos1 = 0; - FX_FILESIZE last_obj = -1, last_xref = -1, last_trailer = -1; - while (pos < m_Syntax.m_FileLen) { - FX_BOOL bOverFlow = FALSE; - FX_DWORD size = (FX_DWORD)(m_Syntax.m_FileLen - pos); - if (size > 4096) { - size = 4096; - } - if (!m_Syntax.m_pFileAccess->ReadBlock(buffer, pos, size)) { - break; - } - for (FX_DWORD i = 0; i < size; i ++) { - uint8_t byte = buffer[i]; - switch (status) { - case 0: - if (PDF_CharType[byte] == 'W') { - status = 1; - } - if (byte <= '9' && byte >= '0') { - --i; - status = 1; - } - if (byte == '%') { - inside_index = 0; - status = 9; - } - if (byte == '(') { - status = 10; - depth = 1; - } - if (byte == '<') { - inside_index = 1; - status = 11; - } - if (byte == '\\') { - status = 13; - } - if (byte == 't') { - status = 7; - inside_index = 1; - } - break; - case 1: - if (PDF_CharType[byte] == 'W') { - break; - } else if (byte <= '9' && byte >= '0') { - start_pos = pos + i; - status = 2; - objnum = byte - '0'; - } else if (byte == 't') { - status = 7; - inside_index = 1; - } else if (byte == 'x') { - status = 8; - inside_index = 1; - } else { - --i; - status = 0; - } - break; - case 2: - if (byte <= '9' && byte >= '0') { - objnum = objnum * 10 + byte - '0'; - break; - } else if (PDF_CharType[byte] == 'W') { - status = 3; - } else { - --i; - status = 14; - inside_index = 0; - } - break; - case 3: - if (byte <= '9' && byte >= '0') { - start_pos1 = pos + i; - status = 4; - gennum = byte - '0'; - } else if (PDF_CharType[byte] == 'W') { - break; - } else if (byte == 't') { - status = 7; - inside_index = 1; - } else { - --i; - status = 0; - } - break; - case 4: - if (byte <= '9' && byte >= '0') { - gennum = gennum * 10 + byte - '0'; - break; - } else if (PDF_CharType[byte] == 'W') { - status = 5; - } else { - --i; - status = 0; - } - break; - case 5: - if (byte == 'o') { - status = 6; - inside_index = 1; - } else if (PDF_CharType[byte] == 'W') { - break; - } else if (byte <= '9' && byte >= '0') { - objnum = gennum; - gennum = byte - '0'; - start_pos = start_pos1; - start_pos1 = pos + i; - status = 4; - } else if (byte == 't') { - status = 7; - inside_index = 1; - } else { - --i; - status = 0; - } - break; - case 6: - switch (inside_index) { - case 1: - if (byte != 'b') { - --i; - status = 0; - } else { - inside_index ++; - } - break; - case 2: - if (byte != 'j') { - --i; - status = 0; - } else { - inside_index ++; - } - break; - case 3: - if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') { - if (objnum > 0x1000000) { - status = 0; - break; - } - FX_FILESIZE obj_pos = start_pos - m_Syntax.m_HeaderOffset; - last_obj = start_pos; - void* pResult = FXSYS_bsearch(&obj_pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_SortedOffset.Add(obj_pos); - } - FX_FILESIZE obj_end = 0; - CPDF_Object *pObject = ParseIndirectObjectAtByStrict(m_pDocument, obj_pos, objnum, NULL, &obj_end); - if (pObject) { - int iType = pObject->GetType(); - if (iType == PDFOBJ_STREAM) { - CPDF_Stream* pStream = (CPDF_Stream*)pObject; - CPDF_Dictionary* pDict = pStream->GetDict(); - if (pDict) { - if (pDict->KeyExist(FX_BSTRC("Type"))) { - CFX_ByteString bsValue = pDict->GetString(FX_BSTRC("Type")); - if (bsValue == FX_BSTRC("XRef") && pDict->KeyExist(FX_BSTRC("Size"))) { - CPDF_Object* pRoot = pDict->GetElement(FX_BSTRC("Root")); - if (pRoot && pRoot->GetDict() && pRoot->GetDict()->GetElement(FX_BSTRC("Pages"))) { - if (m_pTrailer) { - m_pTrailer->Release(); - } - m_pTrailer = (CPDF_Dictionary*)pDict->Clone(); - } - } - } - } - } - } - FX_FILESIZE offset = 0; - m_Syntax.RestorePos(obj_pos); - offset = m_Syntax.FindTag(FX_BSTRC("obj"), 0); - if (offset == -1) { - offset = 0; - } else { - offset += 3; - } - FX_FILESIZE nLen = obj_end - obj_pos - offset; - if ((FX_DWORD)nLen > size - i) { - pos = obj_end + m_Syntax.m_HeaderOffset; - bOverFlow = TRUE; - } else { - i += (FX_DWORD)nLen; - } - if (m_CrossRef.GetSize() > (int32_t)objnum && m_CrossRef[objnum]) { - if (pObject) { - FX_DWORD oldgen = m_ObjVersion.GetAt(objnum); - m_CrossRef[objnum] = obj_pos; - m_ObjVersion.SetAt(objnum, (int16_t)gennum); - if (oldgen != gennum) { - m_bVersionUpdated = TRUE; - } - } - } else { - m_CrossRef.SetAtGrow(objnum, obj_pos); - m_V5Type.SetAtGrow(objnum, 1); - m_ObjVersion.SetAtGrow(objnum, (int16_t)gennum); - } - if (pObject) { - pObject->Release(); - } - } - --i; - status = 0; - break; - } - break; - case 7: - if (inside_index == 7) { - if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') { - last_trailer = pos + i - 7; - m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset); - CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0); - if (pObj) { - if (pObj->GetType() != PDFOBJ_DICTIONARY && pObj->GetType() != PDFOBJ_STREAM) { - pObj->Release(); - } else { - CPDF_Dictionary* pTrailer = NULL; - if (pObj->GetType() == PDFOBJ_STREAM) { - pTrailer = ((CPDF_Stream*)pObj)->GetDict(); - } else { - pTrailer = (CPDF_Dictionary*)pObj; - } - if (pTrailer) { - if (m_pTrailer) { - CPDF_Object* pRoot = pTrailer->GetElement(FX_BSTRC("Root")); - if (pRoot == NULL || (pRoot->GetType() == PDFOBJ_REFERENCE && - (FX_DWORD)m_CrossRef.GetSize() > ((CPDF_Reference*)pRoot)->GetRefObjNum() && - m_CrossRef.GetAt(((CPDF_Reference*)pRoot)->GetRefObjNum()) != 0)) { - FX_POSITION pos = pTrailer->GetStartPos(); - while (pos) { - CFX_ByteString key; - CPDF_Object* pObj = pTrailer->GetNextElement(pos, key); - m_pTrailer->SetAt(key, pObj->Clone(), m_pDocument); - } - pObj->Release(); - } else { - pObj->Release(); - } - } else { - if (pObj->GetType() == PDFOBJ_STREAM) { - m_pTrailer = (CPDF_Dictionary*)pTrailer->Clone(); - pObj->Release(); - } else { - m_pTrailer = pTrailer; - } - FX_FILESIZE dwSavePos = m_Syntax.SavePos(); - CFX_ByteString strWord = m_Syntax.GetKeyword(); - if (!strWord.Compare(FX_BSTRC("startxref"))) { - FX_BOOL bNumber = FALSE; - CFX_ByteString bsOffset = m_Syntax.GetNextWord(bNumber); - if (bNumber) { - m_LastXRefOffset = FXSYS_atoi(bsOffset); - } - } - m_Syntax.RestorePos(dwSavePos); - } - } else { - pObj->Release(); - } - } - } - } - --i; - status = 0; - } else if (byte == "trailer"[inside_index]) { - inside_index ++; - } else { - --i; - status = 0; - } - break; - case 8: - if (inside_index == 4) { - last_xref = pos + i - 4; - status = 1; - } else if (byte == "xref"[inside_index]) { - inside_index ++; - } else { - --i; - status = 0; - } - break; - case 9: - if (byte == '\r' || byte == '\n') { - status = 0; - } - break; - case 10: - if (byte == ')') { - if (depth > 0) { - depth--; - } - } else if (byte == '(') { - depth++; - } - if (!depth) { - status = 0; - } - break; - case 11: - if (byte == '<' && inside_index == 1) { - status = 12; - } else if (byte == '>') { - status = 0; - } - inside_index = 0; - break; - case 12: - --i; - status = 0; - break; - case 13: - if (PDF_CharType[byte] == 'D' || PDF_CharType[byte] == 'W') { - --i; - status = 0; - } - break; - case 14: - if (PDF_CharType[byte] == 'W') { - status = 0; - } else if (byte == '%' || byte == '(' || byte == '<' || byte == '\\') { - status = 0; - --i; - } else if (inside_index == 6) { - status = 0; - --i; - } else if (byte == "endobj"[inside_index]) { - inside_index++; - } - break; - } - if (bOverFlow) { - size = 0; - break; - } - } - pos += size; - } - if (last_xref != -1 && last_xref > last_obj) { - last_trailer = last_xref; - } else if (last_trailer == -1 || last_xref < last_obj) { - last_trailer = m_Syntax.m_FileLen; - } - FX_FILESIZE offset = last_trailer - m_Syntax.m_HeaderOffset; - void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); +CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum) { + CPDF_StreamAcc* pStreamAcc = NULL; + if (m_ObjectStreamMap.Lookup((void*)(uintptr_t)objnum, (void*&)pStreamAcc)) { + return pStreamAcc; + } + const CPDF_Stream* pStream = + m_pDocument ? (CPDF_Stream*)m_pDocument->GetIndirectObject(objnum) : NULL; + if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) { + return NULL; + } + pStreamAcc = new CPDF_StreamAcc; + pStreamAcc->LoadAllData(pStream); + m_ObjectStreamMap.SetAt((void*)(uintptr_t)objnum, pStreamAcc); + return pStreamAcc; +} +FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum) { + if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { + return 0; + } + if (m_V5Type[objnum] == 2) { + objnum = (FX_DWORD)m_CrossRef[objnum]; + } + if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) { + FX_FILESIZE offset = m_CrossRef[objnum]; + if (offset == 0) { + return 0; + } + void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), + m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), + _CompareFileSize); if (pResult == NULL) { - m_SortedOffset.Add(offset); + return 0; } - FX_Free(buffer); - return TRUE; -} -static FX_DWORD _GetVarInt(const uint8_t* p, int32_t n) -{ - FX_DWORD result = 0; - for (int32_t i = 0; i < n; i ++) { - result = result * 256 + p[i]; + if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == + m_SortedOffset.GetSize() - 1) { + return 0; } - return result; + return ((FX_FILESIZE*)pResult)[1] - offset; + } + return 0; } -FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL bMainXRef) -{ - CPDF_Stream* pStream = (CPDF_Stream*)ParseIndirectObjectAt(m_pDocument, pos, 0, NULL); - if (!pStream) { - return FALSE; - } - if (m_pDocument) { - CPDF_Dictionary * pDict = m_pDocument->GetRoot(); - if (!pDict || pDict->GetObjNum() != pStream->m_ObjNum) { - m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream); +void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, + uint8_t*& pBuffer, + FX_DWORD& size) { + pBuffer = NULL; + size = 0; + if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { + return; + } + if (m_V5Type[objnum] == 2) { + CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]); + if (pObjStream == NULL) { + return; + } + int32_t n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N")); + int32_t offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First")); + CPDF_SyntaxParser syntax; + const uint8_t* pData = pObjStream->GetData(); + FX_DWORD totalsize = pObjStream->GetSize(); + CFX_SmartPointer file( + FX_CreateMemoryStream((uint8_t*)pData, (size_t)totalsize, FALSE)); + syntax.InitParser(file.Get(), 0); + while (n) { + FX_DWORD thisnum = syntax.GetDirectNum(); + FX_DWORD thisoff = syntax.GetDirectNum(); + if (thisnum == objnum) { + if (n == 1) { + size = totalsize - (thisoff + offset); } else { - if (pStream->GetType() == PDFOBJ_STREAM) { - pStream->Release(); - } - return FALSE; + syntax.GetDirectNum(); // Skip nextnum. + FX_DWORD nextoff = syntax.GetDirectNum(); + size = nextoff - thisoff; } + pBuffer = FX_Alloc(uint8_t, size); + FXSYS_memcpy(pBuffer, pData + thisoff + offset, size); + return; + } + n--; } - if (pStream->GetType() != PDFOBJ_STREAM) { - return FALSE; - } - prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev")); - int32_t size = pStream->GetDict()->GetInteger(FX_BSTRC("Size")); - if (size < 0) { - pStream->Release(); - return FALSE; - } - if (bMainXRef) { - m_pTrailer = (CPDF_Dictionary*)pStream->GetDict()->Clone(); - m_CrossRef.SetSize(size); - if (m_V5Type.SetSize(size)) { - FXSYS_memset(m_V5Type.GetData(), 0, size); - } - } else { - m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone()); - } - std::vector > arrIndex; - CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index")); - if (pArray) { - FX_DWORD nPairSize = pArray->GetCount() / 2; - for (FX_DWORD i = 0; i < nPairSize; i++) { - CPDF_Object* pStartNumObj = pArray->GetElement(i * 2); - CPDF_Object* pCountObj = pArray->GetElement(i * 2 + 1); - if (pStartNumObj && pStartNumObj->GetType() == PDFOBJ_NUMBER - && pCountObj && pCountObj->GetType() == PDFOBJ_NUMBER) { - int nStartNum = pStartNumObj->GetInteger(); - int nCount = pCountObj->GetInteger(); - if (nStartNum >= 0 && nCount > 0) { - arrIndex.push_back(std::make_pair(nStartNum, nCount)); - } - } - } + return; + } + if (m_V5Type[objnum] == 1) { + FX_FILESIZE pos = m_CrossRef[objnum]; + if (pos == 0) { + return; } - if (arrIndex.size() == 0) { - arrIndex.push_back(std::make_pair(0, size)); + FX_FILESIZE SavedPos = m_Syntax.SavePos(); + m_Syntax.RestorePos(pos); + FX_BOOL bIsNumber; + CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); + if (!bIsNumber) { + m_Syntax.RestorePos(SavedPos); + return; } - pArray = pStream->GetDict()->GetArray(FX_BSTRC("W")); - if (pArray == NULL) { - pStream->Release(); - return FALSE; + FX_DWORD parser_objnum = FXSYS_atoi(word); + if (parser_objnum && parser_objnum != objnum) { + m_Syntax.RestorePos(SavedPos); + return; } - CFX_DWordArray WidthArray; - FX_SAFE_DWORD dwAccWidth = 0; - for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) { - WidthArray.Add(pArray->GetInteger(i)); - dwAccWidth += WidthArray[i]; + word = m_Syntax.GetNextWord(bIsNumber); + if (!bIsNumber) { + m_Syntax.RestorePos(SavedPos); + return; } - if (!dwAccWidth.IsValid() || WidthArray.GetSize() < 3) { - pStream->Release(); - return FALSE; + if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) { + m_Syntax.RestorePos(SavedPos); + return; } - FX_DWORD totalWidth = dwAccWidth.ValueOrDie(); - CPDF_StreamAcc acc; - acc.LoadAllData(pStream); - const uint8_t* pData = acc.GetData(); - FX_DWORD dwTotalSize = acc.GetSize(); - FX_DWORD segindex = 0; - for (FX_DWORD i = 0; i < arrIndex.size(); i ++) { - int32_t startnum = arrIndex[i].first; - if (startnum < 0) { - continue; - } - m_dwXrefStartObjNum = pdfium::base::checked_cast (startnum); - FX_DWORD count = pdfium::base::checked_cast (arrIndex[i].second); - FX_SAFE_DWORD dwCaculatedSize = segindex; - dwCaculatedSize += count; - dwCaculatedSize *= totalWidth; - if (!dwCaculatedSize.IsValid() || dwCaculatedSize.ValueOrDie() > dwTotalSize) { - continue; + void* pResult = + FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { + m_Syntax.RestorePos(SavedPos); + return; + } + FX_FILESIZE nextoff = ((FX_FILESIZE*)pResult)[1]; + FX_BOOL bNextOffValid = FALSE; + if (nextoff != pos) { + m_Syntax.RestorePos(nextoff); + word = m_Syntax.GetNextWord(bIsNumber); + if (word == FX_BSTRC("xref")) { + bNextOffValid = TRUE; + } else if (bIsNumber) { + word = m_Syntax.GetNextWord(bIsNumber); + if (bIsNumber && m_Syntax.GetKeyword() == FX_BSTRC("obj")) { + bNextOffValid = TRUE; } - const uint8_t* segstart = pData + segindex * totalWidth; - FX_SAFE_DWORD dwMaxObjNum = startnum; - dwMaxObjNum += count; - FX_DWORD dwV5Size = pdfium::base::checked_cast (m_V5Type.GetSize()); - if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size) { - continue; + } + } + if (!bNextOffValid) { + m_Syntax.RestorePos(pos); + while (1) { + if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) { + break; } - for (FX_DWORD j = 0; j < count; j ++) { - int32_t type = 1; - const uint8_t* entrystart = segstart + j * totalWidth; - if (WidthArray[0]) { - type = _GetVarInt(entrystart, WidthArray[0]); - } - if (m_V5Type[startnum + j] == 255) { - FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]); - m_CrossRef[startnum + j] = offset; - void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_SortedOffset.Add(offset); - } - continue; - } - if (m_V5Type[startnum + j]) { - continue; - } - m_V5Type[startnum + j] = type; - if (type == 0) { - m_CrossRef[startnum + j] = 0; - } else { - FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]); - m_CrossRef[startnum + j] = offset; - if (type == 1) { - void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_SortedOffset.Add(offset); - } - } else { - if (offset < 0 || offset >= m_V5Type.GetSize()) { - pStream->Release(); - return FALSE; - } - m_V5Type[offset] = 255; - } - } + if (m_Syntax.SavePos() == m_Syntax.m_FileLen) { + break; } - segindex += count; + } + nextoff = m_Syntax.SavePos(); } - pStream->Release(); - return TRUE; + size = (FX_DWORD)(nextoff - pos); + pBuffer = FX_Alloc(uint8_t, size); + m_Syntax.RestorePos(pos); + m_Syntax.ReadBlock(pBuffer, size); + m_Syntax.RestorePos(SavedPos); + } } -CPDF_Array* CPDF_Parser::GetIDArray() -{ - CPDF_Object* pID = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("ID")) : NULL; - if (pID == NULL) { - return NULL; - } - if (pID->GetType() == PDFOBJ_REFERENCE) { - pID = ParseIndirectObject(NULL, ((CPDF_Reference*)pID)->GetRefObjNum()); - m_pTrailer->SetAt(FX_BSTRC("ID"), pID); - } - if (pID == NULL || pID->GetType() != PDFOBJ_ARRAY) { - return NULL; - } - return (CPDF_Array*)pID; +CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList, + FX_FILESIZE pos, + FX_DWORD objnum, + PARSE_CONTEXT* pContext) { + FX_FILESIZE SavedPos = m_Syntax.SavePos(); + m_Syntax.RestorePos(pos); + FX_BOOL bIsNumber; + CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); + if (!bIsNumber) { + m_Syntax.RestorePos(SavedPos); + return NULL; + } + FX_FILESIZE objOffset = m_Syntax.SavePos(); + objOffset -= word.GetLength(); + FX_DWORD parser_objnum = FXSYS_atoi(word); + if (objnum && parser_objnum != objnum) { + m_Syntax.RestorePos(SavedPos); + return NULL; + } + word = m_Syntax.GetNextWord(bIsNumber); + if (!bIsNumber) { + m_Syntax.RestorePos(SavedPos); + return NULL; + } + FX_DWORD parser_gennum = FXSYS_atoi(word); + if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) { + m_Syntax.RestorePos(SavedPos); + return NULL; + } + CPDF_Object* pObj = + m_Syntax.GetObject(pObjList, objnum, parser_gennum, pContext); + m_Syntax.SavePos(); + CFX_ByteString bsWord = m_Syntax.GetKeyword(); + if (bsWord == FX_BSTRC("endobj")) { + m_Syntax.SavePos(); + } + m_Syntax.RestorePos(SavedPos); + if (pObj) { + if (!objnum) { + pObj->m_ObjNum = parser_objnum; + } + pObj->m_GenNum = parser_gennum; + } + return pObj; +} +CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict( + CPDF_IndirectObjects* pObjList, + FX_FILESIZE pos, + FX_DWORD objnum, + struct PARSE_CONTEXT* pContext, + FX_FILESIZE* pResultPos) { + FX_FILESIZE SavedPos = m_Syntax.SavePos(); + m_Syntax.RestorePos(pos); + FX_BOOL bIsNumber; + CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); + if (!bIsNumber) { + m_Syntax.RestorePos(SavedPos); + return NULL; + } + FX_DWORD parser_objnum = FXSYS_atoi(word); + if (objnum && parser_objnum != objnum) { + m_Syntax.RestorePos(SavedPos); + return NULL; + } + word = m_Syntax.GetNextWord(bIsNumber); + if (!bIsNumber) { + m_Syntax.RestorePos(SavedPos); + return NULL; + } + FX_DWORD gennum = FXSYS_atoi(word); + if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) { + m_Syntax.RestorePos(SavedPos); + return NULL; + } + CPDF_Object* pObj = + m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, pContext); + if (pResultPos) { + *pResultPos = m_Syntax.m_Pos; + } + m_Syntax.RestorePos(SavedPos); + return pObj; } -FX_DWORD CPDF_Parser::GetRootObjNum() -{ - CPDF_Object* pRef = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Root")) : NULL; - if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { - return 0; +CPDF_Dictionary* CPDF_Parser::LoadTrailerV4() { + if (m_Syntax.GetKeyword() != FX_BSTRC("trailer")) { + return NULL; + } + CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0); + if (pObj == NULL || pObj->GetType() != PDFOBJ_DICTIONARY) { + if (pObj) { + pObj->Release(); } - return ((CPDF_Reference*) pRef)->GetRefObjNum(); + return NULL; + } + return (CPDF_Dictionary*)pObj; +} +FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision) { + if (m_pSecurityHandler == NULL) { + return (FX_DWORD)-1; + } + FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions(); + if (m_pEncryptDict && + m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) { + dwPermission &= 0xFFFFFFFC; + dwPermission |= 0xFFFFF0C0; + if (bCheckRevision && m_pEncryptDict->GetInteger(FX_BSTRC("R")) == 2) { + dwPermission &= 0xFFFFF0FF; + } + } + return dwPermission; } -FX_DWORD CPDF_Parser::GetInfoObjNum() -{ - CPDF_Object* pRef = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Info")) : NULL; - if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { - return 0; +FX_BOOL CPDF_Parser::IsOwner() { + return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner(); +} +void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler, + FX_BOOL bForced) { + ASSERT(m_pSecurityHandler == NULL); + if (!m_bForceUseSecurityHandler) { + delete m_pSecurityHandler; + m_pSecurityHandler = NULL; + } + m_bForceUseSecurityHandler = bForced; + m_pSecurityHandler = pSecurityHandler; + if (m_bForceUseSecurityHandler) { + return; + } + m_Syntax.m_pCryptoHandler = pSecurityHandler->CreateCryptoHandler(); + m_Syntax.m_pCryptoHandler->Init(NULL, pSecurityHandler); +} +FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, + FX_DWORD offset) { + m_Syntax.InitParser(pFileAccess, offset); + m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9); + FX_FILESIZE SavedPos = m_Syntax.SavePos(); + FX_BOOL bIsNumber; + CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); + if (!bIsNumber) { + return FALSE; + } + FX_DWORD objnum = FXSYS_atoi(word); + word = m_Syntax.GetNextWord(bIsNumber); + if (!bIsNumber) { + return FALSE; + } + FX_DWORD gennum = FXSYS_atoi(word); + if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) { + m_Syntax.RestorePos(SavedPos); + return FALSE; + } + m_pLinearized = m_Syntax.GetObject(NULL, objnum, gennum, 0); + if (!m_pLinearized) { + return FALSE; + } + if (m_pLinearized->GetDict() && + m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) { + m_Syntax.GetNextWord(bIsNumber); + CPDF_Object* pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L")); + if (!pLen) { + m_pLinearized->Release(); + m_pLinearized = NULL; + return FALSE; + } + if (pLen->GetInteger() != (int)pFileAccess->GetSize()) { + return FALSE; + } + CPDF_Object* pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P")); + if (pNo && pNo->GetType() == PDFOBJ_NUMBER) { + m_dwFirstPageNo = pNo->GetInteger(); + } + CPDF_Object* pTable = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T")); + if (pTable && pTable->GetType() == PDFOBJ_NUMBER) { + m_LastXRefOffset = pTable->GetInteger(); } - return ((CPDF_Reference*) pRef)->GetRefObjNum(); + return TRUE; + } + m_pLinearized->Release(); + m_pLinearized = NULL; + return FALSE; } -FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) -{ - bForm = FALSE; - if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { - return TRUE; +FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, + FX_BOOL bReParse, + FX_BOOL bOwnFileRead) { + CloseParser(bReParse); + m_bXRefStream = FALSE; + m_LastXRefOffset = 0; + m_bOwnFileRead = bOwnFileRead; + int32_t offset = GetHeaderOffset(pFileAccess); + if (offset == -1) { + return PDFPARSE_ERROR_FORMAT; + } + if (!IsLinearizedFile(pFileAccess, offset)) { + m_Syntax.m_pFileAccess = NULL; + return StartParse(pFileAccess, bReParse, bOwnFileRead); + } + if (!bReParse) { + m_pDocument = new CPDF_Document(this); + } + FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos(); + FX_BOOL bXRefRebuilt = FALSE; + FX_BOOL bLoadV4 = FALSE; + if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && + !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) { + if (!RebuildCrossRef()) { + return PDFPARSE_ERROR_FORMAT; + } + bXRefRebuilt = TRUE; + m_LastXRefOffset = 0; + } + if (bLoadV4) { + m_pTrailer = LoadTrailerV4(); + if (m_pTrailer == NULL) { + return FALSE; } - if (m_V5Type[objnum] == 0) { - return TRUE; + int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); + if (xrefsize > 0) { + m_CrossRef.SetSize(xrefsize); + m_V5Type.SetSize(xrefsize); + } + } + FX_DWORD dwRet = SetEncryptHandler(); + if (dwRet != PDFPARSE_ERROR_SUCCESS) { + return dwRet; + } + m_pDocument->LoadAsynDoc(m_pLinearized->GetDict()); + if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) { + if (bXRefRebuilt) { + return PDFPARSE_ERROR_FORMAT; } - if (m_V5Type[objnum] == 2) { - return TRUE; + ReleaseEncryptHandler(); + if (!RebuildCrossRef()) { + return PDFPARSE_ERROR_FORMAT; } - FX_FILESIZE pos = m_CrossRef[objnum]; - void* pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - return TRUE; + dwRet = SetEncryptHandler(); + if (dwRet != PDFPARSE_ERROR_SUCCESS) { + return dwRet; } - if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) { - return FALSE; + m_pDocument->LoadAsynDoc(m_pLinearized->GetDict()); + if (m_pDocument->GetRoot() == NULL) { + return PDFPARSE_ERROR_FORMAT; + } + } + FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + FX_DWORD RootObjNum = GetRootObjNum(); + if (RootObjNum == 0) { + ReleaseEncryptHandler(); + RebuildCrossRef(); + RootObjNum = GetRootObjNum(); + if (RootObjNum == 0) { + return PDFPARSE_ERROR_FORMAT; } - FX_FILESIZE size = ((FX_FILESIZE*)pResult)[1] - pos; - FX_FILESIZE SavedPos = m_Syntax.SavePos(); - m_Syntax.RestorePos(pos); - bForm = m_Syntax.SearchMultiWord(FX_BSTRC("/Form\0stream"), TRUE, size) == 0; - m_Syntax.RestorePos(SavedPos); - return TRUE; -} -CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, PARSE_CONTEXT* pContext) -{ - if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { - return NULL; + dwRet = SetEncryptHandler(); + if (dwRet != PDFPARSE_ERROR_SUCCESS) { + return dwRet; } - if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) { - FX_FILESIZE pos = m_CrossRef[objnum]; - if (pos <= 0) { - return NULL; - } - return ParseIndirectObjectAt(pObjList, pos, objnum, pContext); + } + if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) { + CPDF_Object* pMetadata = + m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata")); + if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) { + m_Syntax.m_MetadataObjnum = ((CPDF_Reference*)pMetadata)->GetRefObjNum(); } - if (m_V5Type[objnum] == 2) { - CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]); - if (pObjStream == NULL) { - return NULL; - } - int32_t n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N")); - int32_t offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First")); - CPDF_SyntaxParser syntax; - CFX_SmartPointer file(FX_CreateMemoryStream((uint8_t*)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE)); - syntax.InitParser(file.Get(), 0); - CPDF_Object* pRet = NULL; - while (n) { - FX_DWORD thisnum = syntax.GetDirectNum(); - FX_DWORD thisoff = syntax.GetDirectNum(); - if (thisnum == objnum) { - syntax.RestorePos(offset + thisoff); - pRet = syntax.GetObject(pObjList, 0, 0, pContext); - break; - } - n --; - } - return pRet; + } + return PDFPARSE_ERROR_SUCCESS; +} +FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) { + if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { + return FALSE; + } + while (xrefpos) + if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { + return FALSE; } - return NULL; + m_ObjectStreamMap.InitHashTable(101, FALSE); + m_bXRefStream = TRUE; + return TRUE; } -CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum) -{ - CPDF_StreamAcc* pStreamAcc = NULL; - if (m_ObjectStreamMap.Lookup((void*)(uintptr_t)objnum, (void*&)pStreamAcc)) { - return pStreamAcc; - } - const CPDF_Stream* pStream = m_pDocument ? (CPDF_Stream*)m_pDocument->GetIndirectObject(objnum) : NULL; - if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) { - return NULL; +FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable() { + FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum; + m_Syntax.m_MetadataObjnum = 0; + if (m_pTrailer) { + m_pTrailer->Release(); + m_pTrailer = NULL; + } + m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset); + uint8_t ch = 0; + FX_DWORD dwCount = 0; + m_Syntax.GetNextChar(ch); + int32_t type = PDF_CharType[ch]; + while (type == 'W') { + ++dwCount; + if (m_Syntax.m_FileLen >= + (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) { + break; } - pStreamAcc = new CPDF_StreamAcc; - pStreamAcc->LoadAllData(pStream); - m_ObjectStreamMap.SetAt((void*)(uintptr_t)objnum, pStreamAcc); - return pStreamAcc; + m_Syntax.GetNextChar(ch); + type = PDF_CharType[ch]; + } + m_LastXRefOffset += dwCount; + FX_POSITION pos = m_ObjectStreamMap.GetStartPosition(); + while (pos) { + void* objnum; + CPDF_StreamAcc* pStream; + m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream); + delete pStream; + } + m_ObjectStreamMap.RemoveAll(); + if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && + !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) { + m_LastXRefOffset = 0; + m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum; + return PDFPARSE_ERROR_FORMAT; + } + FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum; + return PDFPARSE_ERROR_SUCCESS; +} + +// static +int CPDF_SyntaxParser::s_CurrentRecursionDepth = 0; + +CPDF_SyntaxParser::CPDF_SyntaxParser() { + m_pFileAccess = NULL; + m_pCryptoHandler = NULL; + m_pFileBuf = NULL; + m_BufSize = CPDF_ModuleMgr::kFileBufSize; + m_pFileBuf = NULL; + m_MetadataObjnum = 0; + m_dwWordPos = 0; + m_bFileStream = FALSE; +} +CPDF_SyntaxParser::~CPDF_SyntaxParser() { + if (m_pFileBuf) { + FX_Free(m_pFileBuf); + } +} +FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, uint8_t& ch) { + FX_FILESIZE save_pos = m_Pos; + m_Pos = pos; + FX_BOOL ret = GetNextChar(ch); + m_Pos = save_pos; + return ret; +} +FX_BOOL CPDF_SyntaxParser::GetNextChar(uint8_t& ch) { + FX_FILESIZE pos = m_Pos + m_HeaderOffset; + if (pos >= m_FileLen) { + return FALSE; + } + if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) { + FX_FILESIZE read_pos = pos; + FX_DWORD read_size = m_BufSize; + if ((FX_FILESIZE)read_size > m_FileLen) { + read_size = (FX_DWORD)m_FileLen; + } + if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) { + if (m_FileLen < (FX_FILESIZE)read_size) { + read_pos = 0; + read_size = (FX_DWORD)m_FileLen; + } else { + read_pos = m_FileLen - read_size; + } + } + if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) { + return FALSE; + } + m_BufOffset = read_pos; + } + ch = m_pFileBuf[pos - m_BufOffset]; + m_Pos++; + return TRUE; +} +FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, uint8_t& ch) { + pos += m_HeaderOffset; + if (pos >= m_FileLen) { + return FALSE; + } + if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) { + FX_FILESIZE read_pos; + if (pos < (FX_FILESIZE)m_BufSize) { + read_pos = 0; + } else { + read_pos = pos - m_BufSize + 1; + } + FX_DWORD read_size = m_BufSize; + if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) { + if (m_FileLen < (FX_FILESIZE)read_size) { + read_pos = 0; + read_size = (FX_DWORD)m_FileLen; + } else { + read_pos = m_FileLen - read_size; + } + } + if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) { + return FALSE; + } + m_BufOffset = read_pos; + } + ch = m_pFileBuf[pos - m_BufOffset]; + return TRUE; +} +FX_BOOL CPDF_SyntaxParser::ReadBlock(uint8_t* pBuf, FX_DWORD size) { + if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) { + return FALSE; + } + m_Pos += size; + return TRUE; } -FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum) -{ - if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { - return 0; +#define MAX_WORD_BUFFER 256 +void CPDF_SyntaxParser::GetNextWord() { + m_WordSize = 0; + m_bIsNumber = TRUE; + uint8_t ch; + if (!GetNextChar(ch)) { + return; + } + uint8_t type = PDF_CharType[ch]; + while (1) { + while (type == 'W') { + if (!GetNextChar(ch)) { + return; + } + type = PDF_CharType[ch]; } - if (m_V5Type[objnum] == 2) { - objnum = (FX_DWORD)m_CrossRef[objnum]; + if (ch != '%') { + break; } - if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) { - FX_FILESIZE offset = m_CrossRef[objnum]; - if (offset == 0) { - return 0; + while (1) { + if (!GetNextChar(ch)) { + return; + } + if (ch == '\r' || ch == '\n') { + break; + } + } + type = PDF_CharType[ch]; + } + if (type == 'D') { + m_bIsNumber = FALSE; + m_WordBuffer[m_WordSize++] = ch; + if (ch == '/') { + while (1) { + if (!GetNextChar(ch)) { + return; } - void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - return 0; + type = PDF_CharType[ch]; + if (type != 'R' && type != 'N') { + m_Pos--; + return; } - if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) { - return 0; + if (m_WordSize < MAX_WORD_BUFFER) { + m_WordBuffer[m_WordSize++] = ch; } - return ((FX_FILESIZE*)pResult)[1] - offset; - } - return 0; -} -void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, uint8_t*& pBuffer, FX_DWORD& size) -{ - pBuffer = NULL; - size = 0; - if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) { + } + } else if (ch == '<') { + if (!GetNextChar(ch)) { return; - } - if (m_V5Type[objnum] == 2) { - CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]); - if (pObjStream == NULL) { - return; - } - int32_t n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N")); - int32_t offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First")); - CPDF_SyntaxParser syntax; - const uint8_t* pData = pObjStream->GetData(); - FX_DWORD totalsize = pObjStream->GetSize(); - CFX_SmartPointer file(FX_CreateMemoryStream((uint8_t*)pData, (size_t)totalsize, FALSE)); - syntax.InitParser(file.Get(), 0); - while (n) { - FX_DWORD thisnum = syntax.GetDirectNum(); - FX_DWORD thisoff = syntax.GetDirectNum(); - if (thisnum == objnum) { - if (n == 1) { - size = totalsize - (thisoff + offset); - } else { - syntax.GetDirectNum(); // Skip nextnum. - FX_DWORD nextoff = syntax.GetDirectNum(); - size = nextoff - thisoff; - } - pBuffer = FX_Alloc(uint8_t, size); - FXSYS_memcpy(pBuffer, pData + thisoff + offset, size); - return; - } - n --; - } + } + if (ch == '<') { + m_WordBuffer[m_WordSize++] = ch; + } else { + m_Pos--; + } + } else if (ch == '>') { + if (!GetNextChar(ch)) { return; + } + if (ch == '>') { + m_WordBuffer[m_WordSize++] = ch; + } else { + m_Pos--; + } } - if (m_V5Type[objnum] == 1) { - FX_FILESIZE pos = m_CrossRef[objnum]; - if (pos == 0) { - return; - } - FX_FILESIZE SavedPos = m_Syntax.SavePos(); - m_Syntax.RestorePos(pos); - FX_BOOL bIsNumber; - CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); - if (!bIsNumber) { - m_Syntax.RestorePos(SavedPos); - return; - } - FX_DWORD parser_objnum = FXSYS_atoi(word); - if (parser_objnum && parser_objnum != objnum) { - m_Syntax.RestorePos(SavedPos); - return; - } - word = m_Syntax.GetNextWord(bIsNumber); - if (!bIsNumber) { - m_Syntax.RestorePos(SavedPos); - return; - } - if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) { - m_Syntax.RestorePos(SavedPos); - return; - } - void* pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - m_Syntax.RestorePos(SavedPos); - return; - } - FX_FILESIZE nextoff = ((FX_FILESIZE*)pResult)[1]; - FX_BOOL bNextOffValid = FALSE; - if (nextoff != pos) { - m_Syntax.RestorePos(nextoff); - word = m_Syntax.GetNextWord(bIsNumber); - if (word == FX_BSTRC("xref")) { - bNextOffValid = TRUE; - } else if (bIsNumber) { - word = m_Syntax.GetNextWord(bIsNumber); - if (bIsNumber && m_Syntax.GetKeyword() == FX_BSTRC("obj")) { - bNextOffValid = TRUE; - } - } + return; + } + while (1) { + if (m_WordSize < MAX_WORD_BUFFER) { + m_WordBuffer[m_WordSize++] = ch; + } + if (type != 'N') { + m_bIsNumber = FALSE; + } + if (!GetNextChar(ch)) { + return; + } + type = PDF_CharType[ch]; + if (type == 'D' || type == 'W') { + m_Pos--; + break; + } + } +} +CFX_ByteString CPDF_SyntaxParser::ReadString() { + uint8_t ch; + if (!GetNextChar(ch)) { + return CFX_ByteString(); + } + CFX_ByteTextBuf buf; + int32_t parlevel = 0; + int32_t status = 0, iEscCode = 0; + while (1) { + switch (status) { + case 0: + if (ch == ')') { + if (parlevel == 0) { + return buf.GetByteString(); + } + parlevel--; + buf.AppendChar(')'); + } else if (ch == '(') { + parlevel++; + buf.AppendChar('('); + } else if (ch == '\\') { + status = 1; + } else { + buf.AppendChar(ch); + } + break; + case 1: + if (ch >= '0' && ch <= '7') { + iEscCode = ch - '0'; + status = 2; + break; + } + if (ch == 'n') { + buf.AppendChar('\n'); + } else if (ch == 'r') { + buf.AppendChar('\r'); + } else if (ch == 't') { + buf.AppendChar('\t'); + } else if (ch == 'b') { + buf.AppendChar('\b'); + } else if (ch == 'f') { + buf.AppendChar('\f'); + } else if (ch == '\r') { + status = 4; + break; + } else if (ch == '\n') { + } else { + buf.AppendChar(ch); + } + status = 0; + break; + case 2: + if (ch >= '0' && ch <= '7') { + iEscCode = iEscCode * 8 + ch - '0'; + status = 3; + } else { + buf.AppendChar(iEscCode); + status = 0; + continue; + } + break; + case 3: + if (ch >= '0' && ch <= '7') { + iEscCode = iEscCode * 8 + ch - '0'; + buf.AppendChar(iEscCode); + status = 0; + } else { + buf.AppendChar(iEscCode); + status = 0; + continue; } - if (!bNextOffValid) { - m_Syntax.RestorePos(pos); - while (1) { - if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) { - break; - } - if (m_Syntax.SavePos() == m_Syntax.m_FileLen) { - break; - } - } - nextoff = m_Syntax.SavePos(); + break; + case 4: + status = 0; + if (ch != '\n') { + continue; } - size = (FX_DWORD)(nextoff - pos); - pBuffer = FX_Alloc(uint8_t, size); - m_Syntax.RestorePos(pos); - m_Syntax.ReadBlock(pBuffer, size); - m_Syntax.RestorePos(SavedPos); + break; } -} -CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum, - PARSE_CONTEXT* pContext) -{ - FX_FILESIZE SavedPos = m_Syntax.SavePos(); - m_Syntax.RestorePos(pos); - FX_BOOL bIsNumber; - CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); - if (!bIsNumber) { - m_Syntax.RestorePos(SavedPos); - return NULL; + if (!GetNextChar(ch)) { + break; } - FX_FILESIZE objOffset = m_Syntax.SavePos(); - objOffset -= word.GetLength(); - FX_DWORD parser_objnum = FXSYS_atoi(word); - if (objnum && parser_objnum != objnum) { - m_Syntax.RestorePos(SavedPos); - return NULL; + } + GetNextChar(ch); + return buf.GetByteString(); +} +CFX_ByteString CPDF_SyntaxParser::ReadHexString() { + uint8_t ch; + if (!GetNextChar(ch)) { + return CFX_ByteString(); + } + CFX_BinaryBuf buf; + FX_BOOL bFirst = TRUE; + uint8_t code = 0; + while (1) { + if (ch == '>') { + break; } - word = m_Syntax.GetNextWord(bIsNumber); - if (!bIsNumber) { - m_Syntax.RestorePos(SavedPos); - return NULL; + if (ch >= '0' && ch <= '9') { + if (bFirst) { + code = (ch - '0') * 16; + } else { + code += ch - '0'; + buf.AppendByte((uint8_t)code); + } + bFirst = !bFirst; + } else if (ch >= 'A' && ch <= 'F') { + if (bFirst) { + code = (ch - 'A' + 10) * 16; + } else { + code += ch - 'A' + 10; + buf.AppendByte((uint8_t)code); + } + bFirst = !bFirst; + } else if (ch >= 'a' && ch <= 'f') { + if (bFirst) { + code = (ch - 'a' + 10) * 16; + } else { + code += ch - 'a' + 10; + buf.AppendByte((uint8_t)code); + } + bFirst = !bFirst; } - FX_DWORD parser_gennum = FXSYS_atoi(word); - if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) { - m_Syntax.RestorePos(SavedPos); - return NULL; + if (!GetNextChar(ch)) { + break; } - CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, parser_gennum, pContext); - m_Syntax.SavePos(); - CFX_ByteString bsWord = m_Syntax.GetKeyword(); - if (bsWord == FX_BSTRC("endobj")) { - m_Syntax.SavePos(); + } + if (!bFirst) { + buf.AppendByte((uint8_t)code); + } + return buf.GetByteString(); +} +void CPDF_SyntaxParser::ToNextLine() { + uint8_t ch; + while (GetNextChar(ch)) { + if (ch == '\n') { + break; + } + if (ch == '\r') { + GetNextChar(ch); + if (ch != '\n') { + --m_Pos; + } + break; + } + } +} +void CPDF_SyntaxParser::ToNextWord() { + uint8_t ch; + if (!GetNextChar(ch)) { + return; + } + uint8_t type = PDF_CharType[ch]; + while (1) { + while (type == 'W') { + m_dwWordPos = m_Pos; + if (!GetNextChar(ch)) { + return; + } + type = PDF_CharType[ch]; } - m_Syntax.RestorePos(SavedPos); - if (pObj) { - if (!objnum) { - pObj->m_ObjNum = parser_objnum; - } - pObj->m_GenNum = parser_gennum; + if (ch != '%') { + break; } - return pObj; + while (1) { + if (!GetNextChar(ch)) { + return; + } + if (ch == '\r' || ch == '\n') { + break; + } + } + type = PDF_CharType[ch]; + } + m_Pos--; } -CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum, - struct PARSE_CONTEXT* pContext, FX_FILESIZE *pResultPos) -{ - FX_FILESIZE SavedPos = m_Syntax.SavePos(); - m_Syntax.RestorePos(pos); - FX_BOOL bIsNumber; - CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); - if (!bIsNumber) { - m_Syntax.RestorePos(SavedPos); - return NULL; +CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber) { + GetNextWord(); + bIsNumber = m_bIsNumber; + return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize); +} +CFX_ByteString CPDF_SyntaxParser::GetKeyword() { + GetNextWord(); + return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize); +} +CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, + FX_DWORD objnum, + FX_DWORD gennum, + PARSE_CONTEXT* pContext, + FX_BOOL bDecrypt) { + CFX_AutoRestorer restorer(&s_CurrentRecursionDepth); + if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) { + return NULL; + } + FX_FILESIZE SavedPos = m_Pos; + FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY); + FX_BOOL bIsNumber; + CFX_ByteString word = GetNextWord(bIsNumber); + CPDF_Object* pRet = NULL; + if (word.GetLength() == 0) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_INVALID; } - FX_DWORD parser_objnum = FXSYS_atoi(word); - if (objnum && parser_objnum != objnum) { - m_Syntax.RestorePos(SavedPos); - return NULL; + return NULL; + } + if (bIsNumber) { + FX_FILESIZE SavedPos = m_Pos; + CFX_ByteString nextword = GetNextWord(bIsNumber); + if (bIsNumber) { + CFX_ByteString nextword2 = GetNextWord(bIsNumber); + if (nextword2 == FX_BSTRC("R")) { + FX_DWORD objnum = FXSYS_atoi(word); + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_REFERENCE; + } + return new CPDF_Reference(pObjList, objnum); + } } - word = m_Syntax.GetNextWord(bIsNumber); - if (!bIsNumber) { - m_Syntax.RestorePos(SavedPos); - return NULL; + m_Pos = SavedPos; + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_NUMBER; } - FX_DWORD gennum = FXSYS_atoi(word); - if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) { - m_Syntax.RestorePos(SavedPos); - return NULL; + return CPDF_Number::Create(word); + } + if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_BOOLEAN; } - CPDF_Object* pObj = m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, pContext); - if (pResultPos) { - *pResultPos = m_Syntax.m_Pos; + pRet = CPDF_Boolean::Create(word == FX_BSTRC("true")); + return pRet; + } + if (word == FX_BSTRC("null")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_NULL; } - m_Syntax.RestorePos(SavedPos); - return pObj; -} -CPDF_Dictionary* CPDF_Parser::LoadTrailerV4() -{ - if (m_Syntax.GetKeyword() != FX_BSTRC("trailer")) { - return NULL; + pRet = CPDF_Null::Create(); + return pRet; + } + if (word == FX_BSTRC("(")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_STRING; } - CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0); - if (pObj == NULL || pObj->GetType() != PDFOBJ_DICTIONARY) { - if (pObj) { - pObj->Release(); - } - return NULL; + CFX_ByteString str = ReadString(); + if (m_pCryptoHandler && bDecrypt) { + m_pCryptoHandler->Decrypt(objnum, gennum, str); } - return (CPDF_Dictionary*)pObj; -} -FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision) -{ - if (m_pSecurityHandler == NULL) { - return (FX_DWORD) - 1; - } - FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions(); - if (m_pEncryptDict && m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) { - dwPermission &= 0xFFFFFFFC; - dwPermission |= 0xFFFFF0C0; - if(bCheckRevision && m_pEncryptDict->GetInteger(FX_BSTRC("R")) == 2) { - dwPermission &= 0xFFFFF0FF; - } + pRet = CPDF_String::Create(str, FALSE); + return pRet; + } + if (word == FX_BSTRC("<")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_STRING; } - return dwPermission; -} -FX_BOOL CPDF_Parser::IsOwner() -{ - return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner(); -} -void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler, FX_BOOL bForced) -{ - ASSERT(m_pSecurityHandler == NULL); - if (!m_bForceUseSecurityHandler) { - delete m_pSecurityHandler; - m_pSecurityHandler = NULL; - } - m_bForceUseSecurityHandler = bForced; - m_pSecurityHandler = pSecurityHandler; - if (m_bForceUseSecurityHandler) { - return; + CFX_ByteString str = ReadHexString(); + if (m_pCryptoHandler && bDecrypt) { + m_pCryptoHandler->Decrypt(objnum, gennum, str); } - m_Syntax.m_pCryptoHandler = pSecurityHandler->CreateCryptoHandler(); - m_Syntax.m_pCryptoHandler->Init(NULL, pSecurityHandler); -} -FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, FX_DWORD offset) -{ - m_Syntax.InitParser(pFileAccess, offset); - m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9); - FX_FILESIZE SavedPos = m_Syntax.SavePos(); - FX_BOOL bIsNumber; - CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber); - if (!bIsNumber) { - return FALSE; + pRet = CPDF_String::Create(str, TRUE); + return pRet; + } + if (word == FX_BSTRC("[")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_ARRAY; } - FX_DWORD objnum = FXSYS_atoi(word); - word = m_Syntax.GetNextWord(bIsNumber); - if (!bIsNumber) { - return FALSE; + CPDF_Array* pArray = CPDF_Array::Create(); + while (1) { + CPDF_Object* pObj = GetObject(pObjList, objnum, gennum); + if (pObj == NULL) { + return pArray; + } + pArray->Add(pObj); + } + } + if (word[0] == '/') { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_NAME; } - FX_DWORD gennum = FXSYS_atoi(word); - if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) { - m_Syntax.RestorePos(SavedPos); - return FALSE; + pRet = CPDF_Name::Create( + PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); + return pRet; + } + if (word == FX_BSTRC("<<")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_DICTIONARY; } - m_pLinearized = m_Syntax.GetObject(NULL, objnum, gennum, 0); - if (!m_pLinearized) { - return FALSE; + if (pContext) { + pContext->m_DictStart = SavedPos; } - if (m_pLinearized->GetDict() && m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) { - m_Syntax.GetNextWord(bIsNumber); - CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L")); - if (!pLen) { - m_pLinearized->Release(); - m_pLinearized = NULL; - return FALSE; - } - if (pLen->GetInteger() != (int)pFileAccess->GetSize()) { - return FALSE; - } - CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P")); - if (pNo && pNo->GetType() == PDFOBJ_NUMBER) { - m_dwFirstPageNo = pNo->GetInteger(); - } - CPDF_Object *pTable = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T")); - if (pTable && pTable->GetType() == PDFOBJ_NUMBER) { - m_LastXRefOffset = pTable->GetInteger(); + CPDF_Dictionary* pDict = CPDF_Dictionary::Create(); + int32_t nKeys = 0; + FX_FILESIZE dwSignValuePos = 0; + while (1) { + FX_BOOL bIsNumber; + CFX_ByteString key = GetNextWord(bIsNumber); + if (key.IsEmpty()) { + if (pDict) + pDict->Release(); + return NULL; + } + FX_FILESIZE SavedPos = m_Pos - key.GetLength(); + if (key == FX_BSTRC(">>")) { + break; + } + if (key == FX_BSTRC("endobj")) { + m_Pos = SavedPos; + break; + } + if (key[0] != '/') { + continue; + } + nKeys++; + key = PDF_NameDecode(key); + if (key == FX_BSTRC("/Contents")) { + dwSignValuePos = m_Pos; + } + CPDF_Object* pObj = GetObject(pObjList, objnum, gennum); + if (pObj == NULL) { + continue; + } + if (key.GetLength() >= 1) { + if (nKeys < 32) { + pDict->SetAt(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), + pObj); + } else { + pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), + pObj); } - return TRUE; + } } - m_pLinearized->Release(); - m_pLinearized = NULL; - return FALSE; -} -FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead) -{ - CloseParser(bReParse); - m_bXRefStream = FALSE; - m_LastXRefOffset = 0; - m_bOwnFileRead = bOwnFileRead; - int32_t offset = GetHeaderOffset(pFileAccess); - if (offset == -1) { - return PDFPARSE_ERROR_FORMAT; + if (IsSignatureDict(pDict)) { + FX_FILESIZE dwSavePos = m_Pos; + m_Pos = dwSignValuePos; + CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, NULL, FALSE); + pDict->SetAt(FX_BSTRC("Contents"), pObj); + m_Pos = dwSavePos; } - if (!IsLinearizedFile(pFileAccess, offset)) { - m_Syntax.m_pFileAccess = NULL; - return StartParse(pFileAccess, bReParse, bOwnFileRead); + if (pContext) { + pContext->m_DictEnd = m_Pos; + if (pContext->m_Flags & PDFPARSE_NOSTREAM) { + return pDict; + } } - if (!bReParse) { - m_pDocument = new CPDF_Document(this); + FX_FILESIZE SavedPos = m_Pos; + FX_BOOL bIsNumber; + CFX_ByteString nextword = GetNextWord(bIsNumber); + if (nextword == FX_BSTRC("stream")) { + CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum); + if (pStream) { + return pStream; + } + if (pDict) + pDict->Release(); + return NULL; + } else { + m_Pos = SavedPos; + return pDict; } - FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos(); - FX_BOOL bXRefRebuilt = FALSE; - FX_BOOL bLoadV4 = FALSE; - if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) { - if (!RebuildCrossRef()) { - return PDFPARSE_ERROR_FORMAT; - } - bXRefRebuilt = TRUE; - m_LastXRefOffset = 0; + } + if (word == FX_BSTRC(">>")) { + m_Pos = SavedPos; + return NULL; + } + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_INVALID; + } + return NULL; +} +CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict( + CPDF_IndirectObjects* pObjList, + FX_DWORD objnum, + FX_DWORD gennum, + struct PARSE_CONTEXT* pContext) { + CFX_AutoRestorer restorer(&s_CurrentRecursionDepth); + if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) { + return NULL; + } + FX_FILESIZE SavedPos = m_Pos; + FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY); + FX_BOOL bIsNumber; + CFX_ByteString word = GetNextWord(bIsNumber); + if (word.GetLength() == 0) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_INVALID; } - if (bLoadV4) { - m_pTrailer = LoadTrailerV4(); - if (m_pTrailer == NULL) { - return FALSE; - } - int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size")); - if (xrefsize > 0) { - m_CrossRef.SetSize(xrefsize); - m_V5Type.SetSize(xrefsize); + return NULL; + } + if (bIsNumber) { + FX_FILESIZE SavedPos = m_Pos; + CFX_ByteString nextword = GetNextWord(bIsNumber); + if (bIsNumber) { + CFX_ByteString nextword2 = GetNextWord(bIsNumber); + if (nextword2 == FX_BSTRC("R")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_REFERENCE; } + FX_DWORD objnum = FXSYS_atoi(word); + return new CPDF_Reference(pObjList, objnum); + } } - FX_DWORD dwRet = SetEncryptHandler(); - if (dwRet != PDFPARSE_ERROR_SUCCESS) { - return dwRet; + m_Pos = SavedPos; + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_NUMBER; } - m_pDocument->LoadAsynDoc(m_pLinearized->GetDict()); - if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) { - if (bXRefRebuilt) { - return PDFPARSE_ERROR_FORMAT; - } - ReleaseEncryptHandler(); - if (!RebuildCrossRef()) { - return PDFPARSE_ERROR_FORMAT; - } - dwRet = SetEncryptHandler(); - if (dwRet != PDFPARSE_ERROR_SUCCESS) { - return dwRet; - } - m_pDocument->LoadAsynDoc(m_pLinearized->GetDict()); - if (m_pDocument->GetRoot() == NULL) { - return PDFPARSE_ERROR_FORMAT; - } + return CPDF_Number::Create(word); + } + if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_BOOLEAN; } - FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - FX_DWORD RootObjNum = GetRootObjNum(); - if (RootObjNum == 0) { - ReleaseEncryptHandler(); - RebuildCrossRef(); - RootObjNum = GetRootObjNum(); - if (RootObjNum == 0) { - return PDFPARSE_ERROR_FORMAT; + return CPDF_Boolean::Create(word == FX_BSTRC("true")); + } + if (word == FX_BSTRC("null")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_NULL; + } + return CPDF_Null::Create(); + } + if (word == FX_BSTRC("(")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_STRING; + } + CFX_ByteString str = ReadString(); + if (m_pCryptoHandler) { + m_pCryptoHandler->Decrypt(objnum, gennum, str); + } + return CPDF_String::Create(str, FALSE); + } + if (word == FX_BSTRC("<")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_STRING; + } + CFX_ByteString str = ReadHexString(); + if (m_pCryptoHandler) { + m_pCryptoHandler->Decrypt(objnum, gennum, str); + } + return CPDF_String::Create(str, TRUE); + } + if (word == FX_BSTRC("[")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_ARRAY; + } + CPDF_Array* pArray = CPDF_Array::Create(); + while (1) { + CPDF_Object* pObj = GetObject(pObjList, objnum, gennum); + if (pObj == NULL) { + if (m_WordBuffer[0] == ']') { + return pArray; } - dwRet = SetEncryptHandler(); - if (dwRet != PDFPARSE_ERROR_SUCCESS) { - return dwRet; + if (pArray) { + pArray->Release(); } + return NULL; + } + pArray->Add(pObj); } - if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) { - CPDF_Object* pMetadata = m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata")); - if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) { - m_Syntax.m_MetadataObjnum = ((CPDF_Reference*) pMetadata)->GetRefObjNum(); - } + } + if (word[0] == '/') { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_NAME; } - return PDFPARSE_ERROR_SUCCESS; -} -FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) -{ - if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { - return FALSE; + return CPDF_Name::Create( + PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); + } + if (word == FX_BSTRC("<<")) { + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_DICTIONARY; } - while (xrefpos) - if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) { - return FALSE; + if (pContext) { + pContext->m_DictStart = SavedPos; + } + CPDF_Dictionary* pDict = CPDF_Dictionary::Create(); + while (1) { + FX_BOOL bIsNumber; + FX_FILESIZE SavedPos = m_Pos; + CFX_ByteString key = GetNextWord(bIsNumber); + if (key.IsEmpty()) { + if (pDict) { + pDict->Release(); } - m_ObjectStreamMap.InitHashTable(101, FALSE); - m_bXRefStream = TRUE; - return TRUE; -} -FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable() -{ - FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum; - m_Syntax.m_MetadataObjnum = 0; - if (m_pTrailer) { - m_pTrailer->Release(); - m_pTrailer = NULL; - } - m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset); - uint8_t ch = 0; - FX_DWORD dwCount = 0; - m_Syntax.GetNextChar(ch); - int32_t type = PDF_CharType[ch]; - while (type == 'W') { - ++dwCount; - if (m_Syntax.m_FileLen >= (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) { + return NULL; + } + if (key == FX_BSTRC(">>")) { + break; + } + if (key == FX_BSTRC("endobj")) { + m_Pos = SavedPos; + break; + } + if (key[0] != '/') { + continue; + } + key = PDF_NameDecode(key); + CPDF_Object* pObj = GetObject(pObjList, objnum, gennum); + if (pObj == NULL) { + if (pDict) { + pDict->Release(); + } + uint8_t ch; + while (1) { + if (!GetNextChar(ch)) { break; + } + if (ch == 0x0A || ch == 0x0D) { + break; + } } - m_Syntax.GetNextChar(ch); - type = PDF_CharType[ch]; + return NULL; + } + if (key.GetLength() > 1) { + pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), + pObj); + } } - m_LastXRefOffset += dwCount; - FX_POSITION pos = m_ObjectStreamMap.GetStartPosition(); - while (pos) { - void* objnum; - CPDF_StreamAcc* pStream; - m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream); - delete pStream; - } - m_ObjectStreamMap.RemoveAll(); - if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) { - m_LastXRefOffset = 0; - m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum; - return PDFPARSE_ERROR_FORMAT; + if (pContext) { + pContext->m_DictEnd = m_Pos; + if (pContext->m_Flags & PDFPARSE_NOSTREAM) { + return pDict; + } } - FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum; - return PDFPARSE_ERROR_SUCCESS; + FX_FILESIZE SavedPos = m_Pos; + FX_BOOL bIsNumber; + CFX_ByteString nextword = GetNextWord(bIsNumber); + if (nextword == FX_BSTRC("stream")) { + CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum); + if (pStream) { + return pStream; + } + if (pDict) { + pDict->Release(); + } + return NULL; + } else { + m_Pos = SavedPos; + return pDict; + } + } + if (word == FX_BSTRC(">>")) { + m_Pos = SavedPos; + return NULL; + } + if (bTypeOnly) { + return (CPDF_Object*)PDFOBJ_INVALID; + } + return NULL; } +CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, + PARSE_CONTEXT* pContext, + FX_DWORD objnum, + FX_DWORD gennum) { + CPDF_Object* pLenObj = pDict->GetElement(FX_BSTRC("Length")); + FX_FILESIZE len = 0; + if (pLenObj && ((pLenObj->GetType() != PDFOBJ_REFERENCE) || + ((((CPDF_Reference*)pLenObj)->GetObjList() != NULL) && + ((CPDF_Reference*)pLenObj)->GetRefObjNum() != objnum))) { + len = pLenObj->GetInteger(); + } -// static -int CPDF_SyntaxParser::s_CurrentRecursionDepth = 0; + ToNextLine(); + FX_FILESIZE StreamStartPos = m_Pos; + if (pContext) { + pContext->m_DataStart = m_Pos; + } -CPDF_SyntaxParser::CPDF_SyntaxParser() -{ - m_pFileAccess = NULL; - m_pCryptoHandler = NULL; - m_pFileBuf = NULL; - m_BufSize = CPDF_ModuleMgr::kFileBufSize; - m_pFileBuf = NULL; - m_MetadataObjnum = 0; - m_dwWordPos = 0; - m_bFileStream = FALSE; -} -CPDF_SyntaxParser::~CPDF_SyntaxParser() -{ - if (m_pFileBuf) { - FX_Free(m_pFileBuf); + CPDF_CryptoHandler* pCryptoHandler = + objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler; + if (pCryptoHandler == NULL) { + pdfium::base::CheckedNumeric pos = m_Pos; + pos += len; + if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) { + m_Pos = pos.ValueOrDie(); } + GetNextWord(); + if (m_WordSize < 9 || FXSYS_memcmp(m_WordBuffer, "endstream", 9)) { + m_Pos = StreamStartPos; + FX_FILESIZE offset = FindTag(FX_BSTRC("endstream"), 0); + if (offset >= 0) { + FX_FILESIZE curPos = m_Pos; + m_Pos = StreamStartPos; + FX_FILESIZE endobjOffset = FindTag(FX_BSTRC("endobj"), 0); + if (endobjOffset < offset && endobjOffset >= 0) { + offset = endobjOffset; + } else { + m_Pos = curPos; + } + uint8_t byte1, byte2; + GetCharAt(StreamStartPos + offset - 1, byte1); + GetCharAt(StreamStartPos + offset - 2, byte2); + if (byte1 == 0x0a && byte2 == 0x0d) { + len -= 2; + } else if (byte1 == 0x0a || byte1 == 0x0d) { + len--; + } + len = (FX_DWORD)offset; + pDict->SetAtInteger(FX_BSTRC("Length"), len); + } else { + m_Pos = StreamStartPos; + if (FindTag(FX_BSTRC("endobj"), 0) < 0) { + return NULL; + } + } + } + m_Pos = StreamStartPos; + } + CPDF_Stream* pStream; + uint8_t* pData = FX_Alloc(uint8_t, len); + ReadBlock(pData, len); + if (pCryptoHandler) { + CFX_BinaryBuf dest_buf; + dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len)); + void* context = pCryptoHandler->DecryptStart(objnum, gennum); + pCryptoHandler->DecryptStream(context, pData, len, dest_buf); + pCryptoHandler->DecryptFinish(context, dest_buf); + FX_Free(pData); + pData = dest_buf.GetBuffer(); + len = dest_buf.GetSize(); + dest_buf.DetachBuffer(); + } + pStream = new CPDF_Stream(pData, len, pDict); + if (pContext) { + pContext->m_DataEnd = pContext->m_DataStart + len; + } + StreamStartPos = m_Pos; + GetNextWord(); + if (m_WordSize == 6 && 0 == FXSYS_memcmp(m_WordBuffer, "endobj", 6)) { + m_Pos = StreamStartPos; + } + return pStream; } -FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, uint8_t& ch) -{ - FX_FILESIZE save_pos = m_Pos; - m_Pos = pos; - FX_BOOL ret = GetNextChar(ch); - m_Pos = save_pos; - return ret; +void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess, + FX_DWORD HeaderOffset) { + if (m_pFileBuf) { + FX_Free(m_pFileBuf); + m_pFileBuf = NULL; + } + m_pFileBuf = FX_Alloc(uint8_t, m_BufSize); + m_HeaderOffset = HeaderOffset; + m_FileLen = pFileAccess->GetSize(); + m_Pos = 0; + m_pFileAccess = pFileAccess; + m_BufOffset = 0; + pFileAccess->ReadBlock( + m_pFileBuf, 0, + (size_t)((FX_FILESIZE)m_BufSize > m_FileLen ? m_FileLen : m_BufSize)); } -FX_BOOL CPDF_SyntaxParser::GetNextChar(uint8_t& ch) -{ - FX_FILESIZE pos = m_Pos + m_HeaderOffset; - if (pos >= m_FileLen) { - return FALSE; +int32_t CPDF_SyntaxParser::GetDirectNum() { + GetNextWord(); + if (!m_bIsNumber) { + return 0; + } + m_WordBuffer[m_WordSize] = 0; + return FXSYS_atoi((const FX_CHAR*)m_WordBuffer); +} +FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, + FX_FILESIZE limit, + const uint8_t* tag, + FX_DWORD taglen) { + uint8_t type = PDF_CharType[tag[0]]; + FX_BOOL bCheckLeft = type != 'D' && type != 'W'; + type = PDF_CharType[tag[taglen - 1]]; + FX_BOOL bCheckRight = type != 'D' && type != 'W'; + uint8_t ch; + if (bCheckRight && startpos + (int32_t)taglen <= limit && + GetCharAt(startpos + (int32_t)taglen, ch)) { + uint8_t type = PDF_CharType[ch]; + if (type == 'N' || type == 'R') { + return FALSE; } - if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) { - FX_FILESIZE read_pos = pos; - FX_DWORD read_size = m_BufSize; - if ((FX_FILESIZE)read_size > m_FileLen) { - read_size = (FX_DWORD)m_FileLen; - } - if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) { - if (m_FileLen < (FX_FILESIZE)read_size) { - read_pos = 0; - read_size = (FX_DWORD)m_FileLen; - } else { - read_pos = m_FileLen - read_size; - } - } - if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) { - return FALSE; - } - m_BufOffset = read_pos; + } + if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) { + uint8_t type = PDF_CharType[ch]; + if (type == 'N' || type == 'R') { + return FALSE; } - ch = m_pFileBuf[pos - m_BufOffset]; - m_Pos ++; - return TRUE; + } + return TRUE; } -FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, uint8_t& ch) -{ - pos += m_HeaderOffset; - if (pos >= m_FileLen) { +FX_BOOL CPDF_SyntaxParser::SearchWord(const CFX_ByteStringC& tag, + FX_BOOL bWholeWord, + FX_BOOL bForward, + FX_FILESIZE limit) { + int32_t taglen = tag.GetLength(); + if (taglen == 0) { + return FALSE; + } + FX_FILESIZE pos = m_Pos; + int32_t offset = 0; + if (!bForward) { + offset = taglen - 1; + } + const uint8_t* tag_data = tag.GetPtr(); + uint8_t byte; + while (1) { + if (bForward) { + if (limit) { + if (pos >= m_Pos + limit) { + return FALSE; + } + } + if (!GetCharAt(pos, byte)) { return FALSE; - } - if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) { - FX_FILESIZE read_pos; - if (pos < (FX_FILESIZE)m_BufSize) { - read_pos = 0; - } else { - read_pos = pos - m_BufSize + 1; - } - FX_DWORD read_size = m_BufSize; - if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) { - if (m_FileLen < (FX_FILESIZE)read_size) { - read_pos = 0; - read_size = (FX_DWORD)m_FileLen; - } else { - read_pos = m_FileLen - read_size; - } - } - if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) { - return FALSE; + } + } else { + if (limit) { + if (pos <= m_Pos - limit) { + return FALSE; } - m_BufOffset = read_pos; - } - ch = m_pFileBuf[pos - m_BufOffset]; - return TRUE; -} -FX_BOOL CPDF_SyntaxParser::ReadBlock(uint8_t* pBuf, FX_DWORD size) -{ - if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) { + } + if (!GetCharAtBackward(pos, byte)) { return FALSE; + } + } + if (byte == tag_data[offset]) { + if (bForward) { + offset++; + if (offset < taglen) { + pos++; + continue; + } + } else { + offset--; + if (offset >= 0) { + pos--; + continue; + } + } + FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos; + if (!bWholeWord || IsWholeWord(startpos, limit, tag.GetPtr(), taglen)) { + m_Pos = startpos; + return TRUE; + } } - m_Pos += size; - return TRUE; -} -#define MAX_WORD_BUFFER 256 -void CPDF_SyntaxParser::GetNextWord() -{ - m_WordSize = 0; - m_bIsNumber = TRUE; - uint8_t ch; - if (!GetNextChar(ch)) { - return; + if (bForward) { + offset = byte == tag_data[0] ? 1 : 0; + pos++; + } else { + offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1; + pos--; } - uint8_t type = PDF_CharType[ch]; - while (1) { - while (type == 'W') { - if (!GetNextChar(ch)) { - return; - } - type = PDF_CharType[ch]; - } - if (ch != '%') { - break; - } - while (1) { - if (!GetNextChar(ch)) { - return; - } - if (ch == '\r' || ch == '\n') { - break; - } - } - type = PDF_CharType[ch]; + if (pos < 0) { + return FALSE; } - if (type == 'D') { - m_bIsNumber = FALSE; - m_WordBuffer[m_WordSize++] = ch; - if (ch == '/') { - while (1) { - if (!GetNextChar(ch)) { - return; - } - type = PDF_CharType[ch]; - if (type != 'R' && type != 'N') { - m_Pos --; - return; - } - if (m_WordSize < MAX_WORD_BUFFER) { - m_WordBuffer[m_WordSize++] = ch; - } - } - } else if (ch == '<') { - if (!GetNextChar(ch)) { - return; - } - if (ch == '<') { - m_WordBuffer[m_WordSize++] = ch; - } else { - m_Pos --; - } - } else if (ch == '>') { - if (!GetNextChar(ch)) { - return; - } - if (ch == '>') { - m_WordBuffer[m_WordSize++] = ch; + } + return FALSE; +} +struct _SearchTagRecord { + const uint8_t* m_pTag; + FX_DWORD m_Len; + FX_DWORD m_Offset; +}; +int32_t CPDF_SyntaxParser::SearchMultiWord(const CFX_ByteStringC& tags, + FX_BOOL bWholeWord, + FX_FILESIZE limit) { + int32_t ntags = 1, i; + for (i = 0; i < tags.GetLength(); i++) + if (tags[i] == 0) { + ntags++; + } + _SearchTagRecord* pPatterns = FX_Alloc(_SearchTagRecord, ntags); + FX_DWORD start = 0, itag = 0, max_len = 0; + for (i = 0; i <= tags.GetLength(); i++) { + if (tags[i] == 0) { + FX_DWORD len = i - start; + if (len > max_len) { + max_len = len; + } + pPatterns[itag].m_pTag = tags.GetPtr() + start; + pPatterns[itag].m_Len = len; + pPatterns[itag].m_Offset = 0; + start = i + 1; + itag++; + } + } + FX_FILESIZE pos = m_Pos; + uint8_t byte; + GetCharAt(pos++, byte); + int32_t found = -1; + while (1) { + for (i = 0; i < ntags; i++) { + if (pPatterns[i].m_pTag[pPatterns[i].m_Offset] == byte) { + pPatterns[i].m_Offset++; + if (pPatterns[i].m_Offset == pPatterns[i].m_Len) { + if (!bWholeWord || + IsWholeWord(pos - pPatterns[i].m_Len, limit, pPatterns[i].m_pTag, + pPatterns[i].m_Len)) { + found = i; + goto end; + } else { + if (pPatterns[i].m_pTag[0] == byte) { + pPatterns[i].m_Offset = 1; } else { - m_Pos --; + pPatterns[i].m_Offset = 0; } + } } - return; - } - while (1) { - if (m_WordSize < MAX_WORD_BUFFER) { - m_WordBuffer[m_WordSize++] = ch; - } - if (type != 'N') { - m_bIsNumber = FALSE; - } - if (!GetNextChar(ch)) { - return; - } - type = PDF_CharType[ch]; - if (type == 'D' || type == 'W') { - m_Pos --; - break; + } else { + if (pPatterns[i].m_pTag[0] == byte) { + pPatterns[i].m_Offset = 1; + } else { + pPatterns[i].m_Offset = 0; } + } } + if (limit && pos >= m_Pos + limit) { + goto end; + } + if (!GetCharAt(pos, byte)) { + goto end; + } + pos++; + } +end: + FX_Free(pPatterns); + return found; } -CFX_ByteString CPDF_SyntaxParser::ReadString() -{ +FX_FILESIZE CPDF_SyntaxParser::FindTag(const CFX_ByteStringC& tag, + FX_FILESIZE limit) { + int32_t taglen = tag.GetLength(); + int32_t match = 0; + limit += m_Pos; + FX_FILESIZE startpos = m_Pos; + while (1) { uint8_t ch; if (!GetNextChar(ch)) { - return CFX_ByteString(); + return -1; } - CFX_ByteTextBuf buf; - int32_t parlevel = 0; - int32_t status = 0, iEscCode = 0; - while (1) { - switch (status) { - case 0: - if (ch == ')') { - if (parlevel == 0) { - return buf.GetByteString(); - } - parlevel --; - buf.AppendChar(')'); - } else if (ch == '(') { - parlevel ++; - buf.AppendChar('('); - } else if (ch == '\\') { - status = 1; - } else { - buf.AppendChar(ch); - } - break; - case 1: - if (ch >= '0' && ch <= '7') { - iEscCode = ch - '0'; - status = 2; - break; - } - if (ch == 'n') { - buf.AppendChar('\n'); - } else if (ch == 'r') { - buf.AppendChar('\r'); - } else if (ch == 't') { - buf.AppendChar('\t'); - } else if (ch == 'b') { - buf.AppendChar('\b'); - } else if (ch == 'f') { - buf.AppendChar('\f'); - } else if (ch == '\r') { - status = 4; - break; - } else if (ch == '\n') { - } else { - buf.AppendChar(ch); - } - status = 0; - break; - case 2: - if (ch >= '0' && ch <= '7') { - iEscCode = iEscCode * 8 + ch - '0'; - status = 3; - } else { - buf.AppendChar(iEscCode); - status = 0; - continue; - } - break; - case 3: - if (ch >= '0' && ch <= '7') { - iEscCode = iEscCode * 8 + ch - '0'; - buf.AppendChar(iEscCode); - status = 0; - } else { - buf.AppendChar(iEscCode); - status = 0; - continue; - } - break; - case 4: - status = 0; - if (ch != '\n') { - continue; - } - break; - } - if (!GetNextChar(ch)) { - break; - } + if (ch == tag[match]) { + match++; + if (match == taglen) { + return m_Pos - startpos - taglen; + } + } else { + match = ch == tag[0] ? 1 : 0; + } + if (limit && m_Pos == limit) { + return -1; } - GetNextChar(ch); - return buf.GetByteString(); + } + return -1; } -CFX_ByteString CPDF_SyntaxParser::ReadHexString() -{ - uint8_t ch; +void CPDF_SyntaxParser::GetBinary(uint8_t* buffer, FX_DWORD size) { + FX_DWORD offset = 0; + uint8_t ch; + while (1) { if (!GetNextChar(ch)) { - return CFX_ByteString(); + return; } - CFX_BinaryBuf buf; - FX_BOOL bFirst = TRUE; - uint8_t code = 0; - while (1) { - if (ch == '>') { - break; - } - if (ch >= '0' && ch <= '9') { - if (bFirst) { - code = (ch - '0') * 16; - } else { - code += ch - '0'; - buf.AppendByte((uint8_t)code); - } - bFirst = !bFirst; - } else if (ch >= 'A' && ch <= 'F') { - if (bFirst) { - code = (ch - 'A' + 10) * 16; - } else { - code += ch - 'A' + 10; - buf.AppendByte((uint8_t)code); - } - bFirst = !bFirst; - } else if (ch >= 'a' && ch <= 'f') { - if (bFirst) { - code = (ch - 'a' + 10) * 16; - } else { - code += ch - 'a' + 10; - buf.AppendByte((uint8_t)code); - } - bFirst = !bFirst; - } - if (!GetNextChar(ch)) { - break; - } - } - if (!bFirst) { - buf.AppendByte((uint8_t)code); - } - return buf.GetByteString(); -} -void CPDF_SyntaxParser::ToNextLine() -{ - uint8_t ch; - while (GetNextChar(ch)) { - if (ch == '\n') { - break; - } - if (ch == '\r') { - GetNextChar(ch); - if (ch != '\n') { - --m_Pos; - } - break; - } - } -} -void CPDF_SyntaxParser::ToNextWord() -{ - uint8_t ch; - if (!GetNextChar(ch)) { - return; - } - uint8_t type = PDF_CharType[ch]; - while (1) { - while (type == 'W') { - m_dwWordPos = m_Pos; - if (!GetNextChar(ch)) { - return; - } - type = PDF_CharType[ch]; - } - if (ch != '%') { - break; - } - while (1) { - if (!GetNextChar(ch)) { - return; - } - if (ch == '\r' || ch == '\n') { - break; - } - } - type = PDF_CharType[ch]; - } - m_Pos --; -} -CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber) -{ - GetNextWord(); - bIsNumber = m_bIsNumber; - return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize); -} -CFX_ByteString CPDF_SyntaxParser::GetKeyword() -{ - GetNextWord(); - return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize); -} -CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, PARSE_CONTEXT* pContext, FX_BOOL bDecrypt) -{ - CFX_AutoRestorer restorer(&s_CurrentRecursionDepth); - if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) { - return NULL; - } - FX_FILESIZE SavedPos = m_Pos; - FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY); - FX_BOOL bIsNumber; - CFX_ByteString word = GetNextWord(bIsNumber); - CPDF_Object* pRet = NULL; - if (word.GetLength() == 0) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_INVALID; - } - return NULL; - } - if (bIsNumber) { - FX_FILESIZE SavedPos = m_Pos; - CFX_ByteString nextword = GetNextWord(bIsNumber); - if (bIsNumber) { - CFX_ByteString nextword2 = GetNextWord(bIsNumber); - if (nextword2 == FX_BSTRC("R")) { - FX_DWORD objnum = FXSYS_atoi(word); - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_REFERENCE; - } - return new CPDF_Reference(pObjList, objnum); - } - } - m_Pos = SavedPos; - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_NUMBER; - } - return CPDF_Number::Create(word); - } - if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_BOOLEAN; - } - pRet = CPDF_Boolean::Create(word == FX_BSTRC("true")); - return pRet; - } - if (word == FX_BSTRC("null")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_NULL; - } - pRet = CPDF_Null::Create(); - return pRet; - } - if (word == FX_BSTRC("(")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_STRING; - } - CFX_ByteString str = ReadString(); - if (m_pCryptoHandler && bDecrypt) { - m_pCryptoHandler->Decrypt(objnum, gennum, str); - } - pRet = CPDF_String::Create(str, FALSE); - return pRet; - } - if (word == FX_BSTRC("<")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_STRING; - } - CFX_ByteString str = ReadHexString(); - if (m_pCryptoHandler && bDecrypt) { - m_pCryptoHandler->Decrypt(objnum, gennum, str); - } - pRet = CPDF_String::Create(str, TRUE); - return pRet; - } - if (word == FX_BSTRC("[")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_ARRAY; - } - CPDF_Array* pArray = CPDF_Array::Create(); - while (1) { - CPDF_Object* pObj = GetObject(pObjList, objnum, gennum); - if (pObj == NULL) { - return pArray; - } - pArray->Add(pObj); - } - } - if (word[0] == '/') { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_NAME; - } - pRet = CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); - return pRet; - } - if (word == FX_BSTRC("<<")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_DICTIONARY; - } - if (pContext) { - pContext->m_DictStart = SavedPos; - } - CPDF_Dictionary* pDict = CPDF_Dictionary::Create(); - int32_t nKeys = 0; - FX_FILESIZE dwSignValuePos = 0; - while (1) { - FX_BOOL bIsNumber; - CFX_ByteString key = GetNextWord(bIsNumber); - if (key.IsEmpty()) { - if (pDict) - pDict->Release(); - return NULL; - } - FX_FILESIZE SavedPos = m_Pos - key.GetLength(); - if (key == FX_BSTRC(">>")) { - break; - } - if (key == FX_BSTRC("endobj")) { - m_Pos = SavedPos; - break; - } - if (key[0] != '/') { - continue; - } - nKeys ++; - key = PDF_NameDecode(key); - if (key == FX_BSTRC("/Contents")) { - dwSignValuePos = m_Pos; - } - CPDF_Object* pObj = GetObject(pObjList, objnum, gennum); - if (pObj == NULL) { - continue; - } - if (key.GetLength() >= 1) { - if (nKeys < 32) { - pDict->SetAt(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj); - } else { - pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj); - } - } - } - if (IsSignatureDict(pDict)) { - FX_FILESIZE dwSavePos = m_Pos; - m_Pos = dwSignValuePos; - CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, NULL, FALSE); - pDict->SetAt(FX_BSTRC("Contents"), pObj); - m_Pos = dwSavePos; - } - if (pContext) { - pContext->m_DictEnd = m_Pos; - if (pContext->m_Flags & PDFPARSE_NOSTREAM) { - return pDict; - } - } - FX_FILESIZE SavedPos = m_Pos; - FX_BOOL bIsNumber; - CFX_ByteString nextword = GetNextWord(bIsNumber); - if (nextword == FX_BSTRC("stream")) { - CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum); - if (pStream) { - return pStream; - } - if (pDict) - pDict->Release(); - return NULL; - } else { - m_Pos = SavedPos; - return pDict; - } - } - if (word == FX_BSTRC(">>")) { - m_Pos = SavedPos; - return NULL; - } - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_INVALID; - } - return NULL; -} -CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, struct PARSE_CONTEXT* pContext) -{ - CFX_AutoRestorer restorer(&s_CurrentRecursionDepth); - if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) { - return NULL; - } - FX_FILESIZE SavedPos = m_Pos; - FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY); - FX_BOOL bIsNumber; - CFX_ByteString word = GetNextWord(bIsNumber); - if (word.GetLength() == 0) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_INVALID; - } - return NULL; - } - if (bIsNumber) { - FX_FILESIZE SavedPos = m_Pos; - CFX_ByteString nextword = GetNextWord(bIsNumber); - if (bIsNumber) { - CFX_ByteString nextword2 = GetNextWord(bIsNumber); - if (nextword2 == FX_BSTRC("R")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_REFERENCE; - } - FX_DWORD objnum = FXSYS_atoi(word); - return new CPDF_Reference(pObjList, objnum); - } - } - m_Pos = SavedPos; - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_NUMBER; - } - return CPDF_Number::Create(word); - } - if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_BOOLEAN; - } - return CPDF_Boolean::Create(word == FX_BSTRC("true")); - } - if (word == FX_BSTRC("null")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_NULL; - } - return CPDF_Null::Create(); - } - if (word == FX_BSTRC("(")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_STRING; - } - CFX_ByteString str = ReadString(); - if (m_pCryptoHandler) { - m_pCryptoHandler->Decrypt(objnum, gennum, str); - } - return CPDF_String::Create(str, FALSE); - } - if (word == FX_BSTRC("<")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_STRING; - } - CFX_ByteString str = ReadHexString(); - if (m_pCryptoHandler) { - m_pCryptoHandler->Decrypt(objnum, gennum, str); - } - return CPDF_String::Create(str, TRUE); - } - if (word == FX_BSTRC("[")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_ARRAY; - } - CPDF_Array* pArray = CPDF_Array::Create(); - while (1) { - CPDF_Object* pObj = GetObject(pObjList, objnum, gennum); - if (pObj == NULL) { - if (m_WordBuffer[0] == ']') { - return pArray; - } - if (pArray) { - pArray->Release(); - } - return NULL; - } - pArray->Add(pObj); - } - } - if (word[0] == '/') { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_NAME; - } - return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); - } - if (word == FX_BSTRC("<<")) { - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_DICTIONARY; - } - if (pContext) { - pContext->m_DictStart = SavedPos; - } - CPDF_Dictionary* pDict = CPDF_Dictionary::Create(); - while (1) { - FX_BOOL bIsNumber; - FX_FILESIZE SavedPos = m_Pos; - CFX_ByteString key = GetNextWord(bIsNumber); - if (key.IsEmpty()) { - if (pDict) { - pDict->Release(); - } - return NULL; - } - if (key == FX_BSTRC(">>")) { - break; - } - if (key == FX_BSTRC("endobj")) { - m_Pos = SavedPos; - break; - } - if (key[0] != '/') { - continue; - } - key = PDF_NameDecode(key); - CPDF_Object* pObj = GetObject(pObjList, objnum, gennum); - if (pObj == NULL) { - if (pDict) { - pDict->Release(); - } - uint8_t ch; - while (1) { - if (!GetNextChar(ch)) { - break; - } - if (ch == 0x0A || ch == 0x0D) { - break; - } - } - return NULL; - } - if (key.GetLength() > 1) { - pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj); - } - } - if (pContext) { - pContext->m_DictEnd = m_Pos; - if (pContext->m_Flags & PDFPARSE_NOSTREAM) { - return pDict; - } - } - FX_FILESIZE SavedPos = m_Pos; - FX_BOOL bIsNumber; - CFX_ByteString nextword = GetNextWord(bIsNumber); - if (nextword == FX_BSTRC("stream")) { - CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum); - if (pStream) { - return pStream; - } - if (pDict) { - pDict->Release(); - } - return NULL; - } else { - m_Pos = SavedPos; - return pDict; - } - } - if (word == FX_BSTRC(">>")) { - m_Pos = SavedPos; - return NULL; - } - if (bTypeOnly) { - return (CPDF_Object*)PDFOBJ_INVALID; - } - return NULL; -} -CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, PARSE_CONTEXT* pContext, - FX_DWORD objnum, FX_DWORD gennum) -{ - CPDF_Object* pLenObj = pDict->GetElement(FX_BSTRC("Length")); - FX_FILESIZE len = 0; - if (pLenObj && ((pLenObj->GetType() != PDFOBJ_REFERENCE) || - ((((CPDF_Reference*)pLenObj)->GetObjList() != NULL) && - ((CPDF_Reference*)pLenObj)->GetRefObjNum() != objnum))) { - len = pLenObj->GetInteger(); - } - - ToNextLine(); - FX_FILESIZE StreamStartPos = m_Pos; - if (pContext) { - pContext->m_DataStart = m_Pos; - } - - CPDF_CryptoHandler* pCryptoHandler = objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler; - if (pCryptoHandler == NULL) { - pdfium::base::CheckedNumeric pos = m_Pos; - pos += len; - if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) { - m_Pos = pos.ValueOrDie(); - } - GetNextWord(); - if (m_WordSize < 9 || FXSYS_memcmp(m_WordBuffer, "endstream", 9)) { - m_Pos = StreamStartPos; - FX_FILESIZE offset = FindTag(FX_BSTRC("endstream"), 0); - if (offset >= 0) { - FX_FILESIZE curPos = m_Pos; - m_Pos = StreamStartPos; - FX_FILESIZE endobjOffset = FindTag(FX_BSTRC("endobj"), 0); - if (endobjOffset < offset && endobjOffset >= 0) { - offset = endobjOffset; - } else { - m_Pos = curPos; - } - uint8_t byte1, byte2; - GetCharAt(StreamStartPos + offset - 1, byte1); - GetCharAt(StreamStartPos + offset - 2, byte2); - if (byte1 == 0x0a && byte2 == 0x0d) { - len -= 2; - } else if (byte1 == 0x0a || byte1 == 0x0d) { - len --; - } - len = (FX_DWORD)offset; - pDict->SetAtInteger(FX_BSTRC("Length"), len); - } else { - m_Pos = StreamStartPos; - if (FindTag(FX_BSTRC("endobj"), 0) < 0) { - return NULL; - } - } - } - m_Pos = StreamStartPos; - } - CPDF_Stream* pStream; - uint8_t* pData = FX_Alloc(uint8_t, len); - ReadBlock(pData, len); - if (pCryptoHandler) { - CFX_BinaryBuf dest_buf; - dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len)); - void* context = pCryptoHandler->DecryptStart(objnum, gennum); - pCryptoHandler->DecryptStream(context, pData, len, dest_buf); - pCryptoHandler->DecryptFinish(context, dest_buf); - FX_Free(pData); - pData = dest_buf.GetBuffer(); - len = dest_buf.GetSize(); - dest_buf.DetachBuffer(); - } - pStream = new CPDF_Stream(pData, len, pDict); - if (pContext) { - pContext->m_DataEnd = pContext->m_DataStart + len; - } - StreamStartPos = m_Pos; - GetNextWord(); - if (m_WordSize == 6 && 0 == FXSYS_memcmp(m_WordBuffer, "endobj", 6)) { - m_Pos = StreamStartPos; - } - return pStream; -} -void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess, FX_DWORD HeaderOffset) -{ - if (m_pFileBuf) { - FX_Free(m_pFileBuf); - m_pFileBuf = NULL; - } - m_pFileBuf = FX_Alloc(uint8_t, m_BufSize); - m_HeaderOffset = HeaderOffset; - m_FileLen = pFileAccess->GetSize(); - m_Pos = 0; - m_pFileAccess = pFileAccess; - m_BufOffset = 0; - pFileAccess->ReadBlock(m_pFileBuf, 0, (size_t)((FX_FILESIZE)m_BufSize > m_FileLen ? m_FileLen : m_BufSize)); -} -int32_t CPDF_SyntaxParser::GetDirectNum() -{ - GetNextWord(); - if (!m_bIsNumber) { - return 0; - } - m_WordBuffer[m_WordSize] = 0; - return FXSYS_atoi((const FX_CHAR*)m_WordBuffer); -} -FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit, const uint8_t* tag, FX_DWORD taglen) -{ - uint8_t type = PDF_CharType[tag[0]]; - FX_BOOL bCheckLeft = type != 'D' && type != 'W'; - type = PDF_CharType[tag[taglen - 1]]; - FX_BOOL bCheckRight = type != 'D' && type != 'W'; - uint8_t ch; - if (bCheckRight && startpos + (int32_t)taglen <= limit && GetCharAt(startpos + (int32_t)taglen, ch)) { - uint8_t type = PDF_CharType[ch]; - if (type == 'N' || type == 'R') { - return FALSE; - } - } - if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) { - uint8_t type = PDF_CharType[ch]; - if (type == 'N' || type == 'R') { - return FALSE; - } - } - return TRUE; -} -FX_BOOL CPDF_SyntaxParser::SearchWord(const CFX_ByteStringC& tag, FX_BOOL bWholeWord, FX_BOOL bForward, FX_FILESIZE limit) -{ - int32_t taglen = tag.GetLength(); - if (taglen == 0) { - return FALSE; - } - FX_FILESIZE pos = m_Pos; - int32_t offset = 0; - if (!bForward) { - offset = taglen - 1; - } - const uint8_t* tag_data = tag.GetPtr(); - uint8_t byte; - while (1) { - if (bForward) { - if (limit) { - if (pos >= m_Pos + limit) { - return FALSE; - } - } - if (!GetCharAt(pos, byte)) { - return FALSE; - } - } else { - if (limit) { - if (pos <= m_Pos - limit) { - return FALSE; - } - } - if (!GetCharAtBackward(pos, byte)) { - return FALSE; - } - } - if (byte == tag_data[offset]) { - if (bForward) { - offset ++; - if (offset < taglen) { - pos ++; - continue; - } - } else { - offset --; - if (offset >= 0) { - pos --; - continue; - } - } - FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos; - if (!bWholeWord || IsWholeWord(startpos, limit, tag.GetPtr(), taglen)) { - m_Pos = startpos; - return TRUE; - } - } - if (bForward) { - offset = byte == tag_data[0] ? 1 : 0; - pos ++; - } else { - offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1; - pos --; - } - if (pos < 0) { - return FALSE; - } - } - return FALSE; -} -struct _SearchTagRecord { - const uint8_t* m_pTag; - FX_DWORD m_Len; - FX_DWORD m_Offset; -}; -int32_t CPDF_SyntaxParser::SearchMultiWord(const CFX_ByteStringC& tags, FX_BOOL bWholeWord, FX_FILESIZE limit) -{ - int32_t ntags = 1, i; - for (i = 0; i < tags.GetLength(); i ++) - if (tags[i] == 0) { - ntags ++; - } - _SearchTagRecord* pPatterns = FX_Alloc(_SearchTagRecord, ntags); - FX_DWORD start = 0, itag = 0, max_len = 0; - for (i = 0; i <= tags.GetLength(); i ++) { - if (tags[i] == 0) { - FX_DWORD len = i - start; - if (len > max_len) { - max_len = len; - } - pPatterns[itag].m_pTag = tags.GetPtr() + start; - pPatterns[itag].m_Len = len; - pPatterns[itag].m_Offset = 0; - start = i + 1; - itag ++; - } - } - FX_FILESIZE pos = m_Pos; - uint8_t byte; - GetCharAt(pos++, byte); - int32_t found = -1; - while (1) { - for (i = 0; i < ntags; i ++) { - if (pPatterns[i].m_pTag[pPatterns[i].m_Offset] == byte) { - pPatterns[i].m_Offset ++; - if (pPatterns[i].m_Offset == pPatterns[i].m_Len) { - if (!bWholeWord || IsWholeWord(pos - pPatterns[i].m_Len, limit, pPatterns[i].m_pTag, pPatterns[i].m_Len)) { - found = i; - goto end; - } else { - if (pPatterns[i].m_pTag[0] == byte) { - pPatterns[i].m_Offset = 1; - } else { - pPatterns[i].m_Offset = 0; - } - } - } - } else { - if (pPatterns[i].m_pTag[0] == byte) { - pPatterns[i].m_Offset = 1; - } else { - pPatterns[i].m_Offset = 0; - } - } - } - if (limit && pos >= m_Pos + limit) { - goto end; - } - if (!GetCharAt(pos, byte)) { - goto end; - } - pos ++; - } -end: - FX_Free(pPatterns); - return found; -} -FX_FILESIZE CPDF_SyntaxParser::FindTag(const CFX_ByteStringC& tag, FX_FILESIZE limit) -{ - int32_t taglen = tag.GetLength(); - int32_t match = 0; - limit += m_Pos; - FX_FILESIZE startpos = m_Pos; - while (1) { - uint8_t ch; - if (!GetNextChar(ch)) { - return -1; - } - if (ch == tag[match]) { - match ++; - if (match == taglen) { - return m_Pos - startpos - taglen; - } - } else { - match = ch == tag[0] ? 1 : 0; - } - if (limit && m_Pos == limit) { - return -1; - } - } - return -1; -} -void CPDF_SyntaxParser::GetBinary(uint8_t* buffer, FX_DWORD size) -{ - FX_DWORD offset = 0; - uint8_t ch; - while (1) { - if (!GetNextChar(ch)) { - return; - } - buffer[offset++] = ch; - if (offset == size) { - break; - } + buffer[offset++] = ch; + if (offset == size) { + break; } + } } -class CPDF_DataAvail final : public IPDF_DataAvail -{ -public: - CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead); - ~CPDF_DataAvail(); +class CPDF_DataAvail final : public IPDF_DataAvail { + public: + CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead); + ~CPDF_DataAvail(); - virtual FX_BOOL IsDocAvail(IFX_DownloadHints* pHints) override; + virtual FX_BOOL IsDocAvail(IFX_DownloadHints* pHints) override; - virtual void SetDocument(CPDF_Document* pDoc) override; + virtual void SetDocument(CPDF_Document* pDoc) override; - virtual FX_BOOL IsPageAvail(int iPage, IFX_DownloadHints* pHints) override; + virtual FX_BOOL IsPageAvail(int iPage, IFX_DownloadHints* pHints) override; - virtual int32_t IsFormAvail(IFX_DownloadHints *pHints) override; + virtual int32_t IsFormAvail(IFX_DownloadHints* pHints) override; - virtual int32_t IsLinearizedPDF() override; + virtual int32_t IsLinearizedPDF() override; - virtual FX_BOOL IsLinearized() override - { - return m_bLinearized; - } + virtual FX_BOOL IsLinearized() override { return m_bLinearized; } - virtual void GetLinearizedMainXRefInfo(FX_FILESIZE *pPos, FX_DWORD *pSize) override; + virtual void GetLinearizedMainXRefInfo(FX_FILESIZE* pPos, + FX_DWORD* pSize) override; -protected: - static const int kMaxDataAvailRecursionDepth = 64; - static int s_CurrentDataAvailRecursionDepth; + protected: + static const int kMaxDataAvailRecursionDepth = 64; + static int s_CurrentDataAvailRecursionDepth; - FX_DWORD GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset); - FX_BOOL IsObjectsAvail(CFX_PtrArray& obj_array, FX_BOOL bParsePage, IFX_DownloadHints* pHints, CFX_PtrArray &ret_array); - FX_BOOL CheckDocStatus(IFX_DownloadHints *pHints); - FX_BOOL CheckHeader(IFX_DownloadHints* pHints); - FX_BOOL CheckFirstPage(IFX_DownloadHints *pHints); - FX_BOOL CheckEnd(IFX_DownloadHints *pHints); - FX_BOOL CheckCrossRef(IFX_DownloadHints* pHints); - FX_BOOL CheckCrossRefItem(IFX_DownloadHints *pHints); - FX_BOOL CheckTrailer(IFX_DownloadHints* pHints); - FX_BOOL CheckRoot(IFX_DownloadHints* pHints); - FX_BOOL CheckInfo(IFX_DownloadHints* pHints); - FX_BOOL CheckPages(IFX_DownloadHints* pHints); - FX_BOOL CheckPage(IFX_DownloadHints* pHints); - FX_BOOL CheckResources(IFX_DownloadHints* pHints); - FX_BOOL CheckAnnots(IFX_DownloadHints* pHints); - FX_BOOL CheckAcroForm(IFX_DownloadHints* pHints); - FX_BOOL CheckAcroFormSubObject(IFX_DownloadHints* pHints); - FX_BOOL CheckTrailerAppend(IFX_DownloadHints* pHints); - FX_BOOL CheckPageStatus(IFX_DownloadHints* pHints); - FX_BOOL CheckAllCrossRefStream(IFX_DownloadHints *pHints); + FX_DWORD GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset); + FX_BOOL IsObjectsAvail(CFX_PtrArray& obj_array, + FX_BOOL bParsePage, + IFX_DownloadHints* pHints, + CFX_PtrArray& ret_array); + FX_BOOL CheckDocStatus(IFX_DownloadHints* pHints); + FX_BOOL CheckHeader(IFX_DownloadHints* pHints); + FX_BOOL CheckFirstPage(IFX_DownloadHints* pHints); + FX_BOOL CheckEnd(IFX_DownloadHints* pHints); + FX_BOOL CheckCrossRef(IFX_DownloadHints* pHints); + FX_BOOL CheckCrossRefItem(IFX_DownloadHints* pHints); + FX_BOOL CheckTrailer(IFX_DownloadHints* pHints); + FX_BOOL CheckRoot(IFX_DownloadHints* pHints); + FX_BOOL CheckInfo(IFX_DownloadHints* pHints); + FX_BOOL CheckPages(IFX_DownloadHints* pHints); + FX_BOOL CheckPage(IFX_DownloadHints* pHints); + FX_BOOL CheckResources(IFX_DownloadHints* pHints); + FX_BOOL CheckAnnots(IFX_DownloadHints* pHints); + FX_BOOL CheckAcroForm(IFX_DownloadHints* pHints); + FX_BOOL CheckAcroFormSubObject(IFX_DownloadHints* pHints); + FX_BOOL CheckTrailerAppend(IFX_DownloadHints* pHints); + FX_BOOL CheckPageStatus(IFX_DownloadHints* pHints); + FX_BOOL CheckAllCrossRefStream(IFX_DownloadHints* pHints); - int32_t CheckCrossRefStream(IFX_DownloadHints *pHints, FX_FILESIZE &xref_offset); - FX_BOOL IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen); - 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 * GetObject(FX_DWORD objnum, IFX_DownloadHints* pHints, FX_BOOL *pExistInFile); - FX_BOOL GetPageKids(CPDF_Parser *pParser, CPDF_Object *pPages); - FX_BOOL PreparePageItem(); - FX_BOOL LoadPages(IFX_DownloadHints* pHints); - FX_BOOL LoadAllXref(IFX_DownloadHints* pHints); - FX_BOOL LoadAllFile(IFX_DownloadHints* pHints); - FX_BOOL CheckLinearizedData(IFX_DownloadHints* pHints); - FX_BOOL CheckFileResources(IFX_DownloadHints* pHints); - FX_BOOL CheckPageAnnots(int iPage, IFX_DownloadHints* pHints); + int32_t CheckCrossRefStream(IFX_DownloadHints* pHints, + FX_FILESIZE& xref_offset); + FX_BOOL IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen); + 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* GetObject(FX_DWORD objnum, + IFX_DownloadHints* pHints, + FX_BOOL* pExistInFile); + FX_BOOL GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages); + FX_BOOL PreparePageItem(); + FX_BOOL LoadPages(IFX_DownloadHints* pHints); + FX_BOOL LoadAllXref(IFX_DownloadHints* pHints); + FX_BOOL LoadAllFile(IFX_DownloadHints* pHints); + FX_BOOL CheckLinearizedData(IFX_DownloadHints* pHints); + FX_BOOL CheckFileResources(IFX_DownloadHints* pHints); + FX_BOOL CheckPageAnnots(int iPage, IFX_DownloadHints* pHints); - FX_BOOL CheckLinearizedFirstPage(int iPage, IFX_DownloadHints* pHints); - FX_BOOL HaveResourceAncestor(CPDF_Dictionary *pDict); - FX_BOOL CheckPage(int32_t iPage, IFX_DownloadHints* pHints); - FX_BOOL LoadDocPages(IFX_DownloadHints* pHints); - FX_BOOL LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints); - FX_BOOL CheckPageNode(CPDF_PageNode &pageNodes, int32_t iPage, int32_t &iCount, IFX_DownloadHints* pHints); - FX_BOOL CheckUnkownPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints); - FX_BOOL CheckArrayPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints); - FX_BOOL CheckPageCount(IFX_DownloadHints* pHints); - FX_BOOL IsFirstCheck(int iPage); - void ResetFirstCheck(int iPage); + FX_BOOL CheckLinearizedFirstPage(int iPage, IFX_DownloadHints* pHints); + FX_BOOL HaveResourceAncestor(CPDF_Dictionary* pDict); + FX_BOOL CheckPage(int32_t iPage, IFX_DownloadHints* pHints); + FX_BOOL LoadDocPages(IFX_DownloadHints* pHints); + FX_BOOL LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints); + FX_BOOL CheckPageNode(CPDF_PageNode& pageNodes, + int32_t iPage, + int32_t& iCount, + IFX_DownloadHints* pHints); + FX_BOOL CheckUnkownPageNode(FX_DWORD dwPageNo, + CPDF_PageNode* pPageNode, + IFX_DownloadHints* pHints); + FX_BOOL CheckArrayPageNode(FX_DWORD dwPageNo, + CPDF_PageNode* pPageNode, + IFX_DownloadHints* pHints); + FX_BOOL CheckPageCount(IFX_DownloadHints* pHints); + FX_BOOL IsFirstCheck(int iPage); + void ResetFirstCheck(int iPage); - CPDF_Parser m_parser; + CPDF_Parser m_parser; - CPDF_SyntaxParser m_syntaxParser; + CPDF_SyntaxParser m_syntaxParser; - CPDF_Object *m_pRoot; + CPDF_Object* m_pRoot; - FX_DWORD m_dwRootObjNum; + FX_DWORD m_dwRootObjNum; - FX_DWORD m_dwInfoObjNum; + FX_DWORD m_dwInfoObjNum; - CPDF_Object *m_pLinearized; + CPDF_Object* m_pLinearized; - CPDF_Object *m_pTrailer; + CPDF_Object* m_pTrailer; - FX_BOOL m_bDocAvail; + FX_BOOL m_bDocAvail; - FX_FILESIZE m_dwHeaderOffset; + FX_FILESIZE m_dwHeaderOffset; - FX_FILESIZE m_dwLastXRefOffset; + FX_FILESIZE m_dwLastXRefOffset; - FX_FILESIZE m_dwXRefOffset; + FX_FILESIZE m_dwXRefOffset; - FX_FILESIZE m_dwTrailerOffset; + FX_FILESIZE m_dwTrailerOffset; - FX_FILESIZE m_dwCurrentOffset; + FX_FILESIZE m_dwCurrentOffset; - PDF_DATAAVAIL_STATUS m_docStatus; + PDF_DATAAVAIL_STATUS m_docStatus; - FX_FILESIZE m_dwFileLen; + FX_FILESIZE m_dwFileLen; - CPDF_Document* m_pDocument; + CPDF_Document* m_pDocument; - CPDF_SortObjNumArray m_objnum_array; + CPDF_SortObjNumArray m_objnum_array; - CFX_PtrArray m_objs_array; + CFX_PtrArray m_objs_array; - FX_FILESIZE m_Pos; + FX_FILESIZE m_Pos; - FX_FILESIZE m_bufferOffset; + FX_FILESIZE m_bufferOffset; - FX_DWORD m_bufferSize; + FX_DWORD m_bufferSize; - CFX_ByteString m_WordBuf; + CFX_ByteString m_WordBuf; - uint8_t m_WordBuffer[257]; + uint8_t m_WordBuffer[257]; - FX_DWORD m_WordSize; + FX_DWORD m_WordSize; - uint8_t m_bufferData[512]; + uint8_t m_bufferData[512]; - CFX_FileSizeArray m_CrossOffset; + CFX_FileSizeArray m_CrossOffset; - CFX_DWordArray m_XRefStreamList; + CFX_DWordArray m_XRefStreamList; - CFX_DWordArray m_PageObjList; + CFX_DWordArray m_PageObjList; - FX_DWORD m_PagesObjNum; + FX_DWORD m_PagesObjNum; - FX_BOOL m_bLinearized; + FX_BOOL m_bLinearized; - FX_DWORD m_dwFirstPageNo; + FX_DWORD m_dwFirstPageNo; - FX_BOOL m_bLinearedDataOK; + FX_BOOL m_bLinearedDataOK; - FX_BOOL m_bMainXRefLoadTried; + FX_BOOL m_bMainXRefLoadTried; - FX_BOOL m_bMainXRefLoadedOK; + FX_BOOL m_bMainXRefLoadedOK; - FX_BOOL m_bPagesTreeLoad; + FX_BOOL m_bPagesTreeLoad; - FX_BOOL m_bPagesLoad; + FX_BOOL m_bPagesLoad; - CPDF_Parser * m_pCurrentParser; + CPDF_Parser* m_pCurrentParser; - FX_FILESIZE m_dwCurrentXRefSteam; + FX_FILESIZE m_dwCurrentXRefSteam; - FX_BOOL m_bAnnotsLoad; + FX_BOOL m_bAnnotsLoad; - FX_BOOL m_bHaveAcroForm; + FX_BOOL m_bHaveAcroForm; - FX_DWORD m_dwAcroFormObjNum; + FX_DWORD m_dwAcroFormObjNum; - FX_BOOL m_bAcroFormLoad; + FX_BOOL m_bAcroFormLoad; - CPDF_Object * m_pAcroForm; + CPDF_Object* m_pAcroForm; - CFX_PtrArray m_arrayAcroforms; + CFX_PtrArray m_arrayAcroforms; - CPDF_Dictionary * m_pPageDict; + CPDF_Dictionary* m_pPageDict; - CPDF_Object * m_pPageResource; + CPDF_Object* m_pPageResource; - FX_BOOL m_bNeedDownLoadResource; + FX_BOOL m_bNeedDownLoadResource; - FX_BOOL m_bPageLoadedOK; + FX_BOOL m_bPageLoadedOK; - FX_BOOL m_bLinearizedFormParamLoad; + FX_BOOL m_bLinearizedFormParamLoad; - CFX_PtrArray m_PagesArray; + CFX_PtrArray m_PagesArray; - FX_DWORD m_dwEncryptObjNum; + FX_DWORD m_dwEncryptObjNum; - FX_FILESIZE m_dwPrevXRefOffset; + FX_FILESIZE m_dwPrevXRefOffset; - FX_BOOL m_bTotalLoadPageTree; + FX_BOOL m_bTotalLoadPageTree; - FX_BOOL m_bCurPageDictLoadOK; + FX_BOOL m_bCurPageDictLoadOK; - CPDF_PageNode m_pageNodes; + CPDF_PageNode m_pageNodes; - CFX_CMapDWordToDWord * m_pageMapCheckState; + CFX_CMapDWordToDWord* m_pageMapCheckState; - CFX_CMapDWordToDWord * m_pagesLoadState; + CFX_CMapDWordToDWord* m_pagesLoadState; }; -IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead) : - m_pFileAvail(pFileAvail), - m_pFileRead(pFileRead) { -} +IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail, + IFX_FileRead* pFileRead) + : m_pFileAvail(pFileAvail), m_pFileRead(pFileRead) {} // static -IPDF_DataAvail* IPDF_DataAvail::Create(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead) -{ +IPDF_DataAvail* IPDF_DataAvail::Create(IFX_FileAvail* pFileAvail, + IFX_FileRead* pFileRead) { return new CPDF_DataAvail(pFileAvail, pFileRead); } // static int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0; -CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead) - : IPDF_DataAvail(pFileAvail, pFileRead) -{ - m_Pos = 0; - m_dwFileLen = 0; - if (m_pFileRead) { - m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize(); - } - m_dwCurrentOffset = 0; - m_WordSize = 0; - m_dwXRefOffset = 0; - m_bufferOffset = 0; - m_dwFirstPageNo = 0; - m_bufferSize = 0; - m_PagesObjNum = 0; - m_dwCurrentXRefSteam = 0; - m_dwAcroFormObjNum = 0; - m_dwInfoObjNum = 0; - m_pDocument = 0; - m_dwEncryptObjNum = 0; - m_dwPrevXRefOffset = 0; - m_dwLastXRefOffset = 0; - m_bDocAvail = FALSE; - m_bMainXRefLoadTried = FALSE; - m_bDocAvail = FALSE; - m_bLinearized = FALSE; - m_bPagesLoad = FALSE; - m_bPagesTreeLoad = FALSE; - m_bMainXRefLoadedOK = FALSE; - m_bAnnotsLoad = FALSE; - m_bHaveAcroForm = FALSE; - m_bAcroFormLoad = FALSE; - m_bPageLoadedOK = FALSE; - m_bNeedDownLoadResource = FALSE; - m_bLinearizedFormParamLoad = FALSE; - m_pLinearized = NULL; - m_pRoot = NULL; - m_pTrailer = NULL; - m_pCurrentParser = NULL; - m_pAcroForm = NULL; - m_pPageDict = NULL; - m_pPageResource = NULL; - m_pageMapCheckState = NULL; - m_docStatus = PDF_DATAAVAIL_HEADER; - m_parser.m_bOwnFileRead = FALSE; - m_bTotalLoadPageTree = FALSE; - m_bCurPageDictLoadOK = FALSE; - m_bLinearedDataOK = FALSE; - m_pagesLoadState = NULL; +CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail, + IFX_FileRead* pFileRead) + : IPDF_DataAvail(pFileAvail, pFileRead) { + m_Pos = 0; + m_dwFileLen = 0; + if (m_pFileRead) { + m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize(); + } + m_dwCurrentOffset = 0; + m_WordSize = 0; + m_dwXRefOffset = 0; + m_bufferOffset = 0; + m_dwFirstPageNo = 0; + m_bufferSize = 0; + m_PagesObjNum = 0; + m_dwCurrentXRefSteam = 0; + m_dwAcroFormObjNum = 0; + m_dwInfoObjNum = 0; + m_pDocument = 0; + m_dwEncryptObjNum = 0; + m_dwPrevXRefOffset = 0; + m_dwLastXRefOffset = 0; + m_bDocAvail = FALSE; + m_bMainXRefLoadTried = FALSE; + m_bDocAvail = FALSE; + m_bLinearized = FALSE; + m_bPagesLoad = FALSE; + m_bPagesTreeLoad = FALSE; + m_bMainXRefLoadedOK = FALSE; + m_bAnnotsLoad = FALSE; + m_bHaveAcroForm = FALSE; + m_bAcroFormLoad = FALSE; + m_bPageLoadedOK = FALSE; + m_bNeedDownLoadResource = FALSE; + m_bLinearizedFormParamLoad = FALSE; + m_pLinearized = NULL; + m_pRoot = NULL; + m_pTrailer = NULL; + m_pCurrentParser = NULL; + m_pAcroForm = NULL; + m_pPageDict = NULL; + m_pPageResource = NULL; + m_pageMapCheckState = NULL; + m_docStatus = PDF_DATAAVAIL_HEADER; + m_parser.m_bOwnFileRead = FALSE; + m_bTotalLoadPageTree = FALSE; + m_bCurPageDictLoadOK = FALSE; + m_bLinearedDataOK = FALSE; + m_pagesLoadState = NULL; } -CPDF_DataAvail::~CPDF_DataAvail() -{ - if (m_pLinearized) { - m_pLinearized->Release(); - } - if (m_pRoot) { - m_pRoot->Release(); - } - if (m_pTrailer) { - m_pTrailer->Release(); - } - delete m_pageMapCheckState; - delete m_pagesLoadState; - int32_t i = 0; - int32_t iSize = m_arrayAcroforms.GetSize(); - for (i = 0; i < iSize; ++i) { - ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release(); - } +CPDF_DataAvail::~CPDF_DataAvail() { + if (m_pLinearized) { + m_pLinearized->Release(); + } + if (m_pRoot) { + m_pRoot->Release(); + } + if (m_pTrailer) { + m_pTrailer->Release(); + } + delete m_pageMapCheckState; + delete m_pagesLoadState; + int32_t i = 0; + int32_t iSize = m_arrayAcroforms.GetSize(); + for (i = 0; i < iSize; ++i) { + ((CPDF_Object*)m_arrayAcroforms.GetAt(i))->Release(); + } } -void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc) -{ - m_pDocument = pDoc; +void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc) { + m_pDocument = pDoc; } -FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset) -{ - CPDF_Parser *pParser = (CPDF_Parser *)(m_pDocument->GetParser()); - if (pParser == NULL) { - return 0; - } - if (objnum >= (FX_DWORD)pParser->m_CrossRef.GetSize()) { - return 0; - } - if (pParser->m_V5Type[objnum] == 2) { - objnum = (FX_DWORD)pParser->m_CrossRef[objnum]; +FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset) { + CPDF_Parser* pParser = (CPDF_Parser*)(m_pDocument->GetParser()); + if (pParser == NULL) { + return 0; + } + if (objnum >= (FX_DWORD)pParser->m_CrossRef.GetSize()) { + return 0; + } + if (pParser->m_V5Type[objnum] == 2) { + objnum = (FX_DWORD)pParser->m_CrossRef[objnum]; + } + if (pParser->m_V5Type[objnum] == 1 || pParser->m_V5Type[objnum] == 255) { + offset = pParser->m_CrossRef[objnum]; + if (offset == 0) { + return 0; + } + void* pResult = FXSYS_bsearch(&offset, pParser->m_SortedOffset.GetData(), + pParser->m_SortedOffset.GetSize(), + sizeof(FX_FILESIZE), _CompareFileSize); + if (pResult == NULL) { + return 0; } - if (pParser->m_V5Type[objnum] == 1 || pParser->m_V5Type[objnum] == 255) { - offset = pParser->m_CrossRef[objnum]; - if (offset == 0) { - return 0; - } - void* pResult = FXSYS_bsearch(&offset, pParser->m_SortedOffset.GetData(), pParser->m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - if (pResult == NULL) { - return 0; - } - if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)pParser->m_SortedOffset.GetData() == pParser->m_SortedOffset.GetSize() - 1) { - return 0; - } - return (FX_DWORD)(((FX_FILESIZE*)pResult)[1] - offset); + if ((FX_FILESIZE*)pResult - + (FX_FILESIZE*)pParser->m_SortedOffset.GetData() == + pParser->m_SortedOffset.GetSize() - 1) { + return 0; } - return 0; + return (FX_DWORD)(((FX_FILESIZE*)pResult)[1] - offset); + } + return 0; } -FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array, FX_BOOL bParsePage, IFX_DownloadHints* pHints, CFX_PtrArray &ret_array) -{ - if (!obj_array.GetSize()) { - return TRUE; - } - FX_DWORD count = 0; - CFX_PtrArray new_obj_array; - int32_t i = 0; - for (i = 0; i < obj_array.GetSize(); i++) { - CPDF_Object *pObj = (CPDF_Object *)obj_array[i]; - if (!pObj) { - continue; +FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array, + FX_BOOL bParsePage, + IFX_DownloadHints* pHints, + CFX_PtrArray& ret_array) { + if (!obj_array.GetSize()) { + return TRUE; + } + FX_DWORD count = 0; + CFX_PtrArray new_obj_array; + int32_t i = 0; + for (i = 0; i < obj_array.GetSize(); i++) { + CPDF_Object* pObj = (CPDF_Object*)obj_array[i]; + if (!pObj) { + continue; + } + int32_t type = pObj->GetType(); + switch (type) { + case PDFOBJ_ARRAY: { + CPDF_Array* pArray = pObj->GetArray(); + for (FX_DWORD k = 0; k < pArray->GetCount(); k++) { + new_obj_array.Add(pArray->GetElement(k)); + } + } break; + case PDFOBJ_STREAM: + pObj = pObj->GetDict(); + case PDFOBJ_DICTIONARY: { + CPDF_Dictionary* pDict = pObj->GetDict(); + if (pDict && pDict->GetString("Type") == "Page" && !bParsePage) { + continue; + } + FX_POSITION pos = pDict->GetStartPos(); + while (pos) { + CPDF_Object* value; + CFX_ByteString key; + value = pDict->GetNextElement(pos, key); + if (key != "Parent") { + new_obj_array.Add(value); + } + } + } break; + case PDFOBJ_REFERENCE: { + CPDF_Reference* pRef = (CPDF_Reference*)pObj; + FX_DWORD dwNum = pRef->GetRefObjNum(); + FX_FILESIZE offset; + FX_DWORD original_size = GetObjectSize(dwNum, offset); + pdfium::base::CheckedNumeric size = original_size; + if (size.ValueOrDefault(0) == 0 || offset < 0 || + offset >= m_dwFileLen) { + break; } - int32_t type = pObj->GetType(); - switch (type) { - case PDFOBJ_ARRAY: { - CPDF_Array *pArray = pObj->GetArray(); - for (FX_DWORD k = 0; k < pArray->GetCount(); k++) { - new_obj_array.Add(pArray->GetElement(k)); - } - } - break; - case PDFOBJ_STREAM: - pObj = pObj->GetDict(); - case PDFOBJ_DICTIONARY: { - CPDF_Dictionary *pDict = pObj->GetDict(); - if (pDict && pDict->GetString("Type") == "Page" && !bParsePage) { - continue; - } - FX_POSITION pos = pDict->GetStartPos(); - while (pos) { - CPDF_Object *value; - CFX_ByteString key; - value = pDict->GetNextElement(pos, key); - if (key != "Parent") { - new_obj_array.Add(value); - } - } - } - break; - case PDFOBJ_REFERENCE: { - CPDF_Reference *pRef = (CPDF_Reference*)pObj; - FX_DWORD dwNum = pRef->GetRefObjNum(); - FX_FILESIZE offset; - FX_DWORD original_size = GetObjectSize(dwNum, offset); - pdfium::base::CheckedNumeric 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()) { - break; - } - if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) { - pHints->AddSegment(offset, size.ValueOrDie()); - ret_array.Add(pObj); - count++; - } else if (!m_objnum_array.Find(dwNum)) { - m_objnum_array.AddObjNum(dwNum); - CPDF_Object *pReferred = m_pDocument->GetIndirectObject(pRef->GetRefObjNum(), NULL); - if (pReferred) { - new_obj_array.Add(pReferred); - } - } - } - 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()) { + break; + } + if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) { + pHints->AddSegment(offset, size.ValueOrDie()); + ret_array.Add(pObj); + count++; + } else if (!m_objnum_array.Find(dwNum)) { + m_objnum_array.AddObjNum(dwNum); + CPDF_Object* pReferred = + m_pDocument->GetIndirectObject(pRef->GetRefObjNum(), NULL); + if (pReferred) { + new_obj_array.Add(pReferred); + } + } + } break; + } + } + if (count > 0) { + int32_t iSize = new_obj_array.GetSize(); + for (i = 0; i < iSize; ++i) { + CPDF_Object* pObj = (CPDF_Object*)new_obj_array[i]; + int32_t type = pObj->GetType(); + if (type == PDFOBJ_REFERENCE) { + CPDF_Reference* pRef = (CPDF_Reference*)pObj; + FX_DWORD dwNum = pRef->GetRefObjNum(); + if (!m_objnum_array.Find(dwNum)) { + ret_array.Add(pObj); + } + } else { + ret_array.Add(pObj); + } } - if (count > 0) { - int32_t iSize = new_obj_array.GetSize(); - for (i = 0; i < iSize; ++i) { - CPDF_Object *pObj = (CPDF_Object *)new_obj_array[i]; - int32_t type = pObj->GetType(); - if (type == PDFOBJ_REFERENCE) { - CPDF_Reference *pRef = (CPDF_Reference *)pObj; - FX_DWORD dwNum = pRef->GetRefObjNum(); - if (!m_objnum_array.Find(dwNum)) { - ret_array.Add(pObj); - } - } else { - ret_array.Add(pObj); - } - } - return FALSE; - } - obj_array.RemoveAll(); - obj_array.Append(new_obj_array); - return IsObjectsAvail(obj_array, FALSE, pHints, ret_array); + return FALSE; + } + obj_array.RemoveAll(); + obj_array.Append(new_obj_array); + return IsObjectsAvail(obj_array, FALSE, pHints, ret_array); } -FX_BOOL CPDF_DataAvail::IsDocAvail(IFX_DownloadHints* pHints) -{ - if (!m_dwFileLen && m_pFileRead) { - m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize(); - if (!m_dwFileLen) { - return TRUE; - } - } - while (!m_bDocAvail) { - if (!CheckDocStatus(pHints)) { - return FALSE; - } - } - return TRUE; +FX_BOOL CPDF_DataAvail::IsDocAvail(IFX_DownloadHints* pHints) { + if (!m_dwFileLen && m_pFileRead) { + m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize(); + if (!m_dwFileLen) { + return TRUE; + } + } + while (!m_bDocAvail) { + if (!CheckDocStatus(pHints)) { + return FALSE; + } + } + return TRUE; } -FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints) -{ - if (!m_objs_array.GetSize()) { - m_objs_array.RemoveAll(); - m_objnum_array.RemoveAll(); - CFX_PtrArray obj_array; - obj_array.Append(m_arrayAcroforms); - FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array); - if (bRet) { - m_objs_array.RemoveAll(); - } - return bRet; - } - CFX_PtrArray new_objs_array; - FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); +FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints) { + if (!m_objs_array.GetSize()) { + m_objs_array.RemoveAll(); + m_objnum_array.RemoveAll(); + CFX_PtrArray obj_array; + obj_array.Append(m_arrayAcroforms); + FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array); if (bRet) { - int32_t iSize = m_arrayAcroforms.GetSize(); - for (int32_t i = 0; i < iSize; ++i) { - ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release(); - } - m_arrayAcroforms.RemoveAll(); - } else { - m_objs_array.RemoveAll(); - m_objs_array.Append(new_objs_array); + m_objs_array.RemoveAll(); } return bRet; -} -FX_BOOL CPDF_DataAvail::CheckAcroForm(IFX_DownloadHints* pHints) -{ - FX_BOOL bExist = FALSE; - m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist); - if (!bExist) { - m_docStatus = PDF_DATAAVAIL_PAGETREE; - return TRUE; - } - if (!m_pAcroForm) { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return TRUE; - } - return FALSE; + } + CFX_PtrArray new_objs_array; + FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); + if (bRet) { + int32_t iSize = m_arrayAcroforms.GetSize(); + for (int32_t i = 0; i < iSize; ++i) { + ((CPDF_Object*)m_arrayAcroforms.GetAt(i))->Release(); } - m_arrayAcroforms.Add(m_pAcroForm); + m_arrayAcroforms.RemoveAll(); + } else { + m_objs_array.RemoveAll(); + m_objs_array.Append(new_objs_array); + } + return bRet; +} +FX_BOOL CPDF_DataAvail::CheckAcroForm(IFX_DownloadHints* pHints) { + FX_BOOL bExist = FALSE; + m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist); + if (!bExist) { m_docStatus = PDF_DATAAVAIL_PAGETREE; return TRUE; -} -FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints *pHints) -{ - switch (m_docStatus) { - case PDF_DATAAVAIL_HEADER: - return CheckHeader(pHints); - case PDF_DATAAVAIL_FIRSTPAGE: - case PDF_DATAAVAIL_FIRSTPAGE_PREPARE: - return CheckFirstPage(pHints); - case PDF_DATAAVAIL_END: - return CheckEnd(pHints); - case PDF_DATAAVAIL_CROSSREF: - return CheckCrossRef(pHints); - case PDF_DATAAVAIL_CROSSREF_ITEM: - return CheckCrossRefItem(pHints); - case PDF_DATAAVAIL_CROSSREF_STREAM: - return CheckAllCrossRefStream(pHints); - case PDF_DATAAVAIL_TRAILER: - return CheckTrailer(pHints); - case PDF_DATAAVAIL_TRAILER_APPEND: - return CheckTrailerAppend(pHints); - case PDF_DATAAVAIL_LOADALLCRSOSSREF: - return LoadAllXref(pHints); - case PDF_DATAAVAIL_LOADALLFILE: - return LoadAllFile(pHints); - case PDF_DATAAVAIL_ROOT: - return CheckRoot(pHints); - case PDF_DATAAVAIL_INFO: - return CheckInfo(pHints); - case PDF_DATAAVAIL_ACROFORM: - return CheckAcroForm(pHints); - case PDF_DATAAVAIL_PAGETREE: - if (m_bTotalLoadPageTree) { - return CheckPages(pHints); - } - return LoadDocPages(pHints); - case PDF_DATAAVAIL_PAGE: - if (m_bTotalLoadPageTree) { - return CheckPage(pHints); - } - m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD; - return TRUE; - case PDF_DATAAVAIL_ERROR: - return LoadAllFile(pHints); - case PDF_DATAAVAIL_PAGE_LATERLOAD: - m_docStatus = PDF_DATAAVAIL_PAGE; - default: - m_bDocAvail = TRUE; - return TRUE; + } + if (!m_pAcroForm) { + if (m_docStatus == PDF_DATAAVAIL_ERROR) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return TRUE; } + return FALSE; + } + m_arrayAcroforms.Add(m_pAcroForm); + m_docStatus = PDF_DATAAVAIL_PAGETREE; + return TRUE; } -FX_BOOL CPDF_DataAvail::CheckPageStatus(IFX_DownloadHints* pHints) -{ - switch (m_docStatus) { - case PDF_DATAAVAIL_PAGETREE: - return CheckPages(pHints); - case PDF_DATAAVAIL_PAGE: - return CheckPage(pHints); - case PDF_DATAAVAIL_ERROR: - return LoadAllFile(pHints); - default: - m_bPagesTreeLoad = TRUE; - m_bPagesLoad = TRUE; - return TRUE; - } +FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints* pHints) { + switch (m_docStatus) { + case PDF_DATAAVAIL_HEADER: + return CheckHeader(pHints); + case PDF_DATAAVAIL_FIRSTPAGE: + case PDF_DATAAVAIL_FIRSTPAGE_PREPARE: + return CheckFirstPage(pHints); + case PDF_DATAAVAIL_END: + return CheckEnd(pHints); + case PDF_DATAAVAIL_CROSSREF: + return CheckCrossRef(pHints); + case PDF_DATAAVAIL_CROSSREF_ITEM: + return CheckCrossRefItem(pHints); + case PDF_DATAAVAIL_CROSSREF_STREAM: + return CheckAllCrossRefStream(pHints); + case PDF_DATAAVAIL_TRAILER: + return CheckTrailer(pHints); + case PDF_DATAAVAIL_TRAILER_APPEND: + return CheckTrailerAppend(pHints); + case PDF_DATAAVAIL_LOADALLCRSOSSREF: + return LoadAllXref(pHints); + case PDF_DATAAVAIL_LOADALLFILE: + return LoadAllFile(pHints); + case PDF_DATAAVAIL_ROOT: + return CheckRoot(pHints); + case PDF_DATAAVAIL_INFO: + return CheckInfo(pHints); + case PDF_DATAAVAIL_ACROFORM: + return CheckAcroForm(pHints); + case PDF_DATAAVAIL_PAGETREE: + if (m_bTotalLoadPageTree) { + return CheckPages(pHints); + } + return LoadDocPages(pHints); + case PDF_DATAAVAIL_PAGE: + if (m_bTotalLoadPageTree) { + return CheckPage(pHints); + } + m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD; + return TRUE; + case PDF_DATAAVAIL_ERROR: + return LoadAllFile(pHints); + case PDF_DATAAVAIL_PAGE_LATERLOAD: + m_docStatus = PDF_DATAAVAIL_PAGE; + default: + m_bDocAvail = TRUE; + return TRUE; + } } -FX_BOOL CPDF_DataAvail::LoadAllFile(IFX_DownloadHints* pHints) -{ - if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) { - m_docStatus = PDF_DATAAVAIL_DONE; - return TRUE; - } - pHints->AddSegment(0, (FX_DWORD)m_dwFileLen); - return FALSE; +FX_BOOL CPDF_DataAvail::CheckPageStatus(IFX_DownloadHints* pHints) { + switch (m_docStatus) { + case PDF_DATAAVAIL_PAGETREE: + return CheckPages(pHints); + case PDF_DATAAVAIL_PAGE: + return CheckPage(pHints); + case PDF_DATAAVAIL_ERROR: + return LoadAllFile(pHints); + default: + m_bPagesTreeLoad = TRUE; + m_bPagesLoad = TRUE; + return TRUE; + } } -FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints) -{ - m_parser.m_Syntax.InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset); - m_parser.m_bOwnFileRead = FALSE; - if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return FALSE; - } - FXSYS_qsort(m_parser.m_SortedOffset.GetData(), m_parser.m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize); - m_dwRootObjNum = m_parser.GetRootObjNum(); - m_dwInfoObjNum = m_parser.GetInfoObjNum(); - m_pCurrentParser = &m_parser; - m_docStatus = PDF_DATAAVAIL_ROOT; +FX_BOOL CPDF_DataAvail::LoadAllFile(IFX_DownloadHints* pHints) { + if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) { + m_docStatus = PDF_DATAAVAIL_DONE; return TRUE; + } + pHints->AddSegment(0, (FX_DWORD)m_dwFileLen); + return FALSE; } -CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum, IFX_DownloadHints* pHints, FX_BOOL *pExistInFile) -{ - CPDF_Object *pRet = NULL; - FX_DWORD original_size = 0; - FX_FILESIZE offset = 0; - CPDF_Parser *pParser = NULL; +FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints) { + m_parser.m_Syntax.InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset); + m_parser.m_bOwnFileRead = FALSE; + if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && + !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return FALSE; + } + FXSYS_qsort(m_parser.m_SortedOffset.GetData(), + m_parser.m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), + _CompareFileSize); + m_dwRootObjNum = m_parser.GetRootObjNum(); + m_dwInfoObjNum = m_parser.GetInfoObjNum(); + m_pCurrentParser = &m_parser; + m_docStatus = PDF_DATAAVAIL_ROOT; + return TRUE; +} +CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum, + IFX_DownloadHints* pHints, + FX_BOOL* pExistInFile) { + CPDF_Object* pRet = NULL; + FX_DWORD original_size = 0; + FX_FILESIZE offset = 0; + CPDF_Parser* pParser = NULL; - if (pExistInFile) { - *pExistInFile = TRUE; - } + if (pExistInFile) { + *pExistInFile = TRUE; + } - if (m_pDocument == NULL) { - original_size = (FX_DWORD)m_parser.GetObjectSize(objnum); - offset = m_parser.GetObjectOffset(objnum); - pParser = &m_parser; - } else { - original_size = GetObjectSize(objnum, offset); - pParser = (CPDF_Parser *)(m_pDocument->GetParser()); - } - - pdfium::base::CheckedNumeric size = original_size; - if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) { - if (pExistInFile) - *pExistInFile = FALSE; + if (m_pDocument == NULL) { + original_size = (FX_DWORD)m_parser.GetObjectSize(objnum); + offset = m_parser.GetObjectOffset(objnum); + pParser = &m_parser; + } else { + original_size = GetObjectSize(objnum, offset); + pParser = (CPDF_Parser*)(m_pDocument->GetParser()); + } - return NULL; - } + pdfium::base::CheckedNumeric size = original_size; + if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) { + if (pExistInFile) + *pExistInFile = FALSE; - size += offset; - size += 512; - if (!size.IsValid()) { - return NULL; - } + return NULL; + } - if (size.ValueOrDie() > m_dwFileLen) { - size = m_dwFileLen - offset; - } else { - size = original_size + 512; - } + size += offset; + size += 512; + if (!size.IsValid()) { + return NULL; + } - if (!size.IsValid()) { - return NULL; - } + if (size.ValueOrDie() > m_dwFileLen) { + size = m_dwFileLen - offset; + } else { + size = original_size + 512; + } - if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) { - pHints->AddSegment(offset, size.ValueOrDie()); - return NULL; - } + if (!size.IsValid()) { + return NULL; + } - if (pParser) { - pRet = pParser->ParseIndirectObject(NULL, objnum, NULL); - } + if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) { + pHints->AddSegment(offset, size.ValueOrDie()); + return NULL; + } - if (!pRet && pExistInFile) { - *pExistInFile = FALSE; - } + if (pParser) { + pRet = pParser->ParseIndirectObject(NULL, objnum, NULL); + } - return pRet; -} + if (!pRet && pExistInFile) { + *pExistInFile = FALSE; + } -FX_BOOL CPDF_DataAvail::CheckInfo(IFX_DownloadHints* pHints) -{ - FX_BOOL bExist = FALSE; - CPDF_Object *pInfo = GetObject(m_dwInfoObjNum, pHints, &bExist); - if (!bExist) { - if (m_bHaveAcroForm) { - m_docStatus = PDF_DATAAVAIL_ACROFORM; - } else { - m_docStatus = PDF_DATAAVAIL_PAGETREE; - } - return TRUE; - } - if (!pInfo) { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return TRUE; - } - if (m_Pos == m_dwFileLen) { - m_docStatus = PDF_DATAAVAIL_ERROR; - } - return FALSE; - } - if (pInfo) { - pInfo->Release(); - } - if (m_bHaveAcroForm) { - m_docStatus = PDF_DATAAVAIL_ACROFORM; - } else { - m_docStatus = PDF_DATAAVAIL_PAGETREE; - } - return TRUE; -} -FX_BOOL CPDF_DataAvail::CheckRoot(IFX_DownloadHints* pHints) -{ - FX_BOOL bExist = FALSE; - m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist); - if (!bExist) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return TRUE; - } - if (!m_pRoot) { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return TRUE; - } - return FALSE; - } - CPDF_Dictionary* pDict = m_pRoot->GetDict(); - if (!pDict) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - CPDF_Reference* pRef = (CPDF_Reference*)pDict->GetElement(FX_BSTRC("Pages")); - if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - m_PagesObjNum = pRef->GetRefObjNum(); - CPDF_Reference* pAcroFormRef = (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("AcroForm")); - if (pAcroFormRef && pAcroFormRef->GetType() == PDFOBJ_REFERENCE) { - m_bHaveAcroForm = TRUE; - m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum(); - } - if (m_dwInfoObjNum) { - m_docStatus = PDF_DATAAVAIL_INFO; - } else { - if (m_bHaveAcroForm) { - m_docStatus = PDF_DATAAVAIL_ACROFORM; - } else { - m_docStatus = PDF_DATAAVAIL_PAGETREE; - } - } - return TRUE; -} -FX_BOOL CPDF_DataAvail::PreparePageItem() -{ - CPDF_Dictionary *pRoot = m_pDocument->GetRoot(); - CPDF_Reference* pRef = pRoot ? (CPDF_Reference*)pRoot->GetElement(FX_BSTRC("Pages")) : NULL; - if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - m_PagesObjNum = pRef->GetRefObjNum(); - m_pCurrentParser = (CPDF_Parser *)m_pDocument->GetParser(); - m_docStatus = PDF_DATAAVAIL_PAGETREE; - return TRUE; -} -FX_BOOL CPDF_DataAvail::IsFirstCheck(int iPage) -{ - if (NULL == m_pageMapCheckState) { - m_pageMapCheckState = new CFX_CMapDWordToDWord(); - } - FX_DWORD dwValue = 0; - if (!m_pageMapCheckState->Lookup(iPage, dwValue)) { - m_pageMapCheckState->SetAt(iPage, 1); - return TRUE; - } - if (dwValue != 0) { - return FALSE; - } - m_pageMapCheckState->SetAt(iPage, 1); - return TRUE; -} -void CPDF_DataAvail::ResetFirstCheck(int iPage) -{ - if (NULL == m_pageMapCheckState) { - m_pageMapCheckState = new CFX_CMapDWordToDWord(); - } - FX_DWORD dwValue = 1; - if (!m_pageMapCheckState->Lookup(iPage, dwValue)) { - return; - } - m_pageMapCheckState->SetAt(iPage, 0); -} -FX_BOOL CPDF_DataAvail::CheckPage(IFX_DownloadHints* pHints) -{ - FX_DWORD iPageObjs = m_PageObjList.GetSize(); - CFX_DWordArray UnavailObjList; - for (FX_DWORD i = 0; i < iPageObjs; ++i) { - FX_DWORD dwPageObjNum = m_PageObjList.GetAt(i); - FX_BOOL bExist = FALSE; - CPDF_Object *pObj = GetObject(dwPageObjNum, pHints, &bExist); - if (!pObj) { - if (bExist) { - UnavailObjList.Add(dwPageObjNum); - } - continue; - } - if (pObj->GetType() == PDFOBJ_ARRAY) { - CPDF_Array *pArray = pObj->GetArray(); - if (pArray) { - int32_t iSize = pArray->GetCount(); - CPDF_Object *pItem = NULL; - for (int32_t j = 0; j < iSize; ++j) { - pItem = pArray->GetElement(j); - if (pItem && pItem->GetType() == PDFOBJ_REFERENCE) { - UnavailObjList.Add(((CPDF_Reference *)pItem)->GetRefObjNum()); - } - } - } - } - if (pObj->GetType() != PDFOBJ_DICTIONARY) { - pObj->Release(); - continue; - } - CFX_ByteString type = pObj->GetDict()->GetString(FX_BSTRC("Type")); - if (type == FX_BSTRC("Pages")) { - m_PagesArray.Add(pObj); - continue; - } - pObj->Release(); - } - m_PageObjList.RemoveAll(); - if (UnavailObjList.GetSize()) { - m_PageObjList.Append(UnavailObjList); - return FALSE; - } - FX_DWORD iPages = m_PagesArray.GetSize(); - for (FX_DWORD i = 0; i < iPages; i++) { - CPDF_Object *pPages = (CPDF_Object *)m_PagesArray.GetAt(i); - if (!pPages) { - continue; - } - if (!GetPageKids(m_pCurrentParser, pPages)) { - pPages->Release(); - while (++i < iPages) { - pPages = (CPDF_Object *)m_PagesArray.GetAt(i); - pPages->Release(); - } - m_PagesArray.RemoveAll(); - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - pPages->Release(); - } - m_PagesArray.RemoveAll(); - if (!m_PageObjList.GetSize()) { - m_docStatus = PDF_DATAAVAIL_DONE; + return pRet; +} + +FX_BOOL CPDF_DataAvail::CheckInfo(IFX_DownloadHints* pHints) { + FX_BOOL bExist = FALSE; + CPDF_Object* pInfo = GetObject(m_dwInfoObjNum, pHints, &bExist); + if (!bExist) { + if (m_bHaveAcroForm) { + m_docStatus = PDF_DATAAVAIL_ACROFORM; + } else { + m_docStatus = PDF_DATAAVAIL_PAGETREE; } return TRUE; -} -FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser *pParser, CPDF_Object *pPages) -{ - if (!pParser) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; + } + if (!pInfo) { + if (m_docStatus == PDF_DATAAVAIL_ERROR) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return TRUE; } - CPDF_Dictionary* pDict = pPages->GetDict(); - CPDF_Object *pKids = pDict ? pDict->GetElement(FX_BSTRC("Kids")) : NULL; - if (!pKids) { - return TRUE; + if (m_Pos == m_dwFileLen) { + m_docStatus = PDF_DATAAVAIL_ERROR; } - switch (pKids->GetType()) { - case PDFOBJ_REFERENCE: { - CPDF_Reference *pKid = (CPDF_Reference *)pKids; - m_PageObjList.Add(pKid->GetRefObjNum()); - } - break; - case PDFOBJ_ARRAY: { - CPDF_Array *pKidsArray = (CPDF_Array *)pKids; - for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) { - CPDF_Object *pKid = (CPDF_Object *)pKidsArray->GetElement(i); - if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) { - m_PageObjList.Add(((CPDF_Reference *)pKid)->GetRefObjNum()); - } - } - } - break; - default: - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; + return FALSE; + } + if (pInfo) { + pInfo->Release(); + } + if (m_bHaveAcroForm) { + m_docStatus = PDF_DATAAVAIL_ACROFORM; + } else { + m_docStatus = PDF_DATAAVAIL_PAGETREE; + } + return TRUE; +} +FX_BOOL CPDF_DataAvail::CheckRoot(IFX_DownloadHints* pHints) { + FX_BOOL bExist = FALSE; + m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist); + if (!bExist) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return TRUE; + } + if (!m_pRoot) { + if (m_docStatus == PDF_DATAAVAIL_ERROR) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return TRUE; + } + return FALSE; + } + CPDF_Dictionary* pDict = m_pRoot->GetDict(); + if (!pDict) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + CPDF_Reference* pRef = (CPDF_Reference*)pDict->GetElement(FX_BSTRC("Pages")); + if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + m_PagesObjNum = pRef->GetRefObjNum(); + CPDF_Reference* pAcroFormRef = + (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("AcroForm")); + if (pAcroFormRef && pAcroFormRef->GetType() == PDFOBJ_REFERENCE) { + m_bHaveAcroForm = TRUE; + m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum(); + } + if (m_dwInfoObjNum) { + m_docStatus = PDF_DATAAVAIL_INFO; + } else { + if (m_bHaveAcroForm) { + m_docStatus = PDF_DATAAVAIL_ACROFORM; + } else { + m_docStatus = PDF_DATAAVAIL_PAGETREE; } + } + return TRUE; +} +FX_BOOL CPDF_DataAvail::PreparePageItem() { + CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); + CPDF_Reference* pRef = + pRoot ? (CPDF_Reference*)pRoot->GetElement(FX_BSTRC("Pages")) : NULL; + if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + m_PagesObjNum = pRef->GetRefObjNum(); + m_pCurrentParser = (CPDF_Parser*)m_pDocument->GetParser(); + m_docStatus = PDF_DATAAVAIL_PAGETREE; + return TRUE; +} +FX_BOOL CPDF_DataAvail::IsFirstCheck(int iPage) { + if (NULL == m_pageMapCheckState) { + m_pageMapCheckState = new CFX_CMapDWordToDWord(); + } + FX_DWORD dwValue = 0; + if (!m_pageMapCheckState->Lookup(iPage, dwValue)) { + m_pageMapCheckState->SetAt(iPage, 1); return TRUE; + } + if (dwValue != 0) { + return FALSE; + } + m_pageMapCheckState->SetAt(iPage, 1); + return TRUE; } -FX_BOOL CPDF_DataAvail::CheckPages(IFX_DownloadHints* pHints) -{ +void CPDF_DataAvail::ResetFirstCheck(int iPage) { + if (NULL == m_pageMapCheckState) { + m_pageMapCheckState = new CFX_CMapDWordToDWord(); + } + FX_DWORD dwValue = 1; + if (!m_pageMapCheckState->Lookup(iPage, dwValue)) { + return; + } + m_pageMapCheckState->SetAt(iPage, 0); +} +FX_BOOL CPDF_DataAvail::CheckPage(IFX_DownloadHints* pHints) { + FX_DWORD iPageObjs = m_PageObjList.GetSize(); + CFX_DWordArray UnavailObjList; + for (FX_DWORD i = 0; i < iPageObjs; ++i) { + FX_DWORD dwPageObjNum = m_PageObjList.GetAt(i); FX_BOOL bExist = FALSE; - CPDF_Object *pPages = GetObject(m_PagesObjNum, pHints, &bExist); - if (!bExist) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return TRUE; - } + CPDF_Object* pObj = GetObject(dwPageObjNum, pHints, &bExist); + if (!pObj) { + if (bExist) { + UnavailObjList.Add(dwPageObjNum); + } + continue; + } + if (pObj->GetType() == PDFOBJ_ARRAY) { + CPDF_Array* pArray = pObj->GetArray(); + if (pArray) { + int32_t iSize = pArray->GetCount(); + CPDF_Object* pItem = NULL; + for (int32_t j = 0; j < iSize; ++j) { + pItem = pArray->GetElement(j); + if (pItem && pItem->GetType() == PDFOBJ_REFERENCE) { + UnavailObjList.Add(((CPDF_Reference*)pItem)->GetRefObjNum()); + } + } + } + } + if (pObj->GetType() != PDFOBJ_DICTIONARY) { + pObj->Release(); + continue; + } + CFX_ByteString type = pObj->GetDict()->GetString(FX_BSTRC("Type")); + if (type == FX_BSTRC("Pages")) { + m_PagesArray.Add(pObj); + continue; + } + pObj->Release(); + } + m_PageObjList.RemoveAll(); + if (UnavailObjList.GetSize()) { + m_PageObjList.Append(UnavailObjList); + return FALSE; + } + FX_DWORD iPages = m_PagesArray.GetSize(); + for (FX_DWORD i = 0; i < iPages; i++) { + CPDF_Object* pPages = (CPDF_Object*)m_PagesArray.GetAt(i); if (!pPages) { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return TRUE; - } - return FALSE; + continue; } if (!GetPageKids(m_pCurrentParser, pPages)) { + pPages->Release(); + while (++i < iPages) { + pPages = (CPDF_Object*)m_PagesArray.GetAt(i); pPages->Release(); - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; + } + m_PagesArray.RemoveAll(); + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; } pPages->Release(); - m_docStatus = PDF_DATAAVAIL_PAGE; - return TRUE; + } + m_PagesArray.RemoveAll(); + if (!m_PageObjList.GetSize()) { + m_docStatus = PDF_DATAAVAIL_DONE; + } + return TRUE; } -FX_BOOL CPDF_DataAvail::CheckHeader(IFX_DownloadHints* pHints) -{ - FX_DWORD req_size = 1024; - if ((FX_FILESIZE)req_size > m_dwFileLen) { - req_size = (FX_DWORD)m_dwFileLen; - } - if (m_pFileAvail->IsDataAvail(0, req_size)) { - uint8_t buffer[1024]; - m_pFileRead->ReadBlock(buffer, 0, req_size); - if (IsLinearizedFile(buffer, req_size)) { - m_docStatus = PDF_DATAAVAIL_FIRSTPAGE; - } else { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - return FALSE; - } - m_docStatus = PDF_DATAAVAIL_END; - } - return TRUE; - } - pHints->AddSegment(0, req_size); +FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages) { + if (!pParser) { + m_docStatus = PDF_DATAAVAIL_ERROR; return FALSE; + } + CPDF_Dictionary* pDict = pPages->GetDict(); + CPDF_Object* pKids = pDict ? pDict->GetElement(FX_BSTRC("Kids")) : NULL; + if (!pKids) { + return TRUE; + } + switch (pKids->GetType()) { + case PDFOBJ_REFERENCE: { + CPDF_Reference* pKid = (CPDF_Reference*)pKids; + m_PageObjList.Add(pKid->GetRefObjNum()); + } break; + case PDFOBJ_ARRAY: { + CPDF_Array* pKidsArray = (CPDF_Array*)pKids; + for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) { + CPDF_Object* pKid = (CPDF_Object*)pKidsArray->GetElement(i); + if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) { + m_PageObjList.Add(((CPDF_Reference*)pKid)->GetRefObjNum()); + } + } + } break; + default: + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + return TRUE; } -FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints *pHints) -{ - CPDF_Dictionary* pDict = m_pLinearized->GetDict(); - CPDF_Object *pEndOffSet = pDict ? pDict->GetElement(FX_BSTRC("E")) : NULL; - if (!pEndOffSet) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - CPDF_Object *pXRefOffset = pDict ? pDict->GetElement(FX_BSTRC("T")) : NULL; - if (!pXRefOffset) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - CPDF_Object *pFileLen = pDict ? pDict->GetElement(FX_BSTRC("L")) : NULL; - if (!pFileLen) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - FX_BOOL bNeedDownLoad = FALSE; - if (pEndOffSet->GetType() == PDFOBJ_NUMBER) { - FX_DWORD dwEnd = pEndOffSet->GetInteger(); - dwEnd += 512; - if ((FX_FILESIZE)dwEnd > m_dwFileLen) { - dwEnd = (FX_DWORD)m_dwFileLen; - } - int32_t iStartPos = (int32_t)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen); - int32_t iSize = dwEnd > 1024 ? dwEnd - 1024 : 0; - if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) { - pHints->AddSegment(iStartPos, iSize); - bNeedDownLoad = TRUE; - } - } - m_dwLastXRefOffset = 0; - FX_FILESIZE dwFileLen = 0; - if (pXRefOffset->GetType() == PDFOBJ_NUMBER) { - m_dwLastXRefOffset = pXRefOffset->GetInteger(); - } - if (pFileLen->GetType() == PDFOBJ_NUMBER) { - dwFileLen = pFileLen->GetInteger(); - } - if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, (FX_DWORD)(dwFileLen - m_dwLastXRefOffset))) { - if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE) { - FX_DWORD dwSize = (FX_DWORD)(dwFileLen - m_dwLastXRefOffset); - FX_FILESIZE offset = m_dwLastXRefOffset; - if (dwSize < 512 && dwFileLen > 512) { - dwSize = 512; - offset = dwFileLen - 512; - } - pHints->AddSegment(offset, dwSize); - } - } else { - m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE; - } - if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) { - m_docStatus = PDF_DATAAVAIL_DONE; - return TRUE; +FX_BOOL CPDF_DataAvail::CheckPages(IFX_DownloadHints* pHints) { + FX_BOOL bExist = FALSE; + CPDF_Object* pPages = GetObject(m_PagesObjNum, pHints, &bExist); + if (!bExist) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return TRUE; + } + if (!pPages) { + if (m_docStatus == PDF_DATAAVAIL_ERROR) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + return TRUE; } - m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE; return FALSE; + } + if (!GetPageKids(m_pCurrentParser, pPages)) { + pPages->Release(); + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + pPages->Release(); + m_docStatus = PDF_DATAAVAIL_PAGE; + return TRUE; } -CPDF_Object * CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD objnum) -{ - FX_FILESIZE SavedPos = m_syntaxParser.SavePos(); - m_syntaxParser.RestorePos(pos); - FX_BOOL bIsNumber; - CFX_ByteString word = m_syntaxParser.GetNextWord(bIsNumber); - if (!bIsNumber) { - return NULL; - } - FX_DWORD parser_objnum = FXSYS_atoi(word); - if (objnum && parser_objnum != objnum) { - return NULL; - } - word = m_syntaxParser.GetNextWord(bIsNumber); - if (!bIsNumber) { - return NULL; - } - FX_DWORD gennum = FXSYS_atoi(word); - if (m_syntaxParser.GetKeyword() != FX_BSTRC("obj")) { - m_syntaxParser.RestorePos(SavedPos); - return NULL; - } - CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0); - m_syntaxParser.RestorePos(SavedPos); - return pObj; -} -int32_t CPDF_DataAvail::IsLinearizedPDF() -{ - FX_DWORD req_size = 1024; - if (!m_pFileAvail->IsDataAvail(0, req_size)) { - return PDF_UNKNOW_LINEARIZED; - } - if (!m_pFileRead) { - return PDF_NOT_LINEARIZED; - } - FX_FILESIZE dwSize = m_pFileRead->GetSize(); - if (dwSize < (FX_FILESIZE)req_size) { - return PDF_UNKNOW_LINEARIZED; - } +FX_BOOL CPDF_DataAvail::CheckHeader(IFX_DownloadHints* pHints) { + FX_DWORD req_size = 1024; + if ((FX_FILESIZE)req_size > m_dwFileLen) { + req_size = (FX_DWORD)m_dwFileLen; + } + if (m_pFileAvail->IsDataAvail(0, req_size)) { uint8_t buffer[1024]; m_pFileRead->ReadBlock(buffer, 0, req_size); if (IsLinearizedFile(buffer, req_size)) { - return PDF_IS_LINEARIZED; - } - return PDF_NOT_LINEARIZED; -} -FX_BOOL CPDF_DataAvail::IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen) -{ - CFX_SmartPointer file(FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE)); - int32_t offset = GetHeaderOffset(file.Get()); - if (offset == -1) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - m_dwHeaderOffset = offset; - m_syntaxParser.InitParser(file.Get(), offset); - m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9); - FX_BOOL bNumber = FALSE; - CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(bNumber); - if (!bNumber) { - return FALSE; - } - FX_DWORD objnum = FXSYS_atoi(wordObjNum); - if (m_pLinearized) { - m_pLinearized->Release(); - m_pLinearized = NULL; - } - m_pLinearized = ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum); - if (!m_pLinearized) { + m_docStatus = PDF_DATAAVAIL_FIRSTPAGE; + } else { + if (m_docStatus == PDF_DATAAVAIL_ERROR) { return FALSE; + } + m_docStatus = PDF_DATAAVAIL_END; } - if (m_pLinearized->GetDict() && m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) { - CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L")); - if (!pLen) { - return FALSE; - } - if ((FX_FILESIZE)pLen->GetInteger() != m_pFileRead->GetSize()) { - return FALSE; - } - m_bLinearized = TRUE; - CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P")); - if (pNo && pNo->GetType() == PDFOBJ_NUMBER) { - m_dwFirstPageNo = pNo->GetInteger(); - } - return TRUE; - } - return FALSE; + return TRUE; + } + pHints->AddSegment(0, req_size); + return FALSE; } -FX_BOOL CPDF_DataAvail::CheckEnd(IFX_DownloadHints* pHints) -{ - FX_DWORD req_pos = (FX_DWORD)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0); - FX_DWORD dwSize = (FX_DWORD)(m_dwFileLen - req_pos); - if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) { - uint8_t buffer[1024]; - m_pFileRead->ReadBlock(buffer, req_pos, dwSize); - CFX_SmartPointer file(FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE)); - m_syntaxParser.InitParser(file.Get(), 0); - m_syntaxParser.RestorePos(dwSize - 1); - if (m_syntaxParser.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, dwSize)) { - FX_BOOL bNumber; - m_syntaxParser.GetNextWord(bNumber); - CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(bNumber); - if (!bNumber) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str); - if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return TRUE; - } - m_dwLastXRefOffset = m_dwXRefOffset; - SetStartOffset(m_dwXRefOffset); - m_docStatus = PDF_DATAAVAIL_CROSSREF; - return TRUE; - } - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return TRUE; - } - pHints->AddSegment(req_pos, dwSize); +FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints* pHints) { + CPDF_Dictionary* pDict = m_pLinearized->GetDict(); + CPDF_Object* pEndOffSet = pDict ? pDict->GetElement(FX_BSTRC("E")) : NULL; + if (!pEndOffSet) { + m_docStatus = PDF_DATAAVAIL_ERROR; return FALSE; + } + CPDF_Object* pXRefOffset = pDict ? pDict->GetElement(FX_BSTRC("T")) : NULL; + if (!pXRefOffset) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + CPDF_Object* pFileLen = pDict ? pDict->GetElement(FX_BSTRC("L")) : NULL; + if (!pFileLen) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + FX_BOOL bNeedDownLoad = FALSE; + if (pEndOffSet->GetType() == PDFOBJ_NUMBER) { + FX_DWORD dwEnd = pEndOffSet->GetInteger(); + dwEnd += 512; + if ((FX_FILESIZE)dwEnd > m_dwFileLen) { + dwEnd = (FX_DWORD)m_dwFileLen; + } + int32_t iStartPos = (int32_t)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen); + int32_t iSize = dwEnd > 1024 ? dwEnd - 1024 : 0; + if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) { + pHints->AddSegment(iStartPos, iSize); + bNeedDownLoad = TRUE; + } + } + m_dwLastXRefOffset = 0; + FX_FILESIZE dwFileLen = 0; + if (pXRefOffset->GetType() == PDFOBJ_NUMBER) { + m_dwLastXRefOffset = pXRefOffset->GetInteger(); + } + if (pFileLen->GetType() == PDFOBJ_NUMBER) { + dwFileLen = pFileLen->GetInteger(); + } + if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, + (FX_DWORD)(dwFileLen - m_dwLastXRefOffset))) { + if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE) { + FX_DWORD dwSize = (FX_DWORD)(dwFileLen - m_dwLastXRefOffset); + FX_FILESIZE offset = m_dwLastXRefOffset; + if (dwSize < 512 && dwFileLen > 512) { + dwSize = 512; + offset = dwFileLen - 512; + } + pHints->AddSegment(offset, dwSize); + } + } else { + m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE; + } + if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) { + m_docStatus = PDF_DATAAVAIL_DONE; + return TRUE; + } + m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE; + return FALSE; } -int32_t CPDF_DataAvail::CheckCrossRefStream(IFX_DownloadHints* pHints, FX_FILESIZE &xref_offset) -{ - xref_offset = 0; - FX_DWORD req_size = (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) { - int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam); - CFX_BinaryBuf buf(iSize); - uint8_t* pBuf = buf.GetBuffer(); - m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize); - CFX_SmartPointer file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE)); - m_parser.m_Syntax.InitParser(file.Get(), 0); - FX_BOOL bNumber = FALSE; - CFX_ByteString objnum = m_parser.m_Syntax.GetNextWord(bNumber); - if (!bNumber) { - return -1; - } - FX_DWORD objNum = FXSYS_atoi(objnum); - CPDF_Object *pObj = m_parser.ParseIndirectObjectAt(NULL, 0, objNum, NULL); - if (!pObj) { - m_Pos += m_parser.m_Syntax.SavePos(); - return 0; - } - CPDF_Dictionary* pDict = pObj->GetDict(); - CPDF_Object *pName = pDict ? pDict->GetElement(FX_BSTRC("Type")) : NULL; - if (pName && pName->GetType() == PDFOBJ_NAME) { - if (pName->GetString() == FX_BSTRC("XRef")) { - m_Pos += m_parser.m_Syntax.SavePos(); - xref_offset = pObj->GetDict()->GetInteger(FX_BSTRC("Prev")); - pObj->Release(); - return 1; - } - } - pObj->Release(); - return -1; - } - pHints->AddSegment(m_Pos, req_size); - return 0; +CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos, + FX_DWORD objnum) { + FX_FILESIZE SavedPos = m_syntaxParser.SavePos(); + m_syntaxParser.RestorePos(pos); + FX_BOOL bIsNumber; + CFX_ByteString word = m_syntaxParser.GetNextWord(bIsNumber); + if (!bIsNumber) { + return NULL; + } + FX_DWORD parser_objnum = FXSYS_atoi(word); + if (objnum && parser_objnum != objnum) { + return NULL; + } + word = m_syntaxParser.GetNextWord(bIsNumber); + if (!bIsNumber) { + return NULL; + } + FX_DWORD gennum = FXSYS_atoi(word); + if (m_syntaxParser.GetKeyword() != FX_BSTRC("obj")) { + m_syntaxParser.RestorePos(SavedPos); + return NULL; + } + CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0); + m_syntaxParser.RestorePos(SavedPos); + return pObj; } -inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset) -{ - m_Pos = dwOffset; +int32_t CPDF_DataAvail::IsLinearizedPDF() { + FX_DWORD req_size = 1024; + if (!m_pFileAvail->IsDataAvail(0, req_size)) { + return PDF_UNKNOW_LINEARIZED; + } + if (!m_pFileRead) { + return PDF_NOT_LINEARIZED; + } + FX_FILESIZE dwSize = m_pFileRead->GetSize(); + if (dwSize < (FX_FILESIZE)req_size) { + return PDF_UNKNOW_LINEARIZED; + } + uint8_t buffer[1024]; + m_pFileRead->ReadBlock(buffer, 0, req_size); + if (IsLinearizedFile(buffer, req_size)) { + return PDF_IS_LINEARIZED; + } + return PDF_NOT_LINEARIZED; } -#define MAX_WORD_BUFFER 256 -FX_BOOL CPDF_DataAvail::GetNextToken(CFX_ByteString &token) -{ - m_WordSize = 0; - uint8_t ch; - if (!GetNextChar(ch)) { - return FALSE; - } - uint8_t type = PDF_CharType[ch]; - while (1) { - while (type == 'W') { - if (!GetNextChar(ch)) { - return FALSE; - } - type = PDF_CharType[ch]; - } - if (ch != '%') { - break; - } - while (1) { - if (!GetNextChar(ch)) { - return FALSE; - } - if (ch == '\r' || ch == '\n') { - break; - } - } - type = PDF_CharType[ch]; - } - if (type == 'D') { - m_WordBuffer[m_WordSize++] = ch; - if (ch == '/') { - while (1) { - if (!GetNextChar(ch)) { - return FALSE; - } - type = PDF_CharType[ch]; - if (type != 'R' && type != 'N') { - m_Pos --; - CFX_ByteString ret(m_WordBuffer, m_WordSize); - token = ret; - return TRUE; - } - if (m_WordSize < MAX_WORD_BUFFER) { - m_WordBuffer[m_WordSize++] = ch; - } - } - } else if (ch == '<') { - if (!GetNextChar(ch)) { - return FALSE; - } - if (ch == '<') { - m_WordBuffer[m_WordSize++] = ch; - } else { - m_Pos --; - } - } else if (ch == '>') { - if (!GetNextChar(ch)) { - return FALSE; - } - if (ch == '>') { - m_WordBuffer[m_WordSize++] = ch; - } else { - m_Pos --; - } - } - CFX_ByteString ret(m_WordBuffer, m_WordSize); - token = ret; - return TRUE; - } - while (1) { - if (m_WordSize < MAX_WORD_BUFFER) { - m_WordBuffer[m_WordSize++] = ch; - } - if (!GetNextChar(ch)) { - return FALSE; - } - type = PDF_CharType[ch]; - if (type == 'D' || type == 'W') { - m_Pos --; - break; - } +FX_BOOL CPDF_DataAvail::IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen) { + CFX_SmartPointer file( + FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE)); + int32_t offset = GetHeaderOffset(file.Get()); + if (offset == -1) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + m_dwHeaderOffset = offset; + m_syntaxParser.InitParser(file.Get(), offset); + m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9); + FX_BOOL bNumber = FALSE; + CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(bNumber); + if (!bNumber) { + return FALSE; + } + FX_DWORD objnum = FXSYS_atoi(wordObjNum); + if (m_pLinearized) { + m_pLinearized->Release(); + m_pLinearized = NULL; + } + m_pLinearized = + ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum); + if (!m_pLinearized) { + return FALSE; + } + if (m_pLinearized->GetDict() && + m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) { + CPDF_Object* pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L")); + if (!pLen) { + return FALSE; } - CFX_ByteString ret(m_WordBuffer, m_WordSize); - token = ret; - return TRUE; -} -FX_BOOL CPDF_DataAvail::GetNextChar(uint8_t &ch) -{ - FX_FILESIZE pos = m_Pos; - if (pos >= m_dwFileLen) { - return FALSE; + if ((FX_FILESIZE)pLen->GetInteger() != m_pFileRead->GetSize()) { + return FALSE; } - if (m_bufferOffset >= pos || (FX_FILESIZE)(m_bufferOffset + m_bufferSize) <= pos) { - FX_FILESIZE read_pos = pos; - FX_DWORD read_size = 512; - if ((FX_FILESIZE)read_size > m_dwFileLen) { - read_size = (FX_DWORD)m_dwFileLen; - } - if ((FX_FILESIZE)(read_pos + read_size) > m_dwFileLen) { - read_pos = m_dwFileLen - read_size; - } - if (!m_pFileRead->ReadBlock(m_bufferData, read_pos, read_size)) { - return FALSE; - } - m_bufferOffset = read_pos; - m_bufferSize = read_size; + m_bLinearized = TRUE; + CPDF_Object* pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P")); + if (pNo && pNo->GetType() == PDFOBJ_NUMBER) { + m_dwFirstPageNo = pNo->GetInteger(); } - ch = m_bufferData[pos - m_bufferOffset]; - m_Pos ++; return TRUE; + } + return FALSE; } -FX_BOOL CPDF_DataAvail::CheckCrossRefItem(IFX_DownloadHints *pHints) -{ - int32_t iSize = 0; - CFX_ByteString token; - while (1) { - if (!GetNextToken(token)) { - iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - pHints->AddSegment(m_Pos, iSize); - return FALSE; - } - if (token == "trailer") { - m_dwTrailerOffset = m_Pos; - m_docStatus = PDF_DATAAVAIL_TRAILER; - return TRUE; - } - } -} -FX_BOOL CPDF_DataAvail::CheckAllCrossRefStream(IFX_DownloadHints *pHints) -{ - FX_FILESIZE xref_offset = 0; - int32_t nRet = CheckCrossRefStream(pHints, xref_offset); - if (nRet == 1) { - if (!xref_offset) { - m_docStatus = PDF_DATAAVAIL_LOADALLCRSOSSREF; - } else { - m_dwCurrentXRefSteam = xref_offset; - m_Pos = xref_offset; - } - return TRUE; - } - if (nRet == -1) { +FX_BOOL CPDF_DataAvail::CheckEnd(IFX_DownloadHints* pHints) { + FX_DWORD req_pos = (FX_DWORD)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0); + FX_DWORD dwSize = (FX_DWORD)(m_dwFileLen - req_pos); + if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) { + uint8_t buffer[1024]; + m_pFileRead->ReadBlock(buffer, req_pos, dwSize); + CFX_SmartPointer file( + FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE)); + m_syntaxParser.InitParser(file.Get(), 0); + m_syntaxParser.RestorePos(dwSize - 1); + if (m_syntaxParser.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, dwSize)) { + FX_BOOL bNumber; + m_syntaxParser.GetNextWord(bNumber); + CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(bNumber); + if (!bNumber) { m_docStatus = PDF_DATAAVAIL_ERROR; - } - return FALSE; -} -FX_BOOL CPDF_DataAvail::CheckCrossRef(IFX_DownloadHints* pHints) -{ - int32_t iSize = 0; - CFX_ByteString token; - if (!GetNextToken(token)) { - iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - pHints->AddSegment(m_Pos, iSize); return FALSE; - } - if (token == "xref") { - m_CrossOffset.InsertAt(0, m_dwXRefOffset); - while (1) { - if (!GetNextToken(token)) { - iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - pHints->AddSegment(m_Pos, iSize); - m_docStatus = PDF_DATAAVAIL_CROSSREF_ITEM; - return FALSE; - } - if (token == "trailer") { - m_dwTrailerOffset = m_Pos; - m_docStatus = PDF_DATAAVAIL_TRAILER; - return TRUE; - } - } - } else { + } + m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str); + if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) { m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return TRUE; + } + m_dwLastXRefOffset = m_dwXRefOffset; + SetStartOffset(m_dwXRefOffset); + m_docStatus = PDF_DATAAVAIL_CROSSREF; + return TRUE; } - return FALSE; -} -FX_BOOL CPDF_DataAvail::CheckTrailerAppend(IFX_DownloadHints* pHints) -{ - if (m_Pos < m_dwFileLen) { - FX_FILESIZE dwAppendPos = m_Pos + m_syntaxParser.SavePos(); - int32_t iSize = (int32_t)(dwAppendPos + 512 > m_dwFileLen ? m_dwFileLen - dwAppendPos : 512); - if (!m_pFileAvail->IsDataAvail(dwAppendPos, iSize)) { - pHints->AddSegment(dwAppendPos, iSize); - return FALSE; - } - } - if (m_dwPrevXRefOffset) { - SetStartOffset(m_dwPrevXRefOffset); - m_docStatus = PDF_DATAAVAIL_CROSSREF; - } else { - m_docStatus = PDF_DATAAVAIL_LOADALLCRSOSSREF; - } + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return TRUE; + } + pHints->AddSegment(req_pos, dwSize); + return FALSE; } -FX_BOOL CPDF_DataAvail::CheckTrailer(IFX_DownloadHints* pHints) -{ - int32_t iTrailerSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) { - int32_t iSize = (int32_t)(m_Pos + iTrailerSize - m_dwTrailerOffset); - CFX_BinaryBuf buf(iSize); - uint8_t* pBuf = buf.GetBuffer(); - if (!pBuf) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) { - return FALSE; - } - CFX_SmartPointer file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE)); - m_syntaxParser.InitParser(file.Get(), 0); - CPDF_Object *pTrailer = m_syntaxParser.GetObject(NULL, 0, 0, 0); - if (!pTrailer) { - m_Pos += m_syntaxParser.SavePos(); - pHints->AddSegment(m_Pos, iTrailerSize); - return FALSE; - } - if (pTrailer->GetType() != PDFOBJ_DICTIONARY) { - return FALSE; - } - CPDF_Dictionary *pTrailerDict = pTrailer->GetDict(); - if (pTrailerDict) { - CPDF_Object *pEncrypt = pTrailerDict->GetElement("Encrypt"); - if (pEncrypt && pEncrypt->GetType() == PDFOBJ_REFERENCE) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - pTrailer->Release(); - return TRUE; - } - } - FX_DWORD xrefpos = GetDirectInteger(pTrailer->GetDict(), FX_BSTRC("Prev")); - if (xrefpos) { - m_dwPrevXRefOffset = GetDirectInteger(pTrailer->GetDict(), FX_BSTRC("XRefStm")); - pTrailer->Release(); - if (m_dwPrevXRefOffset) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - } else { - m_dwPrevXRefOffset = xrefpos; - if (m_dwPrevXRefOffset >= m_dwFileLen) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - } else { - SetStartOffset(m_dwPrevXRefOffset); - m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; - } - } - return TRUE; - } - m_dwPrevXRefOffset = 0; - m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; - pTrailer->Release(); - return TRUE; +int32_t CPDF_DataAvail::CheckCrossRefStream(IFX_DownloadHints* pHints, + FX_FILESIZE& xref_offset) { + xref_offset = 0; + FX_DWORD req_size = + (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); + if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) { + int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam); + CFX_BinaryBuf buf(iSize); + uint8_t* pBuf = buf.GetBuffer(); + m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize); + CFX_SmartPointer file( + FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE)); + m_parser.m_Syntax.InitParser(file.Get(), 0); + FX_BOOL bNumber = FALSE; + CFX_ByteString objnum = m_parser.m_Syntax.GetNextWord(bNumber); + if (!bNumber) { + return -1; } - pHints->AddSegment(m_Pos, iTrailerSize); - return FALSE; -} -FX_BOOL CPDF_DataAvail::CheckPage(int32_t iPage, IFX_DownloadHints* pHints) -{ - while (TRUE) { - switch (m_docStatus) { - case PDF_DATAAVAIL_PAGETREE: - if (!LoadDocPages(pHints)) { - return FALSE; - } - break; - case PDF_DATAAVAIL_PAGE: - if (!LoadDocPage(iPage, pHints)) { - return FALSE; - } - break; - case PDF_DATAAVAIL_ERROR: - return LoadAllFile(pHints); - default: - m_bPagesTreeLoad = TRUE; - m_bPagesLoad = TRUE; - m_bCurPageDictLoadOK = TRUE; - m_docStatus = PDF_DATAAVAIL_PAGE; - return TRUE; - } + FX_DWORD objNum = FXSYS_atoi(objnum); + CPDF_Object* pObj = m_parser.ParseIndirectObjectAt(NULL, 0, objNum, NULL); + if (!pObj) { + m_Pos += m_parser.m_Syntax.SavePos(); + return 0; + } + CPDF_Dictionary* pDict = pObj->GetDict(); + CPDF_Object* pName = pDict ? pDict->GetElement(FX_BSTRC("Type")) : NULL; + if (pName && pName->GetType() == PDFOBJ_NAME) { + if (pName->GetString() == FX_BSTRC("XRef")) { + m_Pos += m_parser.m_Syntax.SavePos(); + xref_offset = pObj->GetDict()->GetInteger(FX_BSTRC("Prev")); + pObj->Release(); + return 1; + } } + pObj->Release(); + return -1; + } + pHints->AddSegment(m_Pos, req_size); + return 0; } -FX_BOOL CPDF_DataAvail::CheckArrayPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints) -{ - FX_BOOL bExist = FALSE; - CPDF_Object *pPages = GetObject(dwPageNo, pHints, &bExist); - if (!bExist) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - if (!pPages) { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } +inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset) { + m_Pos = dwOffset; +} +#define MAX_WORD_BUFFER 256 +FX_BOOL CPDF_DataAvail::GetNextToken(CFX_ByteString& token) { + m_WordSize = 0; + uint8_t ch; + if (!GetNextChar(ch)) { + return FALSE; + } + uint8_t type = PDF_CharType[ch]; + while (1) { + while (type == 'W') { + if (!GetNextChar(ch)) { return FALSE; + } + type = PDF_CharType[ch]; } - if (pPages->GetType() != PDFOBJ_ARRAY) { - pPages->Release(); - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; + if (ch != '%') { + break; } - pPageNode->m_type = PDF_PAGENODE_PAGES; - CPDF_Array* pArray = (CPDF_Array*)pPages; - for (FX_DWORD i = 0; i < pArray->GetCount(); ++i) { - CPDF_Object *pKid = (CPDF_Object *)pArray->GetElement(i); - if (!pKid || pKid->GetType() != PDFOBJ_REFERENCE) { - continue; + while (1) { + if (!GetNextChar(ch)) { + return FALSE; + } + if (ch == '\r' || ch == '\n') { + break; + } + } + type = PDF_CharType[ch]; + } + if (type == 'D') { + m_WordBuffer[m_WordSize++] = ch; + if (ch == '/') { + while (1) { + if (!GetNextChar(ch)) { + return FALSE; } - CPDF_PageNode *pNode = new CPDF_PageNode(); - pPageNode->m_childNode.Add(pNode); - pNode->m_dwPageNo = ((CPDF_Reference*)pKid)->GetRefObjNum(); + type = PDF_CharType[ch]; + if (type != 'R' && type != 'N') { + m_Pos--; + CFX_ByteString ret(m_WordBuffer, m_WordSize); + token = ret; + return TRUE; + } + if (m_WordSize < MAX_WORD_BUFFER) { + m_WordBuffer[m_WordSize++] = ch; + } + } + } else if (ch == '<') { + if (!GetNextChar(ch)) { + return FALSE; + } + if (ch == '<') { + m_WordBuffer[m_WordSize++] = ch; + } else { + m_Pos--; + } + } else if (ch == '>') { + if (!GetNextChar(ch)) { + return FALSE; + } + if (ch == '>') { + m_WordBuffer[m_WordSize++] = ch; + } else { + m_Pos--; + } } - pPages->Release(); + CFX_ByteString ret(m_WordBuffer, m_WordSize); + token = ret; return TRUE; -} -FX_BOOL CPDF_DataAvail::CheckUnkownPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints) -{ - FX_BOOL bExist = FALSE; - CPDF_Object *pPage = GetObject(dwPageNo, pHints, &bExist); - if (!bExist) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; + } + while (1) { + if (m_WordSize < MAX_WORD_BUFFER) { + m_WordBuffer[m_WordSize++] = ch; } - if (!pPage) { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - return FALSE; + if (!GetNextChar(ch)) { + return FALSE; } - if (pPage->GetType() == PDFOBJ_ARRAY) { - pPageNode->m_dwPageNo = dwPageNo; - pPageNode->m_type = PDF_PAGENODE_ARRAY; - pPage->Release(); - return TRUE; + type = PDF_CharType[ch]; + if (type == 'D' || type == 'W') { + m_Pos--; + break; } - if (pPage->GetType() != PDFOBJ_DICTIONARY) { - pPage->Release(); - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; + } + CFX_ByteString ret(m_WordBuffer, m_WordSize); + token = ret; + return TRUE; +} +FX_BOOL CPDF_DataAvail::GetNextChar(uint8_t& ch) { + FX_FILESIZE pos = m_Pos; + if (pos >= m_dwFileLen) { + return FALSE; + } + if (m_bufferOffset >= pos || + (FX_FILESIZE)(m_bufferOffset + m_bufferSize) <= pos) { + FX_FILESIZE read_pos = pos; + FX_DWORD read_size = 512; + if ((FX_FILESIZE)read_size > m_dwFileLen) { + read_size = (FX_DWORD)m_dwFileLen; + } + if ((FX_FILESIZE)(read_pos + read_size) > m_dwFileLen) { + read_pos = m_dwFileLen - read_size; + } + if (!m_pFileRead->ReadBlock(m_bufferData, read_pos, read_size)) { + return FALSE; + } + m_bufferOffset = read_pos; + m_bufferSize = read_size; + } + ch = m_bufferData[pos - m_bufferOffset]; + m_Pos++; + return TRUE; +} +FX_BOOL CPDF_DataAvail::CheckCrossRefItem(IFX_DownloadHints* pHints) { + int32_t iSize = 0; + CFX_ByteString token; + while (1) { + if (!GetNextToken(token)) { + iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); + pHints->AddSegment(m_Pos, iSize); + return FALSE; } - pPageNode->m_dwPageNo = dwPageNo; - CPDF_Dictionary* pDict = pPage->GetDict(); - CFX_ByteString type = pDict ? pDict->GetString(FX_BSTRC("Type")) : CFX_ByteString(); - if (type == FX_BSTRC("Pages")) { - pPageNode->m_type = PDF_PAGENODE_PAGES; - CPDF_Object *pKids = pDict->GetElement(FX_BSTRC("Kids")); - if (!pKids) { - m_docStatus = PDF_DATAAVAIL_PAGE; - return TRUE; - } - switch (pKids->GetType()) { - case PDFOBJ_REFERENCE: { - CPDF_Reference *pKid = (CPDF_Reference *)pKids; - CPDF_PageNode *pNode = new CPDF_PageNode(); - pPageNode->m_childNode.Add(pNode); - pNode->m_dwPageNo = pKid->GetRefObjNum(); - } - break; - case PDFOBJ_ARRAY: { - CPDF_Array *pKidsArray = (CPDF_Array *)pKids; - for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) { - CPDF_Object *pKid = (CPDF_Object *)pKidsArray->GetElement(i); - if (!pKid || pKid->GetType() != PDFOBJ_REFERENCE) { - continue; - } - CPDF_PageNode *pNode = new CPDF_PageNode(); - pPageNode->m_childNode.Add(pNode); - pNode->m_dwPageNo = ((CPDF_Reference*)pKid)->GetRefObjNum(); - } - } - break; - default: - break; - } - } else if (type == FX_BSTRC("Page")) { - pPageNode->m_type = PDF_PAGENODE_PAGE; + if (token == "trailer") { + m_dwTrailerOffset = m_Pos; + m_docStatus = PDF_DATAAVAIL_TRAILER; + return TRUE; + } + } +} +FX_BOOL CPDF_DataAvail::CheckAllCrossRefStream(IFX_DownloadHints* pHints) { + FX_FILESIZE xref_offset = 0; + int32_t nRet = CheckCrossRefStream(pHints, xref_offset); + if (nRet == 1) { + if (!xref_offset) { + m_docStatus = PDF_DATAAVAIL_LOADALLCRSOSSREF; } else { - pPage->Release(); - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; + m_dwCurrentXRefSteam = xref_offset; + m_Pos = xref_offset; } - pPage->Release(); return TRUE; + } + if (nRet == -1) { + m_docStatus = PDF_DATAAVAIL_ERROR; + } + return FALSE; } -FX_BOOL CPDF_DataAvail::CheckPageNode(CPDF_PageNode &pageNodes, int32_t iPage, int32_t &iCount, IFX_DownloadHints* pHints) -{ - int32_t iSize = pageNodes.m_childNode.GetSize(); - if (iSize <= 0 || iPage >= iSize) { - m_docStatus = PDF_DATAAVAIL_ERROR; +FX_BOOL CPDF_DataAvail::CheckCrossRef(IFX_DownloadHints* pHints) { + int32_t iSize = 0; + CFX_ByteString token; + if (!GetNextToken(token)) { + iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); + pHints->AddSegment(m_Pos, iSize); + return FALSE; + } + if (token == "xref") { + m_CrossOffset.InsertAt(0, m_dwXRefOffset); + while (1) { + if (!GetNextToken(token)) { + iSize = + (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); + pHints->AddSegment(m_Pos, iSize); + m_docStatus = PDF_DATAAVAIL_CROSSREF_ITEM; return FALSE; + } + if (token == "trailer") { + m_dwTrailerOffset = m_Pos; + m_docStatus = PDF_DATAAVAIL_TRAILER; + return TRUE; + } } - for (int32_t i = 0; i < iSize; ++i) { - CPDF_PageNode *pNode = (CPDF_PageNode*)pageNodes.m_childNode.GetAt(i); - if (!pNode) { - continue; - } - switch (pNode->m_type) { - case PDF_PAGENODE_UNKOWN: - if (!CheckUnkownPageNode(pNode->m_dwPageNo, pNode, pHints)) { - return FALSE; - } - --i; - break; - case PDF_PAGENODE_PAGE: - iCount++; - if (iPage == iCount && m_pDocument) { - m_pDocument->m_PageList.SetAt(iPage, pNode->m_dwPageNo); - } - break; - case PDF_PAGENODE_PAGES: - if (!CheckPageNode(*pNode, iPage, iCount, pHints)) { - return FALSE; - } - break; - case PDF_PAGENODE_ARRAY: - if (!CheckArrayPageNode(pNode->m_dwPageNo, pNode, pHints)) { - return FALSE; - } - --i; - break; - } - if (iPage == iCount) { - m_docStatus = PDF_DATAAVAIL_DONE; - return TRUE; - } - } + } else { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return TRUE; + } + return FALSE; +} +FX_BOOL CPDF_DataAvail::CheckTrailerAppend(IFX_DownloadHints* pHints) { + if (m_Pos < m_dwFileLen) { + FX_FILESIZE dwAppendPos = m_Pos + m_syntaxParser.SavePos(); + int32_t iSize = (int32_t)( + dwAppendPos + 512 > m_dwFileLen ? m_dwFileLen - dwAppendPos : 512); + if (!m_pFileAvail->IsDataAvail(dwAppendPos, iSize)) { + pHints->AddSegment(dwAppendPos, iSize); + return FALSE; + } + } + if (m_dwPrevXRefOffset) { + SetStartOffset(m_dwPrevXRefOffset); + m_docStatus = PDF_DATAAVAIL_CROSSREF; + } else { + m_docStatus = PDF_DATAAVAIL_LOADALLCRSOSSREF; + } + return TRUE; } -FX_BOOL CPDF_DataAvail::LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints) -{ - if (m_pDocument->GetPageCount() <= iPage || m_pDocument->m_PageList.GetAt(iPage)) { - m_docStatus = PDF_DATAAVAIL_DONE; +FX_BOOL CPDF_DataAvail::CheckTrailer(IFX_DownloadHints* pHints) { + int32_t iTrailerSize = + (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); + if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) { + int32_t iSize = (int32_t)(m_Pos + iTrailerSize - m_dwTrailerOffset); + CFX_BinaryBuf buf(iSize); + uint8_t* pBuf = buf.GetBuffer(); + if (!pBuf) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) { + return FALSE; + } + CFX_SmartPointer file( + FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE)); + m_syntaxParser.InitParser(file.Get(), 0); + CPDF_Object* pTrailer = m_syntaxParser.GetObject(NULL, 0, 0, 0); + if (!pTrailer) { + m_Pos += m_syntaxParser.SavePos(); + pHints->AddSegment(m_Pos, iTrailerSize); + return FALSE; + } + if (pTrailer->GetType() != PDFOBJ_DICTIONARY) { + return FALSE; + } + CPDF_Dictionary* pTrailerDict = pTrailer->GetDict(); + if (pTrailerDict) { + CPDF_Object* pEncrypt = pTrailerDict->GetElement("Encrypt"); + if (pEncrypt && pEncrypt->GetType() == PDFOBJ_REFERENCE) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + pTrailer->Release(); return TRUE; - } - if (m_pageNodes.m_type == PDF_PAGENODE_PAGE) { - if (iPage == 0) { - m_docStatus = PDF_DATAAVAIL_DONE; - return TRUE; + } + } + FX_DWORD xrefpos = GetDirectInteger(pTrailer->GetDict(), FX_BSTRC("Prev")); + if (xrefpos) { + m_dwPrevXRefOffset = + GetDirectInteger(pTrailer->GetDict(), FX_BSTRC("XRefStm")); + pTrailer->Release(); + if (m_dwPrevXRefOffset) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + } else { + m_dwPrevXRefOffset = xrefpos; + if (m_dwPrevXRefOffset >= m_dwFileLen) { + m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + } else { + SetStartOffset(m_dwPrevXRefOffset); + m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; } - m_docStatus = PDF_DATAAVAIL_ERROR; - return TRUE; + } + return TRUE; } - int32_t iCount = -1; - return CheckPageNode(m_pageNodes, iPage, iCount, pHints); + m_dwPrevXRefOffset = 0; + m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; + pTrailer->Release(); + return TRUE; + } + pHints->AddSegment(m_Pos, iTrailerSize); + return FALSE; } -FX_BOOL CPDF_DataAvail::CheckPageCount(IFX_DownloadHints* pHints) -{ - FX_BOOL bExist = FALSE; - CPDF_Object *pPages = GetObject(m_PagesObjNum, pHints, &bExist); - if (!bExist) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - if (!pPages) { - return FALSE; - } - CPDF_Dictionary* pPagesDict = pPages->GetDict(); - if (!pPagesDict) { - pPages->Release(); - m_docStatus = PDF_DATAAVAIL_ERROR; - return FALSE; - } - if (!pPagesDict->KeyExist(FX_BSTRC("Kids"))) { - pPages->Release(); +FX_BOOL CPDF_DataAvail::CheckPage(int32_t iPage, IFX_DownloadHints* pHints) { + while (TRUE) { + switch (m_docStatus) { + case PDF_DATAAVAIL_PAGETREE: + if (!LoadDocPages(pHints)) { + return FALSE; + } + break; + case PDF_DATAAVAIL_PAGE: + if (!LoadDocPage(iPage, pHints)) { + return FALSE; + } + break; + case PDF_DATAAVAIL_ERROR: + return LoadAllFile(pHints); + default: + m_bPagesTreeLoad = TRUE; + m_bPagesLoad = TRUE; + m_bCurPageDictLoadOK = TRUE; + m_docStatus = PDF_DATAAVAIL_PAGE; return TRUE; } - int count = pPagesDict->GetInteger(FX_BSTRC("Count")); - if (count > 0) { - pPages->Release(); - return TRUE; + } +} +FX_BOOL CPDF_DataAvail::CheckArrayPageNode(FX_DWORD dwPageNo, + CPDF_PageNode* pPageNode, + IFX_DownloadHints* pHints) { + FX_BOOL bExist = FALSE; + CPDF_Object* pPages = GetObject(dwPageNo, pHints, &bExist); + if (!bExist) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + if (!pPages) { + if (m_docStatus == PDF_DATAAVAIL_ERROR) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; } + return FALSE; + } + if (pPages->GetType() != PDFOBJ_ARRAY) { pPages->Release(); + m_docStatus = PDF_DATAAVAIL_ERROR; return FALSE; + } + pPageNode->m_type = PDF_PAGENODE_PAGES; + CPDF_Array* pArray = (CPDF_Array*)pPages; + for (FX_DWORD i = 0; i < pArray->GetCount(); ++i) { + CPDF_Object* pKid = (CPDF_Object*)pArray->GetElement(i); + if (!pKid || pKid->GetType() != PDFOBJ_REFERENCE) { + continue; + } + CPDF_PageNode* pNode = new CPDF_PageNode(); + pPageNode->m_childNode.Add(pNode); + pNode->m_dwPageNo = ((CPDF_Reference*)pKid)->GetRefObjNum(); + } + pPages->Release(); + return TRUE; } -FX_BOOL CPDF_DataAvail::LoadDocPages(IFX_DownloadHints* pHints) -{ - if (!CheckUnkownPageNode(m_PagesObjNum, &m_pageNodes, pHints)) { - return FALSE; +FX_BOOL CPDF_DataAvail::CheckUnkownPageNode(FX_DWORD dwPageNo, + CPDF_PageNode* pPageNode, + IFX_DownloadHints* pHints) { + FX_BOOL bExist = FALSE; + CPDF_Object* pPage = GetObject(dwPageNo, pHints, &bExist); + if (!bExist) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + if (!pPage) { + if (m_docStatus == PDF_DATAAVAIL_ERROR) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; } - if (CheckPageCount(pHints)) { - m_docStatus = PDF_DATAAVAIL_PAGE; - return TRUE; + return FALSE; + } + if (pPage->GetType() == PDFOBJ_ARRAY) { + pPageNode->m_dwPageNo = dwPageNo; + pPageNode->m_type = PDF_PAGENODE_ARRAY; + pPage->Release(); + return TRUE; + } + if (pPage->GetType() != PDFOBJ_DICTIONARY) { + pPage->Release(); + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + pPageNode->m_dwPageNo = dwPageNo; + CPDF_Dictionary* pDict = pPage->GetDict(); + CFX_ByteString type = + pDict ? pDict->GetString(FX_BSTRC("Type")) : CFX_ByteString(); + if (type == FX_BSTRC("Pages")) { + pPageNode->m_type = PDF_PAGENODE_PAGES; + CPDF_Object* pKids = pDict->GetElement(FX_BSTRC("Kids")); + if (!pKids) { + m_docStatus = PDF_DATAAVAIL_PAGE; + return TRUE; } - m_bTotalLoadPageTree = TRUE; + switch (pKids->GetType()) { + case PDFOBJ_REFERENCE: { + CPDF_Reference* pKid = (CPDF_Reference*)pKids; + CPDF_PageNode* pNode = new CPDF_PageNode(); + pPageNode->m_childNode.Add(pNode); + pNode->m_dwPageNo = pKid->GetRefObjNum(); + } break; + case PDFOBJ_ARRAY: { + CPDF_Array* pKidsArray = (CPDF_Array*)pKids; + for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) { + CPDF_Object* pKid = (CPDF_Object*)pKidsArray->GetElement(i); + if (!pKid || pKid->GetType() != PDFOBJ_REFERENCE) { + continue; + } + CPDF_PageNode* pNode = new CPDF_PageNode(); + pPageNode->m_childNode.Add(pNode); + pNode->m_dwPageNo = ((CPDF_Reference*)pKid)->GetRefObjNum(); + } + } break; + default: + break; + } + } else if (type == FX_BSTRC("Page")) { + pPageNode->m_type = PDF_PAGENODE_PAGE; + } else { + pPage->Release(); + m_docStatus = PDF_DATAAVAIL_ERROR; return FALSE; + } + pPage->Release(); + return TRUE; } -FX_BOOL CPDF_DataAvail::LoadPages(IFX_DownloadHints* pHints) -{ - while (!m_bPagesTreeLoad) { - if (!CheckPageStatus(pHints)) { - return FALSE; - } - } - if (m_bPagesLoad) { - return TRUE; +FX_BOOL CPDF_DataAvail::CheckPageNode(CPDF_PageNode& pageNodes, + int32_t iPage, + int32_t& iCount, + IFX_DownloadHints* pHints) { + int32_t iSize = pageNodes.m_childNode.GetSize(); + if (iSize <= 0 || iPage >= iSize) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + for (int32_t i = 0; i < iSize; ++i) { + CPDF_PageNode* pNode = (CPDF_PageNode*)pageNodes.m_childNode.GetAt(i); + if (!pNode) { + continue; + } + switch (pNode->m_type) { + case PDF_PAGENODE_UNKOWN: + if (!CheckUnkownPageNode(pNode->m_dwPageNo, pNode, pHints)) { + return FALSE; + } + --i; + break; + case PDF_PAGENODE_PAGE: + iCount++; + if (iPage == iCount && m_pDocument) { + m_pDocument->m_PageList.SetAt(iPage, pNode->m_dwPageNo); + } + break; + case PDF_PAGENODE_PAGES: + if (!CheckPageNode(*pNode, iPage, iCount, pHints)) { + return FALSE; + } + break; + case PDF_PAGENODE_ARRAY: + if (!CheckArrayPageNode(pNode->m_dwPageNo, pNode, pHints)) { + return FALSE; + } + --i; + break; + } + if (iPage == iCount) { + m_docStatus = PDF_DATAAVAIL_DONE; + return TRUE; + } + } + return TRUE; +} +FX_BOOL CPDF_DataAvail::LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints) { + if (m_pDocument->GetPageCount() <= iPage || + m_pDocument->m_PageList.GetAt(iPage)) { + m_docStatus = PDF_DATAAVAIL_DONE; + return TRUE; + } + if (m_pageNodes.m_type == PDF_PAGENODE_PAGE) { + if (iPage == 0) { + m_docStatus = PDF_DATAAVAIL_DONE; + return TRUE; } - m_pDocument->LoadPages(); + m_docStatus = PDF_DATAAVAIL_ERROR; + return TRUE; + } + int32_t iCount = -1; + return CheckPageNode(m_pageNodes, iPage, iCount, pHints); +} +FX_BOOL CPDF_DataAvail::CheckPageCount(IFX_DownloadHints* pHints) { + FX_BOOL bExist = FALSE; + CPDF_Object* pPages = GetObject(m_PagesObjNum, pHints, &bExist); + if (!bExist) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + if (!pPages) { return FALSE; + } + CPDF_Dictionary* pPagesDict = pPages->GetDict(); + if (!pPagesDict) { + pPages->Release(); + m_docStatus = PDF_DATAAVAIL_ERROR; + return FALSE; + } + if (!pPagesDict->KeyExist(FX_BSTRC("Kids"))) { + pPages->Release(); + return TRUE; + } + int count = pPagesDict->GetInteger(FX_BSTRC("Count")); + if (count > 0) { + pPages->Release(); + return TRUE; + } + pPages->Release(); + return FALSE; } -FX_BOOL CPDF_DataAvail::CheckLinearizedData(IFX_DownloadHints* pHints) -{ - if (m_bLinearedDataOK) { - return TRUE; +FX_BOOL CPDF_DataAvail::LoadDocPages(IFX_DownloadHints* pHints) { + if (!CheckUnkownPageNode(m_PagesObjNum, &m_pageNodes, pHints)) { + return FALSE; + } + if (CheckPageCount(pHints)) { + m_docStatus = PDF_DATAAVAIL_PAGE; + return TRUE; + } + m_bTotalLoadPageTree = TRUE; + return FALSE; +} +FX_BOOL CPDF_DataAvail::LoadPages(IFX_DownloadHints* pHints) { + while (!m_bPagesTreeLoad) { + if (!CheckPageStatus(pHints)) { + return FALSE; } + } + if (m_bPagesLoad) { + return TRUE; + } + m_pDocument->LoadPages(); + return FALSE; +} +FX_BOOL CPDF_DataAvail::CheckLinearizedData(IFX_DownloadHints* pHints) { + if (m_bLinearedDataOK) { + return TRUE; + } - if (!m_bMainXRefLoadTried) { - FX_SAFE_DWORD data_size = m_dwFileLen; - data_size -= m_dwLastXRefOffset; - if (!data_size.IsValid()) { - return FALSE; - } - if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, data_size.ValueOrDie())) { - pHints->AddSegment(m_dwLastXRefOffset, data_size.ValueOrDie()); - return FALSE; - } - FX_DWORD dwRet = ((CPDF_Parser *)m_pDocument->GetParser())->LoadLinearizedMainXRefTable(); - m_bMainXRefLoadTried = TRUE; - if (dwRet != PDFPARSE_ERROR_SUCCESS) { - return FALSE; - } - if (!PreparePageItem()) { - return FALSE; - } - m_bMainXRefLoadedOK = TRUE; - m_bLinearedDataOK = TRUE; + if (!m_bMainXRefLoadTried) { + FX_SAFE_DWORD data_size = m_dwFileLen; + data_size -= m_dwLastXRefOffset; + if (!data_size.IsValid()) { + return FALSE; + } + if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, + data_size.ValueOrDie())) { + pHints->AddSegment(m_dwLastXRefOffset, data_size.ValueOrDie()); + return FALSE; + } + FX_DWORD dwRet = + ((CPDF_Parser*)m_pDocument->GetParser())->LoadLinearizedMainXRefTable(); + m_bMainXRefLoadTried = TRUE; + if (dwRet != PDFPARSE_ERROR_SUCCESS) { + return FALSE; + } + if (!PreparePageItem()) { + return FALSE; } + m_bMainXRefLoadedOK = TRUE; + m_bLinearedDataOK = TRUE; + } - return m_bLinearedDataOK; + return m_bLinearedDataOK; } -FX_BOOL CPDF_DataAvail::CheckPageAnnots(int32_t iPage, IFX_DownloadHints* pHints) -{ - if (!m_objs_array.GetSize()) { - m_objs_array.RemoveAll(); - m_objnum_array.RemoveAll(); - CPDF_Dictionary *pPageDict = m_pDocument->GetPage(iPage); - if (!pPageDict) { - return TRUE; - } - CPDF_Object *pAnnots = pPageDict->GetElement(FX_BSTRC("Annots")); - if (!pAnnots) { - return TRUE; - } - CFX_PtrArray obj_array; - obj_array.Add(pAnnots); - FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array); - if (bRet) { - m_objs_array.RemoveAll(); - } - return bRet; - } - CFX_PtrArray new_objs_array; - FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); +FX_BOOL CPDF_DataAvail::CheckPageAnnots(int32_t iPage, + IFX_DownloadHints* pHints) { + if (!m_objs_array.GetSize()) { m_objs_array.RemoveAll(); - if (!bRet) { - m_objs_array.Append(new_objs_array); + m_objnum_array.RemoveAll(); + CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iPage); + if (!pPageDict) { + return TRUE; + } + CPDF_Object* pAnnots = pPageDict->GetElement(FX_BSTRC("Annots")); + if (!pAnnots) { + return TRUE; + } + CFX_PtrArray obj_array; + obj_array.Add(pAnnots); + FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array); + if (bRet) { + m_objs_array.RemoveAll(); } return bRet; + } + CFX_PtrArray new_objs_array; + FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); + m_objs_array.RemoveAll(); + if (!bRet) { + m_objs_array.Append(new_objs_array); + } + return bRet; } -FX_BOOL CPDF_DataAvail::CheckLinearizedFirstPage(int32_t iPage, IFX_DownloadHints* pHints) -{ - if (!m_bAnnotsLoad) { - if (!CheckPageAnnots(iPage, pHints)) { - return FALSE; - } - m_bAnnotsLoad = TRUE; - } - if (m_bAnnotsLoad) { - if (!CheckLinearizedData(pHints)) - return FALSE; - } - m_bPageLoadedOK = FALSE; +FX_BOOL CPDF_DataAvail::CheckLinearizedFirstPage(int32_t iPage, + IFX_DownloadHints* pHints) { + if (!m_bAnnotsLoad) { + if (!CheckPageAnnots(iPage, pHints)) { + return FALSE; + } + m_bAnnotsLoad = TRUE; + } + if (m_bAnnotsLoad) { + if (!CheckLinearizedData(pHints)) + return FALSE; + } + m_bPageLoadedOK = FALSE; + return TRUE; +} +FX_BOOL CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary* pDict) { + CFX_AutoRestorer restorer(&s_CurrentDataAvailRecursionDepth); + if (++s_CurrentDataAvailRecursionDepth > kMaxDataAvailRecursionDepth) { + return FALSE; + } + CPDF_Object* pParent = pDict->GetElement("Parent"); + if (!pParent) { + return FALSE; + } + CPDF_Dictionary* pParentDict = pParent->GetDict(); + if (!pParentDict) { + return FALSE; + } + CPDF_Object* pRet = pParentDict->GetElement("Resources"); + if (pRet) { + m_pPageResource = pRet; return TRUE; + } + return HaveResourceAncestor(pParentDict); } -FX_BOOL CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary *pDict) -{ - CFX_AutoRestorer restorer(&s_CurrentDataAvailRecursionDepth); - if (++s_CurrentDataAvailRecursionDepth > kMaxDataAvailRecursionDepth) { - return FALSE; +FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) { + if (!m_pDocument) { + return FALSE; + } + if (IsFirstCheck(iPage)) { + m_bCurPageDictLoadOK = FALSE; + m_bPageLoadedOK = FALSE; + m_bAnnotsLoad = FALSE; + m_bNeedDownLoadResource = FALSE; + m_objs_array.RemoveAll(); + m_objnum_array.RemoveAll(); + } + if (m_pagesLoadState == NULL) { + m_pagesLoadState = new CFX_CMapDWordToDWord(); + } + FX_DWORD dwPageLoad = 0; + if (m_pagesLoadState->Lookup(iPage, dwPageLoad) && dwPageLoad != 0) { + return TRUE; + } + if (m_bLinearized) { + if ((FX_DWORD)iPage == m_dwFirstPageNo) { + m_pagesLoadState->SetAt(iPage, TRUE); + return TRUE; } - CPDF_Object *pParent = pDict->GetElement("Parent"); - if (!pParent) { - return FALSE; + if (!CheckLinearizedData(pHints)) { + return FALSE; } - CPDF_Dictionary *pParentDict = pParent->GetDict(); - if (!pParentDict) { + if (m_bMainXRefLoadedOK) { + if (m_bTotalLoadPageTree) { + if (!LoadPages(pHints)) { + return FALSE; + } + } else { + if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) { + return FALSE; + } + } + } else { + if (!LoadAllFile(pHints)) { return FALSE; - } - CPDF_Object *pRet = pParentDict->GetElement("Resources"); - if (pRet) { - m_pPageResource = pRet; - return TRUE; - } - return HaveResourceAncestor(pParentDict); -} -FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) -{ - if (!m_pDocument) { + } + ((CPDF_Parser*)m_pDocument->GetParser())->RebuildCrossRef(); + ResetFirstCheck(iPage); + return TRUE; + } + } else { + if (!m_bTotalLoadPageTree) { + if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) { return FALSE; + } } - if (IsFirstCheck(iPage)) { - m_bCurPageDictLoadOK = FALSE; - m_bPageLoadedOK = FALSE; - m_bAnnotsLoad = FALSE; - m_bNeedDownLoadResource = FALSE; - m_objs_array.RemoveAll(); - m_objnum_array.RemoveAll(); - } - if (m_pagesLoadState == NULL) { - m_pagesLoadState = new CFX_CMapDWordToDWord(); + } + if (m_bHaveAcroForm && !m_bAcroFormLoad) { + if (!CheckAcroFormSubObject(pHints)) { + return FALSE; } - FX_DWORD dwPageLoad = 0; - if (m_pagesLoadState->Lookup(iPage, dwPageLoad) && dwPageLoad != 0) { + m_bAcroFormLoad = TRUE; + } + if (!m_bPageLoadedOK) { + if (!m_objs_array.GetSize()) { + m_objs_array.RemoveAll(); + m_objnum_array.RemoveAll(); + m_pPageDict = m_pDocument->GetPage(iPage); + if (!m_pPageDict) { + ResetFirstCheck(iPage); return TRUE; - } - if (m_bLinearized) { - if ((FX_DWORD)iPage == m_dwFirstPageNo) { - m_pagesLoadState->SetAt(iPage, TRUE); - return TRUE; - } - if (!CheckLinearizedData(pHints)) { - return FALSE; - } - if (m_bMainXRefLoadedOK) { - if (m_bTotalLoadPageTree) { - if (!LoadPages(pHints)) { - return FALSE; - } - } else { - if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) { - return FALSE; - } - } - } else { - if (!LoadAllFile(pHints)) { - return FALSE; - } - ((CPDF_Parser *)m_pDocument->GetParser())->RebuildCrossRef(); - ResetFirstCheck(iPage); - return TRUE; - } + } + CFX_PtrArray obj_array; + obj_array.Add(m_pPageDict); + FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array); + if (bRet) { + m_objs_array.RemoveAll(); + m_bPageLoadedOK = TRUE; + } else { + return bRet; + } } else { - if (!m_bTotalLoadPageTree) { - if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) { - return FALSE; - } - } - } - if (m_bHaveAcroForm && !m_bAcroFormLoad) { - if (!CheckAcroFormSubObject(pHints)) { - return FALSE; - } - m_bAcroFormLoad = TRUE; - } - if (!m_bPageLoadedOK) { - if (!m_objs_array.GetSize()) { - m_objs_array.RemoveAll(); - m_objnum_array.RemoveAll(); - m_pPageDict = m_pDocument->GetPage(iPage); - if (!m_pPageDict) { - ResetFirstCheck(iPage); - return TRUE; - } - CFX_PtrArray obj_array; - obj_array.Add(m_pPageDict); - FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array); - if (bRet) { - m_objs_array.RemoveAll(); - m_bPageLoadedOK = TRUE; - } else { - return bRet; - } - } else { - CFX_PtrArray new_objs_array; - FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); - m_objs_array.RemoveAll(); - if (bRet) { - m_bPageLoadedOK = TRUE; - } else { - m_objs_array.Append(new_objs_array); - return bRet; - } - } - } - if (m_bPageLoadedOK) { - if (!m_bAnnotsLoad) { - if (!CheckPageAnnots(iPage, pHints)) { - return FALSE; - } - m_bAnnotsLoad = TRUE; - } + CFX_PtrArray new_objs_array; + FX_BOOL bRet = + IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); + m_objs_array.RemoveAll(); + if (bRet) { + m_bPageLoadedOK = TRUE; + } else { + m_objs_array.Append(new_objs_array); + return bRet; + } } - if (m_pPageDict && !m_bNeedDownLoadResource) { - m_pPageResource = m_pPageDict->GetElement("Resources"); - if (!m_pPageResource) { - m_bNeedDownLoadResource = HaveResourceAncestor(m_pPageDict); - } else { - m_bNeedDownLoadResource = TRUE; - } + } + if (m_bPageLoadedOK) { + if (!m_bAnnotsLoad) { + if (!CheckPageAnnots(iPage, pHints)) { + return FALSE; + } + m_bAnnotsLoad = TRUE; + } + } + if (m_pPageDict && !m_bNeedDownLoadResource) { + m_pPageResource = m_pPageDict->GetElement("Resources"); + if (!m_pPageResource) { + m_bNeedDownLoadResource = HaveResourceAncestor(m_pPageDict); + } else { + m_bNeedDownLoadResource = TRUE; } - if (m_bNeedDownLoadResource) { - FX_BOOL bRet = CheckResources(pHints); - if (!bRet) { - return FALSE; - } - m_bNeedDownLoadResource = FALSE; + } + if (m_bNeedDownLoadResource) { + FX_BOOL bRet = CheckResources(pHints); + if (!bRet) { + return FALSE; } - m_bPageLoadedOK = FALSE; - m_bAnnotsLoad = FALSE; - m_bCurPageDictLoadOK = FALSE; - ResetFirstCheck(iPage); - m_pagesLoadState->SetAt(iPage, TRUE); - return TRUE; + m_bNeedDownLoadResource = FALSE; + } + m_bPageLoadedOK = FALSE; + m_bAnnotsLoad = FALSE; + m_bCurPageDictLoadOK = FALSE; + ResetFirstCheck(iPage); + m_pagesLoadState->SetAt(iPage, TRUE); + return TRUE; } -FX_BOOL CPDF_DataAvail::CheckResources(IFX_DownloadHints* pHints) -{ - if (!m_objs_array.GetSize()) { - m_objs_array.RemoveAll(); - CFX_PtrArray obj_array; - obj_array.Add(m_pPageResource); - FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array); - if (bRet) { - m_objs_array.RemoveAll(); - } - return bRet; - } - CFX_PtrArray new_objs_array; - FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); +FX_BOOL CPDF_DataAvail::CheckResources(IFX_DownloadHints* pHints) { + if (!m_objs_array.GetSize()) { m_objs_array.RemoveAll(); - if (!bRet) { - m_objs_array.Append(new_objs_array); + CFX_PtrArray obj_array; + obj_array.Add(m_pPageResource); + FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array); + if (bRet) { + m_objs_array.RemoveAll(); } return bRet; + } + CFX_PtrArray new_objs_array; + FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); + m_objs_array.RemoveAll(); + if (!bRet) { + m_objs_array.Append(new_objs_array); + } + return bRet; } -void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE *pPos, FX_DWORD *pSize) -{ - if (pPos) { - *pPos = m_dwLastXRefOffset; - } - if (pSize) { - *pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset); - } +void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE* pPos, + FX_DWORD* pSize) { + if (pPos) { + *pPos = m_dwLastXRefOffset; + } + if (pSize) { + *pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset); + } } -int32_t CPDF_DataAvail::IsFormAvail(IFX_DownloadHints *pHints) -{ - if (!m_pDocument) { - return PDFFORM_AVAIL; - } - if (!m_bLinearizedFormParamLoad) { - CPDF_Dictionary *pRoot = m_pDocument->GetRoot(); - if (!pRoot) { - return PDFFORM_AVAIL; - } - CPDF_Object *pAcroForm = pRoot->GetElement(FX_BSTRC("AcroForm")); - if (!pAcroForm) { - return PDFFORM_NOTEXIST; - } - if (!CheckLinearizedData(pHints)) { - return PDFFORM_NOTAVAIL; - } - if (!m_objs_array.GetSize()) { - m_objs_array.Add(pAcroForm->GetDict()); - } - m_bLinearizedFormParamLoad = TRUE; +int32_t CPDF_DataAvail::IsFormAvail(IFX_DownloadHints* pHints) { + if (!m_pDocument) { + return PDFFORM_AVAIL; + } + if (!m_bLinearizedFormParamLoad) { + CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); + if (!pRoot) { + return PDFFORM_AVAIL; } - CFX_PtrArray new_objs_array; - FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); - m_objs_array.RemoveAll(); - if (!bRet) { - m_objs_array.Append(new_objs_array); - return PDFFORM_NOTAVAIL; + CPDF_Object* pAcroForm = pRoot->GetElement(FX_BSTRC("AcroForm")); + if (!pAcroForm) { + return PDFFORM_NOTEXIST; } - return PDFFORM_AVAIL; -} -void CPDF_SortObjNumArray::AddObjNum(FX_DWORD dwObjNum) -{ - int32_t iNext = 0; - if (BinarySearch(dwObjNum, iNext)) { - return; + if (!CheckLinearizedData(pHints)) { + return PDFFORM_NOTAVAIL; } - m_number_array.InsertAt(iNext, dwObjNum); + if (!m_objs_array.GetSize()) { + m_objs_array.Add(pAcroForm->GetDict()); + } + m_bLinearizedFormParamLoad = TRUE; + } + CFX_PtrArray new_objs_array; + FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); + m_objs_array.RemoveAll(); + if (!bRet) { + m_objs_array.Append(new_objs_array); + return PDFFORM_NOTAVAIL; + } + return PDFFORM_AVAIL; } -FX_BOOL CPDF_SortObjNumArray::Find(FX_DWORD dwObjNum) -{ - int32_t iNext = 0; - return BinarySearch(dwObjNum, iNext); +void CPDF_SortObjNumArray::AddObjNum(FX_DWORD dwObjNum) { + int32_t iNext = 0; + if (BinarySearch(dwObjNum, iNext)) { + return; + } + m_number_array.InsertAt(iNext, dwObjNum); } -FX_BOOL CPDF_SortObjNumArray::BinarySearch(FX_DWORD value, int32_t &iNext) -{ - int32_t iLow = 0; - int32_t iHigh = m_number_array.GetSize() - 1; - while (iLow <= iHigh) { - int32_t iMid = (iLow + iHigh) / 2; - if (m_number_array.GetAt(iMid) == value) { - iNext = iMid; - return TRUE; - } - if (m_number_array.GetAt(iMid) > value) { - iHigh = iMid - 1; - } else if (m_number_array.GetAt(iMid) < value) { - iLow = iMid + 1; - } - } - iNext = iLow; - return FALSE; +FX_BOOL CPDF_SortObjNumArray::Find(FX_DWORD dwObjNum) { + int32_t iNext = 0; + return BinarySearch(dwObjNum, iNext); } -CPDF_PageNode::~CPDF_PageNode() -{ - int32_t iSize = m_childNode.GetSize(); - for (int32_t i = 0; i < iSize; ++i) { - CPDF_PageNode* pNode = (CPDF_PageNode*)m_childNode[i]; - delete pNode; - } - m_childNode.RemoveAll(); +FX_BOOL CPDF_SortObjNumArray::BinarySearch(FX_DWORD value, int32_t& iNext) { + int32_t iLow = 0; + int32_t iHigh = m_number_array.GetSize() - 1; + while (iLow <= iHigh) { + int32_t iMid = (iLow + iHigh) / 2; + if (m_number_array.GetAt(iMid) == value) { + iNext = iMid; + return TRUE; + } + if (m_number_array.GetAt(iMid) > value) { + iHigh = iMid - 1; + } else if (m_number_array.GetAt(iMid) < value) { + iLow = iMid + 1; + } + } + iNext = iLow; + return FALSE; +} +CPDF_PageNode::~CPDF_PageNode() { + int32_t iSize = m_childNode.GetSize(); + for (int32_t i = 0; i < iSize; ++i) { + CPDF_PageNode* pNode = (CPDF_PageNode*)m_childNode[i]; + delete pNode; + } + m_childNode.RemoveAll(); } -- cgit v1.2.3