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