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