| Index: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| index e0fd3bfaeecea13e1b023d68982f3d35897ff2b9..e800ef474c436ccfa6c33b73921a5a8d1bca2523 100644
|
| --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
|
| @@ -1,7 +1,7 @@
|
| // Copyright 2014 PDFium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
| -
|
| +
|
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
|
|
|
| #include "../../../include/fpdfapi/fpdf_parser.h"
|
| @@ -10,4405 +10,4495 @@
|
| #include "../../../../third_party/numerics/safe_math.h"
|
| #include "../fpdf_page/pageint.h"
|
| #include <limits.h>
|
| -#define _PARSER_OBJECT_LEVLE_ 64
|
| +#define _PARSER_OBJECT_LEVLE_ 64
|
| extern const FX_LPCSTR _PDF_CharType;
|
| -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 FX_INT32 _CompareDWord(const void* p1, const void* p2)
|
| -{
|
| - return (*(FX_DWORD*)p1) - (*(FX_DWORD*)p2);
|
| +static FX_INT32 _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_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_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 (m_pDocument && !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) {
|
| - FX_LPVOID 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();
|
| - FX_INT32 iLen = m_Trailers.GetSize();
|
| - for (FX_INT32 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 (m_pDocument && !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) {
|
| + FX_LPVOID 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();
|
| + FX_INT32 iLen = m_Trailers.GetSize();
|
| + for (FX_INT32 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 FX_INT32 GetHeaderOffset(IFX_FileRead* pFile)
|
| -{
|
| - FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025);
|
| - FX_BYTE buf[4];
|
| - FX_INT32 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 FX_INT32 GetHeaderOffset(IFX_FileRead* pFile) {
|
| + FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025);
|
| + FX_BYTE buf[4];
|
| + FX_INT32 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(FX_LPCSTR 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(FX_LPCSTR 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(FX_LPCWSTR 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(FX_LPCWSTR 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;
|
| - FX_INT32 offset = GetHeaderOffset(pFileAccess);
|
| - if (offset == -1) {
|
| - if (bOwnFileRead && pFileAccess) {
|
| - pFileAccess->Release();
|
| - }
|
| +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;
|
| + FX_INT32 offset = GetHeaderOffset(pFileAccess);
|
| + if (offset == -1) {
|
| + if (bOwnFileRead && pFileAccess) {
|
| + pFileAccess->Release();
|
| + }
|
| + return PDFPARSE_ERROR_FORMAT;
|
| + }
|
| + m_Syntax.InitParser(pFileAccess, offset);
|
| + FX_BYTE ch;
|
| + m_Syntax.GetCharAt(5, ch);
|
| + m_FileVersion = (ch - '0') * 10;
|
| + m_Syntax.GetCharAt(7, ch);
|
| + m_FileVersion += ch - '0';
|
| + m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9);
|
| + if (!bReParse) {
|
| + m_pDocument = FX_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();
|
| + FX_LPVOID 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;
|
| + }
|
| + 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.InitParser(pFileAccess, offset);
|
| - FX_BYTE ch;
|
| - m_Syntax.GetCharAt(5, ch);
|
| - m_FileVersion = (ch - '0') * 10;
|
| - m_Syntax.GetCharAt(7, ch);
|
| - m_FileVersion += ch - '0';
|
| - m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9);
|
| - if (!bReParse) {
|
| - m_pDocument = FX_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();
|
| - FX_LPVOID 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;
|
| - }
|
| + return PDFPARSE_ERROR_FORMAT;
|
| }
|
| - 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;
|
| + 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()
|
| -{
|
| - if (m_Syntax.m_pCryptoHandler) {
|
| - delete m_Syntax.m_pCryptoHandler;
|
| - m_Syntax.m_pCryptoHandler = NULL;
|
| - }
|
| - if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
|
| - delete m_pSecurityHandler;
|
| - m_pSecurityHandler = NULL;
|
| - }
|
| +void CPDF_Parser::ReleaseEncryptHandler() {
|
| + if (m_Syntax.m_pCryptoHandler) {
|
| + delete m_Syntax.m_pCryptoHandler;
|
| + m_Syntax.m_pCryptoHandler = NULL;
|
| + }
|
| + if (m_pSecurityHandler && !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[(FX_INT32)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[(FX_INT32)m_CrossRef[objnum]];
|
| + }
|
| + return 0;
|
| }
|
| -static FX_INT32 GetDirectInteger(CPDF_Dictionary* pDict, FX_BSTR key)
|
| -{
|
| - CPDF_Object* pObj = pDict->GetElement(key);
|
| - if (pObj == NULL) {
|
| - return 0;
|
| - }
|
| - if (pObj->GetType() == PDFOBJ_NUMBER) {
|
| - return ((CPDF_Number*)pObj)->GetInteger();
|
| - }
|
| +static FX_INT32 GetDirectInteger(CPDF_Dictionary* pDict, FX_BSTR 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, FX_BSTR key, FX_INT32 iType)
|
| -{
|
| - CPDF_Object* pObj = pDict->GetElement(key);
|
| - if (!pObj) {
|
| - return TRUE;
|
| - }
|
| - return pObj->GetType() == iType;
|
| +static FX_BOOL CheckDirectType(CPDF_Dictionary* pDict,
|
| + FX_BSTR key,
|
| + FX_INT32 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;
|
| - }
|
| - FX_INT32 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;
|
| + }
|
| + FX_INT32 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 (FX_INT32 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 (FX_INT32 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;
|
| - }
|
| - FX_INT32 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 (FX_INT32 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;
|
| + }
|
| + FX_INT32 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 (FX_INT32 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);
|
| + FX_LPVOID 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();
|
| + FX_INT32 recordsize = 20;
|
| + char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
|
| + pBuf[1024 * recordsize] = '\0';
|
| + FX_INT32 nBlocks = count / 1024 + 1;
|
| + for (FX_INT32 block = 0; block < nBlocks; block++) {
|
| + FX_INT32 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((FX_LPBYTE)pBuf, dwReadSize)) {
|
| + FX_Free(pBuf);
|
| + return FALSE;
|
| + }
|
| + for (FX_INT32 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 {
|
| + FX_INT32 offset = FXSYS_atoi(pEntry);
|
| + if (offset == 0) {
|
| + for (FX_INT32 c = 0; c < 10; c++) {
|
| + if (pEntry[c] < '0' || pEntry[c] > '9') {
|
| + FX_Free(pBuf);
|
| + return FALSE;
|
| + }
|
| + }
|
| + }
|
| + m_CrossRef.SetAtGrow(objnum, offset);
|
| + FX_INT32 version = FXSYS_atoi(pEntry + 11);
|
| + if (version >= 1) {
|
| + m_bVersionUpdated = TRUE;
|
| + }
|
| + m_ObjVersion.SetAtGrow(objnum, version);
|
| + if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
|
| + FX_LPVOID 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::LoadLinearizedCrossRefV4(FX_FILESIZE pos, FX_DWORD dwObjCount)
|
| -{
|
| - FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset;
|
| - m_Syntax.RestorePos(dwStartPos);
|
| - FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
|
| +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;
|
| + }
|
| + FX_LPVOID pResult = FXSYS_bsearch(&pos,
|
| + m_SortedOffset.GetData(),
|
| + m_SortedOffset.GetSize(),
|
| + sizeof(FX_FILESIZE),
|
| + _CompareFileSize);
|
| + if (pResult == NULL) {
|
| + m_SortedOffset.Add(pos);
|
| + }
|
| + if (streampos) {
|
| + FX_LPVOID 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;
|
| FX_INT32 recordsize = 20;
|
| - char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
|
| - pBuf[1024 * recordsize] = '\0';
|
| - FX_INT32 nBlocks = count / 1024 + 1;
|
| - for (FX_INT32 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';
|
| + FX_INT32 nBlocks = count / 1024 + 1;
|
| + FX_BOOL bFirstBlock = TRUE;
|
| + for (FX_INT32 block = 0; block < nBlocks; block++) {
|
| FX_INT32 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((FX_LPBYTE)pBuf, dwReadSize)) {
|
| - FX_Free(pBuf);
|
| - return FALSE;
|
| - }
|
| - for (FX_INT32 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 {
|
| - FX_INT32 offset = FXSYS_atoi(pEntry);
|
| - if (offset == 0) {
|
| - for (FX_INT32 c = 0; c < 10; c ++) {
|
| - if (pEntry[c] < '0' || pEntry[c] > '9') {
|
| - FX_Free(pBuf);
|
| - return FALSE;
|
| - }
|
| - }
|
| - }
|
| - m_CrossRef.SetAtGrow(objnum, offset);
|
| - FX_INT32 version = FXSYS_atoi(pEntry + 11);
|
| - if (version >= 1) {
|
| - m_bVersionUpdated = TRUE;
|
| - }
|
| - m_ObjVersion.SetAtGrow(objnum, version);
|
| - if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
|
| - FX_LPVOID 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((FX_LPBYTE)pBuf, block_size * recordsize);
|
| + for (FX_INT32 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);
|
| + FX_INT32 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 (FX_INT32 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);
|
| + FX_INT32 version = FXSYS_atoi(pEntry + 11);
|
| + if (version >= 1) {
|
| + m_bVersionUpdated = TRUE;
|
| }
|
| + m_ObjVersion.SetAtGrow(objnum, version);
|
| + if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
|
| + FX_LPVOID 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;
|
| - }
|
| - FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
|
| - if (pResult == NULL) {
|
| - m_SortedOffset.Add(pos);
|
| + }
|
| + if (streampos)
|
| + if (!LoadCrossRefV5(streampos, streampos, FALSE)) {
|
| + return FALSE;
|
| }
|
| - if (streampos) {
|
| - FX_LPVOID 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;
|
| + }
|
| + FX_INT32 status = 0;
|
| + FX_INT32 inside_index = 0;
|
| + FX_DWORD objnum, gennum;
|
| + FX_INT32 depth = 0;
|
| + FX_LPBYTE buffer = FX_Alloc(FX_BYTE, 4096);
|
| + FX_FILESIZE pos = m_Syntax.m_HeaderOffset;
|
| + FX_FILESIZE start_pos, start_pos1;
|
| + FX_FILESIZE last_obj = -1, last_xref = -1, last_trailer = -1;
|
| + FX_BOOL bInUpdate = FALSE;
|
| + 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++) {
|
| + FX_BYTE 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;
|
| - FX_INT32 recordsize = 20;
|
| - if (bFirst) {
|
| - bFirstItem = TRUE;
|
| - }
|
| - m_dwXrefStartObjNum = start_objnum;
|
| - if (!bSkip) {
|
| - char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
|
| - pBuf[1024 * recordsize] = '\0';
|
| - FX_INT32 nBlocks = count / 1024 + 1;
|
| - FX_BOOL bFirstBlock = TRUE;
|
| - for (FX_INT32 block = 0; block < nBlocks; block ++) {
|
| - FX_INT32 block_size = block == nBlocks - 1 ? count % 1024 : 1024;
|
| - m_Syntax.ReadBlock((FX_LPBYTE)pBuf, block_size * recordsize);
|
| - for (FX_INT32 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);
|
| - FX_INT32 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 (FX_INT32 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;
|
| + FX_LPVOID 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);
|
| - FX_INT32 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() > (FX_INT32)objnum &&
|
| + m_CrossRef[objnum]) {
|
| + if (pObject) {
|
| + FX_DWORD oldgen = m_ObjVersion.GetAt(objnum);
|
| + m_CrossRef[objnum] = obj_pos;
|
| + m_ObjVersion.SetAt(objnum, (FX_SHORT)gennum);
|
| + if (oldgen != gennum) {
|
| + m_bVersionUpdated = TRUE;
|
| + }
|
| + }
|
| + } else {
|
| + m_CrossRef.SetAtGrow(objnum, obj_pos);
|
| + m_V5Type.SetAtGrow(objnum, 1);
|
| + m_ObjVersion.SetAtGrow(objnum, (FX_SHORT)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) {
|
| - FX_LPVOID 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();
|
| + }
|
| + bInUpdate = TRUE;
|
| }
|
| + }
|
| }
|
| - FX_Free(pBuf);
|
| - }
|
| - m_Syntax.RestorePos(SavedPos + count * recordsize);
|
| - }
|
| - if (streampos)
|
| - if (!LoadCrossRefV5(streampos, streampos, FALSE)) {
|
| + --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;
|
| + FX_LPVOID 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(FX_LPCBYTE p, FX_INT32 n) {
|
| + FX_DWORD result = 0;
|
| + for (FX_INT32 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) {
|
| + m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
|
| + }
|
| + if (pStream->GetType() != PDFOBJ_STREAM) {
|
| + return FALSE;
|
| + }
|
| + prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev"));
|
| + FX_INT32 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_memset32(m_V5Type.GetData(), 0, size);
|
| + }
|
| + } else {
|
| + m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
|
| + }
|
| + CFX_DWordArray IndexArray, WidthArray;
|
| + FX_DWORD nSegs = 0;
|
| + CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
|
| + if (pArray == NULL) {
|
| + IndexArray.Add(0);
|
| + IndexArray.Add(size);
|
| + nSegs = 1;
|
| + } else {
|
| + for (FX_DWORD i = 0; i < pArray->GetCount(); i++) {
|
| + IndexArray.Add(pArray->GetInteger(i));
|
| + }
|
| + nSegs = pArray->GetCount() / 2;
|
| + }
|
| + pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
|
| + if (pArray == NULL) {
|
| + pStream->Release();
|
| + return FALSE;
|
| + }
|
| + FX_DWORD totalwidth = 0;
|
| + FX_DWORD i;
|
| + for (i = 0; i < pArray->GetCount(); i++) {
|
| + WidthArray.Add(pArray->GetInteger(i));
|
| + if (totalwidth + WidthArray[i] < totalwidth) {
|
| + pStream->Release();
|
| + return FALSE;
|
| + }
|
| + totalwidth += WidthArray[i];
|
| + }
|
| + if (totalwidth == 0 || WidthArray.GetSize() < 3) {
|
| + pStream->Release();
|
| + return FALSE;
|
| + }
|
| + CPDF_StreamAcc acc;
|
| + acc.LoadAllData(pStream);
|
| + FX_LPCBYTE pData = acc.GetData();
|
| + FX_DWORD dwTotalSize = acc.GetSize();
|
| + FX_DWORD segindex = 0;
|
| + for (i = 0; i < nSegs; i++) {
|
| + FX_INT32 startnum = IndexArray[i * 2];
|
| + if (startnum < 0) {
|
| + continue;
|
| + }
|
| + m_dwXrefStartObjNum = startnum;
|
| + FX_DWORD count = IndexArray[i * 2 + 1];
|
| + if (segindex + count < segindex || segindex + count == 0 ||
|
| + (FX_DWORD)totalwidth >= UINT_MAX / (segindex + count) ||
|
| + (segindex + count) * (FX_DWORD)totalwidth > dwTotalSize) {
|
| + continue;
|
| + }
|
| + FX_LPCBYTE segstart = pData + segindex * (FX_DWORD)totalwidth;
|
| + if ((FX_DWORD)startnum + count < (FX_DWORD)startnum ||
|
| + (FX_DWORD)startnum + count > (FX_DWORD)m_V5Type.GetSize()) {
|
| + continue;
|
| + }
|
| + for (FX_DWORD j = 0; j < count; j++) {
|
| + FX_INT32 type = 1;
|
| + FX_LPCBYTE 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;
|
| + FX_LPVOID 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) {
|
| + FX_LPVOID 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];
|
| + FX_LPVOID 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;
|
| + }
|
| + FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
|
| + FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
|
| + CPDF_SyntaxParser syntax;
|
| + CFX_SmartPointer<IFX_FileStream> file(
|
| + FX_CreateMemoryStream((FX_LPBYTE)pObjStream->GetData(),
|
| + (size_t)pObjStream->GetSize(),
|
| + FALSE));
|
| + syntax.InitParser((IFX_FileStream*)file, 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, 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;
|
| - }
|
| - FX_INT32 status = 0;
|
| - FX_INT32 inside_index = 0;
|
| - FX_DWORD objnum, gennum;
|
| - FX_INT32 depth = 0;
|
| - FX_LPBYTE buffer = FX_Alloc(FX_BYTE, 4096);
|
| - FX_FILESIZE pos = m_Syntax.m_HeaderOffset;
|
| - FX_FILESIZE start_pos, start_pos1;
|
| - FX_FILESIZE last_obj = -1, last_xref = -1, last_trailer = -1;
|
| - FX_BOOL bInUpdate = FALSE;
|
| - 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 ++) {
|
| - FX_BYTE 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;
|
| - FX_LPVOID 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() > (FX_INT32)objnum && m_CrossRef[objnum]) {
|
| - if (pObject) {
|
| - FX_DWORD oldgen = m_ObjVersion.GetAt(objnum);
|
| - m_CrossRef[objnum] = obj_pos;
|
| - m_ObjVersion.SetAt(objnum, (FX_SHORT)gennum);
|
| - if (oldgen != gennum) {
|
| - m_bVersionUpdated = TRUE;
|
| - }
|
| - }
|
| - } else {
|
| - m_CrossRef.SetAtGrow(objnum, obj_pos);
|
| - m_V5Type.SetAtGrow(objnum, 1);
|
| - m_ObjVersion.SetAtGrow(objnum, (FX_SHORT)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();
|
| - }
|
| - bInUpdate = TRUE;
|
| - }
|
| - }
|
| - }
|
| - --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;
|
| - FX_LPVOID 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*)(FX_UINTPTR) 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 = FX_NEW CPDF_StreamAcc;
|
| + pStreamAcc->LoadAllData(pStream);
|
| + m_ObjectStreamMap.SetAt((void*)(FX_UINTPTR) 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;
|
| + }
|
| + FX_LPVOID 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(FX_LPCBYTE p, FX_INT32 n)
|
| -{
|
| - FX_DWORD result = 0;
|
| - for (FX_INT32 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) {
|
| - m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
|
| +void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum,
|
| + FX_LPBYTE& 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;
|
| + }
|
| + FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
|
| + FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
|
| + CPDF_SyntaxParser syntax;
|
| + FX_LPCBYTE pData = pObjStream->GetData();
|
| + FX_DWORD totalsize = pObjStream->GetSize();
|
| + CFX_SmartPointer<IFX_FileStream> file(
|
| + FX_CreateMemoryStream((FX_LPBYTE)pData, (size_t)totalsize, FALSE));
|
| + syntax.InitParser((IFX_FileStream*)file, 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(FX_BYTE, size);
|
| + FXSYS_memcpy32(pBuffer, pData + thisoff + offset, size);
|
| + return;
|
| + }
|
| + n--;
|
| }
|
| - if (pStream->GetType() != PDFOBJ_STREAM) {
|
| - return FALSE;
|
| + return;
|
| + }
|
| + if (m_V5Type[objnum] == 1) {
|
| + FX_FILESIZE pos = m_CrossRef[objnum];
|
| + if (pos == 0) {
|
| + return;
|
| }
|
| - prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev"));
|
| - FX_INT32 size = pStream->GetDict()->GetInteger(FX_BSTRC("Size"));
|
| - if (size < 0) {
|
| - pStream->Release();
|
| - return FALSE;
|
| + 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;
|
| }
|
| - if (bMainXRef) {
|
| - m_pTrailer = (CPDF_Dictionary*)pStream->GetDict()->Clone();
|
| - m_CrossRef.SetSize(size);
|
| - if (m_V5Type.SetSize(size)) {
|
| - FXSYS_memset32(m_V5Type.GetData(), 0, size);
|
| - }
|
| - } else {
|
| - m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
|
| - }
|
| - CFX_DWordArray IndexArray, WidthArray;
|
| - FX_DWORD nSegs = 0;
|
| - CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
|
| - if (pArray == NULL) {
|
| - IndexArray.Add(0);
|
| - IndexArray.Add(size);
|
| - nSegs = 1;
|
| - } else {
|
| - for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
|
| - IndexArray.Add(pArray->GetInteger(i));
|
| - }
|
| - nSegs = pArray->GetCount() / 2;
|
| + FX_DWORD real_objnum = FXSYS_atoi(word);
|
| + if (real_objnum && real_objnum != objnum) {
|
| + m_Syntax.RestorePos(SavedPos);
|
| + return;
|
| }
|
| - pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
|
| - if (pArray == NULL) {
|
| - pStream->Release();
|
| - return FALSE;
|
| + word = m_Syntax.GetNextWord(bIsNumber);
|
| + if (!bIsNumber) {
|
| + m_Syntax.RestorePos(SavedPos);
|
| + return;
|
| }
|
| - FX_DWORD totalwidth = 0;
|
| - FX_DWORD i;
|
| - for (i = 0; i < pArray->GetCount(); i ++) {
|
| - WidthArray.Add(pArray->GetInteger(i));
|
| - if (totalwidth + WidthArray[i] < totalwidth) {
|
| - pStream->Release();
|
| - return FALSE;
|
| + if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
|
| + m_Syntax.RestorePos(SavedPos);
|
| + return;
|
| + }
|
| + FX_LPVOID 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;
|
| }
|
| - totalwidth += WidthArray[i];
|
| - }
|
| - if (totalwidth == 0 || WidthArray.GetSize() < 3) {
|
| - pStream->Release();
|
| - return FALSE;
|
| + }
|
| }
|
| - CPDF_StreamAcc acc;
|
| - acc.LoadAllData(pStream);
|
| - FX_LPCBYTE pData = acc.GetData();
|
| - FX_DWORD dwTotalSize = acc.GetSize();
|
| - FX_DWORD segindex = 0;
|
| - for (i = 0; i < nSegs; i ++) {
|
| - FX_INT32 startnum = IndexArray[i * 2];
|
| - if (startnum < 0) {
|
| - continue;
|
| - }
|
| - m_dwXrefStartObjNum = startnum;
|
| - FX_DWORD count = IndexArray[i * 2 + 1];
|
| - if (segindex + count < segindex || segindex + count == 0 ||
|
| - (FX_DWORD)totalwidth >= UINT_MAX / (segindex + count) || (segindex + count) * (FX_DWORD)totalwidth > dwTotalSize) {
|
| - continue;
|
| + if (!bNextOffValid) {
|
| + m_Syntax.RestorePos(pos);
|
| + while (1) {
|
| + if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) {
|
| + break;
|
| }
|
| - FX_LPCBYTE segstart = pData + segindex * (FX_DWORD)totalwidth;
|
| - if ((FX_DWORD)startnum + count < (FX_DWORD)startnum ||
|
| - (FX_DWORD)startnum + count > (FX_DWORD)m_V5Type.GetSize()) {
|
| - continue;
|
| - }
|
| - for (FX_DWORD j = 0; j < count; j ++) {
|
| - FX_INT32 type = 1;
|
| - FX_LPCBYTE 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;
|
| - FX_LPVOID 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) {
|
| - FX_LPVOID 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;
|
| - }
|
| - 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;
|
| + }
|
| + nextoff = m_Syntax.SavePos();
|
| }
|
| - return ((CPDF_Reference*) pRef)->GetRefObjNum();
|
| + size = (FX_DWORD)(nextoff - pos);
|
| + pBuffer = FX_Alloc(FX_BYTE, size);
|
| + m_Syntax.RestorePos(pos);
|
| + m_Syntax.ReadBlock(pBuffer, size);
|
| + m_Syntax.RestorePos(SavedPos);
|
| + }
|
| }
|
| -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();
|
| +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 real_objnum = FXSYS_atoi(word);
|
| + if (objnum && real_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.GetObject(pObjList, objnum, gennum, 0, pContext);
|
| + FX_FILESIZE endOffset = m_Syntax.SavePos();
|
| + CFX_ByteString bsWord = m_Syntax.GetKeyword();
|
| + if (bsWord == FX_BSTRC("endobj")) {
|
| + endOffset = m_Syntax.SavePos();
|
| + }
|
| + m_Syntax.RestorePos(SavedPos);
|
| + if (pObj && !objnum) {
|
| + pObj->m_ObjNum = real_objnum;
|
| + pObj->m_GenNum = gennum;
|
| + }
|
| + return pObj;
|
| }
|
| -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];
|
| - FX_LPVOID 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;
|
| +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 TRUE;
|
| + return NULL;
|
| + }
|
| + FX_DWORD real_objnum = FXSYS_atoi(word);
|
| + if (objnum && real_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, 0, pContext);
|
| + if (pResultPos) {
|
| + *pResultPos = m_Syntax.m_Pos;
|
| + }
|
| + m_Syntax.RestorePos(SavedPos);
|
| + return pObj;
|
| }
|
| -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;
|
| - }
|
| - FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
|
| - FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
|
| - CPDF_SyntaxParser syntax;
|
| - CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE));
|
| - syntax.InitParser((IFX_FileStream*)file, 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, 0, pContext);
|
| - break;
|
| - }
|
| - n --;
|
| - }
|
| - return pRet;
|
| +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 NULL;
|
| + }
|
| + return (CPDF_Dictionary*)pObj;
|
| }
|
| -CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum)
|
| -{
|
| - CPDF_StreamAcc* pStreamAcc = NULL;
|
| - if (m_ObjectStreamMap.Lookup((void*)(FX_UINTPTR)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 = FX_NEW CPDF_StreamAcc;
|
| - pStreamAcc->LoadAllData(pStream);
|
| - m_ObjectStreamMap.SetAt((void*)(FX_UINTPTR)objnum, pStreamAcc);
|
| - return pStreamAcc;
|
| +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_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;
|
| - }
|
| - FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
|
| - if (pResult == NULL) {
|
| - return 0;
|
| - }
|
| - if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
|
| - return 0;
|
| - }
|
| - return ((FX_FILESIZE*)pResult)[1] - offset;
|
| - }
|
| - return 0;
|
| +FX_BOOL CPDF_Parser::IsOwner() {
|
| + return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
|
| }
|
| -void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, FX_LPBYTE& 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;
|
| - }
|
| - FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
|
| - FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
|
| - CPDF_SyntaxParser syntax;
|
| - FX_LPCBYTE pData = pObjStream->GetData();
|
| - FX_DWORD totalsize = pObjStream->GetSize();
|
| - CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pData, (size_t)totalsize, FALSE));
|
| - syntax.InitParser((IFX_FileStream*)file, 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(FX_BYTE, size);
|
| - FXSYS_memcpy32(pBuffer, pData + thisoff + offset, size);
|
| - return;
|
| - }
|
| - n --;
|
| - }
|
| - return;
|
| - }
|
| - 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 real_objnum = FXSYS_atoi(word);
|
| - if (real_objnum && real_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;
|
| - }
|
| - FX_LPVOID 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;
|
| - }
|
| - }
|
| - }
|
| - 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();
|
| - }
|
| - size = (FX_DWORD)(nextoff - pos);
|
| - pBuffer = FX_Alloc(FX_BYTE, size);
|
| - m_Syntax.RestorePos(pos);
|
| - m_Syntax.ReadBlock(pBuffer, size);
|
| - m_Syntax.RestorePos(SavedPos);
|
| - }
|
| +void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler,
|
| + FX_BOOL bForced) {
|
| + ASSERT(m_pSecurityHandler == NULL);
|
| + if (m_pSecurityHandler && !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);
|
| }
|
| -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 real_objnum = FXSYS_atoi(word);
|
| - if (objnum && real_objnum != objnum) {
|
| - m_Syntax.RestorePos(SavedPos);
|
| - return NULL;
|
| - }
|
| - word = m_Syntax.GetNextWord(bIsNumber);
|
| - if (!bIsNumber) {
|
| - m_Syntax.RestorePos(SavedPos);
|
| - return NULL;
|
| +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();
|
| + 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();
|
| }
|
| - FX_DWORD gennum = FXSYS_atoi(word);
|
| - if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
|
| - m_Syntax.RestorePos(SavedPos);
|
| - return NULL;
|
| + 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;
|
| + FX_INT32 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 = FX_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;
|
| }
|
| - CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, gennum, 0, pContext);
|
| - FX_FILESIZE endOffset = m_Syntax.SavePos();
|
| - CFX_ByteString bsWord = m_Syntax.GetKeyword();
|
| - if (bsWord == FX_BSTRC("endobj")) {
|
| - endOffset = m_Syntax.SavePos();
|
| + FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
|
| + if (xrefsize == 0) {
|
| + return FALSE;
|
| }
|
| - m_Syntax.RestorePos(SavedPos);
|
| - if (pObj && !objnum) {
|
| - pObj->m_ObjNum = real_objnum;
|
| - pObj->m_GenNum = gennum;
|
| + 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;
|
| }
|
| - 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;
|
| + ReleaseEncryptHandler();
|
| + if (!RebuildCrossRef()) {
|
| + return PDFPARSE_ERROR_FORMAT;
|
| }
|
| - FX_DWORD real_objnum = FXSYS_atoi(word);
|
| - if (objnum && real_objnum != objnum) {
|
| - m_Syntax.RestorePos(SavedPos);
|
| - return NULL;
|
| + dwRet = SetEncryptHandler();
|
| + if (dwRet != PDFPARSE_ERROR_SUCCESS) {
|
| + return dwRet;
|
| }
|
| - word = m_Syntax.GetNextWord(bIsNumber);
|
| - if (!bIsNumber) {
|
| - m_Syntax.RestorePos(SavedPos);
|
| - return NULL;
|
| + 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_DWORD gennum = FXSYS_atoi(word);
|
| - if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
|
| - m_Syntax.RestorePos(SavedPos);
|
| - return NULL;
|
| + dwRet = SetEncryptHandler();
|
| + if (dwRet != PDFPARSE_ERROR_SUCCESS) {
|
| + return dwRet;
|
| }
|
| - CPDF_Object* pObj = m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, 0, pContext);
|
| - if (pResultPos) {
|
| - *pResultPos = m_Syntax.m_Pos;
|
| + }
|
| + 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();
|
| }
|
| - m_Syntax.RestorePos(SavedPos);
|
| - return pObj;
|
| + }
|
| + return PDFPARSE_ERROR_SUCCESS;
|
| }
|
| -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 NULL;
|
| +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 (CPDF_Dictionary*)pObj;
|
| + m_ObjectStreamMap.InitHashTable(101, FALSE);
|
| + m_bXRefStream = TRUE;
|
| + return TRUE;
|
| }
|
| -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;
|
| - }
|
| +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);
|
| + FX_BYTE ch = 0;
|
| + FX_DWORD dwCount = 0;
|
| + m_Syntax.GetNextChar(ch);
|
| + FX_INT32 type = _PDF_CharType[ch];
|
| + while (type == 'W') {
|
| + ++dwCount;
|
| + if (m_Syntax.m_FileLen >=
|
| + (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
|
| + break;
|
| }
|
| - return dwPermission;
|
| + m_Syntax.GetNextChar(ch);
|
| + type = _PDF_CharType[ch];
|
| + }
|
| + m_LastXRefOffset += dwCount;
|
| + FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
|
| + while (pos) {
|
| + FX_LPVOID 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;
|
| +}
|
| +CPDF_SyntaxParser::CPDF_SyntaxParser() {
|
| + m_pFileAccess = NULL;
|
| + m_pCryptoHandler = NULL;
|
| + m_pFileBuf = NULL;
|
| + m_BufSize = CPDF_ModuleMgr::Get()->m_FileBufSize;
|
| + m_pFileBuf = NULL;
|
| + m_MetadataObjnum = 0;
|
| + m_dwWordPos = 0;
|
| +#if defined(_FPDFAPI_MINI_)
|
| + m_bFileStream = TRUE;
|
| +#else
|
| + m_bFileStream = FALSE;
|
| +#endif
|
| }
|
| -FX_BOOL CPDF_Parser::IsOwner()
|
| -{
|
| - return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
|
| +CPDF_SyntaxParser::~CPDF_SyntaxParser() {
|
| + if (m_pFileBuf) {
|
| + FX_Free(m_pFileBuf);
|
| + }
|
| }
|
| -void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler, FX_BOOL bForced)
|
| -{
|
| - ASSERT(m_pSecurityHandler == NULL);
|
| - if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
|
| - delete m_pSecurityHandler;
|
| - m_pSecurityHandler = NULL;
|
| - }
|
| - m_bForceUseSecurityHandler = bForced;
|
| - m_pSecurityHandler = pSecurityHandler;
|
| - if (m_bForceUseSecurityHandler) {
|
| +FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, FX_BYTE& 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(FX_BYTE& 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, FX_BYTE& 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(FX_LPBYTE pBuf, FX_DWORD size) {
|
| + if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) {
|
| + return FALSE;
|
| + }
|
| + m_Pos += size;
|
| + return TRUE;
|
| +}
|
| +#define MAX_WORD_BUFFER 256
|
| +void CPDF_SyntaxParser::GetNextWord() {
|
| + m_WordSize = 0;
|
| + m_bIsNumber = TRUE;
|
| + FX_BYTE ch;
|
| + if (!GetNextChar(ch)) {
|
| + return;
|
| + }
|
| + FX_BYTE type = _PDF_CharType[ch];
|
| + while (1) {
|
| + while (type == 'W') {
|
| + if (!GetNextChar(ch)) {
|
| return;
|
| + }
|
| + type = _PDF_CharType[ch];
|
| }
|
| - 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();
|
| - 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 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;
|
| - FX_INT32 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 = FX_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;
|
| - }
|
| - FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
|
| - if (xrefsize == 0) {
|
| - return FALSE;
|
| - }
|
| - 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;
|
| - }
|
| - 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;
|
| - }
|
| - }
|
| - 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;
|
| - }
|
| - dwRet = SetEncryptHandler();
|
| - if (dwRet != PDFPARSE_ERROR_SUCCESS) {
|
| - return dwRet;
|
| - }
|
| - }
|
| - 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();
|
| - }
|
| - }
|
| - 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;
|
| - }
|
| - 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);
|
| - FX_BYTE ch = 0;
|
| - FX_DWORD dwCount = 0;
|
| - m_Syntax.GetNextChar(ch);
|
| - FX_INT32 type = _PDF_CharType[ch];
|
| - while (type == 'W') {
|
| - ++dwCount;
|
| - if (m_Syntax.m_FileLen >= (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
|
| - break;
|
| - }
|
| - m_Syntax.GetNextChar(ch);
|
| - type = _PDF_CharType[ch];
|
| - }
|
| - m_LastXRefOffset += dwCount;
|
| - FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
|
| - while (pos) {
|
| - FX_LPVOID 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;
|
| -}
|
| -CPDF_SyntaxParser::CPDF_SyntaxParser()
|
| -{
|
| - m_pFileAccess = NULL;
|
| - m_pCryptoHandler = NULL;
|
| - m_pFileBuf = NULL;
|
| - m_BufSize = CPDF_ModuleMgr::Get()->m_FileBufSize;
|
| - m_pFileBuf = NULL;
|
| - m_MetadataObjnum = 0;
|
| - m_dwWordPos = 0;
|
| -#if defined(_FPDFAPI_MINI_)
|
| - m_bFileStream = TRUE;
|
| -#else
|
| - m_bFileStream = FALSE;
|
| -#endif
|
| -}
|
| -CPDF_SyntaxParser::~CPDF_SyntaxParser()
|
| -{
|
| - if (m_pFileBuf) {
|
| - FX_Free(m_pFileBuf);
|
| - }
|
| -}
|
| -FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, FX_BYTE& 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(FX_BYTE& 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, FX_BYTE& 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(FX_LPBYTE pBuf, FX_DWORD size)
|
| -{
|
| - if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) {
|
| - return FALSE;
|
| - }
|
| - m_Pos += size;
|
| - return TRUE;
|
| -}
|
| -#define MAX_WORD_BUFFER 256
|
| -void CPDF_SyntaxParser::GetNextWord()
|
| -{
|
| - m_WordSize = 0;
|
| - m_bIsNumber = TRUE;
|
| - FX_BYTE ch;
|
| - if (!GetNextChar(ch)) {
|
| - return;
|
| + if (ch != '%') {
|
| + break;
|
| }
|
| - FX_BYTE 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 (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;
|
| - } else {
|
| - m_Pos --;
|
| - }
|
| - }
|
| + if (!GetNextChar(ch)) {
|
| return;
|
| - }
|
| - while (1) {
|
| - if (m_WordSize < MAX_WORD_BUFFER) {
|
| - m_WordBuffer[m_WordSize++] = ch;
|
| - }
|
| - if (type != 'N') {
|
| - m_bIsNumber = FALSE;
|
| - }
|
| + }
|
| + 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;
|
| + return;
|
| }
|
| type = _PDF_CharType[ch];
|
| - if (type == 'D' || type == 'W') {
|
| - m_Pos --;
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -CFX_ByteString CPDF_SyntaxParser::ReadString()
|
| -{
|
| - FX_BYTE ch;
|
| - if (!GetNextChar(ch)) {
|
| - return CFX_ByteString();
|
| - }
|
| - CFX_ByteTextBuf buf;
|
| - FX_INT32 parlevel = 0;
|
| - FX_INT32 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;
|
| - }
|
| - }
|
| - GetNextChar(ch);
|
| - return buf.GetByteString();
|
| -}
|
| -CFX_ByteString CPDF_SyntaxParser::ReadHexString()
|
| -{
|
| - FX_BYTE ch;
|
| - if (!GetNextChar(ch)) {
|
| - return CFX_ByteString();
|
| - }
|
| - CFX_BinaryBuf buf;
|
| - FX_BOOL bFirst = TRUE;
|
| - FX_BYTE code = 0;
|
| - while (1) {
|
| - if (ch == '>') {
|
| - break;
|
| - }
|
| - if (ch >= '0' && ch <= '9') {
|
| - if (bFirst) {
|
| - code = (ch - '0') * 16;
|
| - } else {
|
| - code += ch - '0';
|
| - buf.AppendByte((FX_BYTE)code);
|
| - }
|
| - bFirst = !bFirst;
|
| - } else if (ch >= 'A' && ch <= 'F') {
|
| - if (bFirst) {
|
| - code = (ch - 'A' + 10) * 16;
|
| - } else {
|
| - code += ch - 'A' + 10;
|
| - buf.AppendByte((FX_BYTE)code);
|
| - }
|
| - bFirst = !bFirst;
|
| - } else if (ch >= 'a' && ch <= 'f') {
|
| - if (bFirst) {
|
| - code = (ch - 'a' + 10) * 16;
|
| - } else {
|
| - code += ch - 'a' + 10;
|
| - buf.AppendByte((FX_BYTE)code);
|
| - }
|
| - bFirst = !bFirst;
|
| - }
|
| - if (!GetNextChar(ch)) {
|
| - break;
|
| - }
|
| - }
|
| - if (!bFirst) {
|
| - buf.AppendByte((FX_BYTE)code);
|
| - }
|
| - return buf.GetByteString();
|
| -}
|
| -void CPDF_SyntaxParser::ToNextLine()
|
| -{
|
| - FX_BYTE ch;
|
| - while (1) {
|
| - if (!GetNextChar(ch)) {
|
| - return;
|
| - }
|
| - if (ch == '\n') {
|
| - return;
|
| + if (type != 'R' && type != 'N') {
|
| + m_Pos--;
|
| + return;
|
| }
|
| - if (ch == '\r') {
|
| - GetNextChar(ch);
|
| - if (ch == '\n') {
|
| - return;
|
| - } else {
|
| - m_Pos --;
|
| - return;
|
| - }
|
| + if (m_WordSize < MAX_WORD_BUFFER) {
|
| + m_WordBuffer[m_WordSize++] = ch;
|
| }
|
| - }
|
| -}
|
| -void CPDF_SyntaxParser::ToNextWord()
|
| -{
|
| - FX_BYTE ch;
|
| - if (!GetNextChar(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;
|
| + } else {
|
| + m_Pos--;
|
| + }
|
| }
|
| - FX_BYTE 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((FX_LPCSTR)m_WordBuffer, m_WordSize);
|
| -}
|
| -CFX_ByteString CPDF_SyntaxParser::GetKeyword()
|
| -{
|
| - GetNextWord();
|
| - return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
|
| -}
|
| -CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, FX_INT32 level, PARSE_CONTEXT* pContext, FX_BOOL bDecrypt)
|
| -{
|
| - if (level > _PARSER_OBJECT_LEVLE_) {
|
| - 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;
|
| - }
|
| - pRet = CPDF_Reference::Create(pObjList, objnum);
|
| - return pRet;
|
| - } else {
|
| - m_Pos = SavedPos;
|
| - if (bTypeOnly) {
|
| - return (CPDF_Object*)PDFOBJ_NUMBER;
|
| - }
|
| - pRet = CPDF_Number::Create(word);
|
| - return pRet;
|
| - }
|
| - } else {
|
| - m_Pos = SavedPos;
|
| - if (bTypeOnly) {
|
| - return (CPDF_Object*)PDFOBJ_NUMBER;
|
| - }
|
| - pRet = CPDF_Number::Create(word);
|
| - return pRet;
|
| - }
|
| - }
|
| - 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;
|
| + return;
|
| + }
|
| + while (1) {
|
| + if (m_WordSize < MAX_WORD_BUFFER) {
|
| + m_WordBuffer[m_WordSize++] = ch;
|
| }
|
| - 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, level + 1);
|
| - 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("<<")) {
|
| - FX_FILESIZE saveDictOffset = m_Pos - 2;
|
| - FX_DWORD dwDictSize = 0;
|
| - if (bTypeOnly) {
|
| - return (CPDF_Object*)PDFOBJ_DICTIONARY;
|
| - }
|
| - if (pContext) {
|
| - pContext->m_DictStart = SavedPos;
|
| - }
|
| - CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
|
| - FX_INT32 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(">>")) {
|
| - dwDictSize = m_Pos - saveDictOffset;
|
| - break;
|
| - }
|
| - if (key == FX_BSTRC("endobj")) {
|
| - dwDictSize = m_Pos - 6 - saveDictOffset;
|
| - 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, level + 1);
|
| - if (pObj == NULL) {
|
| - continue;
|
| - }
|
| - if (key.GetLength() == 1) {
|
| - pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
|
| - } else {
|
| - if (nKeys < 32) {
|
| - pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
|
| - } else {
|
| - pDict->AddValue(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
|
| - }
|
| - }
|
| - }
|
| - if (IsSignatureDict(pDict)) {
|
| - FX_FILESIZE dwSavePos = m_Pos;
|
| - m_Pos = dwSignValuePos;
|
| - CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1, 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,
|
| - FX_INT32 level, struct PARSE_CONTEXT* pContext)
|
| -{
|
| - if (level > _PARSER_OBJECT_LEVLE_) {
|
| - 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")) {
|
| - FX_DWORD objnum = FXSYS_atoi(word);
|
| - if (bTypeOnly) {
|
| - return (CPDF_Object*)PDFOBJ_REFERENCE;
|
| - }
|
| - return CPDF_Reference::Create(pObjList, objnum);
|
| - } else {
|
| - m_Pos = SavedPos;
|
| - if (bTypeOnly) {
|
| - return (CPDF_Object*)PDFOBJ_NUMBER;
|
| - }
|
| - return CPDF_Number::Create(word);
|
| - }
|
| - } else {
|
| - 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, level + 1);
|
| - 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, level + 1);
|
| - if (pObj == NULL) {
|
| - if (pDict)
|
| - pDict->Release();
|
| - FX_BYTE ch;
|
| - while (1) {
|
| - if (!GetNextChar(ch)) {
|
| - break;
|
| - }
|
| - if (ch == 0x0A || ch == 0x0D) {
|
| - break;
|
| - }
|
| - }
|
| - return NULL;
|
| - }
|
| - if (key.GetLength() == 1) {
|
| - pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
|
| - } else {
|
| - pDict->AddValue(CFX_ByteStringC(((FX_LPCSTR)key) + 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;
|
| - }
|
| -
|
| - base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
|
| - pos += len;
|
| - if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
|
| - m_Pos = pos.ValueOrDie();
|
| - } else {
|
| - return NULL;
|
| - }
|
| -
|
| - CPDF_CryptoHandler* pCryptoHandler = objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler;
|
| - if (pCryptoHandler == NULL) {
|
| - GetNextWord();
|
| - if (m_WordSize < 9 || FXSYS_memcmp32(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;
|
| - }
|
| - FX_BYTE 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;
|
| -#if defined(_FPDFAPI_MINI_) && !defined(_FXCORE_FEATURE_ALL_)
|
| - pStream = FX_NEW CPDF_Stream(m_pFileAccess, pCryptoHandler, m_HeaderOffset + m_Pos, len, pDict, gennum);
|
| - m_Pos += len;
|
| -#else
|
| - FX_LPBYTE pData = FX_Alloc(FX_BYTE, len);
|
| - if (!pData) {
|
| - return NULL;
|
| - }
|
| - ReadBlock(pData, len);
|
| - if (pCryptoHandler) {
|
| - CFX_BinaryBuf dest_buf;
|
| - dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len));
|
| - FX_LPVOID 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 = FX_NEW CPDF_Stream(pData, len, pDict);
|
| -#endif
|
| - if (pContext) {
|
| - pContext->m_DataEnd = pContext->m_DataStart + len;
|
| - }
|
| - StreamStartPos = m_Pos;
|
| - GetNextWord();
|
| - if (m_WordSize == 6 && 0 == FXSYS_memcmp32(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(FX_BYTE, 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_INT32 CPDF_SyntaxParser::GetDirectNum()
|
| -{
|
| - GetNextWord();
|
| - if (!m_bIsNumber) {
|
| - return 0;
|
| - }
|
| - m_WordBuffer[m_WordSize] = 0;
|
| - return FXSYS_atoi((FX_LPCSTR)m_WordBuffer);
|
| -}
|
| -FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit, FX_LPCBYTE tag, FX_DWORD taglen)
|
| -{
|
| - FX_BYTE 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';
|
| - FX_BYTE ch;
|
| - if (bCheckRight && startpos + (FX_INT32)taglen <= limit && GetCharAt(startpos + (FX_INT32)taglen, ch)) {
|
| - FX_BYTE type = _PDF_CharType[ch];
|
| - if (type == 'N' || type == 'R') {
|
| - return FALSE;
|
| - }
|
| - }
|
| - if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
|
| - FX_BYTE type = _PDF_CharType[ch];
|
| - if (type == 'N' || type == 'R') {
|
| - return FALSE;
|
| - }
|
| - }
|
| - return TRUE;
|
| -}
|
| -FX_BOOL CPDF_SyntaxParser::SearchWord(FX_BSTR tag, FX_BOOL bWholeWord, FX_BOOL bForward, FX_FILESIZE limit)
|
| -{
|
| - FX_INT32 taglen = tag.GetLength();
|
| - if (taglen == 0) {
|
| - return FALSE;
|
| - }
|
| - FX_FILESIZE pos = m_Pos;
|
| - FX_INT32 offset = 0;
|
| - if (!bForward) {
|
| - offset = taglen - 1;
|
| - }
|
| - FX_LPCBYTE tag_data = tag;
|
| - FX_BYTE 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, 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 {
|
| - FX_LPCBYTE m_pTag;
|
| - FX_DWORD m_Len;
|
| - FX_DWORD m_Offset;
|
| -};
|
| -FX_INT32 CPDF_SyntaxParser::SearchMultiWord(FX_BSTR tags, FX_BOOL bWholeWord, FX_FILESIZE limit)
|
| -{
|
| - FX_INT32 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;
|
| - FX_BYTE byte;
|
| - GetCharAt(pos++, byte);
|
| - FX_INT32 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(FX_BSTR tag, FX_FILESIZE limit)
|
| -{
|
| - FX_INT32 taglen = tag.GetLength();
|
| - FX_INT32 match = 0;
|
| - limit += m_Pos;
|
| - FX_FILESIZE startpos = m_Pos;
|
| - while (1) {
|
| - FX_BYTE 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(FX_BYTE* buffer, FX_DWORD size)
|
| -{
|
| - FX_DWORD offset = 0;
|
| - FX_BYTE ch;
|
| - while (1) {
|
| - if (!GetNextChar(ch)) {
|
| - return;
|
| - }
|
| - buffer[offset++] = ch;
|
| - if (offset == size) {
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead)
|
| -{
|
| - m_pFileAvail = pFileAvail;
|
| - m_pFileRead = 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_bMainXRefLoad = 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();
|
| - }
|
| - if (m_pageMapCheckState) {
|
| - delete m_pageMapCheckState;
|
| - }
|
| - if (m_pagesLoadState) {
|
| - delete m_pagesLoadState;
|
| - }
|
| - FX_INT32 i = 0;
|
| - FX_INT32 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;
|
| -}
|
| -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;
|
| - }
|
| - FX_LPVOID 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);
|
| - }
|
| - 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;
|
| - FX_INT32 i = 0;
|
| - for (i = 0; i < obj_array.GetSize(); i++) {
|
| - CPDF_Object *pObj = (CPDF_Object *)obj_array[i];
|
| - if (!pObj) {
|
| - continue;
|
| - }
|
| - FX_INT32 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);
|
| - base::CheckedNumeric<FX_DWORD> size = original_size;
|
| - if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) {
|
| - break;
|
| - }
|
| -
|
| - size += offset;
|
| - size += 512;
|
| - if (!size.IsValid()) {
|
| - break;
|
| - }
|
| - if (size.ValueOrDie() > m_dwFileLen) {
|
| - size = m_dwFileLen - offset;
|
| - } else {
|
| - size = original_size + 512;
|
| - }
|
| - if (!size.IsValid()) {
|
| - 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) {
|
| - FX_INT32 iSize = new_obj_array.GetSize();
|
| - for (i = 0; i < iSize; ++i) {
|
| - CPDF_Object *pObj = (CPDF_Object *)new_obj_array[i];
|
| - FX_INT32 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;
|
| + if (type != 'N') {
|
| + m_bIsNumber = 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;
|
| - }
|
| + if (!GetNextChar(ch)) {
|
| + return;
|
| }
|
| - while (!m_bDocAvail) {
|
| - if (!CheckDocStatus(pHints)) {
|
| - return FALSE;
|
| - }
|
| + type = _PDF_CharType[ch];
|
| + if (type == 'D' || type == 'W') {
|
| + m_Pos--;
|
| + break;
|
| }
|
| - 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;
|
| - } else {
|
| - CFX_PtrArray new_objs_array;
|
| - FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
|
| - if (bRet) {
|
| - FX_INT32 iSize = m_arrayAcroforms.GetSize();
|
| - for (FX_INT32 i = 0; i < iSize; ++i) {
|
| - ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release();
|
| - }
|
| - m_arrayAcroforms.RemoveAll();
|
| +CFX_ByteString CPDF_SyntaxParser::ReadString() {
|
| + FX_BYTE ch;
|
| + if (!GetNextChar(ch)) {
|
| + return CFX_ByteString();
|
| + }
|
| + CFX_ByteTextBuf buf;
|
| + FX_INT32 parlevel = 0;
|
| + FX_INT32 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 {
|
| - m_objs_array.RemoveAll();
|
| - m_objs_array.Append(new_objs_array);
|
| + 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;
|
| }
|
| - return bRet;
|
| + break;
|
| + case 4:
|
| + status = 0;
|
| + if (ch != '\n') {
|
| + continue;
|
| + }
|
| + break;
|
| + }
|
| + if (!GetNextChar(ch)) {
|
| + break;
|
| }
|
| + }
|
| + GetNextChar(ch);
|
| + return buf.GetByteString();
|
| }
|
| -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;
|
| +CFX_ByteString CPDF_SyntaxParser::ReadHexString() {
|
| + FX_BYTE ch;
|
| + if (!GetNextChar(ch)) {
|
| + return CFX_ByteString();
|
| + }
|
| + CFX_BinaryBuf buf;
|
| + FX_BOOL bFirst = TRUE;
|
| + FX_BYTE code = 0;
|
| + while (1) {
|
| + if (ch == '>') {
|
| + break;
|
| + }
|
| + if (ch >= '0' && ch <= '9') {
|
| + if (bFirst) {
|
| + code = (ch - '0') * 16;
|
| + } else {
|
| + code += ch - '0';
|
| + buf.AppendByte((FX_BYTE)code);
|
| + }
|
| + bFirst = !bFirst;
|
| + } else if (ch >= 'A' && ch <= 'F') {
|
| + if (bFirst) {
|
| + code = (ch - 'A' + 10) * 16;
|
| + } else {
|
| + code += ch - 'A' + 10;
|
| + buf.AppendByte((FX_BYTE)code);
|
| + }
|
| + bFirst = !bFirst;
|
| + } else if (ch >= 'a' && ch <= 'f') {
|
| + if (bFirst) {
|
| + code = (ch - 'a' + 10) * 16;
|
| + } else {
|
| + code += ch - 'a' + 10;
|
| + buf.AppendByte((FX_BYTE)code);
|
| + }
|
| + bFirst = !bFirst;
|
| }
|
| - if (!m_pAcroForm) {
|
| - if (m_docStatus == PDF_DATAAVAIL_ERROR) {
|
| - m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
|
| - return TRUE;
|
| - }
|
| - return FALSE;
|
| + if (!GetNextChar(ch)) {
|
| + break;
|
| }
|
| - m_arrayAcroforms.Add(m_pAcroForm);
|
| - m_docStatus = PDF_DATAAVAIL_PAGETREE;
|
| - return TRUE;
|
| + }
|
| + if (!bFirst) {
|
| + buf.AppendByte((FX_BYTE)code);
|
| + }
|
| + return buf.GetByteString();
|
| }
|
| -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);
|
| - } else {
|
| - return LoadDocPages(pHints);
|
| - }
|
| - case PDF_DATAAVAIL_PAGE:
|
| - if (m_bTotalLoadPageTree) {
|
| - return CheckPage(pHints);
|
| - } else {
|
| - 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;
|
| +void CPDF_SyntaxParser::ToNextLine() {
|
| + FX_BYTE ch;
|
| + while (1) {
|
| + if (!GetNextChar(ch)) {
|
| + return;
|
| }
|
| -}
|
| -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;
|
| + if (ch == '\n') {
|
| + return;
|
| }
|
| -}
|
| -FX_BOOL CPDF_DataAvail::LoadAllFile(IFX_DownloadHints* pHints)
|
| -{
|
| - if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) {
|
| - m_docStatus = PDF_DATAAVAIL_DONE;
|
| - return TRUE;
|
| + if (ch == '\r') {
|
| + GetNextChar(ch);
|
| + if (ch == '\n') {
|
| + return;
|
| + } else {
|
| + m_Pos--;
|
| + return;
|
| + }
|
| }
|
| - pHints->AddSegment(0, (FX_DWORD)m_dwFileLen);
|
| - return FALSE;
|
| + }
|
| }
|
| -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;
|
| +void CPDF_SyntaxParser::ToNextWord() {
|
| + FX_BYTE ch;
|
| + if (!GetNextChar(ch)) {
|
| + return;
|
| + }
|
| + FX_BYTE type = _PDF_CharType[ch];
|
| + while (1) {
|
| + while (type == 'W') {
|
| + m_dwWordPos = m_Pos;
|
| + if (!GetNextChar(ch)) {
|
| + return;
|
| + }
|
| + type = _PDF_CharType[ch];
|
| }
|
| - 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;
|
| + if (ch != '%') {
|
| + break;
|
| + }
|
| + while (1) {
|
| + if (!GetNextChar(ch)) {
|
| + return;
|
| + }
|
| + if (ch == '\r' || ch == '\n') {
|
| + break;
|
| + }
|
| + }
|
| + type = _PDF_CharType[ch];
|
| + }
|
| + m_Pos--;
|
| }
|
| -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;
|
| +CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber) {
|
| + GetNextWord();
|
| + bIsNumber = m_bIsNumber;
|
| + return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
|
| +}
|
| +CFX_ByteString CPDF_SyntaxParser::GetKeyword() {
|
| + GetNextWord();
|
| + return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
|
| +}
|
| +CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
|
| + FX_DWORD objnum,
|
| + FX_DWORD gennum,
|
| + FX_INT32 level,
|
| + PARSE_CONTEXT* pContext,
|
| + FX_BOOL bDecrypt) {
|
| + if (level > _PARSER_OBJECT_LEVLE_) {
|
| + 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;
|
| }
|
| -
|
| - if (m_pDocument == NULL) {
|
| - original_size = (FX_DWORD)m_parser.GetObjectSize(objnum);
|
| - offset = m_parser.GetObjectOffset(objnum);
|
| - pParser = &m_parser;
|
| + 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;
|
| + }
|
| + pRet = CPDF_Reference::Create(pObjList, objnum);
|
| + return pRet;
|
| + } else {
|
| + m_Pos = SavedPos;
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_NUMBER;
|
| + }
|
| + pRet = CPDF_Number::Create(word);
|
| + return pRet;
|
| + }
|
| } else {
|
| - original_size = GetObjectSize(objnum, offset);
|
| - pParser = (CPDF_Parser *)(m_pDocument->GetParser());
|
| + m_Pos = SavedPos;
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_NUMBER;
|
| + }
|
| + pRet = CPDF_Number::Create(word);
|
| + return pRet;
|
| + }
|
| + }
|
| + if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_BOOLEAN;
|
| }
|
| -
|
| - base::CheckedNumeric<FX_DWORD> size = original_size;
|
| - if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) {
|
| - if (pExistInFile)
|
| - *pExistInFile = FALSE;
|
| -
|
| - return NULL;
|
| + pRet = CPDF_Boolean::Create(word == FX_BSTRC("true"));
|
| + return pRet;
|
| + }
|
| + if (word == FX_BSTRC("null")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_NULL;
|
| }
|
| -
|
| - size += offset;
|
| - size += 512;
|
| - if (!size.IsValid()) {
|
| - return NULL;
|
| + pRet = CPDF_Null::Create();
|
| + return pRet;
|
| + }
|
| + if (word == FX_BSTRC("(")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_STRING;
|
| }
|
| -
|
| - if (size.ValueOrDie() > m_dwFileLen) {
|
| - size = m_dwFileLen - offset;
|
| - } else {
|
| - size = original_size + 512;
|
| + CFX_ByteString str = ReadString();
|
| + if (m_pCryptoHandler && bDecrypt) {
|
| + m_pCryptoHandler->Decrypt(objnum, gennum, str);
|
| }
|
| -
|
| - if (!size.IsValid()) {
|
| - return NULL;
|
| + pRet = CPDF_String::Create(str, FALSE);
|
| + return pRet;
|
| + }
|
| + if (word == FX_BSTRC("<")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_STRING;
|
| }
|
| -
|
| - if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
|
| - pHints->AddSegment(offset, size.ValueOrDie());
|
| - return NULL;
|
| + CFX_ByteString str = ReadHexString();
|
| + if (m_pCryptoHandler && bDecrypt) {
|
| + m_pCryptoHandler->Decrypt(objnum, gennum, str);
|
| }
|
| -
|
| - if (pParser) {
|
| - pRet = pParser->ParseIndirectObject(NULL, objnum, NULL);
|
| + pRet = CPDF_String::Create(str, TRUE);
|
| + return pRet;
|
| + }
|
| + if (word == FX_BSTRC("[")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_ARRAY;
|
| }
|
| -
|
| - if (!pRet && pExistInFile) {
|
| - *pExistInFile = FALSE;
|
| + CPDF_Array* pArray = CPDF_Array::Create();
|
| + while (1) {
|
| + CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
|
| + 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;
|
| -}
|
| -
|
| -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;
|
| + }
|
| + if (word == FX_BSTRC("<<")) {
|
| + FX_FILESIZE saveDictOffset = m_Pos - 2;
|
| + FX_DWORD dwDictSize = 0;
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_DICTIONARY;
|
| + }
|
| + if (pContext) {
|
| + pContext->m_DictStart = SavedPos;
|
| + }
|
| + CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
|
| + FX_INT32 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(">>")) {
|
| + dwDictSize = m_Pos - saveDictOffset;
|
| + break;
|
| + }
|
| + if (key == FX_BSTRC("endobj")) {
|
| + dwDictSize = m_Pos - 6 - saveDictOffset;
|
| + 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, level + 1);
|
| + if (pObj == NULL) {
|
| + continue;
|
| + }
|
| + if (key.GetLength() == 1) {
|
| + pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1),
|
| + pObj);
|
| + } else {
|
| + if (nKeys < 32) {
|
| + pDict->SetAt(
|
| + CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
|
| } else {
|
| - m_docStatus = PDF_DATAAVAIL_PAGETREE;
|
| + pDict->AddValue(
|
| + CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
|
| }
|
| - 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 (IsSignatureDict(pDict)) {
|
| + FX_FILESIZE dwSavePos = m_Pos;
|
| + m_Pos = dwSignValuePos;
|
| + CPDF_Object* pObj =
|
| + GetObject(pObjList, objnum, gennum, level + 1, NULL, FALSE);
|
| + pDict->SetAt(FX_BSTRC("Contents"), pObj);
|
| + m_Pos = dwSavePos;
|
| }
|
| - if (pInfo) {
|
| - pInfo->Release();
|
| + if (pContext) {
|
| + pContext->m_DictEnd = m_Pos;
|
| + if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
|
| + return pDict;
|
| + }
|
| }
|
| - if (m_bHaveAcroForm) {
|
| - m_docStatus = PDF_DATAAVAIL_ACROFORM;
|
| + 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_docStatus = PDF_DATAAVAIL_PAGETREE;
|
| + m_Pos = SavedPos;
|
| + return pDict;
|
| }
|
| - return TRUE;
|
| + }
|
| + if (word == FX_BSTRC(">>")) {
|
| + m_Pos = SavedPos;
|
| + return NULL;
|
| + }
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_INVALID;
|
| + }
|
| + return NULL;
|
| }
|
| -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;
|
| +CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(
|
| + CPDF_IndirectObjects* pObjList,
|
| + FX_DWORD objnum,
|
| + FX_DWORD gennum,
|
| + FX_INT32 level,
|
| + struct PARSE_CONTEXT* pContext) {
|
| + if (level > _PARSER_OBJECT_LEVLE_) {
|
| + 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 (!m_pRoot) {
|
| - if (m_docStatus == PDF_DATAAVAIL_ERROR) {
|
| - m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
|
| - return TRUE;
|
| + 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 FALSE;
|
| - }
|
| - CPDF_Reference* pRef = (CPDF_Reference*)m_pRoot->GetDict()->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 CPDF_Reference::Create(pObjList, objnum);
|
| + } else {
|
| + m_Pos = SavedPos;
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_NUMBER;
|
| }
|
| + return CPDF_Number::Create(word);
|
| + }
|
| + } else {
|
| + 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 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 = FX_NEW CFX_CMapDWordToDWord();
|
| - }
|
| - FX_DWORD dwValue = 0;
|
| - if (!m_pageMapCheckState->Lookup(iPage, dwValue)) {
|
| - m_pageMapCheckState->SetAt(iPage, 1);
|
| - return TRUE;
|
| + return CPDF_Boolean::Create(word == FX_BSTRC("true"));
|
| + }
|
| + if (word == FX_BSTRC("null")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_NULL;
|
| }
|
| - if (dwValue != 0) {
|
| - return FALSE;
|
| + return CPDF_Null::Create();
|
| + }
|
| + if (word == FX_BSTRC("(")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_STRING;
|
| }
|
| - m_pageMapCheckState->SetAt(iPage, 1);
|
| - return TRUE;
|
| -}
|
| -void CPDF_DataAvail::ResetFirstCheck(int iPage)
|
| -{
|
| - if (NULL == m_pageMapCheckState) {
|
| - m_pageMapCheckState = FX_NEW CFX_CMapDWordToDWord();
|
| + CFX_ByteString str = ReadString();
|
| + if (m_pCryptoHandler) {
|
| + m_pCryptoHandler->Decrypt(objnum, gennum, str);
|
| }
|
| - FX_DWORD dwValue = 1;
|
| - if (!m_pageMapCheckState->Lookup(iPage, dwValue)) {
|
| - return;
|
| + return CPDF_String::Create(str, FALSE);
|
| + }
|
| + if (word == FX_BSTRC("<")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_STRING;
|
| }
|
| - 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) {
|
| - FX_INT32 iSize = pArray->GetCount();
|
| - CPDF_Object *pItem = NULL;
|
| - for (FX_INT32 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();
|
| + CFX_ByteString str = ReadHexString();
|
| + if (m_pCryptoHandler) {
|
| + m_pCryptoHandler->Decrypt(objnum, gennum, str);
|
| }
|
| - m_PageObjList.RemoveAll();
|
| - if (UnavailObjList.GetSize()) {
|
| - m_PageObjList.Append(UnavailObjList);
|
| - return FALSE;
|
| + return CPDF_String::Create(str, TRUE);
|
| + }
|
| + if (word == FX_BSTRC("[")) {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_ARRAY;
|
| }
|
| - 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;
|
| + CPDF_Array* pArray = CPDF_Array::Create();
|
| + while (1) {
|
| + CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
|
| + if (pObj == NULL) {
|
| + if (m_WordBuffer[0] == ']') {
|
| + return pArray;
|
| }
|
| - pPages->Release();
|
| + if (pArray)
|
| + pArray->Release();
|
| + return NULL;
|
| + }
|
| + pArray->Add(pObj);
|
| }
|
| - m_PagesArray.RemoveAll();
|
| - if (!m_PageObjList.GetSize()) {
|
| - m_docStatus = PDF_DATAAVAIL_DONE;
|
| + }
|
| + if (word[0] == '/') {
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_NAME;
|
| }
|
| - return TRUE;
|
| -}
|
| -FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser *pParser, CPDF_Object *pPages)
|
| -{
|
| - if (!pParser) {
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| - 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;
|
| }
|
| - CPDF_Dictionary* pDict = pPages->GetDict();
|
| - CPDF_Object *pKids = pDict ? pDict->GetElement(FX_BSTRC("Kids")) : NULL;
|
| - if (!pKids) {
|
| - return TRUE;
|
| + if (pContext) {
|
| + pContext->m_DictStart = SavedPos;
|
| }
|
| - switch (pKids->GetType()) {
|
| - case PDFOBJ_REFERENCE: {
|
| - CPDF_Reference *pKid = (CPDF_Reference *)pKids;
|
| - m_PageObjList.Add(pKid->GetRefObjNum());
|
| - }
|
| + 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, level + 1);
|
| + if (pObj == NULL) {
|
| + if (pDict)
|
| + pDict->Release();
|
| + FX_BYTE ch;
|
| + while (1) {
|
| + if (!GetNextChar(ch)) {
|
| 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());
|
| - }
|
| - }
|
| - }
|
| + }
|
| + if (ch == 0x0A || ch == 0x0D) {
|
| break;
|
| - default:
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| - return FALSE;
|
| - }
|
| - 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;
|
| - }
|
| - 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;
|
| -}
|
| -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)) {
|
| - FX_BYTE 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);
|
| - return FALSE;
|
| -}
|
| -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;
|
| + return NULL;
|
| + }
|
| + if (key.GetLength() == 1) {
|
| + pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1),
|
| + pObj);
|
| + } else {
|
| + pDict->AddValue(
|
| + CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
|
| + }
|
| }
|
| - 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;
|
| - }
|
| - FX_INT32 iStartPos = (FX_INT32)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen);
|
| - FX_INT32 iSize = dwEnd > 1024 ? dwEnd - 1024 : 0;
|
| - if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) {
|
| - pHints->AddSegment(iStartPos, iSize);
|
| - bNeedDownLoad = TRUE;
|
| - }
|
| + if (pContext) {
|
| + pContext->m_DictEnd = m_Pos;
|
| + if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
|
| + return pDict;
|
| + }
|
| }
|
| - 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);
|
| - }
|
| + 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_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
|
| - }
|
| - if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
|
| - m_docStatus = PDF_DATAAVAIL_DONE;
|
| - return TRUE;
|
| + m_Pos = SavedPos;
|
| + return pDict;
|
| }
|
| - m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
|
| - return FALSE;
|
| + }
|
| + if (word == FX_BSTRC(">>")) {
|
| + m_Pos = SavedPos;
|
| + return NULL;
|
| + }
|
| + if (bTypeOnly) {
|
| + return (CPDF_Object*)PDFOBJ_INVALID;
|
| + }
|
| + return NULL;
|
| }
|
| -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 real_objnum = FXSYS_atoi(word);
|
| - if (objnum && real_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_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;
|
| + }
|
| +
|
| + base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
|
| + pos += len;
|
| + if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
|
| + m_Pos = pos.ValueOrDie();
|
| + } else {
|
| + return NULL;
|
| + }
|
| +
|
| + CPDF_CryptoHandler* pCryptoHandler =
|
| + objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler;
|
| + if (pCryptoHandler == NULL) {
|
| + GetNextWord();
|
| + if (m_WordSize < 9 || FXSYS_memcmp32(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;
|
| + }
|
| + FX_BYTE 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;
|
| + }
|
| + }
|
| }
|
| - CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0);
|
| - m_syntaxParser.RestorePos(SavedPos);
|
| - return pObj;
|
| + }
|
| + m_Pos = StreamStartPos;
|
| + CPDF_Stream* pStream;
|
| +#if defined(_FPDFAPI_MINI_) && !defined(_FXCORE_FEATURE_ALL_)
|
| + pStream = FX_NEW CPDF_Stream(m_pFileAccess,
|
| + pCryptoHandler,
|
| + m_HeaderOffset + m_Pos,
|
| + len,
|
| + pDict,
|
| + gennum);
|
| + m_Pos += len;
|
| +#else
|
| + FX_LPBYTE pData = FX_Alloc(FX_BYTE, len);
|
| + if (!pData) {
|
| + return NULL;
|
| + }
|
| + ReadBlock(pData, len);
|
| + if (pCryptoHandler) {
|
| + CFX_BinaryBuf dest_buf;
|
| + dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len));
|
| + FX_LPVOID 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 = FX_NEW CPDF_Stream(pData, len, pDict);
|
| +#endif
|
| + if (pContext) {
|
| + pContext->m_DataEnd = pContext->m_DataStart + len;
|
| + }
|
| + StreamStartPos = m_Pos;
|
| + GetNextWord();
|
| + if (m_WordSize == 6 && 0 == FXSYS_memcmp32(m_WordBuffer, "endobj", 6)) {
|
| + m_Pos = StreamStartPos;
|
| + }
|
| + return pStream;
|
| }
|
| -FX_INT32 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;
|
| +void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess,
|
| + FX_DWORD HeaderOffset) {
|
| + if (m_pFileBuf) {
|
| + FX_Free(m_pFileBuf);
|
| + m_pFileBuf = NULL;
|
| + }
|
| + m_pFileBuf = FX_Alloc(FX_BYTE, 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_INT32 CPDF_SyntaxParser::GetDirectNum() {
|
| + GetNextWord();
|
| + if (!m_bIsNumber) {
|
| + return 0;
|
| + }
|
| + m_WordBuffer[m_WordSize] = 0;
|
| + return FXSYS_atoi((FX_LPCSTR)m_WordBuffer);
|
| +}
|
| +FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos,
|
| + FX_FILESIZE limit,
|
| + FX_LPCBYTE tag,
|
| + FX_DWORD taglen) {
|
| + FX_BYTE 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';
|
| + FX_BYTE ch;
|
| + if (bCheckRight && startpos + (FX_INT32)taglen <= limit &&
|
| + GetCharAt(startpos + (FX_INT32)taglen, ch)) {
|
| + FX_BYTE type = _PDF_CharType[ch];
|
| + if (type == 'N' || type == 'R') {
|
| + return FALSE;
|
| }
|
| - FX_BYTE buffer[1024];
|
| - m_pFileRead->ReadBlock(buffer, 0, req_size);
|
| - if (IsLinearizedFile(buffer, req_size)) {
|
| - return PDF_IS_LINEARIZED;
|
| + }
|
| + if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
|
| + FX_BYTE type = _PDF_CharType[ch];
|
| + if (type == 'N' || type == 'R') {
|
| + return FALSE;
|
| }
|
| - return PDF_NOT_LINEARIZED;
|
| + }
|
| + return TRUE;
|
| }
|
| -FX_BOOL CPDF_DataAvail::IsLinearizedFile(FX_LPBYTE pData, FX_DWORD dwLen)
|
| -{
|
| - CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE));
|
| - FX_INT32 offset = GetHeaderOffset((IFX_FileStream*)file);
|
| - if (offset == -1) {
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| +FX_BOOL CPDF_SyntaxParser::SearchWord(FX_BSTR tag,
|
| + FX_BOOL bWholeWord,
|
| + FX_BOOL bForward,
|
| + FX_FILESIZE limit) {
|
| + FX_INT32 taglen = tag.GetLength();
|
| + if (taglen == 0) {
|
| + return FALSE;
|
| + }
|
| + FX_FILESIZE pos = m_Pos;
|
| + FX_INT32 offset = 0;
|
| + if (!bForward) {
|
| + offset = taglen - 1;
|
| + }
|
| + FX_LPCBYTE tag_data = tag;
|
| + FX_BYTE byte;
|
| + while (1) {
|
| + if (bForward) {
|
| + if (limit) {
|
| + if (pos >= m_Pos + limit) {
|
| + return FALSE;
|
| + }
|
| + }
|
| + if (!GetCharAt(pos, byte)) {
|
| return FALSE;
|
| - }
|
| - m_dwHeaderOffset = offset;
|
| - m_syntaxParser.InitParser((IFX_FileStream*)file, offset);
|
| - m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9);
|
| - FX_BOOL bNumber = FALSE;
|
| - CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(bNumber);
|
| - if (!bNumber) {
|
| + }
|
| + } 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, taglen)) {
|
| + m_Pos = startpos;
|
| + return TRUE;
|
| + }
|
| }
|
| - 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 (bForward) {
|
| + offset = byte == tag_data[0] ? 1 : 0;
|
| + pos++;
|
| + } else {
|
| + offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1;
|
| + pos--;
|
| }
|
| - 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;
|
| + if (pos < 0) {
|
| + return FALSE;
|
| }
|
| - return FALSE;
|
| + }
|
| + 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)) {
|
| - FX_BYTE buffer[1024];
|
| - m_pFileRead->ReadBlock(buffer, req_pos, dwSize);
|
| - CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE));
|
| - m_syntaxParser.InitParser((IFX_FileStream*)file, 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;
|
| +struct _SearchTagRecord {
|
| + FX_LPCBYTE m_pTag;
|
| + FX_DWORD m_Len;
|
| + FX_DWORD m_Offset;
|
| +};
|
| +FX_INT32 CPDF_SyntaxParser::SearchMultiWord(FX_BSTR tags,
|
| + FX_BOOL bWholeWord,
|
| + FX_FILESIZE limit) {
|
| + FX_INT32 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;
|
| + FX_BYTE byte;
|
| + GetCharAt(pos++, byte);
|
| + FX_INT32 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;
|
| }
|
| - m_dwLastXRefOffset = m_dwXRefOffset;
|
| - SetStartOffset(m_dwXRefOffset);
|
| - m_docStatus = PDF_DATAAVAIL_CROSSREF;
|
| - return TRUE;
|
| + }
|
| + }
|
| + } else {
|
| + if (pPatterns[i].m_pTag[0] == byte) {
|
| + pPatterns[i].m_Offset = 1;
|
| } else {
|
| - m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
|
| - return TRUE;
|
| + pPatterns[i].m_Offset = 0;
|
| }
|
| + }
|
| }
|
| - pHints->AddSegment(req_pos, dwSize);
|
| - return FALSE;
|
| -}
|
| -FX_DWORD 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)) {
|
| - FX_INT32 iSize = (FX_INT32)(m_Pos + req_size - m_dwCurrentXRefSteam);
|
| - CFX_BinaryBuf buf(iSize);
|
| - FX_LPBYTE pBuf = buf.GetBuffer();
|
| - m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize);
|
| - CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
|
| - m_parser.m_Syntax.InitParser((IFX_FileStream*)file, 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;
|
| - } else {
|
| - pObj->Release();
|
| - return -1;
|
| - }
|
| - }
|
| - pObj->Release();
|
| - return -1;
|
| + if (limit && pos >= m_Pos + limit) {
|
| + goto end;
|
| }
|
| - pHints->AddSegment(m_Pos, req_size);
|
| - return 0;
|
| -}
|
| -inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset)
|
| -{
|
| - m_Pos = dwOffset;
|
| + if (!GetCharAt(pos, byte)) {
|
| + goto end;
|
| + }
|
| + pos++;
|
| + }
|
| +end:
|
| + FX_Free(pPatterns);
|
| + return found;
|
| }
|
| -#define MAX_WORD_BUFFER 256
|
| -FX_BOOL CPDF_DataAvail::GetNextToken(CFX_ByteString &token)
|
| -{
|
| - m_WordSize = 0;
|
| +FX_FILESIZE CPDF_SyntaxParser::FindTag(FX_BSTR tag, FX_FILESIZE limit) {
|
| + FX_INT32 taglen = tag.GetLength();
|
| + FX_INT32 match = 0;
|
| + limit += m_Pos;
|
| + FX_FILESIZE startpos = m_Pos;
|
| + while (1) {
|
| FX_BYTE ch;
|
| if (!GetNextChar(ch)) {
|
| - return FALSE;
|
| + return -1;
|
| }
|
| - FX_BYTE 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 (ch == tag[match]) {
|
| + match++;
|
| + if (match == taglen) {
|
| + return m_Pos - startpos - taglen;
|
| + }
|
| + } else {
|
| + match = ch == tag[0] ? 1 : 0;
|
| }
|
| - 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;
|
| + if (limit && m_Pos == limit) {
|
| + return -1;
|
| }
|
| - 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;
|
| - }
|
| + }
|
| + return -1;
|
| +}
|
| +void CPDF_SyntaxParser::GetBinary(FX_BYTE* buffer, FX_DWORD size) {
|
| + FX_DWORD offset = 0;
|
| + FX_BYTE ch;
|
| + while (1) {
|
| + if (!GetNextChar(ch)) {
|
| + return;
|
| }
|
| - CFX_ByteString ret(m_WordBuffer, m_WordSize);
|
| - token = ret;
|
| - return TRUE;
|
| + buffer[offset++] = ch;
|
| + if (offset == size) {
|
| + break;
|
| + }
|
| + }
|
| }
|
| -FX_BOOL CPDF_DataAvail::GetNextChar(FX_BYTE &ch)
|
| -{
|
| - FX_FILESIZE pos = m_Pos;
|
| - if (pos >= m_dwFileLen) {
|
| - return FALSE;
|
| +CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail,
|
| + IFX_FileRead* pFileRead) {
|
| + m_pFileAvail = pFileAvail;
|
| + m_pFileRead = 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_bMainXRefLoad = 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();
|
| + }
|
| + if (m_pageMapCheckState) {
|
| + delete m_pageMapCheckState;
|
| + }
|
| + if (m_pagesLoadState) {
|
| + delete m_pagesLoadState;
|
| + }
|
| + FX_INT32 i = 0;
|
| + FX_INT32 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;
|
| +}
|
| +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;
|
| + }
|
| + FX_LPVOID pResult = FXSYS_bsearch(&offset,
|
| + pParser->m_SortedOffset.GetData(),
|
| + pParser->m_SortedOffset.GetSize(),
|
| + sizeof(FX_FILESIZE),
|
| + _CompareFileSize);
|
| + if (pResult == NULL) {
|
| + return 0;
|
| }
|
| - 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;
|
| + if ((FX_FILESIZE*)pResult -
|
| + (FX_FILESIZE*)pParser->m_SortedOffset.GetData() ==
|
| + pParser->m_SortedOffset.GetSize() - 1) {
|
| + return 0;
|
| }
|
| - ch = m_bufferData[pos - m_bufferOffset];
|
| - m_Pos ++;
|
| - return TRUE;
|
| + return (FX_DWORD)(((FX_FILESIZE*)pResult)[1] - offset);
|
| + }
|
| + return 0;
|
| }
|
| -FX_BOOL CPDF_DataAvail::CheckCrossRefItem(IFX_DownloadHints *pHints)
|
| -{
|
| - FX_INT32 iSize = 0;
|
| - CFX_ByteString token;
|
| - while (1) {
|
| - if (!GetNextToken(token)) {
|
| - iSize = (FX_INT32)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
|
| - pHints->AddSegment(m_Pos, iSize);
|
| - return FALSE;
|
| +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;
|
| + FX_INT32 i = 0;
|
| + for (i = 0; i < obj_array.GetSize(); i++) {
|
| + CPDF_Object* pObj = (CPDF_Object*)obj_array[i];
|
| + if (!pObj) {
|
| + continue;
|
| + }
|
| + FX_INT32 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);
|
| + base::CheckedNumeric<FX_DWORD> size = original_size;
|
| + if (size.ValueOrDefault(0) == 0 || offset < 0 ||
|
| + offset >= m_dwFileLen) {
|
| + break;
|
| }
|
| - if (token == "trailer") {
|
| - m_dwTrailerOffset = m_Pos;
|
| - m_docStatus = PDF_DATAAVAIL_TRAILER;
|
| - return TRUE;
|
| +
|
| + size += offset;
|
| + size += 512;
|
| + if (!size.IsValid()) {
|
| + break;
|
| }
|
| - }
|
| -}
|
| -FX_BOOL CPDF_DataAvail::CheckAllCrossRefStream(IFX_DownloadHints *pHints)
|
| -{
|
| - FX_FILESIZE xref_offset = 0;
|
| - FX_DWORD dwRet = CheckCrossRefStream(pHints, xref_offset);
|
| - if (dwRet == 1) {
|
| - if (!xref_offset) {
|
| - m_docStatus = PDF_DATAAVAIL_LOADALLCRSOSSREF;
|
| + if (size.ValueOrDie() > m_dwFileLen) {
|
| + size = m_dwFileLen - offset;
|
| } else {
|
| - m_dwCurrentXRefSteam = xref_offset;
|
| - m_Pos = xref_offset;
|
| - }
|
| - return TRUE;
|
| - } else if (dwRet == -1) {
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + 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) {
|
| + FX_INT32 iSize = new_obj_array.GetSize();
|
| + for (i = 0; i < iSize; ++i) {
|
| + CPDF_Object* pObj = (CPDF_Object*)new_obj_array[i];
|
| + FX_INT32 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);
|
| }
|
| -FX_BOOL CPDF_DataAvail::CheckCrossRef(IFX_DownloadHints* pHints)
|
| -{
|
| - FX_INT32 iSize = 0;
|
| - CFX_ByteString token;
|
| - if (!GetNextToken(token)) {
|
| - iSize = (FX_INT32)(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 = (FX_INT32)(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;
|
| - }
|
| - }
|
| +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;
|
| + } else {
|
| + CFX_PtrArray new_objs_array;
|
| + FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
|
| + if (bRet) {
|
| + FX_INT32 iSize = m_arrayAcroforms.GetSize();
|
| + for (FX_INT32 i = 0; i < iSize; ++i) {
|
| + ((CPDF_Object*)m_arrayAcroforms.GetAt(i))->Release();
|
| + }
|
| + m_arrayAcroforms.RemoveAll();
|
| } else {
|
| - m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
|
| - return TRUE;
|
| + m_objs_array.RemoveAll();
|
| + m_objs_array.Append(new_objs_array);
|
| }
|
| - return FALSE;
|
| + return bRet;
|
| + }
|
| }
|
| -FX_BOOL CPDF_DataAvail::CheckTrailerAppend(IFX_DownloadHints* pHints)
|
| -{
|
| - if (m_Pos < m_dwFileLen) {
|
| - FX_FILESIZE dwAppendPos = m_Pos + m_syntaxParser.SavePos();
|
| - FX_INT32 iSize = (FX_INT32)(dwAppendPos + 512 > m_dwFileLen ? m_dwFileLen - dwAppendPos : 512);
|
| - if (!m_pFileAvail->IsDataAvail(dwAppendPos, iSize)) {
|
| - pHints->AddSegment(dwAppendPos, iSize);
|
| - return FALSE;
|
| - }
|
| +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;
|
| }
|
| - if (m_dwPrevXRefOffset) {
|
| - SetStartOffset(m_dwPrevXRefOffset);
|
| - m_docStatus = PDF_DATAAVAIL_CROSSREF;
|
| + return FALSE;
|
| + }
|
| + m_arrayAcroforms.Add(m_pAcroForm);
|
| + 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);
|
| + } else {
|
| + return LoadDocPages(pHints);
|
| + }
|
| + case PDF_DATAAVAIL_PAGE:
|
| + if (m_bTotalLoadPageTree) {
|
| + return CheckPage(pHints);
|
| + } else {
|
| + 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::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::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::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 (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());
|
| + }
|
| +
|
| + base::CheckedNumeric<FX_DWORD> size = original_size;
|
| + if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) {
|
| + if (pExistInFile)
|
| + *pExistInFile = FALSE;
|
| +
|
| + return NULL;
|
| + }
|
| +
|
| + size += offset;
|
| + size += 512;
|
| + if (!size.IsValid()) {
|
| + return NULL;
|
| + }
|
| +
|
| + if (size.ValueOrDie() > m_dwFileLen) {
|
| + size = m_dwFileLen - offset;
|
| + } else {
|
| + size = original_size + 512;
|
| + }
|
| +
|
| + if (!size.IsValid()) {
|
| + return NULL;
|
| + }
|
| +
|
| + if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
|
| + pHints->AddSegment(offset, size.ValueOrDie());
|
| + return NULL;
|
| + }
|
| +
|
| + if (pParser) {
|
| + pRet = pParser->ParseIndirectObject(NULL, objnum, NULL);
|
| + }
|
| +
|
| + if (!pRet && pExistInFile) {
|
| + *pExistInFile = FALSE;
|
| + }
|
| +
|
| + 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_LOADALLCRSOSSREF;
|
| + m_docStatus = PDF_DATAAVAIL_PAGETREE;
|
| }
|
| return TRUE;
|
| -}
|
| -FX_BOOL CPDF_DataAvail::CheckTrailer(IFX_DownloadHints* pHints)
|
| -{
|
| - FX_INT32 iTrailerSize = (FX_INT32)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
|
| - if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) {
|
| - FX_INT32 iSize = (FX_INT32)(m_Pos + iTrailerSize - m_dwTrailerOffset);
|
| - CFX_BinaryBuf buf(iSize);
|
| - FX_LPBYTE pBuf = buf.GetBuffer();
|
| - if (!pBuf) {
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| - return FALSE;
|
| - }
|
| - if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) {
|
| - return FALSE;
|
| - }
|
| - CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
|
| - m_syntaxParser.InitParser((IFX_FileStream*)file, 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;
|
| - }
|
| - 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;
|
| - } else {
|
| - m_dwPrevXRefOffset = 0;
|
| - m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND;
|
| - pTrailer->Release();
|
| - }
|
| - 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;
|
| }
|
| - pHints->AddSegment(m_Pos, iTrailerSize);
|
| 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::CheckPage(FX_INT32 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_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_Reference* pRef =
|
| + (CPDF_Reference*)m_pRoot->GetDict()->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 = FX_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::CheckArrayPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints)
|
| -{
|
| +void CPDF_DataAvail::ResetFirstCheck(int iPage) {
|
| + if (NULL == m_pageMapCheckState) {
|
| + m_pageMapCheckState = FX_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(dwPageNo, pHints, &bExist);
|
| - if (!bExist) {
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| - return 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) {
|
| + FX_INT32 iSize = pArray->GetCount();
|
| + CPDF_Object* pItem = NULL;
|
| + for (FX_INT32 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_ERROR;
|
| - return FALSE;
|
| - }
|
| - return FALSE;
|
| + continue;
|
| }
|
| - if (pPages->GetType() != PDFOBJ_ARRAY) {
|
| + if (!GetPageKids(m_pCurrentParser, pPages)) {
|
| + pPages->Release();
|
| + while (++i < iPages) {
|
| + pPages = (CPDF_Object*)m_PagesArray.GetAt(i);
|
| pPages->Release();
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + }
|
| + 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 TRUE;
|
| +}
|
| +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::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;
|
| + }
|
| + 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;
|
| +}
|
| +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)) {
|
| + FX_BYTE 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;
|
| }
|
| - 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 = FX_NEW CPDF_PageNode();
|
| - pPageNode->m_childNode.Add(pNode);
|
| - pNode->m_dwPageNo = ((CPDF_Reference*)pKid)->GetRefObjNum();
|
| + return TRUE;
|
| + }
|
| + pHints->AddSegment(0, req_size);
|
| + return FALSE;
|
| +}
|
| +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;
|
| + }
|
| + FX_INT32 iStartPos = (FX_INT32)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen);
|
| + FX_INT32 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;
|
| +}
|
| +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 real_objnum = FXSYS_atoi(word);
|
| + if (objnum && real_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;
|
| +}
|
| +FX_INT32 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_BYTE 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(FX_LPBYTE pData, FX_DWORD dwLen) {
|
| + CFX_SmartPointer<IFX_FileStream> file(
|
| + FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE));
|
| + FX_INT32 offset = GetHeaderOffset((IFX_FileStream*)file);
|
| + if (offset == -1) {
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + return FALSE;
|
| + }
|
| + m_dwHeaderOffset = offset;
|
| + m_syntaxParser.InitParser((IFX_FileStream*)file, 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;
|
| + }
|
| + 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();
|
| }
|
| - pPages->Release();
|
| return TRUE;
|
| + }
|
| + 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) {
|
| +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)) {
|
| + FX_BYTE buffer[1024];
|
| + m_pFileRead->ReadBlock(buffer, req_pos, dwSize);
|
| + CFX_SmartPointer<IFX_FileStream> file(
|
| + FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE));
|
| + m_syntaxParser.InitParser((IFX_FileStream*)file, 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;
|
| - }
|
| - if (!pPage) {
|
| - if (m_docStatus == PDF_DATAAVAIL_ERROR) {
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| - return FALSE;
|
| - }
|
| - return FALSE;
|
| - }
|
| - if (pPage->GetType() == PDFOBJ_ARRAY) {
|
| - pPageNode->m_dwPageNo = dwPageNo;
|
| - pPageNode->m_type = PDF_PAGENODE_ARRAY;
|
| - pPage->Release();
|
| + }
|
| + 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;
|
| + } else {
|
| + m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
|
| + return TRUE;
|
| }
|
| - if (pPage->GetType() != PDFOBJ_DICTIONARY) {
|
| - pPage->Release();
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| - return FALSE;
|
| + }
|
| + pHints->AddSegment(req_pos, dwSize);
|
| + return FALSE;
|
| +}
|
| +FX_DWORD 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)) {
|
| + FX_INT32 iSize = (FX_INT32)(m_Pos + req_size - m_dwCurrentXRefSteam);
|
| + CFX_BinaryBuf buf(iSize);
|
| + FX_LPBYTE pBuf = buf.GetBuffer();
|
| + m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize);
|
| + CFX_SmartPointer<IFX_FileStream> file(
|
| + FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
|
| + m_parser.m_Syntax.InitParser((IFX_FileStream*)file, 0);
|
| + FX_BOOL bNumber = FALSE;
|
| + CFX_ByteString objnum = m_parser.m_Syntax.GetNextWord(bNumber);
|
| + if (!bNumber) {
|
| + return -1;
|
| }
|
| - 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 = FX_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 = FX_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;
|
| + 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;
|
| + } else {
|
| + pObj->Release();
|
| + return -1;
|
| + }
|
| }
|
| - pPage->Release();
|
| - return TRUE;
|
| + pObj->Release();
|
| + return -1;
|
| + }
|
| + pHints->AddSegment(m_Pos, req_size);
|
| + return 0;
|
| }
|
| -FX_BOOL CPDF_DataAvail::CheckPageNode(CPDF_PageNode &pageNodes, FX_INT32 iPage, FX_INT32 &iCount, IFX_DownloadHints* pHints)
|
| -{
|
| - FX_INT32 iSize = pageNodes.m_childNode.GetSize();
|
| - if (!iSize) {
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| +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;
|
| + FX_BYTE ch;
|
| + if (!GetNextChar(ch)) {
|
| + return FALSE;
|
| + }
|
| + FX_BYTE type = _PDF_CharType[ch];
|
| + while (1) {
|
| + while (type == 'W') {
|
| + if (!GetNextChar(ch)) {
|
| return FALSE;
|
| + }
|
| + type = _PDF_CharType[ch];
|
| }
|
| - for (FX_INT32 i = 0; i < iSize; ++i) {
|
| - CPDF_PageNode *pNode = (CPDF_PageNode*)pageNodes.m_childNode.GetAt(i);
|
| - if (!pNode) {
|
| - continue;
|
| + 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;
|
| }
|
| - 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;
|
| + type = _PDF_CharType[ch];
|
| + if (type != 'R' && type != 'N') {
|
| + m_Pos--;
|
| + CFX_ByteString ret(m_WordBuffer, m_WordSize);
|
| + token = ret;
|
| + return TRUE;
|
| }
|
| - if (iPage == iCount) {
|
| - m_docStatus = PDF_DATAAVAIL_DONE;
|
| - 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;
|
| -}
|
| -FX_BOOL CPDF_DataAvail::LoadDocPage(FX_INT32 iPage, IFX_DownloadHints* pHints)
|
| -{
|
| - if (m_pDocument->GetPageCount() <= iPage || m_pDocument->m_PageList.GetAt(iPage)) {
|
| - m_docStatus = PDF_DATAAVAIL_DONE;
|
| - return TRUE;
|
| + }
|
| + while (1) {
|
| + if (m_WordSize < MAX_WORD_BUFFER) {
|
| + m_WordBuffer[m_WordSize++] = ch;
|
| }
|
| - if (m_pageNodes.m_type == PDF_PAGENODE_PAGE) {
|
| - if (iPage == 0) {
|
| - m_docStatus = PDF_DATAAVAIL_DONE;
|
| - return TRUE;
|
| - }
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| - return TRUE;
|
| + if (!GetNextChar(ch)) {
|
| + return FALSE;
|
| + }
|
| + type = _PDF_CharType[ch];
|
| + if (type == 'D' || type == 'W') {
|
| + m_Pos--;
|
| + break;
|
| }
|
| - FX_INT32 iCount = -1;
|
| - return CheckPageNode(m_pageNodes, iPage, iCount, pHints);
|
| + }
|
| + CFX_ByteString ret(m_WordBuffer, m_WordSize);
|
| + token = ret;
|
| + return TRUE;
|
| }
|
| -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;
|
| +FX_BOOL CPDF_DataAvail::GetNextChar(FX_BYTE& 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) {
|
| + FX_INT32 iSize = 0;
|
| + CFX_ByteString token;
|
| + while (1) {
|
| + if (!GetNextToken(token)) {
|
| + iSize = (FX_INT32)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
|
| + pHints->AddSegment(m_Pos, iSize);
|
| + return FALSE;
|
| }
|
| - if (!pPages) {
|
| - return FALSE;
|
| + if (token == "trailer") {
|
| + m_dwTrailerOffset = m_Pos;
|
| + m_docStatus = PDF_DATAAVAIL_TRAILER;
|
| + return TRUE;
|
| }
|
| - CPDF_Dictionary* pPagesDict = pPages->GetDict();
|
| - if (!pPagesDict) {
|
| - pPages->Release();
|
| - m_docStatus = PDF_DATAAVAIL_ERROR;
|
| - return FALSE;
|
| + }
|
| +}
|
| +FX_BOOL CPDF_DataAvail::CheckAllCrossRefStream(IFX_DownloadHints* pHints) {
|
| + FX_FILESIZE xref_offset = 0;
|
| + FX_DWORD dwRet = CheckCrossRefStream(pHints, xref_offset);
|
| + if (dwRet == 1) {
|
| + if (!xref_offset) {
|
| + m_docStatus = PDF_DATAAVAIL_LOADALLCRSOSSREF;
|
| + } else {
|
| + m_dwCurrentXRefSteam = xref_offset;
|
| + m_Pos = xref_offset;
|
| }
|
| - if (!pPagesDict->KeyExist(FX_BSTRC("Kids"))) {
|
| - pPages->Release();
|
| + return TRUE;
|
| + } else if (dwRet == -1) {
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + }
|
| + return FALSE;
|
| +}
|
| +FX_BOOL CPDF_DataAvail::CheckCrossRef(IFX_DownloadHints* pHints) {
|
| + FX_INT32 iSize = 0;
|
| + CFX_ByteString token;
|
| + if (!GetNextToken(token)) {
|
| + iSize = (FX_INT32)(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 =
|
| + (FX_INT32)(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;
|
| + }
|
| }
|
| - int count = pPagesDict->GetInteger(FX_BSTRC("Count"));
|
| - if (count > 0) {
|
| - pPages->Release();
|
| + } 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();
|
| + FX_INT32 iSize = (FX_INT32)(
|
| + 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::CheckTrailer(IFX_DownloadHints* pHints) {
|
| + FX_INT32 iTrailerSize =
|
| + (FX_INT32)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
|
| + if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) {
|
| + FX_INT32 iSize = (FX_INT32)(m_Pos + iTrailerSize - m_dwTrailerOffset);
|
| + CFX_BinaryBuf buf(iSize);
|
| + FX_LPBYTE pBuf = buf.GetBuffer();
|
| + if (!pBuf) {
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + return FALSE;
|
| + }
|
| + if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) {
|
| + return FALSE;
|
| + }
|
| + CFX_SmartPointer<IFX_FileStream> file(
|
| + FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
|
| + m_syntaxParser.InitParser((IFX_FileStream*)file, 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;
|
| + }
|
| + 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;
|
| + } else {
|
| + m_dwPrevXRefOffset = 0;
|
| + m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND;
|
| + pTrailer->Release();
|
| }
|
| - pPages->Release();
|
| - return FALSE;
|
| + return TRUE;
|
| + }
|
| + pHints->AddSegment(m_Pos, iTrailerSize);
|
| + return FALSE;
|
| }
|
| -FX_BOOL CPDF_DataAvail::LoadDocPages(IFX_DownloadHints* pHints)
|
| -{
|
| - if (!CheckUnkownPageNode(m_PagesObjNum, &m_pageNodes, pHints)) {
|
| - return FALSE;
|
| - }
|
| - if (CheckPageCount(pHints)) {
|
| +FX_BOOL CPDF_DataAvail::CheckPage(FX_INT32 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;
|
| - } else {
|
| - 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;
|
| +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;
|
| }
|
| - m_pDocument->LoadPages();
|
| 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 = FX_NEW CPDF_PageNode();
|
| + pPageNode->m_childNode.Add(pNode);
|
| + pNode->m_dwPageNo = ((CPDF_Reference*)pKid)->GetRefObjNum();
|
| + }
|
| + pPages->Release();
|
| + return TRUE;
|
| }
|
| -FX_BOOL CPDF_DataAvail::CheckLinearizedData(IFX_DownloadHints* pHints)
|
| -{
|
| - if (m_bLinearedDataOK) {
|
| - 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;
|
| + }
|
| + if (!pPage) {
|
| + if (m_docStatus == PDF_DATAAVAIL_ERROR) {
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + return FALSE;
|
| }
|
| - if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset))) {
|
| - pHints->AddSegment(m_dwLastXRefOffset, (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset));
|
| - return FALSE;
|
| + 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;
|
| }
|
| - FX_DWORD dwRet = 0;
|
| - if (!m_bMainXRefLoad) {
|
| - dwRet = ((CPDF_Parser *)m_pDocument->GetParser())->LoadLinearizedMainXRefTable();
|
| - if (dwRet == PDFPARSE_ERROR_SUCCESS) {
|
| - if (!PreparePageItem()) {
|
| - return FALSE;
|
| - }
|
| - m_bMainXRefLoadedOK = TRUE;
|
| - }
|
| - m_bMainXRefLoad = TRUE;
|
| + switch (pKids->GetType()) {
|
| + case PDFOBJ_REFERENCE: {
|
| + CPDF_Reference* pKid = (CPDF_Reference*)pKids;
|
| + CPDF_PageNode* pNode = FX_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 = FX_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::CheckPageNode(CPDF_PageNode& pageNodes,
|
| + FX_INT32 iPage,
|
| + FX_INT32& iCount,
|
| + IFX_DownloadHints* pHints) {
|
| + FX_INT32 iSize = pageNodes.m_childNode.GetSize();
|
| + if (!iSize) {
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| + return FALSE;
|
| + }
|
| + for (FX_INT32 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(FX_INT32 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_bLinearedDataOK = TRUE;
|
| + m_docStatus = PDF_DATAAVAIL_ERROR;
|
| return TRUE;
|
| + }
|
| + FX_INT32 iCount = -1;
|
| + return CheckPageNode(m_pageNodes, iPage, iCount, pHints);
|
| }
|
| -FX_BOOL CPDF_DataAvail::CheckPageAnnots(FX_INT32 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;
|
| - } 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_objs_array.Append(new_objs_array);
|
| - }
|
| - return bRet;
|
| - }
|
| +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::CheckLinearizedFirstPage(FX_INT32 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::LoadDocPages(IFX_DownloadHints* pHints) {
|
| + if (!CheckUnkownPageNode(m_PagesObjNum, &m_pageNodes, pHints)) {
|
| + return FALSE;
|
| + }
|
| + if (CheckPageCount(pHints)) {
|
| + m_docStatus = PDF_DATAAVAIL_PAGE;
|
| return TRUE;
|
| + } else {
|
| + m_bTotalLoadPageTree = TRUE;
|
| + }
|
| + return FALSE;
|
| }
|
| -FX_BOOL CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary *pDict)
|
| -{
|
| - 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;
|
| - } else {
|
| - return HaveResourceAncestor(pParentDict);
|
| +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::IsPageAvail(FX_INT32 iPage, IFX_DownloadHints* pHints)
|
| -{
|
| - if (!m_pDocument) {
|
| +FX_BOOL CPDF_DataAvail::CheckLinearizedData(IFX_DownloadHints* pHints) {
|
| + if (m_bLinearedDataOK) {
|
| + return TRUE;
|
| + }
|
| + if (!m_pFileAvail->IsDataAvail(
|
| + m_dwLastXRefOffset, (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset))) {
|
| + pHints->AddSegment(m_dwLastXRefOffset,
|
| + (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset));
|
| + return FALSE;
|
| + }
|
| + FX_DWORD dwRet = 0;
|
| + if (!m_bMainXRefLoad) {
|
| + dwRet =
|
| + ((CPDF_Parser*)m_pDocument->GetParser())->LoadLinearizedMainXRefTable();
|
| + if (dwRet == PDFPARSE_ERROR_SUCCESS) {
|
| + if (!PreparePageItem()) {
|
| return FALSE;
|
| + }
|
| + m_bMainXRefLoadedOK = TRUE;
|
| }
|
| - if (IsFirstCheck(iPage)) {
|
| - m_bCurPageDictLoadOK = FALSE;
|
| - m_bPageLoadedOK = FALSE;
|
| - m_bAnnotsLoad = FALSE;
|
| - m_bNeedDownLoadResource = FALSE;
|
| - m_objs_array.RemoveAll();
|
| - m_objnum_array.RemoveAll();
|
| + m_bMainXRefLoad = TRUE;
|
| + }
|
| + m_bLinearedDataOK = TRUE;
|
| + return TRUE;
|
| +}
|
| +FX_BOOL CPDF_DataAvail::CheckPageAnnots(FX_INT32 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;
|
| + } 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_objs_array.Append(new_objs_array);
|
| }
|
| - if (m_pagesLoadState == NULL) {
|
| - m_pagesLoadState = FX_NEW CFX_CMapDWordToDWord();
|
| + return bRet;
|
| + }
|
| +}
|
| +FX_BOOL CPDF_DataAvail::CheckLinearizedFirstPage(FX_INT32 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) {
|
| + 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;
|
| + } else {
|
| + return HaveResourceAncestor(pParentDict);
|
| + }
|
| +}
|
| +FX_BOOL CPDF_DataAvail::IsPageAvail(FX_INT32 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 = FX_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;
|
| }
|
| - FX_DWORD dwPageLoad = 0;
|
| - if (m_pagesLoadState->Lookup(iPage, dwPageLoad) && dwPageLoad != 0) {
|
| - return TRUE;
|
| + if (!CheckLinearizedData(pHints)) {
|
| + return FALSE;
|
| }
|
| - 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;
|
| }
|
| - 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;
|
| + } else {
|
| + if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) {
|
| + return FALSE;
|
| }
|
| + }
|
| } 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;
|
| - }
|
| - }
|
| - if (m_pPageDict && !m_bNeedDownLoadResource) {
|
| - m_pPageResource = m_pPageDict->GetElement("Resources");
|
| - if (!m_pPageResource) {
|
| - m_bNeedDownLoadResource = HaveResourceAncestor(m_pPageDict);
|
| - } else {
|
| - m_bNeedDownLoadResource = TRUE;
|
| - }
|
| + if (!LoadAllFile(pHints)) {
|
| + return FALSE;
|
| + }
|
| + ((CPDF_Parser*)m_pDocument->GetParser())->RebuildCrossRef();
|
| + ResetFirstCheck(iPage);
|
| + return TRUE;
|
| + }
|
| + } else {
|
| + if (!m_bTotalLoadPageTree) {
|
| + if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) {
|
| + return FALSE;
|
| + }
|
| }
|
| - if (m_bNeedDownLoadResource) {
|
| - FX_BOOL bRet = CheckResources(pHints);
|
| - if (!bRet) {
|
| - return FALSE;
|
| - }
|
| - m_bNeedDownLoadResource = FALSE;
|
| + }
|
| + if (m_bHaveAcroForm && !m_bAcroFormLoad) {
|
| + if (!CheckAcroFormSubObject(pHints)) {
|
| + return 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)
|
| -{
|
| + 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();
|
| - 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();
|
| - }
|
| + 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_objs_array.Append(new_objs_array);
|
| - }
|
| + 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;
|
| + }
|
| }
|
| -}
|
| -void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE *pPos, FX_DWORD *pSize)
|
| -{
|
| - if (pPos) {
|
| - *pPos = m_dwLastXRefOffset;
|
| + }
|
| + 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 (pSize) {
|
| - *pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset);
|
| + }
|
| + if (m_bNeedDownLoadResource) {
|
| + FX_BOOL bRet = CheckResources(pHints);
|
| + if (!bRet) {
|
| + return FALSE;
|
| }
|
| + m_bNeedDownLoadResource = FALSE;
|
| + }
|
| + m_bPageLoadedOK = FALSE;
|
| + m_bAnnotsLoad = FALSE;
|
| + m_bCurPageDictLoadOK = FALSE;
|
| + ResetFirstCheck(iPage);
|
| + m_pagesLoadState->SetAt(iPage, TRUE);
|
| + return TRUE;
|
| }
|
| -FX_INT32 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 (!m_bMainXRefLoad && !CheckLinearizedData(pHints)) {
|
| - return PDFFORM_NOTAVAIL;
|
| - }
|
| - if (!m_objs_array.GetSize()) {
|
| - m_objs_array.Add(pAcroForm->GetDict());
|
| - }
|
| - m_bLinearizedFormParamLoad = 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;
|
| + } 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_objs_array.Append(new_objs_array);
|
| - return PDFFORM_NOTAVAIL;
|
| + m_objs_array.Append(new_objs_array);
|
| }
|
| - return PDFFORM_AVAIL;
|
| + return bRet;
|
| + }
|
| }
|
| -void CPDF_SortObjNumArray::AddObjNum(FX_DWORD dwObjNum)
|
| -{
|
| - FX_INT32 iNext = 0;
|
| - if (BinarySearch(dwObjNum, iNext)) {
|
| - return;
|
| +void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE* pPos,
|
| + FX_DWORD* pSize) {
|
| + if (pPos) {
|
| + *pPos = m_dwLastXRefOffset;
|
| + }
|
| + if (pSize) {
|
| + *pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset);
|
| + }
|
| +}
|
| +FX_INT32 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;
|
| }
|
| - m_number_array.InsertAt(iNext, dwObjNum);
|
| + if (!m_bMainXRefLoad && !CheckLinearizedData(pHints)) {
|
| + return PDFFORM_NOTAVAIL;
|
| + }
|
| + 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)
|
| -{
|
| - FX_INT32 iNext = 0;
|
| - return BinarySearch(dwObjNum, iNext);
|
| +void CPDF_SortObjNumArray::AddObjNum(FX_DWORD dwObjNum) {
|
| + FX_INT32 iNext = 0;
|
| + if (BinarySearch(dwObjNum, iNext)) {
|
| + return;
|
| + }
|
| + m_number_array.InsertAt(iNext, dwObjNum);
|
| }
|
| -FX_BOOL CPDF_SortObjNumArray::BinarySearch(FX_DWORD value, FX_INT32 &iNext)
|
| -{
|
| - FX_INT32 iLen = m_number_array.GetSize();
|
| - FX_INT32 iLow = 0;
|
| - FX_INT32 iHigh = iLen - 1;
|
| - FX_INT32 iMid = 0;
|
| - while (iLow <= iHigh) {
|
| - iMid = (iLow + iHigh) / 2;
|
| - if (m_number_array.GetAt(iMid) == value) {
|
| - iNext = iMid;
|
| - return TRUE;
|
| - } else 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) {
|
| + FX_INT32 iNext = 0;
|
| + return BinarySearch(dwObjNum, iNext);
|
| }
|
| -CPDF_PageNode::~CPDF_PageNode()
|
| -{
|
| - FX_INT32 iSize = m_childNode.GetSize();
|
| - for (FX_INT32 i = 0; i < iSize; ++i) {
|
| - CPDF_PageNode *pNode = (CPDF_PageNode*)m_childNode[i];
|
| - if (pNode) {
|
| - delete pNode;
|
| - }
|
| - }
|
| - m_childNode.RemoveAll();
|
| +FX_BOOL CPDF_SortObjNumArray::BinarySearch(FX_DWORD value, FX_INT32& iNext) {
|
| + FX_INT32 iLen = m_number_array.GetSize();
|
| + FX_INT32 iLow = 0;
|
| + FX_INT32 iHigh = iLen - 1;
|
| + FX_INT32 iMid = 0;
|
| + while (iLow <= iHigh) {
|
| + iMid = (iLow + iHigh) / 2;
|
| + if (m_number_array.GetAt(iMid) == value) {
|
| + iNext = iMid;
|
| + return TRUE;
|
| + } else 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() {
|
| + FX_INT32 iSize = m_childNode.GetSize();
|
| + for (FX_INT32 i = 0; i < iSize; ++i) {
|
| + CPDF_PageNode* pNode = (CPDF_PageNode*)m_childNode[i];
|
| + if (pNode) {
|
| + delete pNode;
|
| + }
|
| + }
|
| + m_childNode.RemoveAll();
|
| }
|
|
|