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