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