Fix a null object bug
[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             FX_LPBYTE pData = buffer + i;
640             switch (status) {
641                 case 0:
642                     if (_PDF_CharType[byte] == 'W') {
643                         status = 1;
644                     }
645                     if (byte <= '9' && byte >= '0') {
646                         --i;
647                         status = 1;
648                     }
649                     if (byte == '%') {
650                         inside_index = 0;
651                         status = 9;
652                     }
653                     if (byte == '(') {
654                         status = 10;
655                         depth = 1;
656                     }
657                     if (byte == '<') {
658                         inside_index = 1;
659                         status = 11;
660                     }
661                     if (byte == '\\') {
662                         status = 13;
663                     }
664                     if (byte == 't') {
665                         status = 7;
666                         inside_index = 1;
667                     }
668                     break;
669                 case 1:
670                     if (_PDF_CharType[byte] == 'W') {
671                         break;
672                     } else if (byte <= '9' && byte >= '0') {
673                         start_pos = pos + i;
674                         status = 2;
675                         objnum = byte - '0';
676                     } else if (byte == 't') {
677                         status = 7;
678                         inside_index = 1;
679                     } else if (byte == 'x') {
680                         status = 8;
681                         inside_index = 1;
682                     } else {
683                         --i;
684                         status = 0;
685                     }
686                     break;
687                 case 2:
688                     if (byte <= '9' && byte >= '0') {
689                         objnum = objnum * 10 + byte - '0';
690                         break;
691                     } else if (_PDF_CharType[byte] == 'W') {
692                         status = 3;
693                     } else {
694                         --i;
695                         status = 14;
696                         inside_index = 0;
697                     }
698                     break;
699                 case 3:
700                     if (byte <= '9' && byte >= '0') {
701                         start_pos1 = pos + i;
702                         status = 4;
703                         gennum = byte - '0';
704                     } else if (_PDF_CharType[byte] == 'W') {
705                         break;
706                     } else if (byte == 't') {
707                         status = 7;
708                         inside_index = 1;
709                     } else {
710                         --i;
711                         status = 0;
712                     }
713                     break;
714                 case 4:
715                     if (byte <= '9' && byte >= '0') {
716                         gennum = gennum * 10 + byte - '0';
717                         break;
718                     } else if (_PDF_CharType[byte] == 'W') {
719                         status = 5;
720                     } else {
721                         --i;
722                         status = 0;
723                     }
724                     break;
725                 case 5:
726                     if (byte == 'o') {
727                         status = 6;
728                         inside_index = 1;
729                     } else if (_PDF_CharType[byte] == 'W') {
730                         break;
731                     } else if (byte <= '9' && byte >= '0') {
732                         objnum = gennum;
733                         gennum = byte - '0';
734                         start_pos = start_pos1;
735                         start_pos1 = pos + i;
736                         status = 4;
737                     } else if (byte == 't') {
738                         status = 7;
739                         inside_index = 1;
740                     } else {
741                         --i;
742                         status = 0;
743                     }
744                     break;
745                 case 6:
746                     switch (inside_index) {
747                         case 1:
748                             if (byte != 'b') {
749                                 --i;
750                                 status = 0;
751                             } else {
752                                 inside_index ++;
753                             }
754                             break;
755                         case 2:
756                             if (byte != 'j') {
757                                 --i;
758                                 status = 0;
759                             } else {
760                                 inside_index ++;
761                             }
762                             break;
763                         case 3:
764                             if (_PDF_CharType[byte] == 'W' || _PDF_CharType[byte] == 'D') {
765                                 if (objnum > 0x1000000) {
766                                     status = 0;
767                                     break;
768                                 }
769                                 FX_FILESIZE obj_pos = start_pos - m_Syntax.m_HeaderOffset;
770                                 last_obj = start_pos;
771                                 FX_LPVOID pResult = FXSYS_bsearch(&obj_pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
772                                 if (pResult == NULL) {
773                                     m_SortedOffset.Add(obj_pos);
774                                 }
775                                 FX_FILESIZE obj_end = 0;
776                                 CPDF_Object *pObject = ParseIndirectObjectAtByStrict(m_pDocument, obj_pos, objnum, NULL, &obj_end);
777                                 if (pObject) {
778                                     int iType = pObject->GetType();
779                                     if (iType == PDFOBJ_STREAM) {
780                                         CPDF_Stream* pStream = (CPDF_Stream*)pObject;
781                                         CPDF_Dictionary* pDict = pStream->GetDict();
782                                         if (pDict) {
783                                             if (pDict->KeyExist(FX_BSTRC("Type"))) {
784                                                 CFX_ByteString bsValue = pDict->GetString(FX_BSTRC("Type"));
785                                                 if (bsValue == FX_BSTRC("XRef") && pDict->KeyExist(FX_BSTRC("Size"))) {
786                                                     CPDF_Object* pRoot = pDict->GetElement(FX_BSTRC("Root"));
787                                                     if (pRoot && pRoot->GetDict() && pRoot->GetDict()->GetElement(FX_BSTRC("Pages"))) {
788                                                         if (m_pTrailer) {
789                                                             m_pTrailer->Release();
790                                                         }
791                                                         m_pTrailer = (CPDF_Dictionary*)pDict->Clone();
792                                                     }
793                                                 }
794                                             }
795                                         }
796                                     }
797                                 }
798                                 FX_FILESIZE offset = 0;
799                                 m_Syntax.RestorePos(obj_pos);
800                                 offset = m_Syntax.FindTag(FX_BSTRC("obj"), 0);
801                                 if (offset == -1) {
802                                     offset = 0;
803                                 } else {
804                                     offset += 3;
805                                 }
806                                 FX_FILESIZE nLen = obj_end - obj_pos - offset;
807                                 if ((FX_DWORD)nLen > size - i) {
808                                     pos = obj_end + m_Syntax.m_HeaderOffset;
809                                     bOverFlow = TRUE;
810                                 } else {
811                                     i += (FX_DWORD)nLen;
812                                 }
813                                 if (m_CrossRef.GetSize() > (FX_INT32)objnum && m_CrossRef[objnum]) {
814                                     if (pObject) {
815                                         FX_DWORD oldgen = m_ObjVersion.GetAt(objnum);
816                                         m_CrossRef[objnum] = obj_pos;
817                                         m_ObjVersion.SetAt(objnum, (FX_SHORT)gennum);
818                                         if (oldgen != gennum) {
819                                             m_bVersionUpdated = TRUE;
820                                         }
821                                     }
822                                 } else {
823                                     m_CrossRef.SetAtGrow(objnum, obj_pos);
824                                     m_V5Type.SetAtGrow(objnum, 1);
825                                     m_ObjVersion.SetAtGrow(objnum, (FX_SHORT)gennum);
826                                 }
827                                 if (pObject) {
828                                     pObject->Release();
829                                 }
830                             }
831                             --i;
832                             status = 0;
833                             break;
834                     }
835                     break;
836                 case 7:
837                     if (inside_index == 7) {
838                         if (_PDF_CharType[byte] == 'W' || _PDF_CharType[byte] == 'D') {
839                             last_trailer = pos + i - 7;
840                             m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset);
841                             CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
842                             if (pObj) {
843                                 if (pObj->GetType() != PDFOBJ_DICTIONARY && pObj->GetType() != PDFOBJ_STREAM) {
844                                     pObj->Release();
845                                 } else {
846                                     CPDF_Dictionary* pTrailer = NULL;
847                                     if (pObj->GetType() == PDFOBJ_STREAM) {
848                                         pTrailer = ((CPDF_Stream*)pObj)->GetDict();
849                                     } else {
850                                         pTrailer = (CPDF_Dictionary*)pObj;
851                                     }
852                                     if (pTrailer) {
853                                         if (m_pTrailer) {
854                                             CPDF_Object* pRoot = pTrailer->GetElement(FX_BSTRC("Root"));
855                                             if (pRoot == NULL || (pRoot->GetType() == PDFOBJ_REFERENCE &&
856                                                                   (FX_DWORD)m_CrossRef.GetSize() > ((CPDF_Reference*)pRoot)->GetRefObjNum() &&
857                                                                   m_CrossRef.GetAt(((CPDF_Reference*)pRoot)->GetRefObjNum()) != 0)) {
858                                                 FX_POSITION pos = pTrailer->GetStartPos();
859                                                 while (pos) {
860                                                     CFX_ByteString key;
861                                                     CPDF_Object* pObj = pTrailer->GetNextElement(pos, key);
862                                                     m_pTrailer->SetAt(key, pObj->Clone(), m_pDocument);
863                                                 }
864                                                 pObj->Release();
865                                             } else {
866                                                 pObj->Release();
867                                             }
868                                         } else {
869                                             if (pObj->GetType() == PDFOBJ_STREAM) {
870                                                 m_pTrailer = (CPDF_Dictionary*)pTrailer->Clone();
871                                                 pObj->Release();
872                                             } else {
873                                                 m_pTrailer = pTrailer;
874                                             }
875                                             FX_FILESIZE dwSavePos = m_Syntax.SavePos();
876                                             CFX_ByteString strWord = m_Syntax.GetKeyword();
877                                             if (!strWord.Compare(FX_BSTRC("startxref"))) {
878                                                 FX_BOOL bNumber = FALSE;
879                                                 CFX_ByteString bsOffset = m_Syntax.GetNextWord(bNumber);
880                                                 if (bNumber) {
881                                                     m_LastXRefOffset = FXSYS_atoi(bsOffset);
882                                                 }
883                                             }
884                                             m_Syntax.RestorePos(dwSavePos);
885                                         }
886                                     } else {
887                                         pObj->Release();
888                                     }
889                                     bInUpdate = TRUE;
890                                 }
891                             }
892                         }
893                         --i;
894                         status = 0;
895                     } else if (byte == "trailer"[inside_index]) {
896                         inside_index ++;
897                     } else {
898                         --i;
899                         status = 0;
900                     }
901                     break;
902                 case 8:
903                     if (inside_index == 4) {
904                         last_xref = pos + i - 4;
905                         status = 1;
906                     } else if (byte == "xref"[inside_index]) {
907                         inside_index ++;
908                     } else {
909                         --i;
910                         status = 0;
911                     }
912                     break;
913                 case 9:
914                     if (byte == '\r' || byte == '\n') {
915                         status = 0;
916                     }
917                     break;
918                 case 10:
919                     if (byte == ')') {
920                         if (depth > 0) {
921                             depth--;
922                         }
923                     } else if (byte == '(') {
924                         depth++;
925                     }
926                     if (!depth) {
927                         status = 0;
928                     }
929                     break;
930                 case 11:
931                     if (byte == '<' && inside_index == 1) {
932                         status = 12;
933                     } else if (byte == '>') {
934                         status = 0;
935                     }
936                     inside_index = 0;
937                     break;
938                 case 12:
939                     --i;
940                     status = 0;
941                     break;
942                 case 13:
943                     if (_PDF_CharType[byte] == 'D' || _PDF_CharType[byte] == 'W') {
944                         --i;
945                         status = 0;
946                     }
947                     break;
948                 case 14:
949                     if (_PDF_CharType[byte] == 'W') {
950                         status = 0;
951                     } else if (byte == '%' || byte == '(' || byte == '<' || byte == '\\') {
952                         status = 0;
953                         --i;
954                     } else if (inside_index == 6) {
955                         status = 0;
956                         --i;
957                     } else if (byte == "endobj"[inside_index]) {
958                         inside_index++;
959                     }
960                     break;
961             }
962             if (bOverFlow) {
963                 size = 0;
964                 break;
965             }
966         }
967         pos += size;
968     }
969     if (last_xref != -1 && last_xref > last_obj) {
970         last_trailer = last_xref;
971     } else if (last_trailer == -1 || last_xref < last_obj) {
972         last_trailer = m_Syntax.m_FileLen;
973     }
974     FX_FILESIZE offset = last_trailer - m_Syntax.m_HeaderOffset;
975     FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
976     if (pResult == NULL) {
977         m_SortedOffset.Add(offset);
978     }
979     FX_Free(buffer);
980     return TRUE;
981 }
982 static FX_DWORD _GetVarInt(FX_LPCBYTE p, FX_INT32 n)
983 {
984     FX_DWORD result = 0;
985     for (FX_INT32 i = 0; i < n; i ++) {
986         result = result * 256 + p[i];
987     }
988     return result;
989 }
990 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL bMainXRef)
991 {
992     CPDF_Stream* pStream = (CPDF_Stream*)ParseIndirectObjectAt(m_pDocument, pos, 0, NULL);
993     if (!pStream) {
994         return FALSE;
995     }
996     if (m_pDocument) {
997         m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
998     }
999     if (pStream->GetType() != PDFOBJ_STREAM) {
1000         return FALSE;
1001     }
1002     prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev"));
1003     FX_INT32 size = pStream->GetDict()->GetInteger(FX_BSTRC("Size"));
1004     if (size < 0) {
1005         pStream->Release();
1006         return FALSE;
1007     }
1008     if (bMainXRef) {
1009         m_pTrailer = (CPDF_Dictionary*)pStream->GetDict()->Clone();
1010         m_CrossRef.SetSize(size);
1011         if (m_V5Type.SetSize(size)) {
1012             FXSYS_memset32(m_V5Type.GetData(), 0, size);
1013         }
1014     } else {
1015         m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
1016     }
1017     CFX_DWordArray IndexArray, WidthArray;
1018     FX_DWORD nSegs = 0;
1019     CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
1020     if (pArray == NULL) {
1021         IndexArray.Add(0);
1022         IndexArray.Add(size);
1023         nSegs = 1;
1024     } else {
1025         for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
1026             IndexArray.Add(pArray->GetInteger(i));
1027         }
1028         nSegs = pArray->GetCount() / 2;
1029     }
1030     pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
1031     if (pArray == NULL) {
1032         pStream->Release();
1033         return FALSE;
1034     }
1035     FX_DWORD totalwidth = 0;
1036     FX_DWORD i;
1037     for (i = 0; i < pArray->GetCount(); i ++) {
1038         WidthArray.Add(pArray->GetInteger(i));
1039         if (totalwidth + WidthArray[i] < totalwidth) {
1040             pStream->Release();
1041             return FALSE;
1042         }
1043         totalwidth += WidthArray[i];
1044     }
1045     if (totalwidth == 0 || WidthArray.GetSize() < 3) {
1046         pStream->Release();
1047         return FALSE;
1048     }
1049     CPDF_StreamAcc acc;
1050     acc.LoadAllData(pStream);
1051     FX_LPCBYTE pData = acc.GetData();
1052     FX_DWORD dwTotalSize = acc.GetSize();
1053     FX_DWORD segindex = 0;
1054     for (i = 0; i < nSegs; i ++) {
1055         FX_INT32 startnum = IndexArray[i * 2];
1056         if (startnum < 0) {
1057             continue;
1058         }
1059         m_dwXrefStartObjNum = startnum;
1060         FX_DWORD count = IndexArray[i * 2 + 1];
1061         if (segindex + count < segindex || segindex + count == 0 ||
1062                 (FX_DWORD)totalwidth >= UINT_MAX / (segindex + count) || (segindex + count) * (FX_DWORD)totalwidth > dwTotalSize) {
1063             continue;
1064         }
1065         FX_LPCBYTE segstart = pData + segindex * (FX_DWORD)totalwidth;
1066         if ((FX_DWORD)startnum + count < (FX_DWORD)startnum ||
1067                 (FX_DWORD)startnum + count > (FX_DWORD)m_V5Type.GetSize()) {
1068             continue;
1069         }
1070         for (FX_DWORD j = 0; j < count; j ++) {
1071             FX_INT32 type = 1;
1072             FX_LPCBYTE entrystart = segstart + j * totalwidth;
1073             if (WidthArray[0]) {
1074                 type = _GetVarInt(entrystart, WidthArray[0]);
1075             }
1076             if (m_V5Type[startnum + j] == 255) {
1077                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1078                 m_CrossRef[startnum + j] = offset;
1079                 FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1080                 if (pResult == NULL) {
1081                     m_SortedOffset.Add(offset);
1082                 }
1083                 continue;
1084             }
1085             if (m_V5Type[startnum + j]) {
1086                 continue;
1087             }
1088             m_V5Type[startnum + j] = type;
1089             if (type == 0) {
1090                 m_CrossRef[startnum + j] = 0;
1091             } else {
1092                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1093                 m_CrossRef[startnum + j] = offset;
1094                 if (type == 1) {
1095                     FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1096                     if (pResult == NULL) {
1097                         m_SortedOffset.Add(offset);
1098                     }
1099                 } else {
1100                     if (offset < 0 || offset >= m_V5Type.GetSize()) {
1101                         pStream->Release();
1102                         return FALSE;
1103                     }
1104                     m_V5Type[offset] = 255;
1105                 }
1106             }
1107         }
1108         segindex += count;
1109     }
1110     pStream->Release();
1111     return TRUE;
1112 }
1113 CPDF_Array* CPDF_Parser::GetIDArray()
1114 {
1115     CPDF_Object* pID = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("ID")) : NULL;
1116     if (pID == NULL) {
1117         return NULL;
1118     }
1119     if (pID->GetType() == PDFOBJ_REFERENCE) {
1120         pID = ParseIndirectObject(NULL, ((CPDF_Reference*)pID)->GetRefObjNum());
1121         m_pTrailer->SetAt(FX_BSTRC("ID"), pID);
1122     }
1123     if (pID == NULL || pID->GetType() != PDFOBJ_ARRAY) {
1124         return NULL;
1125     }
1126     return (CPDF_Array*)pID;
1127 }
1128 FX_DWORD CPDF_Parser::GetRootObjNum()
1129 {
1130     CPDF_Reference* pRef = m_pTrailer ? (CPDF_Reference*)m_pTrailer->GetElement(FX_BSTRC("Root")) : NULL;
1131     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1132         return 0;
1133     }
1134     return pRef->GetRefObjNum();
1135 }
1136 FX_DWORD CPDF_Parser::GetInfoObjNum()
1137 {
1138     CPDF_Reference* pRef = m_pTrailer ? (CPDF_Reference*)m_pTrailer->GetElement(FX_BSTRC("Info")) : NULL;
1139     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1140         return 0;
1141     }
1142     return pRef->GetRefObjNum();
1143 }
1144 FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm)
1145 {
1146     bForm = FALSE;
1147     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1148         return TRUE;
1149     }
1150     if (m_V5Type[objnum] == 0) {
1151         return TRUE;
1152     }
1153     if (m_V5Type[objnum] == 2) {
1154         return TRUE;
1155     }
1156     FX_FILESIZE pos = m_CrossRef[objnum];
1157     FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1158     if (pResult == NULL) {
1159         return TRUE;
1160     }
1161     if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
1162         return FALSE;
1163     }
1164     FX_FILESIZE size = ((FX_FILESIZE*)pResult)[1] - pos;
1165     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1166     m_Syntax.RestorePos(pos);
1167     bForm = m_Syntax.SearchMultiWord(FX_BSTRC("/Form\0stream"), TRUE, size) == 0;
1168     m_Syntax.RestorePos(SavedPos);
1169     return TRUE;
1170 }
1171 CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, PARSE_CONTEXT* pContext)
1172 {
1173     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1174         return NULL;
1175     }
1176     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1177         FX_FILESIZE pos = m_CrossRef[objnum];
1178         if (pos <= 0) {
1179             return NULL;
1180         }
1181         return ParseIndirectObjectAt(pObjList, pos, objnum, pContext);
1182     }
1183     if (m_V5Type[objnum] == 2) {
1184         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1185         if (pObjStream == NULL) {
1186             return NULL;
1187         }
1188         FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1189         FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1190         CPDF_SyntaxParser syntax;
1191         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE));
1192         syntax.InitParser((IFX_FileStream*)file, 0);
1193         CPDF_Object* pRet = NULL;
1194         while (n) {
1195             FX_DWORD thisnum = syntax.GetDirectNum();
1196             FX_DWORD thisoff = syntax.GetDirectNum();
1197             if (thisnum == objnum) {
1198                 syntax.RestorePos(offset + thisoff);
1199                 pRet = syntax.GetObject(pObjList, 0, 0, 0, pContext);
1200                 break;
1201             }
1202             n --;
1203         }
1204         return pRet;
1205     }
1206     return NULL;
1207 }
1208 CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum)
1209 {
1210     CPDF_StreamAcc* pStreamAcc = NULL;
1211     if (m_ObjectStreamMap.Lookup((void*)(FX_UINTPTR)objnum, (void*&)pStreamAcc)) {
1212         return pStreamAcc;
1213     }
1214     const CPDF_Stream* pStream = m_pDocument ? (CPDF_Stream*)m_pDocument->GetIndirectObject(objnum) : NULL;
1215     if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
1216         return NULL;
1217     }
1218     pStreamAcc = FX_NEW CPDF_StreamAcc;
1219     pStreamAcc->LoadAllData(pStream);
1220     m_ObjectStreamMap.SetAt((void*)(FX_UINTPTR)objnum, pStreamAcc);
1221     return pStreamAcc;
1222 }
1223 FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum)
1224 {
1225     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1226         return 0;
1227     }
1228     if (m_V5Type[objnum] == 2) {
1229         objnum = (FX_DWORD)m_CrossRef[objnum];
1230     }
1231     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1232         FX_FILESIZE offset = m_CrossRef[objnum];
1233         if (offset == 0) {
1234             return 0;
1235         }
1236         FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1237         if (pResult == NULL) {
1238             return 0;
1239         }
1240         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
1241             return 0;
1242         }
1243         return ((FX_FILESIZE*)pResult)[1] - offset;
1244     }
1245     return 0;
1246 }
1247 void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, FX_LPBYTE& pBuffer, FX_DWORD& size)
1248 {
1249     pBuffer = NULL;
1250     size = 0;
1251     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1252         return;
1253     }
1254     if (m_V5Type[objnum] == 2) {
1255         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1256         if (pObjStream == NULL) {
1257             return;
1258         }
1259         FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1260         FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1261         CPDF_SyntaxParser syntax;
1262         FX_LPCBYTE pData = pObjStream->GetData();
1263         FX_DWORD totalsize = pObjStream->GetSize();
1264         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pData, (size_t)totalsize, FALSE));
1265         syntax.InitParser((IFX_FileStream*)file, 0);
1266         while (n) {
1267             FX_DWORD thisnum = syntax.GetDirectNum();
1268             FX_DWORD thisoff = syntax.GetDirectNum();
1269             if (thisnum == objnum) {
1270                 if (n == 1) {
1271                     size = totalsize - (thisoff + offset);
1272                 } else {
1273                     FX_DWORD nextnum = syntax.GetDirectNum();
1274                     FX_DWORD nextoff = syntax.GetDirectNum();
1275                     size = nextoff - thisoff;
1276                 }
1277                 pBuffer = FX_Alloc(FX_BYTE, size);
1278                 FXSYS_memcpy32(pBuffer, pData + thisoff + offset, size);
1279                 return;
1280             }
1281             n --;
1282         }
1283         return;
1284     }
1285     if (m_V5Type[objnum] == 1) {
1286         FX_FILESIZE pos = m_CrossRef[objnum];
1287         if (pos == 0) {
1288             return;
1289         }
1290         FX_FILESIZE SavedPos = m_Syntax.SavePos();
1291         m_Syntax.RestorePos(pos);
1292         FX_BOOL bIsNumber;
1293         CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1294         if (!bIsNumber) {
1295             m_Syntax.RestorePos(SavedPos);
1296             return;
1297         }
1298         FX_DWORD real_objnum = FXSYS_atoi(word);
1299         if (real_objnum && real_objnum != objnum) {
1300             m_Syntax.RestorePos(SavedPos);
1301             return;
1302         }
1303         word = m_Syntax.GetNextWord(bIsNumber);
1304         if (!bIsNumber) {
1305             m_Syntax.RestorePos(SavedPos);
1306             return;
1307         }
1308         if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1309             m_Syntax.RestorePos(SavedPos);
1310             return;
1311         }
1312         FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1313         if (pResult == NULL) {
1314             m_Syntax.RestorePos(SavedPos);
1315             return;
1316         }
1317         FX_FILESIZE nextoff = ((FX_FILESIZE*)pResult)[1];
1318         FX_BOOL bNextOffValid = FALSE;
1319         if (nextoff != pos) {
1320             m_Syntax.RestorePos(nextoff);
1321             word = m_Syntax.GetNextWord(bIsNumber);
1322             if (word == FX_BSTRC("xref")) {
1323                 bNextOffValid = TRUE;
1324             } else if (bIsNumber) {
1325                 word = m_Syntax.GetNextWord(bIsNumber);
1326                 if (bIsNumber && m_Syntax.GetKeyword() == FX_BSTRC("obj")) {
1327                     bNextOffValid = TRUE;
1328                 }
1329             }
1330         }
1331         if (!bNextOffValid) {
1332             m_Syntax.RestorePos(pos);
1333             while (1) {
1334                 if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) {
1335                     break;
1336                 }
1337                 if (m_Syntax.SavePos() == m_Syntax.m_FileLen) {
1338                     break;
1339                 }
1340             }
1341             nextoff = m_Syntax.SavePos();
1342         }
1343         size = (FX_DWORD)(nextoff - pos);
1344         pBuffer = FX_Alloc(FX_BYTE, size);
1345         m_Syntax.RestorePos(pos);
1346         m_Syntax.ReadBlock(pBuffer, size);
1347         m_Syntax.RestorePos(SavedPos);
1348     }
1349 }
1350 CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
1351         PARSE_CONTEXT* pContext)
1352 {
1353     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1354     m_Syntax.RestorePos(pos);
1355     FX_BOOL bIsNumber;
1356     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1357     if (!bIsNumber) {
1358         m_Syntax.RestorePos(SavedPos);
1359         return NULL;
1360     }
1361     FX_FILESIZE objOffset = m_Syntax.SavePos();
1362     objOffset -= word.GetLength();
1363     FX_DWORD real_objnum = FXSYS_atoi(word);
1364     if (objnum && real_objnum != objnum) {
1365         m_Syntax.RestorePos(SavedPos);
1366         return NULL;
1367     }
1368     word = m_Syntax.GetNextWord(bIsNumber);
1369     if (!bIsNumber) {
1370         m_Syntax.RestorePos(SavedPos);
1371         return NULL;
1372     }
1373     FX_DWORD gennum = FXSYS_atoi(word);
1374     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1375         m_Syntax.RestorePos(SavedPos);
1376         return NULL;
1377     }
1378     CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, gennum, 0, pContext);
1379     FX_FILESIZE endOffset = m_Syntax.SavePos();
1380     CFX_ByteString bsWord = m_Syntax.GetKeyword();
1381     if (bsWord == FX_BSTRC("endobj")) {
1382         endOffset = m_Syntax.SavePos();
1383     }
1384     FX_DWORD objSize = endOffset - objOffset;
1385     m_Syntax.RestorePos(SavedPos);
1386     if (pObj && !objnum) {
1387         pObj->m_ObjNum = real_objnum;
1388         pObj->m_GenNum = gennum;
1389     }
1390     return pObj;
1391 }
1392 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
1393         struct PARSE_CONTEXT* pContext, FX_FILESIZE *pResultPos)
1394 {
1395     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1396     m_Syntax.RestorePos(pos);
1397     FX_BOOL bIsNumber;
1398     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1399     if (!bIsNumber) {
1400         m_Syntax.RestorePos(SavedPos);
1401         return NULL;
1402     }
1403     FX_DWORD real_objnum = FXSYS_atoi(word);
1404     if (objnum && real_objnum != objnum) {
1405         m_Syntax.RestorePos(SavedPos);
1406         return NULL;
1407     }
1408     word = m_Syntax.GetNextWord(bIsNumber);
1409     if (!bIsNumber) {
1410         m_Syntax.RestorePos(SavedPos);
1411         return NULL;
1412     }
1413     FX_DWORD gennum = FXSYS_atoi(word);
1414     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1415         m_Syntax.RestorePos(SavedPos);
1416         return NULL;
1417     }
1418     CPDF_Object* pObj = m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, 0, pContext);
1419     if (pResultPos) {
1420         *pResultPos = m_Syntax.m_Pos;
1421     }
1422     m_Syntax.RestorePos(SavedPos);
1423     return pObj;
1424 }
1425 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4()
1426 {
1427     if (m_Syntax.GetKeyword() != FX_BSTRC("trailer")) {
1428         return NULL;
1429     }
1430     CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
1431     if (pObj == NULL || pObj->GetType() != PDFOBJ_DICTIONARY) {
1432         if (pObj) {
1433             pObj->Release();
1434         }
1435         return NULL;
1436     }
1437     return (CPDF_Dictionary*)pObj;
1438 }
1439 FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision)
1440 {
1441     if (m_pSecurityHandler == NULL) {
1442         return (FX_DWORD) - 1;
1443     }
1444     FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions();
1445     if (m_pEncryptDict && m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) {
1446         dwPermission &= 0xFFFFFFFC;
1447         dwPermission |= 0xFFFFF0C0;
1448         if(bCheckRevision && m_pEncryptDict->GetInteger(FX_BSTRC("R")) == 2) {
1449             dwPermission &= 0xFFFFF0FF;
1450         }
1451     }
1452     return dwPermission;
1453 }
1454 FX_BOOL CPDF_Parser::IsOwner()
1455 {
1456     return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
1457 }
1458 void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler, FX_BOOL bForced)
1459 {
1460     ASSERT(m_pSecurityHandler == NULL);
1461     if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
1462         delete m_pSecurityHandler;
1463         m_pSecurityHandler = NULL;
1464     }
1465     m_bForceUseSecurityHandler = bForced;
1466     m_pSecurityHandler = pSecurityHandler;
1467     if (m_bForceUseSecurityHandler) {
1468         return;
1469     }
1470     m_Syntax.m_pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
1471     m_Syntax.m_pCryptoHandler->Init(NULL, pSecurityHandler);
1472 }
1473 FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, FX_DWORD offset)
1474 {
1475     m_Syntax.InitParser(pFileAccess, offset);
1476     m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9);
1477     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1478     FX_BOOL bIsNumber;
1479     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1480     if (!bIsNumber) {
1481         return FALSE;
1482     }
1483     FX_DWORD objnum = FXSYS_atoi(word);
1484     word = m_Syntax.GetNextWord(bIsNumber);
1485     if (!bIsNumber) {
1486         return FALSE;
1487     }
1488     FX_DWORD gennum = FXSYS_atoi(word);
1489     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1490         m_Syntax.RestorePos(SavedPos);
1491         return FALSE;
1492     }
1493     m_pLinearized = m_Syntax.GetObject(NULL, objnum, gennum, 0);
1494     if (!m_pLinearized) {
1495         return FALSE;
1496     }
1497     if (m_pLinearized->GetDict() && m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
1498         m_Syntax.GetNextWord(bIsNumber);
1499         CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
1500         if (!pLen) {
1501             m_pLinearized->Release();
1502             return FALSE;
1503         }
1504         if (pLen->GetInteger() != (int)pFileAccess->GetSize()) {
1505             return FALSE;
1506         }
1507         CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
1508         if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
1509             m_dwFirstPageNo = pNo->GetInteger();
1510         }
1511         CPDF_Object *pTable = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T"));
1512         if (pTable && pTable->GetType() == PDFOBJ_NUMBER) {
1513             m_LastXRefOffset = pTable->GetInteger();
1514         }
1515         return TRUE;
1516     }
1517     m_pLinearized->Release();
1518     m_pLinearized = NULL;
1519     return FALSE;
1520 }
1521 FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead)
1522 {
1523     CloseParser(bReParse);
1524     m_bXRefStream = FALSE;
1525     m_LastXRefOffset = 0;
1526     m_bOwnFileRead = bOwnFileRead;
1527     FX_INT32 offset = GetHeaderOffset(pFileAccess);
1528     if (offset == -1) {
1529         return PDFPARSE_ERROR_FORMAT;
1530     }
1531     if (!IsLinearizedFile(pFileAccess, offset)) {
1532         m_Syntax.m_pFileAccess = NULL;
1533         return StartParse(pFileAccess, bReParse, bOwnFileRead);
1534     }
1535     if (!bReParse) {
1536         m_pDocument = FX_NEW CPDF_Document(this);
1537     }
1538     FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos();
1539     FX_BOOL bXRefRebuilt = FALSE;
1540     FX_BOOL bLoadV4 = FALSE;
1541     if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) {
1542         if (!RebuildCrossRef()) {
1543             return PDFPARSE_ERROR_FORMAT;
1544         }
1545         bXRefRebuilt = TRUE;
1546         m_LastXRefOffset = 0;
1547     }
1548     if (bLoadV4) {
1549         m_pTrailer = LoadTrailerV4();
1550         if (m_pTrailer == NULL) {
1551             return FALSE;
1552         }
1553         FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
1554         if (xrefsize == 0) {
1555             return FALSE;
1556         }
1557         m_CrossRef.SetSize(xrefsize);
1558         m_V5Type.SetSize(xrefsize);
1559     }
1560     FX_DWORD dwRet = SetEncryptHandler();
1561     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1562         return dwRet;
1563     }
1564     m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1565     if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
1566         if (bXRefRebuilt) {
1567             return PDFPARSE_ERROR_FORMAT;
1568         }
1569         ReleaseEncryptHandler();
1570         if (!RebuildCrossRef()) {
1571             return PDFPARSE_ERROR_FORMAT;
1572         }
1573         dwRet = SetEncryptHandler();
1574         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1575             return dwRet;
1576         }
1577         m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1578         if (m_pDocument->GetRoot() == NULL) {
1579             return PDFPARSE_ERROR_FORMAT;
1580         }
1581     }
1582     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1583     FX_DWORD RootObjNum = GetRootObjNum();
1584     if (RootObjNum == 0) {
1585         ReleaseEncryptHandler();
1586         RebuildCrossRef();
1587         RootObjNum = GetRootObjNum();
1588         if (RootObjNum == 0) {
1589             return PDFPARSE_ERROR_FORMAT;
1590         }
1591         dwRet = SetEncryptHandler();
1592         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1593             return dwRet;
1594         }
1595     }
1596     if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) {
1597         CPDF_Reference* pMetadata = (CPDF_Reference*)m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
1598         if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
1599             m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum();
1600         }
1601     }
1602     return PDFPARSE_ERROR_SUCCESS;
1603 }
1604 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos)
1605 {
1606     if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1607         return FALSE;
1608     }
1609     while (xrefpos)
1610         if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1611             return FALSE;
1612         }
1613     m_ObjectStreamMap.InitHashTable(101, FALSE);
1614     m_bXRefStream = TRUE;
1615     return TRUE;
1616 }
1617 FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable()
1618 {
1619     FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum;
1620     m_Syntax.m_MetadataObjnum = 0;
1621     if (m_pTrailer) {
1622         m_pTrailer->Release();
1623         m_pTrailer = NULL;
1624     }
1625     m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset);
1626     FX_FILESIZE dwSavedPos = m_Syntax.SavePos();
1627     FX_BYTE ch = 0;
1628     FX_DWORD dwCount = 0;
1629     m_Syntax.GetNextChar(ch);
1630     FX_INT32 type = _PDF_CharType[ch];
1631     while (type == 'W') {
1632         ++dwCount;
1633         if (m_Syntax.m_FileLen >= (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
1634             break;
1635         }
1636         m_Syntax.GetNextChar(ch);
1637         type = _PDF_CharType[ch];
1638     }
1639     m_LastXRefOffset += dwCount;
1640     FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
1641     while (pos) {
1642         FX_LPVOID objnum;
1643         CPDF_StreamAcc* pStream;
1644         m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
1645         delete pStream;
1646     }
1647     m_ObjectStreamMap.RemoveAll();
1648     if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) {
1649         m_LastXRefOffset = 0;
1650         m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1651         return PDFPARSE_ERROR_FORMAT;
1652     }
1653     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_DWORD), _CompareDWord);
1654     m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1655     return PDFPARSE_ERROR_SUCCESS;
1656 }
1657 CPDF_SyntaxParser::CPDF_SyntaxParser()
1658 {
1659     m_pFileAccess = NULL;
1660     m_pCryptoHandler = NULL;
1661     m_pFileBuf = NULL;
1662     m_BufSize = CPDF_ModuleMgr::Get()->m_FileBufSize;
1663     m_pFileBuf = NULL;
1664     m_MetadataObjnum = 0;
1665     m_dwWordPos = 0;
1666 #if defined(_FPDFAPI_MINI_)
1667     m_bFileStream = TRUE;
1668 #else
1669     m_bFileStream = FALSE;
1670 #endif
1671 }
1672 CPDF_SyntaxParser::~CPDF_SyntaxParser()
1673 {
1674     if (m_pFileBuf) {
1675         FX_Free(m_pFileBuf);
1676     }
1677 }
1678 FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, FX_BYTE& ch)
1679 {
1680     FX_FILESIZE save_pos = m_Pos;
1681     m_Pos = pos;
1682     FX_BOOL ret = GetNextChar(ch);
1683     m_Pos = save_pos;
1684     return ret;
1685 }
1686 FX_BOOL CPDF_SyntaxParser::GetNextChar(FX_BYTE& ch)
1687 {
1688     FX_FILESIZE pos = m_Pos + m_HeaderOffset;
1689     if (pos >= m_FileLen) {
1690         return FALSE;
1691     }
1692     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1693         FX_FILESIZE read_pos = pos;
1694         FX_DWORD read_size = m_BufSize;
1695         if ((FX_FILESIZE)read_size > m_FileLen) {
1696             read_size = (FX_DWORD)m_FileLen;
1697         }
1698         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1699             if (m_FileLen < (FX_FILESIZE)read_size) {
1700                 read_pos = 0;
1701                 read_size = (FX_DWORD)m_FileLen;
1702             } else {
1703                 read_pos = m_FileLen - read_size;
1704             }
1705         }
1706         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1707             return FALSE;
1708         }
1709         m_BufOffset = read_pos;
1710     }
1711     ch = m_pFileBuf[pos - m_BufOffset];
1712     m_Pos ++;
1713     return TRUE;
1714 }
1715 FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, FX_BYTE& ch)
1716 {
1717     pos += m_HeaderOffset;
1718     if (pos >= m_FileLen) {
1719         return FALSE;
1720     }
1721     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1722         FX_FILESIZE read_pos;
1723         if (pos < (FX_FILESIZE)m_BufSize) {
1724             read_pos = 0;
1725         } else {
1726             read_pos = pos - m_BufSize + 1;
1727         }
1728         FX_DWORD read_size = m_BufSize;
1729         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1730             if (m_FileLen < (FX_FILESIZE)read_size) {
1731                 read_pos = 0;
1732                 read_size = (FX_DWORD)m_FileLen;
1733             } else {
1734                 read_pos = m_FileLen - read_size;
1735             }
1736         }
1737         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1738             return FALSE;
1739         }
1740         m_BufOffset = read_pos;
1741     }
1742     ch = m_pFileBuf[pos - m_BufOffset];
1743     return TRUE;
1744 }
1745 FX_BOOL CPDF_SyntaxParser::ReadBlock(FX_LPBYTE pBuf, FX_DWORD size)
1746 {
1747     if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) {
1748         return FALSE;
1749     }
1750     m_Pos += size;
1751     return TRUE;
1752 }
1753 #define MAX_WORD_BUFFER 256
1754 void CPDF_SyntaxParser::GetNextWord()
1755 {
1756     m_WordSize = 0;
1757     m_bIsNumber = TRUE;
1758     FX_BYTE ch;
1759     if (!GetNextChar(ch)) {
1760         return;
1761     }
1762     FX_BYTE type = _PDF_CharType[ch];
1763     while (1) {
1764         while (type == 'W') {
1765             if (!GetNextChar(ch)) {
1766                 return;
1767             }
1768             type = _PDF_CharType[ch];
1769         }
1770         if (ch != '%') {
1771             break;
1772         }
1773         while (1) {
1774             if (!GetNextChar(ch)) {
1775                 return;
1776             }
1777             if (ch == '\r' || ch == '\n') {
1778                 break;
1779             }
1780         }
1781         type = _PDF_CharType[ch];
1782     }
1783     if (type == 'D') {
1784         m_bIsNumber = FALSE;
1785         m_WordBuffer[m_WordSize++] = ch;
1786         if (ch == '/') {
1787             while (1) {
1788                 if (!GetNextChar(ch)) {
1789                     return;
1790                 }
1791                 type = _PDF_CharType[ch];
1792                 if (type != 'R' && type != 'N') {
1793                     m_Pos --;
1794                     return;
1795                 }
1796                 if (m_WordSize < MAX_WORD_BUFFER) {
1797                     m_WordBuffer[m_WordSize++] = ch;
1798                 }
1799             }
1800         } else if (ch == '<') {
1801             if (!GetNextChar(ch)) {
1802                 return;
1803             }
1804             if (ch == '<') {
1805                 m_WordBuffer[m_WordSize++] = ch;
1806             } else {
1807                 m_Pos --;
1808             }
1809         } else if (ch == '>') {
1810             if (!GetNextChar(ch)) {
1811                 return;
1812             }
1813             if (ch == '>') {
1814                 m_WordBuffer[m_WordSize++] = ch;
1815             } else {
1816                 m_Pos --;
1817             }
1818         }
1819         return;
1820     }
1821     while (1) {
1822         if (m_WordSize < MAX_WORD_BUFFER) {
1823             m_WordBuffer[m_WordSize++] = ch;
1824         }
1825         if (type != 'N') {
1826             m_bIsNumber = FALSE;
1827         }
1828         if (!GetNextChar(ch)) {
1829             return;
1830         }
1831         type = _PDF_CharType[ch];
1832         if (type == 'D' || type == 'W') {
1833             m_Pos --;
1834             break;
1835         }
1836     }
1837 }
1838 CFX_ByteString CPDF_SyntaxParser::ReadString()
1839 {
1840     FX_BYTE ch;
1841     if (!GetNextChar(ch)) {
1842         return CFX_ByteString();
1843     }
1844     CFX_ByteTextBuf buf;
1845     FX_INT32 parlevel = 0;
1846     FX_INT32 status = 0, iEscCode = 0;
1847     while (1) {
1848         switch (status) {
1849             case 0:
1850                 if (ch == ')') {
1851                     if (parlevel == 0) {
1852                         return buf.GetByteString();
1853                     }
1854                     parlevel --;
1855                     buf.AppendChar(')');
1856                 } else if (ch == '(') {
1857                     parlevel ++;
1858                     buf.AppendChar('(');
1859                 } else if (ch == '\\') {
1860                     status = 1;
1861                 } else {
1862                     buf.AppendChar(ch);
1863                 }
1864                 break;
1865             case 1:
1866                 if (ch >= '0' && ch <= '7') {
1867                     iEscCode = ch - '0';
1868                     status = 2;
1869                     break;
1870                 }
1871                 if (ch == 'n') {
1872                     buf.AppendChar('\n');
1873                 } else if (ch == 'r') {
1874                     buf.AppendChar('\r');
1875                 } else if (ch == 't') {
1876                     buf.AppendChar('\t');
1877                 } else if (ch == 'b') {
1878                     buf.AppendChar('\b');
1879                 } else if (ch == 'f') {
1880                     buf.AppendChar('\f');
1881                 } else if (ch == '\r') {
1882                     status = 4;
1883                     break;
1884                 } else if (ch == '\n') {
1885                 } else {
1886                     buf.AppendChar(ch);
1887                 }
1888                 status = 0;
1889                 break;
1890             case 2:
1891                 if (ch >= '0' && ch <= '7') {
1892                     iEscCode = iEscCode * 8 + ch - '0';
1893                     status = 3;
1894                 } else {
1895                     buf.AppendChar(iEscCode);
1896                     status = 0;
1897                     continue;
1898                 }
1899                 break;
1900             case 3:
1901                 if (ch >= '0' && ch <= '7') {
1902                     iEscCode = iEscCode * 8 + ch - '0';
1903                     buf.AppendChar(iEscCode);
1904                     status = 0;
1905                 } else {
1906                     buf.AppendChar(iEscCode);
1907                     status = 0;
1908                     continue;
1909                 }
1910                 break;
1911             case 4:
1912                 status = 0;
1913                 if (ch != '\n') {
1914                     continue;
1915                 }
1916                 break;
1917         }
1918         if (!GetNextChar(ch)) {
1919             break;
1920         }
1921     }
1922     GetNextChar(ch);
1923     return buf.GetByteString();
1924 }
1925 CFX_ByteString CPDF_SyntaxParser::ReadHexString()
1926 {
1927     FX_BYTE ch;
1928     if (!GetNextChar(ch)) {
1929         return CFX_ByteString();
1930     }
1931     CFX_BinaryBuf buf;
1932     FX_BOOL bFirst = TRUE;
1933     FX_BYTE code = 0;
1934     while (1) {
1935         if (ch == '>') {
1936             break;
1937         }
1938         if (ch >= '0' && ch <= '9') {
1939             if (bFirst) {
1940                 code = (ch - '0') * 16;
1941             } else {
1942                 code += ch - '0';
1943                 buf.AppendByte((FX_BYTE)code);
1944             }
1945             bFirst = !bFirst;
1946         } else if (ch >= 'A' && ch <= 'F') {
1947             if (bFirst) {
1948                 code = (ch - 'A' + 10) * 16;
1949             } else {
1950                 code += ch - 'A' + 10;
1951                 buf.AppendByte((FX_BYTE)code);
1952             }
1953             bFirst = !bFirst;
1954         } else if (ch >= 'a' && ch <= 'f') {
1955             if (bFirst) {
1956                 code = (ch - 'a' + 10) * 16;
1957             } else {
1958                 code += ch - 'a' + 10;
1959                 buf.AppendByte((FX_BYTE)code);
1960             }
1961             bFirst = !bFirst;
1962         }
1963         if (!GetNextChar(ch)) {
1964             break;
1965         }
1966     }
1967     if (!bFirst) {
1968         buf.AppendByte((FX_BYTE)code);
1969     }
1970     return buf.GetByteString();
1971 }
1972 void CPDF_SyntaxParser::ToNextLine()
1973 {
1974     FX_BYTE ch;
1975     while (1) {
1976         if (!GetNextChar(ch)) {
1977             return;
1978         }
1979         if (ch == '\n') {
1980             return;
1981         }
1982         if (ch == '\r') {
1983             GetNextChar(ch);
1984             if (ch == '\n') {
1985                 return;
1986             } else {
1987                 m_Pos --;
1988                 return;
1989             }
1990         }
1991     }
1992 }
1993 void CPDF_SyntaxParser::ToNextWord()
1994 {
1995     FX_BYTE ch;
1996     if (!GetNextChar(ch)) {
1997         return;
1998     }
1999     FX_BYTE type = _PDF_CharType[ch];
2000     while (1) {
2001         while (type == 'W') {
2002             m_dwWordPos = m_Pos;
2003             if (!GetNextChar(ch)) {
2004                 return;
2005             }
2006             type = _PDF_CharType[ch];
2007         }
2008         if (ch != '%') {
2009             break;
2010         }
2011         while (1) {
2012             if (!GetNextChar(ch)) {
2013                 return;
2014             }
2015             if (ch == '\r' || ch == '\n') {
2016                 break;
2017             }
2018         }
2019         type = _PDF_CharType[ch];
2020     }
2021     m_Pos --;
2022 }
2023 CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber)
2024 {
2025     GetNextWord();
2026     bIsNumber = m_bIsNumber;
2027     return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
2028 }
2029 CFX_ByteString CPDF_SyntaxParser::GetKeyword()
2030 {
2031     GetNextWord();
2032     return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
2033 }
2034 CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, FX_INT32 level, PARSE_CONTEXT* pContext, FX_BOOL bDecrypt)
2035 {
2036     if (level > _PARSER_OBJECT_LEVLE_) {
2037         return NULL;
2038     }
2039     FX_FILESIZE SavedPos = m_Pos;
2040     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2041     FX_BOOL bIsNumber;
2042     CFX_ByteString word = GetNextWord(bIsNumber);
2043     CPDF_Object* pRet = NULL;
2044     if (word.GetLength() == 0) {
2045         if (bTypeOnly) {
2046             return (CPDF_Object*)PDFOBJ_INVALID;
2047         }
2048         return NULL;
2049     }
2050     FX_FILESIZE wordOffset = m_Pos - word.GetLength();
2051     if (bIsNumber) {
2052         FX_FILESIZE SavedPos = m_Pos;
2053         CFX_ByteString nextword = GetNextWord(bIsNumber);
2054         if (bIsNumber) {
2055             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2056             if (nextword2 == FX_BSTRC("R")) {
2057                 FX_DWORD objnum = FXSYS_atoi(word);
2058                 if (bTypeOnly) {
2059                     return (CPDF_Object*)PDFOBJ_REFERENCE;
2060                 }
2061                 pRet = CPDF_Reference::Create(pObjList, objnum);
2062                 return pRet;
2063             } else {
2064                 m_Pos = SavedPos;
2065                 if (bTypeOnly) {
2066                     return (CPDF_Object*)PDFOBJ_NUMBER;
2067                 }
2068                 pRet = CPDF_Number::Create(word);
2069                 return pRet;
2070             }
2071         } else {
2072             m_Pos = SavedPos;
2073             if (bTypeOnly) {
2074                 return (CPDF_Object*)PDFOBJ_NUMBER;
2075             }
2076             pRet = CPDF_Number::Create(word);
2077             return pRet;
2078         }
2079     }
2080     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2081         if (bTypeOnly) {
2082             return (CPDF_Object*)PDFOBJ_BOOLEAN;
2083         }
2084         pRet = CPDF_Boolean::Create(word == FX_BSTRC("true"));
2085         return pRet;
2086     }
2087     if (word == FX_BSTRC("null")) {
2088         if (bTypeOnly) {
2089             return (CPDF_Object*)PDFOBJ_NULL;
2090         }
2091         pRet = CPDF_Null::Create();
2092         return pRet;
2093     }
2094     if (word == FX_BSTRC("(")) {
2095         if (bTypeOnly) {
2096             return (CPDF_Object*)PDFOBJ_STRING;
2097         }
2098         FX_FILESIZE SavedPos = m_Pos - 1;
2099         CFX_ByteString str = ReadString();
2100         if (m_pCryptoHandler && bDecrypt) {
2101             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2102         }
2103         pRet = CPDF_String::Create(str, FALSE);
2104         return pRet;
2105     }
2106     if (word == FX_BSTRC("<")) {
2107         if (bTypeOnly) {
2108             return (CPDF_Object*)PDFOBJ_STRING;
2109         }
2110         FX_FILESIZE SavedPos = m_Pos - 1;
2111         CFX_ByteString str = ReadHexString();
2112         if (m_pCryptoHandler && bDecrypt) {
2113             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2114         }
2115         pRet = CPDF_String::Create(str, TRUE);
2116         return pRet;
2117     }
2118     if (word == FX_BSTRC("[")) {
2119         if (bTypeOnly) {
2120             return (CPDF_Object*)PDFOBJ_ARRAY;
2121         }
2122         CPDF_Array* pArray = CPDF_Array::Create();
2123         FX_FILESIZE firstPos = m_Pos - 1;
2124         while (1) {
2125             FX_FILESIZE SavedPos = m_Pos;
2126             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
2127             if (pObj == NULL) {
2128                 return pArray;
2129             }
2130             pArray->Add(pObj);
2131         }
2132     }
2133     if (word[0] == '/') {
2134         if (bTypeOnly) {
2135             return (CPDF_Object*)PDFOBJ_NAME;
2136         }
2137         pRet = CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2138         return pRet;
2139     }
2140     if (word == FX_BSTRC("<<")) {
2141         FX_FILESIZE saveDictOffset = m_Pos - 2;
2142         FX_DWORD dwDictSize = 0;
2143         if (bTypeOnly) {
2144             return (CPDF_Object*)PDFOBJ_DICTIONARY;
2145         }
2146         if (pContext) {
2147             pContext->m_DictStart = SavedPos;
2148         }
2149         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2150         FX_INT32 nKeys = 0;
2151         FX_FILESIZE dwSignValuePos = 0;
2152         while (1) {
2153             FX_BOOL bIsNumber;
2154             CFX_ByteString key = GetNextWord(bIsNumber);
2155             if (key.IsEmpty()) {
2156                 if (pDict)
2157                     pDict->Release();
2158                 return NULL;
2159             }
2160             FX_FILESIZE SavedPos = m_Pos - key.GetLength();
2161             if (key == FX_BSTRC(">>")) {
2162                 dwDictSize = m_Pos - saveDictOffset;
2163                 break;
2164             }
2165             if (key == FX_BSTRC("endobj")) {
2166                 dwDictSize = m_Pos - 6 - saveDictOffset;
2167                 m_Pos = SavedPos;
2168                 break;
2169             }
2170             if (key[0] != '/') {
2171                 continue;
2172             }
2173             nKeys ++;
2174             key = PDF_NameDecode(key);
2175             if (key == FX_BSTRC("/Contents")) {
2176                 dwSignValuePos = m_Pos;
2177             }
2178             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
2179             if (pObj == NULL) {
2180                 continue;
2181             }
2182             if (key.GetLength() == 1) {
2183                 pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2184             } else {
2185                 if (nKeys < 32) {
2186                     pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2187                 } else {
2188                     pDict->AddValue(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2189                 }
2190             }
2191         }
2192         if (IsSignatureDict(pDict)) {
2193             FX_FILESIZE dwSavePos = m_Pos;
2194             m_Pos = dwSignValuePos;
2195             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1, NULL, FALSE);
2196             pDict->SetAt(FX_BSTRC("Contents"), pObj);
2197             m_Pos = dwSavePos;
2198         }
2199         if (pContext) {
2200             pContext->m_DictEnd = m_Pos;
2201             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2202                 return pDict;
2203             }
2204         }
2205         FX_FILESIZE SavedPos = m_Pos;
2206         FX_BOOL bIsNumber;
2207         CFX_ByteString nextword = GetNextWord(bIsNumber);
2208         if (nextword == FX_BSTRC("stream")) {
2209             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2210             if (pStream) {
2211                 return pStream;
2212             }
2213             if (pDict)
2214                 pDict->Release();
2215             return NULL;
2216         } else {
2217             m_Pos = SavedPos;
2218             return pDict;
2219         }
2220     }
2221     if (word == FX_BSTRC(">>")) {
2222         m_Pos = SavedPos;
2223         return NULL;
2224     }
2225     if (bTypeOnly) {
2226         return (CPDF_Object*)PDFOBJ_INVALID;
2227     }
2228     return NULL;
2229 }
2230 CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum,
2231         FX_INT32 level, struct PARSE_CONTEXT* pContext)
2232 {
2233     if (level > _PARSER_OBJECT_LEVLE_) {
2234         return NULL;
2235     }
2236     FX_FILESIZE SavedPos = m_Pos;
2237     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2238     FX_BOOL bIsNumber;
2239     CFX_ByteString word = GetNextWord(bIsNumber);
2240     if (word.GetLength() == 0) {
2241         if (bTypeOnly) {
2242             return (CPDF_Object*)PDFOBJ_INVALID;
2243         }
2244         return NULL;
2245     }
2246     if (bIsNumber) {
2247         FX_FILESIZE SavedPos = m_Pos;
2248         CFX_ByteString nextword = GetNextWord(bIsNumber);
2249         if (bIsNumber) {
2250             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2251             if (nextword2 == FX_BSTRC("R")) {
2252                 FX_DWORD objnum = FXSYS_atoi(word);
2253                 if (bTypeOnly) {
2254                     return (CPDF_Object*)PDFOBJ_REFERENCE;
2255                 }
2256                 return CPDF_Reference::Create(pObjList, objnum);
2257             } else {
2258                 m_Pos = SavedPos;
2259                 if (bTypeOnly) {
2260                     return (CPDF_Object*)PDFOBJ_NUMBER;
2261                 }
2262                 return CPDF_Number::Create(word);
2263             }
2264         } else {
2265             m_Pos = SavedPos;
2266             if (bTypeOnly) {
2267                 return (CPDF_Object*)PDFOBJ_NUMBER;
2268             }
2269             return CPDF_Number::Create(word);
2270         }
2271     }
2272     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2273         if (bTypeOnly) {
2274             return (CPDF_Object*)PDFOBJ_BOOLEAN;
2275         }
2276         return CPDF_Boolean::Create(word == FX_BSTRC("true"));
2277     }
2278     if (word == FX_BSTRC("null")) {
2279         if (bTypeOnly) {
2280             return (CPDF_Object*)PDFOBJ_NULL;
2281         }
2282         return CPDF_Null::Create();
2283     }
2284     if (word == FX_BSTRC("(")) {
2285         if (bTypeOnly) {
2286             return (CPDF_Object*)PDFOBJ_STRING;
2287         }
2288         CFX_ByteString str = ReadString();
2289         if (m_pCryptoHandler) {
2290             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2291         }
2292         return CPDF_String::Create(str, FALSE);
2293     }
2294     if (word == FX_BSTRC("<")) {
2295         if (bTypeOnly) {
2296             return (CPDF_Object*)PDFOBJ_STRING;
2297         }
2298         CFX_ByteString str = ReadHexString();
2299         if (m_pCryptoHandler) {
2300             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2301         }
2302         return CPDF_String::Create(str, TRUE);
2303     }
2304     if (word == FX_BSTRC("[")) {
2305         if (bTypeOnly) {
2306             return (CPDF_Object*)PDFOBJ_ARRAY;
2307         }
2308         CPDF_Array* pArray = CPDF_Array::Create();
2309         while (1) {
2310             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
2311             if (pObj == NULL) {
2312                 if (m_WordBuffer[0] == ']') {
2313                     return pArray;
2314                 }
2315                 if (pArray)
2316                     pArray->Release();
2317                 return NULL;
2318             }
2319             pArray->Add(pObj);
2320         }
2321     }
2322     if (word[0] == '/') {
2323         if (bTypeOnly) {
2324             return (CPDF_Object*)PDFOBJ_NAME;
2325         }
2326         return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2327     }
2328     if (word == FX_BSTRC("<<")) {
2329         if (bTypeOnly) {
2330             return (CPDF_Object*)PDFOBJ_DICTIONARY;
2331         }
2332         if (pContext) {
2333             pContext->m_DictStart = SavedPos;
2334         }
2335         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2336         while (1) {
2337             FX_BOOL bIsNumber;
2338             FX_FILESIZE SavedPos = m_Pos;
2339             CFX_ByteString key = GetNextWord(bIsNumber);
2340             if (key.IsEmpty()) {
2341                 if (pDict)
2342                     pDict->Release();
2343                 return NULL;
2344             }
2345             if (key == FX_BSTRC(">>")) {
2346                 break;
2347             }
2348             if (key == FX_BSTRC("endobj")) {
2349                 m_Pos = SavedPos;
2350                 break;
2351             }
2352             if (key[0] != '/') {
2353                 continue;
2354             }
2355             key = PDF_NameDecode(key);
2356             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
2357             if (pObj == NULL) {
2358                 if (pDict)
2359                     pDict->Release();
2360                 FX_BYTE ch;
2361                 while (1) {
2362                     if (!GetNextChar(ch)) {
2363                         break;
2364                     }
2365                     if (ch == 0x0A || ch == 0x0D) {
2366                         break;
2367                     }
2368                 }
2369                 return NULL;
2370             }
2371             if (key.GetLength() == 1) {
2372                 pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2373             } else {
2374                 pDict->AddValue(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2375             }
2376         }
2377         if (pContext) {
2378             pContext->m_DictEnd = m_Pos;
2379             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2380                 return pDict;
2381             }
2382         }
2383         FX_FILESIZE SavedPos = m_Pos;
2384         FX_BOOL bIsNumber;
2385         CFX_ByteString nextword = GetNextWord(bIsNumber);
2386         if (nextword == FX_BSTRC("stream")) {
2387             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2388             if (pStream) {
2389                 return pStream;
2390             }
2391             if (pDict)
2392                 pDict->Release();
2393             return NULL;
2394         } else {
2395             m_Pos = SavedPos;
2396             return pDict;
2397         }
2398     }
2399     if (word == FX_BSTRC(">>")) {
2400         m_Pos = SavedPos;
2401         return NULL;
2402     }
2403     if (bTypeOnly) {
2404         return (CPDF_Object*)PDFOBJ_INVALID;
2405     }
2406     return NULL;
2407 }
2408 CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, PARSE_CONTEXT* pContext,
2409         FX_DWORD objnum, FX_DWORD gennum)
2410 {
2411     CPDF_Object* pLenObj = pDict->GetElement(FX_BSTRC("Length"));
2412     FX_FILESIZE len = 0;
2413     if (pLenObj && ((pLenObj->GetType() != PDFOBJ_REFERENCE) ||
2414                     ((((CPDF_Reference*)pLenObj)->GetObjList() != NULL) &&
2415                      ((CPDF_Reference*)pLenObj)->GetRefObjNum() != objnum))) {
2416         len = pLenObj->GetInteger();
2417     }
2418
2419     ToNextLine();
2420     FX_FILESIZE StreamStartPos = m_Pos;
2421     if (pContext) {
2422         pContext->m_DataStart = m_Pos;
2423     }
2424
2425     base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
2426     pos += len;
2427     if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
2428         m_Pos = pos.ValueOrDie();
2429     } else {
2430         return NULL;
2431     }
2432
2433     CPDF_CryptoHandler* pCryptoHandler = objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler;
2434     if (pCryptoHandler == NULL) {
2435         FX_FILESIZE SavedPos = m_Pos;
2436         GetNextWord();
2437         if (m_WordSize < 9 || FXSYS_memcmp32(m_WordBuffer, "endstream", 9)) {
2438             m_Pos = StreamStartPos;
2439             FX_FILESIZE offset = FindTag(FX_BSTRC("endstream"), 0);
2440             if (offset >= 0) {
2441                 FX_FILESIZE curPos = m_Pos;
2442                 m_Pos = StreamStartPos;
2443                 FX_FILESIZE endobjOffset = FindTag(FX_BSTRC("endobj"), 0);
2444                 if (endobjOffset < offset && endobjOffset >= 0) {
2445                     offset = endobjOffset;
2446                 } else {
2447                     m_Pos = curPos;
2448                 }
2449                 FX_BYTE byte1, byte2;
2450                 GetCharAt(StreamStartPos + offset - 1, byte1);
2451                 GetCharAt(StreamStartPos + offset - 2, byte2);
2452                 if (byte1 == 0x0a && byte2 == 0x0d) {
2453                     len -= 2;
2454                 } else if (byte1 == 0x0a || byte1 == 0x0d) {
2455                     len --;
2456                 }
2457                 len = (FX_DWORD)offset;
2458                 pDict->SetAtInteger(FX_BSTRC("Length"), len);
2459             } else {
2460                 m_Pos = StreamStartPos;
2461                 if (FindTag(FX_BSTRC("endobj"), 0) < 0) {
2462                     return NULL;
2463                 }
2464             }
2465         }
2466     }
2467     m_Pos = StreamStartPos;
2468     CPDF_Stream* pStream;
2469 #if defined(_FPDFAPI_MINI_) && !defined(_FXCORE_FEATURE_ALL_)
2470     pStream = FX_NEW CPDF_Stream(m_pFileAccess, pCryptoHandler, m_HeaderOffset + m_Pos, len, pDict, gennum);
2471     m_Pos += len;
2472 #else
2473     FX_LPBYTE pData = FX_Alloc(FX_BYTE, len);
2474     if (!pData) {
2475         return NULL;
2476     }
2477     ReadBlock(pData, len);
2478     if (pCryptoHandler) {
2479         CFX_BinaryBuf dest_buf;
2480         dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len));
2481         FX_LPVOID context = pCryptoHandler->DecryptStart(objnum, gennum);
2482         pCryptoHandler->DecryptStream(context, pData, len, dest_buf);
2483         pCryptoHandler->DecryptFinish(context, dest_buf);
2484         FX_Free(pData);
2485         pData = dest_buf.GetBuffer();
2486         len = dest_buf.GetSize();
2487         dest_buf.DetachBuffer();
2488     }
2489     pStream = FX_NEW CPDF_Stream(pData, len, pDict);
2490 #endif
2491     if (pContext) {
2492         pContext->m_DataEnd = pContext->m_DataStart + len;
2493     }
2494     StreamStartPos = m_Pos;
2495     GetNextWord();
2496     if (m_WordSize == 6 && 0 == FXSYS_memcmp32(m_WordBuffer, "endobj", 6)) {
2497         m_Pos = StreamStartPos;
2498     }
2499     return pStream;
2500 }
2501 void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess, FX_DWORD HeaderOffset)
2502 {
2503     if (m_pFileBuf) {
2504         FX_Free(m_pFileBuf);
2505         m_pFileBuf = NULL;
2506     }
2507     m_pFileBuf = FX_Alloc(FX_BYTE, m_BufSize);
2508     m_HeaderOffset = HeaderOffset;
2509     m_FileLen = pFileAccess->GetSize();
2510     m_Pos = 0;
2511     m_pFileAccess = pFileAccess;
2512     m_BufOffset = 0;
2513     pFileAccess->ReadBlock(m_pFileBuf, 0, (size_t)((FX_FILESIZE)m_BufSize > m_FileLen ? m_FileLen : m_BufSize));
2514 }
2515 FX_INT32 CPDF_SyntaxParser::GetDirectNum()
2516 {
2517     GetNextWord();
2518     if (!m_bIsNumber) {
2519         return 0;
2520     }
2521     m_WordBuffer[m_WordSize] = 0;
2522     return FXSYS_atoi((FX_LPCSTR)m_WordBuffer);
2523 }
2524 FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit, FX_LPCBYTE tag, FX_DWORD taglen)
2525 {
2526     FX_BYTE type = _PDF_CharType[tag[0]];
2527     FX_BOOL bCheckLeft = type != 'D' && type != 'W';
2528     type = _PDF_CharType[tag[taglen - 1]];
2529     FX_BOOL bCheckRight = type != 'D' || type != 'W';
2530     FX_BYTE ch;
2531     if (bCheckRight && startpos + (FX_INT32)taglen <= limit && GetCharAt(startpos + (FX_INT32)taglen, ch)) {
2532         FX_BYTE type = _PDF_CharType[ch];
2533         if (type == 'N' || type == 'R') {
2534             return FALSE;
2535         }
2536     }
2537     if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
2538         FX_BYTE type = _PDF_CharType[ch];
2539         if (type == 'N' || type == 'R') {
2540             return FALSE;
2541         }
2542     }
2543     return TRUE;
2544 }
2545 FX_BOOL CPDF_SyntaxParser::SearchWord(FX_BSTR tag, FX_BOOL bWholeWord, FX_BOOL bForward, FX_FILESIZE limit)
2546 {
2547     FX_INT32 taglen = tag.GetLength();
2548     if (taglen == 0) {
2549         return FALSE;
2550     }
2551     FX_FILESIZE pos = m_Pos;
2552     FX_INT32 offset = 0;
2553     if (!bForward) {
2554         offset = taglen - 1;
2555     }
2556     FX_LPCBYTE tag_data = tag;
2557     FX_BYTE byte;
2558     while (1) {
2559         if (bForward) {
2560             if (limit) {
2561                 if (pos >= m_Pos + limit) {
2562                     return FALSE;
2563                 }
2564             }
2565             if (!GetCharAt(pos, byte)) {
2566                 return FALSE;
2567             }
2568         } else {
2569             if (limit) {
2570                 if (pos <= m_Pos - limit) {
2571                     return FALSE;
2572                 }
2573             }
2574             if (!GetCharAtBackward(pos, byte)) {
2575                 return FALSE;
2576             }
2577         }
2578         if (byte == tag_data[offset]) {
2579             if (bForward) {
2580                 offset ++;
2581                 if (offset < taglen) {
2582                     pos ++;
2583                     continue;
2584                 }
2585             } else {
2586                 offset --;
2587                 if (offset >= 0) {
2588                     pos --;
2589                     continue;
2590                 }
2591             }
2592             FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos;
2593             if (!bWholeWord || IsWholeWord(startpos, limit, tag, taglen)) {
2594                 m_Pos = startpos;
2595                 return TRUE;
2596             }
2597         }
2598         if (bForward) {
2599             offset = byte == tag_data[0] ? 1 : 0;
2600             pos ++;
2601         } else {
2602             offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1;
2603             pos --;
2604         }
2605         if (pos < 0) {
2606             return FALSE;
2607         }
2608     }
2609     return FALSE;
2610 }
2611 struct _SearchTagRecord {
2612     FX_LPCBYTE  m_pTag;
2613     FX_DWORD    m_Len;
2614     FX_DWORD    m_Offset;
2615 };
2616 FX_INT32 CPDF_SyntaxParser::SearchMultiWord(FX_BSTR tags, FX_BOOL bWholeWord, FX_FILESIZE limit)
2617 {
2618     FX_INT32 ntags = 1, i;
2619     for (i = 0; i < tags.GetLength(); i ++)
2620         if (tags[i] == 0) {
2621             ntags ++;
2622         }
2623     _SearchTagRecord* pPatterns = FX_Alloc(_SearchTagRecord, ntags);
2624     FX_DWORD start = 0, itag = 0, max_len = 0;
2625     for (i = 0; i <= tags.GetLength(); i ++) {
2626         if (tags[i] == 0) {
2627             FX_DWORD len = i - start;
2628             if (len > max_len) {
2629                 max_len = len;
2630             }
2631             pPatterns[itag].m_pTag = tags.GetPtr() + start;
2632             pPatterns[itag].m_Len = len;
2633             pPatterns[itag].m_Offset = 0;
2634             start = i + 1;
2635             itag ++;
2636         }
2637     }
2638     FX_FILESIZE pos = m_Pos;
2639     FX_BYTE byte;
2640     GetCharAt(pos++, byte);
2641     FX_INT32 found = -1;
2642     while (1) {
2643         for (i = 0; i < ntags; i ++) {
2644             if (pPatterns[i].m_pTag[pPatterns[i].m_Offset] == byte) {
2645                 pPatterns[i].m_Offset ++;
2646                 if (pPatterns[i].m_Offset == pPatterns[i].m_Len) {
2647                     if (!bWholeWord || IsWholeWord(pos - pPatterns[i].m_Len, limit, pPatterns[i].m_pTag, pPatterns[i].m_Len)) {
2648                         found = i;
2649                         goto end;
2650                     } else {
2651                         if (pPatterns[i].m_pTag[0] == byte) {
2652                             pPatterns[i].m_Offset = 1;
2653                         } else {
2654                             pPatterns[i].m_Offset = 0;
2655                         }
2656                     }
2657                 }
2658             } else {
2659                 if (pPatterns[i].m_pTag[0] == byte) {
2660                     pPatterns[i].m_Offset = 1;
2661                 } else {
2662                     pPatterns[i].m_Offset = 0;
2663                 }
2664             }
2665         }
2666         if (limit && pos >= m_Pos + limit) {
2667             goto end;
2668         }
2669         if (!GetCharAt(pos, byte)) {
2670             goto end;
2671         }
2672         pos ++;
2673     }
2674 end:
2675     FX_Free(pPatterns);
2676     return found;
2677 }
2678 FX_FILESIZE CPDF_SyntaxParser::FindTag(FX_BSTR tag, FX_FILESIZE limit)
2679 {
2680     FX_INT32 taglen = tag.GetLength();
2681     FX_INT32 match = 0;
2682     limit += m_Pos;
2683     FX_FILESIZE startpos = m_Pos;
2684     while (1) {
2685         FX_BYTE ch;
2686         if (!GetNextChar(ch)) {
2687             return -1;
2688         }
2689         if (ch == tag[match]) {
2690             match ++;
2691             if (match == taglen) {
2692                 return m_Pos - startpos - taglen;
2693             }
2694         } else {
2695             match = ch == tag[0] ? 1 : 0;
2696         }
2697         if (limit && m_Pos == limit) {
2698             return -1;
2699         }
2700     }
2701     return -1;
2702 }
2703 void CPDF_SyntaxParser::GetBinary(FX_BYTE* buffer, FX_DWORD size)
2704 {
2705     FX_DWORD offset = 0;
2706     FX_BYTE ch;
2707     while (1) {
2708         if (!GetNextChar(ch)) {
2709             return;
2710         }
2711         buffer[offset++] = ch;
2712         if (offset == size) {
2713             break;
2714         }
2715     }
2716 }
2717 CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead)
2718 {
2719     m_pFileAvail = pFileAvail;
2720     m_pFileRead = pFileRead;
2721     m_Pos = 0;
2722     m_dwFileLen = 0;
2723     if (m_pFileRead) {
2724         m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
2725     }
2726     m_dwCurrentOffset = 0;
2727     m_WordSize = 0;
2728     m_dwXRefOffset = 0;
2729     m_bufferOffset = 0;
2730     m_dwFirstPageNo = 0;
2731     m_bufferSize = 0;
2732     m_PagesObjNum = 0;
2733     m_dwCurrentXRefSteam = 0;
2734     m_dwAcroFormObjNum = 0;
2735     m_dwInfoObjNum = 0;
2736     m_pDocument = 0;
2737     m_dwEncryptObjNum = 0;
2738     m_dwPrevXRefOffset = 0;
2739     m_dwLastXRefOffset = 0;
2740     m_bDocAvail = FALSE;
2741     m_bMainXRefLoad = FALSE;
2742     m_bDocAvail = FALSE;
2743     m_bLinearized = FALSE;
2744     m_bPagesLoad = FALSE;
2745     m_bPagesTreeLoad = FALSE;
2746     m_bMainXRefLoadedOK = FALSE;
2747     m_bAnnotsLoad = FALSE;
2748     m_bHaveAcroForm = FALSE;
2749     m_bAcroFormLoad = FALSE;
2750     m_bPageLoadedOK = FALSE;
2751     m_bNeedDownLoadResource = FALSE;
2752     m_bLinearizedFormParamLoad = FALSE;
2753     m_pLinearized = NULL;
2754     m_pRoot = NULL;
2755     m_pTrailer = NULL;
2756     m_pCurrentParser = NULL;
2757     m_pAcroForm = NULL;
2758     m_pPageDict = NULL;
2759     m_pPageResource = NULL;
2760     m_pageMapCheckState = NULL;
2761     m_docStatus = PDF_DATAAVAIL_HEADER;
2762     m_parser.m_bOwnFileRead = FALSE;
2763     m_bTotalLoadPageTree = FALSE;
2764     m_bCurPageDictLoadOK = FALSE;
2765     m_bLinearedDataOK = FALSE;
2766     m_pagesLoadState = NULL;
2767 }
2768 CPDF_DataAvail::~CPDF_DataAvail()
2769 {
2770     if (m_pLinearized)  {
2771         m_pLinearized->Release();
2772     }
2773     if (m_pRoot) {
2774         m_pRoot->Release();
2775     }
2776     if (m_pTrailer) {
2777         m_pTrailer->Release();
2778     }
2779     if (m_pageMapCheckState) {
2780         delete m_pageMapCheckState;
2781     }
2782     if (m_pagesLoadState) {
2783         delete m_pagesLoadState;
2784     }
2785     FX_INT32 i = 0;
2786     FX_INT32 iSize = m_arrayAcroforms.GetSize();
2787     for (i = 0; i < iSize; ++i) {
2788         ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release();
2789     }
2790 }
2791 void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc)
2792 {
2793     m_pDocument = pDoc;
2794 }
2795 FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset)
2796 {
2797     CPDF_Parser *pParser = (CPDF_Parser *)(m_pDocument->GetParser());
2798     if (pParser == NULL) {
2799         return 0;
2800     }
2801     if (objnum >= (FX_DWORD)pParser->m_CrossRef.GetSize()) {
2802         return 0;
2803     }
2804     if (pParser->m_V5Type[objnum] == 2) {
2805         objnum = (FX_DWORD)pParser->m_CrossRef[objnum];
2806     }
2807     if (pParser->m_V5Type[objnum] == 1 || pParser->m_V5Type[objnum] == 255) {
2808         offset = pParser->m_CrossRef[objnum];
2809         if (offset == 0) {
2810             return 0;
2811         }
2812         FX_LPVOID pResult = FXSYS_bsearch(&offset, pParser->m_SortedOffset.GetData(), pParser->m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
2813         if (pResult == NULL) {
2814             return 0;
2815         }
2816         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)pParser->m_SortedOffset.GetData() == pParser->m_SortedOffset.GetSize() - 1) {
2817             return 0;
2818         }
2819         return (FX_DWORD)(((FX_FILESIZE*)pResult)[1] - offset);
2820     }
2821     return 0;
2822 }
2823 FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array, FX_BOOL bParsePage, IFX_DownloadHints* pHints, CFX_PtrArray &ret_array)
2824 {
2825     if (!obj_array.GetSize()) {
2826         return TRUE;
2827     }
2828     FX_DWORD count = 0;
2829     CFX_PtrArray new_obj_array;
2830     FX_INT32 i = 0;
2831     for (i = 0; i < obj_array.GetSize(); i++) {
2832         CPDF_Object *pObj = (CPDF_Object *)obj_array[i];
2833         if (!pObj) {
2834             continue;
2835         }
2836         FX_INT32 type = pObj->GetType();
2837         switch (type) {
2838             case PDFOBJ_ARRAY: {
2839                     CPDF_Array *pArray = pObj->GetArray();
2840                     for (FX_DWORD k = 0; k < pArray->GetCount(); k++) {
2841                         new_obj_array.Add(pArray->GetElement(k));
2842                     }
2843                 }
2844                 break;
2845             case PDFOBJ_STREAM:
2846                 pObj = pObj->GetDict();
2847             case PDFOBJ_DICTIONARY: {
2848                     CPDF_Dictionary *pDict = pObj->GetDict();
2849                     if (pDict && pDict->GetString("Type") == "Page" && !bParsePage) {
2850                         continue;
2851                     }
2852                     FX_POSITION pos = pDict->GetStartPos();
2853                     while (pos) {
2854                         CPDF_Object *value;
2855                         CFX_ByteString key;
2856                         value = pDict->GetNextElement(pos, key);
2857                         if (key != "Parent") {
2858                             new_obj_array.Add(value);
2859                         }
2860                     }
2861                 }
2862                 break;
2863             case PDFOBJ_REFERENCE: {
2864                     CPDF_Reference *pRef = (CPDF_Reference*)pObj;
2865                     FX_DWORD dwNum = pRef->GetRefObjNum();
2866                     FX_FILESIZE offset;
2867                     FX_DWORD size = GetObjectSize(pRef->GetRefObjNum(), offset);
2868                     if (!size) {
2869                         break;
2870                     }
2871                     size = (FX_DWORD)((FX_FILESIZE)(offset + size + 512) > m_dwFileLen ? m_dwFileLen - offset : size + 512);
2872                     if (!m_pFileAvail->IsDataAvail(offset, size)) {
2873                         pHints->AddSegment(offset, size);
2874                         ret_array.Add(pObj);
2875                         count++;
2876                     } else if (!m_objnum_array.Find(dwNum)) {
2877                         m_objnum_array.AddObjNum(dwNum);
2878                         CPDF_Object *pReferred = m_pDocument->GetIndirectObject(pRef->GetRefObjNum(), NULL);
2879                         if (pReferred) {
2880                             new_obj_array.Add(pReferred);
2881                         }
2882                     }
2883                 }
2884                 break;
2885         }
2886     }
2887     if (count > 0) {
2888         FX_INT32 iSize = new_obj_array.GetSize();
2889         for (i = 0; i < iSize; ++i) {
2890             CPDF_Object *pObj = (CPDF_Object *)new_obj_array[i];
2891             FX_INT32 type = pObj->GetType();
2892             if (type == PDFOBJ_REFERENCE) {
2893                 CPDF_Reference *pRef = (CPDF_Reference *)pObj;
2894                 FX_DWORD dwNum = pRef->GetRefObjNum();
2895                 if (!m_objnum_array.Find(dwNum)) {
2896                     ret_array.Add(pObj);
2897                 }
2898             } else {
2899                 ret_array.Add(pObj);
2900             }
2901         }
2902         return FALSE;
2903     }
2904     obj_array.RemoveAll();
2905     obj_array.Append(new_obj_array);
2906     return IsObjectsAvail(obj_array, FALSE, pHints, ret_array);
2907 }
2908 FX_BOOL CPDF_DataAvail::IsDocAvail(IFX_DownloadHints* pHints)
2909 {
2910     if (!m_dwFileLen && m_pFileRead) {
2911         m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
2912         if (!m_dwFileLen) {
2913             return TRUE;
2914         }
2915     }
2916     while (!m_bDocAvail) {
2917         if (!CheckDocStatus(pHints)) {
2918             return FALSE;
2919         }
2920     }
2921     return TRUE;
2922 }
2923 FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints)
2924 {
2925     if (!m_objs_array.GetSize()) {
2926         m_objs_array.RemoveAll();
2927         m_objnum_array.RemoveAll();
2928         CFX_PtrArray obj_array;
2929         obj_array.Append(m_arrayAcroforms);
2930         FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array);
2931         if (bRet) {
2932             m_objs_array.RemoveAll();
2933         }
2934         return bRet;
2935     } else {
2936         CFX_PtrArray new_objs_array;
2937         FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
2938         if (bRet) {
2939             FX_INT32 iSize = m_arrayAcroforms.GetSize();
2940             for (FX_INT32 i = 0; i < iSize; ++i) {
2941                 ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release();
2942             }
2943             m_arrayAcroforms.RemoveAll();
2944         } else {
2945             m_objs_array.RemoveAll();
2946             m_objs_array.Append(new_objs_array);
2947         }
2948         return bRet;
2949     }
2950 }
2951 FX_BOOL CPDF_DataAvail::CheckAcroForm(IFX_DownloadHints* pHints)
2952 {
2953     FX_BOOL bExist = FALSE;
2954     m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist);
2955     if (!bExist) {
2956         m_docStatus = PDF_DATAAVAIL_PAGETREE;
2957         return TRUE;
2958     }
2959     if (!m_pAcroForm) {
2960         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
2961             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
2962             return TRUE;
2963         }
2964         return FALSE;
2965     }
2966     m_arrayAcroforms.Add(m_pAcroForm);
2967     m_docStatus = PDF_DATAAVAIL_PAGETREE;
2968     return TRUE;
2969 }
2970 FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints *pHints)
2971 {
2972     switch (m_docStatus) {
2973         case PDF_DATAAVAIL_HEADER:
2974             return CheckHeader(pHints);
2975         case PDF_DATAAVAIL_FIRSTPAGE:
2976         case PDF_DATAAVAIL_FIRSTPAGE_PREPARE:
2977             return CheckFirstPage(pHints);
2978         case PDF_DATAAVAIL_END:
2979             return CheckEnd(pHints);
2980         case PDF_DATAAVAIL_CROSSREF:
2981             return CheckCrossRef(pHints);
2982         case PDF_DATAAVAIL_CROSSREF_ITEM:
2983             return CheckCrossRefItem(pHints);
2984         case PDF_DATAAVAIL_CROSSREF_STREAM:
2985             return CheckAllCrossRefStream(pHints);
2986         case PDF_DATAAVAIL_TRAILER:
2987             return CheckTrailer(pHints);
2988         case PDF_DATAAVAIL_TRAILER_APPEND:
2989             return CheckTrailerAppend(pHints);
2990         case PDF_DATAAVAIL_LOADALLCRSOSSREF:
2991             return LoadAllXref(pHints);
2992         case PDF_DATAAVAIL_LOADALLFILE:
2993             return LoadAllFile(pHints);
2994         case PDF_DATAAVAIL_ROOT:
2995             return CheckRoot(pHints);
2996         case PDF_DATAAVAIL_INFO:
2997             return CheckInfo(pHints);
2998         case PDF_DATAAVAIL_ACROFORM:
2999             return CheckAcroForm(pHints);
3000         case PDF_DATAAVAIL_PAGETREE:
3001             if (m_bTotalLoadPageTree) {
3002                 return CheckPages(pHints);
3003             } else {
3004                 return LoadDocPages(pHints);
3005             }
3006         case PDF_DATAAVAIL_PAGE:
3007             if (m_bTotalLoadPageTree) {
3008                 return CheckPage(pHints);
3009             } else {
3010                 m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD;
3011                 return TRUE;
3012             }
3013         case PDF_DATAAVAIL_ERROR:
3014             return LoadAllFile(pHints);
3015         case PDF_DATAAVAIL_PAGE_LATERLOAD:
3016             m_docStatus = PDF_DATAAVAIL_PAGE;
3017         default:
3018             m_bDocAvail = TRUE;
3019             return TRUE;
3020     }
3021 }
3022 FX_BOOL CPDF_DataAvail::CheckPageStatus(IFX_DownloadHints* pHints)
3023 {
3024     switch (m_docStatus) {
3025         case PDF_DATAAVAIL_PAGETREE:
3026             return CheckPages(pHints);
3027         case PDF_DATAAVAIL_PAGE:
3028             return CheckPage(pHints);
3029         case PDF_DATAAVAIL_ERROR:
3030             return LoadAllFile(pHints);
3031         default:
3032             m_bPagesTreeLoad = TRUE;
3033             m_bPagesLoad = TRUE;
3034             return TRUE;
3035     }
3036 }
3037 FX_BOOL CPDF_DataAvail::LoadAllFile(IFX_DownloadHints* pHints)
3038 {
3039     if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) {
3040         m_docStatus = PDF_DATAAVAIL_DONE;
3041         return TRUE;
3042     }
3043     pHints->AddSegment(0, (FX_DWORD)m_dwFileLen);
3044     return FALSE;
3045 }
3046 FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints)
3047 {
3048     m_parser.m_Syntax.InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset);
3049     m_parser.m_bOwnFileRead = FALSE;
3050     if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) {
3051         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3052         return FALSE;
3053     }
3054     FXSYS_qsort(m_parser.m_SortedOffset.GetData(), m_parser.m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
3055     m_dwRootObjNum = m_parser.GetRootObjNum();
3056     m_dwInfoObjNum = m_parser.GetInfoObjNum();
3057     m_pCurrentParser = &m_parser;
3058     m_docStatus = PDF_DATAAVAIL_ROOT;
3059     return TRUE;
3060 }
3061 CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum, IFX_DownloadHints* pHints, FX_BOOL *pExistInFile)
3062 {
3063     CPDF_Object *pRet = NULL;
3064     if (pExistInFile) {
3065         *pExistInFile = TRUE;
3066     }
3067     if (m_pDocument == NULL) {
3068         FX_FILESIZE offset = m_parser.GetObjectOffset(objnum);
3069         if (offset < 0) {
3070             *pExistInFile = FALSE;
3071             return NULL;
3072         }
3073         FX_DWORD size = (FX_DWORD)m_parser.GetObjectSize(objnum);
3074         size = (FX_DWORD)(((FX_FILESIZE)(offset + size + 512)) > m_dwFileLen ? m_dwFileLen - offset : size + 512);
3075         if (!m_pFileAvail->IsDataAvail(offset, size)) {
3076             pHints->AddSegment(offset, size);
3077             return NULL;
3078         }
3079         pRet = m_parser.ParseIndirectObject(NULL, objnum);
3080         if (!pRet && pExistInFile) {
3081             *pExistInFile = FALSE;
3082         }
3083         return pRet;
3084     }
3085     FX_FILESIZE offset = 0;
3086     FX_DWORD size = GetObjectSize(objnum, offset);
3087     size = (FX_DWORD)((FX_FILESIZE)(offset + size + 512) > m_dwFileLen ? m_dwFileLen - offset : size + 512);
3088     if (!m_pFileAvail->IsDataAvail(offset, size)) {
3089         pHints->AddSegment(offset, size);
3090         return NULL;
3091     }
3092     CPDF_Parser *pParser = (CPDF_Parser *)(m_pDocument->GetParser());
3093     pRet = pParser->ParseIndirectObject(NULL, objnum, NULL);
3094     if (!pRet && pExistInFile) {
3095         *pExistInFile = FALSE;
3096     }
3097     return pRet;
3098 }
3099 FX_BOOL CPDF_DataAvail::CheckInfo(IFX_DownloadHints* pHints)
3100 {
3101     FX_BOOL bExist = FALSE;
3102     CPDF_Object *pInfo = GetObject(m_dwInfoObjNum, pHints, &bExist);
3103     if (!bExist) {
3104         if (m_bHaveAcroForm) {
3105             m_docStatus = PDF_DATAAVAIL_ACROFORM;
3106         } else {
3107             m_docStatus = PDF_DATAAVAIL_PAGETREE;
3108         }
3109         return TRUE;
3110     }
3111     if (!pInfo) {
3112         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3113             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3114             return TRUE;
3115         }
3116         if (m_Pos == m_dwFileLen) {
3117             m_docStatus = PDF_DATAAVAIL_ERROR;
3118         }
3119         return FALSE;
3120     }
3121     if (pInfo) {
3122         pInfo->Release();
3123     }
3124     if (m_bHaveAcroForm) {
3125         m_docStatus = PDF_DATAAVAIL_ACROFORM;
3126     } else {
3127         m_docStatus = PDF_DATAAVAIL_PAGETREE;
3128     }
3129     return TRUE;
3130 }
3131 FX_BOOL CPDF_DataAvail::CheckRoot(IFX_DownloadHints* pHints)
3132 {
3133     FX_BOOL bExist = FALSE;
3134     m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist);
3135     if (!bExist) {
3136         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3137         return TRUE;
3138     }
3139     if (!m_pRoot) {
3140         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3141             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3142             return TRUE;
3143         }
3144         return FALSE;
3145     }
3146     CPDF_Reference* pRef = (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("Pages"));
3147     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
3148         m_docStatus = PDF_DATAAVAIL_ERROR;
3149         return FALSE;
3150     }
3151     m_PagesObjNum = pRef->GetRefObjNum();
3152     CPDF_Reference* pAcroFormRef = (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("AcroForm"));
3153     if (pAcroFormRef && pAcroFormRef->GetType() == PDFOBJ_REFERENCE) {
3154         m_bHaveAcroForm = TRUE;
3155         m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum();
3156     }
3157     if (m_dwInfoObjNum) {
3158         m_docStatus = PDF_DATAAVAIL_INFO;
3159     } else {
3160         if (m_bHaveAcroForm) {
3161             m_docStatus = PDF_DATAAVAIL_ACROFORM;
3162         } else {
3163             m_docStatus = PDF_DATAAVAIL_PAGETREE;
3164         }
3165     }
3166     return TRUE;
3167 }
3168 FX_BOOL CPDF_DataAvail::PreparePageItem()
3169 {
3170     CPDF_Dictionary *pRoot = m_pDocument->GetRoot();
3171     CPDF_Reference* pRef = pRoot ? (CPDF_Reference*)pRoot->GetElement(FX_BSTRC("Pages")) : NULL;
3172     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
3173         m_docStatus = PDF_DATAAVAIL_ERROR;
3174         return FALSE;
3175     }
3176     m_PagesObjNum = pRef->GetRefObjNum();
3177     m_pCurrentParser = (CPDF_Parser *)m_pDocument->GetParser();
3178     m_docStatus = PDF_DATAAVAIL_PAGETREE;
3179     return TRUE;
3180 }
3181 FX_BOOL CPDF_DataAvail::IsFirstCheck(int iPage)
3182 {
3183     if (NULL == m_pageMapCheckState) {
3184         m_pageMapCheckState = FX_NEW CFX_CMapDWordToDWord();
3185     }
3186     FX_DWORD dwValue = 0;
3187     if (!m_pageMapCheckState->Lookup(iPage, dwValue)) {
3188         m_pageMapCheckState->SetAt(iPage, 1);
3189         return TRUE;
3190     }
3191     if (dwValue != 0) {
3192         return FALSE;
3193     }
3194     m_pageMapCheckState->SetAt(iPage, 1);
3195     return TRUE;
3196 }
3197 void CPDF_DataAvail::ResetFirstCheck(int iPage)
3198 {
3199     if (NULL == m_pageMapCheckState) {
3200         m_pageMapCheckState = FX_NEW CFX_CMapDWordToDWord();
3201     }
3202     FX_DWORD dwValue = 1;
3203     if (!m_pageMapCheckState->Lookup(iPage, dwValue)) {
3204         return;
3205     }
3206     m_pageMapCheckState->SetAt(iPage, 0);
3207 }
3208 FX_BOOL CPDF_DataAvail::CheckPage(IFX_DownloadHints* pHints)
3209 {
3210     FX_DWORD i = 0;
3211     FX_DWORD iLen = m_PageObjList.GetSize();
3212     CFX_DWordArray UnavailObjList;
3213     for (; i < iLen; ++i) {
3214         FX_DWORD dwPageObjNum = m_PageObjList.GetAt(i);
3215         FX_BOOL bExist = FALSE;
3216         CPDF_Object *pObj = GetObject(dwPageObjNum, pHints, &bExist);
3217         if (!pObj) {
3218             if (bExist) {
3219                 UnavailObjList.Add(dwPageObjNum);
3220             }
3221             continue;
3222         }
3223         if (pObj->GetType() == PDFOBJ_ARRAY) {
3224             CPDF_Array *pArray = pObj->GetArray();
3225             if (pArray) {
3226                 FX_INT32 iSize = pArray->GetCount();
3227                 CPDF_Object *pItem = NULL;
3228                 for (FX_INT32 j = 0; j < iSize; ++j) {
3229                     pItem = pArray->GetElement(j);
3230                     if (pItem && pItem->GetType() == PDFOBJ_REFERENCE) {
3231                         UnavailObjList.Add(((CPDF_Reference *)pItem)->GetRefObjNum());
3232                     }
3233                 }
3234             }
3235         }
3236         if (pObj->GetType() != PDFOBJ_DICTIONARY) {
3237             pObj->Release();
3238             continue;
3239         }
3240         CFX_ByteString type = pObj->GetDict()->GetString(FX_BSTRC("Type"));
3241         if (type == FX_BSTRC("Pages")) {
3242             m_PagesArray.Add(pObj);
3243             continue;
3244         }
3245         pObj->Release();
3246     }
3247     m_PageObjList.RemoveAll();
3248     if (UnavailObjList.GetSize()) {
3249         m_PageObjList.Append(UnavailObjList);
3250         return FALSE;
3251     }
3252     i = 0;
3253     iLen = m_PagesArray.GetSize();
3254     for (; i < iLen; ++i) {
3255         CPDF_Object *pPages = (CPDF_Object *)m_PagesArray.GetAt(i);
3256         if (!pPages) {
3257             continue;
3258         }
3259         if (!GetPageKids(m_pCurrentParser, pPages)) {
3260             pPages->Release();
3261             while (i++ < iLen) {
3262                 pPages = (CPDF_Object *)m_PagesArray.GetAt(i);
3263                 pPages->Release();
3264             }
3265             m_PagesArray.RemoveAll();
3266             m_docStatus = PDF_DATAAVAIL_ERROR;
3267             return FALSE;
3268         }
3269         pPages->Release();
3270     }
3271     m_PagesArray.RemoveAll();
3272     if (!m_PageObjList.GetSize()) {
3273         m_docStatus = PDF_DATAAVAIL_DONE;
3274         return TRUE;
3275     }
3276     return TRUE;
3277 }
3278 FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser *pParser, CPDF_Object *pPages)
3279 {
3280     if (!pParser) {
3281         m_docStatus = PDF_DATAAVAIL_ERROR;
3282         return FALSE;
3283     }
3284     CPDF_Dictionary* pDict = pPages->GetDict();
3285     CPDF_Object *pKids = pDict ? pDict->GetElement(FX_BSTRC("Kids")) : NULL;
3286     if (!pKids) {
3287         return TRUE;
3288     }
3289     switch (pKids->GetType()) {
3290         case PDFOBJ_REFERENCE: {
3291                 CPDF_Reference *pKid = (CPDF_Reference *)pKids;
3292                 m_PageObjList.Add(pKid->GetRefObjNum());
3293             }
3294             break;
3295         case PDFOBJ_ARRAY: {
3296                 CPDF_Array *pKidsArray = (CPDF_Array *)pKids;
3297                 for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) {
3298                     CPDF_Reference *pKid = (CPDF_Reference *)pKidsArray->GetElement(i);
3299                     m_PageObjList.Add(pKid->GetRefObjNum());
3300                 }
3301             }
3302             break;
3303         default:
3304             m_docStatus = PDF_DATAAVAIL_ERROR;
3305             return FALSE;
3306     }
3307     return TRUE;
3308 }
3309 FX_BOOL CPDF_DataAvail::CheckPages(IFX_DownloadHints* pHints)
3310 {
3311     FX_BOOL bExist = FALSE;
3312     CPDF_Object *pPages = GetObject(m_PagesObjNum, pHints, &bExist);
3313     if (!bExist) {
3314         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3315         return TRUE;
3316     }
3317     if (!pPages) {
3318         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3319             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3320             return TRUE;
3321         }
3322         return FALSE;
3323     }
3324     FX_BOOL bNeedLoad = FALSE;
3325     if (!GetPageKids(m_pCurrentParser, pPages)) {
3326         pPages->Release();
3327         m_docStatus = PDF_DATAAVAIL_ERROR;
3328         return FALSE;
3329     }
3330     pPages->Release();
3331     m_docStatus = PDF_DATAAVAIL_PAGE;
3332     return TRUE;
3333 }
3334 FX_BOOL CPDF_DataAvail::CheckHeader(IFX_DownloadHints* pHints)
3335 {
3336     FX_DWORD req_size = 1024;
3337     if ((FX_FILESIZE)req_size > m_dwFileLen) {
3338         req_size = (FX_DWORD)m_dwFileLen;
3339     }
3340     if (m_pFileAvail->IsDataAvail(0, req_size)) {
3341         FX_BYTE buffer[1024];
3342         m_pFileRead->ReadBlock(buffer, 0, req_size);
3343         if (IsLinearizedFile(buffer, req_size)) {
3344             m_docStatus = PDF_DATAAVAIL_FIRSTPAGE;
3345         } else {
3346             if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3347                 return FALSE;
3348             }
3349             m_docStatus = PDF_DATAAVAIL_END;
3350         }
3351         return TRUE;
3352     }
3353     pHints->AddSegment(0, req_size);
3354     return FALSE;
3355 }
3356 FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints *pHints)
3357 {
3358     FX_DWORD dwFirstPageEndOffset = 0;
3359     CPDF_Dictionary* pDict = m_pLinearized->GetDict();
3360     CPDF_Object *pEndOffSet = pDict ? pDict->GetElement(FX_BSTRC("E")) : NULL;
3361     if (!pEndOffSet) {
3362         m_docStatus = PDF_DATAAVAIL_ERROR;
3363         return FALSE;
3364     }
3365     CPDF_Object *pXRefOffset = pDict ? pDict->GetElement(FX_BSTRC("T")) : NULL;
3366     if (!pXRefOffset) {
3367         m_docStatus = PDF_DATAAVAIL_ERROR;
3368         return FALSE;
3369     }
3370     CPDF_Object *pFileLen = pDict ? pDict->GetElement(FX_BSTRC("L")) : NULL;
3371     if (!pFileLen) {
3372         m_docStatus = PDF_DATAAVAIL_ERROR;
3373         return FALSE;
3374     }
3375     FX_BOOL bNeedDownLoad = FALSE;
3376     if (pEndOffSet->GetType() == PDFOBJ_NUMBER) {
3377         FX_DWORD dwEnd = pEndOffSet->GetInteger();
3378         dwEnd += 512;
3379         if ((FX_FILESIZE)dwEnd > m_dwFileLen) {
3380             dwEnd = (FX_DWORD)m_dwFileLen;
3381         }
3382         FX_INT32 iStartPos = (FX_INT32)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen);
3383         FX_INT32 iSize = dwEnd > 1024 ? dwEnd - 1024 : 0;
3384         if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) {
3385             pHints->AddSegment(iStartPos, iSize);
3386             bNeedDownLoad = TRUE;
3387         }
3388     }
3389     m_dwLastXRefOffset = 0;
3390     FX_FILESIZE dwFileLen = 0;
3391     if (pXRefOffset->GetType() == PDFOBJ_NUMBER) {
3392         m_dwLastXRefOffset = pXRefOffset->GetInteger();
3393     }
3394     if (pFileLen->GetType() == PDFOBJ_NUMBER) {
3395         dwFileLen = pFileLen->GetInteger();
3396     }
3397     if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, (FX_DWORD)(dwFileLen - m_dwLastXRefOffset))) {
3398         if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE)     {
3399             FX_DWORD dwSize = (FX_DWORD)(dwFileLen - m_dwLastXRefOffset);
3400             FX_FILESIZE offset = m_dwLastXRefOffset;
3401             if (dwSize < 512 && dwFileLen > 512) {
3402                 dwSize = 512;
3403                 offset = dwFileLen - 512;
3404             }
3405             pHints->AddSegment(offset, dwSize);
3406         }
3407     } else {
3408         m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
3409     }
3410     if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
3411         m_docStatus = PDF_DATAAVAIL_DONE;
3412         return TRUE;
3413     }
3414     m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
3415     return FALSE;
3416 }
3417 CPDF_Object     * CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD objnum)
3418 {
3419     FX_FILESIZE SavedPos = m_syntaxParser.SavePos();
3420     m_syntaxParser.RestorePos(pos);
3421     FX_BOOL bIsNumber;
3422     CFX_ByteString word = m_syntaxParser.GetNextWord(bIsNumber);
3423     if (!bIsNumber) {
3424         return NULL;
3425     }
3426     FX_DWORD real_objnum = FXSYS_atoi(word);
3427     if (objnum && real_objnum != objnum) {
3428         return NULL;
3429     }
3430     word = m_syntaxParser.GetNextWord(bIsNumber);
3431     if (!bIsNumber) {
3432         return NULL;
3433     }
3434     FX_DWORD gennum = FXSYS_atoi(word);
3435     if (m_syntaxParser.GetKeyword() != FX_BSTRC("obj")) {
3436         m_syntaxParser.RestorePos(SavedPos);
3437         return NULL;
3438     }
3439     CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0);
3440     m_syntaxParser.RestorePos(SavedPos);
3441     return pObj;
3442 }
3443 FX_INT32 CPDF_DataAvail::IsLinearizedPDF()
3444 {
3445     FX_DWORD req_size = 1024;
3446     if (!m_pFileAvail->IsDataAvail(0, req_size)) {
3447         return PDF_UNKNOW_LINEARIZED;
3448     }
3449     if (!m_pFileRead) {
3450         return PDF_NOT_LINEARIZED;
3451     }
3452     FX_FILESIZE dwSize = m_pFileRead->GetSize();
3453     if (dwSize < (FX_FILESIZE)req_size) {
3454         return PDF_UNKNOW_LINEARIZED;
3455     }
3456     FX_BYTE buffer[1024];
3457     m_pFileRead->ReadBlock(buffer, 0, req_size);
3458     if (IsLinearizedFile(buffer, req_size)) {
3459         return PDF_IS_LINEARIZED;
3460     }
3461     return PDF_NOT_LINEARIZED;
3462 }
3463 FX_BOOL CPDF_DataAvail::IsLinearizedFile(FX_LPBYTE pData, FX_DWORD dwLen)
3464 {
3465     CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE));
3466     FX_INT32 offset = GetHeaderOffset((IFX_FileStream*)file);
3467     if (offset == -1) {
3468         m_docStatus = PDF_DATAAVAIL_ERROR;
3469         return FALSE;
3470     }
3471     m_dwHeaderOffset = offset;
3472     m_syntaxParser.InitParser((IFX_FileStream*)file, offset);
3473     m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9);
3474     FX_BOOL bNumber = FALSE;
3475     FX_FILESIZE dwSavePos = m_syntaxParser.SavePos();
3476     CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(bNumber);
3477     if (!bNumber) {
3478         return FALSE;
3479     }
3480     FX_DWORD objnum = FXSYS_atoi(wordObjNum);
3481     if (m_pLinearized) {
3482         m_pLinearized->Release();
3483         m_pLinearized = NULL;
3484     }
3485     m_pLinearized = ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum);
3486     if (!m_pLinearized) {
3487         return FALSE;
3488     }
3489     if (m_pLinearized->GetDict() && m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
3490         CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
3491         if (!pLen) {
3492             return FALSE;
3493         }
3494         if ((FX_FILESIZE)pLen->GetInteger() != m_pFileRead->GetSize()) {
3495             return FALSE;
3496         }
3497         m_bLinearized = TRUE;
3498         CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
3499         if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
3500             m_dwFirstPageNo = pNo->GetInteger();
3501         }
3502         return TRUE;
3503     }
3504     return FALSE;
3505 }
3506 FX_BOOL CPDF_DataAvail::CheckEnd(IFX_DownloadHints* pHints)
3507 {
3508     FX_DWORD req_pos = (FX_DWORD)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0);
3509     FX_DWORD dwSize = (FX_DWORD)(m_dwFileLen - req_pos);
3510     if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) {
3511         FX_BYTE buffer[1024];
3512         m_pFileRead->ReadBlock(buffer, req_pos, dwSize);
3513         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE));
3514         m_syntaxParser.InitParser((IFX_FileStream*)file, 0);
3515         m_syntaxParser.RestorePos(dwSize - 1);
3516         if (m_syntaxParser.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, dwSize)) {
3517             FX_BOOL bNumber;
3518             m_syntaxParser.GetNextWord(bNumber);
3519             CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(bNumber);
3520             if (!bNumber) {
3521                 m_docStatus = PDF_DATAAVAIL_ERROR;
3522                 return FALSE;
3523             }
3524             m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
3525             if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) {
3526                 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3527                 return TRUE;
3528             }
3529             m_dwLastXRefOffset = m_dwXRefOffset;
3530             SetStartOffset(m_dwXRefOffset);
3531             m_docStatus = PDF_DATAAVAIL_CROSSREF;
3532             return TRUE;
3533         } else {
3534             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3535             return TRUE;
3536         }
3537     }
3538     pHints->AddSegment(req_pos, dwSize);
3539     return FALSE;
3540 }
3541 FX_DWORD CPDF_DataAvail::CheckCrossRefStream(IFX_DownloadHints* pHints, FX_FILESIZE &xref_offset)
3542 {
3543     xref_offset = 0;
3544     FX_DWORD req_size = (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
3545     if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) {
3546         FX_INT32 iSize = (FX_INT32)(m_Pos + req_size - m_dwCurrentXRefSteam);
3547         CFX_BinaryBuf buf(iSize);
3548         FX_LPBYTE pBuf = buf.GetBuffer();
3549         m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize);
3550         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
3551         m_parser.m_Syntax.InitParser((IFX_FileStream*)file, 0);
3552         FX_BOOL bNumber = FALSE;
3553         FX_FILESIZE dwSavePos = m_parser.m_Syntax.SavePos();
3554         CFX_ByteString objnum = m_parser.m_Syntax.GetNextWord(bNumber);
3555         if (!bNumber) {
3556             return -1;
3557         }
3558         FX_DWORD objNum = FXSYS_atoi(objnum);
3559         CPDF_Object *pObj = m_parser.ParseIndirectObjectAt(NULL, 0, objNum, NULL);
3560         if (!pObj) {
3561             m_Pos += m_parser.m_Syntax.SavePos();
3562             return 0;
3563         }
3564         CPDF_Dictionary* pDict = pObj->GetDict();
3565         CPDF_Object *pName = pDict ? pDict->GetElement(FX_BSTRC("Type")) : NULL;
3566         if (pName && pName->GetType() == PDFOBJ_NAME) {
3567             if (pName->GetString() == FX_BSTRC("XRef")) {
3568                 m_Pos += m_parser.m_Syntax.SavePos();
3569                 xref_offset = pObj->GetDict()->GetInteger(FX_BSTRC("Prev"));
3570                 pObj->Release();