4fd79746846cdb2b8789d88d0e717e49e1ec28e8
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_parser.cpp
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 <utility>
8 #include <vector>
9
10 #include "../../../include/fpdfapi/fpdf_module.h"
11 #include "../../../include/fpdfapi/fpdf_page.h"
12 #include "../../../include/fpdfapi/fpdf_parser.h"
13 #include "../../../include/fxcrt/fx_safe_types.h"
14 #include "../fpdf_page/pageint.h"
15
16 FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict)
17 {
18     CPDF_Object* pType = pDict->GetElementValue(FX_BSTRC("Type"));
19     if (!pType) {
20         pType = pDict->GetElementValue(FX_BSTRC("FT"));
21         if (!pType) {
22             return FALSE;
23         }
24     }
25     if (pType->GetString() == FX_BSTRC("Sig")) {
26         return TRUE;
27     }
28     return FALSE;
29 }
30 static int _CompareFileSize(const void* p1, const void* p2)
31 {
32     FX_FILESIZE ret = (*(FX_FILESIZE*)p1) - (*(FX_FILESIZE*)p2);
33     if (ret > 0) {
34         return 1;
35     }
36     if (ret < 0) {
37         return -1;
38     }
39     return 0;
40 }
41
42 CPDF_Parser::CPDF_Parser()
43 {
44     m_pDocument = NULL;
45     m_pTrailer = NULL;
46     m_pEncryptDict = NULL;
47     m_pSecurityHandler = NULL;
48     m_pLinearized = NULL;
49     m_dwFirstPageNo = 0;
50     m_dwXrefStartObjNum = 0;
51     m_bOwnFileRead = TRUE;
52     m_FileVersion = 0;
53     m_bForceUseSecurityHandler = FALSE;
54 }
55 CPDF_Parser::~CPDF_Parser()
56 {
57     CloseParser(FALSE);
58 }
59 FX_DWORD CPDF_Parser::GetLastObjNum()
60 {
61     FX_DWORD dwSize = m_CrossRef.GetSize();
62     return dwSize ? dwSize - 1 : 0;
63 }
64 void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict)
65 {
66     m_pEncryptDict = pDict;
67 }
68 void CPDF_Parser::CloseParser(FX_BOOL bReParse)
69 {
70     m_bVersionUpdated = FALSE;
71     if (m_pDocument && !bReParse) {
72         delete m_pDocument;
73         m_pDocument = NULL;
74     }
75     if (m_pTrailer) {
76         m_pTrailer->Release();
77         m_pTrailer = NULL;
78     }
79     ReleaseEncryptHandler();
80     SetEncryptDictionary(NULL);
81     if (m_bOwnFileRead && m_Syntax.m_pFileAccess) {
82         m_Syntax.m_pFileAccess->Release();
83         m_Syntax.m_pFileAccess = NULL;
84     }
85     FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
86     while (pos) {
87         void* objnum;
88         CPDF_StreamAcc* pStream;
89         m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
90         delete pStream;
91     }
92     m_ObjectStreamMap.RemoveAll();
93     m_SortedOffset.RemoveAll();
94     m_CrossRef.RemoveAll();
95     m_V5Type.RemoveAll();
96     m_ObjVersion.RemoveAll();
97     int32_t iLen = m_Trailers.GetSize();
98     for (int32_t i = 0; i < iLen; ++i) {
99         if (CPDF_Dictionary* trailer = m_Trailers.GetAt(i))
100             trailer->Release();
101     }
102     m_Trailers.RemoveAll();
103     if (m_pLinearized) {
104         m_pLinearized->Release();
105         m_pLinearized = NULL;
106     }
107 }
108 static int32_t GetHeaderOffset(IFX_FileRead* pFile)
109 {
110     FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025);
111     uint8_t buf[4];
112     int32_t offset = 0;
113     while (1) {
114         if (!pFile->ReadBlock(buf, offset, 4)) {
115             return -1;
116         }
117         if (*(FX_DWORD*)buf == tag) {
118             return offset;
119         }
120         offset ++;
121         if (offset > 1024) {
122             return -1;
123         }
124     }
125     return -1;
126 }
127 FX_DWORD CPDF_Parser::StartParse(const FX_CHAR* filename, FX_BOOL bReParse)
128 {
129     IFX_FileRead* pFileAccess = FX_CreateFileRead(filename);
130     if (!pFileAccess) {
131         return PDFPARSE_ERROR_FILE;
132     }
133     return StartParse(pFileAccess, bReParse);
134 }
135 FX_DWORD CPDF_Parser::StartParse(const FX_WCHAR* filename, FX_BOOL bReParse)
136 {
137     IFX_FileRead* pFileAccess = FX_CreateFileRead(filename);
138     if (!pFileAccess) {
139         return PDFPARSE_ERROR_FILE;
140     }
141     return StartParse(pFileAccess, bReParse);
142 }
143 CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler();
144 CPDF_SecurityHandler* FPDF_CreatePubKeyHandler(void*);
145 FX_DWORD CPDF_Parser::StartParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead)
146 {
147     CloseParser(bReParse);
148     m_bXRefStream = FALSE;
149     m_LastXRefOffset = 0;
150     m_bOwnFileRead = bOwnFileRead;
151     int32_t offset = GetHeaderOffset(pFileAccess);
152     if (offset == -1) {
153         if (bOwnFileRead && pFileAccess) {
154             pFileAccess->Release();
155         }
156         return PDFPARSE_ERROR_FORMAT;
157     }
158     m_Syntax.InitParser(pFileAccess, offset);
159     uint8_t ch;
160     if (!m_Syntax.GetCharAt(5, ch)) {
161         return PDFPARSE_ERROR_FORMAT;
162     }
163     if (ch >= '0' && ch <= '9') {
164         m_FileVersion = (ch - '0') * 10;
165     }
166     if (!m_Syntax.GetCharAt(7, ch)) {
167         return PDFPARSE_ERROR_FORMAT;
168     }
169     if (ch >= '0' && ch <= '9') {
170         m_FileVersion += ch - '0';
171     }
172     if (m_Syntax.m_FileLen <  m_Syntax.m_HeaderOffset + 9) {
173         return PDFPARSE_ERROR_FORMAT;
174     }
175     m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9);
176     if (!bReParse) {
177         m_pDocument = new CPDF_Document(this);
178     }
179     FX_BOOL bXRefRebuilt = FALSE;
180     if (m_Syntax.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, 4096)) {
181         FX_FILESIZE startxref_offset = m_Syntax.SavePos();
182         void* pResult = FXSYS_bsearch(&startxref_offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
183         if (pResult == NULL) {
184             m_SortedOffset.Add(startxref_offset);
185         }
186         m_Syntax.GetKeyword();
187         FX_BOOL bNumber;
188         CFX_ByteString xrefpos_str = m_Syntax.GetNextWord(bNumber);
189         if (!bNumber) {
190             return PDFPARSE_ERROR_FORMAT;
191         }
192         m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
193         if (!LoadAllCrossRefV4(m_LastXRefOffset) && !LoadAllCrossRefV5(m_LastXRefOffset)) {
194             if (!RebuildCrossRef()) {
195                 return PDFPARSE_ERROR_FORMAT;
196             }
197             bXRefRebuilt = TRUE;
198             m_LastXRefOffset = 0;
199         }
200     } else {
201         if (!RebuildCrossRef()) {
202             return PDFPARSE_ERROR_FORMAT;
203         }
204         bXRefRebuilt = TRUE;
205     }
206     FX_DWORD dwRet = SetEncryptHandler();
207     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
208         return dwRet;
209     }
210     m_pDocument->LoadDoc();
211     if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
212         if (bXRefRebuilt) {
213             return PDFPARSE_ERROR_FORMAT;
214         }
215         ReleaseEncryptHandler();
216         if (!RebuildCrossRef()) {
217             return PDFPARSE_ERROR_FORMAT;
218         }
219         dwRet = SetEncryptHandler();
220         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
221             return dwRet;
222         }
223         m_pDocument->LoadDoc();
224         if (m_pDocument->GetRoot() == NULL) {
225             return PDFPARSE_ERROR_FORMAT;
226         }
227     }
228     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
229     FX_DWORD RootObjNum = GetRootObjNum();
230     if (RootObjNum == 0) {
231         ReleaseEncryptHandler();
232         RebuildCrossRef();
233         RootObjNum = GetRootObjNum();
234         if (RootObjNum == 0) {
235             return PDFPARSE_ERROR_FORMAT;
236         }
237         dwRet = SetEncryptHandler();
238         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
239             return dwRet;
240         }
241     }
242     if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) {
243         CPDF_Reference* pMetadata = (CPDF_Reference*)m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
244         if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
245             m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum();
246         }
247     }
248     return PDFPARSE_ERROR_SUCCESS;
249 }
250 FX_DWORD CPDF_Parser::SetEncryptHandler()
251 {
252     ReleaseEncryptHandler();
253     SetEncryptDictionary(NULL);
254     if (m_pTrailer == NULL) {
255         return PDFPARSE_ERROR_FORMAT;
256     }
257     CPDF_Object* pEncryptObj = m_pTrailer->GetElement(FX_BSTRC("Encrypt"));
258     if (pEncryptObj) {
259         if (pEncryptObj->GetType() == PDFOBJ_DICTIONARY) {
260             SetEncryptDictionary((CPDF_Dictionary*)pEncryptObj);
261         } else if (pEncryptObj->GetType() == PDFOBJ_REFERENCE) {
262             pEncryptObj = m_pDocument->GetIndirectObject(((CPDF_Reference*)pEncryptObj)->GetRefObjNum());
263             if (pEncryptObj) {
264                 SetEncryptDictionary(pEncryptObj->GetDict());
265             }
266         }
267     }
268     if (m_bForceUseSecurityHandler) {
269         FX_DWORD err = PDFPARSE_ERROR_HANDLER;
270         if (m_pSecurityHandler == NULL) {
271             return PDFPARSE_ERROR_HANDLER;
272         }
273         if (!m_pSecurityHandler->OnInit(this, m_pEncryptDict)) {
274             return err;
275         }
276         CPDF_CryptoHandler* pCryptoHandler = m_pSecurityHandler->CreateCryptoHandler();
277         if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) {
278             delete pCryptoHandler;
279             pCryptoHandler = NULL;
280             return PDFPARSE_ERROR_HANDLER;
281         }
282         m_Syntax.SetEncrypt(pCryptoHandler);
283     } else if (m_pEncryptDict) {
284         CFX_ByteString filter = m_pEncryptDict->GetString(FX_BSTRC("Filter"));
285         CPDF_SecurityHandler* pSecurityHandler = NULL;
286         FX_DWORD err = PDFPARSE_ERROR_HANDLER;
287         if (filter == FX_BSTRC("Standard")) {
288             pSecurityHandler = FPDF_CreateStandardSecurityHandler();
289             err = PDFPARSE_ERROR_PASSWORD;
290         }
291         if (pSecurityHandler == NULL) {
292             return PDFPARSE_ERROR_HANDLER;
293         }
294         if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) {
295             delete pSecurityHandler;
296             pSecurityHandler = NULL;
297             return err;
298         }
299         m_pSecurityHandler = pSecurityHandler;
300         CPDF_CryptoHandler* pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
301         if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) {
302             delete pCryptoHandler;
303             pCryptoHandler = NULL;
304             return PDFPARSE_ERROR_HANDLER;
305         }
306         m_Syntax.SetEncrypt(pCryptoHandler);
307     }
308     return PDFPARSE_ERROR_SUCCESS;
309 }
310 void CPDF_Parser::ReleaseEncryptHandler()
311 {
312     if (m_Syntax.m_pCryptoHandler) {
313         delete m_Syntax.m_pCryptoHandler;
314         m_Syntax.m_pCryptoHandler = NULL;
315     }
316     if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
317         delete m_pSecurityHandler;
318         m_pSecurityHandler = NULL;
319     }
320 }
321 FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum)
322 {
323     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
324         return 0;
325     }
326     if (m_V5Type[objnum] == 1) {
327         return m_CrossRef[objnum];
328     }
329     if (m_V5Type[objnum] == 2) {
330         return m_CrossRef[(int32_t)m_CrossRef[objnum]];
331     }
332     return 0;
333 }
334 static int32_t GetDirectInteger(CPDF_Dictionary* pDict, const CFX_ByteStringC& key)
335 {
336     CPDF_Object* pObj = pDict->GetElement(key);
337     if (pObj == NULL) {
338         return 0;
339     }
340     if (pObj->GetType() == PDFOBJ_NUMBER) {
341         return ((CPDF_Number*)pObj)->GetInteger();
342     }
343     return 0;
344 }
345 static FX_BOOL CheckDirectType(CPDF_Dictionary* pDict, const CFX_ByteStringC& key, int32_t iType)
346 {
347     CPDF_Object* pObj = pDict->GetElement(key);
348     if (!pObj) {
349         return TRUE;
350     }
351     return pObj->GetType() == iType;
352 }
353 FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos)
354 {
355     if (!LoadCrossRefV4(xrefpos, 0, TRUE, FALSE)) {
356         return FALSE;
357     }
358     m_pTrailer = LoadTrailerV4();
359     if (m_pTrailer == NULL) {
360         return FALSE;
361     }
362     int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
363     if (xrefsize <= 0 || xrefsize > (1 << 20)) {
364         return FALSE;
365     }
366     m_CrossRef.SetSize(xrefsize);
367     m_V5Type.SetSize(xrefsize);
368     CFX_FileSizeArray CrossRefList, XRefStreamList;
369     CrossRefList.Add(xrefpos);
370     XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm")));
371     if (!CheckDirectType(m_pTrailer, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) {
372         return FALSE;
373     }
374     FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev"));
375     if (newxrefpos == xrefpos) {
376         return FALSE;
377     }
378     xrefpos = newxrefpos;
379     while (xrefpos) {
380         CrossRefList.InsertAt(0, xrefpos);
381         LoadCrossRefV4(xrefpos, 0, TRUE, FALSE);
382         CPDF_Dictionary* pDict = LoadTrailerV4();
383         if (pDict == NULL) {
384             return FALSE;
385         }
386         if (!CheckDirectType(pDict, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) {
387             pDict->Release();
388             return FALSE;
389         }
390         newxrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev"));
391         if (newxrefpos == xrefpos) {
392             pDict->Release();
393             return FALSE;
394         }
395         xrefpos = newxrefpos;
396         XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm")));
397         m_Trailers.Add(pDict);
398     }
399     for (int32_t i = 0; i < CrossRefList.GetSize(); i ++)
400         if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) {
401             return FALSE;
402         }
403     return TRUE;
404 }
405 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, FX_DWORD dwObjCount)
406 {
407     if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) {
408         return FALSE;
409     }
410     m_pTrailer = LoadTrailerV4();
411     if (m_pTrailer == NULL) {
412         return FALSE;
413     }
414     int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
415     if (xrefsize == 0) {
416         return FALSE;
417     }
418     CFX_FileSizeArray CrossRefList, XRefStreamList;
419     CrossRefList.Add(xrefpos);
420     XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm")));
421     xrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev"));
422     while (xrefpos) {
423         CrossRefList.InsertAt(0, xrefpos);
424         LoadCrossRefV4(xrefpos, 0, TRUE, FALSE);
425         CPDF_Dictionary* pDict = LoadTrailerV4();
426         if (pDict == NULL) {
427             return FALSE;
428         }
429         xrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev"));
430         XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm")));
431         m_Trailers.Add(pDict);
432     }
433     for (int32_t i = 1; i < CrossRefList.GetSize(); i ++)
434         if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) {
435             return FALSE;
436         }
437     return TRUE;
438 }
439 FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, FX_DWORD dwObjCount)
440 {
441     FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset;
442     m_Syntax.RestorePos(dwStartPos);
443     void* pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
444     if (pResult == NULL) {
445         m_SortedOffset.Add(pos);
446     }
447     FX_DWORD start_objnum = 0;
448     FX_DWORD count = dwObjCount;
449     FX_FILESIZE SavedPos = m_Syntax.SavePos();
450     int32_t recordsize = 20;
451     char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
452     pBuf[1024 * recordsize] = '\0';
453     int32_t nBlocks = count / 1024 + 1;
454     for (int32_t block = 0; block < nBlocks; block ++) {
455         int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024;
456         FX_DWORD dwReadSize = block_size * recordsize;
457         if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_Syntax.m_FileLen) {
458             FX_Free(pBuf);
459             return FALSE;
460         }
461         if (!m_Syntax.ReadBlock((uint8_t*)pBuf, dwReadSize)) {
462             FX_Free(pBuf);
463             return FALSE;
464         }
465         for (int32_t i = 0; i < block_size; i ++) {
466             FX_DWORD objnum = start_objnum + block * 1024 + i;
467             char* pEntry = pBuf + i * recordsize;
468             if (pEntry[17] == 'f') {
469                 m_CrossRef.SetAtGrow(objnum, 0);
470                 m_V5Type.SetAtGrow(objnum, 0);
471             } else {
472                 int32_t offset = FXSYS_atoi(pEntry);
473                 if (offset == 0) {
474                     for (int32_t c = 0; c < 10; c ++) {
475                         if (pEntry[c] < '0' || pEntry[c] > '9') {
476                             FX_Free(pBuf);
477                             return FALSE;
478                         }
479                     }
480                 }
481                 m_CrossRef.SetAtGrow(objnum, offset);
482                 int32_t version = FXSYS_atoi(pEntry + 11);
483                 if (version >= 1) {
484                     m_bVersionUpdated = TRUE;
485                 }
486                 m_ObjVersion.SetAtGrow(objnum, version);
487                 if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
488                     void* pResult = FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
489                     if (pResult == NULL) {
490                         m_SortedOffset.Add(m_CrossRef[objnum]);
491                     }
492                 }
493                 m_V5Type.SetAtGrow(objnum, 1);
494             }
495         }
496     }
497     FX_Free(pBuf);
498     m_Syntax.RestorePos(SavedPos + count * recordsize);
499     return TRUE;
500 }
501 FX_BOOL CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, FX_FILESIZE streampos, FX_BOOL bSkip, FX_BOOL bFirst)
502 {
503     m_Syntax.RestorePos(pos);
504     if (m_Syntax.GetKeyword() != FX_BSTRC("xref")) {
505         return FALSE;
506     }
507     void* pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
508     if (pResult == NULL) {
509         m_SortedOffset.Add(pos);
510     }
511     if (streampos) {
512         void* pResult = FXSYS_bsearch(&streampos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
513         if (pResult == NULL) {
514             m_SortedOffset.Add(streampos);
515         }
516     }
517     while (1) {
518         FX_FILESIZE SavedPos = m_Syntax.SavePos();
519         FX_BOOL bIsNumber;
520         CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
521         if (word.IsEmpty()) {
522             return FALSE;
523         }
524         if (!bIsNumber) {
525             m_Syntax.RestorePos(SavedPos);
526             break;
527         }
528         FX_DWORD start_objnum = FXSYS_atoi(word);
529         if (start_objnum >= (1 << 20)) {
530             return FALSE;
531         }
532         FX_DWORD count = m_Syntax.GetDirectNum();
533         m_Syntax.ToNextWord();
534         SavedPos = m_Syntax.SavePos();
535         FX_BOOL bFirstItem = FALSE;
536         int32_t recordsize = 20;
537         if (bFirst) {
538             bFirstItem = TRUE;
539         }
540         m_dwXrefStartObjNum = start_objnum;
541         if (!bSkip) {
542             char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
543             pBuf[1024 * recordsize] = '\0';
544             int32_t nBlocks = count / 1024 + 1;
545             FX_BOOL bFirstBlock = TRUE;
546             for (int32_t block = 0; block < nBlocks; block ++) {
547                 int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024;
548                 m_Syntax.ReadBlock((uint8_t*)pBuf, block_size * recordsize);
549                 for (int32_t i = 0; i < block_size; i ++) {
550                     FX_DWORD objnum = start_objnum + block * 1024 + i;
551                     char* pEntry = pBuf + i * recordsize;
552                     if (pEntry[17] == 'f') {
553                         if (bFirstItem) {
554                             objnum = 0;
555                             bFirstItem = FALSE;
556                         }
557                         if (bFirstBlock) {
558                             FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
559                             int32_t version = FXSYS_atoi(pEntry + 11);
560                             if (offset == 0 && version == 65535 && start_objnum != 0) {
561                                 start_objnum--;
562                                 objnum = 0;
563                             }
564                         }
565                         m_CrossRef.SetAtGrow(objnum, 0);
566                         m_V5Type.SetAtGrow(objnum, 0);
567                     } else {
568                         FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
569                         if (offset == 0) {
570                             for (int32_t c = 0; c < 10; c ++) {
571                                 if (pEntry[c] < '0' || pEntry[c] > '9') {
572                                     FX_Free(pBuf);
573                                     return FALSE;
574                                 }
575                             }
576                         }
577                         m_CrossRef.SetAtGrow(objnum, offset);
578                         int32_t version = FXSYS_atoi(pEntry + 11);
579                         if (version >= 1) {
580                             m_bVersionUpdated = TRUE;
581                         }
582                         m_ObjVersion.SetAtGrow(objnum, version);
583                         if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
584                             void* pResult = FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
585                             if (pResult == NULL) {
586                                 m_SortedOffset.Add(m_CrossRef[objnum]);
587                             }
588                         }
589                         m_V5Type.SetAtGrow(objnum, 1);
590                     }
591                     if (bFirstBlock) {
592                         bFirstBlock = FALSE;
593                     }
594                 }
595             }
596             FX_Free(pBuf);
597         }
598         m_Syntax.RestorePos(SavedPos + count * recordsize);
599     }
600     if (streampos)
601         if (!LoadCrossRefV5(streampos, streampos, FALSE)) {
602             return FALSE;
603         }
604     return TRUE;
605 }
606 FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos)
607 {
608     if (!LoadCrossRefV5(xrefpos, xrefpos, TRUE)) {
609         return FALSE;
610     }
611     while (xrefpos)
612         if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
613             return FALSE;
614         }
615     m_ObjectStreamMap.InitHashTable(101, FALSE);
616     m_bXRefStream = TRUE;
617     return TRUE;
618 }
619 FX_BOOL CPDF_Parser::RebuildCrossRef()
620 {
621     m_CrossRef.RemoveAll();
622     m_V5Type.RemoveAll();
623     m_SortedOffset.RemoveAll();
624     m_ObjVersion.RemoveAll();
625     if (m_pTrailer) {
626         m_pTrailer->Release();
627         m_pTrailer = NULL;
628     }
629     int32_t status = 0;
630     int32_t inside_index = 0;
631     FX_DWORD objnum = 0, gennum = 0;
632     int32_t depth = 0;
633     uint8_t* buffer = FX_Alloc(uint8_t, 4096);
634     FX_FILESIZE pos = m_Syntax.m_HeaderOffset;
635     FX_FILESIZE start_pos = 0, start_pos1 = 0;
636     FX_FILESIZE last_obj = -1, last_xref = -1, last_trailer = -1;
637     while (pos < m_Syntax.m_FileLen) {
638         FX_BOOL bOverFlow = FALSE;
639         FX_DWORD size = (FX_DWORD)(m_Syntax.m_FileLen - pos);
640         if (size > 4096) {
641             size = 4096;
642         }
643         if (!m_Syntax.m_pFileAccess->ReadBlock(buffer, pos, size)) {
644             break;
645         }
646         for (FX_DWORD i = 0; i < size; i ++) {
647             uint8_t byte = buffer[i];
648             switch (status) {
649                 case 0:
650                     if (PDF_CharType[byte] == 'W') {
651                         status = 1;
652                     }
653                     if (byte <= '9' && byte >= '0') {
654                         --i;
655                         status = 1;
656                     }
657                     if (byte == '%') {
658                         inside_index = 0;
659                         status = 9;
660                     }
661                     if (byte == '(') {
662                         status = 10;
663                         depth = 1;
664                     }
665                     if (byte == '<') {
666                         inside_index = 1;
667                         status = 11;
668                     }
669                     if (byte == '\\') {
670                         status = 13;
671                     }
672                     if (byte == 't') {
673                         status = 7;
674                         inside_index = 1;
675                     }
676                     break;
677                 case 1:
678                     if (PDF_CharType[byte] == 'W') {
679                         break;
680                     } else if (byte <= '9' && byte >= '0') {
681                         start_pos = pos + i;
682                         status = 2;
683                         objnum = byte - '0';
684                     } else if (byte == 't') {
685                         status = 7;
686                         inside_index = 1;
687                     } else if (byte == 'x') {
688                         status = 8;
689                         inside_index = 1;
690                     } else {
691                         --i;
692                         status = 0;
693                     }
694                     break;
695                 case 2:
696                     if (byte <= '9' && byte >= '0') {
697                         objnum = objnum * 10 + byte - '0';
698                         break;
699                     } else if (PDF_CharType[byte] == 'W') {
700                         status = 3;
701                     } else {
702                         --i;
703                         status = 14;
704                         inside_index = 0;
705                     }
706                     break;
707                 case 3:
708                     if (byte <= '9' && byte >= '0') {
709                         start_pos1 = pos + i;
710                         status = 4;
711                         gennum = byte - '0';
712                     } else if (PDF_CharType[byte] == 'W') {
713                         break;
714                     } else if (byte == 't') {
715                         status = 7;
716                         inside_index = 1;
717                     } else {
718                         --i;
719                         status = 0;
720                     }
721                     break;
722                 case 4:
723                     if (byte <= '9' && byte >= '0') {
724                         gennum = gennum * 10 + byte - '0';
725                         break;
726                     } else if (PDF_CharType[byte] == 'W') {
727                         status = 5;
728                     } else {
729                         --i;
730                         status = 0;
731                     }
732                     break;
733                 case 5:
734                     if (byte == 'o') {
735                         status = 6;
736                         inside_index = 1;
737                     } else if (PDF_CharType[byte] == 'W') {
738                         break;
739                     } else if (byte <= '9' && byte >= '0') {
740                         objnum = gennum;
741                         gennum = byte - '0';
742                         start_pos = start_pos1;
743                         start_pos1 = pos + i;
744                         status = 4;
745                     } else if (byte == 't') {
746                         status = 7;
747                         inside_index = 1;
748                     } else {
749                         --i;
750                         status = 0;
751                     }
752                     break;
753                 case 6:
754                     switch (inside_index) {
755                         case 1:
756                             if (byte != 'b') {
757                                 --i;
758                                 status = 0;
759                             } else {
760                                 inside_index ++;
761                             }
762                             break;
763                         case 2:
764                             if (byte != 'j') {
765                                 --i;
766                                 status = 0;
767                             } else {
768                                 inside_index ++;
769                             }
770                             break;
771                         case 3:
772                             if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') {
773                                 if (objnum > 0x1000000) {
774                                     status = 0;
775                                     break;
776                                 }
777                                 FX_FILESIZE obj_pos = start_pos - m_Syntax.m_HeaderOffset;
778                                 last_obj = start_pos;
779                                 void* pResult = FXSYS_bsearch(&obj_pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
780                                 if (pResult == NULL) {
781                                     m_SortedOffset.Add(obj_pos);
782                                 }
783                                 FX_FILESIZE obj_end = 0;
784                                 CPDF_Object *pObject = ParseIndirectObjectAtByStrict(m_pDocument, obj_pos, objnum, NULL, &obj_end);
785                                 if (pObject) {
786                                     int iType = pObject->GetType();
787                                     if (iType == PDFOBJ_STREAM) {
788                                         CPDF_Stream* pStream = (CPDF_Stream*)pObject;
789                                         CPDF_Dictionary* pDict = pStream->GetDict();
790                                         if (pDict) {
791                                             if (pDict->KeyExist(FX_BSTRC("Type"))) {
792                                                 CFX_ByteString bsValue = pDict->GetString(FX_BSTRC("Type"));
793                                                 if (bsValue == FX_BSTRC("XRef") && pDict->KeyExist(FX_BSTRC("Size"))) {
794                                                     CPDF_Object* pRoot = pDict->GetElement(FX_BSTRC("Root"));
795                                                     if (pRoot && pRoot->GetDict() && pRoot->GetDict()->GetElement(FX_BSTRC("Pages"))) {
796                                                         if (m_pTrailer) {
797                                                             m_pTrailer->Release();
798                                                         }
799                                                         m_pTrailer = (CPDF_Dictionary*)pDict->Clone();
800                                                     }
801                                                 }
802                                             }
803                                         }
804                                     }
805                                 }
806                                 FX_FILESIZE offset = 0;
807                                 m_Syntax.RestorePos(obj_pos);
808                                 offset = m_Syntax.FindTag(FX_BSTRC("obj"), 0);
809                                 if (offset == -1) {
810                                     offset = 0;
811                                 } else {
812                                     offset += 3;
813                                 }
814                                 FX_FILESIZE nLen = obj_end - obj_pos - offset;
815                                 if ((FX_DWORD)nLen > size - i) {
816                                     pos = obj_end + m_Syntax.m_HeaderOffset;
817                                     bOverFlow = TRUE;
818                                 } else {
819                                     i += (FX_DWORD)nLen;
820                                 }
821                                 if (m_CrossRef.GetSize() > (int32_t)objnum && m_CrossRef[objnum]) {
822                                     if (pObject) {
823                                         FX_DWORD oldgen = m_ObjVersion.GetAt(objnum);
824                                         m_CrossRef[objnum] = obj_pos;
825                                         m_ObjVersion.SetAt(objnum, (int16_t)gennum);
826                                         if (oldgen != gennum) {
827                                             m_bVersionUpdated = TRUE;
828                                         }
829                                     }
830                                 } else {
831                                     m_CrossRef.SetAtGrow(objnum, obj_pos);
832                                     m_V5Type.SetAtGrow(objnum, 1);
833                                     m_ObjVersion.SetAtGrow(objnum, (int16_t)gennum);
834                                 }
835                                 if (pObject) {
836                                     pObject->Release();
837                                 }
838                             }
839                             --i;
840                             status = 0;
841                             break;
842                     }
843                     break;
844                 case 7:
845                     if (inside_index == 7) {
846                         if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') {
847                             last_trailer = pos + i - 7;
848                             m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset);
849                             CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
850                             if (pObj) {
851                                 if (pObj->GetType() != PDFOBJ_DICTIONARY && pObj->GetType() != PDFOBJ_STREAM) {
852                                     pObj->Release();
853                                 } else {
854                                     CPDF_Dictionary* pTrailer = NULL;
855                                     if (pObj->GetType() == PDFOBJ_STREAM) {
856                                         pTrailer = ((CPDF_Stream*)pObj)->GetDict();
857                                     } else {
858                                         pTrailer = (CPDF_Dictionary*)pObj;
859                                     }
860                                     if (pTrailer) {
861                                         if (m_pTrailer) {
862                                             CPDF_Object* pRoot = pTrailer->GetElement(FX_BSTRC("Root"));
863                                             if (pRoot == NULL || (pRoot->GetType() == PDFOBJ_REFERENCE &&
864                                                                   (FX_DWORD)m_CrossRef.GetSize() > ((CPDF_Reference*)pRoot)->GetRefObjNum() &&
865                                                                   m_CrossRef.GetAt(((CPDF_Reference*)pRoot)->GetRefObjNum()) != 0)) {
866                                                 FX_POSITION pos = pTrailer->GetStartPos();
867                                                 while (pos) {
868                                                     CFX_ByteString key;
869                                                     CPDF_Object* pObj = pTrailer->GetNextElement(pos, key);
870                                                     m_pTrailer->SetAt(key, pObj->Clone(), m_pDocument);
871                                                 }
872                                                 pObj->Release();
873                                             } else {
874                                                 pObj->Release();
875                                             }
876                                         } else {
877                                             if (pObj->GetType() == PDFOBJ_STREAM) {
878                                                 m_pTrailer = (CPDF_Dictionary*)pTrailer->Clone();
879                                                 pObj->Release();
880                                             } else {
881                                                 m_pTrailer = pTrailer;
882                                             }
883                                             FX_FILESIZE dwSavePos = m_Syntax.SavePos();
884                                             CFX_ByteString strWord = m_Syntax.GetKeyword();
885                                             if (!strWord.Compare(FX_BSTRC("startxref"))) {
886                                                 FX_BOOL bNumber = FALSE;
887                                                 CFX_ByteString bsOffset = m_Syntax.GetNextWord(bNumber);
888                                                 if (bNumber) {
889                                                     m_LastXRefOffset = FXSYS_atoi(bsOffset);
890                                                 }
891                                             }
892                                             m_Syntax.RestorePos(dwSavePos);
893                                         }
894                                     } else {
895                                         pObj->Release();
896                                     }
897                                 }
898                             }
899                         }
900                         --i;
901                         status = 0;
902                     } else if (byte == "trailer"[inside_index]) {
903                         inside_index ++;
904                     } else {
905                         --i;
906                         status = 0;
907                     }
908                     break;
909                 case 8:
910                     if (inside_index == 4) {
911                         last_xref = pos + i - 4;
912                         status = 1;
913                     } else if (byte == "xref"[inside_index]) {
914                         inside_index ++;
915                     } else {
916                         --i;
917                         status = 0;
918                     }
919                     break;
920                 case 9:
921                     if (byte == '\r' || byte == '\n') {
922                         status = 0;
923                     }
924                     break;
925                 case 10:
926                     if (byte == ')') {
927                         if (depth > 0) {
928                             depth--;
929                         }
930                     } else if (byte == '(') {
931                         depth++;
932                     }
933                     if (!depth) {
934                         status = 0;
935                     }
936                     break;
937                 case 11:
938                     if (byte == '<' && inside_index == 1) {
939                         status = 12;
940                     } else if (byte == '>') {
941                         status = 0;
942                     }
943                     inside_index = 0;
944                     break;
945                 case 12:
946                     --i;
947                     status = 0;
948                     break;
949                 case 13:
950                     if (PDF_CharType[byte] == 'D' || PDF_CharType[byte] == 'W') {
951                         --i;
952                         status = 0;
953                     }
954                     break;
955                 case 14:
956                     if (PDF_CharType[byte] == 'W') {
957                         status = 0;
958                     } else if (byte == '%' || byte == '(' || byte == '<' || byte == '\\') {
959                         status = 0;
960                         --i;
961                     } else if (inside_index == 6) {
962                         status = 0;
963                         --i;
964                     } else if (byte == "endobj"[inside_index]) {
965                         inside_index++;
966                     }
967                     break;
968             }
969             if (bOverFlow) {
970                 size = 0;
971                 break;
972             }
973         }
974         pos += size;
975     }
976     if (last_xref != -1 && last_xref > last_obj) {
977         last_trailer = last_xref;
978     } else if (last_trailer == -1 || last_xref < last_obj) {
979         last_trailer = m_Syntax.m_FileLen;
980     }
981     FX_FILESIZE offset = last_trailer - m_Syntax.m_HeaderOffset;
982     void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
983     if (pResult == NULL) {
984         m_SortedOffset.Add(offset);
985     }
986     FX_Free(buffer);
987     return TRUE;
988 }
989 static FX_DWORD _GetVarInt(const uint8_t* p, int32_t n)
990 {
991     FX_DWORD result = 0;
992     for (int32_t i = 0; i < n; i ++) {
993         result = result * 256 + p[i];
994     }
995     return result;
996 }
997 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL bMainXRef)
998 {
999     CPDF_Stream* pStream = (CPDF_Stream*)ParseIndirectObjectAt(m_pDocument, pos, 0, NULL);
1000     if (!pStream) {
1001         return FALSE;
1002     }
1003     if (m_pDocument) {
1004         CPDF_Dictionary * pDict = m_pDocument->GetRoot();
1005         if (!pDict || pDict->GetObjNum() != pStream->m_ObjNum) {
1006             m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
1007         } else {
1008             if (pStream->GetType() == PDFOBJ_STREAM) {
1009                 pStream->Release();
1010             }
1011             return FALSE;
1012         }
1013     }
1014     if (pStream->GetType() != PDFOBJ_STREAM) {
1015         return FALSE;
1016     }
1017     prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev"));
1018     int32_t size = pStream->GetDict()->GetInteger(FX_BSTRC("Size"));
1019     if (size < 0) {
1020         pStream->Release();
1021         return FALSE;
1022     }
1023     if (bMainXRef) {
1024         m_pTrailer = (CPDF_Dictionary*)pStream->GetDict()->Clone();
1025         m_CrossRef.SetSize(size);
1026         if (m_V5Type.SetSize(size)) {
1027             FXSYS_memset32(m_V5Type.GetData(), 0, size);
1028         }
1029     } else {
1030         m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
1031     }
1032     std::vector<std::pair<int32_t, int32_t> > arrIndex;
1033     CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
1034     if (pArray) {
1035         FX_DWORD nPairSize = pArray->GetCount() / 2;
1036         for (FX_DWORD i = 0; i < nPairSize; i++) {
1037             CPDF_Object* pStartNumObj = pArray->GetElement(i * 2);
1038             CPDF_Object* pCountObj = pArray->GetElement(i * 2 + 1);
1039             if (pStartNumObj && pStartNumObj->GetType() == PDFOBJ_NUMBER
1040                 && pCountObj && pCountObj->GetType() == PDFOBJ_NUMBER) {
1041                 int nStartNum = pStartNumObj->GetInteger();
1042                 int nCount = pCountObj->GetInteger();
1043                 if (nStartNum >= 0 && nCount > 0) {
1044                     arrIndex.push_back(std::make_pair(nStartNum, nCount));
1045                 }
1046             }
1047         }
1048     }
1049     if (arrIndex.size() == 0) {
1050         arrIndex.push_back(std::make_pair(0, size));
1051     }
1052     pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
1053     if (pArray == NULL) {
1054         pStream->Release();
1055         return FALSE;
1056     }
1057     CFX_DWordArray WidthArray;
1058     FX_SAFE_DWORD dwAccWidth = 0;
1059     for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
1060         WidthArray.Add(pArray->GetInteger(i));
1061         dwAccWidth += WidthArray[i];
1062     }
1063     if (!dwAccWidth.IsValid() || WidthArray.GetSize() < 3) {
1064         pStream->Release();
1065         return FALSE;
1066     }
1067     FX_DWORD totalWidth = dwAccWidth.ValueOrDie();
1068     CPDF_StreamAcc acc;
1069     acc.LoadAllData(pStream);
1070     const uint8_t* pData = acc.GetData();
1071     FX_DWORD dwTotalSize = acc.GetSize();
1072     FX_DWORD segindex = 0;
1073     for (FX_DWORD i = 0; i < arrIndex.size(); i ++) {
1074         int32_t startnum = arrIndex[i].first;
1075         if (startnum < 0) {
1076             continue;
1077         }
1078         m_dwXrefStartObjNum = pdfium::base::checked_cast<FX_DWORD, int32_t> (startnum);
1079         FX_DWORD count = pdfium::base::checked_cast<FX_DWORD, int32_t> (arrIndex[i].second);
1080         FX_SAFE_DWORD dwCaculatedSize = segindex;
1081         dwCaculatedSize += count;
1082         dwCaculatedSize *= totalWidth;
1083         if (!dwCaculatedSize.IsValid() || dwCaculatedSize.ValueOrDie() > dwTotalSize) { 
1084             continue;
1085         }
1086         const uint8_t* segstart = pData + segindex * totalWidth;
1087         FX_SAFE_DWORD dwMaxObjNum = startnum;
1088         dwMaxObjNum += count;
1089         FX_DWORD dwV5Size = pdfium::base::checked_cast<FX_DWORD, int32_t> (m_V5Type.GetSize());
1090         if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size) {
1091             continue;
1092         }
1093         for (FX_DWORD j = 0; j < count; j ++) {
1094             int32_t type = 1;
1095             const uint8_t* entrystart = segstart + j * totalWidth;
1096             if (WidthArray[0]) {
1097                 type = _GetVarInt(entrystart, WidthArray[0]);
1098             }
1099             if (m_V5Type[startnum + j] == 255) {
1100                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1101                 m_CrossRef[startnum + j] = offset;
1102                 void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1103                 if (pResult == NULL) {
1104                     m_SortedOffset.Add(offset);
1105                 }
1106                 continue;
1107             }
1108             if (m_V5Type[startnum + j]) {
1109                 continue;
1110             }
1111             m_V5Type[startnum + j] = type;
1112             if (type == 0) {
1113                 m_CrossRef[startnum + j] = 0;
1114             } else {
1115                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1116                 m_CrossRef[startnum + j] = offset;
1117                 if (type == 1) {
1118                     void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1119                     if (pResult == NULL) {
1120                         m_SortedOffset.Add(offset);
1121                     }
1122                 } else {
1123                     if (offset < 0 || offset >= m_V5Type.GetSize()) {
1124                         pStream->Release();
1125                         return FALSE;
1126                     }
1127                     m_V5Type[offset] = 255;
1128                 }
1129             }
1130         }
1131         segindex += count;
1132     }
1133     pStream->Release();
1134     return TRUE;
1135 }
1136 CPDF_Array* CPDF_Parser::GetIDArray()
1137 {
1138     CPDF_Object* pID = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("ID")) : NULL;
1139     if (pID == NULL) {
1140         return NULL;
1141     }
1142     if (pID->GetType() == PDFOBJ_REFERENCE) {
1143         pID = ParseIndirectObject(NULL, ((CPDF_Reference*)pID)->GetRefObjNum());
1144         m_pTrailer->SetAt(FX_BSTRC("ID"), pID);
1145     }
1146     if (pID == NULL || pID->GetType() != PDFOBJ_ARRAY) {
1147         return NULL;
1148     }
1149     return (CPDF_Array*)pID;
1150 }
1151 FX_DWORD CPDF_Parser::GetRootObjNum()
1152 {
1153     CPDF_Object* pRef = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Root")) : NULL;
1154     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1155         return 0;
1156     }
1157     return ((CPDF_Reference*) pRef)->GetRefObjNum();
1158 }
1159 FX_DWORD CPDF_Parser::GetInfoObjNum()
1160 {
1161     CPDF_Object* pRef = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Info")) : NULL;
1162     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1163         return 0;
1164     }
1165     return ((CPDF_Reference*) pRef)->GetRefObjNum();
1166 }
1167 FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm)
1168 {
1169     bForm = FALSE;
1170     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1171         return TRUE;
1172     }
1173     if (m_V5Type[objnum] == 0) {
1174         return TRUE;
1175     }
1176     if (m_V5Type[objnum] == 2) {
1177         return TRUE;
1178     }
1179     FX_FILESIZE pos = m_CrossRef[objnum];
1180     void* pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1181     if (pResult == NULL) {
1182         return TRUE;
1183     }
1184     if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
1185         return FALSE;
1186     }
1187     FX_FILESIZE size = ((FX_FILESIZE*)pResult)[1] - pos;
1188     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1189     m_Syntax.RestorePos(pos);
1190     bForm = m_Syntax.SearchMultiWord(FX_BSTRC("/Form\0stream"), TRUE, size) == 0;
1191     m_Syntax.RestorePos(SavedPos);
1192     return TRUE;
1193 }
1194 CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, PARSE_CONTEXT* pContext)
1195 {
1196     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1197         return NULL;
1198     }
1199     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1200         FX_FILESIZE pos = m_CrossRef[objnum];
1201         if (pos <= 0) {
1202             return NULL;
1203         }
1204         return ParseIndirectObjectAt(pObjList, pos, objnum, pContext);
1205     }
1206     if (m_V5Type[objnum] == 2) {
1207         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1208         if (pObjStream == NULL) {
1209             return NULL;
1210         }
1211         int32_t n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1212         int32_t offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1213         CPDF_SyntaxParser syntax;
1214         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((uint8_t*)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE));
1215         syntax.InitParser(file.Get(), 0);
1216         CPDF_Object* pRet = NULL;
1217         while (n) {
1218             FX_DWORD thisnum = syntax.GetDirectNum();
1219             FX_DWORD thisoff = syntax.GetDirectNum();
1220             if (thisnum == objnum) {
1221                 syntax.RestorePos(offset + thisoff);
1222                 pRet = syntax.GetObject(pObjList, 0, 0, pContext);
1223                 break;
1224             }
1225             n --;
1226         }
1227         return pRet;
1228     }
1229     return NULL;
1230 }
1231 CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum)
1232 {
1233     CPDF_StreamAcc* pStreamAcc = NULL;
1234     if (m_ObjectStreamMap.Lookup((void*)(uintptr_t)objnum, (void*&)pStreamAcc)) {
1235         return pStreamAcc;
1236     }
1237     const CPDF_Stream* pStream = m_pDocument ? (CPDF_Stream*)m_pDocument->GetIndirectObject(objnum) : NULL;
1238     if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
1239         return NULL;
1240     }
1241     pStreamAcc = new CPDF_StreamAcc;
1242     pStreamAcc->LoadAllData(pStream);
1243     m_ObjectStreamMap.SetAt((void*)(uintptr_t)objnum, pStreamAcc);
1244     return pStreamAcc;
1245 }
1246 FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum)
1247 {
1248     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1249         return 0;
1250     }
1251     if (m_V5Type[objnum] == 2) {
1252         objnum = (FX_DWORD)m_CrossRef[objnum];
1253     }
1254     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1255         FX_FILESIZE offset = m_CrossRef[objnum];
1256         if (offset == 0) {
1257             return 0;
1258         }
1259         void* pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1260         if (pResult == NULL) {
1261             return 0;
1262         }
1263         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
1264             return 0;
1265         }
1266         return ((FX_FILESIZE*)pResult)[1] - offset;
1267     }
1268     return 0;
1269 }
1270 void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, uint8_t*& pBuffer, FX_DWORD& size)
1271 {
1272     pBuffer = NULL;
1273     size = 0;
1274     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1275         return;
1276     }
1277     if (m_V5Type[objnum] == 2) {
1278         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1279         if (pObjStream == NULL) {
1280             return;
1281         }
1282         int32_t n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1283         int32_t offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1284         CPDF_SyntaxParser syntax;
1285         const uint8_t* pData = pObjStream->GetData();
1286         FX_DWORD totalsize = pObjStream->GetSize();
1287         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((uint8_t*)pData, (size_t)totalsize, FALSE));
1288         syntax.InitParser(file.Get(), 0);
1289         while (n) {
1290             FX_DWORD thisnum = syntax.GetDirectNum();
1291             FX_DWORD thisoff = syntax.GetDirectNum();
1292             if (thisnum == objnum) {
1293                 if (n == 1) {
1294                     size = totalsize - (thisoff + offset);
1295                 } else {
1296                     syntax.GetDirectNum();  // Skip nextnum.
1297                     FX_DWORD nextoff = syntax.GetDirectNum();
1298                     size = nextoff - thisoff;
1299                 }
1300                 pBuffer = FX_Alloc(uint8_t, size);
1301                 FXSYS_memcpy32(pBuffer, pData + thisoff + offset, size);
1302                 return;
1303             }
1304             n --;
1305         }
1306         return;
1307     }
1308     if (m_V5Type[objnum] == 1) {
1309         FX_FILESIZE pos = m_CrossRef[objnum];
1310         if (pos == 0) {
1311             return;
1312         }
1313         FX_FILESIZE SavedPos = m_Syntax.SavePos();
1314         m_Syntax.RestorePos(pos);
1315         FX_BOOL bIsNumber;
1316         CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1317         if (!bIsNumber) {
1318             m_Syntax.RestorePos(SavedPos);
1319             return;
1320         }
1321         FX_DWORD parser_objnum = FXSYS_atoi(word);
1322         if (parser_objnum && parser_objnum != objnum) {
1323             m_Syntax.RestorePos(SavedPos);
1324             return;
1325         }
1326         word = m_Syntax.GetNextWord(bIsNumber);
1327         if (!bIsNumber) {
1328             m_Syntax.RestorePos(SavedPos);
1329             return;
1330         }
1331         if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1332             m_Syntax.RestorePos(SavedPos);
1333             return;
1334         }
1335         void* pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1336         if (pResult == NULL) {
1337             m_Syntax.RestorePos(SavedPos);
1338             return;
1339         }
1340         FX_FILESIZE nextoff = ((FX_FILESIZE*)pResult)[1];
1341         FX_BOOL bNextOffValid = FALSE;
1342         if (nextoff != pos) {
1343             m_Syntax.RestorePos(nextoff);
1344             word = m_Syntax.GetNextWord(bIsNumber);
1345             if (word == FX_BSTRC("xref")) {
1346                 bNextOffValid = TRUE;
1347             } else if (bIsNumber) {
1348                 word = m_Syntax.GetNextWord(bIsNumber);
1349                 if (bIsNumber && m_Syntax.GetKeyword() == FX_BSTRC("obj")) {
1350                     bNextOffValid = TRUE;
1351                 }
1352             }
1353         }
1354         if (!bNextOffValid) {
1355             m_Syntax.RestorePos(pos);
1356             while (1) {
1357                 if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) {
1358                     break;
1359                 }
1360                 if (m_Syntax.SavePos() == m_Syntax.m_FileLen) {
1361                     break;
1362                 }
1363             }
1364             nextoff = m_Syntax.SavePos();
1365         }
1366         size = (FX_DWORD)(nextoff - pos);
1367         pBuffer = FX_Alloc(uint8_t, size);
1368         m_Syntax.RestorePos(pos);
1369         m_Syntax.ReadBlock(pBuffer, size);
1370         m_Syntax.RestorePos(SavedPos);
1371     }
1372 }
1373 CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
1374         PARSE_CONTEXT* pContext)
1375 {
1376     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1377     m_Syntax.RestorePos(pos);
1378     FX_BOOL bIsNumber;
1379     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1380     if (!bIsNumber) {
1381         m_Syntax.RestorePos(SavedPos);
1382         return NULL;
1383     }
1384     FX_FILESIZE objOffset = m_Syntax.SavePos();
1385     objOffset -= word.GetLength();
1386     FX_DWORD parser_objnum = FXSYS_atoi(word);
1387     if (objnum && parser_objnum != objnum) {
1388         m_Syntax.RestorePos(SavedPos);
1389         return NULL;
1390     }
1391     word = m_Syntax.GetNextWord(bIsNumber);
1392     if (!bIsNumber) {
1393         m_Syntax.RestorePos(SavedPos);
1394         return NULL;
1395     }
1396     FX_DWORD parser_gennum = FXSYS_atoi(word);
1397     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1398         m_Syntax.RestorePos(SavedPos);
1399         return NULL;
1400     }
1401     CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, parser_gennum, pContext);
1402     m_Syntax.SavePos();
1403     CFX_ByteString bsWord = m_Syntax.GetKeyword();
1404     if (bsWord == FX_BSTRC("endobj")) {
1405         m_Syntax.SavePos();
1406     }
1407     m_Syntax.RestorePos(SavedPos);
1408     if (pObj) {
1409         if (!objnum) {
1410             pObj->m_ObjNum = parser_objnum;
1411         }
1412         pObj->m_GenNum = parser_gennum;
1413     }
1414     return pObj;
1415 }
1416 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
1417         struct PARSE_CONTEXT* pContext, FX_FILESIZE *pResultPos)
1418 {
1419     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1420     m_Syntax.RestorePos(pos);
1421     FX_BOOL bIsNumber;
1422     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1423     if (!bIsNumber) {
1424         m_Syntax.RestorePos(SavedPos);
1425         return NULL;
1426     }
1427     FX_DWORD parser_objnum = FXSYS_atoi(word);
1428     if (objnum && parser_objnum != objnum) {
1429         m_Syntax.RestorePos(SavedPos);
1430         return NULL;
1431     }
1432     word = m_Syntax.GetNextWord(bIsNumber);
1433     if (!bIsNumber) {
1434         m_Syntax.RestorePos(SavedPos);
1435         return NULL;
1436     }
1437     FX_DWORD gennum = FXSYS_atoi(word);
1438     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1439         m_Syntax.RestorePos(SavedPos);
1440         return NULL;
1441     }
1442     CPDF_Object* pObj = m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, pContext);
1443     if (pResultPos) {
1444         *pResultPos = m_Syntax.m_Pos;
1445     }
1446     m_Syntax.RestorePos(SavedPos);
1447     return pObj;
1448 }
1449 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4()
1450 {
1451     if (m_Syntax.GetKeyword() != FX_BSTRC("trailer")) {
1452         return NULL;
1453     }
1454     CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
1455     if (pObj == NULL || pObj->GetType() != PDFOBJ_DICTIONARY) {
1456         if (pObj) {
1457             pObj->Release();
1458         }
1459         return NULL;
1460     }
1461     return (CPDF_Dictionary*)pObj;
1462 }
1463 FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision)
1464 {
1465     if (m_pSecurityHandler == NULL) {
1466         return (FX_DWORD) - 1;
1467     }
1468     FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions();
1469     if (m_pEncryptDict && m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) {
1470         dwPermission &= 0xFFFFFFFC;
1471         dwPermission |= 0xFFFFF0C0;
1472         if(bCheckRevision && m_pEncryptDict->GetInteger(FX_BSTRC("R")) == 2) {
1473             dwPermission &= 0xFFFFF0FF;
1474         }
1475     }
1476     return dwPermission;
1477 }
1478 FX_BOOL CPDF_Parser::IsOwner()
1479 {
1480     return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
1481 }
1482 void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler, FX_BOOL bForced)
1483 {
1484     ASSERT(m_pSecurityHandler == NULL);
1485     if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
1486         delete m_pSecurityHandler;
1487         m_pSecurityHandler = NULL;
1488     }
1489     m_bForceUseSecurityHandler = bForced;
1490     m_pSecurityHandler = pSecurityHandler;
1491     if (m_bForceUseSecurityHandler) {
1492         return;
1493     }
1494     m_Syntax.m_pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
1495     m_Syntax.m_pCryptoHandler->Init(NULL, pSecurityHandler);
1496 }
1497 FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, FX_DWORD offset)
1498 {
1499     m_Syntax.InitParser(pFileAccess, offset);
1500     m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9);
1501     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1502     FX_BOOL bIsNumber;
1503     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1504     if (!bIsNumber) {
1505         return FALSE;
1506     }
1507     FX_DWORD objnum = FXSYS_atoi(word);
1508     word = m_Syntax.GetNextWord(bIsNumber);
1509     if (!bIsNumber) {
1510         return FALSE;
1511     }
1512     FX_DWORD gennum = FXSYS_atoi(word);
1513     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1514         m_Syntax.RestorePos(SavedPos);
1515         return FALSE;
1516     }
1517     m_pLinearized = m_Syntax.GetObject(NULL, objnum, gennum, 0);
1518     if (!m_pLinearized) {
1519         return FALSE;
1520     }
1521     if (m_pLinearized->GetDict() && m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
1522         m_Syntax.GetNextWord(bIsNumber);
1523         CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
1524         if (!pLen) {
1525             m_pLinearized->Release();
1526             m_pLinearized = NULL;
1527             return FALSE;
1528         }
1529         if (pLen->GetInteger() != (int)pFileAccess->GetSize()) {
1530             return FALSE;
1531         }
1532         CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
1533         if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
1534             m_dwFirstPageNo = pNo->GetInteger();
1535         }
1536         CPDF_Object *pTable = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T"));
1537         if (pTable && pTable->GetType() == PDFOBJ_NUMBER) {
1538             m_LastXRefOffset = pTable->GetInteger();
1539         }
1540         return TRUE;
1541     }
1542     m_pLinearized->Release();
1543     m_pLinearized = NULL;
1544     return FALSE;
1545 }
1546 FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead)
1547 {
1548     CloseParser(bReParse);
1549     m_bXRefStream = FALSE;
1550     m_LastXRefOffset = 0;
1551     m_bOwnFileRead = bOwnFileRead;
1552     int32_t offset = GetHeaderOffset(pFileAccess);
1553     if (offset == -1) {
1554         return PDFPARSE_ERROR_FORMAT;
1555     }
1556     if (!IsLinearizedFile(pFileAccess, offset)) {
1557         m_Syntax.m_pFileAccess = NULL;
1558         return StartParse(pFileAccess, bReParse, bOwnFileRead);
1559     }
1560     if (!bReParse) {
1561         m_pDocument = new CPDF_Document(this);
1562     }
1563     FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos();
1564     FX_BOOL bXRefRebuilt = FALSE;
1565     FX_BOOL bLoadV4 = FALSE;
1566     if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) {
1567         if (!RebuildCrossRef()) {
1568             return PDFPARSE_ERROR_FORMAT;
1569         }
1570         bXRefRebuilt = TRUE;
1571         m_LastXRefOffset = 0;
1572     }
1573     if (bLoadV4) {
1574         m_pTrailer = LoadTrailerV4();
1575         if (m_pTrailer == NULL) {
1576             return FALSE;
1577         }
1578         int32_t xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
1579         if (xrefsize > 0) {
1580             m_CrossRef.SetSize(xrefsize);
1581             m_V5Type.SetSize(xrefsize);
1582         }
1583     }
1584     FX_DWORD dwRet = SetEncryptHandler();
1585     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1586         return dwRet;
1587     }
1588     m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1589     if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
1590         if (bXRefRebuilt) {
1591             return PDFPARSE_ERROR_FORMAT;
1592         }
1593         ReleaseEncryptHandler();
1594         if (!RebuildCrossRef()) {
1595             return PDFPARSE_ERROR_FORMAT;
1596         }
1597         dwRet = SetEncryptHandler();
1598         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1599             return dwRet;
1600         }
1601         m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1602         if (m_pDocument->GetRoot() == NULL) {
1603             return PDFPARSE_ERROR_FORMAT;
1604         }
1605     }
1606     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1607     FX_DWORD RootObjNum = GetRootObjNum();
1608     if (RootObjNum == 0) {
1609         ReleaseEncryptHandler();
1610         RebuildCrossRef();
1611         RootObjNum = GetRootObjNum();
1612         if (RootObjNum == 0) {
1613             return PDFPARSE_ERROR_FORMAT;
1614         }
1615         dwRet = SetEncryptHandler();
1616         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1617             return dwRet;
1618         }
1619     }
1620     if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) {
1621         CPDF_Object* pMetadata = m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
1622         if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
1623             m_Syntax.m_MetadataObjnum = ((CPDF_Reference*) pMetadata)->GetRefObjNum();
1624         }
1625     }
1626     return PDFPARSE_ERROR_SUCCESS;
1627 }
1628 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos)
1629 {
1630     if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1631         return FALSE;
1632     }
1633     while (xrefpos)
1634         if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1635             return FALSE;
1636         }
1637     m_ObjectStreamMap.InitHashTable(101, FALSE);
1638     m_bXRefStream = TRUE;
1639     return TRUE;
1640 }
1641 FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable()
1642 {
1643     FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum;
1644     m_Syntax.m_MetadataObjnum = 0;
1645     if (m_pTrailer) {
1646         m_pTrailer->Release();
1647         m_pTrailer = NULL;
1648     }
1649     m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset);
1650     uint8_t ch = 0;
1651     FX_DWORD dwCount = 0;
1652     m_Syntax.GetNextChar(ch);
1653     int32_t type = PDF_CharType[ch];
1654     while (type == 'W') {
1655         ++dwCount;
1656         if (m_Syntax.m_FileLen >= (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
1657             break;
1658         }
1659         m_Syntax.GetNextChar(ch);
1660         type = PDF_CharType[ch];
1661     }
1662     m_LastXRefOffset += dwCount;
1663     FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
1664     while (pos) {
1665         void* objnum;
1666         CPDF_StreamAcc* pStream;
1667         m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
1668         delete pStream;
1669     }
1670     m_ObjectStreamMap.RemoveAll();
1671     if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) {
1672         m_LastXRefOffset = 0;
1673         m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1674         return PDFPARSE_ERROR_FORMAT;
1675     }
1676     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1677     m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1678     return PDFPARSE_ERROR_SUCCESS;
1679 }
1680
1681 // static
1682 int CPDF_SyntaxParser::s_CurrentRecursionDepth = 0;
1683
1684 CPDF_SyntaxParser::CPDF_SyntaxParser()
1685 {
1686     m_pFileAccess = NULL;
1687     m_pCryptoHandler = NULL;
1688     m_pFileBuf = NULL;
1689     m_BufSize = CPDF_ModuleMgr::Get()->m_FileBufSize;
1690     m_pFileBuf = NULL;
1691     m_MetadataObjnum = 0;
1692     m_dwWordPos = 0;
1693     m_bFileStream = FALSE;
1694 }
1695 CPDF_SyntaxParser::~CPDF_SyntaxParser()
1696 {
1697     if (m_pFileBuf) {
1698         FX_Free(m_pFileBuf);
1699     }
1700 }
1701 FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, uint8_t& ch)
1702 {
1703     FX_FILESIZE save_pos = m_Pos;
1704     m_Pos = pos;
1705     FX_BOOL ret = GetNextChar(ch);
1706     m_Pos = save_pos;
1707     return ret;
1708 }
1709 FX_BOOL CPDF_SyntaxParser::GetNextChar(uint8_t& ch)
1710 {
1711     FX_FILESIZE pos = m_Pos + m_HeaderOffset;
1712     if (pos >= m_FileLen) {
1713         return FALSE;
1714     }
1715     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1716         FX_FILESIZE read_pos = pos;
1717         FX_DWORD read_size = m_BufSize;
1718         if ((FX_FILESIZE)read_size > m_FileLen) {
1719             read_size = (FX_DWORD)m_FileLen;
1720         }
1721         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1722             if (m_FileLen < (FX_FILESIZE)read_size) {
1723                 read_pos = 0;
1724                 read_size = (FX_DWORD)m_FileLen;
1725             } else {
1726                 read_pos = m_FileLen - read_size;
1727             }
1728         }
1729         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1730             return FALSE;
1731         }
1732         m_BufOffset = read_pos;
1733     }
1734     ch = m_pFileBuf[pos - m_BufOffset];
1735     m_Pos ++;
1736     return TRUE;
1737 }
1738 FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, uint8_t& ch)
1739 {
1740     pos += m_HeaderOffset;
1741     if (pos >= m_FileLen) {
1742         return FALSE;
1743     }
1744     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1745         FX_FILESIZE read_pos;
1746         if (pos < (FX_FILESIZE)m_BufSize) {
1747             read_pos = 0;
1748         } else {
1749             read_pos = pos - m_BufSize + 1;
1750         }
1751         FX_DWORD read_size = m_BufSize;
1752         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1753             if (m_FileLen < (FX_FILESIZE)read_size) {
1754                 read_pos = 0;
1755                 read_size = (FX_DWORD)m_FileLen;
1756             } else {
1757                 read_pos = m_FileLen - read_size;
1758             }
1759         }
1760         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1761             return FALSE;
1762         }
1763         m_BufOffset = read_pos;
1764     }
1765     ch = m_pFileBuf[pos - m_BufOffset];
1766     return TRUE;
1767 }
1768 FX_BOOL CPDF_SyntaxParser::ReadBlock(uint8_t* pBuf, FX_DWORD size)
1769 {
1770     if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) {
1771         return FALSE;
1772     }
1773     m_Pos += size;
1774     return TRUE;
1775 }
1776 #define MAX_WORD_BUFFER 256
1777 void CPDF_SyntaxParser::GetNextWord()
1778 {
1779     m_WordSize = 0;
1780     m_bIsNumber = TRUE;
1781     uint8_t ch;
1782     if (!GetNextChar(ch)) {
1783         return;
1784     }
1785     uint8_t type = PDF_CharType[ch];
1786     while (1) {
1787         while (type == 'W') {
1788             if (!GetNextChar(ch)) {
1789                 return;
1790             }
1791             type = PDF_CharType[ch];
1792         }
1793         if (ch != '%') {
1794             break;
1795         }
1796         while (1) {
1797             if (!GetNextChar(ch)) {
1798                 return;
1799             }
1800             if (ch == '\r' || ch == '\n') {
1801                 break;
1802             }
1803         }
1804         type = PDF_CharType[ch];
1805     }
1806     if (type == 'D') {
1807         m_bIsNumber = FALSE;
1808         m_WordBuffer[m_WordSize++] = ch;
1809         if (ch == '/') {
1810             while (1) {
1811                 if (!GetNextChar(ch)) {
1812                     return;
1813                 }
1814                 type = PDF_CharType[ch];
1815                 if (type != 'R' && type != 'N') {
1816                     m_Pos --;
1817                     return;
1818                 }
1819                 if (m_WordSize < MAX_WORD_BUFFER) {
1820                     m_WordBuffer[m_WordSize++] = ch;
1821                 }
1822             }
1823         } else if (ch == '<') {
1824             if (!GetNextChar(ch)) {
1825                 return;
1826             }
1827             if (ch == '<') {
1828                 m_WordBuffer[m_WordSize++] = ch;
1829             } else {
1830                 m_Pos --;
1831             }
1832         } else if (ch == '>') {
1833             if (!GetNextChar(ch)) {
1834                 return;
1835             }
1836             if (ch == '>') {
1837                 m_WordBuffer[m_WordSize++] = ch;
1838             } else {
1839                 m_Pos --;
1840             }
1841         }
1842         return;
1843     }
1844     while (1) {
1845         if (m_WordSize < MAX_WORD_BUFFER) {
1846             m_WordBuffer[m_WordSize++] = ch;
1847         }
1848         if (type != 'N') {
1849             m_bIsNumber = FALSE;
1850         }
1851         if (!GetNextChar(ch)) {
1852             return;
1853         }
1854         type = PDF_CharType[ch];
1855         if (type == 'D' || type == 'W') {
1856             m_Pos --;
1857             break;
1858         }
1859     }
1860 }
1861 CFX_ByteString CPDF_SyntaxParser::ReadString()
1862 {
1863     uint8_t ch;
1864     if (!GetNextChar(ch)) {
1865         return CFX_ByteString();
1866     }
1867     CFX_ByteTextBuf buf;
1868     int32_t parlevel = 0;
1869     int32_t status = 0, iEscCode = 0;
1870     while (1) {
1871         switch (status) {
1872             case 0:
1873                 if (ch == ')') {
1874                     if (parlevel == 0) {
1875                         return buf.GetByteString();
1876                     }
1877                     parlevel --;
1878                     buf.AppendChar(')');
1879                 } else if (ch == '(') {
1880                     parlevel ++;
1881                     buf.AppendChar('(');
1882                 } else if (ch == '\\') {
1883                     status = 1;
1884                 } else {
1885                     buf.AppendChar(ch);
1886                 }
1887                 break;
1888             case 1:
1889                 if (ch >= '0' && ch <= '7') {
1890                     iEscCode = ch - '0';
1891                     status = 2;
1892                     break;
1893                 }
1894                 if (ch == 'n') {
1895                     buf.AppendChar('\n');
1896                 } else if (ch == 'r') {
1897                     buf.AppendChar('\r');
1898                 } else if (ch == 't') {
1899                     buf.AppendChar('\t');
1900                 } else if (ch == 'b') {
1901                     buf.AppendChar('\b');
1902                 } else if (ch == 'f') {
1903                     buf.AppendChar('\f');
1904                 } else if (ch == '\r') {
1905                     status = 4;
1906                     break;
1907                 } else if (ch == '\n') {
1908                 } else {
1909                     buf.AppendChar(ch);
1910                 }
1911                 status = 0;
1912                 break;
1913             case 2:
1914                 if (ch >= '0' && ch <= '7') {
1915                     iEscCode = iEscCode * 8 + ch - '0';
1916                     status = 3;
1917                 } else {
1918                     buf.AppendChar(iEscCode);
1919                     status = 0;
1920                     continue;
1921                 }
1922                 break;
1923             case 3:
1924                 if (ch >= '0' && ch <= '7') {
1925                     iEscCode = iEscCode * 8 + ch - '0';
1926                     buf.AppendChar(iEscCode);
1927                     status = 0;
1928                 } else {
1929                     buf.AppendChar(iEscCode);
1930                     status = 0;
1931                     continue;
1932                 }
1933                 break;
1934             case 4:
1935                 status = 0;
1936                 if (ch != '\n') {
1937                     continue;
1938                 }
1939                 break;
1940         }
1941         if (!GetNextChar(ch)) {
1942             break;
1943         }
1944     }
1945     GetNextChar(ch);
1946     return buf.GetByteString();
1947 }
1948 CFX_ByteString CPDF_SyntaxParser::ReadHexString()
1949 {
1950     uint8_t ch;
1951     if (!GetNextChar(ch)) {
1952         return CFX_ByteString();
1953     }
1954     CFX_BinaryBuf buf;
1955     FX_BOOL bFirst = TRUE;
1956     uint8_t code = 0;
1957     while (1) {
1958         if (ch == '>') {
1959             break;
1960         }
1961         if (ch >= '0' && ch <= '9') {
1962             if (bFirst) {
1963                 code = (ch - '0') * 16;
1964             } else {
1965                 code += ch - '0';
1966                 buf.AppendByte((uint8_t)code);
1967             }
1968             bFirst = !bFirst;
1969         } else if (ch >= 'A' && ch <= 'F') {
1970             if (bFirst) {
1971                 code = (ch - 'A' + 10) * 16;
1972             } else {
1973                 code += ch - 'A' + 10;
1974                 buf.AppendByte((uint8_t)code);
1975             }
1976             bFirst = !bFirst;
1977         } else if (ch >= 'a' && ch <= 'f') {
1978             if (bFirst) {
1979                 code = (ch - 'a' + 10) * 16;
1980             } else {
1981                 code += ch - 'a' + 10;
1982                 buf.AppendByte((uint8_t)code);
1983             }
1984             bFirst = !bFirst;
1985         }
1986         if (!GetNextChar(ch)) {
1987             break;
1988         }
1989     }
1990     if (!bFirst) {
1991         buf.AppendByte((uint8_t)code);
1992     }
1993     return buf.GetByteString();
1994 }
1995 void CPDF_SyntaxParser::ToNextLine()
1996 {
1997     uint8_t ch;
1998     while (1) {
1999         if (!GetNextChar(ch)) {
2000             return;
2001         }
2002         if (ch == '\n') {
2003             return;
2004         }
2005         if (ch == '\r') {
2006             GetNextChar(ch);
2007             if (ch == '\n') {
2008                 return;
2009             } else {
2010                 m_Pos --;
2011                 return;
2012             }
2013         }
2014     }
2015 }
2016 void CPDF_SyntaxParser::ToNextWord()
2017 {
2018     uint8_t ch;
2019     if (!GetNextChar(ch)) {
2020         return;
2021     }
2022     uint8_t type = PDF_CharType[ch];
2023     while (1) {
2024         while (type == 'W') {
2025             m_dwWordPos = m_Pos;
2026             if (!GetNextChar(ch)) {
2027                 return;
2028             }
2029             type = PDF_CharType[ch];
2030         }
2031         if (ch != '%') {
2032             break;
2033         }
2034         while (1) {
2035             if (!GetNextChar(ch)) {
2036                 return;
2037             }
2038             if (ch == '\r' || ch == '\n') {
2039                 break;
2040             }
2041         }
2042         type = PDF_CharType[ch];
2043     }
2044     m_Pos --;
2045 }
2046 CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber)
2047 {
2048     GetNextWord();
2049     bIsNumber = m_bIsNumber;
2050     return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize);
2051 }
2052 CFX_ByteString CPDF_SyntaxParser::GetKeyword()
2053 {
2054     GetNextWord();
2055     return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize);
2056 }
2057 CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, PARSE_CONTEXT* pContext, FX_BOOL bDecrypt)
2058 {
2059     CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
2060     if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) {
2061         return NULL;
2062     }
2063     FX_FILESIZE SavedPos = m_Pos;
2064     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2065     FX_BOOL bIsNumber;
2066     CFX_ByteString word = GetNextWord(bIsNumber);
2067     CPDF_Object* pRet = NULL;
2068     if (word.GetLength() == 0) {
2069         if (bTypeOnly) {
2070             return (CPDF_Object*)PDFOBJ_INVALID;
2071         }
2072         return NULL;
2073     }
2074     if (bIsNumber) {
2075         FX_FILESIZE SavedPos = m_Pos;
2076         CFX_ByteString nextword = GetNextWord(bIsNumber);
2077         if (bIsNumber) {
2078             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2079             if (nextword2 == FX_BSTRC("R")) {
2080                 FX_DWORD objnum = FXSYS_atoi(word);
2081                 if (bTypeOnly) {
2082                     return (CPDF_Object*)PDFOBJ_REFERENCE;
2083                 }
2084                 pRet = CPDF_Reference::Create(pObjList, objnum);
2085                 return pRet;
2086             } else {
2087                 m_Pos = SavedPos;
2088                 if (bTypeOnly) {
2089                     return (CPDF_Object*)PDFOBJ_NUMBER;
2090                 }
2091                 pRet = CPDF_Number::Create(word);
2092                 return pRet;
2093             }
2094         } else {
2095             m_Pos = SavedPos;
2096             if (bTypeOnly) {
2097                 return (CPDF_Object*)PDFOBJ_NUMBER;
2098             }
2099             pRet = CPDF_Number::Create(word);
2100             return pRet;
2101         }
2102     }
2103     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2104         if (bTypeOnly) {
2105             return (CPDF_Object*)PDFOBJ_BOOLEAN;
2106         }
2107         pRet = CPDF_Boolean::Create(word == FX_BSTRC("true"));
2108         return pRet;
2109     }
2110     if (word == FX_BSTRC("null")) {
2111         if (bTypeOnly) {
2112             return (CPDF_Object*)PDFOBJ_NULL;
2113         }
2114         pRet = CPDF_Null::Create();
2115         return pRet;
2116     }
2117     if (word == FX_BSTRC("(")) {
2118         if (bTypeOnly) {
2119             return (CPDF_Object*)PDFOBJ_STRING;
2120         }
2121         CFX_ByteString str = ReadString();
2122         if (m_pCryptoHandler && bDecrypt) {
2123             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2124         }
2125         pRet = CPDF_String::Create(str, FALSE);
2126         return pRet;
2127     }
2128     if (word == FX_BSTRC("<")) {
2129         if (bTypeOnly) {
2130             return (CPDF_Object*)PDFOBJ_STRING;
2131         }
2132         CFX_ByteString str = ReadHexString();
2133         if (m_pCryptoHandler && bDecrypt) {
2134             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2135         }
2136         pRet = CPDF_String::Create(str, TRUE);
2137         return pRet;
2138     }
2139     if (word == FX_BSTRC("[")) {
2140         if (bTypeOnly) {
2141             return (CPDF_Object*)PDFOBJ_ARRAY;
2142         }
2143         CPDF_Array* pArray = CPDF_Array::Create();
2144         while (1) {
2145             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2146             if (pObj == NULL) {
2147                 return pArray;
2148             }
2149             pArray->Add(pObj);
2150         }
2151     }
2152     if (word[0] == '/') {
2153         if (bTypeOnly) {
2154             return (CPDF_Object*)PDFOBJ_NAME;
2155         }
2156         pRet = CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2157         return pRet;
2158     }
2159     if (word == FX_BSTRC("<<")) {
2160         if (bTypeOnly) {
2161             return (CPDF_Object*)PDFOBJ_DICTIONARY;
2162         }
2163         if (pContext) {
2164             pContext->m_DictStart = SavedPos;
2165         }
2166         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2167         int32_t nKeys = 0;
2168         FX_FILESIZE dwSignValuePos = 0;
2169         while (1) {
2170             FX_BOOL bIsNumber;
2171             CFX_ByteString key = GetNextWord(bIsNumber);
2172             if (key.IsEmpty()) {
2173                 if (pDict)
2174                     pDict->Release();
2175                 return NULL;
2176             }
2177             FX_FILESIZE SavedPos = m_Pos - key.GetLength();
2178             if (key == FX_BSTRC(">>")) {
2179                 break;
2180             }
2181             if (key == FX_BSTRC("endobj")) {
2182                 m_Pos = SavedPos;
2183                 break;
2184             }
2185             if (key[0] != '/') {
2186                 continue;
2187             }
2188             nKeys ++;
2189             key = PDF_NameDecode(key);
2190             if (key == FX_BSTRC("/Contents")) {
2191                 dwSignValuePos = m_Pos;
2192             }
2193             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2194             if (pObj == NULL) {
2195                 continue;
2196             }
2197             if (key.GetLength() >= 1) {
2198                 if (nKeys < 32) {
2199                     pDict->SetAt(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj);
2200                 } else {
2201                     pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj);
2202                 }
2203             }
2204         }
2205         if (IsSignatureDict(pDict)) {
2206             FX_FILESIZE dwSavePos = m_Pos;
2207             m_Pos = dwSignValuePos;
2208             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, NULL, FALSE);
2209             pDict->SetAt(FX_BSTRC("Contents"), pObj);
2210             m_Pos = dwSavePos;
2211         }
2212         if (pContext) {
2213             pContext->m_DictEnd = m_Pos;
2214             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2215                 return pDict;
2216             }
2217         }
2218         FX_FILESIZE SavedPos = m_Pos;
2219         FX_BOOL bIsNumber;
2220         CFX_ByteString nextword = GetNextWord(bIsNumber);
2221         if (nextword == FX_BSTRC("stream")) {
2222             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2223             if (pStream) {
2224                 return pStream;
2225             }
2226             if (pDict)
2227                 pDict->Release();
2228             return NULL;
2229         } else {
2230             m_Pos = SavedPos;
2231             return pDict;
2232         }
2233     }
2234     if (word == FX_BSTRC(">>")) {
2235         m_Pos = SavedPos;
2236         return NULL;
2237     }
2238     if (bTypeOnly) {
2239         return (CPDF_Object*)PDFOBJ_INVALID;
2240     }
2241     return NULL;
2242 }
2243 CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, struct PARSE_CONTEXT* pContext)
2244 {
2245     CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
2246     if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) {
2247         return NULL;
2248     }
2249     FX_FILESIZE SavedPos = m_Pos;
2250     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2251     FX_BOOL bIsNumber;
2252     CFX_ByteString word = GetNextWord(bIsNumber);
2253     if (word.GetLength() == 0) {
2254         if (bTypeOnly) {
2255             return (CPDF_Object*)PDFOBJ_INVALID;
2256         }
2257         return NULL;
2258     }
2259     if (bIsNumber) {
2260         FX_FILESIZE SavedPos = m_Pos;
2261         CFX_ByteString nextword = GetNextWord(bIsNumber);
2262         if (bIsNumber) {
2263             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2264             if (nextword2 == FX_BSTRC("R")) {
2265                 FX_DWORD objnum = FXSYS_atoi(word);
2266                 if (bTypeOnly) {
2267                     return (CPDF_Object*)PDFOBJ_REFERENCE;
2268                 }
2269                 return CPDF_Reference::Create(pObjList, objnum);
2270             } else {
2271                 m_Pos = SavedPos;
2272                 if (bTypeOnly) {
2273                     return (CPDF_Object*)PDFOBJ_NUMBER;
2274                 }
2275                 return CPDF_Number::Create(word);
2276             }
2277         } else {
2278             m_Pos = SavedPos;
2279             if (bTypeOnly) {
2280                 return (CPDF_Object*)PDFOBJ_NUMBER;
2281             }
2282             return CPDF_Number::Create(word);
2283         }
2284     }
2285     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2286         if (bTypeOnly) {
2287             return (CPDF_Object*)PDFOBJ_BOOLEAN;
2288         }
2289         return CPDF_Boolean::Create(word == FX_BSTRC("true"));
2290     }
2291     if (word == FX_BSTRC("null")) {
2292         if (bTypeOnly) {
2293             return (CPDF_Object*)PDFOBJ_NULL;
2294         }
2295         return CPDF_Null::Create();
2296     }
2297     if (word == FX_BSTRC("(")) {
2298         if (bTypeOnly) {
2299             return (CPDF_Object*)PDFOBJ_STRING;
2300         }
2301         CFX_ByteString str = ReadString();
2302         if (m_pCryptoHandler) {
2303             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2304         }
2305         return CPDF_String::Create(str, FALSE);
2306     }
2307     if (word == FX_BSTRC("<")) {
2308         if (bTypeOnly) {
2309             return (CPDF_Object*)PDFOBJ_STRING;
2310         }
2311         CFX_ByteString str = ReadHexString();
2312         if (m_pCryptoHandler) {
2313             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2314         }
2315         return CPDF_String::Create(str, TRUE);
2316     }
2317     if (word == FX_BSTRC("[")) {
2318         if (bTypeOnly) {
2319             return (CPDF_Object*)PDFOBJ_ARRAY;
2320         }
2321         CPDF_Array* pArray = CPDF_Array::Create();
2322         while (1) {
2323             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2324             if (pObj == NULL) {
2325                 if (m_WordBuffer[0] == ']') {
2326                     return pArray;
2327                 }
2328                 if (pArray) {
2329                     pArray->Release();
2330                 }
2331                 return NULL;
2332             }
2333             pArray->Add(pObj);
2334         }
2335     }
2336     if (word[0] == '/') {
2337         if (bTypeOnly) {
2338             return (CPDF_Object*)PDFOBJ_NAME;
2339         }
2340         return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2341     }
2342     if (word == FX_BSTRC("<<")) {
2343         if (bTypeOnly) {
2344             return (CPDF_Object*)PDFOBJ_DICTIONARY;
2345         }
2346         if (pContext) {
2347             pContext->m_DictStart = SavedPos;
2348         }
2349         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2350         while (1) {
2351             FX_BOOL bIsNumber;
2352             FX_FILESIZE SavedPos = m_Pos;
2353             CFX_ByteString key = GetNextWord(bIsNumber);
2354             if (key.IsEmpty()) {
2355                 if (pDict) {
2356                     pDict->Release();
2357                 }
2358                 return NULL;
2359             }
2360             if (key == FX_BSTRC(">>")) {
2361                 break;
2362             }
2363             if (key == FX_BSTRC("endobj")) {
2364                 m_Pos = SavedPos;
2365                 break;
2366             }
2367             if (key[0] != '/') {
2368                 continue;
2369             }
2370             key = PDF_NameDecode(key);
2371             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2372             if (pObj == NULL) {
2373                 if (pDict) {
2374                     pDict->Release();
2375                 }
2376                 uint8_t ch;
2377                 while (1) {
2378                     if (!GetNextChar(ch)) {
2379                         break;
2380                     }
2381                     if (ch == 0x0A || ch == 0x0D) {
2382                         break;
2383                     }
2384                 }
2385                 return NULL;
2386             }
2387             if (key.GetLength() > 1) {
2388                 pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj);
2389             } 
2390         }
2391         if (pContext) {
2392             pContext->m_DictEnd = m_Pos;
2393             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2394                 return pDict;
2395             }
2396         }
2397         FX_FILESIZE SavedPos = m_Pos;
2398         FX_BOOL bIsNumber;
2399         CFX_ByteString nextword = GetNextWord(bIsNumber);
2400         if (nextword == FX_BSTRC("stream")) {
2401             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2402             if (pStream) {
2403                 return pStream;
2404             }
2405             if (pDict) {
2406                 pDict->Release();
2407             }
2408             return NULL;
2409         } else {
2410             m_Pos = SavedPos;
2411             return pDict;
2412         }
2413     }
2414     if (word == FX_BSTRC(">>")) {
2415         m_Pos = SavedPos;
2416         return NULL;
2417     }
2418     if (bTypeOnly) {
2419         return (CPDF_Object*)PDFOBJ_INVALID;
2420     }
2421     return NULL;
2422 }
2423 CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, PARSE_CONTEXT* pContext,
2424         FX_DWORD objnum, FX_DWORD gennum)
2425 {
2426     CPDF_Object* pLenObj = pDict->GetElement(FX_BSTRC("Length"));
2427     FX_FILESIZE len = 0;
2428     if (pLenObj && ((pLenObj->GetType() != PDFOBJ_REFERENCE) ||
2429                     ((((CPDF_Reference*)pLenObj)->GetObjList() != NULL) &&
2430                      ((CPDF_Reference*)pLenObj)->GetRefObjNum() != objnum))) {
2431         len = pLenObj->GetInteger();
2432     }
2433
2434     ToNextLine();
2435     FX_FILESIZE StreamStartPos = m_Pos;
2436     if (pContext) {
2437         pContext->m_DataStart = m_Pos;
2438     }
2439
2440     CPDF_CryptoHandler* pCryptoHandler = objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler;
2441     if (pCryptoHandler == NULL) {
2442         pdfium::base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
2443         pos += len;
2444         if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
2445             m_Pos = pos.ValueOrDie();
2446         }
2447         GetNextWord();
2448         if (m_WordSize < 9 || FXSYS_memcmp32(m_WordBuffer, "endstream", 9)) {
2449             m_Pos = StreamStartPos;
2450             FX_FILESIZE offset = FindTag(FX_BSTRC("endstream"), 0);
2451             if (offset >= 0) {
2452                 FX_FILESIZE curPos = m_Pos;
2453                 m_Pos = StreamStartPos;
2454                 FX_FILESIZE endobjOffset = FindTag(FX_BSTRC("endobj"), 0);
2455                 if (endobjOffset < offset && endobjOffset >= 0) {
2456                     offset = endobjOffset;
2457                 } else {
2458                     m_Pos = curPos;
2459                 }
2460                 uint8_t byte1, byte2;
2461                 GetCharAt(StreamStartPos + offset - 1, byte1);
2462                 GetCharAt(StreamStartPos + offset - 2, byte2);
2463                 if (byte1 == 0x0a && byte2 == 0x0d) {
2464                     len -= 2;
2465                 } else if (byte1 == 0x0a || byte1 == 0x0d) {
2466                     len --;
2467                 }
2468                 len = (FX_DWORD)offset;
2469                 pDict->SetAtInteger(FX_BSTRC("Length"), len);
2470             } else {
2471                 m_Pos = StreamStartPos;
2472                 if (FindTag(FX_BSTRC("endobj"), 0) < 0) {
2473                     return NULL;
2474                 }
2475             }
2476         }
2477         m_Pos = StreamStartPos;
2478     }
2479     CPDF_Stream* pStream;
2480     uint8_t* pData = FX_Alloc(uint8_t, len);
2481     ReadBlock(pData, len);
2482     if (pCryptoHandler) {
2483         CFX_BinaryBuf dest_buf;
2484         dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len));
2485         void* context = pCryptoHandler->DecryptStart(objnum, gennum);
2486         pCryptoHandler->DecryptStream(context, pData, len, dest_buf);
2487         pCryptoHandler->DecryptFinish(context, dest_buf);
2488         FX_Free(pData);
2489         pData = dest_buf.GetBuffer();
2490         len = dest_buf.GetSize();
2491         dest_buf.DetachBuffer();
2492     }
2493     pStream = new CPDF_Stream(pData, len, pDict);
2494     if (pContext) {
2495         pContext->m_DataEnd = pContext->m_DataStart + len;
2496     }
2497     StreamStartPos = m_Pos;
2498     GetNextWord();
2499     if (m_WordSize == 6 && 0 == FXSYS_memcmp32(m_WordBuffer, "endobj", 6)) {
2500         m_Pos = StreamStartPos;
2501     }
2502     return pStream;
2503 }
2504 void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess, FX_DWORD HeaderOffset)
2505 {
2506     if (m_pFileBuf) {
2507         FX_Free(m_pFileBuf);
2508         m_pFileBuf = NULL;
2509     }
2510     m_pFileBuf = FX_Alloc(uint8_t, m_BufSize);
2511     m_HeaderOffset = HeaderOffset;
2512     m_FileLen = pFileAccess->GetSize();
2513     m_Pos = 0;
2514     m_pFileAccess = pFileAccess;
2515     m_BufOffset = 0;
2516     pFileAccess->ReadBlock(m_pFileBuf, 0, (size_t)((FX_FILESIZE)m_BufSize > m_FileLen ? m_FileLen : m_BufSize));
2517 }
2518 int32_t CPDF_SyntaxParser::GetDirectNum()
2519 {
2520     GetNextWord();
2521     if (!m_bIsNumber) {
2522         return 0;
2523     }
2524     m_WordBuffer[m_WordSize] = 0;
2525     return FXSYS_atoi((const FX_CHAR*)m_WordBuffer);
2526 }
2527 FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit, const uint8_t* tag, FX_DWORD taglen)
2528 {
2529     uint8_t type = PDF_CharType[tag[0]];
2530     FX_BOOL bCheckLeft = type != 'D' && type != 'W';
2531     type = PDF_CharType[tag[taglen - 1]];
2532     FX_BOOL bCheckRight = type != 'D' && type != 'W';
2533     uint8_t ch;
2534     if (bCheckRight && startpos + (int32_t)taglen <= limit && GetCharAt(startpos + (int32_t)taglen, ch)) {
2535         uint8_t type = PDF_CharType[ch];
2536         if (type == 'N' || type == 'R') {
2537             return FALSE;
2538         }
2539     }
2540     if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
2541         uint8_t type = PDF_CharType[ch];
2542         if (type == 'N' || type == 'R') {
2543             return FALSE;
2544         }
2545     }
2546     return TRUE;
2547 }
2548 FX_BOOL CPDF_SyntaxParser::SearchWord(const CFX_ByteStringC& tag, FX_BOOL bWholeWord, FX_BOOL bForward, FX_FILESIZE limit)
2549 {
2550     int32_t taglen = tag.GetLength();
2551     if (taglen == 0) {
2552         return FALSE;
2553     }
2554     FX_FILESIZE pos = m_Pos;
2555     int32_t offset = 0;
2556     if (!bForward) {
2557         offset = taglen - 1;
2558     }
2559     const uint8_t* tag_data = tag.GetPtr();
2560     uint8_t byte;
2561     while (1) {
2562         if (bForward) {
2563             if (limit) {
2564                 if (pos >= m_Pos + limit) {
2565                     return FALSE;
2566                 }
2567             }
2568             if (!GetCharAt(pos, byte)) {
2569                 return FALSE;
2570             }
2571         } else {
2572             if (limit) {
2573                 if (pos <= m_Pos - limit) {
2574                     return FALSE;
2575                 }
2576             }
2577             if (!GetCharAtBackward(pos, byte)) {
2578                 return FALSE;
2579             }
2580         }
2581         if (byte == tag_data[offset]) {
2582             if (bForward) {
2583                 offset ++;
2584                 if (offset < taglen) {
2585                     pos ++;
2586                     continue;
2587                 }
2588             } else {
2589                 offset --;
2590                 if (offset >= 0) {
2591                     pos --;
2592                     continue;
2593                 }
2594             }
2595             FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos;
2596             if (!bWholeWord || IsWholeWord(startpos, limit, tag.GetPtr(), taglen)) {
2597                 m_Pos = startpos;
2598                 return TRUE;
2599             }
2600         }
2601         if (bForward) {
2602             offset = byte == tag_data[0] ? 1 : 0;
2603             pos ++;
2604         } else {
2605             offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1;
2606             pos --;
2607         }
2608         if (pos < 0) {
2609             return FALSE;
2610         }
2611     }
2612     return FALSE;
2613 }
2614 struct _SearchTagRecord {
2615     const uint8_t*      m_pTag;
2616     FX_DWORD    m_Len;
2617     FX_DWORD    m_Offset;
2618 };
2619 int32_t CPDF_SyntaxParser::SearchMultiWord(const CFX_ByteStringC& tags, FX_BOOL bWholeWord, FX_FILESIZE limit)
2620 {
2621     int32_t ntags = 1, i;
2622     for (i = 0; i < tags.GetLength(); i ++)
2623         if (tags[i] == 0) {
2624             ntags ++;
2625         }
2626     _SearchTagRecord* pPatterns = FX_Alloc(_SearchTagRecord, ntags);
2627     FX_DWORD start = 0, itag = 0, max_len = 0;
2628     for (i = 0; i <= tags.GetLength(); i ++) {
2629         if (tags[i] == 0) {
2630             FX_DWORD len = i - start;
2631             if (len > max_len) {
2632                 max_len = len;
2633             }
2634             pPatterns[itag].m_pTag = tags.GetPtr() + start;
2635             pPatterns[itag].m_Len = len;
2636             pPatterns[itag].m_Offset = 0;
2637             start = i + 1;
2638             itag ++;
2639         }
2640     }
2641     FX_FILESIZE pos = m_Pos;
2642     uint8_t byte;
2643     GetCharAt(pos++, byte);
2644     int32_t found = -1;
2645     while (1) {
2646         for (i = 0; i < ntags; i ++) {
2647             if (pPatterns[i].m_pTag[pPatterns[i].m_Offset] == byte) {
2648                 pPatterns[i].m_Offset ++;
2649                 if (pPatterns[i].m_Offset == pPatterns[i].m_Len) {
2650                     if (!bWholeWord || IsWholeWord(pos - pPatterns[i].m_Len, limit, pPatterns[i].m_pTag, pPatterns[i].m_Len)) {
2651                         found = i;
2652                         goto end;
2653                     } else {
2654                         if (pPatterns[i].m_pTag[0] == byte) {
2655                             pPatterns[i].m_Offset = 1;
2656                         } else {
2657                             pPatterns[i].m_Offset = 0;
2658                         }
2659                     }
2660                 }
2661             } else {
2662                 if (pPatterns[i].m_pTag[0] == byte) {
2663                     pPatterns[i].m_Offset = 1;
2664                 } else {
2665                     pPatterns[i].m_Offset = 0;
2666                 }
2667             }
2668         }
2669         if (limit && pos >= m_Pos + limit) {
2670             goto end;
2671         }
2672         if (!GetCharAt(pos, byte)) {
2673             goto end;
2674         }
2675         pos ++;
2676     }
2677 end:
2678     FX_Free(pPatterns);
2679     return found;
2680 }
2681 FX_FILESIZE CPDF_SyntaxParser::FindTag(const CFX_ByteStringC& tag, FX_FILESIZE limit)
2682 {
2683     int32_t taglen = tag.GetLength();
2684     int32_t match = 0;
2685     limit += m_Pos;
2686     FX_FILESIZE startpos = m_Pos;
2687     while (1) {
2688         uint8_t ch;
2689         if (!GetNextChar(ch)) {
2690             return -1;
2691         }
2692         if (ch == tag[match]) {
2693             match ++;
2694             if (match == taglen) {
2695                 return m_Pos - startpos - taglen;
2696             }
2697         } else {
2698             match = ch == tag[0] ? 1 : 0;
2699         }
2700         if (limit && m_Pos == limit) {
2701             return -1;
2702         }
2703     }
2704     return -1;
2705 }
2706 void CPDF_SyntaxParser::GetBinary(uint8_t* buffer, FX_DWORD size)
2707 {
2708     FX_DWORD offset = 0;
2709     uint8_t ch;
2710     while (1) {
2711         if (!GetNextChar(ch)) {
2712             return;
2713         }
2714         buffer[offset++] = ch;
2715         if (offset == size) {
2716             break;
2717         }
2718     }
2719 }
2720
2721 class CPDF_DataAvail final : public IPDF_DataAvail
2722 {
2723 public:
2724     CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead);
2725     ~CPDF_DataAvail();
2726
2727     virtual FX_BOOL                     IsDocAvail(IFX_DownloadHints* pHints)  override;
2728
2729     virtual void                        SetDocument(CPDF_Document* pDoc)  override;
2730
2731     virtual FX_BOOL                     IsPageAvail(int iPage, IFX_DownloadHints* pHints)  override;
2732
2733     virtual int32_t                     IsFormAvail(IFX_DownloadHints *pHints)  override;
2734
2735     virtual int32_t                     IsLinearizedPDF()  override;
2736
2737     virtual FX_BOOL                     IsLinearized()  override
2738     {
2739         return m_bLinearized;
2740     }
2741
2742     virtual void                        GetLinearizedMainXRefInfo(FX_FILESIZE *pPos, FX_DWORD *pSize)  override;
2743
2744 protected:
2745     static const int kMaxDataAvailRecursionDepth = 64;
2746     static int s_CurrentDataAvailRecursionDepth;
2747
2748     FX_DWORD                            GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset);
2749     FX_BOOL                             IsObjectsAvail(CFX_PtrArray& obj_array, FX_BOOL bParsePage, IFX_DownloadHints* pHints, CFX_PtrArray &ret_array);
2750     FX_BOOL                             CheckDocStatus(IFX_DownloadHints *pHints);
2751     FX_BOOL                             CheckHeader(IFX_DownloadHints* pHints);
2752     FX_BOOL                             CheckFirstPage(IFX_DownloadHints *pHints);
2753     FX_BOOL                             CheckEnd(IFX_DownloadHints *pHints);
2754     FX_BOOL                             CheckCrossRef(IFX_DownloadHints* pHints);
2755     FX_BOOL                             CheckCrossRefItem(IFX_DownloadHints *pHints);
2756     FX_BOOL                             CheckTrailer(IFX_DownloadHints* pHints);
2757     FX_BOOL                             CheckRoot(IFX_DownloadHints* pHints);
2758     FX_BOOL                             CheckInfo(IFX_DownloadHints* pHints);
2759     FX_BOOL                             CheckPages(IFX_DownloadHints* pHints);
2760     FX_BOOL                             CheckPage(IFX_DownloadHints* pHints);
2761     FX_BOOL                             CheckResources(IFX_DownloadHints* pHints);
2762     FX_BOOL                             CheckAnnots(IFX_DownloadHints* pHints);
2763     FX_BOOL                             CheckAcroForm(IFX_DownloadHints* pHints);
2764     FX_BOOL                             CheckAcroFormSubObject(IFX_DownloadHints* pHints);
2765     FX_BOOL                             CheckTrailerAppend(IFX_DownloadHints* pHints);
2766     FX_BOOL                             CheckPageStatus(IFX_DownloadHints* pHints);
2767     FX_BOOL                             CheckAllCrossRefStream(IFX_DownloadHints *pHints);
2768
2769     int32_t                            CheckCrossRefStream(IFX_DownloadHints *pHints, FX_FILESIZE &xref_offset);
2770     FX_BOOL                             IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen);
2771     void                                SetStartOffset(FX_FILESIZE dwOffset);
2772     FX_BOOL                             GetNextToken(CFX_ByteString &token);
2773     FX_BOOL                             GetNextChar(uint8_t &ch);
2774     CPDF_Object *                       ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD objnum);
2775     CPDF_Object *                       GetObject(FX_DWORD objnum, IFX_DownloadHints* pHints, FX_BOOL *pExistInFile);
2776     FX_BOOL                             GetPageKids(CPDF_Parser *pParser, CPDF_Object *pPages);
2777     FX_BOOL                             PreparePageItem();
2778     FX_BOOL                             LoadPages(IFX_DownloadHints* pHints);
2779     FX_BOOL                             LoadAllXref(IFX_DownloadHints* pHints);
2780     FX_BOOL                             LoadAllFile(IFX_DownloadHints* pHints);
2781     FX_BOOL                             CheckLinearizedData(IFX_DownloadHints* pHints);
2782     FX_BOOL                             CheckFileResources(IFX_DownloadHints* pHints);
2783     FX_BOOL                             CheckPageAnnots(int iPage, IFX_DownloadHints* pHints);
2784
2785     FX_BOOL                             CheckLinearizedFirstPage(int iPage, IFX_DownloadHints* pHints);
2786     FX_BOOL                             HaveResourceAncestor(CPDF_Dictionary *pDict);
2787     FX_BOOL                             CheckPage(int32_t iPage, IFX_DownloadHints* pHints);
2788     FX_BOOL                             LoadDocPages(IFX_DownloadHints* pHints);
2789     FX_BOOL                             LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints);
2790     FX_BOOL                             CheckPageNode(CPDF_PageNode &pageNodes, int32_t iPage, int32_t &iCount, IFX_DownloadHints* pHints);
2791     FX_BOOL                             CheckUnkownPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints);
2792     FX_BOOL                             CheckArrayPageNode(FX_DWORD dwPageNo, CPDF_PageNode *pPageNode, IFX_DownloadHints* pHints);
2793     FX_BOOL                             CheckPageCount(IFX_DownloadHints* pHints);
2794     FX_BOOL                             IsFirstCheck(int iPage);
2795     void                                ResetFirstCheck(int iPage);
2796
2797     CPDF_Parser                         m_parser;
2798
2799     CPDF_SyntaxParser                   m_syntaxParser;
2800
2801     CPDF_Object                         *m_pRoot;
2802
2803     FX_DWORD                            m_dwRootObjNum;
2804
2805     FX_DWORD                            m_dwInfoObjNum;
2806
2807     CPDF_Object                         *m_pLinearized;
2808
2809     CPDF_Object                         *m_pTrailer;
2810
2811     FX_BOOL                             m_bDocAvail;
2812
2813     FX_FILESIZE                         m_dwHeaderOffset;
2814
2815     FX_FILESIZE                         m_dwLastXRefOffset;
2816
2817     FX_FILESIZE                         m_dwXRefOffset;
2818
2819     FX_FILESIZE                         m_dwTrailerOffset;
2820
2821     FX_FILESIZE                         m_dwCurrentOffset;
2822
2823     PDF_DATAAVAIL_STATUS                m_docStatus;
2824
2825     FX_FILESIZE                         m_dwFileLen;
2826
2827     CPDF_Document*                      m_pDocument;
2828
2829     CPDF_SortObjNumArray                m_objnum_array;
2830
2831     CFX_PtrArray                        m_objs_array;
2832
2833     FX_FILESIZE                         m_Pos;
2834
2835     FX_FILESIZE                         m_bufferOffset;
2836
2837     FX_DWORD                            m_bufferSize;
2838
2839     CFX_ByteString                      m_WordBuf;
2840
2841     uint8_t                             m_WordBuffer[257];
2842
2843     FX_DWORD                            m_WordSize;
2844
2845     uint8_t                             m_bufferData[512];
2846
2847     CFX_FileSizeArray                   m_CrossOffset;
2848
2849     CFX_DWordArray                      m_XRefStreamList;
2850
2851     CFX_DWordArray                      m_PageObjList;
2852
2853     FX_DWORD                            m_PagesObjNum;
2854
2855     FX_BOOL                             m_bLinearized;
2856
2857     FX_DWORD                            m_dwFirstPageNo;
2858
2859     FX_BOOL                             m_bLinearedDataOK;
2860
2861     FX_BOOL                             m_bMainXRefLoadTried;
2862
2863     FX_BOOL                             m_bMainXRefLoadedOK;
2864
2865     FX_BOOL                             m_bPagesTreeLoad;
2866
2867     FX_BOOL                             m_bPagesLoad;
2868
2869     CPDF_Parser *                       m_pCurrentParser;
2870
2871     FX_FILESIZE                         m_dwCurrentXRefSteam;
2872
2873     FX_BOOL                             m_bAnnotsLoad;
2874
2875     FX_BOOL                             m_bHaveAcroForm;
2876
2877     FX_DWORD                            m_dwAcroFormObjNum;
2878
2879     FX_BOOL                             m_bAcroFormLoad;
2880
2881     CPDF_Object *                       m_pAcroForm;
2882
2883     CFX_PtrArray                        m_arrayAcroforms;
2884
2885     CPDF_Dictionary *                   m_pPageDict;
2886
2887     CPDF_Object *                       m_pPageResource;
2888
2889     FX_BOOL                             m_bNeedDownLoadResource;
2890
2891     FX_BOOL                             m_bPageLoadedOK;
2892
2893     FX_BOOL                             m_bLinearizedFormParamLoad;
2894
2895     CFX_PtrArray                        m_PagesArray;
2896
2897     FX_DWORD                            m_dwEncryptObjNum;
2898
2899     FX_FILESIZE                         m_dwPrevXRefOffset;
2900
2901     FX_BOOL                             m_bTotalLoadPageTree;
2902
2903     FX_BOOL                             m_bCurPageDictLoadOK;
2904
2905     CPDF_PageNode                       m_pageNodes;
2906
2907     CFX_CMapDWordToDWord *              m_pageMapCheckState;
2908
2909     CFX_CMapDWordToDWord *              m_pagesLoadState;
2910 };
2911
2912 IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead) :
2913     m_pFileAvail(pFileAvail),
2914     m_pFileRead(pFileRead) {
2915 }
2916
2917 // static
2918 IPDF_DataAvail* IPDF_DataAvail::Create(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead)
2919 {
2920   return new CPDF_DataAvail(pFileAvail, pFileRead);
2921 }
2922
2923 // static
2924 int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0;
2925
2926 CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead)
2927     : IPDF_DataAvail(pFileAvail, pFileRead)
2928 {
2929     m_Pos = 0;
2930     m_dwFileLen = 0;
2931     if (m_pFileRead) {
2932         m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
2933     }
2934     m_dwCurrentOffset = 0;
2935     m_WordSize = 0;
2936     m_dwXRefOffset = 0;
2937     m_bufferOffset = 0;
2938     m_dwFirstPageNo = 0;
2939     m_bufferSize = 0;
2940     m_PagesObjNum = 0;
2941     m_dwCurrentXRefSteam = 0;
2942     m_dwAcroFormObjNum = 0;
2943     m_dwInfoObjNum = 0;
2944     m_pDocument = 0;
2945     m_dwEncryptObjNum = 0;
2946     m_dwPrevXRefOffset = 0;
2947     m_dwLastXRefOffset = 0;
2948     m_bDocAvail = FALSE;
2949     m_bMainXRefLoadTried = FALSE;
2950     m_bDocAvail = FALSE;
2951     m_bLinearized = FALSE;
2952     m_bPagesLoad = FALSE;
2953     m_bPagesTreeLoad = FALSE;
2954     m_bMainXRefLoadedOK = FALSE;
2955     m_bAnnotsLoad = FALSE;
2956     m_bHaveAcroForm = FALSE;
2957     m_bAcroFormLoad = FALSE;
2958     m_bPageLoadedOK = FALSE;
2959     m_bNeedDownLoadResource = FALSE;
2960     m_bLinearizedFormParamLoad = FALSE;
2961     m_pLinearized = NULL;
2962     m_pRoot = NULL;
2963     m_pTrailer = NULL;
2964     m_pCurrentParser = NULL;
2965     m_pAcroForm = NULL;
2966     m_pPageDict = NULL;
2967     m_pPageResource = NULL;
2968     m_pageMapCheckState = NULL;
2969     m_docStatus = PDF_DATAAVAIL_HEADER;
2970     m_parser.m_bOwnFileRead = FALSE;
2971     m_bTotalLoadPageTree = FALSE;
2972     m_bCurPageDictLoadOK = FALSE;
2973     m_bLinearedDataOK = FALSE;
2974     m_pagesLoadState = NULL;
2975 }
2976 CPDF_DataAvail::~CPDF_DataAvail()
2977 {
2978     if (m_pLinearized)  {
2979         m_pLinearized->Release();
2980     }
2981     if (m_pRoot) {
2982         m_pRoot->Release();
2983     }
2984     if (m_pTrailer) {
2985         m_pTrailer->Release();
2986     }
2987     if (m_pageMapCheckState) {
2988         delete m_pageMapCheckState;
2989     }
2990     if (m_pagesLoadState) {
2991         delete m_pagesLoadState;
2992     }
2993     int32_t i = 0;
2994     int32_t iSize = m_arrayAcroforms.GetSize();
2995     for (i = 0; i < iSize; ++i) {
2996         ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release();
2997     }
2998 }
2999 void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc)
3000 {
3001     m_pDocument = pDoc;
3002 }
3003 FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset)
3004 {
3005     CPDF_Parser *pParser = (CPDF_Parser *)(m_pDocument->GetParser());
3006     if (pParser == NULL) {
3007         return 0;
3008     }
3009     if (objnum >= (FX_DWORD)pParser->m_CrossRef.GetSize()) {
3010         return 0;
3011     }
3012     if (pParser->m_V5Type[objnum] == 2) {
3013         objnum = (FX_DWORD)pParser->m_CrossRef[objnum];
3014     }
3015     if (pParser->m_V5Type[objnum] == 1 || pParser->m_V5Type[objnum] == 255) {
3016         offset = pParser->m_CrossRef[objnum];
3017         if (offset == 0) {
3018             return 0;
3019         }
3020         void* pResult = FXSYS_bsearch(&offset, pParser->m_SortedOffset.GetData(), pParser->m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
3021         if (pResult == NULL) {
3022             return 0;
3023         }
3024         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)pParser->m_SortedOffset.GetData() == pParser->m_SortedOffset.GetSize() - 1) {
3025             return 0;
3026         }
3027         return (FX_DWORD)(((FX_FILESIZE*)pResult)[1] - offset);
3028     }
3029     return 0;
3030 }
3031 FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array, FX_BOOL bParsePage, IFX_DownloadHints* pHints, CFX_PtrArray &ret_array)
3032 {
3033     if (!obj_array.GetSize()) {
3034         return TRUE;
3035     }
3036     FX_DWORD count = 0;
3037     CFX_PtrArray new_obj_array;
3038     int32_t i = 0;
3039     for (i = 0; i < obj_array.GetSize(); i++) {
3040         CPDF_Object *pObj = (CPDF_Object *)obj_array[i];
3041         if (!pObj) {
3042             continue;
3043         }
3044         int32_t type = pObj->GetType();
3045         switch (type) {
3046             case PDFOBJ_ARRAY: {
3047                     CPDF_Array *pArray = pObj->GetArray();
3048                     for (FX_DWORD k = 0; k < pArray->GetCount(); k++) {
3049                         new_obj_array.Add(pArray->GetElement(k));
3050                     }
3051                 }
3052                 break;
3053             case PDFOBJ_STREAM:
3054                 pObj = pObj->GetDict();
3055             case PDFOBJ_DICTIONARY: {
3056                     CPDF_Dictionary *pDict = pObj->GetDict();
3057                     if (pDict && pDict->GetString("Type") == "Page" && !bParsePage) {
3058                         continue;
3059                     }
3060                     FX_POSITION pos = pDict->GetStartPos();
3061                     while (pos) {
3062                         CPDF_Object *value;
3063                         CFX_ByteString key;
3064                         value = pDict->GetNextElement(pos, key);
3065                         if (key != "Parent") {
3066                             new_obj_array.Add(value);
3067          &