Fix Regression: Incomplete file loading is seen for multi page pdf files.
[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     std::vector<std::pair<FX_INT32, FX_INT32> > arrIndex;
1031     CPDF_Array* pArray = pStream->GetDict()->GetArray(FX_BSTRC("Index"));
1032     if (pArray) {
1033         FX_DWORD nPairSize = pArray->GetCount() / 2;
1034         for (FX_DWORD i = 0; i < nPairSize; i++) {
1035             CPDF_Object* pStartNumObj = pArray->GetElement(i * 2);
1036             CPDF_Object* pCountObj = pArray->GetElement(i * 2 + 1);
1037             if (pStartNumObj && pStartNumObj->GetType() == PDFOBJ_NUMBER
1038                 && pCountObj && pCountObj->GetType() == PDFOBJ_NUMBER) {
1039                 arrIndex.push_back(std::make_pair(pStartNumObj->GetInteger(), pCountObj->GetInteger()));
1040             }
1041         }
1042     }
1043     if (arrIndex.size() == 0) {
1044         arrIndex.push_back(std::make_pair(0, size));
1045     }
1046     pArray = pStream->GetDict()->GetArray(FX_BSTRC("W"));
1047     if (pArray == NULL) {
1048         pStream->Release();
1049         return FALSE;
1050     }
1051     CFX_DWordArray WidthArray;
1052     FX_SAFE_DWORD dwAccWidth = 0;
1053     for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
1054         WidthArray.Add(pArray->GetInteger(i));
1055         dwAccWidth += WidthArray[i];
1056     }
1057     if (!dwAccWidth.IsValid() || WidthArray.GetSize() < 3) {
1058         pStream->Release();
1059         return FALSE;
1060     }
1061     FX_DWORD totalWidth = dwAccWidth.ValueOrDie();
1062     CPDF_StreamAcc acc;
1063     acc.LoadAllData(pStream);
1064     FX_LPCBYTE pData = acc.GetData();
1065     FX_DWORD dwTotalSize = acc.GetSize();
1066     FX_DWORD segindex = 0;
1067     for (FX_DWORD i = 0; i < arrIndex.size(); i ++) {
1068         FX_INT32 startnum = arrIndex[i].first;
1069         if (startnum < 0) {
1070             continue;
1071         }
1072         m_dwXrefStartObjNum = base::checked_cast<FX_DWORD, FX_INT32> (startnum);
1073         FX_DWORD count = base::checked_cast<FX_DWORD, FX_INT32> (arrIndex[i].second);
1074         FX_SAFE_DWORD dwCaculatedSize = segindex;
1075         dwCaculatedSize += count;
1076         dwCaculatedSize *= totalWidth;
1077         if (!dwCaculatedSize.IsValid() || dwCaculatedSize.ValueOrDie() > dwTotalSize) { 
1078             continue;
1079         }
1080         FX_LPCBYTE segstart = pData + segindex * totalWidth;
1081         FX_SAFE_DWORD dwMaxObjNum = startnum;
1082         dwMaxObjNum += count;
1083         FX_DWORD dwV5Size = base::checked_cast<FX_DWORD, FX_INT32> (m_V5Type.GetSize());
1084         if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size) {
1085             continue;
1086         }
1087         for (FX_DWORD j = 0; j < count; j ++) {
1088             FX_INT32 type = 1;
1089             FX_LPCBYTE entrystart = segstart + j * totalWidth;
1090             if (WidthArray[0]) {
1091                 type = _GetVarInt(entrystart, WidthArray[0]);
1092             }
1093             if (m_V5Type[startnum + j] == 255) {
1094                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1095                 m_CrossRef[startnum + j] = offset;
1096                 FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1097                 if (pResult == NULL) {
1098                     m_SortedOffset.Add(offset);
1099                 }
1100                 continue;
1101             }
1102             if (m_V5Type[startnum + j]) {
1103                 continue;
1104             }
1105             m_V5Type[startnum + j] = type;
1106             if (type == 0) {
1107                 m_CrossRef[startnum + j] = 0;
1108             } else {
1109                 FX_FILESIZE offset = _GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
1110                 m_CrossRef[startnum + j] = offset;
1111                 if (type == 1) {
1112                     FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1113                     if (pResult == NULL) {
1114                         m_SortedOffset.Add(offset);
1115                     }
1116                 } else {
1117                     if (offset < 0 || offset >= m_V5Type.GetSize()) {
1118                         pStream->Release();
1119                         return FALSE;
1120                     }
1121                     m_V5Type[offset] = 255;
1122                 }
1123             }
1124         }
1125         segindex += count;
1126     }
1127     pStream->Release();
1128     return TRUE;
1129 }
1130 CPDF_Array* CPDF_Parser::GetIDArray()
1131 {
1132     CPDF_Object* pID = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("ID")) : NULL;
1133     if (pID == NULL) {
1134         return NULL;
1135     }
1136     if (pID->GetType() == PDFOBJ_REFERENCE) {
1137         pID = ParseIndirectObject(NULL, ((CPDF_Reference*)pID)->GetRefObjNum());
1138         m_pTrailer->SetAt(FX_BSTRC("ID"), pID);
1139     }
1140     if (pID == NULL || pID->GetType() != PDFOBJ_ARRAY) {
1141         return NULL;
1142     }
1143     return (CPDF_Array*)pID;
1144 }
1145 FX_DWORD CPDF_Parser::GetRootObjNum()
1146 {
1147     CPDF_Object* pRef = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Root")) : NULL;
1148     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1149         return 0;
1150     }
1151     return ((CPDF_Reference*) pRef)->GetRefObjNum();
1152 }
1153 FX_DWORD CPDF_Parser::GetInfoObjNum()
1154 {
1155     CPDF_Object* pRef = m_pTrailer ? m_pTrailer->GetElement(FX_BSTRC("Info")) : NULL;
1156     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
1157         return 0;
1158     }
1159     return ((CPDF_Reference*) pRef)->GetRefObjNum();
1160 }
1161 FX_BOOL CPDF_Parser::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm)
1162 {
1163     bForm = FALSE;
1164     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1165         return TRUE;
1166     }
1167     if (m_V5Type[objnum] == 0) {
1168         return TRUE;
1169     }
1170     if (m_V5Type[objnum] == 2) {
1171         return TRUE;
1172     }
1173     FX_FILESIZE pos = m_CrossRef[objnum];
1174     FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1175     if (pResult == NULL) {
1176         return TRUE;
1177     }
1178     if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
1179         return FALSE;
1180     }
1181     FX_FILESIZE size = ((FX_FILESIZE*)pResult)[1] - pos;
1182     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1183     m_Syntax.RestorePos(pos);
1184     bForm = m_Syntax.SearchMultiWord(FX_BSTRC("/Form\0stream"), TRUE, size) == 0;
1185     m_Syntax.RestorePos(SavedPos);
1186     return TRUE;
1187 }
1188 CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, PARSE_CONTEXT* pContext)
1189 {
1190     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1191         return NULL;
1192     }
1193     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1194         FX_FILESIZE pos = m_CrossRef[objnum];
1195         if (pos <= 0) {
1196             return NULL;
1197         }
1198         return ParseIndirectObjectAt(pObjList, pos, objnum, pContext);
1199     }
1200     if (m_V5Type[objnum] == 2) {
1201         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1202         if (pObjStream == NULL) {
1203             return NULL;
1204         }
1205         FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1206         FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1207         CPDF_SyntaxParser syntax;
1208         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pObjStream->GetData(), (size_t)pObjStream->GetSize(), FALSE));
1209         syntax.InitParser((IFX_FileStream*)file, 0);
1210         CPDF_Object* pRet = NULL;
1211         while (n) {
1212             FX_DWORD thisnum = syntax.GetDirectNum();
1213             FX_DWORD thisoff = syntax.GetDirectNum();
1214             if (thisnum == objnum) {
1215                 syntax.RestorePos(offset + thisoff);
1216                 pRet = syntax.GetObject(pObjList, 0, 0, 0, pContext);
1217                 break;
1218             }
1219             n --;
1220         }
1221         return pRet;
1222     }
1223     return NULL;
1224 }
1225 CPDF_StreamAcc* CPDF_Parser::GetObjectStream(FX_DWORD objnum)
1226 {
1227     CPDF_StreamAcc* pStreamAcc = NULL;
1228     if (m_ObjectStreamMap.Lookup((void*)(FX_UINTPTR)objnum, (void*&)pStreamAcc)) {
1229         return pStreamAcc;
1230     }
1231     const CPDF_Stream* pStream = m_pDocument ? (CPDF_Stream*)m_pDocument->GetIndirectObject(objnum) : NULL;
1232     if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
1233         return NULL;
1234     }
1235     pStreamAcc = FX_NEW CPDF_StreamAcc;
1236     pStreamAcc->LoadAllData(pStream);
1237     m_ObjectStreamMap.SetAt((void*)(FX_UINTPTR)objnum, pStreamAcc);
1238     return pStreamAcc;
1239 }
1240 FX_FILESIZE CPDF_Parser::GetObjectSize(FX_DWORD objnum)
1241 {
1242     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1243         return 0;
1244     }
1245     if (m_V5Type[objnum] == 2) {
1246         objnum = (FX_DWORD)m_CrossRef[objnum];
1247     }
1248     if (m_V5Type[objnum] == 1 || m_V5Type[objnum] == 255) {
1249         FX_FILESIZE offset = m_CrossRef[objnum];
1250         if (offset == 0) {
1251             return 0;
1252         }
1253         FX_LPVOID pResult = FXSYS_bsearch(&offset, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1254         if (pResult == NULL) {
1255             return 0;
1256         }
1257         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)m_SortedOffset.GetData() == m_SortedOffset.GetSize() - 1) {
1258             return 0;
1259         }
1260         return ((FX_FILESIZE*)pResult)[1] - offset;
1261     }
1262     return 0;
1263 }
1264 void CPDF_Parser::GetIndirectBinary(FX_DWORD objnum, FX_LPBYTE& pBuffer, FX_DWORD& size)
1265 {
1266     pBuffer = NULL;
1267     size = 0;
1268     if (objnum >= (FX_DWORD)m_CrossRef.GetSize()) {
1269         return;
1270     }
1271     if (m_V5Type[objnum] == 2) {
1272         CPDF_StreamAcc* pObjStream = GetObjectStream((FX_DWORD)m_CrossRef[objnum]);
1273         if (pObjStream == NULL) {
1274             return;
1275         }
1276         FX_INT32 n = pObjStream->GetDict()->GetInteger(FX_BSTRC("N"));
1277         FX_INT32 offset = pObjStream->GetDict()->GetInteger(FX_BSTRC("First"));
1278         CPDF_SyntaxParser syntax;
1279         FX_LPCBYTE pData = pObjStream->GetData();
1280         FX_DWORD totalsize = pObjStream->GetSize();
1281         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream((FX_LPBYTE)pData, (size_t)totalsize, FALSE));
1282         syntax.InitParser((IFX_FileStream*)file, 0);
1283         while (n) {
1284             FX_DWORD thisnum = syntax.GetDirectNum();
1285             FX_DWORD thisoff = syntax.GetDirectNum();
1286             if (thisnum == objnum) {
1287                 if (n == 1) {
1288                     size = totalsize - (thisoff + offset);
1289                 } else {
1290                     syntax.GetDirectNum();  // Skip nextnum.
1291                     FX_DWORD nextoff = syntax.GetDirectNum();
1292                     size = nextoff - thisoff;
1293                 }
1294                 pBuffer = FX_Alloc(FX_BYTE, size);
1295                 FXSYS_memcpy32(pBuffer, pData + thisoff + offset, size);
1296                 return;
1297             }
1298             n --;
1299         }
1300         return;
1301     }
1302     if (m_V5Type[objnum] == 1) {
1303         FX_FILESIZE pos = m_CrossRef[objnum];
1304         if (pos == 0) {
1305             return;
1306         }
1307         FX_FILESIZE SavedPos = m_Syntax.SavePos();
1308         m_Syntax.RestorePos(pos);
1309         FX_BOOL bIsNumber;
1310         CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1311         if (!bIsNumber) {
1312             m_Syntax.RestorePos(SavedPos);
1313             return;
1314         }
1315         FX_DWORD real_objnum = FXSYS_atoi(word);
1316         if (real_objnum && real_objnum != objnum) {
1317             m_Syntax.RestorePos(SavedPos);
1318             return;
1319         }
1320         word = m_Syntax.GetNextWord(bIsNumber);
1321         if (!bIsNumber) {
1322             m_Syntax.RestorePos(SavedPos);
1323             return;
1324         }
1325         if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1326             m_Syntax.RestorePos(SavedPos);
1327             return;
1328         }
1329         FX_LPVOID pResult = FXSYS_bsearch(&pos, m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1330         if (pResult == NULL) {
1331             m_Syntax.RestorePos(SavedPos);
1332             return;
1333         }
1334         FX_FILESIZE nextoff = ((FX_FILESIZE*)pResult)[1];
1335         FX_BOOL bNextOffValid = FALSE;
1336         if (nextoff != pos) {
1337             m_Syntax.RestorePos(nextoff);
1338             word = m_Syntax.GetNextWord(bIsNumber);
1339             if (word == FX_BSTRC("xref")) {
1340                 bNextOffValid = TRUE;
1341             } else if (bIsNumber) {
1342                 word = m_Syntax.GetNextWord(bIsNumber);
1343                 if (bIsNumber && m_Syntax.GetKeyword() == FX_BSTRC("obj")) {
1344                     bNextOffValid = TRUE;
1345                 }
1346             }
1347         }
1348         if (!bNextOffValid) {
1349             m_Syntax.RestorePos(pos);
1350             while (1) {
1351                 if (m_Syntax.GetKeyword() == FX_BSTRC("endobj")) {
1352                     break;
1353                 }
1354                 if (m_Syntax.SavePos() == m_Syntax.m_FileLen) {
1355                     break;
1356                 }
1357             }
1358             nextoff = m_Syntax.SavePos();
1359         }
1360         size = (FX_DWORD)(nextoff - pos);
1361         pBuffer = FX_Alloc(FX_BYTE, size);
1362         m_Syntax.RestorePos(pos);
1363         m_Syntax.ReadBlock(pBuffer, size);
1364         m_Syntax.RestorePos(SavedPos);
1365     }
1366 }
1367 CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
1368         PARSE_CONTEXT* pContext)
1369 {
1370     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1371     m_Syntax.RestorePos(pos);
1372     FX_BOOL bIsNumber;
1373     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1374     if (!bIsNumber) {
1375         m_Syntax.RestorePos(SavedPos);
1376         return NULL;
1377     }
1378     FX_FILESIZE objOffset = m_Syntax.SavePos();
1379     objOffset -= word.GetLength();
1380     FX_DWORD real_objnum = FXSYS_atoi(word);
1381     if (objnum && real_objnum != objnum) {
1382         m_Syntax.RestorePos(SavedPos);
1383         return NULL;
1384     }
1385     word = m_Syntax.GetNextWord(bIsNumber);
1386     if (!bIsNumber) {
1387         m_Syntax.RestorePos(SavedPos);
1388         return NULL;
1389     }
1390     FX_DWORD gennum = FXSYS_atoi(word);
1391     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1392         m_Syntax.RestorePos(SavedPos);
1393         return NULL;
1394     }
1395     CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, gennum, 0, pContext);
1396     FX_FILESIZE endOffset = m_Syntax.SavePos();
1397     CFX_ByteString bsWord = m_Syntax.GetKeyword();
1398     if (bsWord == FX_BSTRC("endobj")) {
1399         endOffset = m_Syntax.SavePos();
1400     }
1401     m_Syntax.RestorePos(SavedPos);
1402     if (pObj && !objnum) {
1403         pObj->m_ObjNum = real_objnum;
1404         pObj->m_GenNum = gennum;
1405     }
1406     return pObj;
1407 }
1408 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(CPDF_IndirectObjects* pObjList, FX_FILESIZE pos, FX_DWORD objnum,
1409         struct PARSE_CONTEXT* pContext, FX_FILESIZE *pResultPos)
1410 {
1411     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1412     m_Syntax.RestorePos(pos);
1413     FX_BOOL bIsNumber;
1414     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1415     if (!bIsNumber) {
1416         m_Syntax.RestorePos(SavedPos);
1417         return NULL;
1418     }
1419     FX_DWORD real_objnum = FXSYS_atoi(word);
1420     if (objnum && real_objnum != objnum) {
1421         m_Syntax.RestorePos(SavedPos);
1422         return NULL;
1423     }
1424     word = m_Syntax.GetNextWord(bIsNumber);
1425     if (!bIsNumber) {
1426         m_Syntax.RestorePos(SavedPos);
1427         return NULL;
1428     }
1429     FX_DWORD gennum = FXSYS_atoi(word);
1430     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1431         m_Syntax.RestorePos(SavedPos);
1432         return NULL;
1433     }
1434     CPDF_Object* pObj = m_Syntax.GetObjectByStrict(pObjList, objnum, gennum, 0, pContext);
1435     if (pResultPos) {
1436         *pResultPos = m_Syntax.m_Pos;
1437     }
1438     m_Syntax.RestorePos(SavedPos);
1439     return pObj;
1440 }
1441 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4()
1442 {
1443     if (m_Syntax.GetKeyword() != FX_BSTRC("trailer")) {
1444         return NULL;
1445     }
1446     CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
1447     if (pObj == NULL || pObj->GetType() != PDFOBJ_DICTIONARY) {
1448         if (pObj) {
1449             pObj->Release();
1450         }
1451         return NULL;
1452     }
1453     return (CPDF_Dictionary*)pObj;
1454 }
1455 FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision)
1456 {
1457     if (m_pSecurityHandler == NULL) {
1458         return (FX_DWORD) - 1;
1459     }
1460     FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions();
1461     if (m_pEncryptDict && m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) {
1462         dwPermission &= 0xFFFFFFFC;
1463         dwPermission |= 0xFFFFF0C0;
1464         if(bCheckRevision && m_pEncryptDict->GetInteger(FX_BSTRC("R")) == 2) {
1465             dwPermission &= 0xFFFFF0FF;
1466         }
1467     }
1468     return dwPermission;
1469 }
1470 FX_BOOL CPDF_Parser::IsOwner()
1471 {
1472     return m_pSecurityHandler == NULL ? TRUE : m_pSecurityHandler->IsOwner();
1473 }
1474 void CPDF_Parser::SetSecurityHandler(CPDF_SecurityHandler* pSecurityHandler, FX_BOOL bForced)
1475 {
1476     ASSERT(m_pSecurityHandler == NULL);
1477     if (m_pSecurityHandler && !m_bForceUseSecurityHandler) {
1478         delete m_pSecurityHandler;
1479         m_pSecurityHandler = NULL;
1480     }
1481     m_bForceUseSecurityHandler = bForced;
1482     m_pSecurityHandler = pSecurityHandler;
1483     if (m_bForceUseSecurityHandler) {
1484         return;
1485     }
1486     m_Syntax.m_pCryptoHandler = pSecurityHandler->CreateCryptoHandler();
1487     m_Syntax.m_pCryptoHandler->Init(NULL, pSecurityHandler);
1488 }
1489 FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, FX_DWORD offset)
1490 {
1491     m_Syntax.InitParser(pFileAccess, offset);
1492     m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9);
1493     FX_FILESIZE SavedPos = m_Syntax.SavePos();
1494     FX_BOOL bIsNumber;
1495     CFX_ByteString word = m_Syntax.GetNextWord(bIsNumber);
1496     if (!bIsNumber) {
1497         return FALSE;
1498     }
1499     FX_DWORD objnum = FXSYS_atoi(word);
1500     word = m_Syntax.GetNextWord(bIsNumber);
1501     if (!bIsNumber) {
1502         return FALSE;
1503     }
1504     FX_DWORD gennum = FXSYS_atoi(word);
1505     if (m_Syntax.GetKeyword() != FX_BSTRC("obj")) {
1506         m_Syntax.RestorePos(SavedPos);
1507         return FALSE;
1508     }
1509     m_pLinearized = m_Syntax.GetObject(NULL, objnum, gennum, 0);
1510     if (!m_pLinearized) {
1511         return FALSE;
1512     }
1513     if (m_pLinearized->GetDict() && m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
1514         m_Syntax.GetNextWord(bIsNumber);
1515         CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
1516         if (!pLen) {
1517             m_pLinearized->Release();
1518             m_pLinearized = NULL;
1519             return FALSE;
1520         }
1521         if (pLen->GetInteger() != (int)pFileAccess->GetSize()) {
1522             return FALSE;
1523         }
1524         CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
1525         if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
1526             m_dwFirstPageNo = pNo->GetInteger();
1527         }
1528         CPDF_Object *pTable = m_pLinearized->GetDict()->GetElement(FX_BSTRC("T"));
1529         if (pTable && pTable->GetType() == PDFOBJ_NUMBER) {
1530             m_LastXRefOffset = pTable->GetInteger();
1531         }
1532         return TRUE;
1533     }
1534     m_pLinearized->Release();
1535     m_pLinearized = NULL;
1536     return FALSE;
1537 }
1538 FX_DWORD CPDF_Parser::StartAsynParse(IFX_FileRead* pFileAccess, FX_BOOL bReParse, FX_BOOL bOwnFileRead)
1539 {
1540     CloseParser(bReParse);
1541     m_bXRefStream = FALSE;
1542     m_LastXRefOffset = 0;
1543     m_bOwnFileRead = bOwnFileRead;
1544     FX_INT32 offset = GetHeaderOffset(pFileAccess);
1545     if (offset == -1) {
1546         return PDFPARSE_ERROR_FORMAT;
1547     }
1548     if (!IsLinearizedFile(pFileAccess, offset)) {
1549         m_Syntax.m_pFileAccess = NULL;
1550         return StartParse(pFileAccess, bReParse, bOwnFileRead);
1551     }
1552     if (!bReParse) {
1553         m_pDocument = FX_NEW CPDF_Document(this);
1554     }
1555     FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos();
1556     FX_BOOL bXRefRebuilt = FALSE;
1557     FX_BOOL bLoadV4 = FALSE;
1558     if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE, FALSE)) && !LoadCrossRefV5(dwFirstXRefOffset, dwFirstXRefOffset, TRUE)) {
1559         if (!RebuildCrossRef()) {
1560             return PDFPARSE_ERROR_FORMAT;
1561         }
1562         bXRefRebuilt = TRUE;
1563         m_LastXRefOffset = 0;
1564     }
1565     if (bLoadV4) {
1566         m_pTrailer = LoadTrailerV4();
1567         if (m_pTrailer == NULL) {
1568             return FALSE;
1569         }
1570         FX_INT32 xrefsize = GetDirectInteger(m_pTrailer, FX_BSTRC("Size"));
1571         if (xrefsize == 0) {
1572             return FALSE;
1573         }
1574         m_CrossRef.SetSize(xrefsize);
1575         m_V5Type.SetSize(xrefsize);
1576     }
1577     FX_DWORD dwRet = SetEncryptHandler();
1578     if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1579         return dwRet;
1580     }
1581     m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1582     if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
1583         if (bXRefRebuilt) {
1584             return PDFPARSE_ERROR_FORMAT;
1585         }
1586         ReleaseEncryptHandler();
1587         if (!RebuildCrossRef()) {
1588             return PDFPARSE_ERROR_FORMAT;
1589         }
1590         dwRet = SetEncryptHandler();
1591         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1592             return dwRet;
1593         }
1594         m_pDocument->LoadAsynDoc(m_pLinearized->GetDict());
1595         if (m_pDocument->GetRoot() == NULL) {
1596             return PDFPARSE_ERROR_FORMAT;
1597         }
1598     }
1599     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1600     FX_DWORD RootObjNum = GetRootObjNum();
1601     if (RootObjNum == 0) {
1602         ReleaseEncryptHandler();
1603         RebuildCrossRef();
1604         RootObjNum = GetRootObjNum();
1605         if (RootObjNum == 0) {
1606             return PDFPARSE_ERROR_FORMAT;
1607         }
1608         dwRet = SetEncryptHandler();
1609         if (dwRet != PDFPARSE_ERROR_SUCCESS) {
1610             return dwRet;
1611         }
1612     }
1613     if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) {
1614         CPDF_Object* pMetadata = m_pDocument->GetRoot()->GetElement(FX_BSTRC("Metadata"));
1615         if (pMetadata && pMetadata->GetType() == PDFOBJ_REFERENCE) {
1616             m_Syntax.m_MetadataObjnum = ((CPDF_Reference*) pMetadata)->GetRefObjNum();
1617         }
1618     }
1619     return PDFPARSE_ERROR_SUCCESS;
1620 }
1621 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos)
1622 {
1623     if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1624         return FALSE;
1625     }
1626     while (xrefpos)
1627         if (!LoadCrossRefV5(xrefpos, xrefpos, FALSE)) {
1628             return FALSE;
1629         }
1630     m_ObjectStreamMap.InitHashTable(101, FALSE);
1631     m_bXRefStream = TRUE;
1632     return TRUE;
1633 }
1634 FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable()
1635 {
1636     FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum;
1637     m_Syntax.m_MetadataObjnum = 0;
1638     if (m_pTrailer) {
1639         m_pTrailer->Release();
1640         m_pTrailer = NULL;
1641     }
1642     m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset);
1643     FX_BYTE ch = 0;
1644     FX_DWORD dwCount = 0;
1645     m_Syntax.GetNextChar(ch);
1646     FX_INT32 type = _PDF_CharType[ch];
1647     while (type == 'W') {
1648         ++dwCount;
1649         if (m_Syntax.m_FileLen >= (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
1650             break;
1651         }
1652         m_Syntax.GetNextChar(ch);
1653         type = _PDF_CharType[ch];
1654     }
1655     m_LastXRefOffset += dwCount;
1656     FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
1657     while (pos) {
1658         FX_LPVOID objnum;
1659         CPDF_StreamAcc* pStream;
1660         m_ObjectStreamMap.GetNextAssoc(pos, objnum, (void*&)pStream);
1661         delete pStream;
1662     }
1663     m_ObjectStreamMap.RemoveAll();
1664     if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) {
1665         m_LastXRefOffset = 0;
1666         m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1667         return PDFPARSE_ERROR_FORMAT;
1668     }
1669     FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
1670     m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum;
1671     return PDFPARSE_ERROR_SUCCESS;
1672 }
1673 CPDF_SyntaxParser::CPDF_SyntaxParser()
1674 {
1675     m_pFileAccess = NULL;
1676     m_pCryptoHandler = NULL;
1677     m_pFileBuf = NULL;
1678     m_BufSize = CPDF_ModuleMgr::Get()->m_FileBufSize;
1679     m_pFileBuf = NULL;
1680     m_MetadataObjnum = 0;
1681     m_dwWordPos = 0;
1682 #if defined(_FPDFAPI_MINI_)
1683     m_bFileStream = TRUE;
1684 #else
1685     m_bFileStream = FALSE;
1686 #endif
1687 }
1688 CPDF_SyntaxParser::~CPDF_SyntaxParser()
1689 {
1690     if (m_pFileBuf) {
1691         FX_Free(m_pFileBuf);
1692     }
1693 }
1694 FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, FX_BYTE& ch)
1695 {
1696     FX_FILESIZE save_pos = m_Pos;
1697     m_Pos = pos;
1698     FX_BOOL ret = GetNextChar(ch);
1699     m_Pos = save_pos;
1700     return ret;
1701 }
1702 FX_BOOL CPDF_SyntaxParser::GetNextChar(FX_BYTE& ch)
1703 {
1704     FX_FILESIZE pos = m_Pos + m_HeaderOffset;
1705     if (pos >= m_FileLen) {
1706         return FALSE;
1707     }
1708     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1709         FX_FILESIZE read_pos = pos;
1710         FX_DWORD read_size = m_BufSize;
1711         if ((FX_FILESIZE)read_size > m_FileLen) {
1712             read_size = (FX_DWORD)m_FileLen;
1713         }
1714         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1715             if (m_FileLen < (FX_FILESIZE)read_size) {
1716                 read_pos = 0;
1717                 read_size = (FX_DWORD)m_FileLen;
1718             } else {
1719                 read_pos = m_FileLen - read_size;
1720             }
1721         }
1722         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1723             return FALSE;
1724         }
1725         m_BufOffset = read_pos;
1726     }
1727     ch = m_pFileBuf[pos - m_BufOffset];
1728     m_Pos ++;
1729     return TRUE;
1730 }
1731 FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, FX_BYTE& ch)
1732 {
1733     pos += m_HeaderOffset;
1734     if (pos >= m_FileLen) {
1735         return FALSE;
1736     }
1737     if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) {
1738         FX_FILESIZE read_pos;
1739         if (pos < (FX_FILESIZE)m_BufSize) {
1740             read_pos = 0;
1741         } else {
1742             read_pos = pos - m_BufSize + 1;
1743         }
1744         FX_DWORD read_size = m_BufSize;
1745         if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) {
1746             if (m_FileLen < (FX_FILESIZE)read_size) {
1747                 read_pos = 0;
1748                 read_size = (FX_DWORD)m_FileLen;
1749             } else {
1750                 read_pos = m_FileLen - read_size;
1751             }
1752         }
1753         if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) {
1754             return FALSE;
1755         }
1756         m_BufOffset = read_pos;
1757     }
1758     ch = m_pFileBuf[pos - m_BufOffset];
1759     return TRUE;
1760 }
1761 FX_BOOL CPDF_SyntaxParser::ReadBlock(FX_LPBYTE pBuf, FX_DWORD size)
1762 {
1763     if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) {
1764         return FALSE;
1765     }
1766     m_Pos += size;
1767     return TRUE;
1768 }
1769 #define MAX_WORD_BUFFER 256
1770 void CPDF_SyntaxParser::GetNextWord()
1771 {
1772     m_WordSize = 0;
1773     m_bIsNumber = TRUE;
1774     FX_BYTE ch;
1775     if (!GetNextChar(ch)) {
1776         return;
1777     }
1778     FX_BYTE type = _PDF_CharType[ch];
1779     while (1) {
1780         while (type == 'W') {
1781             if (!GetNextChar(ch)) {
1782                 return;
1783             }
1784             type = _PDF_CharType[ch];
1785         }
1786         if (ch != '%') {
1787             break;
1788         }
1789         while (1) {
1790             if (!GetNextChar(ch)) {
1791                 return;
1792             }
1793             if (ch == '\r' || ch == '\n') {
1794                 break;
1795             }
1796         }
1797         type = _PDF_CharType[ch];
1798     }
1799     if (type == 'D') {
1800         m_bIsNumber = FALSE;
1801         m_WordBuffer[m_WordSize++] = ch;
1802         if (ch == '/') {
1803             while (1) {
1804                 if (!GetNextChar(ch)) {
1805                     return;
1806                 }
1807                 type = _PDF_CharType[ch];
1808                 if (type != 'R' && type != 'N') {
1809                     m_Pos --;
1810                     return;
1811                 }
1812                 if (m_WordSize < MAX_WORD_BUFFER) {
1813                     m_WordBuffer[m_WordSize++] = ch;
1814                 }
1815             }
1816         } else if (ch == '<') {
1817             if (!GetNextChar(ch)) {
1818                 return;
1819             }
1820             if (ch == '<') {
1821                 m_WordBuffer[m_WordSize++] = ch;
1822             } else {
1823                 m_Pos --;
1824             }
1825         } else if (ch == '>') {
1826             if (!GetNextChar(ch)) {
1827                 return;
1828             }
1829             if (ch == '>') {
1830                 m_WordBuffer[m_WordSize++] = ch;
1831             } else {
1832                 m_Pos --;
1833             }
1834         }
1835         return;
1836     }
1837     while (1) {
1838         if (m_WordSize < MAX_WORD_BUFFER) {
1839             m_WordBuffer[m_WordSize++] = ch;
1840         }
1841         if (type != 'N') {
1842             m_bIsNumber = FALSE;
1843         }
1844         if (!GetNextChar(ch)) {
1845             return;
1846         }
1847         type = _PDF_CharType[ch];
1848         if (type == 'D' || type == 'W') {
1849             m_Pos --;
1850             break;
1851         }
1852     }
1853 }
1854 CFX_ByteString CPDF_SyntaxParser::ReadString()
1855 {
1856     FX_BYTE ch;
1857     if (!GetNextChar(ch)) {
1858         return CFX_ByteString();
1859     }
1860     CFX_ByteTextBuf buf;
1861     FX_INT32 parlevel = 0;
1862     FX_INT32 status = 0, iEscCode = 0;
1863     while (1) {
1864         switch (status) {
1865             case 0:
1866                 if (ch == ')') {
1867                     if (parlevel == 0) {
1868                         return buf.GetByteString();
1869                     }
1870                     parlevel --;
1871                     buf.AppendChar(')');
1872                 } else if (ch == '(') {
1873                     parlevel ++;
1874                     buf.AppendChar('(');
1875                 } else if (ch == '\\') {
1876                     status = 1;
1877                 } else {
1878                     buf.AppendChar(ch);
1879                 }
1880                 break;
1881             case 1:
1882                 if (ch >= '0' && ch <= '7') {
1883                     iEscCode = ch - '0';
1884                     status = 2;
1885                     break;
1886                 }
1887                 if (ch == 'n') {
1888                     buf.AppendChar('\n');
1889                 } else if (ch == 'r') {
1890                     buf.AppendChar('\r');
1891                 } else if (ch == 't') {
1892                     buf.AppendChar('\t');
1893                 } else if (ch == 'b') {
1894                     buf.AppendChar('\b');
1895                 } else if (ch == 'f') {
1896                     buf.AppendChar('\f');
1897                 } else if (ch == '\r') {
1898                     status = 4;
1899                     break;
1900                 } else if (ch == '\n') {
1901                 } else {
1902                     buf.AppendChar(ch);
1903                 }
1904                 status = 0;
1905                 break;
1906             case 2:
1907                 if (ch >= '0' && ch <= '7') {
1908                     iEscCode = iEscCode * 8 + ch - '0';
1909                     status = 3;
1910                 } else {
1911                     buf.AppendChar(iEscCode);
1912                     status = 0;
1913                     continue;
1914                 }
1915                 break;
1916             case 3:
1917                 if (ch >= '0' && ch <= '7') {
1918                     iEscCode = iEscCode * 8 + ch - '0';
1919                     buf.AppendChar(iEscCode);
1920                     status = 0;
1921                 } else {
1922                     buf.AppendChar(iEscCode);
1923                     status = 0;
1924                     continue;
1925                 }
1926                 break;
1927             case 4:
1928                 status = 0;
1929                 if (ch != '\n') {
1930                     continue;
1931                 }
1932                 break;
1933         }
1934         if (!GetNextChar(ch)) {
1935             break;
1936         }
1937     }
1938     GetNextChar(ch);
1939     return buf.GetByteString();
1940 }
1941 CFX_ByteString CPDF_SyntaxParser::ReadHexString()
1942 {
1943     FX_BYTE ch;
1944     if (!GetNextChar(ch)) {
1945         return CFX_ByteString();
1946     }
1947     CFX_BinaryBuf buf;
1948     FX_BOOL bFirst = TRUE;
1949     FX_BYTE code = 0;
1950     while (1) {
1951         if (ch == '>') {
1952             break;
1953         }
1954         if (ch >= '0' && ch <= '9') {
1955             if (bFirst) {
1956                 code = (ch - '0') * 16;
1957             } else {
1958                 code += ch - '0';
1959                 buf.AppendByte((FX_BYTE)code);
1960             }
1961             bFirst = !bFirst;
1962         } else if (ch >= 'A' && ch <= 'F') {
1963             if (bFirst) {
1964                 code = (ch - 'A' + 10) * 16;
1965             } else {
1966                 code += ch - 'A' + 10;
1967                 buf.AppendByte((FX_BYTE)code);
1968             }
1969             bFirst = !bFirst;
1970         } else if (ch >= 'a' && ch <= 'f') {
1971             if (bFirst) {
1972                 code = (ch - 'a' + 10) * 16;
1973             } else {
1974                 code += ch - 'a' + 10;
1975                 buf.AppendByte((FX_BYTE)code);
1976             }
1977             bFirst = !bFirst;
1978         }
1979         if (!GetNextChar(ch)) {
1980             break;
1981         }
1982     }
1983     if (!bFirst) {
1984         buf.AppendByte((FX_BYTE)code);
1985     }
1986     return buf.GetByteString();
1987 }
1988 void CPDF_SyntaxParser::ToNextLine()
1989 {
1990     FX_BYTE ch;
1991     while (1) {
1992         if (!GetNextChar(ch)) {
1993             return;
1994         }
1995         if (ch == '\n') {
1996             return;
1997         }
1998         if (ch == '\r') {
1999             GetNextChar(ch);
2000             if (ch == '\n') {
2001                 return;
2002             } else {
2003                 m_Pos --;
2004                 return;
2005             }
2006         }
2007     }
2008 }
2009 void CPDF_SyntaxParser::ToNextWord()
2010 {
2011     FX_BYTE ch;
2012     if (!GetNextChar(ch)) {
2013         return;
2014     }
2015     FX_BYTE type = _PDF_CharType[ch];
2016     while (1) {
2017         while (type == 'W') {
2018             m_dwWordPos = m_Pos;
2019             if (!GetNextChar(ch)) {
2020                 return;
2021             }
2022             type = _PDF_CharType[ch];
2023         }
2024         if (ch != '%') {
2025             break;
2026         }
2027         while (1) {
2028             if (!GetNextChar(ch)) {
2029                 return;
2030             }
2031             if (ch == '\r' || ch == '\n') {
2032                 break;
2033             }
2034         }
2035         type = _PDF_CharType[ch];
2036     }
2037     m_Pos --;
2038 }
2039 CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber)
2040 {
2041     GetNextWord();
2042     bIsNumber = m_bIsNumber;
2043     return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
2044 }
2045 CFX_ByteString CPDF_SyntaxParser::GetKeyword()
2046 {
2047     GetNextWord();
2048     return CFX_ByteString((FX_LPCSTR)m_WordBuffer, m_WordSize);
2049 }
2050 CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum, FX_INT32 level, PARSE_CONTEXT* pContext, FX_BOOL bDecrypt)
2051 {
2052     if (level > _PARSER_OBJECT_LEVLE_) {
2053         return NULL;
2054     }
2055     FX_FILESIZE SavedPos = m_Pos;
2056     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2057     FX_BOOL bIsNumber;
2058     CFX_ByteString word = GetNextWord(bIsNumber);
2059     CPDF_Object* pRet = NULL;
2060     if (word.GetLength() == 0) {
2061         if (bTypeOnly) {
2062             return (CPDF_Object*)PDFOBJ_INVALID;
2063         }
2064         return NULL;
2065     }
2066     if (bIsNumber) {
2067         FX_FILESIZE SavedPos = m_Pos;
2068         CFX_ByteString nextword = GetNextWord(bIsNumber);
2069         if (bIsNumber) {
2070             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2071             if (nextword2 == FX_BSTRC("R")) {
2072                 FX_DWORD objnum = FXSYS_atoi(word);
2073                 if (bTypeOnly) {
2074                     return (CPDF_Object*)PDFOBJ_REFERENCE;
2075                 }
2076                 pRet = CPDF_Reference::Create(pObjList, objnum);
2077                 return pRet;
2078             } else {
2079                 m_Pos = SavedPos;
2080                 if (bTypeOnly) {
2081                     return (CPDF_Object*)PDFOBJ_NUMBER;
2082                 }
2083                 pRet = CPDF_Number::Create(word);
2084                 return pRet;
2085             }
2086         } else {
2087             m_Pos = SavedPos;
2088             if (bTypeOnly) {
2089                 return (CPDF_Object*)PDFOBJ_NUMBER;
2090             }
2091             pRet = CPDF_Number::Create(word);
2092             return pRet;
2093         }
2094     }
2095     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2096         if (bTypeOnly) {
2097             return (CPDF_Object*)PDFOBJ_BOOLEAN;
2098         }
2099         pRet = CPDF_Boolean::Create(word == FX_BSTRC("true"));
2100         return pRet;
2101     }
2102     if (word == FX_BSTRC("null")) {
2103         if (bTypeOnly) {
2104             return (CPDF_Object*)PDFOBJ_NULL;
2105         }
2106         pRet = CPDF_Null::Create();
2107         return pRet;
2108     }
2109     if (word == FX_BSTRC("(")) {
2110         if (bTypeOnly) {
2111             return (CPDF_Object*)PDFOBJ_STRING;
2112         }
2113         CFX_ByteString str = ReadString();
2114         if (m_pCryptoHandler && bDecrypt) {
2115             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2116         }
2117         pRet = CPDF_String::Create(str, FALSE);
2118         return pRet;
2119     }
2120     if (word == FX_BSTRC("<")) {
2121         if (bTypeOnly) {
2122             return (CPDF_Object*)PDFOBJ_STRING;
2123         }
2124         CFX_ByteString str = ReadHexString();
2125         if (m_pCryptoHandler && bDecrypt) {
2126             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2127         }
2128         pRet = CPDF_String::Create(str, TRUE);
2129         return pRet;
2130     }
2131     if (word == FX_BSTRC("[")) {
2132         if (bTypeOnly) {
2133             return (CPDF_Object*)PDFOBJ_ARRAY;
2134         }
2135         CPDF_Array* pArray = CPDF_Array::Create();
2136         while (1) {
2137             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
2138             if (pObj == NULL) {
2139                 return pArray;
2140             }
2141             pArray->Add(pObj);
2142         }
2143     }
2144     if (word[0] == '/') {
2145         if (bTypeOnly) {
2146             return (CPDF_Object*)PDFOBJ_NAME;
2147         }
2148         pRet = CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2149         return pRet;
2150     }
2151     if (word == FX_BSTRC("<<")) {
2152         FX_FILESIZE saveDictOffset = m_Pos - 2;
2153         FX_DWORD dwDictSize = 0;
2154         if (bTypeOnly) {
2155             return (CPDF_Object*)PDFOBJ_DICTIONARY;
2156         }
2157         if (pContext) {
2158             pContext->m_DictStart = SavedPos;
2159         }
2160         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2161         FX_INT32 nKeys = 0;
2162         FX_FILESIZE dwSignValuePos = 0;
2163         while (1) {
2164             FX_BOOL bIsNumber;
2165             CFX_ByteString key = GetNextWord(bIsNumber);
2166             if (key.IsEmpty()) {
2167                 if (pDict)
2168                     pDict->Release();
2169                 return NULL;
2170             }
2171             FX_FILESIZE SavedPos = m_Pos - key.GetLength();
2172             if (key == FX_BSTRC(">>")) {
2173                 dwDictSize = m_Pos - saveDictOffset;
2174                 break;
2175             }
2176             if (key == FX_BSTRC("endobj")) {
2177                 dwDictSize = m_Pos - 6 - saveDictOffset;
2178                 m_Pos = SavedPos;
2179                 break;
2180             }
2181             if (key[0] != '/') {
2182                 continue;
2183             }
2184             nKeys ++;
2185             key = PDF_NameDecode(key);
2186             if (key == FX_BSTRC("/Contents")) {
2187                 dwSignValuePos = m_Pos;
2188             }
2189             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
2190             if (pObj == NULL) {
2191                 continue;
2192             }
2193             if (key.GetLength() == 1) {
2194                 pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2195             } else {
2196                 if (nKeys < 32) {
2197                     pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2198                 } else {
2199                     pDict->AddValue(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2200                 }
2201             }
2202         }
2203         if (IsSignatureDict(pDict)) {
2204             FX_FILESIZE dwSavePos = m_Pos;
2205             m_Pos = dwSignValuePos;
2206             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1, NULL, FALSE);
2207             pDict->SetAt(FX_BSTRC("Contents"), pObj);
2208             m_Pos = dwSavePos;
2209         }
2210         if (pContext) {
2211             pContext->m_DictEnd = m_Pos;
2212             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2213                 return pDict;
2214             }
2215         }
2216         FX_FILESIZE SavedPos = m_Pos;
2217         FX_BOOL bIsNumber;
2218         CFX_ByteString nextword = GetNextWord(bIsNumber);
2219         if (nextword == FX_BSTRC("stream")) {
2220             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2221             if (pStream) {
2222                 return pStream;
2223             }
2224             if (pDict)
2225                 pDict->Release();
2226             return NULL;
2227         } else {
2228             m_Pos = SavedPos;
2229             return pDict;
2230         }
2231     }
2232     if (word == FX_BSTRC(">>")) {
2233         m_Pos = SavedPos;
2234         return NULL;
2235     }
2236     if (bTypeOnly) {
2237         return (CPDF_Object*)PDFOBJ_INVALID;
2238     }
2239     return NULL;
2240 }
2241 CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(CPDF_IndirectObjects* pObjList, FX_DWORD objnum, FX_DWORD gennum,
2242         FX_INT32 level, struct PARSE_CONTEXT* pContext)
2243 {
2244     if (level > _PARSER_OBJECT_LEVLE_) {
2245         return NULL;
2246     }
2247     FX_FILESIZE SavedPos = m_Pos;
2248     FX_BOOL bTypeOnly = pContext && (pContext->m_Flags & PDFPARSE_TYPEONLY);
2249     FX_BOOL bIsNumber;
2250     CFX_ByteString word = GetNextWord(bIsNumber);
2251     if (word.GetLength() == 0) {
2252         if (bTypeOnly) {
2253             return (CPDF_Object*)PDFOBJ_INVALID;
2254         }
2255         return NULL;
2256     }
2257     if (bIsNumber) {
2258         FX_FILESIZE SavedPos = m_Pos;
2259         CFX_ByteString nextword = GetNextWord(bIsNumber);
2260         if (bIsNumber) {
2261             CFX_ByteString nextword2 = GetNextWord(bIsNumber);
2262             if (nextword2 == FX_BSTRC("R")) {
2263                 FX_DWORD objnum = FXSYS_atoi(word);
2264                 if (bTypeOnly) {
2265                     return (CPDF_Object*)PDFOBJ_REFERENCE;
2266                 }
2267                 return CPDF_Reference::Create(pObjList, objnum);
2268             } else {
2269                 m_Pos = SavedPos;
2270                 if (bTypeOnly) {
2271                     return (CPDF_Object*)PDFOBJ_NUMBER;
2272                 }
2273                 return CPDF_Number::Create(word);
2274             }
2275         } else {
2276             m_Pos = SavedPos;
2277             if (bTypeOnly) {
2278                 return (CPDF_Object*)PDFOBJ_NUMBER;
2279             }
2280             return CPDF_Number::Create(word);
2281         }
2282     }
2283     if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
2284         if (bTypeOnly) {
2285             return (CPDF_Object*)PDFOBJ_BOOLEAN;
2286         }
2287         return CPDF_Boolean::Create(word == FX_BSTRC("true"));
2288     }
2289     if (word == FX_BSTRC("null")) {
2290         if (bTypeOnly) {
2291             return (CPDF_Object*)PDFOBJ_NULL;
2292         }
2293         return CPDF_Null::Create();
2294     }
2295     if (word == FX_BSTRC("(")) {
2296         if (bTypeOnly) {
2297             return (CPDF_Object*)PDFOBJ_STRING;
2298         }
2299         CFX_ByteString str = ReadString();
2300         if (m_pCryptoHandler) {
2301             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2302         }
2303         return CPDF_String::Create(str, FALSE);
2304     }
2305     if (word == FX_BSTRC("<")) {
2306         if (bTypeOnly) {
2307             return (CPDF_Object*)PDFOBJ_STRING;
2308         }
2309         CFX_ByteString str = ReadHexString();
2310         if (m_pCryptoHandler) {
2311             m_pCryptoHandler->Decrypt(objnum, gennum, str);
2312         }
2313         return CPDF_String::Create(str, TRUE);
2314     }
2315     if (word == FX_BSTRC("[")) {
2316         if (bTypeOnly) {
2317             return (CPDF_Object*)PDFOBJ_ARRAY;
2318         }
2319         CPDF_Array* pArray = CPDF_Array::Create();
2320         while (1) {
2321             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
2322             if (pObj == NULL) {
2323                 if (m_WordBuffer[0] == ']') {
2324                     return pArray;
2325                 }
2326                 if (pArray)
2327                     pArray->Release();
2328                 return NULL;
2329             }
2330             pArray->Add(pObj);
2331         }
2332     }
2333     if (word[0] == '/') {
2334         if (bTypeOnly) {
2335             return (CPDF_Object*)PDFOBJ_NAME;
2336         }
2337         return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
2338     }
2339     if (word == FX_BSTRC("<<")) {
2340         if (bTypeOnly) {
2341             return (CPDF_Object*)PDFOBJ_DICTIONARY;
2342         }
2343         if (pContext) {
2344             pContext->m_DictStart = SavedPos;
2345         }
2346         CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
2347         while (1) {
2348             FX_BOOL bIsNumber;
2349             FX_FILESIZE SavedPos = m_Pos;
2350             CFX_ByteString key = GetNextWord(bIsNumber);
2351             if (key.IsEmpty()) {
2352                 if (pDict)
2353                     pDict->Release();
2354                 return NULL;
2355             }
2356             if (key == FX_BSTRC(">>")) {
2357                 break;
2358             }
2359             if (key == FX_BSTRC("endobj")) {
2360                 m_Pos = SavedPos;
2361                 break;
2362             }
2363             if (key[0] != '/') {
2364                 continue;
2365             }
2366             key = PDF_NameDecode(key);
2367             CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, level + 1);
2368             if (pObj == NULL) {
2369                 if (pDict)
2370                     pDict->Release();
2371                 FX_BYTE ch;
2372                 while (1) {
2373                     if (!GetNextChar(ch)) {
2374                         break;
2375                     }
2376                     if (ch == 0x0A || ch == 0x0D) {
2377                         break;
2378                     }
2379                 }
2380                 return NULL;
2381             }
2382             if (key.GetLength() == 1) {
2383                 pDict->SetAt(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2384             } else {
2385                 pDict->AddValue(CFX_ByteStringC(((FX_LPCSTR)key) + 1, key.GetLength() - 1), pObj);
2386             }
2387         }
2388         if (pContext) {
2389             pContext->m_DictEnd = m_Pos;
2390             if (pContext->m_Flags & PDFPARSE_NOSTREAM) {
2391                 return pDict;
2392             }
2393         }
2394         FX_FILESIZE SavedPos = m_Pos;
2395         FX_BOOL bIsNumber;
2396         CFX_ByteString nextword = GetNextWord(bIsNumber);
2397         if (nextword == FX_BSTRC("stream")) {
2398             CPDF_Stream* pStream = ReadStream(pDict, pContext, objnum, gennum);
2399             if (pStream) {
2400                 return pStream;
2401             }
2402             if (pDict)
2403                 pDict->Release();
2404             return NULL;
2405         } else {
2406             m_Pos = SavedPos;
2407             return pDict;
2408         }
2409     }
2410     if (word == FX_BSTRC(">>")) {
2411         m_Pos = SavedPos;
2412         return NULL;
2413     }
2414     if (bTypeOnly) {
2415         return (CPDF_Object*)PDFOBJ_INVALID;
2416     }
2417     return NULL;
2418 }
2419 CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, PARSE_CONTEXT* pContext,
2420         FX_DWORD objnum, FX_DWORD gennum)
2421 {
2422     CPDF_Object* pLenObj = pDict->GetElement(FX_BSTRC("Length"));
2423     FX_FILESIZE len = 0;
2424     if (pLenObj && ((pLenObj->GetType() != PDFOBJ_REFERENCE) ||
2425                     ((((CPDF_Reference*)pLenObj)->GetObjList() != NULL) &&
2426                      ((CPDF_Reference*)pLenObj)->GetRefObjNum() != objnum))) {
2427         len = pLenObj->GetInteger();
2428     }
2429
2430     ToNextLine();
2431     FX_FILESIZE StreamStartPos = m_Pos;
2432     if (pContext) {
2433         pContext->m_DataStart = m_Pos;
2434     }
2435
2436     base::CheckedNumeric<FX_FILESIZE> pos = m_Pos;
2437     pos += len;
2438     if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) {
2439         m_Pos = pos.ValueOrDie();
2440     } else {
2441         return NULL;
2442     }
2443
2444     CPDF_CryptoHandler* pCryptoHandler = objnum == (FX_DWORD)m_MetadataObjnum ? NULL : m_pCryptoHandler;
2445     if (pCryptoHandler == NULL) {
2446         GetNextWord();
2447         if (m_WordSize < 9 || FXSYS_memcmp32(m_WordBuffer, "endstream", 9)) {
2448             m_Pos = StreamStartPos;
2449             FX_FILESIZE offset = FindTag(FX_BSTRC("endstream"), 0);
2450             if (offset >= 0) {
2451                 FX_FILESIZE curPos = m_Pos;
2452                 m_Pos = StreamStartPos;
2453                 FX_FILESIZE endobjOffset = FindTag(FX_BSTRC("endobj"), 0);
2454                 if (endobjOffset < offset && endobjOffset >= 0) {
2455                     offset = endobjOffset;
2456                 } else {
2457                     m_Pos = curPos;
2458                 }
2459                 FX_BYTE byte1, byte2;
2460                 GetCharAt(StreamStartPos + offset - 1, byte1);
2461                 GetCharAt(StreamStartPos + offset - 2, byte2);
2462                 if (byte1 == 0x0a && byte2 == 0x0d) {
2463                     len -= 2;
2464                 } else if (byte1 == 0x0a || byte1 == 0x0d) {
2465                     len --;
2466                 }
2467                 len = (FX_DWORD)offset;
2468                 pDict->SetAtInteger(FX_BSTRC("Length"), len);
2469             } else {
2470                 m_Pos = StreamStartPos;
2471                 if (FindTag(FX_BSTRC("endobj"), 0) < 0) {
2472                     return NULL;
2473                 }
2474             }
2475         }
2476     }
2477     m_Pos = StreamStartPos;
2478     CPDF_Stream* pStream;
2479 #if defined(_FPDFAPI_MINI_) && !defined(_FXCORE_FEATURE_ALL_)
2480     pStream = FX_NEW CPDF_Stream(m_pFileAccess, pCryptoHandler, m_HeaderOffset + m_Pos, len, pDict, gennum);
2481     m_Pos += len;
2482 #else
2483     FX_LPBYTE pData = FX_Alloc(FX_BYTE, len);
2484     if (!pData) {
2485         return NULL;
2486     }
2487     ReadBlock(pData, len);
2488     if (pCryptoHandler) {
2489         CFX_BinaryBuf dest_buf;
2490         dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len));
2491         FX_LPVOID context = pCryptoHandler->DecryptStart(objnum, gennum);
2492         pCryptoHandler->DecryptStream(context, pData, len, dest_buf);
2493         pCryptoHandler->DecryptFinish(context, dest_buf);
2494         FX_Free(pData);
2495         pData = dest_buf.GetBuffer();
2496         len = dest_buf.GetSize();
2497         dest_buf.DetachBuffer();
2498     }
2499     pStream = FX_NEW CPDF_Stream(pData, len, pDict);
2500 #endif
2501     if (pContext) {
2502         pContext->m_DataEnd = pContext->m_DataStart + len;
2503     }
2504     StreamStartPos = m_Pos;
2505     GetNextWord();
2506     if (m_WordSize == 6 && 0 == FXSYS_memcmp32(m_WordBuffer, "endobj", 6)) {
2507         m_Pos = StreamStartPos;
2508     }
2509     return pStream;
2510 }
2511 void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess, FX_DWORD HeaderOffset)
2512 {
2513     if (m_pFileBuf) {
2514         FX_Free(m_pFileBuf);
2515         m_pFileBuf = NULL;
2516     }
2517     m_pFileBuf = FX_Alloc(FX_BYTE, m_BufSize);
2518     m_HeaderOffset = HeaderOffset;
2519     m_FileLen = pFileAccess->GetSize();
2520     m_Pos = 0;
2521     m_pFileAccess = pFileAccess;
2522     m_BufOffset = 0;
2523     pFileAccess->ReadBlock(m_pFileBuf, 0, (size_t)((FX_FILESIZE)m_BufSize > m_FileLen ? m_FileLen : m_BufSize));
2524 }
2525 FX_INT32 CPDF_SyntaxParser::GetDirectNum()
2526 {
2527     GetNextWord();
2528     if (!m_bIsNumber) {
2529         return 0;
2530     }
2531     m_WordBuffer[m_WordSize] = 0;
2532     return FXSYS_atoi((FX_LPCSTR)m_WordBuffer);
2533 }
2534 FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit, FX_LPCBYTE tag, FX_DWORD taglen)
2535 {
2536     FX_BYTE type = _PDF_CharType[tag[0]];
2537     FX_BOOL bCheckLeft = type != 'D' && type != 'W';
2538     type = _PDF_CharType[tag[taglen - 1]];
2539     FX_BOOL bCheckRight = type != 'D' || type != 'W';
2540     FX_BYTE ch;
2541     if (bCheckRight && startpos + (FX_INT32)taglen <= limit && GetCharAt(startpos + (FX_INT32)taglen, ch)) {
2542         FX_BYTE type = _PDF_CharType[ch];
2543         if (type == 'N' || type == 'R') {
2544             return FALSE;
2545         }
2546     }
2547     if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
2548         FX_BYTE type = _PDF_CharType[ch];
2549         if (type == 'N' || type == 'R') {
2550             return FALSE;
2551         }
2552     }
2553     return TRUE;
2554 }
2555 FX_BOOL CPDF_SyntaxParser::SearchWord(FX_BSTR tag, FX_BOOL bWholeWord, FX_BOOL bForward, FX_FILESIZE limit)
2556 {
2557     FX_INT32 taglen = tag.GetLength();
2558     if (taglen == 0) {
2559         return FALSE;
2560     }
2561     FX_FILESIZE pos = m_Pos;
2562     FX_INT32 offset = 0;
2563     if (!bForward) {
2564         offset = taglen - 1;
2565     }
2566     FX_LPCBYTE tag_data = tag;
2567     FX_BYTE byte;
2568     while (1) {
2569         if (bForward) {
2570             if (limit) {
2571                 if (pos >= m_Pos + limit) {
2572                     return FALSE;
2573                 }
2574             }
2575             if (!GetCharAt(pos, byte)) {
2576                 return FALSE;
2577             }
2578         } else {
2579             if (limit) {
2580                 if (pos <= m_Pos - limit) {
2581                     return FALSE;
2582                 }
2583             }
2584             if (!GetCharAtBackward(pos, byte)) {
2585                 return FALSE;
2586             }
2587         }
2588         if (byte == tag_data[offset]) {
2589             if (bForward) {
2590                 offset ++;
2591                 if (offset < taglen) {
2592                     pos ++;
2593                     continue;
2594                 }
2595             } else {
2596                 offset --;
2597                 if (offset >= 0) {
2598                     pos --;
2599                     continue;
2600                 }
2601             }
2602             FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos;
2603             if (!bWholeWord || IsWholeWord(startpos, limit, tag, taglen)) {
2604                 m_Pos = startpos;
2605                 return TRUE;
2606             }
2607         }
2608         if (bForward) {
2609             offset = byte == tag_data[0] ? 1 : 0;
2610             pos ++;
2611         } else {
2612             offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1;
2613             pos --;
2614         }
2615         if (pos < 0) {
2616             return FALSE;
2617         }
2618     }
2619     return FALSE;
2620 }
2621 struct _SearchTagRecord {
2622     FX_LPCBYTE  m_pTag;
2623     FX_DWORD    m_Len;
2624     FX_DWORD    m_Offset;
2625 };
2626 FX_INT32 CPDF_SyntaxParser::SearchMultiWord(FX_BSTR tags, FX_BOOL bWholeWord, FX_FILESIZE limit)
2627 {
2628     FX_INT32 ntags = 1, i;
2629     for (i = 0; i < tags.GetLength(); i ++)
2630         if (tags[i] == 0) {
2631             ntags ++;
2632         }
2633     _SearchTagRecord* pPatterns = FX_Alloc(_SearchTagRecord, ntags);
2634     FX_DWORD start = 0, itag = 0, max_len = 0;
2635     for (i = 0; i <= tags.GetLength(); i ++) {
2636         if (tags[i] == 0) {
2637             FX_DWORD len = i - start;
2638             if (len > max_len) {
2639                 max_len = len;
2640             }
2641             pPatterns[itag].m_pTag = tags.GetPtr() + start;
2642             pPatterns[itag].m_Len = len;
2643             pPatterns[itag].m_Offset = 0;
2644             start = i + 1;
2645             itag ++;
2646         }
2647     }
2648     FX_FILESIZE pos = m_Pos;
2649     FX_BYTE byte;
2650     GetCharAt(pos++, byte);
2651     FX_INT32 found = -1;
2652     while (1) {
2653         for (i = 0; i < ntags; i ++) {
2654             if (pPatterns[i].m_pTag[pPatterns[i].m_Offset] == byte) {
2655                 pPatterns[i].m_Offset ++;
2656                 if (pPatterns[i].m_Offset == pPatterns[i].m_Len) {
2657                     if (!bWholeWord || IsWholeWord(pos - pPatterns[i].m_Len, limit, pPatterns[i].m_pTag, pPatterns[i].m_Len)) {
2658                         found = i;
2659                         goto end;
2660                     } else {
2661                         if (pPatterns[i].m_pTag[0] == byte) {
2662                             pPatterns[i].m_Offset = 1;
2663                         } else {
2664                             pPatterns[i].m_Offset = 0;
2665                         }
2666                     }
2667                 }
2668             } else {
2669                 if (pPatterns[i].m_pTag[0] == byte) {
2670                     pPatterns[i].m_Offset = 1;
2671                 } else {
2672                     pPatterns[i].m_Offset = 0;
2673                 }
2674             }
2675         }
2676         if (limit && pos >= m_Pos + limit) {
2677             goto end;
2678         }
2679         if (!GetCharAt(pos, byte)) {
2680             goto end;
2681         }
2682         pos ++;
2683     }
2684 end:
2685     FX_Free(pPatterns);
2686     return found;
2687 }
2688 FX_FILESIZE CPDF_SyntaxParser::FindTag(FX_BSTR tag, FX_FILESIZE limit)
2689 {
2690     FX_INT32 taglen = tag.GetLength();
2691     FX_INT32 match = 0;
2692     limit += m_Pos;
2693     FX_FILESIZE startpos = m_Pos;
2694     while (1) {
2695         FX_BYTE ch;
2696         if (!GetNextChar(ch)) {
2697             return -1;
2698         }
2699         if (ch == tag[match]) {
2700             match ++;
2701             if (match == taglen) {
2702                 return m_Pos - startpos - taglen;
2703             }
2704         } else {
2705             match = ch == tag[0] ? 1 : 0;
2706         }
2707         if (limit && m_Pos == limit) {
2708             return -1;
2709         }
2710     }
2711     return -1;
2712 }
2713 void CPDF_SyntaxParser::GetBinary(FX_BYTE* buffer, FX_DWORD size)
2714 {
2715     FX_DWORD offset = 0;
2716     FX_BYTE ch;
2717     while (1) {
2718         if (!GetNextChar(ch)) {
2719             return;
2720         }
2721         buffer[offset++] = ch;
2722         if (offset == size) {
2723             break;
2724         }
2725     }
2726 }
2727 CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead)
2728 {
2729     m_pFileAvail = pFileAvail;
2730     m_pFileRead = pFileRead;
2731     m_Pos = 0;
2732     m_dwFileLen = 0;
2733     if (m_pFileRead) {
2734         m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
2735     }
2736     m_dwCurrentOffset = 0;
2737     m_WordSize = 0;
2738     m_dwXRefOffset = 0;
2739     m_bufferOffset = 0;
2740     m_dwFirstPageNo = 0;
2741     m_bufferSize = 0;
2742     m_PagesObjNum = 0;
2743     m_dwCurrentXRefSteam = 0;
2744     m_dwAcroFormObjNum = 0;
2745     m_dwInfoObjNum = 0;
2746     m_pDocument = 0;
2747     m_dwEncryptObjNum = 0;
2748     m_dwPrevXRefOffset = 0;
2749     m_dwLastXRefOffset = 0;
2750     m_bDocAvail = FALSE;
2751     m_bMainXRefLoadTried = FALSE;
2752     m_bDocAvail = FALSE;
2753     m_bLinearized = FALSE;
2754     m_bPagesLoad = FALSE;
2755     m_bPagesTreeLoad = FALSE;
2756     m_bMainXRefLoadedOK = FALSE;
2757     m_bAnnotsLoad = FALSE;
2758     m_bHaveAcroForm = FALSE;
2759     m_bAcroFormLoad = FALSE;
2760     m_bPageLoadedOK = FALSE;
2761     m_bNeedDownLoadResource = FALSE;
2762     m_bLinearizedFormParamLoad = FALSE;
2763     m_pLinearized = NULL;
2764     m_pRoot = NULL;
2765     m_pTrailer = NULL;
2766     m_pCurrentParser = NULL;
2767     m_pAcroForm = NULL;
2768     m_pPageDict = NULL;
2769     m_pPageResource = NULL;
2770     m_pageMapCheckState = NULL;
2771     m_docStatus = PDF_DATAAVAIL_HEADER;
2772     m_parser.m_bOwnFileRead = FALSE;
2773     m_bTotalLoadPageTree = FALSE;
2774     m_bCurPageDictLoadOK = FALSE;
2775     m_bLinearedDataOK = FALSE;
2776     m_pagesLoadState = NULL;
2777 }
2778 CPDF_DataAvail::~CPDF_DataAvail()
2779 {
2780     if (m_pLinearized)  {
2781         m_pLinearized->Release();
2782     }
2783     if (m_pRoot) {
2784         m_pRoot->Release();
2785     }
2786     if (m_pTrailer) {
2787         m_pTrailer->Release();
2788     }
2789     if (m_pageMapCheckState) {
2790         delete m_pageMapCheckState;
2791     }
2792     if (m_pagesLoadState) {
2793         delete m_pagesLoadState;
2794     }
2795     FX_INT32 i = 0;
2796     FX_INT32 iSize = m_arrayAcroforms.GetSize();
2797     for (i = 0; i < iSize; ++i) {
2798         ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release();
2799     }
2800 }
2801 void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc)
2802 {
2803     m_pDocument = pDoc;
2804 }
2805 FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset)
2806 {
2807     CPDF_Parser *pParser = (CPDF_Parser *)(m_pDocument->GetParser());
2808     if (pParser == NULL) {
2809         return 0;
2810     }
2811     if (objnum >= (FX_DWORD)pParser->m_CrossRef.GetSize()) {
2812         return 0;
2813     }
2814     if (pParser->m_V5Type[objnum] == 2) {
2815         objnum = (FX_DWORD)pParser->m_CrossRef[objnum];
2816     }
2817     if (pParser->m_V5Type[objnum] == 1 || pParser->m_V5Type[objnum] == 255) {
2818         offset = pParser->m_CrossRef[objnum];
2819         if (offset == 0) {
2820             return 0;
2821         }
2822         FX_LPVOID pResult = FXSYS_bsearch(&offset, pParser->m_SortedOffset.GetData(), pParser->m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
2823         if (pResult == NULL) {
2824             return 0;
2825         }
2826         if ((FX_FILESIZE*)pResult - (FX_FILESIZE*)pParser->m_SortedOffset.GetData() == pParser->m_SortedOffset.GetSize() - 1) {
2827             return 0;
2828         }
2829         return (FX_DWORD)(((FX_FILESIZE*)pResult)[1] - offset);
2830     }
2831     return 0;
2832 }
2833 FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array, FX_BOOL bParsePage, IFX_DownloadHints* pHints, CFX_PtrArray &ret_array)
2834 {
2835     if (!obj_array.GetSize()) {
2836         return TRUE;
2837     }
2838     FX_DWORD count = 0;
2839     CFX_PtrArray new_obj_array;
2840     FX_INT32 i = 0;
2841     for (i = 0; i < obj_array.GetSize(); i++) {
2842         CPDF_Object *pObj = (CPDF_Object *)obj_array[i];
2843         if (!pObj) {
2844             continue;
2845         }
2846         FX_INT32 type = pObj->GetType();
2847         switch (type) {
2848             case PDFOBJ_ARRAY: {
2849                     CPDF_Array *pArray = pObj->GetArray();
2850                     for (FX_DWORD k = 0; k < pArray->GetCount(); k++) {
2851                         new_obj_array.Add(pArray->GetElement(k));
2852                     }
2853                 }
2854                 break;
2855             case PDFOBJ_STREAM:
2856                 pObj = pObj->GetDict();
2857             case PDFOBJ_DICTIONARY: {
2858                     CPDF_Dictionary *pDict = pObj->GetDict();
2859                     if (pDict && pDict->GetString("Type") == "Page" && !bParsePage) {
2860                         continue;
2861                     }
2862                     FX_POSITION pos = pDict->GetStartPos();
2863                     while (pos) {
2864                         CPDF_Object *value;
2865                         CFX_ByteString key;
2866                         value = pDict->GetNextElement(pos, key);
2867                         if (key != "Parent") {
2868                             new_obj_array.Add(value);
2869                         }
2870                     }
2871                 }
2872                 break;
2873             case PDFOBJ_REFERENCE: {
2874                     CPDF_Reference *pRef = (CPDF_Reference*)pObj;
2875                     FX_DWORD dwNum = pRef->GetRefObjNum();
2876                     FX_FILESIZE offset;
2877                     FX_DWORD original_size = GetObjectSize(dwNum, offset);
2878                     base::CheckedNumeric<FX_DWORD> size = original_size;
2879                     if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) {
2880                         break;
2881                     }
2882                     
2883                     size += offset;
2884                     size += 512;
2885                     if (!size.IsValid()) {
2886                         break;
2887                     }
2888                     if (size.ValueOrDie() > m_dwFileLen) {
2889                         size = m_dwFileLen - offset;
2890                     } else {
2891                         size = original_size + 512;
2892                     }
2893                     if (!size.IsValid()) {
2894                         break;
2895                     }
2896                     if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
2897                         pHints->AddSegment(offset, size.ValueOrDie());
2898                         ret_array.Add(pObj);
2899                         count++;
2900                     } else if (!m_objnum_array.Find(dwNum)) {
2901                         m_objnum_array.AddObjNum(dwNum);
2902                         CPDF_Object *pReferred = m_pDocument->GetIndirectObject(pRef->GetRefObjNum(), NULL);
2903                         if (pReferred) {
2904                             new_obj_array.Add(pReferred);
2905                         }
2906                     }
2907                 }
2908                 break;
2909         }
2910     }
2911     if (count > 0) {
2912         FX_INT32 iSize = new_obj_array.GetSize();
2913         for (i = 0; i < iSize; ++i) {
2914             CPDF_Object *pObj = (CPDF_Object *)new_obj_array[i];
2915             FX_INT32 type = pObj->GetType();
2916             if (type == PDFOBJ_REFERENCE) {
2917                 CPDF_Reference *pRef = (CPDF_Reference *)pObj;
2918                 FX_DWORD dwNum = pRef->GetRefObjNum();
2919                 if (!m_objnum_array.Find(dwNum)) {
2920                     ret_array.Add(pObj);
2921                 }
2922             } else {
2923                 ret_array.Add(pObj);
2924             }
2925         }
2926         return FALSE;
2927     }
2928     obj_array.RemoveAll();
2929     obj_array.Append(new_obj_array);
2930     return IsObjectsAvail(obj_array, FALSE, pHints, ret_array);
2931 }
2932 FX_BOOL CPDF_DataAvail::IsDocAvail(IFX_DownloadHints* pHints)
2933 {
2934     if (!m_dwFileLen && m_pFileRead) {
2935         m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
2936         if (!m_dwFileLen) {
2937             return TRUE;
2938         }
2939     }
2940     while (!m_bDocAvail) {
2941         if (!CheckDocStatus(pHints)) {
2942             return FALSE;
2943         }
2944     }
2945     return TRUE;
2946 }
2947 FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints)
2948 {
2949     if (!m_objs_array.GetSize()) {
2950         m_objs_array.RemoveAll();
2951         m_objnum_array.RemoveAll();
2952         CFX_PtrArray obj_array;
2953         obj_array.Append(m_arrayAcroforms);
2954         FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array);
2955         if (bRet) {
2956             m_objs_array.RemoveAll();
2957         }
2958         return bRet;
2959     } else {
2960         CFX_PtrArray new_objs_array;
2961         FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
2962         if (bRet) {
2963             FX_INT32 iSize = m_arrayAcroforms.GetSize();
2964             for (FX_INT32 i = 0; i < iSize; ++i) {
2965                 ((CPDF_Object *)m_arrayAcroforms.GetAt(i))->Release();
2966             }
2967             m_arrayAcroforms.RemoveAll();
2968         } else {
2969             m_objs_array.RemoveAll();
2970             m_objs_array.Append(new_objs_array);
2971         }
2972         return bRet;
2973     }
2974 }
2975 FX_BOOL CPDF_DataAvail::CheckAcroForm(IFX_DownloadHints* pHints)
2976 {
2977     FX_BOOL bExist = FALSE;
2978     m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist);
2979     if (!bExist) {
2980         m_docStatus = PDF_DATAAVAIL_PAGETREE;
2981         return TRUE;
2982     }
2983     if (!m_pAcroForm) {
2984         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
2985             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
2986             return TRUE;
2987         }
2988         return FALSE;
2989     }
2990     m_arrayAcroforms.Add(m_pAcroForm);
2991     m_docStatus = PDF_DATAAVAIL_PAGETREE;
2992     return TRUE;
2993 }
2994 FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints *pHints)
2995 {
2996     switch (m_docStatus) {
2997         case PDF_DATAAVAIL_HEADER:
2998             return CheckHeader(pHints);
2999         case PDF_DATAAVAIL_FIRSTPAGE:
3000         case PDF_DATAAVAIL_FIRSTPAGE_PREPARE:
3001             return CheckFirstPage(pHints);
3002         case PDF_DATAAVAIL_END:
3003             return CheckEnd(pHints);
3004         case PDF_DATAAVAIL_CROSSREF:
3005             return CheckCrossRef(pHints);
3006         case PDF_DATAAVAIL_CROSSREF_ITEM:
3007             return CheckCrossRefItem(pHints);
3008         case PDF_DATAAVAIL_CROSSREF_STREAM:
3009             return CheckAllCrossRefStream(pHints);
3010         case PDF_DATAAVAIL_TRAILER:
3011             return CheckTrailer(pHints);
3012         case PDF_DATAAVAIL_TRAILER_APPEND:
3013             return CheckTrailerAppend(pHints);
3014         case PDF_DATAAVAIL_LOADALLCRSOSSREF:
3015             return LoadAllXref(pHints);
3016         case PDF_DATAAVAIL_LOADALLFILE:
3017             return LoadAllFile(pHints);
3018         case PDF_DATAAVAIL_ROOT:
3019             return CheckRoot(pHints);
3020         case PDF_DATAAVAIL_INFO:
3021             return CheckInfo(pHints);
3022         case PDF_DATAAVAIL_ACROFORM:
3023             return CheckAcroForm(pHints);
3024         case PDF_DATAAVAIL_PAGETREE:
3025             if (m_bTotalLoadPageTree) {
3026                 return CheckPages(pHints);
3027             } else {
3028                 return LoadDocPages(pHints);
3029             }
3030         case PDF_DATAAVAIL_PAGE:
3031             if (m_bTotalLoadPageTree) {
3032                 return CheckPage(pHints);
3033             } else {
3034                 m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD;
3035                 return TRUE;
3036             }
3037         case PDF_DATAAVAIL_ERROR:
3038             return LoadAllFile(pHints);
3039         case PDF_DATAAVAIL_PAGE_LATERLOAD:
3040             m_docStatus = PDF_DATAAVAIL_PAGE;
3041         default:
3042             m_bDocAvail = TRUE;
3043             return TRUE;
3044     }
3045 }
3046 FX_BOOL CPDF_DataAvail::CheckPageStatus(IFX_DownloadHints* pHints)
3047 {
3048     switch (m_docStatus) {
3049         case PDF_DATAAVAIL_PAGETREE:
3050             return CheckPages(pHints);
3051         case PDF_DATAAVAIL_PAGE:
3052             return CheckPage(pHints);
3053         case PDF_DATAAVAIL_ERROR:
3054             return LoadAllFile(pHints);
3055         default:
3056             m_bPagesTreeLoad = TRUE;
3057             m_bPagesLoad = TRUE;
3058             return TRUE;
3059     }
3060 }
3061 FX_BOOL CPDF_DataAvail::LoadAllFile(IFX_DownloadHints* pHints)
3062 {
3063     if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) {
3064         m_docStatus = PDF_DATAAVAIL_DONE;
3065         return TRUE;
3066     }
3067     pHints->AddSegment(0, (FX_DWORD)m_dwFileLen);
3068     return FALSE;
3069 }
3070 FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints)
3071 {
3072     m_parser.m_Syntax.InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset);
3073     m_parser.m_bOwnFileRead = FALSE;
3074     if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) {
3075         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3076         return FALSE;
3077     }
3078     FXSYS_qsort(m_parser.m_SortedOffset.GetData(), m_parser.m_SortedOffset.GetSize(), sizeof(FX_FILESIZE), _CompareFileSize);
3079     m_dwRootObjNum = m_parser.GetRootObjNum();
3080     m_dwInfoObjNum = m_parser.GetInfoObjNum();
3081     m_pCurrentParser = &m_parser;
3082     m_docStatus = PDF_DATAAVAIL_ROOT;
3083     return TRUE;
3084 }
3085 CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum, IFX_DownloadHints* pHints, FX_BOOL *pExistInFile)
3086 {
3087     CPDF_Object *pRet         = NULL;
3088     FX_DWORD    original_size = 0;
3089     FX_FILESIZE offset        = 0;
3090     CPDF_Parser *pParser      = NULL;
3091
3092     if (pExistInFile) { 
3093         *pExistInFile = TRUE;
3094     }
3095
3096     if (m_pDocument == NULL) {
3097         original_size = (FX_DWORD)m_parser.GetObjectSize(objnum);
3098         offset        = m_parser.GetObjectOffset(objnum);
3099         pParser       = &m_parser; 
3100     } else {
3101         original_size = GetObjectSize(objnum, offset);
3102         pParser       = (CPDF_Parser *)(m_pDocument->GetParser());
3103     }
3104
3105     base::CheckedNumeric<FX_DWORD> size = original_size;
3106     if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) {
3107         if (pExistInFile)
3108            *pExistInFile = FALSE;
3109
3110         return NULL;
3111     }
3112  
3113     size += offset;
3114     size += 512;
3115     if (!size.IsValid()) {
3116         return NULL;
3117     }
3118
3119     if (size.ValueOrDie() > m_dwFileLen) {
3120         size = m_dwFileLen - offset;
3121     } else {
3122         size = original_size + 512;
3123     }
3124
3125     if (!size.IsValid()) {
3126         return NULL;
3127     }
3128
3129     if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
3130         pHints->AddSegment(offset, size.ValueOrDie());
3131         return NULL;
3132     }
3133
3134     if (pParser) {
3135         pRet = pParser->ParseIndirectObject(NULL, objnum, NULL);
3136     }
3137
3138     if (!pRet && pExistInFile) {
3139         *pExistInFile = FALSE;
3140     }
3141  
3142     return pRet;
3143 }
3144
3145 FX_BOOL CPDF_DataAvail::CheckInfo(IFX_DownloadHints* pHints)
3146 {
3147     FX_BOOL bExist = FALSE;
3148     CPDF_Object *pInfo = GetObject(m_dwInfoObjNum, pHints, &bExist);
3149     if (!bExist) {
3150         if (m_bHaveAcroForm) {
3151             m_docStatus = PDF_DATAAVAIL_ACROFORM;
3152         } else {
3153             m_docStatus = PDF_DATAAVAIL_PAGETREE;
3154         }
3155         return TRUE;
3156     }
3157     if (!pInfo) {
3158         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3159             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3160             return TRUE;
3161         }
3162         if (m_Pos == m_dwFileLen) {
3163             m_docStatus = PDF_DATAAVAIL_ERROR;
3164         }
3165         return FALSE;
3166     }
3167     if (pInfo) {
3168         pInfo->Release();
3169     }
3170     if (m_bHaveAcroForm) {
3171         m_docStatus = PDF_DATAAVAIL_ACROFORM;
3172     } else {
3173         m_docStatus = PDF_DATAAVAIL_PAGETREE;
3174     }
3175     return TRUE;
3176 }
3177 FX_BOOL CPDF_DataAvail::CheckRoot(IFX_DownloadHints* pHints)
3178 {
3179     FX_BOOL bExist = FALSE;
3180     m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist);
3181     if (!bExist) {
3182         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3183         return TRUE;
3184     }
3185     if (!m_pRoot) {
3186         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3187             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3188             return TRUE;
3189         }
3190         return FALSE;
3191     }
3192     CPDF_Reference* pRef = (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("Pages"));
3193     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
3194         m_docStatus = PDF_DATAAVAIL_ERROR;
3195         return FALSE;
3196     }
3197     m_PagesObjNum = pRef->GetRefObjNum();
3198     CPDF_Reference* pAcroFormRef = (CPDF_Reference*)m_pRoot->GetDict()->GetElement(FX_BSTRC("AcroForm"));
3199     if (pAcroFormRef && pAcroFormRef->GetType() == PDFOBJ_REFERENCE) {
3200         m_bHaveAcroForm = TRUE;
3201         m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum();
3202     }
3203     if (m_dwInfoObjNum) {
3204         m_docStatus = PDF_DATAAVAIL_INFO;
3205     } else {
3206         if (m_bHaveAcroForm) {
3207             m_docStatus = PDF_DATAAVAIL_ACROFORM;
3208         } else {
3209             m_docStatus = PDF_DATAAVAIL_PAGETREE;
3210         }
3211     }
3212     return TRUE;
3213 }
3214 FX_BOOL CPDF_DataAvail::PreparePageItem()
3215 {
3216     CPDF_Dictionary *pRoot = m_pDocument->GetRoot();
3217     CPDF_Reference* pRef = pRoot ? (CPDF_Reference*)pRoot->GetElement(FX_BSTRC("Pages")) : NULL;
3218     if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) {
3219         m_docStatus = PDF_DATAAVAIL_ERROR;
3220         return FALSE;
3221     }
3222     m_PagesObjNum = pRef->GetRefObjNum();
3223     m_pCurrentParser = (CPDF_Parser *)m_pDocument->GetParser();
3224     m_docStatus = PDF_DATAAVAIL_PAGETREE;
3225     return TRUE;
3226 }
3227 FX_BOOL CPDF_DataAvail::IsFirstCheck(int iPage)
3228 {
3229     if (NULL == m_pageMapCheckState) {
3230         m_pageMapCheckState = FX_NEW CFX_CMapDWordToDWord();
3231     }
3232     FX_DWORD dwValue = 0;
3233     if (!m_pageMapCheckState->Lookup(iPage, dwValue)) {
3234         m_pageMapCheckState->SetAt(iPage, 1);
3235         return TRUE;
3236     }
3237     if (dwValue != 0) {
3238         return FALSE;
3239     }
3240     m_pageMapCheckState->SetAt(iPage, 1);
3241     return TRUE;
3242 }
3243 void CPDF_DataAvail::ResetFirstCheck(int iPage)
3244 {
3245     if (NULL == m_pageMapCheckState) {
3246         m_pageMapCheckState = FX_NEW CFX_CMapDWordToDWord();
3247     }
3248     FX_DWORD dwValue = 1;
3249     if (!m_pageMapCheckState->Lookup(iPage, dwValue)) {
3250         return;
3251     }
3252     m_pageMapCheckState->SetAt(iPage, 0);
3253 }
3254 FX_BOOL CPDF_DataAvail::CheckPage(IFX_DownloadHints* pHints)
3255 {
3256     FX_DWORD iPageObjs = m_PageObjList.GetSize();
3257     CFX_DWordArray UnavailObjList;
3258     for (FX_DWORD i = 0; i < iPageObjs; ++i) {
3259         FX_DWORD dwPageObjNum = m_PageObjList.GetAt(i);
3260         FX_BOOL bExist = FALSE;
3261         CPDF_Object *pObj = GetObject(dwPageObjNum, pHints, &bExist);
3262         if (!pObj) {
3263             if (bExist) {
3264                 UnavailObjList.Add(dwPageObjNum);
3265             }
3266             continue;
3267         }
3268         if (pObj->GetType() == PDFOBJ_ARRAY) {
3269             CPDF_Array *pArray = pObj->GetArray();
3270             if (pArray) {
3271                 FX_INT32 iSize = pArray->GetCount();
3272                 CPDF_Object *pItem = NULL;
3273                 for (FX_INT32 j = 0; j < iSize; ++j) {
3274                     pItem = pArray->GetElement(j);
3275                     if (pItem && pItem->GetType() == PDFOBJ_REFERENCE) {
3276                         UnavailObjList.Add(((CPDF_Reference *)pItem)->GetRefObjNum());
3277                     }
3278                 }
3279             }
3280         }
3281         if (pObj->GetType() != PDFOBJ_DICTIONARY) {
3282             pObj->Release();
3283             continue;
3284         }
3285         CFX_ByteString type = pObj->GetDict()->GetString(FX_BSTRC("Type"));
3286         if (type == FX_BSTRC("Pages")) {
3287             m_PagesArray.Add(pObj);
3288             continue;
3289         }
3290         pObj->Release();
3291     }
3292     m_PageObjList.RemoveAll();
3293     if (UnavailObjList.GetSize()) {
3294         m_PageObjList.Append(UnavailObjList);
3295         return FALSE;
3296     }
3297     FX_DWORD iPages = m_PagesArray.GetSize();
3298     for (FX_DWORD i = 0; i < iPages; i++) {
3299         CPDF_Object *pPages = (CPDF_Object *)m_PagesArray.GetAt(i);
3300         if (!pPages) {
3301             continue;
3302         }
3303         if (!GetPageKids(m_pCurrentParser, pPages)) {
3304             pPages->Release();
3305             while (++i < iPages) {
3306                 pPages = (CPDF_Object *)m_PagesArray.GetAt(i);
3307                 pPages->Release();
3308             }
3309             m_PagesArray.RemoveAll();
3310             m_docStatus = PDF_DATAAVAIL_ERROR;
3311             return FALSE;
3312         }
3313         pPages->Release();
3314     }
3315     m_PagesArray.RemoveAll();
3316     if (!m_PageObjList.GetSize()) {
3317         m_docStatus = PDF_DATAAVAIL_DONE;
3318     }
3319     return TRUE;
3320 }
3321 FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser *pParser, CPDF_Object *pPages)
3322 {
3323     if (!pParser) {
3324         m_docStatus = PDF_DATAAVAIL_ERROR;
3325         return FALSE;
3326     }
3327     CPDF_Dictionary* pDict = pPages->GetDict();
3328     CPDF_Object *pKids = pDict ? pDict->GetElement(FX_BSTRC("Kids")) : NULL;
3329     if (!pKids) {
3330         return TRUE;
3331     }
3332     switch (pKids->GetType()) {
3333         case PDFOBJ_REFERENCE: {
3334                 CPDF_Reference *pKid = (CPDF_Reference *)pKids;
3335                 m_PageObjList.Add(pKid->GetRefObjNum());
3336             }
3337             break;
3338         case PDFOBJ_ARRAY: {
3339                 CPDF_Array *pKidsArray = (CPDF_Array *)pKids;
3340                 for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) {
3341                     CPDF_Object *pKid = (CPDF_Object *)pKidsArray->GetElement(i);
3342                     if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) {
3343                         m_PageObjList.Add(((CPDF_Reference *)pKid)->GetRefObjNum());
3344                     }
3345                 }
3346             }
3347             break;
3348         default:
3349             m_docStatus = PDF_DATAAVAIL_ERROR;
3350             return FALSE;
3351     }
3352     return TRUE;
3353 }
3354 FX_BOOL CPDF_DataAvail::CheckPages(IFX_DownloadHints* pHints)
3355 {
3356     FX_BOOL bExist = FALSE;
3357     CPDF_Object *pPages = GetObject(m_PagesObjNum, pHints, &bExist);
3358     if (!bExist) {
3359         m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3360         return TRUE;
3361     }
3362     if (!pPages) {
3363         if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3364             m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3365             return TRUE;
3366         }
3367         return FALSE;
3368     }
3369     if (!GetPageKids(m_pCurrentParser, pPages)) {
3370         pPages->Release();
3371         m_docStatus = PDF_DATAAVAIL_ERROR;
3372         return FALSE;
3373     }
3374     pPages->Release();
3375     m_docStatus = PDF_DATAAVAIL_PAGE;
3376     return TRUE;
3377 }
3378 FX_BOOL CPDF_DataAvail::CheckHeader(IFX_DownloadHints* pHints)
3379 {
3380     FX_DWORD req_size = 1024;
3381     if ((FX_FILESIZE)req_size > m_dwFileLen) {
3382         req_size = (FX_DWORD)m_dwFileLen;
3383     }
3384     if (m_pFileAvail->IsDataAvail(0, req_size)) {
3385         FX_BYTE buffer[1024];
3386         m_pFileRead->ReadBlock(buffer, 0, req_size);
3387         if (IsLinearizedFile(buffer, req_size)) {
3388             m_docStatus = PDF_DATAAVAIL_FIRSTPAGE;
3389         } else {
3390             if (m_docStatus == PDF_DATAAVAIL_ERROR) {
3391                 return FALSE;
3392             }
3393             m_docStatus = PDF_DATAAVAIL_END;
3394         }
3395         return TRUE;
3396     }
3397     pHints->AddSegment(0, req_size);
3398     return FALSE;
3399 }
3400 FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints *pHints)
3401 {
3402     CPDF_Dictionary* pDict = m_pLinearized->GetDict();
3403     CPDF_Object *pEndOffSet = pDict ? pDict->GetElement(FX_BSTRC("E")) : NULL;
3404     if (!pEndOffSet) {
3405         m_docStatus = PDF_DATAAVAIL_ERROR;
3406         return FALSE;
3407     }
3408     CPDF_Object *pXRefOffset = pDict ? pDict->GetElement(FX_BSTRC("T")) : NULL;
3409     if (!pXRefOffset) {
3410         m_docStatus = PDF_DATAAVAIL_ERROR;
3411         return FALSE;
3412     }
3413     CPDF_Object *pFileLen = pDict ? pDict->GetElement(FX_BSTRC("L")) : NULL;
3414     if (!pFileLen) {
3415         m_docStatus = PDF_DATAAVAIL_ERROR;
3416         return FALSE;
3417     }
3418     FX_BOOL bNeedDownLoad = FALSE;
3419     if (pEndOffSet->GetType() == PDFOBJ_NUMBER) {
3420         FX_DWORD dwEnd = pEndOffSet->GetInteger();
3421         dwEnd += 512;
3422         if ((FX_FILESIZE)dwEnd > m_dwFileLen) {
3423             dwEnd = (FX_DWORD)m_dwFileLen;
3424         }
3425         FX_INT32 iStartPos = (FX_INT32)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen);
3426         FX_INT32 iSize = dwEnd > 1024 ? dwEnd - 1024 : 0;
3427         if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) {
3428             pHints->AddSegment(iStartPos, iSize);
3429             bNeedDownLoad = TRUE;
3430         }
3431     }
3432     m_dwLastXRefOffset = 0;
3433     FX_FILESIZE dwFileLen = 0;
3434     if (pXRefOffset->GetType() == PDFOBJ_NUMBER) {
3435         m_dwLastXRefOffset = pXRefOffset->GetInteger();
3436     }
3437     if (pFileLen->GetType() == PDFOBJ_NUMBER) {
3438         dwFileLen = pFileLen->GetInteger();
3439     }
3440     if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, (FX_DWORD)(dwFileLen - m_dwLastXRefOffset))) {
3441         if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE)     {
3442             FX_DWORD dwSize = (FX_DWORD)(dwFileLen - m_dwLastXRefOffset);
3443             FX_FILESIZE offset = m_dwLastXRefOffset;
3444             if (dwSize < 512 && dwFileLen > 512) {
3445                 dwSize = 512;
3446                 offset = dwFileLen - 512;
3447             }
3448             pHints->AddSegment(offset, dwSize);
3449         }
3450     } else {
3451         m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
3452     }
3453     if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
3454         m_docStatus = PDF_DATAAVAIL_DONE;
3455         return TRUE;
3456     }
3457     m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
3458     return FALSE;
3459 }
3460 CPDF_Object     * CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD objnum)
3461 {
3462     FX_FILESIZE SavedPos = m_syntaxParser.SavePos();
3463     m_syntaxParser.RestorePos(pos);
3464     FX_BOOL bIsNumber;
3465     CFX_ByteString word = m_syntaxParser.GetNextWord(bIsNumber);
3466     if (!bIsNumber) {
3467         return NULL;
3468     }
3469     FX_DWORD real_objnum = FXSYS_atoi(word);
3470     if (objnum && real_objnum != objnum) {
3471         return NULL;
3472     }
3473     word = m_syntaxParser.GetNextWord(bIsNumber);
3474     if (!bIsNumber) {
3475         return NULL;
3476     }
3477     FX_DWORD gennum = FXSYS_atoi(word);
3478     if (m_syntaxParser.GetKeyword() != FX_BSTRC("obj")) {
3479         m_syntaxParser.RestorePos(SavedPos);
3480         return NULL;
3481     }
3482     CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0);
3483     m_syntaxParser.RestorePos(SavedPos);
3484     return pObj;
3485 }
3486 FX_INT32 CPDF_DataAvail::IsLinearizedPDF()
3487 {
3488     FX_DWORD req_size = 1024;
3489     if (!m_pFileAvail->IsDataAvail(0, req_size)) {
3490         return PDF_UNKNOW_LINEARIZED;
3491     }
3492     if (!m_pFileRead) {
3493         return PDF_NOT_LINEARIZED;
3494     }
3495     FX_FILESIZE dwSize = m_pFileRead->GetSize();
3496     if (dwSize < (FX_FILESIZE)req_size) {
3497         return PDF_UNKNOW_LINEARIZED;
3498     }
3499     FX_BYTE buffer[1024];
3500     m_pFileRead->ReadBlock(buffer, 0, req_size);
3501     if (IsLinearizedFile(buffer, req_size)) {
3502         return PDF_IS_LINEARIZED;
3503     }
3504     return PDF_NOT_LINEARIZED;
3505 }
3506 FX_BOOL CPDF_DataAvail::IsLinearizedFile(FX_LPBYTE pData, FX_DWORD dwLen)
3507 {
3508     CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE));
3509     FX_INT32 offset = GetHeaderOffset((IFX_FileStream*)file);
3510     if (offset == -1) {
3511         m_docStatus = PDF_DATAAVAIL_ERROR;
3512         return FALSE;
3513     }
3514     m_dwHeaderOffset = offset;
3515     m_syntaxParser.InitParser((IFX_FileStream*)file, offset);
3516     m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9);
3517     FX_BOOL bNumber = FALSE;
3518     CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(bNumber);
3519     if (!bNumber) {
3520         return FALSE;
3521     }
3522     FX_DWORD objnum = FXSYS_atoi(wordObjNum);
3523     if (m_pLinearized) {
3524         m_pLinearized->Release();
3525         m_pLinearized = NULL;
3526     }
3527     m_pLinearized = ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum);
3528     if (!m_pLinearized) {
3529         return FALSE;
3530     }
3531     if (m_pLinearized->GetDict() && m_pLinearized->GetDict()->GetElement(FX_BSTRC("Linearized"))) {
3532         CPDF_Object *pLen = m_pLinearized->GetDict()->GetElement(FX_BSTRC("L"));
3533         if (!pLen) {
3534             return FALSE;
3535         }
3536         if ((FX_FILESIZE)pLen->GetInteger() != m_pFileRead->GetSize()) {
3537             return FALSE;
3538         }
3539         m_bLinearized = TRUE;
3540         CPDF_Object *pNo = m_pLinearized->GetDict()->GetElement(FX_BSTRC("P"));
3541         if (pNo && pNo->GetType() == PDFOBJ_NUMBER) {
3542             m_dwFirstPageNo = pNo->GetInteger();
3543         }
3544         return TRUE;
3545     }
3546     return FALSE;
3547 }
3548 FX_BOOL CPDF_DataAvail::CheckEnd(IFX_DownloadHints* pHints)
3549 {
3550     FX_DWORD req_pos = (FX_DWORD)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0);
3551     FX_DWORD dwSize = (FX_DWORD)(m_dwFileLen - req_pos);
3552     if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) {
3553         FX_BYTE buffer[1024];
3554         m_pFileRead->ReadBlock(buffer, req_pos, dwSize);
3555         CFX_SmartPointer<IFX_FileStream> file(FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE));
3556         m_syntaxParser.InitParser((IFX_FileStream*)file, 0);
3557         m_syntaxParser.RestorePos(dwSize - 1);
3558         if (m_syntaxParser.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, dwSize)) {
3559             FX_BOOL bNumber;
3560             m_syntaxParser.GetNextWord(bNumber);
3561             CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(bNumber);
3562             if (!bNumber) {
3563                 m_docStatus = PDF_DATAAVAIL_ERROR;
3564                 return FALSE;
3565             }
3566             m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
3567             if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) {
3568                 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
3569                 return TRUE;
3570             }
3571             m_dwLastXRefOffset = m_dwXRefOffset;
3572             SetStartOffset(m_dwXRefOffset);
3573  &nb