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