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
15FX_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}
29static 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
41CPDF_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}
54CPDF_Parser::~CPDF_Parser()
55{
56    CloseParser(FALSE);
57}
58FX_DWORD CPDF_Parser::GetLastObjNum()
59{
60    FX_DWORD dwSize = m_CrossRef.GetSize();
61    return dwSize ? dwSize - 1 : 0;
62}
63void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict)
64{
65    m_pEncryptDict = pDict;
66}
67void 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}
107static 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}
126FX_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}
134FX_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}
142CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler();
143CPDF_SecurityHandler* FPDF_CreatePubKeyHandler(void*);
144FX_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}
249FX_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}
309void 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}
320FX_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}
333static 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}
344static 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}
352FX_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}
404FX_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}
438FX_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}
500FX_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}
605FX_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}
618FX_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}
988static 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}
996FX_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}
1135CPDF_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}
1150FX_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}
1158FX_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}
1166FX_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}
1193CPDF_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}
1230CPDF_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}
1245FX_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}
1269void 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}
1372CPDF_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}
1415CPDF_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}
1448CPDF_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}
1462FX_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}
1477FX_BOOL CPDF_Parser::IsOwner()
1478{
1479    return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
1480}
1481void 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}
1496FX_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}
1545FX_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}
1627FX_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}
1640FX_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
1681int CPDF_SyntaxParser::s_CurrentRecursionDepth = 0;
1682
1683CPDF_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}
1694CPDF_SyntaxParser::~CPDF_SyntaxParser()
1695{
1696    if (m_pFileBuf) {
1697        FX_Free(m_pFileBuf);
1698    }
1699}
1700FX_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}
1708FX_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}
1737FX_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}
1767FX_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
1776void 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}
1860CFX_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}
1947CFX_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}
1994void 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}
2015void 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}
2045CFX_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}
2051CFX_ByteString CPDF_SyntaxParser::GetKeyword()
2052{
2053    GetNextWord();
2054    return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
2055}
2056CPDF_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}
2242CPDF_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}
2422CPDF_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}
2503void 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}
2517FX_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}
2526FX_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}
2547FX_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}
2613struct _SearchTagRecord {
2614    FX_LPCBYTE	m_pTag;
2615    FX_DWORD	m_Len;
2616    FX_DWORD	m_Offset;
2617};
2618FX_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    }
2676end:
2677    FX_Free(pPatterns);
2678    return found;
2679}
2680FX_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}
2705void 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
2720class CPDF_DataAvail FX_FINAL : public IPDF_DataAvail
2721{
2722public:
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
2743protected:
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
2911IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead) :
2912    m_pFileAvail(pFileAvail),
2913    m_pFileRead(pFileRead) {
2914}
2915
2916// static
2917IPDF_DataAvail* IPDF_DataAvail::Create(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead)
2918{
2919  return new CPDF_DataAvail(pFileAvail, pFileRead);
2920}
2921
2922// static
2923int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0;
2924
2925CPDF_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}
2975CPDF_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}
2998void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc)
2999{
3000    m_pDocument = pDoc;
3001}
3002FX_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}
3030FX_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}
3129FX_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}
3144FX_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}
3172FX_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}
3191FX_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}
3243FX_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}
3258FX_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}
3267FX_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}
3282CPDF_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
3342FX_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}
3374FX_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}
3416FX_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}
3429FX_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}
3445void 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}
3456FX_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}
3523FX_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}
3556FX_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}
3580FX_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}
3602FX_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}
3662CPDF_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}
3688FX_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}
3708FX_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}
3750FX_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}
3785FX_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}
3826inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset)
3827{
3828    m_Pos = dwOffset;
3829}
3830#define MAX_WORD_BUFFER 256
3831FX_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}
3917FX_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}
3942FX_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}
3959FX_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}
3976FX_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}
4006FX_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}
4024FX_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}
4084FX_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}
4109FX_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}
4143FX_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}
4213FX_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}
4257FX_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}
4274FX_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}
4303FX_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}
4316FX_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}
4329FX_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}
4359FX_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}
4389FX_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}
4404FX_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}
4425FX_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}
4544FX_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}
4565void 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}
4574FX_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}
4605void 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}
4613FX_BOOL CPDF_SortObjNumArray::Find(FX_DWORD dwObjNum)
4614{
4615    FX_INT32 iNext = 0;
4616    return BinarySearch(dwObjNum, iNext);
4617}
4618FX_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}
4638CPDF_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