7c3253f2df2ee3247fe9bd374dc1ba318f67f877
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_parser.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4  
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../../include/fpdfapi/fpdf_parser.h"
8 #include "../../../include/fpdfapi/fpdf_module.h"
9 #include "../../../include/fpdfapi/fpdf_page.h"
10 #include "../../../src/fxcrt/fx_safe_types.h"
11 #include "../fpdf_page/pageint.h"
12 #include <utility>
13 #include <vector>
14
15 FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict)
16 {
17     CPDF_Object* pType = pDict->GetElementValue(FX_BSTRC("Type"));
18     if (!pType) {
19         pType = pDict->GetElementValue(FX_BSTRC("FT"));
20         if (!pType) {
21             return FALSE;
22         }
23     }
24     if (pType->GetString() == FX_BSTRC("Sig")) {
25         return TRUE;
26     }
27     return FALSE;
28 }
29 static int _CompareFileSize(const void* p1, const void* p2)
30 {
31     FX_FILESIZE ret = (*(FX_FILESIZE*)p1) - (*(FX_FILESIZE*)p2);
32     if (ret > 0) {
33         return 1;
34     }
35     if (ret < 0) {
36         return -1;
37     }
38     return 0;
39 }
40
41 CPDF_Parser::CPDF_Parser()
42 {
43     m_pDocument = NULL;
44     m_pTrailer = NULL;
45     m_pEncryptDict = NULL;
46     m_pSecurityHandler = NULL;
47     m_pLinearized = NULL;
48     m_dwFirstPageNo = 0;
49     m_dwXrefStartObjNum = 0;
50     m_bOwnFileRead = TRUE;
51     m_FileVersion = 0;
52     m_bForceUseSecurityHandler = FALSE;
53 }
54 CPDF_Parser::~CPDF_Parser()
55 {
56     CloseParser(FALSE);
57 }
58 FX_DWORD CPDF_Parser::GetLastObjNum()
59 {
60     FX_DWORD dwSize = m_CrossRef.GetSize();
61     return dwSize ? dwSize - 1 : 0;
62 }
63 void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict)
64 {
65     m_pEncryptDict = pDict;
66 }
67 void CPDF_Parser::CloseParser(FX_BOOL bReParse)
68 {
69     m_bVersionUpdated = FALSE;
70     if (m_pDocument && !bReParse) {
71         delete m_pDocument;
72         m_pDocument = NULL;
73     }
74     if (m_pTrailer) {
75         m_pTrailer->Release();
76         m_pTrailer = NULL;
77     }
78     ReleaseEncryptHandler();
79     SetEncryptDictionary(NULL);
80     if (m_bOwnFileRead && m_Syntax.m_pFileAccess) {
81         m_Syntax.m_pFileAccess->Release();
82         m_Syntax.m_pFileAccess = NULL;
83     }
84     FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
85     while (pos) {
86         FX_LPVOID objnum;
87         CPDF_StreamAcc* pStream;
88         m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
89         delete pStream;
90     }
91     m_ObjectStreamMap.RemoveAll();
92     m_SortedOffset.RemoveAll();
93     m_CrossRef.RemoveAll();
94     m_V5Type.RemoveAll();
95     m_ObjVersion.RemoveAll();
96     FX_INT32 iLen = m_Trailers.GetSize();
97     for (FX_INT32 i = 0; i < iLen; ++i) {
98         if (CPDF_Dictionary* trailer = m_Trailers.GetAt(i))
99             trailer->Release();
100     }
101     m_Trailers.RemoveAll();
102     if (m_pLinearized) {
103         m_pLinearized->Release();
104         m_pLinearized = NULL;
105     }
106 }
107 static FX_INT32 GetHeaderOffset(IFX_FileRead* pFile)
108 {
109     FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025);
110     FX_BYTE buf[4];
111     FX_INT32 offset = 0;
112     while (1) {
113         if (!pFile->ReadBlock(buf, offset, 4)) {
114             return -1;
115         }
116         if (*(FX_DWORD*)buf == tag) {
117             return offset;
118         }
119         offset ++;
120         if (offset > 1024) {
121             return -1;
122         }
123     }
124     return -1;
125 }
126 FX_DWORD CPDF_Parser::StartParse(FX_LPCSTR filename, FX_BOOL bReParse)
127 {
128     IFX_FileRead* pFileAccess = FX_CreateFileRead(filename);
129     if (!pFileAccess) {
130         return PDFPARSE_ERROR_FILE;
131     }
132     return StartParse(pFileAccess, bReParse);
133 }
134 FX_DWORD CPDF_Parser::StartParse(FX_LPCWSTR filename, FX_BOOL bReParse)
135 {
136     IFX_FileRead* pFileAccess = FX_CreateFileRead(filename);
137     if (!pFileAccess) {
138         return PDFPARSE_ERROR_FILE;
139     }
140     return StartParse(pFileAccess, bReParse);
141 }
142 CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler();
143 CPDF_SecurityHandler* FPDF_CreatePubKeyHandler(void*);
144 FX_DWORD CPDF_Parser::StartParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead)
145 {
146     CloseParser(bReParse);
147     m_bXRefStream = FALSE;
148     m_LastXRefOffset = 0;
149     m_bOwnFileRead = bOwnFileRead;
150     FX_INT32 offset = GetHeaderOffset(pFileAccess);
151     if (offset == -1) {
152         if (bOwnFileRead && pFileAccess) {
153             pFileAccess->Release();
154         }
155         return PDFPARSE_ERROR_FORMAT;
156     }
157     m_Syntax.InitParser(pFileAccess, offset);
158     FX_BYTE ch;
159     if (!m_Syntax.GetCharAt(5, ch)) {
160         return PDFPARSE_ERROR_FORMAT;
161     }
162     if (ch >= '0' && ch <= '9') {
163         m_FileVersion = (ch - '0') * 10;
164     }
165     if (!m_Syntax.GetCharAt(7, ch)) {
166         return PDFPARSE_ERROR_FORMAT;
167     }
168     if (ch >= '0' && ch <= '9') {
169         m_FileVersion += ch - '0';
170     }
171     if (m_Syntax.m_FileLen <  m_Syntax.m_HeaderOffset + 9) {
172         return PDFPARSE_ERROR_FORMAT;
173     }
174     m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9);
175     if (!bReParse) {
176         m_pDocument = FX_NEW CPDF_Document(this);
177     }
178     FX_BOOL bXRefRebuilt = FALSE;
179     if (m_Syntax.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, 4096)) {
180         FX_FILESIZE startxref_offset = m_Syntax.SavePos();
181         FX_LPVOID pResult = FXSYS_bsearch(&startxref_offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
182         if (pResult == NULL) {
183             m_SortedOffset.Add(startxref_offset);
184         }
185         m_Syntax.GetKeyword();
186         FX_BOOL bNumber;
187         CFX_ByteString xrefpos_str = m_Syntax.GetNextWord(bNumber);
188         if (!bNumber) {
189             return PDFPARSE_ERROR_FORMAT;
190         }
191         m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
192         if (!LoadAllCrossRefV4(m_LastXRefOffset) && !LoadAllCrossRefV5(m_LastXRefOffset)) {
193             if (!RebuildCrossRef()) {
194                 return PDFPARSE_ERROR_FORMAT;
195             }
196             bXRefRebuilt = TRUE;
197             m_LastXRefOffset = 0;
198         }
199     } else {
200         if (!RebuildCrossRef()) {
201             return PDFPARSE_ERROR_FORMAT;
202         }
203         bXRefRebuilt = TRUE;
204     }
205     FX_DWORD dwRet = SetEncryptHandler();
206     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
207         return dwRet;
208     }
209     m_pDocument->LoadDoc();
210     if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
211         if (bXRefRebuilt) {
212             return PDFPARSE_ERROR_FORMAT;
213         }
214         ReleaseEncryptHandler();
215         if (!RebuildCrossRef()) {
216             return PDFPARSE_ERROR_FORMAT;
217         }
218         dwRet = SetEncryptHandler();
219         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
220             return dwRet;
221         }
222         m_pDocument->LoadDoc();
223         if (m_pDocument->GetRoot() == NULL) {
224             return PDFPARSE_ERROR_FORMAT;
225         }
226     }
227     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
228     FX_DWORD RootObjNum = GetRootObjNum();
229     if (RootObjNum == 0) {
230         ReleaseEncryptHandler();
231         RebuildCrossRef();
232         RootObjNum = GetRootObjNum();
233         if (RootObjNum == 0) {
234             return PDFPARSE_ERROR_FORMAT;
235         }
236         dwRet = SetEncryptHandler();
237         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
238             return dwRet;
239         }
240     }
241     if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) {
242         CPDF_Reference* pMetadata = (CPDF_Reference*)m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
243         if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
244             m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum();
245         }
246     }
247     return PDFPARSE_ERROR_SUCCESS;
248 }
249 FX_DWORD CPDF_Parser::SetEncryptHandler()
250 {
251     ReleaseEncryptHandler();
252     SetEncryptDictionary(NULL);
253     if (m_pTrailer == NULL) {
254         return PDFPARSE_ERROR_FORMAT;
255     }
256     CPDF_Object* pEncryptObj = m_pTrailer->GetElement(FX_BSTRC("Encrypt"));
257     if (pEncryptObj) {
258         if (pEncryptObj->GetType() == PDFOBJ_DICTIONARY) {
259             SetEncryptDictionary((CPDF_Dictionary*)pEncryptObj);
260         } else if (pEncryptObj->GetType() == PDFOBJ_REFERENCE) {
261             pEncryptObj = m_pDocument->GetIndirectObject(((CPDF_Reference*)pEncryptObj)->GetRefObjNum());
262             if (pEncryptObj) {
263                 SetEncryptDictionary(pEncryptObj->GetDict());
264             }
265         }
266     }
267     if (m_bForceUseSecurityHandler) {
268         FX_DWORD err = PDFPARSE_ERROR_HANDLER;
269         if (m_pSecurityHandler == NULL) {
270             return PDFPARSE_ERROR_HANDLER;
271         }
272         if (!m_pSecurityHandler->OnInit(this, m_pEncryptDict)) {
273             return err;
274         }
275         CPDF_CryptoHandler* pCryptoHandler = m_pSecurityHandler->CreateCryptoHandler();
276         if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) {
277             delete pCryptoHandler;
278             pCryptoHandler = NULL;
279             return PDFPARSE_ERROR_HANDLER;
280         }
281         m_Syntax.SetEncrypt(pCryptoHandler);
282     } else if (m_pEncryptDict) {
283         CFX_ByteString filter = m_pEncryptDict->GetString(FX_BSTRC("Filter"));
284         CPDF_SecurityHandler* pSecurityHandler = NULL;
285         FX_DWORD err = PDFPARSE_ERROR_HANDLER;
286         if (filter == FX_BSTRC("Standard")) {
287             pSecurityHandler = FPDF_CreateStandardSecurityHandler();
288             err = PDFPARSE_ERROR_PASSWORD;
289         }
290         if (pSecurityHandler == NULL) {
291             return PDFPARSE_ERROR_HANDLER;
292         }
293         if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) {
294             delete pSecurityHandler;
295             pSecurityHandler = NULL;
296             return err;
297         }
298         m_pSecurityHandler = pSecurityHandler;
299         CPDF_CryptoHandler* pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
300         if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler)) {
301             delete pCryptoHandler;
302             pCryptoHandler = NULL;
303             return PDFPARSE_ERROR_HANDLER;
304         }
305         m_Syntax.SetEncrypt(pCryptoHandler);
306     }
307     return PDFPARSE_ERROR_SUCCESS;
308 }
309 void CPDF_Parser::ReleaseEncryptHandler()
310 {
311     if (m_Syntax.m_pCryptoHandler) {
312         delete m_Syntax.m_pCryptoHandler;
313         m_Syntax.m_pCryptoHandler = NULL;
314     }
315     if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
316         delete m_pSecurityHandler;
317         m_pSecurityHandler = NULL;
318     }
319 }
320 FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum)
321 {
322     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
323         return 0;
324     }
325     if (m_V5Type[objnum] == 1) {
326         return m_CrossRef[objnum];
327     }
328     if (m_V5Type[objnum] == 2) {
329         return m_CrossRef[(FX_INT32)m_CrossRef[objnum]];
330     }
331     return 0;
332 }
333 static FX_INT32 GetDirectInteger(CPDF_Dictionary* pDict, FX_BSTR key)
334 {
335     CPDF_Object* pObj = pDict->GetElement(key);
336     if (pObj == NULL) {
337         return 0;
338     }
339     if (pObj->GetType() == PDFOBJ_NUMBER) {
340         return ((CPDF_Number*)pObj)->GetInteger();
341     }
342     return 0;
343 }
344 static FX_BOOL CheckDirectType(CPDF_Dictionary* pDict, FX_BSTR key, FX_INT32 iType)
345 {
346     CPDF_Object* pObj = pDict->GetElement(key);
347     if (!pObj) {
348         return TRUE;
349     }
350     return pObj->GetType() == iType;
351 }
352 FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos)
353 {
354     if (!LoadCrossRefV4(xrefpos, 0, TRUE, FALSE)) {
355         return FALSE;
356     }
357     m_pTrailer = LoadTrailerV4();
358     if (m_pTrailer == NULL) {
359         return FALSE;
360     }
361     FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
362     if (xrefsize <= 0 || xrefsize > (1 << 20)) {
363         return FALSE;
364     }
365     m_CrossRef.SetSize(xrefsize);
366     m_V5Type.SetSize(xrefsize);
367     CFX_FileSizeArray CrossRefList, XRefStreamList;
368     CrossRefList.Add(xrefpos);
369     XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm")));
370     if (!CheckDirectType(m_pTrailer, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) {
371         return FALSE;
372     }
373     FX_FILESIZE newxrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev"));
374     if (newxrefpos == xrefpos) {
375         return FALSE;
376     }
377     xrefpos = newxrefpos;
378     while (xrefpos) {
379         CrossRefList.InsertAt(0, xrefpos);
380         LoadCrossRefV4(xrefpos, 0, TRUE, FALSE);
381         CPDF_Dictionary* pDict = LoadTrailerV4();
382         if (pDict == NULL) {
383             return FALSE;
384         }
385         if (!CheckDirectType(pDict, FX_BSTRC("Prev"), PDFOBJ_NUMBER)) {
386             pDict->Release();
387             return FALSE;
388         }
389         newxrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev"));
390         if (newxrefpos == xrefpos) {
391             pDict->Release();
392             return FALSE;
393         }
394         xrefpos = newxrefpos;
395         XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm")));
396         m_Trailers.Add(pDict);
397     }
398     for (FX_INT32 i = 0; i < CrossRefList.GetSize(); i ++)
399         if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) {
400             return FALSE;
401         }
402     return TRUE;
403 }
404 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, FX_DWORD dwObjCount)
405 {
406     if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) {
407         return FALSE;
408     }
409     m_pTrailer = LoadTrailerV4();
410     if (m_pTrailer == NULL) {
411         return FALSE;
412     }
413     FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
414     if (xrefsize == 0) {
415         return FALSE;
416     }
417     CFX_FileSizeArray CrossRefList, XRefStreamList;
418     CrossRefList.Add(xrefpos);
419     XRefStreamList.Add(GetDirectInteger(m_pTrailer, FX_BSTRC("XRefStm")));
420     xrefpos = GetDirectInteger(m_pTrailer, FX_BSTRC("Prev"));
421     while (xrefpos) {
422         CrossRefList.InsertAt(0, xrefpos);
423         LoadCrossRefV4(xrefpos, 0, TRUE, FALSE);
424         CPDF_Dictionary* pDict = LoadTrailerV4();
425         if (pDict == NULL) {
426             return FALSE;
427         }
428         xrefpos = GetDirectInteger(pDict, FX_BSTRC("Prev"));
429         XRefStreamList.InsertAt(0, pDict->GetInteger(FX_BSTRC("XRefStm")));
430         m_Trailers.Add(pDict);
431     }
432     for (FX_INT32 i = 1; i < CrossRefList.GetSize(); i ++)
433         if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE, i == 0)) {
434             return FALSE;
435         }
436     return TRUE;
437 }
438 FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, FX_DWORD dwObjCount)
439 {
440     FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset;
441     m_Syntax.RestorePos(dwStartPos);
442     FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
443     if (pResult == NULL) {
444         m_SortedOffset.Add(pos);
445     }
446     FX_DWORD start_objnum = 0;
447     FX_DWORD count = dwObjCount;
448     FX_FILESIZE SavedPos = m_Syntax.SavePos();
449     FX_INT32 recordsize = 20;
450     char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
451     pBuf[1024 * recordsize] = '\0';
452     FX_INT32 nBlocks = count / 1024 + 1;
453     for (FX_INT32 block = 0; block < nBlocks; block ++) {
454         FX_INT32 block_size = block == nBlocks - 1 ? count % 1024 : 1024;
455         FX_DWORD dwReadSize = block_size * recordsize;
456         if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_Syntax.m_FileLen) {
457             FX_Free(pBuf);
458             return FALSE;
459         }
460         if (!m_Syntax.ReadBlock((FX_LPBYTE)pBuf, dwReadSize)) {
461             FX_Free(pBuf);
462             return FALSE;
463         }
464         for (FX_INT32 i = 0; i < block_size; i ++) {
465             FX_DWORD objnum = start_objnum + block * 1024 + i;
466             char* pEntry = pBuf + i * recordsize;
467             if (pEntry[17] == 'f') {
468                 m_CrossRef.SetAtGrow(objnum, 0);
469                 m_V5Type.SetAtGrow(objnum, 0);
470             } else {
471                 FX_INT32 offset = FXSYS_atoi(pEntry);
472                 if (offset == 0) {
473                     for (FX_INT32 c = 0; c < 10; c ++) {
474                         if (pEntry[c] < '0' || pEntry[c] > '9') {
475                             FX_Free(pBuf);
476                             return FALSE;
477                         }
478                     }
479                 }
480                 m_CrossRef.SetAtGrow(objnum, offset);
481                 FX_INT32 version = FXSYS_atoi(pEntry + 11);
482                 if (version >= 1) {
483                     m_bVersionUpdated = TRUE;
484                 }
485                 m_ObjVersion.SetAtGrow(objnum, version);
486                 if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
487                     FX_LPVOID pResult = FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
488                     if (pResult == NULL) {
489                         m_SortedOffset.Add(m_CrossRef[objnum]);
490                     }
491                 }
492                 m_V5Type.SetAtGrow(objnum, 1);
493             }
494         }
495     }
496     FX_Free(pBuf);
497     m_Syntax.RestorePos(SavedPos + count * recordsize);
498     return TRUE;
499 }
500 FX_BOOL CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, FX_FILESIZE streampos, FX_BOOL bSkip, FX_BOOL bFirst)
501 {
502     m_Syntax.RestorePos(pos);
503     if (m_Syntax.GetKeyword() != FX_BSTRC("xref")) {
504         return FALSE;
505     }
506     FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
507     if (pResult == NULL) {
508         m_SortedOffset.Add(pos);
509     }
510     if (streampos) {
511         FX_LPVOID pResult = FXSYS_bsearch(&streampos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
512         if (pResult == NULL) {
513             m_SortedOffset.Add(streampos);
514         }
515     }
516     while (1) {
517         FX_FILESIZE SavedPos = m_Syntax.SavePos();
518         FX_BOOL bIsNumber;
519         CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
520         if (word.IsEmpty()) {
521             return FALSE;
522         }
523         if (!bIsNumber) {
524             m_Syntax.RestorePos(SavedPos);
525             break;
526         }
527         FX_DWORD start_objnum = FXSYS_atoi(word);
528         if (start_objnum >= (1 << 20)) {
529             return FALSE;
530         }
531         FX_DWORD count = m_Syntax.GetDirectNum();
532         m_Syntax.ToNextWord();
533         SavedPos = m_Syntax.SavePos();
534         FX_BOOL bFirstItem = FALSE;
535         FX_INT32 recordsize = 20;
536         if (bFirst) {
537             bFirstItem = TRUE;
538         }
539         m_dwXrefStartObjNum = start_objnum;
540         if (!bSkip) {
541             char* pBuf = FX_Alloc(char, 1024 * recordsize + 1);
542             pBuf[1024 * recordsize] = '\0';
543             FX_INT32 nBlocks = count / 1024 + 1;
544             FX_BOOL bFirstBlock = TRUE;
545             for (FX_INT32 block = 0; block < nBlocks; block ++) {
546                 FX_INT32 block_size = block == nBlocks - 1 ? count % 1024 : 1024;
547                 m_Syntax.ReadBlock((FX_LPBYTE)pBuf, block_size * recordsize);
548                 for (FX_INT32 i = 0; i < block_size; i ++) {
549                     FX_DWORD objnum = start_objnum + block * 1024 + i;
550                     char* pEntry = pBuf + i * recordsize;
551                     if (pEntry[17] == 'f') {
552                         if (bFirstItem) {
553                             objnum = 0;
554                             bFirstItem = FALSE;
555                         }
556                         if (bFirstBlock) {
557                             FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
558                             FX_INT32 version = FXSYS_atoi(pEntry + 11);
559                             if (offset == 0 && version == 65535 && start_objnum != 0) {
560                                 start_objnum--;
561                                 objnum = 0;
562                             }
563                         }
564                         m_CrossRef.SetAtGrow(objnum, 0);
565                         m_V5Type.SetAtGrow(objnum, 0);
566                     } else {
567                         FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
568                         if (offset == 0) {
569                             for (FX_INT32 c = 0; c < 10; c ++) {
570                                 if (pEntry[c] < '0' || pEntry[c] > '9') {
571                                     FX_Free(pBuf);
572                                     return FALSE;
573                                 }
574                             }
575                         }
576                         m_CrossRef.SetAtGrow(objnum, offset);
577                         FX_INT32 version = FXSYS_atoi(pEntry + 11);
578                         if (version >= 1) {
579                             m_bVersionUpdated = TRUE;
580                         }
581                         m_ObjVersion.SetAtGrow(objnum, version);
582                         if (m_CrossRef[objnum] < m_Syntax.m_FileLen) {
583                             FX_LPVOID pResult = FXSYS_bsearch(&m_CrossRef[objnum], m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
584                             if (pResult == NULL) {
585                                 m_SortedOffset.Add(m_CrossRef[objnum]);
586                             }
587                         }
588                         m_V5Type.SetAtGrow(objnum, 1);
589                     }
590                     if (bFirstBlock) {
591                         bFirstBlock = FALSE;
592                     }
593                 }
594             }
595             FX_Free(pBuf);
596         }
597         m_Syntax.RestorePos(SavedPos + count * recordsize);
598     }
599     if (streampos)
600         if (!LoadCrossRefV5(streampos, streampos, FALSE)) {
601             return FALSE;
602         }
603     return TRUE;
604 }
605 FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos)
606 {
607     if (!LoadCrossRefV5(xrefpos, xrefpos, TRUE)) {
608         return FALSE;
609     }
610     while (xrefpos)
611         if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
612             return FALSE;
613         }
614     m_ObjectStreamMap.InitHashTable(101, FALSE);
615     m_bXRefStream = TRUE;
616     return TRUE;
617 }
618 FX_BOOL CPDF_Parser::RebuildCrossRef()
619 {
620     m_CrossRef.RemoveAll();
621     m_V5Type.RemoveAll();
622     m_SortedOffset.RemoveAll();
623     m_ObjVersion.RemoveAll();
624     if (m_pTrailer) {
625         m_pTrailer->Release();
626         m_pTrailer = NULL;
627     }
628     FX_INT32 status = 0;
629     FX_INT32 inside_index = 0;
630     FX_DWORD objnum, gennum;
631     FX_INT32 depth = 0;
632     FX_LPBYTE buffer = FX_Alloc(FX_BYTE, 4096);
633     FX_FILESIZE pos = m_Syntax.m_HeaderOffset;
634     FX_FILESIZE start_pos, start_pos1;
635     FX_FILESIZE last_obj = -1, last_xref = -1, last_trailer = -1;
636     FX_BOOL bInUpdate = FALSE;
637     while (pos < m_Syntax.m_FileLen) {
638         FX_BOOL bOverFlow = FALSE;
639         FX_DWORD size = (FX_DWORD)(m_Syntax.m_FileLen - pos);
640         if (size > 4096) {
641             size = 4096;
642         }
643         if (!m_Syntax.m_pFileAccess->ReadBlock(buffer, pos, size)) {
644             break;
645         }
646         for (FX_DWORD i = 0; i < size; i ++) {
647             FX_BYTE byte = buffer[i];
648             switch (status) {
649                 case 0:
650                     if (PDF_CharType[byte] == 'W') {
651                         status = 1;
652                     }
653                     if (byte <= '9' && byte >= '0') {
654                         --i;
655                         status = 1;
656                     }
657                     if (byte == '%') {
658                         inside_index = 0;
659                         status = 9;
660                     }
661                     if (byte == '(') {
662                         status = 10;
663                         depth = 1;
664                     }
665                     if (byte == '<') {
666                         inside_index = 1;
667                         status = 11;
668                     }
669                     if (byte == '\\') {
670                         status = 13;
671                     }
672                     if (byte == 't') {
673                         status = 7;
674                         inside_index = 1;
675                     }
676                     break;
677                 case 1:
678                     if (PDF_CharType[byte] == 'W') {
679                         break;
680                     } else if (byte <= '9' && byte >= '0') {
681                         start_pos = pos + i;
682                         status = 2;
683                         objnum = byte - '0';
684                     } else if (byte == 't') {
685                         status = 7;
686                         inside_index = 1;
687                     } else if (byte == 'x') {
688                         status = 8;
689                         inside_index = 1;
690                     } else {
691                         --i;
692                         status = 0;
693                     }
694                     break;
695                 case 2:
696                     if (byte <= '9' && byte >= '0') {
697                         objnum = objnum * 10 + byte - '0';
698                         break;
699                     } else if (PDF_CharType[byte] == 'W') {
700                         status = 3;
701                     } else {
702                         --i;
703                         status = 14;
704                         inside_index = 0;
705                     }
706                     break;
707                 case 3:
708                     if (byte <= '9' && byte >= '0') {
709                         start_pos1 = pos + i;
710                         status = 4;
711                         gennum = byte - '0';
712                     } else if (PDF_CharType[byte] == 'W') {
713                         break;
714                     } else if (byte == 't') {
715                         status = 7;
716                         inside_index = 1;
717                     } else {
718                         --i;
719                         status = 0;
720                     }
721                     break;
722                 case 4:
723                     if (byte <= '9' && byte >= '0') {
724                         gennum = gennum * 10 + byte - '0';
725                         break;
726                     } else if (PDF_CharType[byte] == 'W') {
727                         status = 5;
728                     } else {
729                         --i;
730                         status = 0;
731                     }
732                     break;
733                 case 5:
734                     if (byte == 'o') {
735                         status = 6;
736                         inside_index = 1;
737                     } else if (PDF_CharType[byte] == 'W') {
738                         break;
739                     } else if (byte <= '9' && byte >= '0') {
740                         objnum = gennum;
741                         gennum = byte - '0';
742                         start_pos = start_pos1;
743                         start_pos1 = pos + i;
744                         status = 4;
745                     } else if (byte == 't') {
746                         status = 7;
747                         inside_index = 1;
748                     } else {
749                         --i;
750                         status = 0;
751                     }
752                     break;
753                 case 6:
754                     switch (inside_index) {
755                         case 1:
756                             if (byte != 'b') {
757                                 --i;
758                                 status = 0;
759                             } else {
760                                 inside_index ++;
761                             }
762                             break;
763                         case 2:
764                             if (byte != 'j') {
765                                 --i;
766                                 status = 0;
767                             } else {
768                                 inside_index ++;
769                             }
770                             break;
771                         case 3:
772                             if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') {
773                                 if (objnum > 0x1000000) {
774                                     status = 0;
775                                     break;
776                                 }
777                                 FX_FILESIZE obj_pos = start_pos - m_Syntax.m_HeaderOffset;
778                                 last_obj = start_pos;
779                                 FX_LPVOID pResult = FXSYS_bsearch(&obj_pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
780                                 if (pResult == NULL) {
781                                     m_SortedOffset.Add(obj_pos);
782                                 }
783                                 FX_FILESIZE obj_end = 0;
784                                 CPDF_Object *pObject = ParseIndirectObjectAtByStrict(m_pDocument, obj_pos, objnum, NULL, &obj_end);
785                                 if (pObject) {
786                                     int iType = pObject->GetType();
787                                     if (iType == PDFOBJ_STREAM) {
788                                         CPDF_Stream* pStream = (CPDF_Stream*)pObject;
789                                         CPDF_Dictionary* pDict = pStream->GetDict();
790                                         if (pDict) {
791                                             if (pDict->KeyExist(FX_BSTRC("Type"))) {
792                                                 CFX_ByteString bsValue = pDict->GetString(FX_BSTRC("Type"));
793                                                 if (bsValue == FX_BSTRC("XRef") && pDict->KeyExist(FX_BSTRC("Size"))) {
794                                                     CPDF_Object* pRoot = pDict->GetElement(FX_BSTRC("Root"));
795                                                     if (pRoot && pRoot->GetDict() && pRoot->GetDict()->GetElement(FX_BSTRC("Pages"))) {
796                                                         if (m_pTrailer) {
797                                                             m_pTrailer->Release();
798                                                         }
799                                                         m_pTrailer = (CPDF_Dictionary*)pDict->Clone();
800                                                     }
801                                                 }
802                                             }
803                                         }
804                                     }
805                                 }
806                                 FX_FILESIZE offset = 0;
807                                 m_Syntax.RestorePos(obj_pos);
808                                 offset = m_Syntax.FindTag(FX_BSTRC("obj"), 0);
809                                 if (offset == -1) {
810                                     offset = 0;
811                                 } else {
812                                     offset += 3;
813                                 }
814                                 FX_FILESIZE nLen = obj_end - obj_pos - offset;
815                                 if ((FX_DWORD)nLen > size - i) {
816                                     pos = obj_end + m_Syntax.m_HeaderOffset;
817                                     bOverFlow = TRUE;
818                                 } else {
819                                     i += (FX_DWORD)nLen;
820                                 }
821                                 if (m_CrossRef.GetSize() > (FX_INT32)objnum && m_CrossRef[objnum]) {
822                                     if (pObject) {
823                                         FX_DWORD oldgen = m_ObjVersion.GetAt(objnum);
824                                         m_CrossRef[objnum] = obj_pos;
825                                         m_ObjVersion.SetAt(objnum, (FX_SHORT)gennum);
826                                         if (oldgen != gennum) {
827                                             m_bVersionUpdated = TRUE;
828                                         }
829                                     }
830                                 } else {
831                                     m_CrossRef.SetAtGrow(objnum, obj_pos);
832                                     m_V5Type.SetAtGrow(objnum, 1);
833                                     m_ObjVersion.SetAtGrow(objnum, (FX_SHORT)gennum);
834                                 }
835                                 if (pObject) {
836                                     pObject->Release();
837                                 }
838                             }
839                             --i;
840                             status = 0;
841                             break;
842                     }
843                     break;
844                 case 7:
845                     if (inside_index == 7) {
846                         if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') {
847                             last_trailer = pos + i - 7;
848                             m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset);
849                             CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
850                             if (pObj) {
851                                 if (pObj->GetType() != PDFOBJ_DICTIONARY && pObj->GetType() != PDFOBJ_STREAM) {
852                                     pObj->Release();
853                                 } else {
854                                     CPDF_Dictionary* pTrailer = NULL;
855                                     if (pObj->GetType() == PDFOBJ_STREAM) {
856                                         pTrailer = ((CPDF_Stream*)pObj)->GetDict();
857                                     } else {
858                                         pTrailer = (CPDF_Dictionary*)pObj;
859                                     }
860                                     if (pTrailer) {
861                                         if (m_pTrailer) {
862                                             CPDF_Object* pRoot = pTrailer->GetElement(FX_BSTRC("Root"));
863                                             if (pRoot == NULL || (pRoot->GetType() == PDFOBJ_REFERENCE &&
864                                                                   (FX_DWORD)m_CrossRef.GetSize() > ((CPDF_Reference*)pRoot)->GetRefObjNum() &&
865                                                                   m_CrossRef.GetAt(((CPDF_Reference*)pRoot)->GetRefObjNum()) != 0)) {
866                                                 FX_POSITION pos = pTrailer->GetStartPos();
867                                                 while (pos) {
868                                                     CFX_ByteString key;
869                                                     CPDF_Object* pObj = pTrailer->GetNextElement(pos, key);
870                                                     m_pTrailer->SetAt(key, pObj->Clone(), m_pDocument);
871                                                 }
872                                                 pObj->Release();
873                                             } else {
874                                                 pObj->Release();
875                                             }
876                                         } else {
877                                             if (pObj->GetType() == PDFOBJ_STREAM) {
878                                                 m_pTrailer = (CPDF_Dictionary*)pTrailer->Clone();
879                                                 pObj->Release();
880                                             } else {
881                                                 m_pTrailer = pTrailer;
882                                             }
883                                             FX_FILESIZE dwSavePos = m_Syntax.SavePos();
884                                             CFX_ByteString strWord = m_Syntax.GetKeyword();
885                                             if (!strWord.Compare(FX_BSTRC("startxref"))) {
886                                                 FX_BOOL bNumber = FALSE;
887                                                 CFX_ByteString bsOffset = m_Syntax.GetNextWord(bNumber);
888                                                 if (bNumber) {
889                                                     m_LastXRefOffset = FXSYS_atoi(bsOffset);
890                                                 }
891                                             }
892                                             m_Syntax.RestorePos(dwSavePos);
893                                         }
894                                     } else {
895                                         pObj->Release();
896                                     }
897                                     bInUpdate = TRUE;
898                                 }
899                             }
900                         }
901                         --i;
902                         status = 0;
903                     } else if (byte == "trailer"[inside_index]) {
904                         inside_index ++;
905                     } else {
906                         --i;
907                         status = 0;
908                     }
909                     break;
910                 case 8:
911                     if (inside_index == 4) {
912                         last_xref = pos + i - 4;
913                         status = 1;
914                     } else if (byte == "xref"[inside_index]) {
915                         inside_index ++;
916                     } else {
917                         --i;
918                         status = 0;
919                     }
920                     break;
921                 case 9:
922                     if (byte == '\r' || byte == '\n') {
923                         status = 0;
924                     }
925                     break;
926                 case 10:
927                     if (byte == ')') {
928                         if (depth > 0) {
929                             depth--;
930                         }
931                     } else if (byte == '(') {
932                         depth++;
933                     }
934                     if (!depth) {
935                         status = 0;
936                     }
937                     break;
938                 case 11:
939                     if (byte == '<' && inside_index == 1) {
940                         status = 12;
941                     } else if (byte == '>') {
942                         status = 0;
943                     }
944                     inside_index = 0;
945                     break;
946                 case 12:
947                     --i;
948                     status = 0;
949                     break;
950                 case 13:
951                     if (PDF_CharType[byte] == 'D' || PDF_CharType[byte] == 'W') {
952                         --i;
953                         status = 0;
954                     }
955                     break;
956                 case 14:
957                     if (PDF_CharType[byte] == 'W') {
958                         status = 0;
959                     } else if (byte == '%' || byte == '(' || byte == '<' || byte == '\\') {
960                         status = 0;
961                         --i;
962                     } else if (inside_index == 6) {
963                         status = 0;
964                         --i;
965                     } else if (byte == "endobj"[inside_index]) {
966                         inside_index++;
967                     }
968                     break;
969             }
970             if (bOverFlow) {
971                 size = 0;
972                 break;
973             }
974         }
975         pos += size;
976     }
977     if (last_xref != -1 && last_xref > last_obj) {
978         last_trailer = last_xref;
979     } else if (last_trailer == -1 || last_xref < last_obj) {
980         last_trailer = m_Syntax.m_FileLen;
981     }
982     FX_FILESIZE offset = last_trailer - m_Syntax.m_HeaderOffset;
983     FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
984     if (pResult == NULL) {
985         m_SortedOffset.Add(offset);
986     }
987     FX_Free(buffer);
988     return TRUE;
989 }
990 static FX_DWORD _GetVarInt(FX_LPCBYTE p, FX_INT32 n)
991 {
992     FX_DWORD result = 0;
993     for (FX_INT32 i = 0; i < n; i ++) {
994         result = result * 256 + p[i];
995     }
996     return result;
997 }
998 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE pos, FX_FILESIZE& prev, FX_BOOL bMainXRef)
999 {
1000     CPDF_Stream* pStream = (CPDF_Stream*)ParseIndirectObjectAt(m_pDocument, pos, 0, NULL);
1001     if (!pStream) {
1002         return FALSE;
1003     }
1004     if (m_pDocument) {
1005         CPDF_Dictionary * pDict = m_pDocument->GetRoot();
1006         if (!pDict || pDict->GetObjNum() != pStream->m_ObjNum) {
1007             m_pDocument->InsertIndirectObject(pStream->m_ObjNum, pStream);
1008         } else {
1009             if (pStream->GetType() == PDFOBJ_STREAM) {
1010                 pStream->Release();
1011             }
1012             return FALSE;
1013         }
1014     }
1015     if (pStream->GetType() != PDFOBJ_STREAM) {
1016         return FALSE;
1017     }
1018     prev = pStream->GetDict()->GetInteger(FX_BSTRC("Prev"));
1019     FX_INT32 size = pStream->GetDict()->GetInteger(FX_BSTRC("Size"));
1020     if (size < 0) {
1021         pStream->Release();
1022         return FALSE;
1023     }
1024     if (bMainXRef) {
1025         m_pTrailer = (CPDF_Dictionary*)pStream->GetDict()->Clone();
1026         m_CrossRef.SetSize(size);
1027         if (m_V5Type.SetSize(size)) {
1028             FXSYS_memset32(m_V5Type.GetData(), 0, size);
1029         }
1030     } else {
1031         m_Trailers.Add((CPDF_Dictionary*)pStream->GetDict()->Clone());
1032     }
1033     std::vector<std::pair<FX_INT32, FX_INT32> > arrIndex;
1034     CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
1035     if (pArray) {
1036         FX_DWORD nPairSize = pArray->GetCount() / 2;
1037         for (FX_DWORD i = 0; i < nPairSize; i++) {
1038             CPDF_Object* pStartNumObj = pArray->GetElement(i * 2);
1039             CPDF_Object* pCountObj = pArray->GetElement(i * 2 + 1);
1040             if (pStartNumObj && pStartNumObj->GetType() == PDFOBJ_NUMBER
1041                 && pCountObj && pCountObj->GetType() == PDFOBJ_NUMBER) {
1042                 int nStartNum = pStartNumObj->GetInteger();
1043                 int nCount = pCountObj->GetInteger();
1044                 if (nStartNum >= 0 && nCount > 0) {
1045                     arrIndex.push_back(std::make_pair(nStartNum, nCount));
1046                 }
1047             }
1048         }
1049     }
1050     if (arrIndex.size() == 0) {
1051         arrIndex.push_back(std::make_pair(0, size));
1052     }
1053     pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
1054     if (pArray == NULL) {
1055         pStream->Release();
1056         return FALSE;
1057     }
1058     CFX_DWordArray WidthArray;
1059     FX_SAFE_DWORD dwAccWidth = 0;
1060     for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
1061         WidthArray.Add(pArray->GetInteger(i));
1062         dwAccWidth += WidthArray[i];
1063     }
1064     if (!dwAccWidth.IsValid() || WidthArray.GetSize() < 3) {
1065         pStream->Release();
1066         return FALSE;
1067     }
1068     FX_DWORD totalWidth = dwAccWidth.ValueOrDie();
1069     CPDF_StreamAcc acc;
1070     acc.LoadAllData(pStream);
1071     FX_LPCBYTE pData = acc.GetData();
1072     FX_DWORD dwTotalSize = acc.GetSize();
1073     FX_DWORD segindex = 0;
1074     for (FX_DWORD i = 0; i < arrIndex.size(); i ++) {
1075         FX_INT32 startnum = arrIndex[i].first;
1076         if (startnum < 0) {
1077             continue;
1078         }
1079         m_dwXrefStartObjNum = pdfium::base::checked_cast<FX_DWORD, FX_INT32> (startnum);
1080         FX_DWORD count = pdfium::base::checked_cast<FX_DWORD, FX_INT32> (arrIndex[i].second);
1081         FX_SAFE_DWORD dwCaculatedSize = segindex;
1082         dwCaculatedSize += count;
1083         dwCaculatedSize *= totalWidth;
1084         if (!dwCaculatedSize.IsValid() || dwCaculatedSize.ValueOrDie() > dwTotalSize) { 
1085             continue;
1086         }
1087         FX_LPCBYTE segstart = pData + segindex * totalWidth;
1088         FX_SAFE_DWORD dwMaxObjNum = startnum;
1089         dwMaxObjNum += count;
1090         FX_DWORD dwV5Size = pdfium::base::checked_cast<FX_DWORD, FX_INT32> (m_V5Type.GetSize());
1091         if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size) {
1092             continue;
1093         }
1094         for (FX_DWORD j = 0; j < count; j ++) {
1095             FX_INT32 type = 1;
1096             FX_LPCBYTE entrystart = segstart + j * totalWidth;
1097             if (WidthArray[0]) {
1098                 type = _GetVarInt(entrystart, WidthArray[0]);
1099             }
1100             if (m_V5Type[startnum + j] == 255) {
1101                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1102                 m_CrossRef[startnum + j] = offset;
1103                 FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1104                 if (pResult == NULL) {
1105                     m_SortedOffset.Add(offset);
1106                 }
1107                 continue;
1108             }
1109             if (m_V5Type[startnum + j]) {
1110                 continue;
1111             }
1112             m_V5Type[startnum + j] = type;
1113             if (type == 0) {
1114                 m_CrossRef[startnum + j] = 0;
1115             } else {
1116                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1117                 m_CrossRef[startnum + j] = offset;
1118                 if (type == 1) {
1119                     FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1120                     if (pResult == NULL) {
1121                         m_SortedOffset.Add(offset);
1122                     }
1123                 } else {
1124                     if (offset < 0 || offset >= m_V5Type.GetSize()) {
1125                         pStream->Release();
1126                         return FALSE;
1127                     }
1128                     m_V5Type[offset] = 255;
1129                 }
1130             }
1131         }
1132         segindex += count;
1133     }
1134     pStream->Release();
1135     return TRUE;
1136 }
1137 CPDF_Array* CPDF_Parser::GetIDArray()
1138 {
1139     CPDF_Object* pID = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("ID")) : NULL;
1140     if (pID == NULL) {
1141         return NULL;
1142     }
1143     if (pID->GetType() == PDFOBJ_REFERENCE) {
1144         pID = ParseIndirectObject(NULL, ((CPDF_Reference*)pID)->GetRefObjNum());
1145         m_pTrailer->SetAt(FX_BSTRC("ID"), pID);
1146     }
1147     if (pID == NULL || pID->GetType() != PDFOBJ_ARRAY) {
1148         return NULL;
1149     }
1150     return (CPDF_Array*)pID;
1151 }
1152 FX_DWORD CPDF_Parser::GetRootObjNum()
1153 {
1154     CPDF_Object* pRef = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Root")) : NULL;
1155     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1156         return 0;
1157     }
1158     return ((CPDF_Reference*) pRef)->GetRefObjNum();
1159 }
1160 FX_DWORD CPDF_Parser::GetInfoObjNum()
1161 {
1162     CPDF_Object* pRef = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Info")) : NULL;
1163     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1164         return 0;
1165     }
1166     return ((CPDF_Reference*) pRef)->GetRefObjNum();
1167 }
1168 FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm)
1169 {
1170     bForm = FALSE;
1171     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1172         return TRUE;
1173     }
1174     if (m_V5Type[objnum] == 0) {
1175         return TRUE;
1176     }
1177     if (m_V5Type[objnum] == 2) {
1178         return TRUE;
1179     }
1180     FX_FILESIZE pos = m_CrossRef[objnum];
1181     FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1182     if (pResult == NULL) {
1183         return TRUE;
1184     }
1185     if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
1186         return FALSE;
1187     }
1188     FX_FILESIZE size = ((FX_FILESIZE*)pResult)[1] - pos;
1189     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1190     m_Syntax.RestorePos(pos);
1191     bForm = m_Syntax.SearchMultiWord(FX_BSTRC("/Form\0stream"), TRUE, size) == 0;
1192     m_Syntax.RestorePos(SavedPos);
1193     return TRUE;
1194 }
1195 CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, PARSE_CONTEXT* pContext)
1196 {
1197     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1198         return NULL;
1199     }
1200     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1201         FX_FILESIZE pos = m_CrossRef[objnum];
1202         if (pos <= 0) {
1203             return NULL;
1204         }
1205         return ParseIndirectObjectAt(pObjList, pos, objnum, pContext);
1206     }
1207     if (m_V5Type[objnum] == 2) {
1208         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1209         if (pObjStream == NULL) {
1210             return NULL;
1211         }
1212         FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1213         FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1214         CPDF_SyntaxParser syntax;
1215         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE));
1216         syntax.InitParser(file.Get(), 0);
1217         CPDF_Object* pRet = NULL;
1218         while (n) {
1219             FX_DWORD thisnum = syntax.GetDirectNum();
1220             FX_DWORD thisoff = syntax.GetDirectNum();
1221             if (thisnum == objnum) {
1222                 syntax.RestorePos(offset + thisoff);
1223                 pRet = syntax.GetObject(pObjList, 0, 0, pContext);
1224                 break;
1225             }
1226             n --;
1227         }
1228         return pRet;
1229     }
1230     return NULL;
1231 }
1232 CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum)
1233 {
1234     CPDF_StreamAcc* pStreamAcc = NULL;
1235     if (m_ObjectStreamMap.Lookup((void*)(FX_UINTPTR)objnum, (void*&)pStreamAcc)) {
1236         return pStreamAcc;
1237     }
1238     const CPDF_Stream* pStream = m_pDocument ? (CPDF_Stream*)m_pDocument->GetIndirectObject(objnum) : NULL;
1239     if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
1240         return NULL;
1241     }
1242     pStreamAcc = FX_NEW CPDF_StreamAcc;
1243     pStreamAcc->LoadAllData(pStream);
1244     m_ObjectStreamMap.SetAt((void*)(FX_UINTPTR)objnum, pStreamAcc);
1245     return pStreamAcc;
1246 }
1247 FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum)
1248 {
1249     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1250         return 0;
1251     }
1252     if (m_V5Type[objnum] == 2) {
1253         objnum = (FX_DWORD)m_CrossRef[objnum];
1254     }
1255     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1256         FX_FILESIZE offset = m_CrossRef[objnum];
1257         if (offset == 0) {
1258             return 0;
1259         }
1260         FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1261         if (pResult == NULL) {
1262             return 0;
1263         }
1264         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
1265             return 0;
1266         }
1267         return ((FX_FILESIZE*)pResult)[1] - offset;
1268     }
1269     return 0;
1270 }
1271 void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, FX_LPBYTE& pBuffer, FX_DWORD& size)
1272 {
1273     pBuffer = NULL;
1274     size = 0;
1275     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1276         return;
1277     }
1278     if (m_V5Type[objnum] == 2) {
1279         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1280         if (pObjStream == NULL) {
1281             return;
1282         }
1283         FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1284         FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1285         CPDF_SyntaxParser syntax;
1286         FX_LPCBYTE pData = pObjStream->GetData();
1287         FX_DWORD totalsize = pObjStream->GetSize();
1288         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pData, (size_t)totalsize, FALSE));
1289         syntax.InitParser(file.Get(), 0);
1290         while (n) {
1291             FX_DWORD thisnum = syntax.GetDirectNum();
1292             FX_DWORD thisoff = syntax.GetDirectNum();
1293             if (thisnum == objnum) {
1294                 if (n == 1) {
1295                     size = totalsize - (thisoff + offset);
1296                 } else {
1297                     syntax.GetDirectNum();  // Skip nextnum.
1298                     FX_DWORD nextoff = syntax.GetDirectNum();
1299                     size = nextoff - thisoff;
1300                 }
1301                 pBuffer = FX_Alloc(FX_BYTE, size);
1302                 FXSYS_memcpy32(pBuffer, pData + thisoff + offset, size);
1303                 return;
1304             }
1305             n --;
1306         }
1307         return;
1308     }
1309     if (m_V5Type[objnum] == 1) {
1310         FX_FILESIZE pos = m_CrossRef[objnum];
1311         if (pos == 0) {
1312             return;
1313         }
1314         FX_FILESIZE SavedPos = m_Syntax.SavePos();
1315         m_Syntax.RestorePos(pos);
1316         FX_BOOL bIsNumber;
1317         CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1318         if (!bIsNumber) {
1319             m_Syntax.RestorePos(SavedPos);
1320             return;
1321         }
1322         FX_DWORD parser_objnum = FXSYS_atoi(word);
1323         if (parser_objnum && parser_objnum != objnum) {
1324             m_Syntax.RestorePos(SavedPos);
1325             return;
1326         }
1327         word = m_Syntax.GetNextWord(bIsNumber);
1328         if (!bIsNumber) {
1329             m_Syntax.RestorePos(SavedPos);
1330             return;
1331         }
1332         if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1333             m_Syntax.RestorePos(SavedPos);
1334             return;
1335         }
1336         FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1337         if (pResult == NULL) {
1338             m_Syntax.RestorePos(SavedPos);
1339             return;
1340         }
1341         FX_FILESIZE nextoff = ((FX_FILESIZE*)pResult)[1];
1342         FX_BOOL bNextOffValid = FALSE;
1343         if (nextoff != pos) {
1344             m_Syntax.RestorePos(nextoff);
1345             word = m_Syntax.GetNextWord(bIsNumber);
1346             if (word == FX_BSTRC("xref")) {
1347                 bNextOffValid = TRUE;
1348             } else if (bIsNumber) {
1349                 word = m_Syntax.GetNextWord(bIsNumber);
1350                 if (bIsNumber && m_Syntax.GetKeyword() == FX_BSTRC("obj")) {
1351                     bNextOffValid = TRUE;
1352                 }
1353             }
1354         }
1355         if (!bNextOffValid) {
1356             m_Syntax.RestorePos(pos);
1357             while (1) {
1358                 if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) {
1359                     break;
1360                 }
1361                 if (m_Syntax.SavePos() == m_Syntax.m_FileLen) {
1362                     break;
1363                 }
1364             }
1365             nextoff = m_Syntax.SavePos();
1366         }
1367         size = (FX_DWORD)(nextoff - pos);
1368         pBuffer = FX_Alloc(FX_BYTE, size);
1369         m_Syntax.RestorePos(pos);
1370         m_Syntax.ReadBlock(pBuffer, size);
1371         m_Syntax.RestorePos(SavedPos);
1372     }
1373 }
1374 CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
1375         PARSE_CONTEXT* pContext)
1376 {
1377     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1378     m_Syntax.RestorePos(pos);
1379     FX_BOOL bIsNumber;
1380     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1381     if (!bIsNumber) {
1382         m_Syntax.RestorePos(SavedPos);
1383         return NULL;
1384     }
1385     FX_FILESIZE objOffset = m_Syntax.SavePos();
1386     objOffset -= word.GetLength();
1387     FX_DWORD parser_objnum = FXSYS_atoi(word);
1388     if (objnum && parser_objnum != objnum) {
1389         m_Syntax.RestorePos(SavedPos);
1390         return NULL;
1391     }
1392     word = m_Syntax.GetNextWord(bIsNumber);
1393     if (!bIsNumber) {
1394         m_Syntax.RestorePos(SavedPos);
1395         return NULL;
1396     }
1397     FX_DWORD parser_gennum = FXSYS_atoi(word);
1398     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1399         m_Syntax.RestorePos(SavedPos);
1400         return NULL;
1401     }
1402     CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, parser_gennum, pContext);
1403     FX_FILESIZE endOffset = m_Syntax.SavePos();
1404     CFX_ByteString bsWord = m_Syntax.GetKeyword();
1405     if (bsWord == FX_BSTRC("endobj")) {
1406         endOffset = m_Syntax.SavePos();
1407     }
1408     m_Syntax.RestorePos(SavedPos);
1409     if (pObj) {
1410         if (!objnum) {
1411             pObj->m_ObjNum = parser_objnum;
1412         }
1413         pObj->m_GenNum = parser_gennum;
1414     }
1415     return pObj;
1416 }
1417 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
1418         struct PARSE_CONTEXT* pContext, FX_FILESIZE *pResultPos)
1419 {
1420     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1421     m_Syntax.RestorePos(pos);
1422     FX_BOOL bIsNumber;
1423     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1424     if (!bIsNumber) {
1425         m_Syntax.RestorePos(SavedPos);
1426         return NULL;
1427     }
1428     FX_DWORD parser_objnum = FXSYS_atoi(word);
1429     if (objnum && parser_objnum != objnum) {
1430         m_Syntax.RestorePos(SavedPos);
1431         return NULL;
1432     }
1433     word = m_Syntax.GetNextWord(bIsNumber);
1434     if (!bIsNumber) {
1435         m_Syntax.RestorePos(SavedPos);
1436         return NULL;
1437     }
1438     FX_DWORD gennum = FXSYS_atoi(word);
1439     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1440         m_Syntax.RestorePos(SavedPos);
1441         return NULL;
1442     }
1443     CPDF_Object* pObj = m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, pContext);
1444     if (pResultPos) {
1445         *pResultPos = m_Syntax.m_Pos;
1446     }
1447     m_Syntax.RestorePos(SavedPos);
1448     return pObj;
1449 }
1450 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4()
1451 {
1452     if (m_Syntax.GetKeyword() != FX_BSTRC("trailer")) {
1453         return NULL;
1454     }
1455     CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
1456     if (pObj == NULL || pObj->GetType() != PDFOBJ_DICTIONARY) {
1457         if (pObj) {
1458             pObj->Release();
1459         }
1460         return NULL;
1461     }
1462     return (CPDF_Dictionary*)pObj;
1463 }
1464 FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision)
1465 {
1466     if (m_pSecurityHandler == NULL) {
1467         return (FX_DWORD) - 1;
1468     }
1469     FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions();
1470     if (m_pEncryptDict && m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) {
1471         dwPermission &= 0xFFFFFFFC;
1472         dwPermission |= 0xFFFFF0C0;
1473         if(bCheckRevision && m_pEncryptDict->GetInteger(FX_BSTRC("R")) == 2) {
1474             dwPermission &= 0xFFFFF0FF;
1475         }
1476     }
1477     return dwPermission;
1478 }
1479 FX_BOOL CPDF_Parser::IsOwner()
1480 {
1481     return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
1482 }
1483 void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler, FX_BOOL bForced)
1484 {
1485     ASSERT(m_pSecurityHandler == NULL);
1486     if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
1487         delete m_pSecurityHandler;
1488         m_pSecurityHandler = NULL;
1489     }
1490     m_bForceUseSecurityHandler = bForced;
1491     m_pSecurityHandler = pSecurityHandler;
1492     if (m_bForceUseSecurityHandler) {
1493         return;
1494     }
1495     m_Syntax.m_pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
1496     m_Syntax.m_pCryptoHandler->Init(NULL, pSecurityHandler);
1497 }
1498 FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, FX_DWORD offset)
1499 {
1500     m_Syntax.InitParser(pFileAccess, offset);
1501     m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9);
1502     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1503     FX_BOOL bIsNumber;
1504     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1505     if (!bIsNumber) {
1506         return FALSE;
1507     }
1508     FX_DWORD objnum = FXSYS_atoi(word);
1509     word = m_Syntax.GetNextWord(bIsNumber);
1510     if (!bIsNumber) {
1511         return FALSE;
1512     }
1513     FX_DWORD gennum = FXSYS_atoi(word);
1514     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1515         m_Syntax.RestorePos(SavedPos);
1516         return FALSE;
1517     }
1518     m_pLinearized = m_Syntax.GetObject(NULL, objnum, gennum, 0);
1519     if (!m_pLinearized) {
1520         return FALSE;
1521     }
1522     if (m_pLinearized->GetDict() && m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
1523         m_Syntax.GetNextWord(bIsNumber);
1524         CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
1525         if (!pLen) {
1526             m_pLinearized->Release();
1527             m_pLinearized = NULL;
1528             return FALSE;
1529         }
1530         if (pLen->GetInteger() != (int)pFileAccess->GetSize()) {
1531             return FALSE;
1532         }
1533         CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
1534         if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
1535             m_dwFirstPageNo = pNo->GetInteger();
1536         }
1537         CPDF_Object *pTable = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T"));
1538         if (pTable && pTable->GetType() == PDFOBJ_NUMBER) {
1539             m_LastXRefOffset = pTable->GetInteger();
1540         }
1541         return TRUE;
1542     }
1543     m_pLinearized->Release();
1544     m_pLinearized = NULL;
1545     return FALSE;
1546 }
1547 FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead)
1548 {
1549     CloseParser(bReParse);
1550     m_bXRefStream = FALSE;
1551     m_LastXRefOffset = 0;
1552     m_bOwnFileRead = bOwnFileRead;
1553     FX_INT32 offset = GetHeaderOffset(pFileAccess);
1554     if (offset == -1) {
1555         return PDFPARSE_ERROR_FORMAT;
1556     }
1557     if (!IsLinearizedFile(pFileAccess, offset)) {
1558         m_Syntax.m_pFileAccess = NULL;
1559         return StartParse(pFileAccess, bReParse, bOwnFileRead);
1560     }
1561     if (!bReParse) {
1562         m_pDocument = FX_NEW CPDF_Document(this);
1563     }
1564     FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos();
1565     FX_BOOL bXRefRebuilt = FALSE;
1566     FX_BOOL bLoadV4 = FALSE;
1567     if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) {
1568         if (!RebuildCrossRef()) {
1569             return PDFPARSE_ERROR_FORMAT;
1570         }
1571         bXRefRebuilt = TRUE;
1572         m_LastXRefOffset = 0;
1573     }
1574     if (bLoadV4) {
1575         m_pTrailer = LoadTrailerV4();
1576         if (m_pTrailer == NULL) {
1577             return FALSE;
1578         }
1579         FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
1580         if (xrefsize > 0) {
1581             m_CrossRef.SetSize(xrefsize);
1582             m_V5Type.SetSize(xrefsize);
1583         }
1584     }
1585     FX_DWORD dwRet = SetEncryptHandler();
1586     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1587         return dwRet;
1588     }
1589     m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1590     if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
1591         if (bXRefRebuilt) {
1592             return PDFPARSE_ERROR_FORMAT;
1593         }
1594         ReleaseEncryptHandler();
1595         if (!RebuildCrossRef()) {
1596             return PDFPARSE_ERROR_FORMAT;
1597         }
1598         dwRet = SetEncryptHandler();
1599         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1600             return dwRet;
1601         }
1602         m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1603         if (m_pDocument->GetRoot() == NULL) {
1604             return PDFPARSE_ERROR_FORMAT;
1605         }
1606     }
1607     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1608     FX_DWORD RootObjNum = GetRootObjNum();
1609     if (RootObjNum == 0) {
1610         ReleaseEncryptHandler();
1611         RebuildCrossRef();
1612         RootObjNum = GetRootObjNum();
1613         if (RootObjNum == 0) {
1614             return PDFPARSE_ERROR_FORMAT;
1615         }
1616         dwRet = SetEncryptHandler();
1617         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1618             return dwRet;
1619         }
1620     }
1621     if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) {
1622         CPDF_Object* pMetadata = m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
1623         if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
1624             m_Syntax.m_MetadataObjnum = ((CPDF_Reference*) pMetadata)->GetRefObjNum();
1625         }
1626     }
1627     return PDFPARSE_ERROR_SUCCESS;
1628 }
1629 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos)
1630 {
1631     if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1632         return FALSE;
1633     }
1634     while (xrefpos)
1635         if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1636             return FALSE;
1637         }
1638     m_ObjectStreamMap.InitHashTable(101, FALSE);
1639     m_bXRefStream = TRUE;
1640     return TRUE;
1641 }
1642 FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable()
1643 {
1644     FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum;
1645     m_Syntax.m_MetadataObjnum = 0;
1646     if (m_pTrailer) {
1647         m_pTrailer->Release();
1648         m_pTrailer = NULL;
1649     }
1650     m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset);
1651     FX_BYTE ch = 0;
1652     FX_DWORD dwCount = 0;
1653     m_Syntax.GetNextChar(ch);
1654     FX_INT32 type = PDF_CharType[ch];
1655     while (type == 'W') {
1656         ++dwCount;
1657         if (m_Syntax.m_FileLen >= (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
1658             break;
1659         }
1660         m_Syntax.GetNextChar(ch);
1661         type = PDF_CharType[ch];
1662     }
1663     m_LastXRefOffset += dwCount;
1664     FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
1665     while (pos) {
1666         FX_LPVOID objnum;
1667         CPDF_StreamAcc* pStream;
1668         m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
1669         delete pStream;
1670     }
1671     m_ObjectStreamMap.RemoveAll();
1672     if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) {
1673         m_LastXRefOffset = 0;
1674         m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1675         return PDFPARSE_ERROR_FORMAT;
1676     }
1677     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1678     m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1679     return PDFPARSE_ERROR_SUCCESS;
1680 }
1681
1682 // static
1683 int CPDF_SyntaxParser::s_CurrentRecursionDepth = 0;
1684
1685 CPDF_SyntaxParser::CPDF_SyntaxParser()
1686 {
1687     m_pFileAccess = NULL;
1688     m_pCryptoHandler = NULL;
1689     m_pFileBuf = NULL;
1690     m_BufSize = CPDF_ModuleMgr::Get()->m_FileBufSize;
1691     m_pFileBuf = NULL;
1692     m_MetadataObjnum = 0;
1693     m_dwWordPos = 0;
1694     m_bFileStream = FALSE;
1695 }
1696 CPDF_SyntaxParser::~CPDF_SyntaxParser()
1697 {
1698     if (m_pFileBuf) {
1699         FX_Free(m_pFileBuf);
1700     }
1701 }
1702 FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, FX_BYTE& ch)
1703 {
1704     FX_FILESIZE save_pos = m_Pos;
1705     m_Pos = pos;
1706     FX_BOOL ret = GetNextChar(ch);
1707     m_Pos = save_pos;
1708     return ret;
1709 }
1710 FX_BOOL CPDF_SyntaxParser::GetNextChar(FX_BYTE& ch)
1711 {
1712     FX_FILESIZE pos = m_Pos + m_HeaderOffset;
1713     if (pos >= m_FileLen) {
1714         return FALSE;
1715     }
1716     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1717         FX_FILESIZE read_pos = pos;
1718         FX_DWORD read_size = m_BufSize;
1719         if ((FX_FILESIZE)read_size > m_FileLen) {
1720             read_size = (FX_DWORD)m_FileLen;
1721         }
1722         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1723             if (m_FileLen < (FX_FILESIZE)read_size) {
1724                 read_pos = 0;
1725                 read_size = (FX_DWORD)m_FileLen;
1726             } else {
1727                 read_pos = m_FileLen - read_size;
1728             }
1729         }
1730         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1731             return FALSE;
1732         }
1733         m_BufOffset = read_pos;
1734     }
1735     ch = m_pFileBuf[pos - m_BufOffset];
1736     m_Pos ++;
1737     return TRUE;
1738 }
1739 FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, FX_BYTE& ch)
1740 {
1741     pos += m_HeaderOffset;
1742     if (pos >= m_FileLen) {
1743         return FALSE;
1744     }
1745     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1746         FX_FILESIZE read_pos;
1747         if (pos < (FX_FILESIZE)m_BufSize) {
1748             read_pos = 0;
1749         } else {
1750             read_pos = pos - m_BufSize + 1;
1751         }
1752         FX_DWORD read_size = m_BufSize;
1753         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1754             if (m_FileLen < (FX_FILESIZE)read_size) {
1755                 read_pos = 0;
1756                 read_size = (FX_DWORD)m_FileLen;
1757             } else {
1758                 read_pos = m_FileLen - read_size;
1759             }
1760         }
1761         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1762             return FALSE;
1763         }
1764         m_BufOffset = read_pos;
1765     }
1766     ch = m_pFileBuf[pos - m_BufOffset];
1767     return TRUE;
1768 }
1769 FX_BOOL CPDF_SyntaxParser::ReadBlock(FX_LPBYTE pBuf, FX_DWORD size)
1770 {
1771     if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) {
1772         return FALSE;
1773     }
1774     m_Pos += size;
1775     return TRUE;
1776 }
1777 #define MAX_WORD_BUFFER 256
1778 void CPDF_SyntaxParser::GetNextWord()
1779 {
1780     m_WordSize = 0;
1781     m_bIsNumber = TRUE;
1782     FX_BYTE ch;
1783     if (!GetNextChar(ch)) {
1784         return;
1785     }
1786     FX_BYTE type = PDF_CharType[ch];
1787     while (1) {
1788         while (type == 'W') {
1789             if (!GetNextChar(ch)) {
1790                 return;
1791             }
1792             type = PDF_CharType[ch];
1793         }
1794         if (ch != '%') {
1795             break;
1796         }
1797         while (1) {
1798             if (!GetNextChar(ch)) {
1799                 return;
1800             }
1801             if (ch == '\r' || ch == '\n') {
1802                 break;
1803             }
1804         }
1805         type = PDF_CharType[ch];
1806     }
1807     if (type == 'D') {
1808         m_bIsNumber = FALSE;
1809         m_WordBuffer[m_WordSize++] = ch;
1810         if (ch == '/') {
1811             while (1) {
1812                 if (!GetNextChar(ch)) {
1813                     return;
1814                 }
1815                 type = PDF_CharType[ch];
1816                 if (type != 'R' && type != 'N') {
1817                     m_Pos --;
1818                     return;
1819                 }
1820                 if (m_WordSize < MAX_WORD_BUFFER) {
1821                     m_WordBuffer[m_WordSize++] = ch;
1822                 }
1823             }
1824         } else if (ch == '<') {
1825             if (!GetNextChar(ch)) {
1826                 return;
1827             }
1828             if (ch == '<') {
1829                 m_WordBuffer[m_WordSize++] = ch;
1830             } else {
1831                 m_Pos --;
1832             }
1833         } else if (ch == '>') {
1834             if (!GetNextChar(ch)) {
1835                 return;
1836             }
1837             if (ch == '>') {
1838                 m_WordBuffer[m_WordSize++] = ch;
1839             } else {
1840                 m_Pos --;
1841             }
1842         }
1843         return;
1844     }
1845     while (1) {
1846         if (m_WordSize < MAX_WORD_BUFFER) {
1847             m_WordBuffer[m_WordSize++] = ch;
1848         }
1849         if (type != 'N') {
1850             m_bIsNumber = FALSE;
1851         }
1852         if (!GetNextChar(ch)) {
1853             return;
1854         }
1855         type = PDF_CharType[ch];
1856         if (type == 'D' || type == 'W') {
1857             m_Pos --;
1858             break;
1859         }
1860     }
1861 }
1862 CFX_ByteString CPDF_SyntaxParser::ReadString()
1863 {
1864     FX_BYTE ch;
1865     if (!GetNextChar(ch)) {
1866         return CFX_ByteString();
1867     }
1868     CFX_ByteTextBuf buf;
1869     FX_INT32 parlevel = 0;
1870     FX_INT32 status = 0, iEscCode = 0;
1871     while (1) {
1872         switch (status) {
1873             case 0:
1874                 if (ch == ')') {
1875                     if (parlevel == 0) {
1876                         return buf.GetByteString();
1877                     }
1878                     parlevel --;
1879                     buf.AppendChar(')');
1880                 } else if (ch == '(') {
1881                     parlevel ++;
1882                     buf.AppendChar('(');
1883                 } else if (ch == '\\') {
1884                     status = 1;
1885                 } else {
1886                     buf.AppendChar(ch);
1887                 }
1888                 break;
1889             case 1:
1890                 if (ch >= '0' && ch <= '7') {
1891                     iEscCode = ch - '0';
1892                     status = 2;
1893                     break;
1894                 }
1895                 if (ch == 'n') {
1896                     buf.AppendChar('\n');
1897                 } else if (ch == 'r') {
1898                     buf.AppendChar('\r');
1899                 } else if (ch == 't') {
1900                     buf.AppendChar('\t');
1901                 } else if (ch == 'b') {
1902                     buf.AppendChar('\b');
1903                 } else if (ch == 'f') {
1904                     buf.AppendChar('\f');
1905                 } else if (ch == '\r') {
1906                     status = 4;
1907                     break;
1908                 } else if (ch == '\n') {
1909                 } else {
1910                     buf.AppendChar(ch);
1911                 }
1912                 status = 0;
1913                 break;
1914             case 2:
1915                 if (ch >= '0' && ch <= '7') {
1916                     iEscCode = iEscCode * 8 + ch - '0';
1917                     status = 3;
1918                 } else {
1919                     buf.AppendChar(iEscCode);
1920                     status = 0;
1921                     continue;
1922                 }
1923                 break;
1924             case 3:
1925                 if (ch >= '0' && ch <= '7') {
1926                     iEscCode = iEscCode * 8 + ch - '0';
1927                     buf.AppendChar(iEscCode);
1928                     status = 0;
1929                 } else {
1930                     buf.AppendChar(iEscCode);
1931                     status = 0;
1932                     continue;
1933                 }
1934                 break;
1935             case 4:
1936                 status = 0;
1937                 if (ch != '\n') {
1938                     continue;
1939                 }
1940                 break;
1941         }
1942         if (!GetNextChar(ch)) {
1943             break;
1944         }
1945     }
1946     GetNextChar(ch);
1947     return buf.GetByteString();
1948 }
1949 CFX_ByteString CPDF_SyntaxParser::ReadHexString()
1950 {
1951     FX_BYTE ch;
1952     if (!GetNextChar(ch)) {
1953         return CFX_ByteString();
1954     }
1955     CFX_BinaryBuf buf;
1956     FX_BOOL bFirst = TRUE;
1957     FX_BYTE code = 0;
1958     while (1) {
1959         if (ch == '>') {
1960             break;
1961         }
1962         if (ch >= '0' && ch <= '9') {
1963             if (bFirst) {
1964                 code = (ch - '0') * 16;
1965             } else {
1966                 code += ch - '0';
1967                 buf.AppendByte((FX_BYTE)code);
1968             }
1969             bFirst = !bFirst;
1970         } else if (ch >= 'A' && ch <= 'F') {
1971             if (bFirst) {
1972                 code = (ch - 'A' + 10) * 16;
1973             } else {
1974                 code += ch - 'A' + 10;
1975                 buf.AppendByte((FX_BYTE)code);
1976             }
1977             bFirst = !bFirst;
1978         } else if (ch >= 'a' && ch <= 'f') {
1979             if (bFirst) {
1980                 code = (ch - 'a' + 10) * 16;
1981             } else {
1982                 code += ch - 'a' + 10;
1983                 buf.AppendByte((FX_BYTE)code);
1984             }
1985             bFirst = !bFirst;
1986         }
1987         if (!GetNextChar(ch)) {
1988             break;
1989         }
1990     }
1991     if (!bFirst) {
1992         buf.AppendByte((FX_BYTE)code);
1993     }
1994     return buf.GetByteString();
1995 }
1996 void CPDF_SyntaxParser::ToNextLine()
1997 {
1998     FX_BYTE ch;
1999     while (1) {
2000         if (!GetNextChar(ch)) {
2001             return;
2002         }
2003         if (ch == '\n') {
2004             return;
2005         }
2006         if (ch == '\r') {
2007             GetNextChar(ch);
2008             if (ch == '\n') {
2009                 return;
2010             } else {
2011                 m_Pos --;
2012                 return;
2013             }
2014         }
2015     }
2016 }
2017 void CPDF_SyntaxParser::ToNextWord()
2018 {
2019     FX_BYTE ch;
2020     if (!GetNextChar(ch)) {
2021         return;
2022     }
2023     FX_BYTE type = PDF_CharType[ch];
2024     while (1) {
2025         while (type == 'W') {
2026             m_dwWordPos = m_Pos;
2027             if (!GetNextChar(ch)) {
2028                 return;
2029             }
2030             type = PDF_CharType[ch];
2031         }
2032         if (ch != '%') {
2033             break;
2034         }
2035         while (1) {
2036             if (!GetNextChar(ch)) {
2037                 return;
2038             }
2039             if (ch == '\r' || ch == '\n') {
2040                 break;
2041             }
2042         }
2043         type = PDF_CharType[ch];
2044     }
2045     m_Pos --;
2046 }
2047 CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber)
2048 {
2049     GetNextWord();
2050     bIsNumber = m_bIsNumber;
2051     return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
2052 }
2053 CFX_ByteString CPDF_SyntaxParser::GetKeyword()
2054 {
2055     GetNextWord();
2056     return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
2057 }
2058 CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, PARSE_CONTEXT* pContext, FX_BOOL bDecrypt)
2059 {
2060     CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
2061     if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) {
2062         return NULL;
2063     }
2064     FX_FILESIZE SavedPos = m_Pos;
2065     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2066     FX_BOOL bIsNumber;
2067     CFX_ByteString word = GetNextWord(bIsNumber);
2068     CPDF_Object* pRet = NULL;
2069     if (word.GetLength() == 0) {
2070         if (bTypeOnly) {
2071             return (CPDF_Object*)PDFOBJ_INVALID;
2072         }
2073         return NULL;
2074     }
2075     if (bIsNumber) {
2076         FX_FILESIZE SavedPos = m_Pos;
2077         CFX_ByteString nextword = GetNextWord(bIsNumber);
2078         if (bIsNumber) {
2079             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2080             if (nextword2 == FX_BSTRC("R")) {
2081                 FX_DWORD objnum = FXSYS_atoi(word);
2082                 if (bTypeOnly) {
2083                     return (CPDF_Object*)PDFOBJ_REFERENCE;
2084                 }
2085                 pRet = CPDF_Reference::Create(pObjList, objnum);
2086                 return pRet;
2087             } else {
2088                 m_Pos = SavedPos;
2089                 if (bTypeOnly) {
2090                     return (CPDF_Object*)PDFOBJ_NUMBER;
2091                 }
2092                 pRet = CPDF_Number::Create(word);
2093                 return pRet;
2094             }
2095         } else {
2096             m_Pos = SavedPos;
2097             if (bTypeOnly) {
2098                 return (CPDF_Object*)PDFOBJ_NUMBER;
2099             }
2100             pRet = CPDF_Number::Create(word);
2101             return pRet;
2102         }
2103     }
2104     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2105         if (bTypeOnly) {
2106             return (CPDF_Object*)PDFOBJ_BOOLEAN;
2107         }
2108         pRet = CPDF_Boolean::Create(word == FX_BSTRC("true"));
2109         return pRet;
2110     }
2111     if (word == FX_BSTRC("null")) {
2112         if (bTypeOnly) {
2113             return (CPDF_Object*)PDFOBJ_NULL;
2114         }
2115         pRet = CPDF_Null::Create();
2116         return pRet;
2117     }
2118     if (word == FX_BSTRC("(")) {
2119         if (bTypeOnly) {
2120             return (CPDF_Object*)PDFOBJ_STRING;
2121         }
2122         CFX_ByteString str = ReadString();
2123         if (m_pCryptoHandler && bDecrypt) {
2124             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2125         }
2126         pRet = CPDF_String::Create(str, FALSE);
2127         return pRet;
2128     }
2129     if (word == FX_BSTRC("<")) {
2130         if (bTypeOnly) {
2131             return (CPDF_Object*)PDFOBJ_STRING;
2132         }
2133         CFX_ByteString str = ReadHexString();
2134         if (m_pCryptoHandler && bDecrypt) {
2135             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2136         }
2137         pRet = CPDF_String::Create(str, TRUE);
2138         return pRet;
2139     }
2140     if (word == FX_BSTRC("[")) {
2141         if (bTypeOnly) {
2142             return (CPDF_Object*)PDFOBJ_ARRAY;
2143         }
2144         CPDF_Array* pArray = CPDF_Array::Create();
2145         while (1) {
2146             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2147             if (pObj == NULL) {
2148                 return pArray;
2149             }
2150             pArray->Add(pObj);
2151         }
2152     }
2153     if (word[0] == '/') {
2154         if (bTypeOnly) {
2155             return (CPDF_Object*)PDFOBJ_NAME;
2156         }
2157         pRet = CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2158         return pRet;
2159     }
2160     if (word == FX_BSTRC("<<")) {
2161         FX_FILESIZE saveDictOffset = m_Pos - 2;
2162         FX_DWORD dwDictSize = 0;
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                 dwDictSize = m_Pos - saveDictOffset;
2183                 break;
2184             }
2185             if (key == FX_BSTRC("endobj")) {
2186                 dwDictSize = m_Pos - 6 - saveDictOffset;
2187                 m_Pos = SavedPos;
2188                 break;
2189             }
2190             if (key[0] != '/') {
2191                 continue;
2192             }
2193             nKeys ++;
2194             key = PDF_NameDecode(key);
2195             if (key == FX_BSTRC("/Contents")) {
2196                 dwSignValuePos = m_Pos;
2197             }
2198             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2199             if (pObj == NULL) {
2200                 continue;
2201             }
2202             if (key.GetLength() >= 1) {
2203                 if (nKeys < 32) {
2204                     pDict->SetAt(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj);
2205                 } else {
2206                     pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj);
2207                 }
2208             }
2209         }
2210         if (IsSignatureDict(pDict)) {
2211             FX_FILESIZE dwSavePos = m_Pos;
2212             m_Pos = dwSignValuePos;
2213             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, NULL, FALSE);
2214             pDict->SetAt(FX_BSTRC("Contents"), pObj);
2215             m_Pos = dwSavePos;
2216         }
2217         if (pContext) {
2218             pContext->m_DictEnd = m_Pos;
2219             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2220                 return pDict;
2221             }
2222         }
2223         FX_FILESIZE SavedPos = m_Pos;
2224         FX_BOOL bIsNumber;
2225         CFX_ByteString nextword = GetNextWord(bIsNumber);
2226         if (nextword == FX_BSTRC("stream")) {
2227             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2228             if (pStream) {
2229                 return pStream;
2230             }
2231             if (pDict)
2232                 pDict->Release();
2233             return NULL;
2234         } else {
2235             m_Pos = SavedPos;
2236             return pDict;
2237         }
2238     }
2239     if (word == FX_BSTRC(">>")) {
2240         m_Pos = SavedPos;
2241         return NULL;
2242     }
2243     if (bTypeOnly) {
2244         return (CPDF_Object*)PDFOBJ_INVALID;
2245     }
2246     return NULL;
2247 }
2248 CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, struct PARSE_CONTEXT* pContext)
2249 {
2250     CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
2251     if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) {
2252         return NULL;
2253     }
2254     FX_FILESIZE SavedPos = m_Pos;
2255     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2256     FX_BOOL bIsNumber;
2257     CFX_ByteString word = GetNextWord(bIsNumber);
2258     if (word.GetLength() == 0) {
2259         if (bTypeOnly) {
2260             return (CPDF_Object*)PDFOBJ_INVALID;
2261         }
2262         return NULL;
2263     }
2264     if (bIsNumber) {
2265         FX_FILESIZE SavedPos = m_Pos;
2266         CFX_ByteString nextword = GetNextWord(bIsNumber);
2267         if (bIsNumber) {
2268             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2269             if (nextword2 == FX_BSTRC("R")) {
2270                 FX_DWORD objnum = FXSYS_atoi(word);
2271                 if (bTypeOnly) {
2272                     return (CPDF_Object*)PDFOBJ_REFERENCE;
2273                 }
2274                 return CPDF_Reference::Create(pObjList, objnum);
2275             } else {
2276                 m_Pos = SavedPos;
2277                 if (bTypeOnly) {
2278                     return (CPDF_Object*)PDFOBJ_NUMBER;
2279                 }
2280                 return CPDF_Number::Create(word);
2281             }
2282         } else {
2283             m_Pos = SavedPos;
2284             if (bTypeOnly) {
2285                 return (CPDF_Object*)PDFOBJ_NUMBER;
2286             }
2287             return CPDF_Number::Create(word);
2288         }
2289     }
2290     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2291         if (bTypeOnly) {
2292             return (CPDF_Object*)PDFOBJ_BOOLEAN;
2293         }
2294         return CPDF_Boolean::Create(word == FX_BSTRC("true"));
2295     }
2296     if (word == FX_BSTRC("null")) {
2297         if (bTypeOnly) {
2298             return (CPDF_Object*)PDFOBJ_NULL;
2299         }
2300         return CPDF_Null::Create();
2301     }
2302     if (word == FX_BSTRC("(")) {
2303         if (bTypeOnly) {
2304             return (CPDF_Object*)PDFOBJ_STRING;
2305         }
2306         CFX_ByteString str = ReadString();
2307         if (m_pCryptoHandler) {
2308             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2309         }
2310         return CPDF_String::Create(str, FALSE);
2311     }
2312     if (word == FX_BSTRC("<")) {
2313         if (bTypeOnly) {
2314             return (CPDF_Object*)PDFOBJ_STRING;
2315         }
2316         CFX_ByteString str = ReadHexString();
2317         if (m_pCryptoHandler) {
2318             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2319         }
2320         return CPDF_String::Create(str, TRUE);
2321     }
2322     if (word == FX_BSTRC("[")) {
2323         if (bTypeOnly) {
2324             return (CPDF_Object*)PDFOBJ_ARRAY;
2325         }
2326         CPDF_Array* pArray = CPDF_Array::Create();
2327         while (1) {
2328             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum);
2329             if (pObj == NULL) {
2330                 if (m_WordBuffer[0] == ']') {
2331                     return pArray;
2332                 }
2333                 if (pArray)
2334                     pArray->Release();
2335                 return NULL;
2336             }
2337             pArray->Add(pObj);
2338         }
2339     }
2340     if (word[0] == '/') {
2341         if (bTypeOnly) {
2342             return (CPDF_Object*)PDFOBJ_NAME;
2343         }
2344         return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2345     }
2346     if (word == FX_BSTRC("<<")) {
2347         if (bTypeOnly) {
2348             return (CPDF_Object*)PDFOBJ_DICTIONARY;
2349         }
2350         if (pContext) {
2351             pContext->m_DictStart = SavedPos;
2352         }
2353         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2354         while (1) {
2355             FX_BOOL bIsNumber;
2356             FX_FILESIZE SavedPos = m_Pos;
2357             CFX_ByteString key = GetNextWord(bIsNumber);
2358             if (key.IsEmpty()) {
2359                 if (pDict)
2360                     pDict->Release();
2361                 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                 FX_BYTE ch;
2379                 while (1) {
2380                     if (!GetNextChar(ch)) {
2381                         break;
2382                     }
2383                     if (ch == 0x0A || ch == 0x0D) {
2384                         break;
2385                     }
2386                 }
2387                 return NULL;
2388             }
2389             if (key.GetLength() == 1) {
2390                 pDict->SetAt(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj);
2391             } else {
2392                 pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), pObj);
2393             }
2394         }
2395         if (pContext) {
2396             pContext->m_DictEnd = m_Pos;
2397             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2398                 return pDict;
2399             }
2400         }
2401         FX_FILESIZE SavedPos = m_Pos;
2402         FX_BOOL bIsNumber;
2403         CFX_ByteString nextword = GetNextWord(bIsNumber);
2404         if (nextword == FX_BSTRC("stream")) {
2405             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2406             if (pStream) {
2407                 return pStream;
2408             }
2409             if (pDict)
2410                 pDict->Release();
2411             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;
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, 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_DWORD                            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  &