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