Home | History | Annotate | Download | only in fpdf_parser
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../../include/fpdfapi/fpdf_parser.h"
      8 #include "../../../include/fpdfapi/fpdf_module.h"
      9 #include "../../../include/fpdfapi/fpdf_page.h"
     10 #include "../fpdf_page/pageint.h"
     11 #include <limits.h>
     12 #define _PARSER_OBJECT_LEVLE_		64
     13 extern const FX_LPCSTR _PDF_CharType;
     14 FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict)
     15 {
     16     CPDF_Object* pType = pDict->GetElementValue(FX_BSTRC("Type"));
     17     if (!pType) {
     18         pType = pDict->GetElementValue(FX_BSTRC("FT"));
     19         if (!pType) {
     20             return FALSE;
     21         }
     22     }
     23     if (pType->GetString() == FX_BSTRC("Sig")) {
     24         return TRUE;
     25     }
     26     return FALSE;
     27 }
     28 static FX_INT32 _CompareDWord(const void* p1, const void* p2)
     29 {
     30     return (*(FX_DWORD*)p1) - (*(FX_DWORD*)p2);
     31 }
     32 static int _CompareFileSize(const void* p1, const void* p2)
     33 {
     34     FX_FILESIZE ret = (*(FX_FILESIZE*)p1) - (*(FX_FILESIZE*)p2);
     35     if (ret > 0) {
     36         return 1;
     37     }
     38     if (ret < 0) {
     39         return -1;
     40     }
     41     return 0;
     42 }
     43 CPDF_Parser::CPDF_Parser()
     44 {
     45     m_pDocument = NULL;
     46     m_pTrailer = NULL;
     47     m_pEncryptDict = NULL;
     48     m_pSecurityHandler = NULL;
     49     m_pLinearized = NULL;
     50     m_dwFirstPageNo = 0;
     51     m_dwXrefStartObjNum = 0;
     52     m_bOwnFileRead = TRUE;
     53     m_bForceUseSecurityHandler = FALSE;
     54 }
     55 CPDF_Parser::~CPDF_Parser()
     56 {
     57     CloseParser(FALSE);
     58 }
     59 FX_DWORD CPDF_Parser::GetLastObjNum()
     60 {
     61     FX_DWORD dwSize = m_CrossRef.GetSize();
     62     return dwSize ? dwSize - 1 : 0;
     63 }
     64 void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict)
     65 {
     66     m_pEncryptDict = pDict;
     67 }
     68 void CPDF_Parser::CloseParser(FX_BOOL bReParse)
     69 {
     70     m_bVersionUpdated = FALSE;
     71     if (m_pDocument && !bReParse) {
     72         delete m_pDocument;
     73         m_pDocument = NULL;
     74     }
     75     if (m_pTrailer) {
     76         m_pTrailer->Release();
     77         m_pTrailer = NULL;
     78     }
     79     ReleaseEncryptHandler();
     80     SetEncryptDictionary(NULL);
     81     if (m_bOwnFileRead && m_Syntax.m_pFileAccess != NULL) {
     82         m_Syntax.m_pFileAccess->Release();
     83         m_Syntax.m_pFileAccess = NULL;
     84     }
     85     FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
     86     while (pos) {
     87         FX_LPVOID objnum;
     88         CPDF_StreamAcc* pStream;
     89         m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
     90         delete pStream;
     91     }
     92     m_ObjectStreamMap.RemoveAll();
     93     m_SortedOffset.RemoveAll();
     94     m_CrossRef.RemoveAll();
     95     m_V5Type.RemoveAll();
     96     m_ObjVersion.RemoveAll();
     97     FX_INT32 iLen = m_Trailers.GetSize();
     98     for (FX_INT32 i = 0; i < iLen; ++i) {
     99         m_Trailers.GetAt(i)->Release();
    100     }
    101     m_Trailers.RemoveAll();
    102     if (m_pLinearized) {
    103         m_pLinearized->Release();
    104         m_pLinearized = NULL;
    105     }
    106 }
    107 static FX_INT32 GetHeaderOffset(IFX_FileRead* pFile)
    108 {
    109     FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025);
    110     FX_BYTE buf[4];
    111     FX_INT32 offset = 0;
    112     while (1) {
    113         if (!pFile->ReadBlock(buf, offset, 4)) {
    114             return -1;
    115         }
    116         if (*(FX_DWORD*)buf == tag) {
    117             return offset;
    118         }
    119         offset ++;
    120         if (offset > 1024) {
    121             return -1;
    122         }
    123     }
    124     return -1;
    125 }
    126 FX_DWORD CPDF_Parser::StartParse(FX_LPCSTR filename, FX_BOOL bReParse)
    127 {
    128     IFX_FileRead* pFileAccess = FX_CreateFileRead(filename);
    129     if (!pFileAccess) {
    130         return PDFPARSE_ERROR_FILE;
    131     }
    132     return StartParse(pFileAccess, bReParse);
    133 }
    134 FX_DWORD CPDF_Parser::StartParse(FX_LPCWSTR filename, FX_BOOL bReParse)
    135 {
    136     IFX_FileRead* pFileAccess = FX_CreateFileRead(filename);
    137     if (!pFileAccess) {
    138         return PDFPARSE_ERROR_FILE;
    139     }
    140     return StartParse(pFileAccess, bReParse);
    141 }
    142 CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler();
    143 CPDF_SecurityHandler* FPDF_CreatePubKeyHandler(void*);
    144 FX_DWORD CPDF_Parser::StartParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead)
    145 {
    146     CloseParser(bReParse);
    147     m_bXRefStream = FALSE;
    148     m_LastXRefOffset = 0;
    149     m_bOwnFileRead = bOwnFileRead;
    150     FX_INT32 offset = GetHeaderOffset(pFileAccess);
    151     if (offset == -1) {
    152         if (bOwnFileRead && pFileAccess) {
    153             pFileAccess->Release();
    154         }
    155         return PDFPARSE_ERROR_FORMAT;
    156     }
    157     m_Syntax.InitParser(pFileAccess, offset);
    158     FX_BYTE ch;
    159     m_Syntax.GetCharAt(5, ch);
    160     m_FileVersion = (ch - '0') * 10;
    161     m_Syntax.GetCharAt(7, ch);
    162     m_FileVersion += ch - '0';
    163     m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9);
    164     if (!bReParse) {
    165         m_pDocument = FX_NEW CPDF_Document(this);
    166     }
    167     FX_BOOL bXRefRebuilt = FALSE;
    168     if (m_Syntax.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, 4096)) {
    169         FX_FILESIZE startxref_offset = m_Syntax.SavePos();
    170         FX_LPVOID pResult = FXSYS_bsearch(&startxref_offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    171         if (pResult == NULL) {
    172             m_SortedOffset.Add(startxref_offset);
    173         }
    174         m_Syntax.GetKeyword();
    175         FX_BOOL bNumber;
    176         CFX_ByteString xrefpos_str = m_Syntax.GetNextWord(bNumber);
    177         if (!bNumber) {
    178             return PDFPARSE_ERROR_FORMAT;
    179         }
    180         m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
    181         if (!LoadAllCrossRefV4(m_LastXRefOffset) && !LoadAllCrossRefV5(m_LastXRefOffset)) {
    182             if (!RebuildCrossRef()) {
    183                 return PDFPARSE_ERROR_FORMAT;
    184             }
    185             bXRefRebuilt = TRUE;
    186             m_LastXRefOffset = 0;
    187         }
    188     } else {
    189         if (!RebuildCrossRef()) {
    190             return PDFPARSE_ERROR_FORMAT;
    191         }
    192         bXRefRebuilt = TRUE;
    193     }
    194     FX_DWORD dwRet = SetEncryptHandler();
    195     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
    196         return dwRet;
    197     }
    198     m_pDocument->LoadDoc();
    199     if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
    200         if (bXRefRebuilt) {
    201             return PDFPARSE_ERROR_FORMAT;
    202         }
    203         ReleaseEncryptHandler();
    204         if (!RebuildCrossRef()) {
    205             return PDFPARSE_ERROR_FORMAT;
    206         }
    207         dwRet = SetEncryptHandler();
    208         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
    209             return dwRet;
    210         }
    211         m_pDocument->LoadDoc();
    212         if (m_pDocument->GetRoot() == NULL) {
    213             return PDFPARSE_ERROR_FORMAT;
    214         }
    215     }
    216     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    217     FX_DWORD RootObjNum = GetRootObjNum();
    218     if (RootObjNum == 0) {
    219         ReleaseEncryptHandler();
    220         RebuildCrossRef();
    221         RootObjNum = GetRootObjNum();
    222         if (RootObjNum == 0) {
    223             return PDFPARSE_ERROR_FORMAT;
    224         }
    225         dwRet = SetEncryptHandler();
    226         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
    227             return dwRet;
    228         }
    229     }
    230     if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) {
    231         CPDF_Reference* pMetadata = (CPDF_Reference*)m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
    232         if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
    233             m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum();
    234         }
    235     }
    236     return PDFPARSE_ERROR_SUCCESS;
    237 }
    238 FX_DWORD CPDF_Parser::SetEncryptHandler()
    239 {
    240     ReleaseEncryptHandler();
    241     SetEncryptDictionary(NULL);
    242     if (m_pTrailer == NULL) {
    243         return PDFPARSE_ERROR_FORMAT;
    244     }
    245     CPDF_Object* pEncryptObj = m_pTrailer->GetElement(FX_BSTRC("Encrypt"));
    246     if (pEncryptObj) {
    247         if (pEncryptObj->GetType() == PDFOBJ_DICTIONARY) {
    248             SetEncryptDictionary((CPDF_Dictionary*)pEncryptObj);
    249         } else if (pEncryptObj->GetType() == PDFOBJ_REFERENCE) {
    250             pEncryptObj = m_pDocument->GetIndirectObject(((CPDF_Reference*)pEncryptObj)->GetRefObjNum());
    251             if (pEncryptObj) {
    252                 SetEncryptDictionary(pEncryptObj->GetDict());
    253             }
    254         }
    255     }
    256     if (m_bForceUseSecurityHandler) {
    257         FX_DWORD err = PDFPARSE_ERROR_HANDLER;
    258         if (m_pSecurityHandler == NULL) {
    259             return PDFPARSE_ERROR_HANDLER;
    260         }
    261         if (!m_pSecurityHandler->OnInit(this, m_pEncryptDict)) {
    262             return err;
    263         }
    264         CPDF_CryptoHandler* pCryptoHandler = m_pSecurityHandler->CreateCryptoHandler();
    265         if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) {
    266             delete pCryptoHandler;
    267             pCryptoHandler = NULL;
    268             return PDFPARSE_ERROR_HANDLER;
    269         }
    270         m_Syntax.SetEncrypt(pCryptoHandler);
    271     } else if (m_pEncryptDict) {
    272         CFX_ByteString filter = m_pEncryptDict->GetString(FX_BSTRC("Filter"));
    273         CPDF_SecurityHandler* pSecurityHandler = NULL;
    274         FX_DWORD err = PDFPARSE_ERROR_HANDLER;
    275         if (filter == FX_BSTRC("Standard")) {
    276             pSecurityHandler = FPDF_CreateStandardSecurityHandler();
    277             err = PDFPARSE_ERROR_PASSWORD;
    278         }
    279         if (pSecurityHandler == NULL) {
    280             return PDFPARSE_ERROR_HANDLER;
    281         }
    282         if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) {
    283             delete pSecurityHandler;
    284             pSecurityHandler = NULL;
    285             return err;
    286         }
    287         m_pSecurityHandler = pSecurityHandler;
    288         CPDF_CryptoHandler* pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
    289         if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) {
    290             delete pCryptoHandler;
    291             pCryptoHandler = NULL;
    292             return PDFPARSE_ERROR_HANDLER;
    293         }
    294         m_Syntax.SetEncrypt(pCryptoHandler);
    295     }
    296     return PDFPARSE_ERROR_SUCCESS;
    297 }
    298 void CPDF_Parser::ReleaseEncryptHandler()
    299 {
    300     if (m_Syntax.m_pCryptoHandler) {
    301         delete m_Syntax.m_pCryptoHandler;
    302         m_Syntax.m_pCryptoHandler = NULL;
    303     }
    304     if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
    305         delete m_pSecurityHandler;
    306         m_pSecurityHandler = NULL;
    307     }
    308 }
    309 FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum)
    310 {
    311     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
    312         return 0;
    313     }
    314     if (m_V5Type[objnum] == 1) {
    315         return m_CrossRef[objnum];
    316     }
    317     if (m_V5Type[objnum] == 2) {
    318         return m_CrossRef[(FX_INT32)m_CrossRef[objnum]];
    319     }
    320     return 0;
    321 }
    322 static FX_INT32 GetDirectInteger(CPDF_Dictionary* pDict, FX_BSTR key)
    323 {
    324     CPDF_Object* pObj = pDict->GetElement(key);
    325     if (pObj == NULL) {
    326         return 0;
    327     }
    328     if (pObj->GetType() == PDFOBJ_NUMBER) {
    329         return ((CPDF_Number*)pObj)->GetInteger();
    330     }
    331     return 0;
    332 }
    333 static FX_BOOL CheckDirectType(CPDF_Dictionary* pDict, FX_BSTR key, FX_INT32 iType)
    334 {
    335     CPDF_Object* pObj = pDict->GetElement(key);
    336     if (!pObj) {
    337         return TRUE;
    338     }
    339     return pObj->GetType() == iType;
    340 }
    341 FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos)
    342 {
    343     if (!LoadCrossRefV4(xrefpos, 0, TRUE, FALSE)) {
    344         return FALSE;
    345     }
    346     m_pTrailer = LoadTrailerV4();
    347     if (m_pTrailer == NULL) {
    348         return FALSE;
    349     }
    350     FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
    351     if (xrefsize <= 0 || xrefsize > (1 << 20)) {
    352         return FALSE;
    353     }
    354     m_CrossRef.SetSize(xrefsize);
    355     m_V5Type.SetSize(xrefsize);
    356     CFX_FileSizeArray CrossRefList, XRefStreamList;
    357     CrossRefList.Add(xrefpos);
    358     XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm")));
    359     if (!CheckDirectType(m_pTrailer, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) {
    360         return FALSE;
    361     }
    362     FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev"));
    363     if (newxrefpos == xrefpos) {
    364         return FALSE;
    365     }
    366     xrefpos = newxrefpos;
    367     while (xrefpos) {
    368         CrossRefList.InsertAt(0, xrefpos);
    369         LoadCrossRefV4(xrefpos, 0, TRUE, FALSE);
    370         CPDF_Dictionary* pDict = LoadTrailerV4();
    371         if (pDict == NULL) {
    372             return FALSE;
    373         }
    374         if (!CheckDirectType(pDict, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) {
    375             pDict->Release();
    376             return FALSE;
    377         }
    378         newxrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev"));
    379         if (newxrefpos == xrefpos) {
    380             pDict->Release();
    381             return FALSE;
    382         }
    383         xrefpos = newxrefpos;
    384         XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm")));
    385         m_Trailers.Add(pDict);
    386     }
    387     for (FX_INT32 i = 0; i < CrossRefList.GetSize(); i ++)
    388         if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) {
    389             return FALSE;
    390         }
    391     return TRUE;
    392 }
    393 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, FX_DWORD dwObjCount)
    394 {
    395     if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) {
    396         return FALSE;
    397     }
    398     m_pTrailer = LoadTrailerV4();
    399     if (m_pTrailer == NULL) {
    400         return FALSE;
    401     }
    402     FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
    403     if (xrefsize == 0) {
    404         return FALSE;
    405     }
    406     CFX_FileSizeArray CrossRefList, XRefStreamList;
    407     CrossRefList.Add(xrefpos);
    408     XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm")));
    409     xrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev"));
    410     while (xrefpos) {
    411         CrossRefList.InsertAt(0, xrefpos);
    412         LoadCrossRefV4(xrefpos, 0, TRUE, FALSE);
    413         CPDF_Dictionary* pDict = LoadTrailerV4();
    414         if (pDict == NULL) {
    415             return FALSE;
    416         }
    417         xrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev"));
    418         XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm")));
    419         m_Trailers.Add(pDict);
    420     }
    421     for (FX_INT32 i = 1; i < CrossRefList.GetSize(); i ++)
    422         if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) {
    423             return FALSE;
    424         }
    425     return TRUE;
    426 }
    427 FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, FX_DWORD dwObjCount)
    428 {
    429     FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset;
    430     m_Syntax.RestorePos(dwStartPos);
    431     FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    432     if (pResult == NULL) {
    433         m_SortedOffset.Add(pos);
    434     }
    435     FX_DWORD start_objnum = 0;
    436     FX_DWORD count = dwObjCount;
    437     FX_FILESIZE SavedPos = m_Syntax.SavePos();
    438     FX_INT32 recordsize = 20;
    439     char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
    440     pBuf[1024 * recordsize] = '\0';
    441     FX_INT32 nBlocks = count / 1024 + 1;
    442     for (FX_INT32 block = 0; block < nBlocks; block ++) {
    443         FX_INT32 block_size = block == nBlocks - 1 ? count % 1024 : 1024;
    444         FX_DWORD dwReadSize = block_size * recordsize;
    445         if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_Syntax.m_FileLen) {
    446             FX_Free(pBuf);
    447             return FALSE;
    448         }
    449         if (!m_Syntax.ReadBlock((FX_LPBYTE)pBuf, dwReadSize)) {
    450             FX_Free(pBuf);
    451             return FALSE;
    452         }
    453         for (FX_INT32 i = 0; i < block_size; i ++) {
    454             FX_DWORD objnum = start_objnum + block * 1024 + i;
    455             char* pEntry = pBuf + i * recordsize;
    456             if (pEntry[17] == 'f') {
    457                 m_CrossRef.SetAtGrow(objnum, 0);
    458                 m_V5Type.SetAtGrow(objnum, 0);
    459             } else {
    460                 FX_INT32 offset = FXSYS_atoi(pEntry);
    461                 if (offset == 0) {
    462                     for (FX_INT32 c = 0; c < 10; c ++) {
    463                         if (pEntry[c] < '0' || pEntry[c] > '9') {
    464                             FX_Free(pBuf);
    465                             return FALSE;
    466                         }
    467                     }
    468                 }
    469                 m_CrossRef.SetAtGrow(objnum, offset);
    470                 FX_INT32 version = FXSYS_atoi(pEntry + 11);
    471                 if (version >= 1) {
    472                     m_bVersionUpdated = TRUE;
    473                 }
    474                 m_ObjVersion.SetAtGrow(objnum, version);
    475                 if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
    476                     FX_LPVOID pResult = FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    477                     if (pResult == NULL) {
    478                         m_SortedOffset.Add(m_CrossRef[objnum]);
    479                     }
    480                 }
    481                 m_V5Type.SetAtGrow(objnum, 1);
    482             }
    483         }
    484     }
    485     FX_Free(pBuf);
    486     m_Syntax.RestorePos(SavedPos + count * recordsize);
    487     return TRUE;
    488 }
    489 FX_BOOL CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, FX_FILESIZE streampos, FX_BOOL bSkip, FX_BOOL bFirst)
    490 {
    491     m_Syntax.RestorePos(pos);
    492     if (m_Syntax.GetKeyword() != FX_BSTRC("xref")) {
    493         return FALSE;
    494     }
    495     FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    496     if (pResult == NULL) {
    497         m_SortedOffset.Add(pos);
    498     }
    499     if (streampos) {
    500         FX_LPVOID pResult = FXSYS_bsearch(&streampos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    501         if (pResult == NULL) {
    502             m_SortedOffset.Add(streampos);
    503         }
    504     }
    505     while (1) {
    506         FX_FILESIZE SavedPos = m_Syntax.SavePos();
    507         FX_BOOL bIsNumber;
    508         CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
    509         if (word.IsEmpty()) {
    510             return FALSE;
    511         }
    512         if (!bIsNumber) {
    513             m_Syntax.RestorePos(SavedPos);
    514             break;
    515         }
    516         FX_DWORD start_objnum = FXSYS_atoi(word);
    517         if (start_objnum >= (1 << 20)) {
    518             return FALSE;
    519         }
    520         FX_DWORD count = m_Syntax.GetDirectNum();
    521         m_Syntax.ToNextWord();
    522         SavedPos = m_Syntax.SavePos();
    523         FX_BOOL bFirstItem = FALSE;
    524         FX_INT32 recordsize = 20;
    525         if (bFirst) {
    526             bFirstItem = TRUE;
    527         }
    528         m_dwXrefStartObjNum = start_objnum;
    529         if (!bSkip) {
    530             char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
    531             pBuf[1024 * recordsize] = '\0';
    532             FX_INT32 nBlocks = count / 1024 + 1;
    533             FX_BOOL bFirstBlock = TRUE;
    534             for (FX_INT32 block = 0; block < nBlocks; block ++) {
    535                 FX_INT32 block_size = block == nBlocks - 1 ? count % 1024 : 1024;
    536                 m_Syntax.ReadBlock((FX_LPBYTE)pBuf, block_size * recordsize);
    537                 for (FX_INT32 i = 0; i < block_size; i ++) {
    538                     FX_DWORD objnum = start_objnum + block * 1024 + i;
    539                     char* pEntry = pBuf + i * recordsize;
    540                     if (pEntry[17] == 'f') {
    541                         if (bFirstItem) {
    542                             objnum = 0;
    543                             bFirstItem = FALSE;
    544                         }
    545                         if (bFirstBlock) {
    546                             FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
    547                             FX_INT32 version = FXSYS_atoi(pEntry + 11);
    548                             if (offset == 0 && version == 65535 && start_objnum != 0) {
    549                                 start_objnum--;
    550                                 objnum = 0;
    551                             }
    552                         }
    553                         m_CrossRef.SetAtGrow(objnum, 0);
    554                         m_V5Type.SetAtGrow(objnum, 0);
    555                     } else {
    556                         FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
    557                         if (offset == 0) {
    558                             for (FX_INT32 c = 0; c < 10; c ++) {
    559                                 if (pEntry[c] < '0' || pEntry[c] > '9') {
    560                                     FX_Free(pBuf);
    561                                     return FALSE;
    562                                 }
    563                             }
    564                         }
    565                         m_CrossRef.SetAtGrow(objnum, offset);
    566                         FX_INT32 version = FXSYS_atoi(pEntry + 11);
    567                         if (version >= 1) {
    568                             m_bVersionUpdated = TRUE;
    569                         }
    570                         m_ObjVersion.SetAtGrow(objnum, version);
    571                         if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
    572                             FX_LPVOID pResult = FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    573                             if (pResult == NULL) {
    574                                 m_SortedOffset.Add(m_CrossRef[objnum]);
    575                             }
    576                         }
    577                         m_V5Type.SetAtGrow(objnum, 1);
    578                     }
    579                     if (bFirstBlock) {
    580                         bFirstBlock = FALSE;
    581                     }
    582                 }
    583             }
    584             FX_Free(pBuf);
    585         }
    586         m_Syntax.RestorePos(SavedPos + count * recordsize);
    587     }
    588     if (streampos)
    589         if (!LoadCrossRefV5(streampos, streampos, FALSE)) {
    590             return FALSE;
    591         }
    592     return TRUE;
    593 }
    594 FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos)
    595 {
    596     if (!LoadCrossRefV5(xrefpos, xrefpos, TRUE)) {
    597         return FALSE;
    598     }
    599     while (xrefpos)
    600         if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
    601             return FALSE;
    602         }
    603     m_ObjectStreamMap.InitHashTable(101, FALSE);
    604     m_bXRefStream = TRUE;
    605     return TRUE;
    606 }
    607 FX_BOOL CPDF_Parser::RebuildCrossRef()
    608 {
    609     m_CrossRef.RemoveAll();
    610     m_V5Type.RemoveAll();
    611     m_SortedOffset.RemoveAll();
    612     m_ObjVersion.RemoveAll();
    613     if (m_pTrailer) {
    614         m_pTrailer->Release();
    615         m_pTrailer = NULL;
    616     }
    617     FX_INT32 status = 0;
    618     FX_INT32 inside_index = 0;
    619     FX_DWORD objnum, gennum;
    620     FX_INT32 depth = 0;
    621     FX_LPBYTE buffer = FX_Alloc(FX_BYTE, 4096);
    622     FX_FILESIZE pos = m_Syntax.m_HeaderOffset;
    623     FX_FILESIZE start_pos, start_pos1;
    624     FX_FILESIZE last_obj = -1, last_xref = -1, last_trailer = -1;
    625     FX_BOOL bInUpdate = FALSE;
    626     while (pos < m_Syntax.m_FileLen) {
    627         FX_BOOL bOverFlow = FALSE;
    628         FX_DWORD size = (FX_DWORD)(m_Syntax.m_FileLen - pos);
    629         if (size > 4096) {
    630             size = 4096;
    631         }
    632         if (!m_Syntax.m_pFileAccess->ReadBlock(buffer, pos, size)) {
    633             break;
    634         }
    635         for (FX_DWORD i = 0; i < size; i ++) {
    636             FX_BYTE byte = buffer[i];
    637             FX_LPBYTE pData = buffer + i;
    638             switch (status) {
    639                 case 0:
    640                     if (_PDF_CharType[byte] == 'W') {
    641                         status = 1;
    642                     }
    643                     if (byte <= '9' && byte >= '0') {
    644                         --i;
    645                         status = 1;
    646                     }
    647                     if (byte == '%') {
    648                         inside_index = 0;
    649                         status = 9;
    650                     }
    651                     if (byte == '(') {
    652                         status = 10;
    653                         depth = 1;
    654                     }
    655                     if (byte == '<') {
    656                         inside_index = 1;
    657                         status = 11;
    658                     }
    659                     if (byte == '\\') {
    660                         status = 13;
    661                     }
    662                     if (byte == 't') {
    663                         status = 7;
    664                         inside_index = 1;
    665                     }
    666                     break;
    667                 case 1:
    668                     if (_PDF_CharType[byte] == 'W') {
    669                         break;
    670                     } else if (byte <= '9' && byte >= '0') {
    671                         start_pos = pos + i;
    672                         status = 2;
    673                         objnum = byte - '0';
    674                     } else if (byte == 't') {
    675                         status = 7;
    676                         inside_index = 1;
    677                     } else if (byte == 'x') {
    678                         status = 8;
    679                         inside_index = 1;
    680                     } else {
    681                         --i;
    682                         status = 0;
    683                     }
    684                     break;
    685                 case 2:
    686                     if (byte <= '9' && byte >= '0') {
    687                         objnum = objnum * 10 + byte - '0';
    688                         break;
    689                     } else if (_PDF_CharType[byte] == 'W') {
    690                         status = 3;
    691                     } else {
    692                         --i;
    693                         status = 14;
    694                         inside_index = 0;
    695                     }
    696                     break;
    697                 case 3:
    698                     if (byte <= '9' && byte >= '0') {
    699                         start_pos1 = pos + i;
    700                         status = 4;
    701                         gennum = byte - '0';
    702                     } else if (_PDF_CharType[byte] == 'W') {
    703                         break;
    704                     } else if (byte == 't') {
    705                         status = 7;
    706                         inside_index = 1;
    707                     } else {
    708                         --i;
    709                         status = 0;
    710                     }
    711                     break;
    712                 case 4:
    713                     if (byte <= '9' && byte >= '0') {
    714                         gennum = gennum * 10 + byte - '0';
    715                         break;
    716                     } else if (_PDF_CharType[byte] == 'W') {
    717                         status = 5;
    718                     } else {
    719                         --i;
    720                         status = 0;
    721                     }
    722                     break;
    723                 case 5:
    724                     if (byte == 'o') {
    725                         status = 6;
    726                         inside_index = 1;
    727                     } else if (_PDF_CharType[byte] == 'W') {
    728                         break;
    729                     } else if (byte <= '9' && byte >= '0') {
    730                         objnum = gennum;
    731                         gennum = byte - '0';
    732                         start_pos = start_pos1;
    733                         start_pos1 = pos + i;
    734                         status = 4;
    735                     } else if (byte == 't') {
    736                         status = 7;
    737                         inside_index = 1;
    738                     } else {
    739                         --i;
    740                         status = 0;
    741                     }
    742                     break;
    743                 case 6:
    744                     switch (inside_index) {
    745                         case 1:
    746                             if (byte != 'b') {
    747                                 --i;
    748                                 status = 0;
    749                             } else {
    750                                 inside_index ++;
    751                             }
    752                             break;
    753                         case 2:
    754                             if (byte != 'j') {
    755                                 --i;
    756                                 status = 0;
    757                             } else {
    758                                 inside_index ++;
    759                             }
    760                             break;
    761                         case 3:
    762                             if (_PDF_CharType[byte] == 'W' || _PDF_CharType[byte] == 'D') {
    763                                 if (objnum > 0x1000000) {
    764                                     status = 0;
    765                                     break;
    766                                 }
    767                                 FX_FILESIZE obj_pos = start_pos - m_Syntax.m_HeaderOffset;
    768                                 last_obj = start_pos;
    769                                 FX_LPVOID pResult = FXSYS_bsearch(&obj_pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    770                                 if (pResult == NULL) {
    771                                     m_SortedOffset.Add(obj_pos);
    772                                 }
    773                                 FX_FILESIZE obj_end = 0;
    774                                 CPDF_Object *pObject = ParseIndirectObjectAtByStrict(m_pDocument, obj_pos, objnum, NULL, &obj_end);
    775                                 if (pObject) {
    776                                     int iType =	pObject->GetType();
    777                                     if (iType == PDFOBJ_STREAM) {
    778                                         CPDF_Stream* pStream = (CPDF_Stream*)pObject;
    779                                         CPDF_Dictionary* pDict = pStream->GetDict();
    780                                         if (pDict) {
    781                                             if (pDict->KeyExist(FX_BSTRC("Type"))) {
    782                                                 CFX_ByteString bsValue = pDict->GetString(FX_BSTRC("Type"));
    783                                                 if (bsValue == FX_BSTRC("XRef") && pDict->KeyExist(FX_BSTRC("Size"))) {
    784                                                     CPDF_Object* pRoot = pDict->GetElement(FX_BSTRC("Root"));
    785                                                     if (pRoot && pRoot->GetDict() && pRoot->GetDict()->GetElement(FX_BSTRC("Pages"))) {
    786                                                         if (m_pTrailer) {
    787                                                             m_pTrailer->Release();
    788                                                         }
    789                                                         m_pTrailer = (CPDF_Dictionary*)pDict->Clone();
    790                                                     }
    791                                                 }
    792                                             }
    793                                         }
    794                                     }
    795                                 }
    796                                 FX_FILESIZE offset = 0;
    797                                 m_Syntax.RestorePos(obj_pos);
    798                                 offset = m_Syntax.FindTag(FX_BSTRC("obj"), 0);
    799                                 if (offset == -1) {
    800                                     offset = 0;
    801                                 } else {
    802                                     offset += 3;
    803                                 }
    804                                 FX_FILESIZE nLen = obj_end - obj_pos - offset;
    805                                 if ((FX_DWORD)nLen > size - i) {
    806                                     pos = obj_end + m_Syntax.m_HeaderOffset;
    807                                     bOverFlow = TRUE;
    808                                 } else {
    809                                     i += (FX_DWORD)nLen;
    810                                 }
    811                                 if (m_CrossRef.GetSize() > (FX_INT32)objnum && m_CrossRef[objnum]) {
    812                                     if (pObject) {
    813                                         FX_DWORD oldgen = m_ObjVersion.GetAt(objnum);
    814                                         m_CrossRef[objnum] = obj_pos;
    815                                         m_ObjVersion.SetAt(objnum, (FX_SHORT)gennum);
    816                                         if (oldgen != gennum) {
    817                                             m_bVersionUpdated = TRUE;
    818                                         }
    819                                     }
    820                                 } else {
    821                                     m_CrossRef.SetAtGrow(objnum, obj_pos);
    822                                     m_V5Type.SetAtGrow(objnum, 1);
    823                                     m_ObjVersion.SetAtGrow(objnum, (FX_SHORT)gennum);
    824                                 }
    825                                 if (pObject) {
    826                                     pObject->Release();
    827                                 }
    828                             }
    829                             --i;
    830                             status = 0;
    831                             break;
    832                     }
    833                     break;
    834                 case 7:
    835                     if (inside_index == 7) {
    836                         if (_PDF_CharType[byte] == 'W' || _PDF_CharType[byte] == 'D') {
    837                             last_trailer = pos + i - 7;
    838                             m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset);
    839                             CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
    840                             if (pObj) {
    841                                 if (pObj->GetType() != PDFOBJ_DICTIONARY && pObj->GetType() != PDFOBJ_STREAM) {
    842                                     pObj->Release();
    843                                 } else {
    844                                     CPDF_Dictionary* pTrailer = NULL;
    845                                     if (pObj->GetType() == PDFOBJ_STREAM) {
    846                                         pTrailer = ((CPDF_Stream*)pObj)->GetDict();
    847                                     } else {
    848                                         pTrailer = (CPDF_Dictionary*)pObj;
    849                                     }
    850                                     if (pTrailer) {
    851                                         if (m_pTrailer) {
    852                                             CPDF_Object* pRoot = pTrailer->GetElement(FX_BSTRC("Root"));
    853                                             if (pRoot == NULL || (pRoot->GetType() == PDFOBJ_REFERENCE &&
    854                                                                   (FX_DWORD)m_CrossRef.GetSize() > ((CPDF_Reference*)pRoot)->GetRefObjNum() &&
    855                                                                   m_CrossRef.GetAt(((CPDF_Reference*)pRoot)->GetRefObjNum()) != 0)) {
    856                                                 FX_POSITION pos = pTrailer->GetStartPos();
    857                                                 while (pos) {
    858                                                     CFX_ByteString key;
    859                                                     CPDF_Object* pObj = pTrailer->GetNextElement(pos, key);
    860                                                     m_pTrailer->SetAt(key, pObj->Clone(), m_pDocument);
    861                                                 }
    862                                                 pObj->Release();
    863                                             } else {
    864                                                 pObj->Release();
    865                                             }
    866                                         } else {
    867                                             if (pObj->GetType() == PDFOBJ_STREAM) {
    868                                                 m_pTrailer = (CPDF_Dictionary*)pTrailer->Clone();
    869                                                 pObj->Release();
    870                                             } else {
    871                                                 m_pTrailer = pTrailer;
    872                                             }
    873                                             FX_FILESIZE dwSavePos = m_Syntax.SavePos();
    874                                             CFX_ByteString strWord = m_Syntax.GetKeyword();
    875                                             if (!strWord.Compare(FX_BSTRC("startxref"))) {
    876                                                 FX_BOOL bNumber = FALSE;
    877                                                 CFX_ByteString bsOffset = m_Syntax.GetNextWord(bNumber);
    878                                                 if (bNumber) {
    879                                                     m_LastXRefOffset = FXSYS_atoi(bsOffset);
    880                                                 }
    881                                             }
    882                                             m_Syntax.RestorePos(dwSavePos);
    883                                         }
    884                                     } else {
    885                                         pObj->Release();
    886                                     }
    887                                     bInUpdate = TRUE;
    888                                 }
    889                             }
    890                         }
    891                         --i;
    892                         status = 0;
    893                     } else if (byte == "trailer"[inside_index]) {
    894                         inside_index ++;
    895                     } else {
    896                         --i;
    897                         status = 0;
    898                     }
    899                     break;
    900                 case 8:
    901                     if (inside_index == 4) {
    902                         last_xref = pos + i - 4;
    903                         status = 1;
    904                     } else if (byte == "xref"[inside_index]) {
    905                         inside_index ++;
    906                     } else {
    907                         --i;
    908                         status = 0;
    909                     }
    910                     break;
    911                 case 9:
    912                     if (byte == '\r' || byte == '\n') {
    913                         status = 0;
    914                     }
    915                     break;
    916                 case 10:
    917                     if (byte == ')') {
    918                         if (depth > 0) {
    919                             depth--;
    920                         }
    921                     } else if (byte == '(') {
    922                         depth++;
    923                     }
    924                     if (!depth) {
    925                         status = 0;
    926                     }
    927                     break;
    928                 case 11:
    929                     if (byte == '<' && inside_index == 1) {
    930                         status = 12;
    931                     } else if (byte == '>') {
    932                         status = 0;
    933                     }
    934                     inside_index = 0;
    935                     break;
    936                 case 12:
    937                     --i;
    938                     status = 0;
    939                     break;
    940                 case 13:
    941                     if (_PDF_CharType[byte] == 'D' || _PDF_CharType[byte] == 'W') {
    942                         --i;
    943                         status = 0;
    944                     }
    945                     break;
    946                 case 14:
    947                     if (_PDF_CharType[byte] == 'W') {
    948                         status = 0;
    949                     } else if (byte == '%' || byte == '(' || byte == '<' || byte == '\\') {
    950                         status = 0;
    951                         --i;
    952                     } else if (inside_index == 6) {
    953                         status = 0;
    954                         --i;
    955                     } else if (byte == "endobj"[inside_index]) {
    956                         inside_index++;
    957                     }
    958                     break;
    959             }
    960             if (bOverFlow) {
    961                 size = 0;
    962                 break;
    963             }
    964         }
    965         pos += size;
    966     }
    967     if (last_xref != -1 && last_xref > last_obj) {
    968         last_trailer = last_xref;
    969     } else if (last_trailer == -1 || last_xref < last_obj) {
    970         last_trailer = m_Syntax.m_FileLen;
    971     }
    972     FX_FILESIZE offset = last_trailer - m_Syntax.m_HeaderOffset;
    973     FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
    974     if (pResult == NULL) {
    975         m_SortedOffset.Add(offset);
    976     }
    977     FX_Free(buffer);
    978     return TRUE;
    979 }
    980 static FX_DWORD _GetVarInt(FX_LPCBYTE p, FX_INT32 n)
    981 {
    982     FX_DWORD result = 0;
    983     for (FX_INT32 i = 0; i < n; i ++) {
    984         result = result * 256 + p[i];
    985     }
    986     return result;
    987 }
    988 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL bMainXRef)
    989 {
    990     CPDF_Stream* pStream = (CPDF_Stream*)ParseIndirectObjectAt(m_pDocument, pos, 0, NULL);
    991     if (!pStream) {
    992         return FALSE;
    993     }
    994     if (m_pDocument) {
    995         m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
    996     }
    997     if (pStream->GetType() != PDFOBJ_STREAM) {
    998         return FALSE;
    999     }
   1000     prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev"));
   1001     FX_INT32 size = pStream->GetDict()->GetInteger(FX_BSTRC("Size"));
   1002     if (size < 0) {
   1003         pStream->Release();
   1004         return FALSE;
   1005     }
   1006     if (bMainXRef) {
   1007         m_pTrailer = (CPDF_Dictionary*)pStream->GetDict()->Clone();
   1008         m_CrossRef.SetSize(size);
   1009         if (m_V5Type.SetSize(size)) {
   1010             FXSYS_memset32(m_V5Type.GetData(), 0, size);
   1011         }
   1012     } else {
   1013         m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
   1014     }
   1015     CFX_DWordArray IndexArray, WidthArray;
   1016     FX_DWORD nSegs = 0;
   1017     CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
   1018     if (pArray == NULL) {
   1019         IndexArray.Add(0);
   1020         IndexArray.Add(size);
   1021         nSegs = 1;
   1022     } else {
   1023         for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
   1024             IndexArray.Add(pArray->GetInteger(i));
   1025         }
   1026         nSegs = pArray->GetCount() / 2;
   1027     }
   1028     pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
   1029     if (pArray == NULL) {
   1030         pStream->Release();
   1031         return FALSE;
   1032     }
   1033     FX_DWORD totalwidth = 0;
   1034     FX_DWORD i;
   1035     for (i = 0; i < pArray->GetCount(); i ++) {
   1036         WidthArray.Add(pArray->GetInteger(i));
   1037         if (totalwidth + WidthArray[i] < totalwidth) {
   1038             pStream->Release();
   1039             return FALSE;
   1040         }
   1041         totalwidth += WidthArray[i];
   1042     }
   1043     if (totalwidth == 0 || WidthArray.GetSize() < 3) {
   1044         pStream->Release();
   1045         return FALSE;
   1046     }
   1047     CPDF_StreamAcc acc;
   1048     acc.LoadAllData(pStream);
   1049     FX_LPCBYTE pData = acc.GetData();
   1050     FX_DWORD dwTotalSize = acc.GetSize();
   1051     FX_DWORD segindex = 0;
   1052     for (i = 0; i < nSegs; i ++) {
   1053         FX_INT32 startnum = IndexArray[i * 2];
   1054         if (startnum < 0) {
   1055             continue;
   1056         }
   1057         m_dwXrefStartObjNum = startnum;
   1058         FX_DWORD count = IndexArray[i * 2 + 1];
   1059         if (segindex + count < segindex || segindex + count == 0 ||
   1060                 (FX_DWORD)totalwidth >= UINT_MAX / (segindex + count) || (segindex + count) * (FX_DWORD)totalwidth > dwTotalSize) {
   1061             continue;
   1062         }
   1063         FX_LPCBYTE segstart = pData + segindex * (FX_DWORD)totalwidth;
   1064         if ((FX_DWORD)startnum + count < (FX_DWORD)startnum ||
   1065                 (FX_DWORD)startnum + count > (FX_DWORD)m_V5Type.GetSize()) {
   1066             continue;
   1067         }
   1068         for (FX_DWORD j = 0; j < count; j ++) {
   1069             FX_INT32 type = 1;
   1070             FX_LPCBYTE entrystart = segstart + j * totalwidth;
   1071             if (WidthArray[0]) {
   1072                 type = _GetVarInt(entrystart, WidthArray[0]);
   1073             }
   1074             if (m_V5Type[startnum + j] == 255) {
   1075                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
   1076                 m_CrossRef[startnum + j] = offset;
   1077                 FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
   1078                 if (pResult == NULL) {
   1079                     m_SortedOffset.Add(offset);
   1080                 }
   1081                 continue;
   1082             }
   1083             if (m_V5Type[startnum + j]) {
   1084                 continue;
   1085             }
   1086             m_V5Type[startnum + j] = type;
   1087             if (type == 0) {
   1088                 m_CrossRef[startnum + j] = 0;
   1089             } else {
   1090                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
   1091                 m_CrossRef[startnum + j] = offset;
   1092                 if (type == 1) {
   1093                     FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
   1094                     if (pResult == NULL) {
   1095                         m_SortedOffset.Add(offset);
   1096                     }
   1097                 } else {
   1098                     if (offset < 0 || offset >= m_V5Type.GetSize()) {
   1099                         pStream->Release();
   1100                         return FALSE;
   1101                     }
   1102                     m_V5Type[offset] = 255;
   1103                 }
   1104             }
   1105         }
   1106         segindex += count;
   1107     }
   1108     pStream->Release();
   1109     return TRUE;
   1110 }
   1111 CPDF_Array* CPDF_Parser::GetIDArray()
   1112 {
   1113     CPDF_Object* pID = m_pTrailer->GetElement(FX_BSTRC("ID"));
   1114     if (pID == NULL) {
   1115         return NULL;
   1116     }
   1117     if (pID->GetType() == PDFOBJ_REFERENCE) {
   1118         pID = ParseIndirectObject(NULL, ((CPDF_Reference*)pID)->GetRefObjNum());
   1119         m_pTrailer->SetAt(FX_BSTRC("ID"), pID);
   1120     }
   1121     if (pID == NULL || pID->GetType() != PDFOBJ_ARRAY) {
   1122         return NULL;
   1123     }
   1124     return (CPDF_Array*)pID;
   1125 }
   1126 FX_DWORD CPDF_Parser::GetRootObjNum()
   1127 {
   1128     CPDF_Reference* pRef = (CPDF_Reference*)m_pTrailer->GetElement(FX_BSTRC("Root"));
   1129     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
   1130         return 0;
   1131     }
   1132     return pRef->GetRefObjNum();
   1133 }
   1134 FX_DWORD CPDF_Parser::GetInfoObjNum()
   1135 {
   1136     CPDF_Reference* pRef = (CPDF_Reference*)m_pTrailer->GetElement(FX_BSTRC("Info"));
   1137     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
   1138         return 0;
   1139     }
   1140     return pRef->GetRefObjNum();
   1141 }
   1142 FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm)
   1143 {
   1144     bForm = FALSE;
   1145     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
   1146         return TRUE;
   1147     }
   1148     if (m_V5Type[objnum] == 0) {
   1149         return TRUE;
   1150     }
   1151     if (m_V5Type[objnum] == 2) {
   1152         return TRUE;
   1153     }
   1154     FX_FILESIZE pos = m_CrossRef[objnum];
   1155     FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
   1156     if (pResult == NULL) {
   1157         return TRUE;
   1158     }
   1159     if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
   1160         return FALSE;
   1161     }
   1162     FX_FILESIZE size = ((FX_FILESIZE*)pResult)[1] - pos;
   1163     FX_FILESIZE SavedPos = m_Syntax.SavePos();
   1164     m_Syntax.RestorePos(pos);
   1165     bForm = m_Syntax.SearchMultiWord(FX_BSTRC("/Form\0stream"), TRUE, size) == 0;
   1166     m_Syntax.RestorePos(SavedPos);
   1167     return TRUE;
   1168 }
   1169 CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, PARSE_CONTEXT* pContext)
   1170 {
   1171     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
   1172         return NULL;
   1173     }
   1174     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
   1175         FX_FILESIZE pos = m_CrossRef[objnum];
   1176         if (pos <= 0) {
   1177             return NULL;
   1178         }
   1179         return ParseIndirectObjectAt(pObjList, pos, objnum, pContext);
   1180     }
   1181     if (m_V5Type[objnum] == 2) {
   1182         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
   1183         if (pObjStream == NULL) {
   1184             return NULL;
   1185         }
   1186         FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
   1187         FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
   1188         CPDF_SyntaxParser syntax;
   1189         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE));
   1190         syntax.InitParser((IFX_FileStream*)file, 0);
   1191         CPDF_Object* pRet = NULL;
   1192         while (n) {
   1193             FX_DWORD thisnum = syntax.GetDirectNum();
   1194             FX_DWORD thisoff = syntax.GetDirectNum();
   1195             if (thisnum == objnum) {
   1196                 syntax.RestorePos(offset + thisoff);
   1197                 pRet = syntax.GetObject(pObjList, 0, 0, 0, pContext);
   1198                 break;
   1199             }
   1200             n --;
   1201         }
   1202         return pRet;
   1203     }
   1204     return NULL;
   1205 }
   1206 CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum)
   1207 {
   1208     CPDF_StreamAcc* pStreamAcc = NULL;
   1209     if (m_ObjectStreamMap.Lookup((void*)(FX_UINTPTR)objnum, (void*&)pStreamAcc)) {
   1210         return pStreamAcc;
   1211     }
   1212     const CPDF_Stream* pStream = (CPDF_Stream*)m_pDocument->GetIndirectObject(objnum);
   1213     if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
   1214         return NULL;
   1215     }
   1216     pStreamAcc = FX_NEW CPDF_StreamAcc;
   1217     pStreamAcc->LoadAllData(pStream);
   1218     m_ObjectStreamMap.SetAt((void*)(FX_UINTPTR)objnum, pStreamAcc);
   1219     return pStreamAcc;
   1220 }
   1221 FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum)
   1222 {
   1223     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
   1224         return 0;
   1225     }
   1226     if (m_V5Type[objnum] == 2) {
   1227         objnum = (FX_DWORD)m_CrossRef[objnum];
   1228     }
   1229     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
   1230         FX_FILESIZE offset = m_CrossRef[objnum];
   1231         if (offset == 0) {
   1232             return 0;
   1233         }
   1234         FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
   1235         if (pResult == NULL) {
   1236             return 0;
   1237         }
   1238         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
   1239             return 0;
   1240         }
   1241         return ((FX_FILESIZE*)pResult)[1] - offset;
   1242     }
   1243     return 0;
   1244 }
   1245 void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, FX_LPBYTE& pBuffer, FX_DWORD& size)
   1246 {
   1247     pBuffer = NULL;
   1248     size = 0;
   1249     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
   1250         return;
   1251     }
   1252     if (m_V5Type[objnum] == 2) {
   1253         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
   1254         if (pObjStream == NULL) {
   1255             return;
   1256         }
   1257         FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
   1258         FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
   1259         CPDF_SyntaxParser syntax;
   1260         FX_LPCBYTE pData = pObjStream->GetData();
   1261         FX_DWORD totalsize = pObjStream->GetSize();
   1262         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pData, (size_t)totalsize, FALSE));
   1263         syntax.InitParser((IFX_FileStream*)file, 0);
   1264         while (n) {
   1265             FX_DWORD thisnum = syntax.GetDirectNum();
   1266             FX_DWORD thisoff = syntax.GetDirectNum();
   1267             if (thisnum == objnum) {
   1268                 if (n == 1) {
   1269                     size = totalsize - (thisoff + offset);
   1270                 } else {
   1271                     FX_DWORD nextnum = syntax.GetDirectNum();
   1272                     FX_DWORD nextoff = syntax.GetDirectNum();
   1273                     size = nextoff - thisoff;
   1274                 }
   1275                 pBuffer = FX_Alloc(FX_BYTE, size);
   1276                 FXSYS_memcpy32(pBuffer, pData + thisoff + offset, size);
   1277                 return;
   1278             }
   1279             n --;
   1280         }
   1281         return;
   1282     }
   1283     if (m_V5Type[objnum] == 1) {
   1284         FX_FILESIZE pos = m_CrossRef[objnum];
   1285         if (pos == 0) {
   1286             return;
   1287         }
   1288         FX_FILESIZE SavedPos = m_Syntax.SavePos();
   1289         m_Syntax.RestorePos(pos);
   1290         FX_BOOL bIsNumber;
   1291         CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
   1292         if (!bIsNumber) {
   1293             m_Syntax.RestorePos(SavedPos);
   1294             return;
   1295         }
   1296         FX_DWORD real_objnum = FXSYS_atoi(word);
   1297         if (real_objnum && real_objnum != objnum) {
   1298             m_Syntax.RestorePos(SavedPos);
   1299             return;
   1300         }
   1301         word = m_Syntax.GetNextWord(bIsNumber);
   1302         if (!bIsNumber) {
   1303             m_Syntax.RestorePos(SavedPos);
   1304             return;
   1305         }
   1306         if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
   1307             m_Syntax.RestorePos(SavedPos);
   1308             return;
   1309         }
   1310         FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
   1311         if (pResult == NULL) {
   1312             m_Syntax.RestorePos(SavedPos);
   1313             return;
   1314         }
   1315         FX_FILESIZE nextoff = ((FX_FILESIZE*)pResult)[1];
   1316         FX_BOOL bNextOffValid = FALSE;
   1317         if (nextoff != pos) {
   1318             m_Syntax.RestorePos(nextoff);
   1319             word = m_Syntax.GetNextWord(bIsNumber);
   1320             if (word == FX_BSTRC("xref")) {
   1321                 bNextOffValid = TRUE;
   1322             } else if (bIsNumber) {
   1323                 word = m_Syntax.GetNextWord(bIsNumber);
   1324                 if (bIsNumber && m_Syntax.GetKeyword() == FX_BSTRC("obj")) {
   1325                     bNextOffValid = TRUE;
   1326                 }
   1327             }
   1328         }
   1329         if (!bNextOffValid) {
   1330             m_Syntax.RestorePos(pos);
   1331             while (1) {
   1332                 if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) {
   1333                     break;
   1334                 }
   1335                 if (m_Syntax.SavePos() == m_Syntax.m_FileLen) {
   1336                     break;
   1337                 }
   1338             }
   1339             nextoff = m_Syntax.SavePos();
   1340         }
   1341         size = (FX_DWORD)(nextoff - pos);
   1342         pBuffer = FX_Alloc(FX_BYTE, size);
   1343         m_Syntax.RestorePos(pos);
   1344         m_Syntax.ReadBlock(pBuffer, size);
   1345         m_Syntax.RestorePos(SavedPos);
   1346     }
   1347 }
   1348 CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
   1349         PARSE_CONTEXT* pContext)
   1350 {
   1351     FX_FILESIZE SavedPos = m_Syntax.SavePos();
   1352     m_Syntax.RestorePos(pos);
   1353     FX_BOOL bIsNumber;
   1354     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
   1355     if (!bIsNumber) {
   1356         m_Syntax.RestorePos(SavedPos);
   1357         return NULL;
   1358     }
   1359     FX_FILESIZE objOffset = m_Syntax.SavePos();
   1360     objOffset -= word.GetLength();
   1361     FX_DWORD real_objnum = FXSYS_atoi(word);
   1362     if (objnum && real_objnum != objnum) {
   1363         m_Syntax.RestorePos(SavedPos);
   1364         return NULL;
   1365     }
   1366     word = m_Syntax.GetNextWord(bIsNumber);
   1367     if (!bIsNumber) {
   1368         m_Syntax.RestorePos(SavedPos);
   1369         return NULL;
   1370     }
   1371     FX_DWORD gennum = FXSYS_atoi(word);
   1372     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
   1373         m_Syntax.RestorePos(SavedPos);
   1374         return NULL;
   1375     }
   1376     CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, gennum, 0, pContext);
   1377     FX_FILESIZE endOffset = m_Syntax.SavePos();
   1378     CFX_ByteString bsWord = m_Syntax.GetKeyword();
   1379     if (bsWord == FX_BSTRC("endobj")) {
   1380         endOffset = m_Syntax.SavePos();
   1381     }
   1382     FX_DWORD objSize = endOffset - objOffset;
   1383     m_Syntax.RestorePos(SavedPos);
   1384     if (pObj && !objnum) {
   1385         pObj->m_ObjNum = real_objnum;
   1386     }
   1387     return pObj;
   1388 }
   1389 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
   1390         struct PARSE_CONTEXT* pContext, FX_FILESIZE *pResultPos)
   1391 {
   1392     FX_FILESIZE SavedPos = m_Syntax.SavePos();
   1393     m_Syntax.RestorePos(pos);
   1394     FX_BOOL bIsNumber;
   1395     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
   1396     if (!bIsNumber) {
   1397         m_Syntax.RestorePos(SavedPos);
   1398         return NULL;
   1399     }
   1400     FX_DWORD real_objnum = FXSYS_atoi(word);
   1401     if (objnum && real_objnum != objnum) {
   1402         m_Syntax.RestorePos(SavedPos);
   1403         return NULL;
   1404     }
   1405     word = m_Syntax.GetNextWord(bIsNumber);
   1406     if (!bIsNumber) {
   1407         m_Syntax.RestorePos(SavedPos);
   1408         return NULL;
   1409     }
   1410     FX_DWORD gennum = FXSYS_atoi(word);
   1411     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
   1412         m_Syntax.RestorePos(SavedPos);
   1413         return NULL;
   1414     }
   1415     CPDF_Object* pObj = m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, 0, pContext);
   1416     if (pResultPos) {
   1417         *pResultPos = m_Syntax.m_Pos;
   1418     }
   1419     m_Syntax.RestorePos(SavedPos);
   1420     return pObj;
   1421 }
   1422 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4()
   1423 {
   1424     if (m_Syntax.GetKeyword() != FX_BSTRC("trailer")) {
   1425         return NULL;
   1426     }
   1427     CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
   1428     if (pObj == NULL || pObj->GetType() != PDFOBJ_DICTIONARY) {
   1429         if (pObj) {
   1430             pObj->Release();
   1431         }
   1432         return NULL;
   1433     }
   1434     return (CPDF_Dictionary*)pObj;
   1435 }
   1436 FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision)
   1437 {
   1438     if (m_pSecurityHandler == NULL) {
   1439         return (FX_DWORD) - 1;
   1440     }
   1441     FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions();
   1442     if (m_pEncryptDict && m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) {
   1443         dwPermission &= 0xFFFFFFFC;
   1444         dwPermission |= 0xFFFFF0C0;
   1445         if(bCheckRevision && m_pEncryptDict->GetInteger(FX_BSTRC("R")) == 2) {
   1446             dwPermission &= 0xFFFFF0FF;
   1447         }
   1448     }
   1449     return dwPermission;
   1450 }
   1451 FX_BOOL CPDF_Parser::IsOwner()
   1452 {
   1453     return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
   1454 }
   1455 void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler, FX_BOOL bForced)
   1456 {
   1457     ASSERT(m_pSecurityHandler == NULL);
   1458     if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
   1459         delete m_pSecurityHandler;
   1460         m_pSecurityHandler = NULL;
   1461     }
   1462     m_bForceUseSecurityHandler = bForced;
   1463     m_pSecurityHandler = pSecurityHandler;
   1464     if (m_bForceUseSecurityHandler) {
   1465         return;
   1466     }
   1467     m_Syntax.m_pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
   1468     m_Syntax.m_pCryptoHandler->Init(NULL, pSecurityHandler);
   1469 }
   1470 FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, FX_DWORD offset)
   1471 {
   1472     m_Syntax.InitParser(pFileAccess, offset);
   1473     m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9);
   1474     FX_FILESIZE SavedPos = m_Syntax.SavePos();
   1475     FX_BOOL bIsNumber;
   1476     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
   1477     if (!bIsNumber) {
   1478         return FALSE;
   1479     }
   1480     FX_DWORD objnum = FXSYS_atoi(word);
   1481     word = m_Syntax.GetNextWord(bIsNumber);
   1482     if (!bIsNumber) {
   1483         return FALSE;
   1484     }
   1485     FX_DWORD gennum = FXSYS_atoi(word);
   1486     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
   1487         m_Syntax.RestorePos(SavedPos);
   1488         return FALSE;
   1489     }
   1490     m_pLinearized = m_Syntax.GetObject(NULL, objnum, gennum, 0);
   1491     if (!m_pLinearized) {
   1492         return FALSE;
   1493     }
   1494     if (m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
   1495         m_Syntax.GetNextWord(bIsNumber);
   1496         CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
   1497         if (!pLen) {
   1498             m_pLinearized->Release();
   1499             return FALSE;
   1500         }
   1501         if (pLen->GetInteger() != (int)pFileAccess->GetSize()) {
   1502             return FALSE;
   1503         }
   1504         CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
   1505         if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
   1506             m_dwFirstPageNo = pNo->GetInteger();
   1507         }
   1508         CPDF_Object *pTable = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T"));
   1509         if (pTable && pTable->GetType() == PDFOBJ_NUMBER) {
   1510             m_LastXRefOffset = pTable->GetInteger();
   1511         }
   1512         return TRUE;
   1513     }
   1514     m_pLinearized->Release();
   1515     m_pLinearized = NULL;
   1516     return FALSE;
   1517 }
   1518 FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead)
   1519 {
   1520     CloseParser(bReParse);
   1521     m_bXRefStream = FALSE;
   1522     m_LastXRefOffset = 0;
   1523     m_bOwnFileRead = bOwnFileRead;
   1524     FX_INT32 offset = GetHeaderOffset(pFileAccess);
   1525     if (offset == -1) {
   1526         return PDFPARSE_ERROR_FORMAT;
   1527     }
   1528     if (!IsLinearizedFile(pFileAccess, offset)) {
   1529         m_Syntax.m_pFileAccess = NULL;
   1530         return StartParse(pFileAccess, bReParse, bOwnFileRead);
   1531     }
   1532     if (!bReParse) {
   1533         m_pDocument = FX_NEW CPDF_Document(this);
   1534     }
   1535     FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos();
   1536     FX_BOOL bXRefRebuilt = FALSE;
   1537     FX_BOOL bLoadV4 = FALSE;
   1538     if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) {
   1539         if (!RebuildCrossRef()) {
   1540             return PDFPARSE_ERROR_FORMAT;
   1541         }
   1542         bXRefRebuilt = TRUE;
   1543         m_LastXRefOffset = 0;
   1544     }
   1545     if (bLoadV4) {
   1546         m_pTrailer = LoadTrailerV4();
   1547         if (m_pTrailer == NULL) {
   1548             return FALSE;
   1549         }
   1550         FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
   1551         if (xrefsize == 0) {
   1552             return FALSE;
   1553         }
   1554         m_CrossRef.SetSize(xrefsize);
   1555         m_V5Type.SetSize(xrefsize);
   1556     }
   1557     FX_DWORD dwRet = SetEncryptHandler();
   1558     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
   1559         return dwRet;
   1560     }
   1561     m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
   1562     if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
   1563         if (bXRefRebuilt) {
   1564             return PDFPARSE_ERROR_FORMAT;
   1565         }
   1566         ReleaseEncryptHandler();
   1567         if (!RebuildCrossRef()) {
   1568             return PDFPARSE_ERROR_FORMAT;
   1569         }
   1570         dwRet = SetEncryptHandler();
   1571         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
   1572             return dwRet;
   1573         }
   1574         m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
   1575         if (m_pDocument->GetRoot() == NULL) {
   1576             return PDFPARSE_ERROR_FORMAT;
   1577         }
   1578     }
   1579     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
   1580     FX_DWORD RootObjNum = GetRootObjNum();
   1581     if (RootObjNum == 0) {
   1582         ReleaseEncryptHandler();
   1583         RebuildCrossRef();
   1584         RootObjNum = GetRootObjNum();
   1585         if (RootObjNum == 0) {
   1586             return PDFPARSE_ERROR_FORMAT;
   1587         }
   1588         dwRet = SetEncryptHandler();
   1589         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
   1590             return dwRet;
   1591         }
   1592     }
   1593     if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) {
   1594         CPDF_Reference* pMetadata = (CPDF_Reference*)m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
   1595         if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
   1596             m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum();
   1597         }
   1598     }
   1599     return PDFPARSE_ERROR_SUCCESS;
   1600 }
   1601 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos)
   1602 {
   1603     if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
   1604         return FALSE;
   1605     }
   1606     while (xrefpos)
   1607         if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
   1608             return FALSE;
   1609         }
   1610     m_ObjectStreamMap.InitHashTable(101, FALSE);
   1611     m_bXRefStream = TRUE;
   1612     return TRUE;
   1613 }
   1614 FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable()
   1615 {
   1616     FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum;
   1617     m_Syntax.m_MetadataObjnum = 0;
   1618     if (m_pTrailer) {
   1619         m_pTrailer->Release();
   1620         m_pTrailer = NULL;
   1621     }
   1622     m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset);
   1623     FX_FILESIZE dwSavedPos = m_Syntax.SavePos();
   1624     FX_BYTE ch = 0;
   1625     FX_DWORD dwCount = 0;
   1626     m_Syntax.GetNextChar(ch);
   1627     FX_INT32 type = _PDF_CharType[ch];
   1628     while (type == 'W') {
   1629         ++dwCount;
   1630         if (m_Syntax.m_FileLen >= (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
   1631             break;
   1632         }
   1633         m_Syntax.GetNextChar(ch);
   1634         type = _PDF_CharType[ch];
   1635     }
   1636     m_LastXRefOffset += dwCount;
   1637     FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
   1638     while (pos) {
   1639         FX_LPVOID objnum;
   1640         CPDF_StreamAcc* pStream;
   1641         m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
   1642         delete pStream;
   1643     }
   1644     m_ObjectStreamMap.RemoveAll();
   1645     if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) {
   1646         m_LastXRefOffset = 0;
   1647         m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
   1648         return PDFPARSE_ERROR_FORMAT;
   1649     }
   1650     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_DWORD), _CompareDWord);
   1651     m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
   1652     return PDFPARSE_ERROR_SUCCESS;
   1653 }
   1654 CPDF_SyntaxParser::CPDF_SyntaxParser()
   1655 {
   1656     m_pFileAccess = NULL;
   1657     m_pCryptoHandler = NULL;
   1658     m_pFileBuf = NULL;
   1659     m_BufSize = CPDF_ModuleMgr::Get()->m_FileBufSize;
   1660     m_pFileBuf = NULL;
   1661     m_MetadataObjnum = 0;
   1662     m_dwWordPos = 0;
   1663 #if defined(_FPDFAPI_MINI_)
   1664     m_bFileStream = TRUE;
   1665 #else
   1666     m_bFileStream = FALSE;
   1667 #endif
   1668 }
   1669 CPDF_SyntaxParser::~CPDF_SyntaxParser()
   1670 {
   1671     if (m_pFileBuf) {
   1672         FX_Free(m_pFileBuf);
   1673     }
   1674 }
   1675 FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, FX_BYTE& ch)
   1676 {
   1677     FX_FILESIZE save_pos = m_Pos;
   1678     m_Pos = pos;
   1679     FX_BOOL ret = GetNextChar(ch);
   1680     m_Pos = save_pos;
   1681     return ret;
   1682 }
   1683 FX_BOOL CPDF_SyntaxParser::GetNextChar(FX_BYTE& ch)
   1684 {
   1685     FX_FILESIZE pos = m_Pos + m_HeaderOffset;
   1686     if (pos >= m_FileLen) {
   1687         return FALSE;
   1688     }
   1689     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
   1690         FX_FILESIZE read_pos = pos;
   1691         FX_DWORD read_size = m_BufSize;
   1692         if ((FX_FILESIZE)read_size > m_FileLen) {
   1693             read_size = (FX_DWORD)m_FileLen;
   1694         }
   1695         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
   1696             if (m_FileLen < (FX_FILESIZE)read_size) {
   1697                 read_pos = 0;
   1698                 read_size = (FX_DWORD)m_FileLen;
   1699             } else {
   1700                 read_pos = m_FileLen - read_size;
   1701             }
   1702         }
   1703         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
   1704             return FALSE;
   1705         }
   1706         m_BufOffset = read_pos;
   1707     }
   1708     ch = m_pFileBuf[pos - m_BufOffset];
   1709     m_Pos ++;
   1710     return TRUE;
   1711 }
   1712 FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, FX_BYTE& ch)
   1713 {
   1714     pos += m_HeaderOffset;
   1715     if (pos >= m_FileLen) {
   1716         return FALSE;
   1717     }
   1718     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
   1719         FX_FILESIZE read_pos;
   1720         if (pos < (FX_FILESIZE)m_BufSize) {
   1721             read_pos = 0;
   1722         } else {
   1723             read_pos = pos - m_BufSize + 1;
   1724         }
   1725         FX_DWORD read_size = m_BufSize;
   1726         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
   1727             if (m_FileLen < (FX_FILESIZE)read_size) {
   1728                 read_pos = 0;
   1729                 read_size = (FX_DWORD)m_FileLen;
   1730             } else {
   1731                 read_pos = m_FileLen - read_size;
   1732             }
   1733         }
   1734         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
   1735             return FALSE;
   1736         }
   1737         m_BufOffset = read_pos;
   1738     }
   1739     ch = m_pFileBuf[pos - m_BufOffset];
   1740     return TRUE;
   1741 }
   1742 FX_BOOL CPDF_SyntaxParser::ReadBlock(FX_LPBYTE pBuf, FX_DWORD size)
   1743 {
   1744     if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) {
   1745         return FALSE;
   1746     }
   1747     m_Pos += size;
   1748     return TRUE;
   1749 }
   1750 #define MAX_WORD_BUFFER 256
   1751 void CPDF_SyntaxParser::GetNextWord()
   1752 {
   1753     m_WordSize = 0;
   1754     m_bIsNumber = TRUE;
   1755     FX_BYTE ch;
   1756     if (!GetNextChar(ch)) {
   1757         return;
   1758     }
   1759     FX_BYTE type = _PDF_CharType[ch];
   1760     while (1) {
   1761         while (type == 'W') {
   1762             if (!GetNextChar(ch)) {
   1763                 return;
   1764             }
   1765             type = _PDF_CharType[ch];
   1766         }
   1767         if (ch != '%') {
   1768             break;
   1769         }
   1770         while (1) {
   1771             if (!GetNextChar(ch)) {
   1772                 return;
   1773             }
   1774             if (ch == '\r' || ch == '\n') {
   1775                 break;
   1776             }
   1777         }
   1778         type = _PDF_CharType[ch];
   1779     }
   1780     if (type == 'D') {
   1781         m_bIsNumber = FALSE;
   1782         m_WordBuffer[m_WordSize++] = ch;
   1783         if (ch == '/') {
   1784             while (1) {
   1785                 if (!GetNextChar(ch)) {
   1786                     return;
   1787                 }
   1788                 type = _PDF_CharType[ch];
   1789                 if (type != 'R' && type != 'N') {
   1790                     m_Pos --;
   1791                     return;
   1792                 }
   1793                 if (m_WordSize < MAX_WORD_BUFFER) {
   1794                     m_WordBuffer[m_WordSize++] = ch;
   1795                 }
   1796             }
   1797         } else if (ch == '<') {
   1798             if (!GetNextChar(ch)) {
   1799                 return;
   1800             }
   1801             if (ch == '<') {
   1802                 m_WordBuffer[m_WordSize++] = ch;
   1803             } else {
   1804                 m_Pos --;
   1805             }
   1806         } else if (ch == '>') {
   1807             if (!GetNextChar(ch)) {
   1808                 return;
   1809             }
   1810             if (ch == '>') {
   1811                 m_WordBuffer[m_WordSize++] = ch;
   1812             } else {
   1813                 m_Pos --;
   1814             }
   1815         }
   1816         return;
   1817     }
   1818     while (1) {
   1819         if (m_WordSize < MAX_WORD_BUFFER) {
   1820             m_WordBuffer[m_WordSize++] = ch;
   1821         }
   1822         if (type != 'N') {
   1823             m_bIsNumber = FALSE;
   1824         }
   1825         if (!GetNextChar(ch)) {
   1826             return;
   1827         }
   1828         type = _PDF_CharType[ch];
   1829         if (type == 'D' || type == 'W') {
   1830             m_Pos --;
   1831             break;
   1832         }
   1833     }
   1834 }
   1835 CFX_ByteString CPDF_SyntaxParser::ReadString()
   1836 {
   1837     FX_BYTE ch;
   1838     if (!GetNextChar(ch)) {
   1839         return CFX_ByteString();
   1840     }
   1841     CFX_ByteTextBuf buf;
   1842     FX_INT32 parlevel = 0;
   1843     FX_INT32 status = 0, iEscCode = 0;
   1844     while (1) {
   1845         switch (status) {
   1846             case 0:
   1847                 if (ch == ')') {
   1848                     if (parlevel == 0) {
   1849                         return buf.GetByteString();
   1850                     }
   1851                     parlevel --;
   1852                     buf.AppendChar(')');
   1853                 } else if (ch == '(') {
   1854                     parlevel ++;
   1855                     buf.AppendChar('(');
   1856                 } else if (ch == '\\') {
   1857                     status = 1;
   1858                 } else {
   1859                     buf.AppendChar(ch);
   1860                 }
   1861                 break;
   1862             case 1:
   1863                 if (ch >= '0' && ch <= '7') {
   1864                     iEscCode = ch - '0';
   1865                     status = 2;
   1866                     break;
   1867                 }
   1868                 if (ch == 'n') {
   1869                     buf.AppendChar('\n');
   1870                 } else if (ch == 'r') {
   1871                     buf.AppendChar('\r');
   1872                 } else if (ch == 't') {
   1873                     buf.AppendChar('\t');
   1874                 } else if (ch == 'b') {
   1875                     buf.AppendChar('\b');
   1876                 } else if (ch == 'f') {
   1877                     buf.AppendChar('\f');
   1878                 } else if (ch == '\r') {
   1879                     status = 4;
   1880                     break;
   1881                 } else if (ch == '\n') {
   1882                 } else {
   1883                     buf.AppendChar(ch);
   1884                 }
   1885                 status = 0;
   1886                 break;
   1887             case 2:
   1888                 if (ch >= '0' && ch <= '7') {
   1889                     iEscCode = iEscCode * 8 + ch - '0';
   1890                     status = 3;
   1891                 } else {
   1892                     buf.AppendChar(iEscCode);
   1893                     status = 0;
   1894                     continue;
   1895                 }
   1896                 break;
   1897             case 3:
   1898                 if (ch >= '0' && ch <= '7') {
   1899                     iEscCode = iEscCode * 8 + ch - '0';
   1900                     buf.AppendChar(iEscCode);
   1901                     status = 0;
   1902                 } else {
   1903                     buf.AppendChar(iEscCode);
   1904                     status = 0;
   1905                     continue;
   1906                 }
   1907                 break;
   1908             case 4:
   1909                 status = 0;
   1910                 if (ch != '\n') {
   1911                     continue;
   1912                 }
   1913                 break;
   1914         }
   1915         if (!GetNextChar(ch)) {
   1916             break;
   1917         }
   1918     }
   1919     GetNextChar(ch);
   1920     return buf.GetByteString();
   1921 }
   1922 CFX_ByteString CPDF_SyntaxParser::ReadHexString()
   1923 {
   1924     FX_BYTE ch;
   1925     if (!GetNextChar(ch)) {
   1926         return CFX_ByteString();
   1927     }
   1928     CFX_BinaryBuf buf;
   1929     FX_BOOL bFirst = TRUE;
   1930     FX_BYTE code = 0;
   1931     while (1) {
   1932         if (ch == '>') {
   1933             break;
   1934         }
   1935         if (ch >= '0' && ch <= '9') {
   1936             if (bFirst) {
   1937                 code = (ch - '0') * 16;
   1938             } else {
   1939                 code += ch - '0';
   1940                 buf.AppendByte((FX_BYTE)code);
   1941             }
   1942             bFirst = !bFirst;
   1943         } else if (ch >= 'A' && ch <= 'F') {
   1944             if (bFirst) {
   1945                 code = (ch - 'A' + 10) * 16;
   1946             } else {
   1947                 code += ch - 'A' + 10;
   1948                 buf.AppendByte((FX_BYTE)code);
   1949             }
   1950             bFirst = !bFirst;
   1951         } else if (ch >= 'a' && ch <= 'f') {
   1952             if (bFirst) {
   1953                 code = (ch - 'a' + 10) * 16;
   1954             } else {
   1955                 code += ch - 'a' + 10;
   1956                 buf.AppendByte((FX_BYTE)code);
   1957             }
   1958             bFirst = !bFirst;
   1959         }
   1960         if (!GetNextChar(ch)) {
   1961             break;
   1962         }
   1963     }
   1964     if (!bFirst) {
   1965         buf.AppendByte((FX_BYTE)code);
   1966     }
   1967     return buf.GetByteString();
   1968 }
   1969 void CPDF_SyntaxParser::ToNextLine()
   1970 {
   1971     FX_BYTE ch;
   1972     while (1) {
   1973         if (!GetNextChar(ch)) {
   1974             return;
   1975         }
   1976         if (ch == '\n') {
   1977             return;
   1978         }
   1979         if (ch == '\r') {
   1980             GetNextChar(ch);
   1981             if (ch == '\n') {
   1982                 return;
   1983             } else {
   1984                 m_Pos --;
   1985                 return;
   1986             }
   1987         }
   1988     }
   1989 }
   1990 void CPDF_SyntaxParser::ToNextWord()
   1991 {
   1992     FX_BYTE ch;
   1993     if (!GetNextChar(ch)) {
   1994         return;
   1995     }
   1996     FX_BYTE type = _PDF_CharType[ch];
   1997     while (1) {
   1998         while (type == 'W') {
   1999             m_dwWordPos = m_Pos;
   2000             if (!GetNextChar(ch)) {
   2001                 return;
   2002             }
   2003             type = _PDF_CharType[ch];
   2004         }
   2005         if (ch != '%') {
   2006             break;
   2007         }
   2008         while (1) {
   2009             if (!GetNextChar(ch)) {
   2010                 return;
   2011             }
   2012             if (ch == '\r' || ch == '\n') {
   2013                 break;
   2014             }
   2015         }
   2016         type = _PDF_CharType[ch];
   2017     }
   2018     m_Pos --;
   2019 }
   2020 CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber)
   2021 {
   2022     GetNextWord();
   2023     bIsNumber = m_bIsNumber;
   2024     return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
   2025 }
   2026 CFX_ByteString CPDF_SyntaxParser::GetKeyword()
   2027 {
   2028     GetNextWord();
   2029     return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
   2030 }
   2031 CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, FX_INT32 level, PARSE_CONTEXT* pContext, FX_BOOL bDecrypt)
   2032 {
   2033     if (level > _PARSER_OBJECT_LEVLE_) {
   2034         return NULL;
   2035     }
   2036     FX_FILESIZE SavedPos = m_Pos;
   2037     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
   2038     FX_BOOL bIsNumber;
   2039     CFX_ByteString word = GetNextWord(bIsNumber);
   2040     CPDF_Object* pRet = NULL;
   2041     if (word.GetLength() == 0) {
   2042         if (bTypeOnly) {
   2043             return (CPDF_Object*)PDFOBJ_INVALID;
   2044         }
   2045         return NULL;
   2046     }
   2047     FX_FILESIZE wordOffset = m_Pos - word.GetLength();
   2048     if (bIsNumber) {
   2049         FX_FILESIZE SavedPos = m_Pos;
   2050         CFX_ByteString nextword = GetNextWord(bIsNumber);
   2051         if (bIsNumber) {
   2052             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
   2053             if (nextword2 == FX_BSTRC("R")) {
   2054                 FX_DWORD objnum = FXSYS_atoi(word);
   2055                 if (bTypeOnly) {
   2056                     return (CPDF_Object*)PDFOBJ_REFERENCE;
   2057                 }
   2058                 pRet = CPDF_Reference::Create(pObjList, objnum);
   2059                 return pRet;
   2060             } else {
   2061                 m_Pos = SavedPos;
   2062                 if (bTypeOnly) {
   2063                     return (CPDF_Object*)PDFOBJ_NUMBER;
   2064                 }
   2065                 pRet = CPDF_Number::Create(word);
   2066                 return pRet;
   2067             }
   2068         } else {
   2069             m_Pos = SavedPos;
   2070             if (bTypeOnly) {
   2071                 return (CPDF_Object*)PDFOBJ_NUMBER;
   2072             }
   2073             pRet = CPDF_Number::Create(word);
   2074             return pRet;
   2075         }
   2076     }
   2077     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
   2078         if (bTypeOnly) {
   2079             return (CPDF_Object*)PDFOBJ_BOOLEAN;
   2080         }
   2081         pRet = CPDF_Boolean::Create(word == FX_BSTRC("true"));
   2082         return pRet;
   2083     }
   2084     if (word == FX_BSTRC("null")) {
   2085         if (bTypeOnly) {
   2086             return (CPDF_Object*)PDFOBJ_NULL;
   2087         }
   2088         pRet = CPDF_Null::Create();
   2089         return pRet;
   2090     }
   2091     if (word == FX_BSTRC("(")) {
   2092         if (bTypeOnly) {
   2093             return (CPDF_Object*)PDFOBJ_STRING;
   2094         }
   2095         FX_FILESIZE SavedPos = m_Pos - 1;
   2096         CFX_ByteString str = ReadString();
   2097         if (m_pCryptoHandler && bDecrypt) {
   2098             m_pCryptoHandler->Decrypt(objnum, gennum, str);
   2099         }
   2100         pRet = CPDF_String::Create(str, FALSE);
   2101         return pRet;
   2102     }
   2103     if (word == FX_BSTRC("<")) {
   2104         if (bTypeOnly) {
   2105             return (CPDF_Object*)PDFOBJ_STRING;
   2106         }
   2107         FX_FILESIZE SavedPos = m_Pos - 1;
   2108         CFX_ByteString str = ReadHexString();
   2109         if (m_pCryptoHandler && bDecrypt) {
   2110             m_pCryptoHandler->Decrypt(objnum, gennum, str);
   2111         }
   2112         pRet = CPDF_String::Create(str, TRUE);
   2113         return pRet;
   2114     }
   2115     if (word == FX_BSTRC("[")) {
   2116         if (bTypeOnly) {
   2117             return (CPDF_Object*)PDFOBJ_ARRAY;
   2118         }
   2119         CPDF_Array* pArray = CPDF_Array::Create();
   2120         FX_FILESIZE firstPos = m_Pos - 1;
   2121         while (1) {
   2122             FX_FILESIZE SavedPos = m_Pos;
   2123             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
   2124             if (pObj == NULL) {
   2125                 return pArray;
   2126             }
   2127             pArray->Add(pObj);
   2128         }
   2129     }
   2130     if (word[0] == '/') {
   2131         if (bTypeOnly) {
   2132             return (CPDF_Object*)PDFOBJ_NAME;
   2133         }
   2134         pRet = CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
   2135         return pRet;
   2136     }
   2137     if (word == FX_BSTRC("<<")) {
   2138         FX_FILESIZE saveDictOffset = m_Pos - 2;
   2139         FX_DWORD dwDictSize = 0;
   2140         if (bTypeOnly) {
   2141             return (CPDF_Object*)PDFOBJ_DICTIONARY;
   2142         }
   2143         if (pContext) {
   2144             pContext->m_DictStart = SavedPos;
   2145         }
   2146         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
   2147         FX_INT32 nKeys = 0;
   2148         FX_FILESIZE dwSignValuePos = 0;
   2149         while (1) {
   2150             FX_BOOL bIsNumber;
   2151             CFX_ByteString key = GetNextWord(bIsNumber);
   2152             if (key.IsEmpty()) {
   2153                 pDict->Release();
   2154                 return NULL;
   2155             }
   2156             FX_FILESIZE SavedPos = m_Pos - key.GetLength();
   2157             if (key == FX_BSTRC(">>")) {
   2158                 dwDictSize = m_Pos - saveDictOffset;
   2159                 break;
   2160             }
   2161             if (key == FX_BSTRC("endobj")) {
   2162                 dwDictSize = m_Pos - 6 - saveDictOffset;
   2163                 m_Pos = SavedPos;
   2164                 break;
   2165             }
   2166             if (key[0] != '/') {
   2167                 continue;
   2168             }
   2169             nKeys ++;
   2170             key = PDF_NameDecode(key);
   2171             if (key == FX_BSTRC("/Contents")) {
   2172                 dwSignValuePos = m_Pos;
   2173             }
   2174             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
   2175             if (pObj == NULL) {
   2176                 continue;
   2177             }
   2178             if (key.GetLength() == 1) {
   2179                 pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
   2180             } else {
   2181                 if (nKeys < 32) {
   2182                     pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
   2183                 } else {
   2184                     pDict->AddValue(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
   2185                 }
   2186             }
   2187         }
   2188         if (IsSignatureDict(pDict)) {
   2189             FX_FILESIZE dwSavePos = m_Pos;
   2190             m_Pos = dwSignValuePos;
   2191             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1, NULL, FALSE);
   2192             pDict->SetAt(FX_BSTRC("Contents"), pObj);
   2193             m_Pos = dwSavePos;
   2194         }
   2195         if (pContext) {
   2196             pContext->m_DictEnd = m_Pos;
   2197             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
   2198                 return pDict;
   2199             }
   2200         }
   2201         FX_FILESIZE SavedPos = m_Pos;
   2202         FX_BOOL bIsNumber;
   2203         CFX_ByteString nextword = GetNextWord(bIsNumber);
   2204         if (nextword == FX_BSTRC("stream")) {
   2205             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
   2206             if (pStream) {
   2207                 return pStream;
   2208             }
   2209             pDict->Release();
   2210             return NULL;
   2211         } else {
   2212             m_Pos = SavedPos;
   2213             return pDict;
   2214         }
   2215     }
   2216     if (word == FX_BSTRC(">>")) {
   2217         m_Pos = SavedPos;
   2218         return NULL;
   2219     }
   2220     if (bTypeOnly) {
   2221         return (CPDF_Object*)PDFOBJ_INVALID;
   2222     }
   2223     return NULL;
   2224 }
   2225 CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum,
   2226         FX_INT32 level, struct PARSE_CONTEXT* pContext)
   2227 {
   2228     if (level > _PARSER_OBJECT_LEVLE_) {
   2229         return NULL;
   2230     }
   2231     FX_FILESIZE SavedPos = m_Pos;
   2232     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
   2233     FX_BOOL bIsNumber;
   2234     CFX_ByteString word = GetNextWord(bIsNumber);
   2235     if (word.GetLength() == 0) {
   2236         if (bTypeOnly) {
   2237             return (CPDF_Object*)PDFOBJ_INVALID;
   2238         }
   2239         return NULL;
   2240     }
   2241     if (bIsNumber) {
   2242         FX_FILESIZE SavedPos = m_Pos;
   2243         CFX_ByteString nextword = GetNextWord(bIsNumber);
   2244         if (bIsNumber) {
   2245             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
   2246             if (nextword2 == FX_BSTRC("R")) {
   2247                 FX_DWORD objnum = FXSYS_atoi(word);
   2248                 if (bTypeOnly) {
   2249                     return (CPDF_Object*)PDFOBJ_REFERENCE;
   2250                 }
   2251                 return CPDF_Reference::Create(pObjList, objnum);
   2252             } else {
   2253                 m_Pos = SavedPos;
   2254                 if (bTypeOnly) {
   2255                     return (CPDF_Object*)PDFOBJ_NUMBER;
   2256                 }
   2257                 return CPDF_Number::Create(word);
   2258             }
   2259         } else {
   2260             m_Pos = SavedPos;
   2261             if (bTypeOnly) {
   2262                 return (CPDF_Object*)PDFOBJ_NUMBER;
   2263             }
   2264             return CPDF_Number::Create(word);
   2265         }
   2266     }
   2267     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
   2268         if (bTypeOnly) {
   2269             return (CPDF_Object*)PDFOBJ_BOOLEAN;
   2270         }
   2271         return CPDF_Boolean::Create(word == FX_BSTRC("true"));
   2272     }
   2273     if (word == FX_BSTRC("null")) {
   2274         if (bTypeOnly) {
   2275             return (CPDF_Object*)PDFOBJ_NULL;
   2276         }
   2277         return CPDF_Null::Create();
   2278     }
   2279     if (word == FX_BSTRC("(")) {
   2280         if (bTypeOnly) {
   2281             return (CPDF_Object*)PDFOBJ_STRING;
   2282         }
   2283         CFX_ByteString str = ReadString();
   2284         if (m_pCryptoHandler) {
   2285             m_pCryptoHandler->Decrypt(objnum, gennum, str);
   2286         }
   2287         return CPDF_String::Create(str, FALSE);
   2288     }
   2289     if (word == FX_BSTRC("<")) {
   2290         if (bTypeOnly) {
   2291             return (CPDF_Object*)PDFOBJ_STRING;
   2292         }
   2293         CFX_ByteString str = ReadHexString();
   2294         if (m_pCryptoHandler) {
   2295             m_pCryptoHandler->Decrypt(objnum, gennum, str);
   2296         }
   2297         return CPDF_String::Create(str, TRUE);
   2298     }
   2299     if (word == FX_BSTRC("[")) {
   2300         if (bTypeOnly) {
   2301             return (CPDF_Object*)PDFOBJ_ARRAY;
   2302         }
   2303         CPDF_Array* pArray = CPDF_Array::Create();
   2304         while (1) {
   2305             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
   2306             if (pObj == NULL) {
   2307                 if (m_WordBuffer[0] == ']') {
   2308                     return pArray;
   2309                 }
   2310                 pArray->Release();
   2311                 return NULL;
   2312             }
   2313             pArray->Add(pObj);
   2314         }
   2315     }
   2316     if (word[0] == '/') {
   2317         if (bTypeOnly) {
   2318             return (CPDF_Object*)PDFOBJ_NAME;
   2319         }
   2320         return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
   2321     }
   2322     if (word == FX_BSTRC("<<")) {
   2323         if (bTypeOnly) {
   2324             return (CPDF_Object*)PDFOBJ_DICTIONARY;
   2325         }
   2326         if (pContext) {
   2327             pContext->m_DictStart = SavedPos;
   2328         }
   2329         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
   2330         while (1) {
   2331             FX_BOOL bIsNumber;
   2332             FX_FILESIZE SavedPos = m_Pos;
   2333             CFX_ByteString key = GetNextWord(bIsNumber);
   2334             if (key.IsEmpty()) {
   2335                 pDict->Release();
   2336                 return NULL;
   2337             }
   2338             if (key == FX_BSTRC(">>")) {
   2339                 break;
   2340             }
   2341             if (key == FX_BSTRC("endobj")) {
   2342                 m_Pos = SavedPos;
   2343                 break;
   2344             }
   2345             if (key[0] != '/') {
   2346                 continue;
   2347             }
   2348             key = PDF_NameDecode(key);
   2349             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
   2350             if (pObj == NULL) {
   2351                 pDict->Release();
   2352                 FX_BYTE ch;
   2353                 while (1) {
   2354                     if (!GetNextChar(ch)) {
   2355                         break;
   2356                     }
   2357                     if (ch == 0x0A || ch == 0x0D) {
   2358                         break;
   2359                     }
   2360                 }
   2361                 return NULL;
   2362             }
   2363             if (key.GetLength() == 1) {
   2364                 pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
   2365             } else {
   2366                 pDict->AddValue(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
   2367             }
   2368         }
   2369         if (pContext) {
   2370             pContext->m_DictEnd = m_Pos;
   2371             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
   2372                 return pDict;
   2373             }
   2374         }
   2375         FX_FILESIZE SavedPos = m_Pos;
   2376         FX_BOOL bIsNumber;
   2377         CFX_ByteString nextword = GetNextWord(bIsNumber);
   2378         if (nextword == FX_BSTRC("stream")) {
   2379             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
   2380             if (pStream) {
   2381                 return pStream;
   2382             }
   2383             pDict->Release();
   2384             return NULL;
   2385         } else {
   2386             m_Pos = SavedPos;
   2387             return pDict;
   2388         }
   2389     }
   2390     if (word == FX_BSTRC(">>")) {
   2391         m_Pos = SavedPos;
   2392         return NULL;
   2393     }
   2394     if (bTypeOnly) {
   2395         return (CPDF_Object*)PDFOBJ_INVALID;
   2396     }
   2397     return NULL;
   2398 }
   2399 CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, PARSE_CONTEXT* pContext,
   2400         FX_DWORD objnum, FX_DWORD gennum)
   2401 {
   2402     CPDF_Object* pLenObj = pDict->GetElement(FX_BSTRC("Length"));
   2403     FX_DWORD len = 0;
   2404     if (pLenObj && (pLenObj->GetType() != PDFOBJ_REFERENCE ||
   2405                     ((((CPDF_Reference*)pLenObj)->GetObjList() != NULL) &&
   2406                      ((CPDF_Reference*)pLenObj)->GetRefObjNum() != objnum))) {
   2407         FX_FILESIZE pos = m_Pos;
   2408         if (pLenObj) {
   2409             len = pLenObj->GetInteger();
   2410         }
   2411         m_Pos = pos;
   2412         if (len > 0x40000000) {
   2413             return NULL;
   2414         }
   2415     }
   2416     ToNextLine();
   2417     FX_FILESIZE StreamStartPos = m_Pos;
   2418     if (pContext) {
   2419         pContext->m_DataStart = m_Pos;
   2420     }
   2421     m_Pos += len;
   2422     CPDF_CryptoHandler* pCryptoHandler = objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler;
   2423     if (pCryptoHandler == NULL) {
   2424         FX_FILESIZE SavedPos = m_Pos;
   2425         GetNextWord();
   2426         if (m_WordSize < 9 || FXSYS_memcmp32(m_WordBuffer, "endstream", 9)) {
   2427             m_Pos = StreamStartPos;
   2428             FX_FILESIZE offset = FindTag(FX_BSTRC("endstream"), 0);
   2429             if (offset >= 0) {
   2430                 FX_FILESIZE curPos = m_Pos;
   2431                 m_Pos = StreamStartPos;
   2432                 FX_FILESIZE endobjOffset = FindTag(FX_BSTRC("endobj"), 0);
   2433                 if (endobjOffset < offset && endobjOffset >= 0) {
   2434                     offset = endobjOffset;
   2435                 } else {
   2436                     m_Pos = curPos;
   2437                 }
   2438                 FX_BYTE byte1, byte2;
   2439                 GetCharAt(StreamStartPos + offset - 1, byte1);
   2440                 GetCharAt(StreamStartPos + offset - 2, byte2);
   2441                 if (byte1 == 0x0a && byte2 == 0x0d) {
   2442                     len -= 2;
   2443                 } else if (byte1 == 0x0a || byte1 == 0x0d) {
   2444                     len --;
   2445                 }
   2446                 len = (FX_DWORD)offset;
   2447                 pDict->SetAtInteger(FX_BSTRC("Length"), len);
   2448             } else {
   2449                 m_Pos = StreamStartPos;
   2450                 if (FindTag(FX_BSTRC("endobj"), 0) < 0) {
   2451                     return NULL;
   2452                 }
   2453             }
   2454         }
   2455     }
   2456     m_Pos = StreamStartPos;
   2457     CPDF_Stream* pStream;
   2458 #if defined(_FPDFAPI_MINI_) && !defined(_FXCORE_FEATURE_ALL_)
   2459     pStream = FX_NEW CPDF_Stream(m_pFileAccess, pCryptoHandler, m_HeaderOffset + m_Pos, len, pDict, gennum);
   2460     m_Pos += len;
   2461 #else
   2462     FX_LPBYTE pData = FX_Alloc(FX_BYTE, len);
   2463     if (!pData) {
   2464         return NULL;
   2465     }
   2466     ReadBlock(pData, len);
   2467     if (pCryptoHandler) {
   2468         CFX_BinaryBuf dest_buf;
   2469         dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len));
   2470         FX_LPVOID context = pCryptoHandler->DecryptStart(objnum, gennum);
   2471         pCryptoHandler->DecryptStream(context, pData, len, dest_buf);
   2472         pCryptoHandler->DecryptFinish(context, dest_buf);
   2473         FX_Free(pData);
   2474         pData = dest_buf.GetBuffer();
   2475         len = dest_buf.GetSize();
   2476         dest_buf.DetachBuffer();
   2477     }
   2478     pStream = FX_NEW CPDF_Stream(pData, len, pDict);
   2479 #endif
   2480     if (pContext) {
   2481         pContext->m_DataEnd = pContext->m_DataStart + len;
   2482     }
   2483     StreamStartPos = m_Pos;
   2484     GetNextWord();
   2485     if (m_WordSize == 6 && 0 == FXSYS_memcmp32(m_WordBuffer, "endobj", 6)) {
   2486         m_Pos = StreamStartPos;
   2487     }
   2488     return pStream;
   2489 }
   2490 void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess, FX_DWORD HeaderOffset)
   2491 {
   2492     if (m_pFileBuf) {
   2493         FX_Free(m_pFileBuf);
   2494         m_pFileBuf = NULL;
   2495     }
   2496     m_pFileBuf = FX_Alloc(FX_BYTE, m_BufSize);
   2497     m_HeaderOffset = HeaderOffset;
   2498     m_FileLen = pFileAccess->GetSize();
   2499     m_Pos = 0;
   2500     m_pFileAccess = pFileAccess;
   2501     m_BufOffset = 0;
   2502     pFileAccess->ReadBlock(m_pFileBuf, 0, (size_t)((FX_FILESIZE)m_BufSize > m_FileLen ? m_FileLen : m_BufSize));
   2503 }
   2504 FX_INT32 CPDF_SyntaxParser::GetDirectNum()
   2505 {
   2506     GetNextWord();
   2507     if (!m_bIsNumber) {
   2508         return 0;
   2509     }
   2510     m_WordBuffer[m_WordSize] = 0;
   2511     return FXSYS_atoi((FX_LPCSTR)m_WordBuffer);
   2512 }
   2513 FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit, FX_LPCBYTE tag, FX_DWORD taglen)
   2514 {
   2515     FX_BYTE type = _PDF_CharType[tag[0]];
   2516     FX_BOOL bCheckLeft = type != 'D' && type != 'W';
   2517     type = _PDF_CharType[tag[taglen - 1]];
   2518     FX_BOOL bCheckRight = type != 'D' || type != 'W';
   2519     FX_BYTE ch;
   2520     if (bCheckRight && startpos + (FX_INT32)taglen <= limit && GetCharAt(startpos + (FX_INT32)taglen, ch)) {
   2521         FX_BYTE type = _PDF_CharType[ch];
   2522         if (type == 'N' || type == 'R') {
   2523             return FALSE;
   2524         }
   2525     }
   2526     if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
   2527         FX_BYTE type = _PDF_CharType[ch];
   2528         if (type == 'N' || type == 'R') {
   2529             return FALSE;
   2530         }
   2531     }
   2532     return TRUE;
   2533 }
   2534 FX_BOOL CPDF_SyntaxParser::SearchWord(FX_BSTR tag, FX_BOOL bWholeWord, FX_BOOL bForward, FX_FILESIZE limit)
   2535 {
   2536     FX_INT32 taglen = tag.GetLength();
   2537     if (taglen == 0) {
   2538         return FALSE;
   2539     }
   2540     FX_FILESIZE pos = m_Pos;
   2541     FX_INT32 offset = 0;
   2542     if (!bForward) {
   2543         offset = taglen - 1;
   2544     }
   2545     FX_LPCBYTE tag_data = tag;
   2546     FX_BYTE byte;
   2547     while (1) {
   2548         if (bForward) {
   2549             if (limit) {
   2550                 if (pos >= m_Pos + limit) {
   2551                     return FALSE;
   2552                 }
   2553             }
   2554             if (!GetCharAt(pos, byte)) {
   2555                 return FALSE;
   2556             }
   2557         } else {
   2558             if (limit) {
   2559                 if (pos <= m_Pos - limit) {
   2560                     return FALSE;
   2561                 }
   2562             }
   2563             if (!GetCharAtBackward(pos, byte)) {
   2564                 return FALSE;
   2565             }
   2566         }
   2567         if (byte == tag_data[offset]) {
   2568             if (bForward) {
   2569                 offset ++;
   2570                 if (offset < taglen) {
   2571                     pos ++;
   2572                     continue;
   2573                 }
   2574             } else {
   2575                 offset --;
   2576                 if (offset >= 0) {
   2577                     pos --;
   2578                     continue;
   2579                 }
   2580             }
   2581             FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos;
   2582             if (!bWholeWord || IsWholeWord(startpos, limit, tag, taglen)) {
   2583                 m_Pos = startpos;
   2584                 return TRUE;
   2585             }
   2586         }
   2587         if (bForward) {
   2588             offset = byte == tag_data[0] ? 1 : 0;
   2589             pos ++;
   2590         } else {
   2591             offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1;
   2592             pos --;
   2593         }
   2594         if (pos < 0) {
   2595             return FALSE;
   2596         }
   2597     }
   2598     return FALSE;
   2599 }
   2600 struct _SearchTagRecord {
   2601     FX_LPCBYTE	m_pTag;
   2602     FX_DWORD	m_Len;
   2603     FX_DWORD	m_Offset;
   2604 };
   2605 FX_INT32 CPDF_SyntaxParser::SearchMultiWord(FX_BSTR tags, FX_BOOL bWholeWord, FX_FILESIZE limit)
   2606 {
   2607     FX_INT32 ntags = 1, i;
   2608     for (i = 0; i < tags.GetLength(); i ++)
   2609         if (tags[i] == 0) {
   2610             ntags ++;
   2611         }
   2612     _SearchTagRecord* pPatterns = FX_Alloc(_SearchTagRecord, ntags);
   2613     FX_DWORD start = 0, itag = 0, max_len = 0;
   2614     for (i = 0; i <= tags.GetLength(); i ++) {
   2615         if (tags[i] == 0) {
   2616             FX_DWORD len = i - start;
   2617             if (len > max_len) {
   2618                 max_len = len;
   2619             }
   2620             pPatterns[itag].m_pTag = tags.GetPtr() + start;
   2621             pPatterns[itag].m_Len = len;
   2622             pPatterns[itag].m_Offset = 0;
   2623             start = i + 1;
   2624             itag ++;
   2625         }
   2626     }
   2627     FX_FILESIZE pos = m_Pos;
   2628     FX_BYTE byte;
   2629     GetCharAt(pos++, byte);
   2630     FX_INT32 found = -1;
   2631     while (1) {
   2632         for (i = 0; i < ntags; i ++) {
   2633             if (pPatterns[i].m_pTag[pPatterns[i].m_Offset] == byte) {
   2634                 pPatterns[i].m_Offset ++;
   2635                 if (pPatterns[i].m_Offset == pPatterns[i].m_Len) {
   2636                     if (!bWholeWord || IsWholeWord(pos - pPatterns[i].m_Len, limit, pPatterns[i].m_pTag, pPatterns[i].m_Len)) {
   2637                         found = i;
   2638                         goto end;
   2639                     } else {
   2640                         if (pPatterns[i].m_pTag[0] == byte) {
   2641                             pPatterns[i].m_Offset = 1;
   2642                         } else {
   2643                             pPatterns[i].m_Offset = 0;
   2644                         }
   2645                     }
   2646                 }
   2647             } else {
   2648                 if (pPatterns[i].m_pTag[0] == byte) {
   2649                     pPatterns[i].m_Offset = 1;
   2650                 } else {
   2651                     pPatterns[i].m_Offset = 0;
   2652                 }
   2653             }
   2654         }
   2655         if (limit && pos >= m_Pos + limit) {
   2656             goto end;
   2657         }
   2658         if (!GetCharAt(pos, byte)) {
   2659             goto end;
   2660         }
   2661         pos ++;
   2662     }
   2663 end:
   2664     FX_Free(pPatterns);
   2665     return found;
   2666 }
   2667 FX_FILESIZE CPDF_SyntaxParser::FindTag(FX_BSTR tag, FX_FILESIZE limit)
   2668 {
   2669     FX_INT32 taglen = tag.GetLength();
   2670     FX_INT32 match = 0;
   2671     limit += m_Pos;
   2672     FX_FILESIZE startpos = m_Pos;
   2673     while (1) {
   2674         FX_BYTE ch;
   2675         if (!GetNextChar(ch)) {
   2676             return -1;
   2677         }
   2678         if (ch == tag[match]) {
   2679             match ++;
   2680             if (match == taglen) {
   2681                 return m_Pos - startpos - taglen;
   2682             }
   2683         } else {
   2684             match = ch == tag[0] ? 1 : 0;
   2685         }
   2686         if (limit && m_Pos == limit) {
   2687             return -1;
   2688         }
   2689     }
   2690     return -1;
   2691 }
   2692 void CPDF_SyntaxParser::GetBinary(FX_BYTE* buffer, FX_DWORD size)
   2693 {
   2694     FX_DWORD offset = 0;
   2695     FX_BYTE ch;
   2696     while (1) {
   2697         if (!GetNextChar(ch)) {
   2698             return;
   2699         }
   2700         buffer[offset++] = ch;
   2701         if (offset == size) {
   2702             break;
   2703         }
   2704     }
   2705 }
   2706 CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead)
   2707 {
   2708     m_pFileAvail = pFileAvail;
   2709     m_pFileRead = pFileRead;
   2710     m_Pos = 0;
   2711     m_dwFileLen = 0;
   2712     if (m_pFileRead) {
   2713         m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
   2714     }
   2715     m_dwCurrentOffset = 0;
   2716     m_WordSize = 0;
   2717     m_dwXRefOffset = 0;
   2718     m_bufferOffset = 0;
   2719     m_dwFirstPageNo = 0;
   2720     m_bufferSize = 0;
   2721     m_PagesObjNum = 0;
   2722     m_dwCurrentXRefSteam = 0;
   2723     m_dwAcroFormObjNum = 0;
   2724     m_dwInfoObjNum = 0;
   2725     m_pDocument = 0;
   2726     m_dwEncryptObjNum = 0;
   2727     m_dwPrevXRefOffset = 0;
   2728     m_dwLastXRefOffset = 0;
   2729     m_bDocAvail = FALSE;
   2730     m_bMainXRefLoad = FALSE;
   2731     m_bDocAvail = FALSE;
   2732     m_bLinearized = FALSE;
   2733     m_bPagesLoad = FALSE;
   2734     m_bPagesTreeLoad = FALSE;
   2735     m_bMainXRefLoadedOK = FALSE;
   2736     m_bAnnotsLoad = FALSE;
   2737     m_bHaveAcroForm = FALSE;
   2738     m_bAcroFormLoad = FALSE;
   2739     m_bPageLoadedOK = FALSE;
   2740     m_bNeedDownLoadResource = FALSE;
   2741     m_bLinearizedFormParamLoad = FALSE;
   2742     m_pLinearized = NULL;
   2743     m_pRoot = NULL;
   2744     m_pTrailer = NULL;
   2745     m_pCurrentParser = NULL;
   2746     m_pAcroForm = NULL;
   2747     m_pPageDict = NULL;
   2748     m_pPageResource = NULL;
   2749     m_pageMapCheckState = NULL;
   2750     m_docStatus = PDF_DATAAVAIL_HEADER;
   2751     m_parser.m_bOwnFileRead = FALSE;
   2752     m_bTotalLoadPageTree = FALSE;
   2753     m_bCurPageDictLoadOK = FALSE;
   2754     m_bLinearedDataOK = FALSE;
   2755     m_pagesLoadState = NULL;
   2756 }
   2757 CPDF_DataAvail::~CPDF_DataAvail()
   2758 {
   2759     if (m_pLinearized)	{
   2760         m_pLinearized->Release();
   2761     }
   2762     if (m_pRoot) {
   2763         m_pRoot->Release();
   2764     }
   2765     if (m_pTrailer) {
   2766         m_pTrailer->Release();
   2767     }
   2768     if (m_pageMapCheckState) {
   2769         delete m_pageMapCheckState;
   2770     }
   2771     if (m_pagesLoadState) {
   2772         delete m_pagesLoadState;
   2773     }
   2774     FX_INT32 i = 0;
   2775     FX_INT32 iSize = m_arrayAcroforms.GetSize();
   2776     for (i = 0; i < iSize; ++i) {
   2777         ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release();
   2778     }
   2779 }
   2780 void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc)
   2781 {
   2782     m_pDocument = pDoc;
   2783 }
   2784 FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset)
   2785 {
   2786     CPDF_Parser *pParser = (CPDF_Parser *)(m_pDocument->GetParser());
   2787     if (pParser == NULL) {
   2788         return 0;
   2789     }
   2790     if (objnum >= (FX_DWORD)pParser->m_CrossRef.GetSize()) {
   2791         return 0;
   2792     }
   2793     if (pParser->m_V5Type[objnum] == 2) {
   2794         objnum = (FX_DWORD)pParser->m_CrossRef[objnum];
   2795     }
   2796     if (pParser->m_V5Type[objnum] == 1 || pParser->m_V5Type[objnum] == 255) {
   2797         offset = pParser->m_CrossRef[objnum];
   2798         if (offset == 0) {
   2799             return 0;
   2800         }
   2801         FX_LPVOID pResult = FXSYS_bsearch(&offset, pParser->m_SortedOffset.GetData(), pParser->m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
   2802         if (pResult == NULL) {
   2803             return 0;
   2804         }
   2805         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)pParser->m_SortedOffset.GetData() == pParser->m_SortedOffset.GetSize() - 1) {
   2806             return 0;
   2807         }
   2808         return (FX_DWORD)(((FX_FILESIZE*)pResult)[1] - offset);
   2809     }
   2810     return 0;
   2811 }
   2812 FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array, FX_BOOL bParsePage, IFX_DownloadHints* pHints, CFX_PtrArray &ret_array)
   2813 {
   2814     if (!obj_array.GetSize()) {
   2815         return TRUE;
   2816     }
   2817     FX_DWORD count = 0;
   2818     CFX_PtrArray new_obj_array;
   2819     FX_INT32 i = 0;
   2820     for (i = 0; i < obj_array.GetSize(); i++) {
   2821         CPDF_Object *pObj = (CPDF_Object *)obj_array[i];
   2822         if (!pObj) {
   2823             continue;
   2824         }
   2825         FX_INT32 type = pObj->GetType();
   2826         switch (type) {
   2827             case PDFOBJ_ARRAY: {
   2828                     CPDF_Array *pArray = pObj->GetArray();
   2829                     for (FX_DWORD k = 0; k < pArray->GetCount(); k++) {
   2830                         new_obj_array.Add(pArray->GetElement(k));
   2831                     }
   2832                 }
   2833                 break;
   2834             case PDFOBJ_STREAM:
   2835                 pObj = pObj->GetDict();
   2836             case PDFOBJ_DICTIONARY: {
   2837                     CPDF_Dictionary *pDict = pObj->GetDict();
   2838                     if (pDict->GetString("Type") == "Page" && !bParsePage) {
   2839                         continue;
   2840                     }
   2841                     FX_POSITION pos = pDict->GetStartPos();
   2842                     while (pos) {
   2843                         CPDF_Object *value;
   2844                         CFX_ByteString key;
   2845                         value = pDict->GetNextElement(pos, key);
   2846                         if (key != "Parent") {
   2847                             new_obj_array.Add(value);
   2848                         }
   2849                     }
   2850                 }
   2851                 break;
   2852             case PDFOBJ_REFERENCE: {
   2853                     CPDF_Reference *pRef = (CPDF_Reference*)pObj;
   2854                     FX_DWORD dwNum = pRef->GetRefObjNum();
   2855                     FX_FILESIZE offset;
   2856                     FX_DWORD size = GetObjectSize(pRef->GetRefObjNum(), offset);
   2857                     if (!size) {
   2858                         break;
   2859                     }
   2860                     size = (FX_DWORD)((FX_FILESIZE)(offset + size + 512) > m_dwFileLen ? m_dwFileLen - offset : size + 512);
   2861                     if (!m_pFileAvail->IsDataAvail(offset, size)) {
   2862                         pHints->AddSegment(offset, size);
   2863                         ret_array.Add(pObj);
   2864                         count++;
   2865                     } else if (!m_objnum_array.Find(dwNum)) {
   2866                         m_objnum_array.AddObjNum(dwNum);
   2867                         CPDF_Object *pReferred = m_pDocument->GetIndirectObject(pRef->GetRefObjNum(), NULL);
   2868                         if (pReferred) {
   2869                             new_obj_array.Add(pReferred);
   2870                         }
   2871                     }
   2872                 }
   2873                 break;
   2874         }
   2875     }
   2876     if (count > 0) {
   2877         FX_INT32 iSize = new_obj_array.GetSize();
   2878         for (i = 0; i < iSize; ++i) {
   2879             CPDF_Object *pObj = (CPDF_Object *)new_obj_array[i];
   2880             FX_INT32 type = pObj->GetType();
   2881             if (type == PDFOBJ_REFERENCE) {
   2882                 CPDF_Reference *pRef = (CPDF_Reference *)pObj;
   2883                 FX_DWORD dwNum = pRef->GetRefObjNum();
   2884                 if (!m_objnum_array.Find(dwNum)) {
   2885                     ret_array.Add(pObj);
   2886                 }
   2887             } else {
   2888                 ret_array.Add(pObj);
   2889             }
   2890         }
   2891         return FALSE;
   2892     }
   2893     obj_array.RemoveAll();
   2894     obj_array.Append(new_obj_array);
   2895     return IsObjectsAvail(obj_array, FALSE, pHints, ret_array);
   2896 }
   2897 FX_BOOL CPDF_DataAvail::IsDocAvail(IFX_DownloadHints* pHints)
   2898 {
   2899     if (!m_dwFileLen && m_pFileRead) {
   2900         m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
   2901         if (!m_dwFileLen) {
   2902             return TRUE;
   2903         }
   2904     }
   2905     while (!m_bDocAvail) {
   2906         if (!CheckDocStatus(pHints)) {
   2907             return FALSE;
   2908         }
   2909     }
   2910     return TRUE;
   2911 }
   2912 FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints)
   2913 {
   2914     if (!m_objs_array.GetSize()) {
   2915         m_objs_array.RemoveAll();
   2916         m_objnum_array.RemoveAll();
   2917         CFX_PtrArray obj_array;
   2918         obj_array.Append(m_arrayAcroforms);
   2919         FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array);
   2920         if (bRet) {
   2921             m_objs_array.RemoveAll();
   2922         }
   2923         return bRet;
   2924     } else {
   2925         CFX_PtrArray new_objs_array;
   2926         FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
   2927         if (bRet) {
   2928             FX_INT32 iSize = m_arrayAcroforms.GetSize();
   2929             for (FX_INT32 i = 0; i < iSize; ++i) {
   2930                 ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release();
   2931             }
   2932             m_arrayAcroforms.RemoveAll();
   2933         } else {
   2934             m_objs_array.RemoveAll();
   2935             m_objs_array.Append(new_objs_array);
   2936         }
   2937         return bRet;
   2938     }
   2939 }
   2940 FX_BOOL CPDF_DataAvail::CheckAcroForm(IFX_DownloadHints* pHints)
   2941 {
   2942     FX_BOOL bExist = FALSE;
   2943     m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist);
   2944     if (!bExist) {
   2945         m_docStatus = PDF_DATAAVAIL_PAGETREE;
   2946         return TRUE;
   2947     }
   2948     if (!m_pAcroForm) {
   2949         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
   2950             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   2951             return TRUE;
   2952         }
   2953         return FALSE;
   2954     }
   2955     m_arrayAcroforms.Add(m_pAcroForm);
   2956     m_docStatus = PDF_DATAAVAIL_PAGETREE;
   2957     return TRUE;
   2958 }
   2959 FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints *pHints)
   2960 {
   2961     switch (m_docStatus) {
   2962         case PDF_DATAAVAIL_HEADER:
   2963             return CheckHeader(pHints);
   2964         case PDF_DATAAVAIL_FIRSTPAGE:
   2965         case PDF_DATAAVAIL_FIRSTPAGE_PREPARE:
   2966             return CheckFirstPage(pHints);
   2967         case PDF_DATAAVAIL_END:
   2968             return CheckEnd(pHints);
   2969         case PDF_DATAAVAIL_CROSSREF:
   2970             return CheckCrossRef(pHints);
   2971         case PDF_DATAAVAIL_CROSSREF_ITEM:
   2972             return CheckCrossRefItem(pHints);
   2973         case PDF_DATAAVAIL_CROSSREF_STREAM:
   2974             return CheckAllCrossRefStream(pHints);
   2975         case PDF_DATAAVAIL_TRAILER:
   2976             return CheckTrailer(pHints);
   2977         case PDF_DATAAVAIL_TRAILER_APPEND:
   2978             return CheckTrailerAppend(pHints);
   2979         case PDF_DATAAVAIL_LOADALLCRSOSSREF:
   2980             return LoadAllXref(pHints);
   2981         case PDF_DATAAVAIL_LOADALLFILE:
   2982             return LoadAllFile(pHints);
   2983         case PDF_DATAAVAIL_ROOT:
   2984             return CheckRoot(pHints);
   2985         case PDF_DATAAVAIL_INFO:
   2986             return CheckInfo(pHints);
   2987         case PDF_DATAAVAIL_ACROFORM:
   2988             return CheckAcroForm(pHints);
   2989         case PDF_DATAAVAIL_PAGETREE:
   2990             if (m_bTotalLoadPageTree) {
   2991                 return CheckPages(pHints);
   2992             } else {
   2993                 return LoadDocPages(pHints);
   2994             }
   2995         case PDF_DATAAVAIL_PAGE:
   2996             if (m_bTotalLoadPageTree) {
   2997                 return CheckPage(pHints);
   2998             } else {
   2999                 m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD;
   3000                 return TRUE;
   3001             }
   3002         case PDF_DATAAVAIL_ERROR:
   3003             return LoadAllFile(pHints);
   3004         case PDF_DATAAVAIL_PAGE_LATERLOAD:
   3005             m_docStatus = PDF_DATAAVAIL_PAGE;
   3006         default:
   3007             m_bDocAvail = TRUE;
   3008             return TRUE;
   3009     }
   3010 }
   3011 FX_BOOL	CPDF_DataAvail::CheckPageStatus(IFX_DownloadHints* pHints)
   3012 {
   3013     switch (m_docStatus) {
   3014         case PDF_DATAAVAIL_PAGETREE:
   3015             return CheckPages(pHints);
   3016         case PDF_DATAAVAIL_PAGE:
   3017             return CheckPage(pHints);
   3018         case PDF_DATAAVAIL_ERROR:
   3019             return LoadAllFile(pHints);
   3020         default:
   3021             m_bPagesTreeLoad = TRUE;
   3022             m_bPagesLoad = TRUE;
   3023             return TRUE;
   3024     }
   3025 }
   3026 FX_BOOL CPDF_DataAvail::LoadAllFile(IFX_DownloadHints* pHints)
   3027 {
   3028     if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) {
   3029         m_docStatus = PDF_DATAAVAIL_DONE;
   3030         return TRUE;
   3031     }
   3032     pHints->AddSegment(0, (FX_DWORD)m_dwFileLen);
   3033     return FALSE;
   3034 }
   3035 FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints)
   3036 {
   3037     m_parser.m_Syntax.InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset);
   3038     m_parser.m_bOwnFileRead = FALSE;
   3039     if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) {
   3040         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3041         return FALSE;
   3042     }
   3043     FXSYS_qsort(m_parser.m_SortedOffset.GetData(), m_parser.m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
   3044     m_dwRootObjNum = m_parser.GetRootObjNum();
   3045     m_dwInfoObjNum = m_parser.GetInfoObjNum();
   3046     m_pCurrentParser = &m_parser;
   3047     m_docStatus = PDF_DATAAVAIL_ROOT;
   3048     return TRUE;
   3049 }
   3050 CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum, IFX_DownloadHints* pHints, FX_BOOL *pExistInFile)
   3051 {
   3052     CPDF_Object *pRet = NULL;
   3053     if (pExistInFile) {
   3054         *pExistInFile = TRUE;
   3055     }
   3056     if (m_pDocument == NULL) {
   3057         FX_FILESIZE offset = m_parser.GetObjectOffset(objnum);
   3058         if (offset < 0) {
   3059             *pExistInFile = FALSE;
   3060             return NULL;
   3061         }
   3062         FX_DWORD size = (FX_DWORD)m_parser.GetObjectSize(objnum);
   3063         size = (FX_DWORD)(((FX_FILESIZE)(offset + size + 512)) > m_dwFileLen ? m_dwFileLen - offset : size + 512);
   3064         if (!m_pFileAvail->IsDataAvail(offset, size)) {
   3065             pHints->AddSegment(offset, size);
   3066             return NULL;
   3067         }
   3068         pRet = m_parser.ParseIndirectObject(NULL, objnum);
   3069         if (!pRet && pExistInFile) {
   3070             *pExistInFile = FALSE;
   3071         }
   3072         return pRet;
   3073     }
   3074     FX_FILESIZE offset;
   3075     FX_DWORD size = GetObjectSize(objnum, offset);
   3076     size = (FX_DWORD)((FX_FILESIZE)(offset + size + 512) > m_dwFileLen ? m_dwFileLen - offset : size + 512);
   3077     if (!m_pFileAvail->IsDataAvail(offset, size)) {
   3078         pHints->AddSegment(offset, size);
   3079         return NULL;
   3080     }
   3081     CPDF_Parser *pParser = (CPDF_Parser *)(m_pDocument->GetParser());
   3082     pRet = pParser->ParseIndirectObject(NULL, objnum, NULL);
   3083     if (!pRet && pExistInFile) {
   3084         *pExistInFile = FALSE;
   3085     }
   3086     return pRet;
   3087 }
   3088 FX_BOOL CPDF_DataAvail::CheckInfo(IFX_DownloadHints* pHints)
   3089 {
   3090     FX_BOOL bExist = FALSE;
   3091     CPDF_Object *pInfo = GetObject(m_dwInfoObjNum, pHints, &bExist);
   3092     if (!bExist) {
   3093         if (m_bHaveAcroForm) {
   3094             m_docStatus = PDF_DATAAVAIL_ACROFORM;
   3095         } else {
   3096             m_docStatus = PDF_DATAAVAIL_PAGETREE;
   3097         }
   3098         return TRUE;
   3099     }
   3100     if (!pInfo) {
   3101         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
   3102             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3103             return TRUE;
   3104         }
   3105         if (m_Pos == m_dwFileLen) {
   3106             m_docStatus = PDF_DATAAVAIL_ERROR;
   3107         }
   3108         return FALSE;
   3109     }
   3110     if (pInfo) {
   3111         pInfo->Release();
   3112     }
   3113     if (m_bHaveAcroForm) {
   3114         m_docStatus = PDF_DATAAVAIL_ACROFORM;
   3115     } else {
   3116         m_docStatus = PDF_DATAAVAIL_PAGETREE;
   3117     }
   3118     return TRUE;
   3119 }
   3120 FX_BOOL CPDF_DataAvail::CheckRoot(IFX_DownloadHints* pHints)
   3121 {
   3122     FX_BOOL bExist = FALSE;
   3123     m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist);
   3124     if (!bExist) {
   3125         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3126         return TRUE;
   3127     }
   3128     if (!m_pRoot) {
   3129         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
   3130             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3131             return TRUE;
   3132         }
   3133         return FALSE;
   3134     }
   3135     CPDF_Reference* pRef = (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("Pages"));
   3136     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
   3137         m_docStatus = PDF_DATAAVAIL_ERROR;
   3138         return FALSE;
   3139     }
   3140     m_PagesObjNum = pRef->GetRefObjNum();
   3141     CPDF_Reference* pAcroFormRef = (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("AcroForm"));
   3142     if (pAcroFormRef && pAcroFormRef->GetType() == PDFOBJ_REFERENCE) {
   3143         m_bHaveAcroForm = TRUE;
   3144         m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum();
   3145     }
   3146     if (m_dwInfoObjNum) {
   3147         m_docStatus = PDF_DATAAVAIL_INFO;
   3148     } else {
   3149         if (m_bHaveAcroForm) {
   3150             m_docStatus = PDF_DATAAVAIL_ACROFORM;
   3151         } else {
   3152             m_docStatus = PDF_DATAAVAIL_PAGETREE;
   3153         }
   3154     }
   3155     return TRUE;
   3156 }
   3157 FX_BOOL CPDF_DataAvail::PreparePageItem()
   3158 {
   3159     CPDF_Dictionary *pRoot = m_pDocument->GetRoot();
   3160     CPDF_Reference* pRef = (CPDF_Reference*)pRoot->GetElement(FX_BSTRC("Pages"));
   3161     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
   3162         m_docStatus = PDF_DATAAVAIL_ERROR;
   3163         return FALSE;
   3164     }
   3165     m_PagesObjNum = pRef->GetRefObjNum();
   3166     m_pCurrentParser = (CPDF_Parser *)m_pDocument->GetParser();
   3167     m_docStatus = PDF_DATAAVAIL_PAGETREE;
   3168     return TRUE;
   3169 }
   3170 FX_BOOL CPDF_DataAvail::IsFirstCheck(int iPage)
   3171 {
   3172     if (NULL == m_pageMapCheckState) {
   3173         m_pageMapCheckState = FX_NEW CFX_CMapDWordToDWord();
   3174     }
   3175     FX_DWORD dwValue = 0;
   3176     if (!m_pageMapCheckState->Lookup(iPage, dwValue)) {
   3177         m_pageMapCheckState->SetAt(iPage, 1);
   3178         return TRUE;
   3179     }
   3180     if (dwValue != 0) {
   3181         return FALSE;
   3182     }
   3183     m_pageMapCheckState->SetAt(iPage, 1);
   3184     return TRUE;
   3185 }
   3186 void CPDF_DataAvail::ResetFirstCheck(int iPage)
   3187 {
   3188     if (NULL == m_pageMapCheckState) {
   3189         m_pageMapCheckState = FX_NEW CFX_CMapDWordToDWord();
   3190     }
   3191     FX_DWORD dwValue = 1;
   3192     if (!m_pageMapCheckState->Lookup(iPage, dwValue)) {
   3193         return;
   3194     }
   3195     m_pageMapCheckState->SetAt(iPage, 0);
   3196 }
   3197 FX_BOOL CPDF_DataAvail::CheckPage(IFX_DownloadHints* pHints)
   3198 {
   3199     FX_DWORD i = 0;
   3200     FX_DWORD iLen = m_PageObjList.GetSize();
   3201     CFX_DWordArray UnavailObjList;
   3202     for (; i < iLen; ++i) {
   3203         FX_DWORD dwPageObjNum = m_PageObjList.GetAt(i);
   3204         FX_BOOL bExist = FALSE;
   3205         CPDF_Object *pObj = GetObject(dwPageObjNum, pHints, &bExist);
   3206         if (!pObj) {
   3207             if (bExist) {
   3208                 UnavailObjList.Add(dwPageObjNum);
   3209             }
   3210             continue;
   3211         }
   3212         if (pObj->GetType() == PDFOBJ_ARRAY) {
   3213             CPDF_Array *pArray = pObj->GetArray();
   3214             if (pArray) {
   3215                 FX_INT32 iSize = pArray->GetCount();
   3216                 CPDF_Object *pItem = NULL;
   3217                 for (FX_INT32 j = 0; j < iSize; ++j) {
   3218                     pItem = pArray->GetElement(j);
   3219                     if (pItem && pItem->GetType() == PDFOBJ_REFERENCE) {
   3220                         UnavailObjList.Add(((CPDF_Reference *)pItem)->GetRefObjNum());
   3221                     }
   3222                 }
   3223             }
   3224         }
   3225         if (pObj->GetType() != PDFOBJ_DICTIONARY) {
   3226             pObj->Release();
   3227             continue;
   3228         }
   3229         CFX_ByteString type = pObj->GetDict()->GetString(FX_BSTRC("Type"));
   3230         if (type == FX_BSTRC("Pages")) {
   3231             m_PagesArray.Add(pObj);
   3232             continue;
   3233         }
   3234         pObj->Release();
   3235     }
   3236     m_PageObjList.RemoveAll();
   3237     if (UnavailObjList.GetSize()) {
   3238         m_PageObjList.Append(UnavailObjList);
   3239         return FALSE;
   3240     }
   3241     i = 0;
   3242     iLen = m_PagesArray.GetSize();
   3243     for (; i < iLen; ++i) {
   3244         CPDF_Object *pPages = (CPDF_Object *)m_PagesArray.GetAt(i);
   3245         if (!pPages) {
   3246             continue;
   3247         }
   3248         if (!GetPageKids(m_pCurrentParser, pPages)) {
   3249             pPages->Release();
   3250             while (i++ < iLen) {
   3251                 pPages = (CPDF_Object *)m_PagesArray.GetAt(i);
   3252                 pPages->Release();
   3253             }
   3254             m_PagesArray.RemoveAll();
   3255             m_docStatus = PDF_DATAAVAIL_ERROR;
   3256             return FALSE;
   3257         }
   3258         pPages->Release();
   3259     }
   3260     m_PagesArray.RemoveAll();
   3261     if (!m_PageObjList.GetSize()) {
   3262         m_docStatus = PDF_DATAAVAIL_DONE;
   3263         return TRUE;
   3264     }
   3265     return TRUE;
   3266 }
   3267 FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser *pParser, CPDF_Object *pPages)
   3268 {
   3269     if (!pParser) {
   3270         m_docStatus = PDF_DATAAVAIL_ERROR;
   3271         return FALSE;
   3272     }
   3273     CPDF_Object *pKids = pPages->GetDict()->GetElement(FX_BSTRC("Kids"));
   3274     if (!pKids) {
   3275         return TRUE;
   3276     }
   3277     switch (pKids->GetType()) {
   3278         case PDFOBJ_REFERENCE: {
   3279                 CPDF_Reference *pKid = (CPDF_Reference *)pKids;
   3280                 m_PageObjList.Add(pKid->GetRefObjNum());
   3281             }
   3282             break;
   3283         case PDFOBJ_ARRAY: {
   3284                 CPDF_Array *pKidsArray = (CPDF_Array *)pKids;
   3285                 for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) {
   3286                     CPDF_Reference *pKid = (CPDF_Reference *)pKidsArray->GetElement(i);
   3287                     m_PageObjList.Add(pKid->GetRefObjNum());
   3288                 }
   3289             }
   3290             break;
   3291         default:
   3292             m_docStatus = PDF_DATAAVAIL_ERROR;
   3293             return FALSE;
   3294     }
   3295     return TRUE;
   3296 }
   3297 FX_BOOL CPDF_DataAvail::CheckPages(IFX_DownloadHints* pHints)
   3298 {
   3299     FX_BOOL bExist = FALSE;
   3300     CPDF_Object *pPages = GetObject(m_PagesObjNum, pHints, &bExist);
   3301     if (!bExist) {
   3302         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3303         return TRUE;
   3304     }
   3305     if (!pPages) {
   3306         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
   3307             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3308             return TRUE;
   3309         }
   3310         return FALSE;
   3311     }
   3312     FX_BOOL bNeedLoad = FALSE;
   3313     if (!GetPageKids(m_pCurrentParser, pPages)) {
   3314         pPages->Release();
   3315         m_docStatus = PDF_DATAAVAIL_ERROR;
   3316         return FALSE;
   3317     }
   3318     pPages->Release();
   3319     m_docStatus = PDF_DATAAVAIL_PAGE;
   3320     return TRUE;
   3321 }
   3322 FX_BOOL CPDF_DataAvail::CheckHeader(IFX_DownloadHints* pHints)
   3323 {
   3324     FX_DWORD req_size = 1024;
   3325     if ((FX_FILESIZE)req_size > m_dwFileLen) {
   3326         req_size = (FX_DWORD)m_dwFileLen;
   3327     }
   3328     if (m_pFileAvail->IsDataAvail(0, req_size)) {
   3329         FX_BYTE buffer[1024];
   3330         m_pFileRead->ReadBlock(buffer, 0, req_size);
   3331         if (IsLinearizedFile(buffer, req_size)) {
   3332             m_docStatus = PDF_DATAAVAIL_FIRSTPAGE;
   3333         } else {
   3334             if (m_docStatus == PDF_DATAAVAIL_ERROR) {
   3335                 return FALSE;
   3336             }
   3337             m_docStatus = PDF_DATAAVAIL_END;
   3338         }
   3339         return TRUE;
   3340     }
   3341     pHints->AddSegment(0, req_size);
   3342     return FALSE;
   3343 }
   3344 FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints *pHints)
   3345 {
   3346     FX_DWORD dwFirstPageEndOffset = 0;
   3347     CPDF_Object *pEndOffSet = m_pLinearized->GetDict()->GetElement(FX_BSTRC("E"));
   3348     if (!pEndOffSet) {
   3349         m_docStatus = PDF_DATAAVAIL_ERROR;
   3350         return FALSE;
   3351     }
   3352     CPDF_Object *pXRefOffset  = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T"));
   3353     if (!pXRefOffset) {
   3354         m_docStatus = PDF_DATAAVAIL_ERROR;
   3355         return FALSE;
   3356     }
   3357     CPDF_Object *pFileLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
   3358     if (!pFileLen) {
   3359         m_docStatus = PDF_DATAAVAIL_ERROR;
   3360         return FALSE;
   3361     }
   3362     FX_BOOL bNeedDownLoad = FALSE;
   3363     if (pEndOffSet->GetType() == PDFOBJ_NUMBER) {
   3364         FX_DWORD dwEnd = pEndOffSet->GetInteger();
   3365         dwEnd += 512;
   3366         if ((FX_FILESIZE)dwEnd > m_dwFileLen) {
   3367             dwEnd = (FX_DWORD)m_dwFileLen;
   3368         }
   3369         FX_INT32 iStartPos = (FX_INT32)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen);
   3370         FX_INT32 iSize = dwEnd > 1024 ? dwEnd - 1024 : 0;
   3371         if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) {
   3372             pHints->AddSegment(iStartPos, iSize);
   3373             bNeedDownLoad = TRUE;
   3374         }
   3375     }
   3376     m_dwLastXRefOffset = 0;
   3377     FX_FILESIZE dwFileLen = 0;
   3378     if (pXRefOffset->GetType() == PDFOBJ_NUMBER) {
   3379         m_dwLastXRefOffset = pXRefOffset->GetInteger();
   3380     }
   3381     if (pFileLen->GetType() == PDFOBJ_NUMBER) {
   3382         dwFileLen = pFileLen->GetInteger();
   3383     }
   3384     if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, (FX_DWORD)(dwFileLen - m_dwLastXRefOffset))) {
   3385         if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE)	{
   3386             FX_DWORD dwSize = (FX_DWORD)(dwFileLen - m_dwLastXRefOffset);
   3387             FX_FILESIZE offset = m_dwLastXRefOffset;
   3388             if (dwSize < 512 && dwFileLen > 512) {
   3389                 dwSize = 512;
   3390                 offset = dwFileLen - 512;
   3391             }
   3392             pHints->AddSegment(offset, dwSize);
   3393         }
   3394     } else {
   3395         m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
   3396     }
   3397     if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
   3398         m_docStatus = PDF_DATAAVAIL_DONE;
   3399         return TRUE;
   3400     }
   3401     m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
   3402     return FALSE;
   3403 }
   3404 CPDF_Object	* CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD objnum)
   3405 {
   3406     FX_FILESIZE SavedPos = m_syntaxParser.SavePos();
   3407     m_syntaxParser.RestorePos(pos);
   3408     FX_BOOL bIsNumber;
   3409     CFX_ByteString word = m_syntaxParser.GetNextWord(bIsNumber);
   3410     if (!bIsNumber) {
   3411         return NULL;
   3412     }
   3413     FX_DWORD real_objnum = FXSYS_atoi(word);
   3414     if (objnum && real_objnum != objnum) {
   3415         return NULL;
   3416     }
   3417     word = m_syntaxParser.GetNextWord(bIsNumber);
   3418     if (!bIsNumber) {
   3419         return NULL;
   3420     }
   3421     FX_DWORD gennum = FXSYS_atoi(word);
   3422     if (m_syntaxParser.GetKeyword() != FX_BSTRC("obj")) {
   3423         m_syntaxParser.RestorePos(SavedPos);
   3424         return NULL;
   3425     }
   3426     CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0);
   3427     m_syntaxParser.RestorePos(SavedPos);
   3428     return pObj;
   3429 }
   3430 FX_INT32 CPDF_DataAvail::IsLinearizedPDF()
   3431 {
   3432     FX_DWORD req_size = 1024;
   3433     if (!m_pFileAvail->IsDataAvail(0, req_size)) {
   3434         return PDF_UNKNOW_LINEARIZED;
   3435     }
   3436     if (!m_pFileRead) {
   3437         return PDF_NOT_LINEARIZED;
   3438     }
   3439     FX_FILESIZE dwSize = m_pFileRead->GetSize();
   3440     if (dwSize < (FX_FILESIZE)req_size) {
   3441         return PDF_UNKNOW_LINEARIZED;
   3442     }
   3443     FX_BYTE buffer[1024];
   3444     m_pFileRead->ReadBlock(buffer, 0, req_size);
   3445     if (IsLinearizedFile(buffer, req_size)) {
   3446         return PDF_IS_LINEARIZED;
   3447     }
   3448     return PDF_NOT_LINEARIZED;
   3449 }
   3450 FX_BOOL CPDF_DataAvail::IsLinearizedFile(FX_LPBYTE pData, FX_DWORD dwLen)
   3451 {
   3452     CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE));
   3453     FX_INT32 offset = GetHeaderOffset((IFX_FileStream*)file);
   3454     if (offset == -1) {
   3455         m_docStatus = PDF_DATAAVAIL_ERROR;
   3456         return FALSE;
   3457     }
   3458     m_dwHeaderOffset = offset;
   3459     m_syntaxParser.InitParser((IFX_FileStream*)file, offset);
   3460     m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9);
   3461     FX_BOOL bNumber = FALSE;
   3462     FX_FILESIZE dwSavePos = m_syntaxParser.SavePos();
   3463     CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(bNumber);
   3464     if (!bNumber) {
   3465         return FALSE;
   3466     }
   3467     FX_DWORD objnum = FXSYS_atoi(wordObjNum);
   3468     if (m_pLinearized) {
   3469         m_pLinearized->Release();
   3470         m_pLinearized = NULL;
   3471     }
   3472     m_pLinearized = ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum);
   3473     if (!m_pLinearized) {
   3474         return FALSE;
   3475     }
   3476     if (m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
   3477         CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
   3478         if (!pLen) {
   3479             return FALSE;
   3480         }
   3481         if ((FX_FILESIZE)pLen->GetInteger() != m_pFileRead->GetSize()) {
   3482             return FALSE;
   3483         }
   3484         m_bLinearized = TRUE;
   3485         CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
   3486         if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
   3487             m_dwFirstPageNo = pNo->GetInteger();
   3488         }
   3489         return TRUE;
   3490     }
   3491     return FALSE;
   3492 }
   3493 FX_BOOL CPDF_DataAvail::CheckEnd(IFX_DownloadHints* pHints)
   3494 {
   3495     FX_DWORD req_pos = (FX_DWORD)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0);
   3496     FX_DWORD dwSize = (FX_DWORD)(m_dwFileLen - req_pos);
   3497     if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) {
   3498         FX_BYTE buffer[1024];
   3499         m_pFileRead->ReadBlock(buffer, req_pos, dwSize);
   3500         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE));
   3501         m_syntaxParser.InitParser((IFX_FileStream*)file, 0);
   3502         m_syntaxParser.RestorePos(dwSize - 1);
   3503         if (m_syntaxParser.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, dwSize)) {
   3504             FX_BOOL bNumber;
   3505             m_syntaxParser.GetNextWord(bNumber);
   3506             CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(bNumber);
   3507             if (!bNumber) {
   3508                 m_docStatus = PDF_DATAAVAIL_ERROR;
   3509                 return FALSE;
   3510             }
   3511             m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
   3512             if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) {
   3513                 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3514                 return TRUE;
   3515             }
   3516             m_dwLastXRefOffset = m_dwXRefOffset;
   3517             SetStartOffset(m_dwXRefOffset);
   3518             m_docStatus = PDF_DATAAVAIL_CROSSREF;
   3519             return TRUE;
   3520         } else {
   3521             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3522             return TRUE;
   3523         }
   3524     }
   3525     pHints->AddSegment(req_pos, dwSize);
   3526     return FALSE;
   3527 }
   3528 FX_DWORD CPDF_DataAvail::CheckCrossRefStream(IFX_DownloadHints* pHints, FX_FILESIZE &xref_offset)
   3529 {
   3530     xref_offset = 0;
   3531     FX_DWORD req_size = (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
   3532     if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) {
   3533         FX_INT32 iSize = (FX_INT32)(m_Pos + req_size - m_dwCurrentXRefSteam);
   3534         CFX_BinaryBuf buf(iSize);
   3535         FX_LPBYTE pBuf = buf.GetBuffer();
   3536         m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize);
   3537         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
   3538         m_parser.m_Syntax.InitParser((IFX_FileStream*)file, 0);
   3539         FX_BOOL bNumber = FALSE;
   3540         FX_FILESIZE dwSavePos = m_parser.m_Syntax.SavePos();
   3541         CFX_ByteString objnum = m_parser.m_Syntax.GetNextWord(bNumber);
   3542         if (!bNumber) {
   3543             return -1;
   3544         }
   3545         FX_DWORD objNum = FXSYS_atoi(objnum);
   3546         CPDF_Object *pObj = m_parser.ParseIndirectObjectAt(NULL, 0, objNum, NULL);
   3547         if (!pObj) {
   3548             m_Pos += m_parser.m_Syntax.SavePos();
   3549             return 0;
   3550         }
   3551         CPDF_Object *pName = pObj->GetDict()->GetElement(FX_BSTRC("Type"));
   3552         if (pName && pName->GetType() == PDFOBJ_NAME) {
   3553             if (pName->GetString() == FX_BSTRC("XRef")) {
   3554                 m_Pos += m_parser.m_Syntax.SavePos();
   3555                 xref_offset = pObj->GetDict()->GetInteger(FX_BSTRC("Prev"));
   3556                 pObj->Release();
   3557                 return 1;
   3558             } else {
   3559                 pObj->Release();
   3560                 return -1;
   3561             }
   3562         }
   3563         pObj->Release();
   3564         return -1;
   3565     }
   3566     pHints->AddSegment(m_Pos, req_size);
   3567     return 0;
   3568 }
   3569 inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset)
   3570 {
   3571     m_Pos = dwOffset;
   3572 }
   3573 #define MAX_WORD_BUFFER 256
   3574 FX_BOOL CPDF_DataAvail::GetNextToken(CFX_ByteString &token)
   3575 {
   3576     m_WordSize = 0;
   3577     FX_BYTE ch;
   3578     if (!GetNextChar(ch)) {
   3579         return FALSE;
   3580     }
   3581     FX_BYTE type = _PDF_CharType[ch];
   3582     while (1) {
   3583         while (type == 'W') {
   3584             if (!GetNextChar(ch)) {
   3585                 return FALSE;
   3586             }
   3587             type = _PDF_CharType[ch];
   3588         }
   3589         if (ch != '%') {
   3590             break;
   3591         }
   3592         while (1) {
   3593             if (!GetNextChar(ch)) {
   3594                 return FALSE;
   3595             }
   3596             if (ch == '\r' || ch == '\n') {
   3597                 break;
   3598             }
   3599         }
   3600         type = _PDF_CharType[ch];
   3601     }
   3602     if (type == 'D') {
   3603         m_WordBuffer[m_WordSize++] = ch;
   3604         if (ch == '/') {
   3605             while (1) {
   3606                 if (!GetNextChar(ch)) {
   3607                     return FALSE;
   3608                 }
   3609                 type = _PDF_CharType[ch];
   3610                 if (type != 'R' && type != 'N') {
   3611                     m_Pos --;
   3612                     CFX_ByteString ret(m_WordBuffer, m_WordSize);
   3613                     token = ret;
   3614                     return TRUE;
   3615                 }
   3616                 if (m_WordSize < MAX_WORD_BUFFER) {
   3617                     m_WordBuffer[m_WordSize++] = ch;
   3618                 }
   3619             }
   3620         } else if (ch == '<') {
   3621             if (!GetNextChar(ch)) {
   3622                 return FALSE;
   3623             }
   3624             if (ch == '<') {
   3625                 m_WordBuffer[m_WordSize++] = ch;
   3626             } else {
   3627                 m_Pos --;
   3628             }
   3629         } else if (ch == '>') {
   3630             if (!GetNextChar(ch)) {
   3631                 return FALSE;
   3632             }
   3633             if (ch == '>') {
   3634                 m_WordBuffer[m_WordSize++] = ch;
   3635             } else {
   3636                 m_Pos --;
   3637             }
   3638         }
   3639         CFX_ByteString ret(m_WordBuffer, m_WordSize);
   3640         token = ret;
   3641         return TRUE;
   3642     }
   3643     while (1) {
   3644         if (m_WordSize < MAX_WORD_BUFFER) {
   3645             m_WordBuffer[m_WordSize++] = ch;
   3646         }
   3647         if (!GetNextChar(ch)) {
   3648             return FALSE;
   3649         }
   3650         type = _PDF_CharType[ch];
   3651         if (type == 'D' || type == 'W') {
   3652             m_Pos --;
   3653             break;
   3654         }
   3655     }
   3656     CFX_ByteString ret(m_WordBuffer, m_WordSize);
   3657     token = ret;
   3658     return TRUE;
   3659 }
   3660 FX_BOOL CPDF_DataAvail::GetNextChar(FX_BYTE &ch)
   3661 {
   3662     FX_FILESIZE pos = m_Pos;
   3663     if (pos >= m_dwFileLen) {
   3664         return FALSE;
   3665     }
   3666     if (m_bufferOffset >= pos || (FX_FILESIZE)(m_bufferOffset + m_bufferSize) <= pos) {
   3667         FX_FILESIZE read_pos = pos;
   3668         FX_DWORD read_size = 512;
   3669         if ((FX_FILESIZE)read_size > m_dwFileLen) {
   3670             read_size = (FX_DWORD)m_dwFileLen;
   3671         }
   3672         if ((FX_FILESIZE)(read_pos + read_size) > m_dwFileLen) {
   3673             read_pos = m_dwFileLen - read_size;
   3674         }
   3675         if (!m_pFileRead->ReadBlock(m_bufferData, read_pos, read_size)) {
   3676             return FALSE;
   3677         }
   3678         m_bufferOffset = read_pos;
   3679         m_bufferSize = read_size;
   3680     }
   3681     ch = m_bufferData[pos - m_bufferOffset];
   3682     m_Pos ++;
   3683     return TRUE;
   3684 }
   3685 FX_BOOL CPDF_DataAvail::CheckCrossRefItem(IFX_DownloadHints *pHints)
   3686 {
   3687     FX_INT32 iSize = 0;
   3688     CFX_ByteString token;
   3689     while (1) {
   3690         if (!GetNextToken(token)) {
   3691             iSize = (FX_INT32)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
   3692             pHints->AddSegment(m_Pos, iSize);
   3693             return FALSE;
   3694         }
   3695         if (token == "trailer") {
   3696             m_dwTrailerOffset = m_Pos;
   3697             m_docStatus = PDF_DATAAVAIL_TRAILER;
   3698             return TRUE;
   3699         }
   3700     }
   3701 }
   3702 FX_BOOL CPDF_DataAvail::CheckAllCrossRefStream(IFX_DownloadHints *pHints)
   3703 {
   3704     FX_FILESIZE xref_offset = 0;
   3705     FX_DWORD dwRet = CheckCrossRefStream(pHints, xref_offset);
   3706     if (dwRet == 1) {
   3707         if (!xref_offset) {
   3708             m_docStatus = PDF_DATAAVAIL_LOADALLCRSOSSREF;
   3709         } else {
   3710             m_dwCurrentXRefSteam = xref_offset;
   3711             m_Pos = xref_offset;
   3712         }
   3713         return TRUE;
   3714     } else if (dwRet == -1) {
   3715         m_docStatus = PDF_DATAAVAIL_ERROR;
   3716     }
   3717     return FALSE;
   3718 }
   3719 FX_BOOL CPDF_DataAvail::CheckCrossRef(IFX_DownloadHints* pHints)
   3720 {
   3721     FX_FILESIZE dwSavePos = m_Pos;
   3722     FX_INT32 iSize = 0;
   3723     CFX_ByteString token;
   3724     if (!GetNextToken(token)) {
   3725         iSize = (FX_INT32)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
   3726         pHints->AddSegment(m_Pos, iSize);
   3727         return FALSE;
   3728     }
   3729     if (token == "xref") {
   3730         m_CrossOffset.InsertAt(0, m_dwXRefOffset);
   3731         while (1) {
   3732             if (!GetNextToken(token)) {
   3733                 iSize = (FX_INT32)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
   3734                 pHints->AddSegment(m_Pos, iSize);
   3735                 m_docStatus = PDF_DATAAVAIL_CROSSREF_ITEM;
   3736                 return FALSE;
   3737             }
   3738             if (token == "trailer") {
   3739                 m_dwTrailerOffset = m_Pos;
   3740                 m_docStatus = PDF_DATAAVAIL_TRAILER;
   3741                 return TRUE;
   3742             }
   3743         }
   3744     } else {
   3745         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3746         return TRUE;
   3747     }
   3748     return FALSE;
   3749 }
   3750 FX_BOOL CPDF_DataAvail::CheckTrailerAppend(IFX_DownloadHints* pHints)
   3751 {
   3752     if (m_Pos < m_dwFileLen) {
   3753         FX_FILESIZE dwAppendPos = m_Pos + m_syntaxParser.SavePos();
   3754         FX_INT32 iSize = (FX_INT32)(dwAppendPos + 512 > m_dwFileLen ? m_dwFileLen - dwAppendPos : 512);
   3755         if (!m_pFileAvail->IsDataAvail(dwAppendPos, iSize)) {
   3756             pHints->AddSegment(dwAppendPos, iSize);
   3757             return FALSE;
   3758         }
   3759     }
   3760     if (m_dwPrevXRefOffset) {
   3761         SetStartOffset(m_dwPrevXRefOffset);
   3762         m_docStatus = PDF_DATAAVAIL_CROSSREF;
   3763     } else {
   3764         m_docStatus = PDF_DATAAVAIL_LOADALLCRSOSSREF;
   3765     }
   3766     return TRUE;
   3767 }
   3768 FX_BOOL CPDF_DataAvail::CheckTrailer(IFX_DownloadHints* pHints)
   3769 {
   3770     FX_INT32 iTrailerSize = (FX_INT32)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
   3771     if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) {
   3772         FX_INT32 iSize = (FX_INT32)(m_Pos + iTrailerSize - m_dwTrailerOffset);
   3773         CFX_BinaryBuf buf(iSize);
   3774         FX_LPBYTE pBuf = buf.GetBuffer();
   3775         if (!pBuf) {
   3776             m_docStatus = PDF_DATAAVAIL_ERROR;
   3777             return FALSE;
   3778         }
   3779         if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) {
   3780             return FALSE;
   3781         }
   3782         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
   3783         m_syntaxParser.InitParser((IFX_FileStream*)file, 0);
   3784         CPDF_Object *pTrailer = m_syntaxParser.GetObject(NULL, 0, 0, 0);
   3785         if (!pTrailer) {
   3786             m_Pos += m_syntaxParser.SavePos();
   3787             pHints->AddSegment(m_Pos, iTrailerSize);
   3788             return FALSE;
   3789         }
   3790         CPDF_Dictionary *pTrailerDict = pTrailer->GetDict();
   3791         if (pTrailerDict) {
   3792             CPDF_Object *pEncrypt = pTrailerDict->GetElement("Encrypt");
   3793             if (pEncrypt && pEncrypt->GetType() == PDFOBJ_REFERENCE) {
   3794                 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3795                 pTrailer->Release();
   3796                 return TRUE;
   3797             }
   3798         }
   3799         FX_DWORD xrefpos = GetDirectInteger(pTrailer->GetDict(), FX_BSTRC("Prev"));
   3800         if (xrefpos) {
   3801             m_dwPrevXRefOffset = GetDirectInteger(pTrailer->GetDict(), FX_BSTRC("XRefStm"));
   3802             pTrailer->Release();
   3803             if (m_dwPrevXRefOffset) {
   3804                 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3805             } else {
   3806                 m_dwPrevXRefOffset = xrefpos;
   3807                 if (m_dwPrevXRefOffset >= m_dwFileLen) {
   3808                     m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
   3809                 } else {
   3810                     SetStartOffset(m_dwPrevXRefOffset);
   3811                     m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND;
   3812                 }
   3813             }
   3814             return TRUE;
   3815         } else {
   3816             m_dwPrevXRefOffset = 0;
   3817             m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND;
   3818             pTrailer->Release();
   3819         }
   3820         return TRUE;
   3821     }
   3822     pHints->AddSegment(m_Pos, iTrailerSize);
   3823     return FALSE;
   3824 }
   3825 FX_BOOL CPDF_DataAvail::CheckPage(FX_INT32 iPage, IFX_DownloadHints* pHints)
   3826 {
   3827     while (TRUE) {
   3828         switch (m_docStatus) {
   3829             case PDF_DATAAVAIL_PAGETREE:
   3830                 if (!LoadDocPages(pHints)) {
   3831                     return FALSE;
   3832                 }
   3833                 break;
   3834             case PDF_DATAAVAIL_PAGE:
   3835                 if (!LoadDocPage(iPage, pHints)) {
   3836                     return FALSE;
   3837                 }
   3838                 break;
   3839             case PDF_DATAAVAIL_ERROR:
   3840                 return LoadAllFile(pHints);
   3841             default:
   3842                 m_bPagesTreeLoad = TRUE;
   3843                 m_bPagesLoad = TRUE;
   3844                 m_bCurPageDictLoadOK = TRUE;
   3845                 m_docStatus = PDF_DATAAVAIL_PAGE;
   3846                 return TRUE;
   3847         }
   3848     }
   3849 }
   3850 FX_BOOL	CPDF_DataAvail::CheckArrayPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints)
   3851 {
   3852     FX_BOOL bExist = FALSE;
   3853     CPDF_Object *pPages = GetObject(dwPageNo, pHints, &bExist);
   3854     if (!bExist) {
   3855         m_docStatus = PDF_DATAAVAIL_ERROR;
   3856         return FALSE;
   3857     }
   3858     if (!pPages) {
   3859         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
   3860             m_docStatus = PDF_DATAAVAIL_ERROR;
   3861             return FALSE;
   3862         }
   3863         return FALSE;
   3864     }
   3865     if (pPages->GetType() != PDFOBJ_ARRAY) {
   3866         pPages->Release();
   3867         m_docStatus = PDF_DATAAVAIL_ERROR;
   3868         return FALSE;
   3869     }
   3870     pPageNode->m_type = PDF_PAGENODE_PAGES;
   3871     CPDF_Array* pArray = (CPDF_Array*)pPages;
   3872     for (FX_DWORD i = 0; i < pArray->GetCount(); ++i) {
   3873         CPDF_Object *pKid = (CPDF_Object *)pArray->GetElement(i);
   3874         if (!pKid || pKid->GetType() != PDFOBJ_REFERENCE) {
   3875             continue;
   3876         }
   3877         CPDF_PageNode *pNode = FX_NEW CPDF_PageNode();
   3878         pPageNode->m_childNode.Add(pNode);
   3879         pNode->m_dwPageNo = ((CPDF_Reference*)pKid)->GetRefObjNum();
   3880     }
   3881     pPages->Release();
   3882     return TRUE;
   3883 }
   3884 FX_BOOL CPDF_DataAvail::CheckUnkownPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints)
   3885 {
   3886     FX_BOOL bExist = FALSE;
   3887     CPDF_Object *pPage = GetObject(dwPageNo, pHints, &bExist);
   3888     if (!bExist) {
   3889         m_docStatus = PDF_DATAAVAIL_ERROR;
   3890         return FALSE;
   3891     }
   3892     if (!pPage) {
   3893         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
   3894             m_docStatus = PDF_DATAAVAIL_ERROR;
   3895             return FALSE;
   3896         }
   3897         return FALSE;
   3898     }
   3899     if (pPage->GetType() == PDFOBJ_ARRAY) {
   3900         pPageNode->m_dwPageNo = dwPageNo;
   3901         pPageNode->m_type = PDF_PAGENODE_ARRAY;
   3902         pPage->Release();
   3903         return TRUE;
   3904     }
   3905     if (pPage->GetType() != PDFOBJ_DICTIONARY) {
   3906         pPage->Release();
   3907         m_docStatus = PDF_DATAAVAIL_ERROR;
   3908         return FALSE;
   3909     }
   3910     pPageNode->m_dwPageNo = dwPageNo;
   3911     CFX_ByteString type = pPage->GetDict()->GetString(FX_BSTRC("Type"));
   3912     if (type == FX_BSTRC("Pages")) {
   3913         pPageNode->m_type = PDF_PAGENODE_PAGES;
   3914         CPDF_Object *pKids = pPage->GetDict()->GetElement(FX_BSTRC("Kids"));
   3915         if (!pKids) {
   3916             m_docStatus = PDF_DATAAVAIL_PAGE;
   3917             return TRUE;
   3918         }
   3919         switch (pKids->GetType()) {
   3920             case PDFOBJ_REFERENCE: {
   3921                     CPDF_Reference *pKid = (CPDF_Reference *)pKids;
   3922                     CPDF_PageNode *pNode = FX_NEW CPDF_PageNode();
   3923                     pPageNode->m_childNode.Add(pNode);
   3924                     pNode->m_dwPageNo = pKid->GetRefObjNum();
   3925                 }
   3926                 break;
   3927             case PDFOBJ_ARRAY: {
   3928                     CPDF_Array *pKidsArray = (CPDF_Array *)pKids;
   3929                     for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) {
   3930                         CPDF_Object *pKid = (CPDF_Object *)pKidsArray->GetElement(i);
   3931                         if (!pKid || pKid->GetType() != PDFOBJ_REFERENCE) {
   3932                             continue;
   3933                         }
   3934                         CPDF_PageNode *pNode = FX_NEW CPDF_PageNode();
   3935                         pPageNode->m_childNode.Add(pNode);
   3936                         pNode->m_dwPageNo = ((CPDF_Reference*)pKid)->GetRefObjNum();
   3937                     }
   3938                 }
   3939                 break;
   3940             default:
   3941                 break;
   3942         }
   3943     } else if (type == FX_BSTRC("Page")) {
   3944         pPageNode->m_type = PDF_PAGENODE_PAGE;
   3945     } else {
   3946         pPage->Release();
   3947         m_docStatus = PDF_DATAAVAIL_ERROR;
   3948         return FALSE;
   3949     }
   3950     pPage->Release();
   3951     return TRUE;
   3952 }
   3953 FX_BOOL CPDF_DataAvail::CheckPageNode(CPDF_PageNode &pageNodes, FX_INT32 iPage, FX_INT32 &iCount, IFX_DownloadHints* pHints)
   3954 {
   3955     FX_INT32 iSize = pageNodes.m_childNode.GetSize();
   3956     if (!iSize) {
   3957         m_docStatus = PDF_DATAAVAIL_ERROR;
   3958         return FALSE;
   3959     }
   3960     for (FX_INT32 i = 0; i < iSize; ++i) {
   3961         CPDF_PageNode *pNode = (CPDF_PageNode*)pageNodes.m_childNode.GetAt(i);
   3962         if (!pNode) {
   3963             continue;
   3964         }
   3965         switch (pNode->m_type) {
   3966             case PDF_PAGENODE_UNKOWN:
   3967                 if (!CheckUnkownPageNode(pNode->m_dwPageNo, pNode, pHints)) {
   3968                     return FALSE;
   3969                 }
   3970                 --i;
   3971                 break;
   3972             case PDF_PAGENODE_PAGE:
   3973                 iCount++;
   3974                 if (iPage == iCount && m_pDocument) {
   3975                     m_pDocument->m_PageList.SetAt(iPage, pNode->m_dwPageNo);
   3976                 }
   3977                 break;
   3978             case PDF_PAGENODE_PAGES:
   3979                 if (!CheckPageNode(*pNode, iPage, iCount, pHints)) {
   3980                     return FALSE;
   3981                 }
   3982                 break;
   3983             case PDF_PAGENODE_ARRAY:
   3984                 if (!CheckArrayPageNode(pNode->m_dwPageNo, pNode, pHints)) {
   3985                     return FALSE;
   3986                 }
   3987                 --i;
   3988                 break;
   3989         }
   3990         if (iPage == iCount) {
   3991             m_docStatus = PDF_DATAAVAIL_DONE;
   3992             return TRUE;
   3993         }
   3994     }
   3995     return TRUE;
   3996 }
   3997 FX_BOOL CPDF_DataAvail::LoadDocPage(FX_INT32 iPage, IFX_DownloadHints* pHints)
   3998 {
   3999     if (m_pDocument->GetPageCount() <= iPage || m_pDocument->m_PageList.GetAt(iPage)) {
   4000         m_docStatus = PDF_DATAAVAIL_DONE;
   4001         return TRUE;
   4002     }
   4003     if (m_pageNodes.m_type == PDF_PAGENODE_PAGE) {
   4004         if (iPage == 0) {
   4005             m_docStatus = PDF_DATAAVAIL_DONE;
   4006             return TRUE;
   4007         }
   4008         m_docStatus = PDF_DATAAVAIL_ERROR;
   4009         return TRUE;
   4010     }
   4011     FX_INT32 iCount = -1;
   4012     return CheckPageNode(m_pageNodes, iPage, iCount, pHints);
   4013 }
   4014 FX_BOOL CPDF_DataAvail::CheckPageCount(IFX_DownloadHints* pHints)
   4015 {
   4016     FX_BOOL bExist = FALSE;
   4017     CPDF_Object *pPages = GetObject(m_PagesObjNum, pHints, &bExist);
   4018     if (!bExist) {
   4019         m_docStatus = PDF_DATAAVAIL_ERROR;
   4020         return FALSE;
   4021     }
   4022     if (!pPages) {
   4023         return FALSE;
   4024     }
   4025     CPDF_Dictionary* pPagesDict = pPages->GetDict();
   4026     if (!pPagesDict) {
   4027         pPages->Release();
   4028         m_docStatus = PDF_DATAAVAIL_ERROR;
   4029         return FALSE;
   4030     }
   4031     if (!pPagesDict->KeyExist(FX_BSTRC("Kids"))) {
   4032         pPages->Release();
   4033         return TRUE;
   4034     }
   4035     int count = pPagesDict->GetInteger(FX_BSTRC("Count"));
   4036     if (count > 0) {
   4037         pPages->Release();
   4038         return TRUE;
   4039     }
   4040     pPages->Release();
   4041     return FALSE;
   4042 }
   4043 FX_BOOL CPDF_DataAvail::LoadDocPages(IFX_DownloadHints* pHints)
   4044 {
   4045     if (!CheckUnkownPageNode(m_PagesObjNum, &m_pageNodes, pHints)) {
   4046         return FALSE;
   4047     }
   4048     if (CheckPageCount(pHints)) {
   4049         m_docStatus = PDF_DATAAVAIL_PAGE;
   4050         return TRUE;
   4051     } else {
   4052         m_bTotalLoadPageTree = TRUE;
   4053     }
   4054     return FALSE;
   4055 }
   4056 FX_BOOL CPDF_DataAvail::LoadPages(IFX_DownloadHints* pHints)
   4057 {
   4058     while (!m_bPagesTreeLoad) {
   4059         if (!CheckPageStatus(pHints)) {
   4060             return FALSE;
   4061         }
   4062     }
   4063     if (m_bPagesLoad) {
   4064         return TRUE;
   4065     }
   4066     m_pDocument->LoadPages();
   4067     return FALSE;
   4068 }
   4069 FX_BOOL CPDF_DataAvail::CheckLinearizedData(IFX_DownloadHints* pHints)
   4070 {
   4071     if (m_bLinearedDataOK) {
   4072         return TRUE;
   4073     }
   4074     if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset))) {
   4075         pHints->AddSegment(m_dwLastXRefOffset, (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset));
   4076         return FALSE;
   4077     }
   4078     FX_DWORD dwRet = 0;
   4079     if (!m_bMainXRefLoad) {
   4080         dwRet = ((CPDF_Parser *)m_pDocument->GetParser())->LoadLinearizedMainXRefTable();
   4081         if (dwRet == PDFPARSE_ERROR_SUCCESS) {
   4082             if (!PreparePageItem()) {
   4083                 return FALSE;
   4084             }
   4085             m_bMainXRefLoadedOK = TRUE;
   4086         }
   4087         m_bMainXRefLoad = TRUE;
   4088     }
   4089     m_bLinearedDataOK = TRUE;
   4090     return TRUE;
   4091 }
   4092 FX_BOOL CPDF_DataAvail::CheckPageAnnots(FX_INT32 iPage, IFX_DownloadHints* pHints)
   4093 {
   4094     if (!m_objs_array.GetSize()) {
   4095         m_objs_array.RemoveAll();
   4096         m_objnum_array.RemoveAll();
   4097         CPDF_Dictionary *pPageDict = m_pDocument->GetPage(iPage);
   4098         if (!pPageDict) {
   4099             return TRUE;
   4100         }
   4101         CPDF_Object *pAnnots = pPageDict->GetElement(FX_BSTRC("Annots"));
   4102         if (!pAnnots) {
   4103             return TRUE;
   4104         }
   4105         CFX_PtrArray obj_array;
   4106         obj_array.Add(pAnnots);
   4107         FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array);
   4108         if (bRet) {
   4109             m_objs_array.RemoveAll();
   4110         }
   4111         return bRet;
   4112     } else {
   4113         CFX_PtrArray new_objs_array;
   4114         FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
   4115         m_objs_array.RemoveAll();
   4116         if (!bRet) {
   4117             m_objs_array.Append(new_objs_array);
   4118         }
   4119         return bRet;
   4120     }
   4121 }
   4122 FX_BOOL CPDF_DataAvail::CheckLinearizedFirstPage(FX_INT32 iPage, IFX_DownloadHints* pHints)
   4123 {
   4124     if (!m_bAnnotsLoad) {
   4125         if (!CheckPageAnnots(iPage, pHints)) {
   4126             return FALSE;
   4127         }
   4128         m_bAnnotsLoad = TRUE;
   4129     }
   4130     if (m_bAnnotsLoad)
   4131         if (!CheckLinearizedData(pHints)) {
   4132             return FALSE;
   4133         }
   4134     m_bPageLoadedOK = FALSE;
   4135     return TRUE;
   4136 }
   4137 FX_BOOL CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary *pDict)
   4138 {
   4139     CPDF_Object *pParent = pDict->GetElement("Parent");
   4140     if (!pParent) {
   4141         return FALSE;
   4142     }
   4143     CPDF_Dictionary *pParentDict = pParent->GetDict();
   4144     if (!pParentDict) {
   4145         return FALSE;
   4146     }
   4147     CPDF_Object *pRet = pParentDict->GetElement("Resource");
   4148     if (pRet) {
   4149         m_pPageResource = pRet;
   4150         return TRUE;
   4151     } else {
   4152         return HaveResourceAncestor(pParentDict);
   4153     }
   4154 }
   4155 FX_BOOL CPDF_DataAvail::IsPageAvail(FX_INT32 iPage, IFX_DownloadHints* pHints)
   4156 {
   4157     if (!m_pDocument) {
   4158         return FALSE;
   4159     }
   4160     if (IsFirstCheck(iPage)) {
   4161         m_bCurPageDictLoadOK = FALSE;
   4162         m_bPageLoadedOK = FALSE;
   4163         m_bAnnotsLoad = FALSE;
   4164         m_bNeedDownLoadResource = FALSE;
   4165         m_objs_array.RemoveAll();
   4166         m_objnum_array.RemoveAll();
   4167     }
   4168     if (m_pagesLoadState == NULL) {
   4169         m_pagesLoadState = FX_NEW CFX_CMapDWordToDWord();
   4170     }
   4171     FX_DWORD dwPageLoad = 0;
   4172     if (m_pagesLoadState->Lookup(iPage, dwPageLoad) && dwPageLoad != 0) {
   4173         return TRUE;
   4174     }
   4175     if (m_bLinearized) {
   4176         if ((FX_DWORD)iPage == m_dwFirstPageNo) {
   4177             m_pagesLoadState->SetAt(iPage, TRUE);
   4178             return TRUE;
   4179         }
   4180         if (!CheckLinearizedData(pHints)) {
   4181             return FALSE;
   4182         }
   4183         if (m_bMainXRefLoadedOK) {
   4184             if (m_bTotalLoadPageTree) {
   4185                 if (!LoadPages(pHints)) {
   4186                     return FALSE;
   4187                 }
   4188             } else {
   4189                 if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) {
   4190                     return FALSE;
   4191                 }
   4192             }
   4193         } else {
   4194             if (!LoadAllFile(pHints)) {
   4195                 return FALSE;
   4196             }
   4197             ((CPDF_Parser *)m_pDocument->GetParser())->RebuildCrossRef();
   4198             ResetFirstCheck(iPage);
   4199             return TRUE;
   4200         }
   4201     } else {
   4202         if (!m_bTotalLoadPageTree) {
   4203             if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) {
   4204                 return FALSE;
   4205             }
   4206         }
   4207     }
   4208     if (m_bHaveAcroForm && !m_bAcroFormLoad) {
   4209         if (!CheckAcroFormSubObject(pHints)) {
   4210             return FALSE;
   4211         }
   4212         m_bAcroFormLoad = TRUE;
   4213     }
   4214     if (!m_bPageLoadedOK) {
   4215         if (!m_objs_array.GetSize()) {
   4216             m_objs_array.RemoveAll();
   4217             m_objnum_array.RemoveAll();
   4218             m_pPageDict = m_pDocument->GetPage(iPage);
   4219             if (!m_pPageDict) {
   4220                 ResetFirstCheck(iPage);
   4221                 return TRUE;
   4222             }
   4223             CFX_PtrArray obj_array;
   4224             obj_array.Add(m_pPageDict);
   4225             FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array);
   4226             if (bRet) {
   4227                 m_objs_array.RemoveAll();
   4228                 m_bPageLoadedOK = TRUE;
   4229             } else {
   4230                 return bRet;
   4231             }
   4232         } else {
   4233             CFX_PtrArray new_objs_array;
   4234             FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
   4235             m_objs_array.RemoveAll();
   4236             if (bRet) {
   4237                 m_bPageLoadedOK = TRUE;
   4238             } else {
   4239                 m_objs_array.Append(new_objs_array);
   4240                 return bRet;
   4241             }
   4242         }
   4243     }
   4244     if (m_bPageLoadedOK) {
   4245         if (!m_bAnnotsLoad) {
   4246             if (!CheckPageAnnots(iPage, pHints)) {
   4247                 return FALSE;
   4248             }
   4249             m_bAnnotsLoad = TRUE;
   4250         }
   4251     }
   4252     if (m_pPageDict && !m_bNeedDownLoadResource) {
   4253         CPDF_Object *pRes = m_pPageDict->GetElement("Resource");
   4254         if (!pRes) {
   4255             m_bNeedDownLoadResource = HaveResourceAncestor(m_pPageDict);
   4256         }
   4257         m_bNeedDownLoadResource = FALSE;
   4258     }
   4259     if (m_bNeedDownLoadResource) {
   4260         FX_BOOL bRet = CheckResources(pHints);
   4261         if (!bRet) {
   4262             return FALSE;
   4263         }
   4264         m_bNeedDownLoadResource = FALSE;
   4265     }
   4266     m_bPageLoadedOK = FALSE;
   4267     m_bAnnotsLoad = FALSE;
   4268     m_bCurPageDictLoadOK = FALSE;
   4269     ResetFirstCheck(iPage);
   4270     m_pagesLoadState->SetAt(iPage, TRUE);
   4271     return TRUE;
   4272 }
   4273 FX_BOOL CPDF_DataAvail::CheckResources(IFX_DownloadHints* pHints)
   4274 {
   4275     if (!m_objs_array.GetSize()) {
   4276         m_objs_array.RemoveAll();
   4277         CFX_PtrArray obj_array;
   4278         obj_array.Add(m_pPageResource);
   4279         FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array);
   4280         if (bRet) {
   4281             m_objs_array.RemoveAll();
   4282         }
   4283         return bRet;
   4284     } else {
   4285         CFX_PtrArray new_objs_array;
   4286         FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
   4287         m_objs_array.RemoveAll();
   4288         if (!bRet) {
   4289             m_objs_array.Append(new_objs_array);
   4290         }
   4291         return bRet;
   4292     }
   4293 }
   4294 void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE *pPos, FX_DWORD *pSize)
   4295 {
   4296     if (pPos) {
   4297         *pPos = m_dwLastXRefOffset;
   4298     }
   4299     if (pSize) {
   4300         *pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset);
   4301     }
   4302 }
   4303 FX_INT32 CPDF_DataAvail::IsFormAvail(IFX_DownloadHints *pHints)
   4304 {
   4305     if (!m_pDocument) {
   4306         return PDFFORM_AVAIL;
   4307     }
   4308     if (!m_bLinearizedFormParamLoad) {
   4309         CPDF_Dictionary *pRoot = m_pDocument->GetRoot();
   4310         if (!pRoot) {
   4311             return PDFFORM_AVAIL;
   4312         }
   4313         CPDF_Object *pAcroForm = pRoot->GetElement(FX_BSTRC("AcroForm"));
   4314         if (!pAcroForm) {
   4315             return PDFFORM_NOTEXIST;
   4316         }
   4317         if (!m_bMainXRefLoad && !CheckLinearizedData(pHints)) {
   4318             return PDFFORM_NOTAVAIL;
   4319         }
   4320         if (!m_objs_array.GetSize()) {
   4321             m_objs_array.Add(pAcroForm->GetDict());
   4322         }
   4323         m_bLinearizedFormParamLoad = TRUE;
   4324     }
   4325     CFX_PtrArray new_objs_array;
   4326     FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
   4327     m_objs_array.RemoveAll();
   4328     if (!bRet) {
   4329         m_objs_array.Append(new_objs_array);
   4330         return PDFFORM_NOTAVAIL;
   4331     }
   4332     return PDFFORM_AVAIL;
   4333 }
   4334 void CPDF_SortObjNumArray::AddObjNum(FX_DWORD dwObjNum)
   4335 {
   4336     FX_INT32 iNext = 0;
   4337     if (BinarySearch(dwObjNum, iNext)) {
   4338         return;
   4339     }
   4340     m_number_array.InsertAt(iNext, dwObjNum);
   4341 }
   4342 FX_BOOL CPDF_SortObjNumArray::Find(FX_DWORD dwObjNum)
   4343 {
   4344     FX_INT32 iNext = 0;
   4345     return BinarySearch(dwObjNum, iNext);
   4346 }
   4347 FX_BOOL CPDF_SortObjNumArray::BinarySearch(FX_DWORD value, FX_INT32 &iNext)
   4348 {
   4349     FX_INT32 iLen = m_number_array.GetSize();
   4350     FX_INT32 iLow = 0;
   4351     FX_INT32 iHigh = iLen - 1;
   4352     FX_INT32 iMid = 0;
   4353     while (iLow <= iHigh) {
   4354         iMid = (iLow + iHigh) / 2;
   4355         FX_DWORD tt = m_number_array.GetAt(iMid);
   4356         if (m_number_array.GetAt(iMid) == value) {
   4357             iNext = iMid;
   4358             return TRUE;
   4359         } else if (m_number_array.GetAt(iMid) > value) {
   4360             iHigh = iMid - 1;
   4361         } else if (m_number_array.GetAt(iMid) < value) {
   4362             iLow = iMid + 1;
   4363         }
   4364     }
   4365     iNext = iLow;
   4366     return FALSE;
   4367 }
   4368 CPDF_PageNode::~CPDF_PageNode()
   4369 {
   4370     FX_INT32 iSize = m_childNode.GetSize();
   4371     for (FX_INT32 i = 0; i < iSize; ++i) {
   4372         CPDF_PageNode *pNode = (CPDF_PageNode*)m_childNode[i];
   4373         if (pNode) {
   4374             delete pNode;
   4375         }
   4376     }
   4377     m_childNode.RemoveAll();
   4378 }
   4379