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