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