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