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