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