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