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