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