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