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