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