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