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