OLD | NEW |
| (Empty) |
1 // Copyright 2016 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "core/include/fpdfapi/cpdf_array.h" | |
8 #include "core/include/fpdfapi/cpdf_dictionary.h" | |
9 #include "core/include/fpdfapi/cpdf_document.h" | |
10 #include "core/include/fpdfapi/cpdf_name.h" | |
11 #include "core/include/fpdfapi/cpdf_number.h" | |
12 #include "core/include/fpdfapi/cpdf_reference.h" | |
13 #include "core/include/fpdfapi/cpdf_stream.h" | |
14 #include "core/include/fxcrt/fx_ext.h" | |
15 #include "core/include/fxcrt/fx_safe_types.h" | |
16 #include "core/src/fpdfapi/fpdf_parser/cpdf_data_avail.h" | |
17 #include "core/src/fpdfapi/fpdf_parser/fpdf_parser_utility.h" | |
18 #include "third_party/base/stl_util.h" | |
19 | |
20 IPDF_DataAvail::IPDF_DataAvail(IPDF_DataAvail::FileAvail* pFileAvail, | |
21 IFX_FileRead* pFileRead) | |
22 : m_pFileAvail(pFileAvail), m_pFileRead(pFileRead) {} | |
23 | |
24 IPDF_DataAvail::~IPDF_DataAvail() {} | |
25 | |
26 IPDF_DataAvail::FileAvail::~FileAvail() {} | |
27 | |
28 IPDF_DataAvail::DownloadHints::~DownloadHints() {} | |
29 | |
30 // static | |
31 IPDF_DataAvail* IPDF_DataAvail::Create(IPDF_DataAvail::FileAvail* pFileAvail, | |
32 IFX_FileRead* pFileRead) { | |
33 return new CPDF_DataAvail(pFileAvail, pFileRead, TRUE); | |
34 } | |
35 | |
36 // static | |
37 int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0; | |
38 | |
39 CPDF_DataAvail::CPDF_DataAvail(IPDF_DataAvail::FileAvail* pFileAvail, | |
40 IFX_FileRead* pFileRead, | |
41 FX_BOOL bSupportHintTable) | |
42 : IPDF_DataAvail(pFileAvail, pFileRead) { | |
43 m_Pos = 0; | |
44 m_dwFileLen = 0; | |
45 if (m_pFileRead) { | |
46 m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize(); | |
47 } | |
48 m_dwCurrentOffset = 0; | |
49 m_dwXRefOffset = 0; | |
50 m_bufferOffset = 0; | |
51 m_dwFirstPageNo = 0; | |
52 m_bufferSize = 0; | |
53 m_PagesObjNum = 0; | |
54 m_dwCurrentXRefSteam = 0; | |
55 m_dwAcroFormObjNum = 0; | |
56 m_dwInfoObjNum = 0; | |
57 m_pDocument = 0; | |
58 m_dwEncryptObjNum = 0; | |
59 m_dwPrevXRefOffset = 0; | |
60 m_dwLastXRefOffset = 0; | |
61 m_bDocAvail = FALSE; | |
62 m_bMainXRefLoadTried = FALSE; | |
63 m_bDocAvail = FALSE; | |
64 m_bLinearized = FALSE; | |
65 m_bPagesLoad = FALSE; | |
66 m_bPagesTreeLoad = FALSE; | |
67 m_bMainXRefLoadedOK = FALSE; | |
68 m_bAnnotsLoad = FALSE; | |
69 m_bHaveAcroForm = FALSE; | |
70 m_bAcroFormLoad = FALSE; | |
71 m_bPageLoadedOK = FALSE; | |
72 m_bNeedDownLoadResource = FALSE; | |
73 m_bLinearizedFormParamLoad = FALSE; | |
74 m_pLinearized = NULL; | |
75 m_pRoot = NULL; | |
76 m_pTrailer = NULL; | |
77 m_pCurrentParser = NULL; | |
78 m_pAcroForm = NULL; | |
79 m_pPageDict = NULL; | |
80 m_pPageResource = NULL; | |
81 m_docStatus = PDF_DATAAVAIL_HEADER; | |
82 m_parser.m_bOwnFileRead = false; | |
83 m_bTotalLoadPageTree = FALSE; | |
84 m_bCurPageDictLoadOK = FALSE; | |
85 m_bLinearedDataOK = FALSE; | |
86 m_bSupportHintTable = bSupportHintTable; | |
87 } | |
88 CPDF_DataAvail::~CPDF_DataAvail() { | |
89 if (m_pLinearized) | |
90 m_pLinearized->Release(); | |
91 | |
92 if (m_pRoot) | |
93 m_pRoot->Release(); | |
94 | |
95 if (m_pTrailer) | |
96 m_pTrailer->Release(); | |
97 | |
98 int iSize = m_arrayAcroforms.GetSize(); | |
99 for (int i = 0; i < iSize; ++i) | |
100 m_arrayAcroforms.GetAt(i)->Release(); | |
101 } | |
102 | |
103 void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc) { | |
104 m_pDocument = pDoc; | |
105 } | |
106 | |
107 FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset) { | |
108 CPDF_Parser* pParser = m_pDocument->GetParser(); | |
109 if (!pParser || !pParser->IsValidObjectNumber(objnum)) | |
110 return 0; | |
111 | |
112 if (pParser->GetObjectType(objnum) == 2) | |
113 objnum = pParser->GetObjectPositionOrZero(objnum); | |
114 | |
115 if (pParser->GetObjectType(objnum) != 1 && | |
116 pParser->GetObjectType(objnum) != 255) { | |
117 return 0; | |
118 } | |
119 | |
120 offset = pParser->GetObjectPositionOrZero(objnum); | |
121 if (offset == 0) | |
122 return 0; | |
123 | |
124 auto it = pParser->m_SortedOffset.find(offset); | |
125 if (it == pParser->m_SortedOffset.end() || | |
126 ++it == pParser->m_SortedOffset.end()) { | |
127 return 0; | |
128 } | |
129 return *it - offset; | |
130 } | |
131 | |
132 FX_BOOL CPDF_DataAvail::IsObjectsAvail( | |
133 CFX_ArrayTemplate<CPDF_Object*>& obj_array, | |
134 FX_BOOL bParsePage, | |
135 IPDF_DataAvail::DownloadHints* pHints, | |
136 CFX_ArrayTemplate<CPDF_Object*>& ret_array) { | |
137 if (!obj_array.GetSize()) | |
138 return TRUE; | |
139 | |
140 FX_DWORD count = 0; | |
141 CFX_ArrayTemplate<CPDF_Object*> new_obj_array; | |
142 int32_t i = 0; | |
143 for (i = 0; i < obj_array.GetSize(); i++) { | |
144 CPDF_Object* pObj = obj_array[i]; | |
145 if (!pObj) | |
146 continue; | |
147 | |
148 int32_t type = pObj->GetType(); | |
149 switch (type) { | |
150 case CPDF_Object::ARRAY: { | |
151 CPDF_Array* pArray = pObj->GetArray(); | |
152 for (FX_DWORD k = 0; k < pArray->GetCount(); ++k) | |
153 new_obj_array.Add(pArray->GetElement(k)); | |
154 } break; | |
155 case CPDF_Object::STREAM: | |
156 pObj = pObj->GetDict(); | |
157 case CPDF_Object::DICTIONARY: { | |
158 CPDF_Dictionary* pDict = pObj->GetDict(); | |
159 if (pDict && pDict->GetStringBy("Type") == "Page" && !bParsePage) | |
160 continue; | |
161 | |
162 for (const auto& it : *pDict) { | |
163 const CFX_ByteString& key = it.first; | |
164 CPDF_Object* value = it.second; | |
165 if (key != "Parent") | |
166 new_obj_array.Add(value); | |
167 } | |
168 } break; | |
169 case CPDF_Object::REFERENCE: { | |
170 CPDF_Reference* pRef = pObj->AsReference(); | |
171 FX_DWORD dwNum = pRef->GetRefObjNum(); | |
172 | |
173 FX_FILESIZE offset; | |
174 FX_DWORD size = GetObjectSize(dwNum, offset); | |
175 if (size == 0 || offset < 0 || offset >= m_dwFileLen) | |
176 break; | |
177 | |
178 if (!IsDataAvail(offset, size, pHints)) { | |
179 ret_array.Add(pObj); | |
180 count++; | |
181 } else if (!pdfium::ContainsKey(m_ObjectSet, dwNum)) { | |
182 m_ObjectSet.insert(dwNum); | |
183 CPDF_Object* pReferred = | |
184 m_pDocument->GetIndirectObject(pRef->GetRefObjNum()); | |
185 if (pReferred) | |
186 new_obj_array.Add(pReferred); | |
187 } | |
188 } break; | |
189 } | |
190 } | |
191 | |
192 if (count > 0) { | |
193 int32_t iSize = new_obj_array.GetSize(); | |
194 for (i = 0; i < iSize; ++i) { | |
195 CPDF_Object* pObj = new_obj_array[i]; | |
196 if (CPDF_Reference* pRef = pObj->AsReference()) { | |
197 FX_DWORD dwNum = pRef->GetRefObjNum(); | |
198 if (!pdfium::ContainsKey(m_ObjectSet, dwNum)) | |
199 ret_array.Add(pObj); | |
200 } else { | |
201 ret_array.Add(pObj); | |
202 } | |
203 } | |
204 return FALSE; | |
205 } | |
206 | |
207 obj_array.RemoveAll(); | |
208 obj_array.Append(new_obj_array); | |
209 return IsObjectsAvail(obj_array, FALSE, pHints, ret_array); | |
210 } | |
211 | |
212 IPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsDocAvail( | |
213 IPDF_DataAvail::DownloadHints* pHints) { | |
214 if (!m_dwFileLen && m_pFileRead) { | |
215 m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize(); | |
216 if (!m_dwFileLen) | |
217 return DataError; | |
218 } | |
219 | |
220 while (!m_bDocAvail) { | |
221 if (!CheckDocStatus(pHints)) | |
222 return DataNotAvailable; | |
223 } | |
224 | |
225 return DataAvailable; | |
226 } | |
227 | |
228 FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject( | |
229 IPDF_DataAvail::DownloadHints* pHints) { | |
230 if (!m_objs_array.GetSize()) { | |
231 m_objs_array.RemoveAll(); | |
232 m_ObjectSet.clear(); | |
233 CFX_ArrayTemplate<CPDF_Object*> obj_array; | |
234 obj_array.Append(m_arrayAcroforms); | |
235 FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array); | |
236 if (bRet) | |
237 m_objs_array.RemoveAll(); | |
238 return bRet; | |
239 } | |
240 | |
241 CFX_ArrayTemplate<CPDF_Object*> new_objs_array; | |
242 FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); | |
243 if (bRet) { | |
244 int32_t iSize = m_arrayAcroforms.GetSize(); | |
245 for (int32_t i = 0; i < iSize; ++i) { | |
246 m_arrayAcroforms.GetAt(i)->Release(); | |
247 } | |
248 m_arrayAcroforms.RemoveAll(); | |
249 } else { | |
250 m_objs_array.RemoveAll(); | |
251 m_objs_array.Append(new_objs_array); | |
252 } | |
253 return bRet; | |
254 } | |
255 | |
256 FX_BOOL CPDF_DataAvail::CheckAcroForm(IPDF_DataAvail::DownloadHints* pHints) { | |
257 FX_BOOL bExist = FALSE; | |
258 m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist); | |
259 if (!bExist) { | |
260 m_docStatus = PDF_DATAAVAIL_PAGETREE; | |
261 return TRUE; | |
262 } | |
263 | |
264 if (!m_pAcroForm) { | |
265 if (m_docStatus == PDF_DATAAVAIL_ERROR) { | |
266 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
267 return TRUE; | |
268 } | |
269 return FALSE; | |
270 } | |
271 | |
272 m_arrayAcroforms.Add(m_pAcroForm); | |
273 m_docStatus = PDF_DATAAVAIL_PAGETREE; | |
274 return TRUE; | |
275 } | |
276 | |
277 FX_BOOL CPDF_DataAvail::CheckDocStatus(IPDF_DataAvail::DownloadHints* pHints) { | |
278 switch (m_docStatus) { | |
279 case PDF_DATAAVAIL_HEADER: | |
280 return CheckHeader(pHints); | |
281 case PDF_DATAAVAIL_FIRSTPAGE: | |
282 case PDF_DATAAVAIL_FIRSTPAGE_PREPARE: | |
283 return CheckFirstPage(pHints); | |
284 case PDF_DATAAVAIL_HINTTABLE: | |
285 return CheckHintTables(pHints); | |
286 case PDF_DATAAVAIL_END: | |
287 return CheckEnd(pHints); | |
288 case PDF_DATAAVAIL_CROSSREF: | |
289 return CheckCrossRef(pHints); | |
290 case PDF_DATAAVAIL_CROSSREF_ITEM: | |
291 return CheckCrossRefItem(pHints); | |
292 case PDF_DATAAVAIL_CROSSREF_STREAM: | |
293 return CheckAllCrossRefStream(pHints); | |
294 case PDF_DATAAVAIL_TRAILER: | |
295 return CheckTrailer(pHints); | |
296 case PDF_DATAAVAIL_TRAILER_APPEND: | |
297 return CheckTrailerAppend(pHints); | |
298 case PDF_DATAAVAIL_LOADALLCROSSREF: | |
299 return LoadAllXref(pHints); | |
300 case PDF_DATAAVAIL_LOADALLFILE: | |
301 return LoadAllFile(pHints); | |
302 case PDF_DATAAVAIL_ROOT: | |
303 return CheckRoot(pHints); | |
304 case PDF_DATAAVAIL_INFO: | |
305 return CheckInfo(pHints); | |
306 case PDF_DATAAVAIL_ACROFORM: | |
307 return CheckAcroForm(pHints); | |
308 case PDF_DATAAVAIL_PAGETREE: | |
309 if (m_bTotalLoadPageTree) | |
310 return CheckPages(pHints); | |
311 return LoadDocPages(pHints); | |
312 case PDF_DATAAVAIL_PAGE: | |
313 if (m_bTotalLoadPageTree) | |
314 return CheckPage(pHints); | |
315 m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD; | |
316 return TRUE; | |
317 case PDF_DATAAVAIL_ERROR: | |
318 return LoadAllFile(pHints); | |
319 case PDF_DATAAVAIL_PAGE_LATERLOAD: | |
320 m_docStatus = PDF_DATAAVAIL_PAGE; | |
321 default: | |
322 m_bDocAvail = TRUE; | |
323 return TRUE; | |
324 } | |
325 } | |
326 | |
327 FX_BOOL CPDF_DataAvail::CheckPageStatus(IPDF_DataAvail::DownloadHints* pHints) { | |
328 switch (m_docStatus) { | |
329 case PDF_DATAAVAIL_PAGETREE: | |
330 return CheckPages(pHints); | |
331 case PDF_DATAAVAIL_PAGE: | |
332 return CheckPage(pHints); | |
333 case PDF_DATAAVAIL_ERROR: | |
334 return LoadAllFile(pHints); | |
335 default: | |
336 m_bPagesTreeLoad = TRUE; | |
337 m_bPagesLoad = TRUE; | |
338 return TRUE; | |
339 } | |
340 } | |
341 | |
342 FX_BOOL CPDF_DataAvail::LoadAllFile(IPDF_DataAvail::DownloadHints* pHints) { | |
343 if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) { | |
344 m_docStatus = PDF_DATAAVAIL_DONE; | |
345 return TRUE; | |
346 } | |
347 | |
348 pHints->AddSegment(0, (FX_DWORD)m_dwFileLen); | |
349 return FALSE; | |
350 } | |
351 | |
352 FX_BOOL CPDF_DataAvail::LoadAllXref(IPDF_DataAvail::DownloadHints* pHints) { | |
353 m_parser.m_pSyntax->InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset); | |
354 m_parser.m_bOwnFileRead = false; | |
355 if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && | |
356 !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) { | |
357 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
358 return FALSE; | |
359 } | |
360 | |
361 m_dwRootObjNum = m_parser.GetRootObjNum(); | |
362 m_dwInfoObjNum = m_parser.GetInfoObjNum(); | |
363 m_pCurrentParser = &m_parser; | |
364 m_docStatus = PDF_DATAAVAIL_ROOT; | |
365 return TRUE; | |
366 } | |
367 | |
368 CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum, | |
369 IPDF_DataAvail::DownloadHints* pHints, | |
370 FX_BOOL* pExistInFile) { | |
371 CPDF_Object* pRet = nullptr; | |
372 FX_DWORD size = 0; | |
373 FX_FILESIZE offset = 0; | |
374 CPDF_Parser* pParser = nullptr; | |
375 | |
376 if (pExistInFile) | |
377 *pExistInFile = TRUE; | |
378 | |
379 if (m_pDocument) { | |
380 size = GetObjectSize(objnum, offset); | |
381 pParser = m_pDocument->GetParser(); | |
382 } else { | |
383 size = (FX_DWORD)m_parser.GetObjectSize(objnum); | |
384 offset = m_parser.GetObjectOffset(objnum); | |
385 pParser = &m_parser; | |
386 } | |
387 | |
388 if (!IsDataAvail(offset, size, pHints)) | |
389 return nullptr; | |
390 | |
391 if (pParser) | |
392 pRet = pParser->ParseIndirectObject(nullptr, objnum); | |
393 | |
394 if (!pRet && pExistInFile) | |
395 *pExistInFile = FALSE; | |
396 | |
397 return pRet; | |
398 } | |
399 | |
400 FX_BOOL CPDF_DataAvail::CheckInfo(IPDF_DataAvail::DownloadHints* pHints) { | |
401 FX_BOOL bExist = FALSE; | |
402 CPDF_Object* pInfo = GetObject(m_dwInfoObjNum, pHints, &bExist); | |
403 if (!bExist) { | |
404 m_docStatus = | |
405 (m_bHaveAcroForm ? PDF_DATAAVAIL_ACROFORM : PDF_DATAAVAIL_PAGETREE); | |
406 return TRUE; | |
407 } | |
408 | |
409 if (!pInfo) { | |
410 if (m_docStatus == PDF_DATAAVAIL_ERROR) { | |
411 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
412 return TRUE; | |
413 } | |
414 | |
415 if (m_Pos == m_dwFileLen) | |
416 m_docStatus = PDF_DATAAVAIL_ERROR; | |
417 return FALSE; | |
418 } | |
419 | |
420 if (pInfo) | |
421 pInfo->Release(); | |
422 | |
423 m_docStatus = | |
424 (m_bHaveAcroForm ? PDF_DATAAVAIL_ACROFORM : PDF_DATAAVAIL_PAGETREE); | |
425 | |
426 return TRUE; | |
427 } | |
428 | |
429 FX_BOOL CPDF_DataAvail::CheckRoot(IPDF_DataAvail::DownloadHints* pHints) { | |
430 FX_BOOL bExist = FALSE; | |
431 m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist); | |
432 if (!bExist) { | |
433 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
434 return TRUE; | |
435 } | |
436 | |
437 if (!m_pRoot) { | |
438 if (m_docStatus == PDF_DATAAVAIL_ERROR) { | |
439 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
440 return TRUE; | |
441 } | |
442 return FALSE; | |
443 } | |
444 | |
445 CPDF_Dictionary* pDict = m_pRoot->GetDict(); | |
446 if (!pDict) { | |
447 m_docStatus = PDF_DATAAVAIL_ERROR; | |
448 return FALSE; | |
449 } | |
450 | |
451 CPDF_Reference* pRef = ToReference(pDict->GetElement("Pages")); | |
452 if (!pRef) { | |
453 m_docStatus = PDF_DATAAVAIL_ERROR; | |
454 return FALSE; | |
455 } | |
456 | |
457 m_PagesObjNum = pRef->GetRefObjNum(); | |
458 CPDF_Reference* pAcroFormRef = | |
459 ToReference(m_pRoot->GetDict()->GetElement("AcroForm")); | |
460 if (pAcroFormRef) { | |
461 m_bHaveAcroForm = TRUE; | |
462 m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum(); | |
463 } | |
464 | |
465 if (m_dwInfoObjNum) { | |
466 m_docStatus = PDF_DATAAVAIL_INFO; | |
467 } else { | |
468 m_docStatus = | |
469 m_bHaveAcroForm ? PDF_DATAAVAIL_ACROFORM : PDF_DATAAVAIL_PAGETREE; | |
470 } | |
471 return TRUE; | |
472 } | |
473 | |
474 FX_BOOL CPDF_DataAvail::PreparePageItem() { | |
475 CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); | |
476 CPDF_Reference* pRef = | |
477 ToReference(pRoot ? pRoot->GetElement("Pages") : nullptr); | |
478 if (!pRef) { | |
479 m_docStatus = PDF_DATAAVAIL_ERROR; | |
480 return FALSE; | |
481 } | |
482 | |
483 m_PagesObjNum = pRef->GetRefObjNum(); | |
484 m_pCurrentParser = m_pDocument->GetParser(); | |
485 m_docStatus = PDF_DATAAVAIL_PAGETREE; | |
486 return TRUE; | |
487 } | |
488 | |
489 bool CPDF_DataAvail::IsFirstCheck(int iPage) { | |
490 return m_pageMapCheckState.insert(iPage).second; | |
491 } | |
492 | |
493 void CPDF_DataAvail::ResetFirstCheck(int iPage) { | |
494 m_pageMapCheckState.erase(iPage); | |
495 } | |
496 | |
497 FX_BOOL CPDF_DataAvail::CheckPage(IPDF_DataAvail::DownloadHints* pHints) { | |
498 FX_DWORD iPageObjs = m_PageObjList.GetSize(); | |
499 CFX_DWordArray UnavailObjList; | |
500 for (FX_DWORD i = 0; i < iPageObjs; ++i) { | |
501 FX_DWORD dwPageObjNum = m_PageObjList.GetAt(i); | |
502 FX_BOOL bExist = FALSE; | |
503 CPDF_Object* pObj = GetObject(dwPageObjNum, pHints, &bExist); | |
504 if (!pObj) { | |
505 if (bExist) | |
506 UnavailObjList.Add(dwPageObjNum); | |
507 continue; | |
508 } | |
509 | |
510 if (pObj->IsArray()) { | |
511 CPDF_Array* pArray = pObj->GetArray(); | |
512 if (pArray) { | |
513 int32_t iSize = pArray->GetCount(); | |
514 for (int32_t j = 0; j < iSize; ++j) { | |
515 if (CPDF_Reference* pRef = ToReference(pArray->GetElement(j))) | |
516 UnavailObjList.Add(pRef->GetRefObjNum()); | |
517 } | |
518 } | |
519 } | |
520 | |
521 if (!pObj->IsDictionary()) { | |
522 pObj->Release(); | |
523 continue; | |
524 } | |
525 | |
526 CFX_ByteString type = pObj->GetDict()->GetStringBy("Type"); | |
527 if (type == "Pages") { | |
528 m_PagesArray.Add(pObj); | |
529 continue; | |
530 } | |
531 pObj->Release(); | |
532 } | |
533 | |
534 m_PageObjList.RemoveAll(); | |
535 if (UnavailObjList.GetSize()) { | |
536 m_PageObjList.Append(UnavailObjList); | |
537 return FALSE; | |
538 } | |
539 | |
540 FX_DWORD iPages = m_PagesArray.GetSize(); | |
541 for (FX_DWORD i = 0; i < iPages; i++) { | |
542 CPDF_Object* pPages = m_PagesArray.GetAt(i); | |
543 if (!pPages) | |
544 continue; | |
545 | |
546 if (!GetPageKids(m_pCurrentParser, pPages)) { | |
547 pPages->Release(); | |
548 while (++i < iPages) { | |
549 pPages = m_PagesArray.GetAt(i); | |
550 pPages->Release(); | |
551 } | |
552 m_PagesArray.RemoveAll(); | |
553 | |
554 m_docStatus = PDF_DATAAVAIL_ERROR; | |
555 return FALSE; | |
556 } | |
557 pPages->Release(); | |
558 } | |
559 | |
560 m_PagesArray.RemoveAll(); | |
561 if (!m_PageObjList.GetSize()) | |
562 m_docStatus = PDF_DATAAVAIL_DONE; | |
563 return TRUE; | |
564 } | |
565 | |
566 FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages) { | |
567 if (!pParser) { | |
568 m_docStatus = PDF_DATAAVAIL_ERROR; | |
569 return FALSE; | |
570 } | |
571 | |
572 CPDF_Dictionary* pDict = pPages->GetDict(); | |
573 CPDF_Object* pKids = pDict ? pDict->GetElement("Kids") : NULL; | |
574 if (!pKids) | |
575 return TRUE; | |
576 | |
577 switch (pKids->GetType()) { | |
578 case CPDF_Object::REFERENCE: | |
579 m_PageObjList.Add(pKids->AsReference()->GetRefObjNum()); | |
580 break; | |
581 case CPDF_Object::ARRAY: { | |
582 CPDF_Array* pKidsArray = pKids->AsArray(); | |
583 for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) { | |
584 if (CPDF_Reference* pRef = ToReference(pKidsArray->GetElement(i))) | |
585 m_PageObjList.Add(pRef->GetRefObjNum()); | |
586 } | |
587 } break; | |
588 default: | |
589 m_docStatus = PDF_DATAAVAIL_ERROR; | |
590 return FALSE; | |
591 } | |
592 return TRUE; | |
593 } | |
594 | |
595 FX_BOOL CPDF_DataAvail::CheckPages(IPDF_DataAvail::DownloadHints* pHints) { | |
596 FX_BOOL bExist = FALSE; | |
597 CPDF_Object* pPages = GetObject(m_PagesObjNum, pHints, &bExist); | |
598 if (!bExist) { | |
599 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
600 return TRUE; | |
601 } | |
602 | |
603 if (!pPages) { | |
604 if (m_docStatus == PDF_DATAAVAIL_ERROR) { | |
605 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
606 return TRUE; | |
607 } | |
608 return FALSE; | |
609 } | |
610 | |
611 if (!GetPageKids(m_pCurrentParser, pPages)) { | |
612 pPages->Release(); | |
613 m_docStatus = PDF_DATAAVAIL_ERROR; | |
614 return FALSE; | |
615 } | |
616 | |
617 pPages->Release(); | |
618 m_docStatus = PDF_DATAAVAIL_PAGE; | |
619 return TRUE; | |
620 } | |
621 | |
622 FX_BOOL CPDF_DataAvail::CheckHeader(IPDF_DataAvail::DownloadHints* pHints) { | |
623 FX_DWORD req_size = 1024; | |
624 if ((FX_FILESIZE)req_size > m_dwFileLen) | |
625 req_size = (FX_DWORD)m_dwFileLen; | |
626 | |
627 if (m_pFileAvail->IsDataAvail(0, req_size)) { | |
628 uint8_t buffer[1024]; | |
629 m_pFileRead->ReadBlock(buffer, 0, req_size); | |
630 | |
631 if (IsLinearizedFile(buffer, req_size)) { | |
632 m_docStatus = PDF_DATAAVAIL_FIRSTPAGE; | |
633 } else { | |
634 if (m_docStatus == PDF_DATAAVAIL_ERROR) | |
635 return FALSE; | |
636 m_docStatus = PDF_DATAAVAIL_END; | |
637 } | |
638 return TRUE; | |
639 } | |
640 | |
641 pHints->AddSegment(0, req_size); | |
642 return FALSE; | |
643 } | |
644 | |
645 FX_BOOL CPDF_DataAvail::CheckFirstPage(IPDF_DataAvail::DownloadHints* pHints) { | |
646 CPDF_Dictionary* pDict = m_pLinearized->GetDict(); | |
647 CPDF_Object* pEndOffSet = pDict ? pDict->GetElement("E") : NULL; | |
648 if (!pEndOffSet) { | |
649 m_docStatus = PDF_DATAAVAIL_ERROR; | |
650 return FALSE; | |
651 } | |
652 | |
653 CPDF_Object* pXRefOffset = pDict ? pDict->GetElement("T") : NULL; | |
654 if (!pXRefOffset) { | |
655 m_docStatus = PDF_DATAAVAIL_ERROR; | |
656 return FALSE; | |
657 } | |
658 | |
659 CPDF_Object* pFileLen = pDict ? pDict->GetElement("L") : NULL; | |
660 if (!pFileLen) { | |
661 m_docStatus = PDF_DATAAVAIL_ERROR; | |
662 return FALSE; | |
663 } | |
664 | |
665 FX_BOOL bNeedDownLoad = FALSE; | |
666 if (pEndOffSet->IsNumber()) { | |
667 FX_DWORD dwEnd = pEndOffSet->GetInteger(); | |
668 dwEnd += 512; | |
669 if ((FX_FILESIZE)dwEnd > m_dwFileLen) | |
670 dwEnd = (FX_DWORD)m_dwFileLen; | |
671 | |
672 int32_t iStartPos = (int32_t)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen); | |
673 int32_t iSize = dwEnd > 1024 ? dwEnd - 1024 : 0; | |
674 if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) { | |
675 pHints->AddSegment(iStartPos, iSize); | |
676 bNeedDownLoad = TRUE; | |
677 } | |
678 } | |
679 | |
680 m_dwLastXRefOffset = 0; | |
681 FX_FILESIZE dwFileLen = 0; | |
682 if (pXRefOffset->IsNumber()) | |
683 m_dwLastXRefOffset = pXRefOffset->GetInteger(); | |
684 | |
685 if (pFileLen->IsNumber()) | |
686 dwFileLen = pFileLen->GetInteger(); | |
687 | |
688 if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, | |
689 (FX_DWORD)(dwFileLen - m_dwLastXRefOffset))) { | |
690 if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE) { | |
691 FX_DWORD dwSize = (FX_DWORD)(dwFileLen - m_dwLastXRefOffset); | |
692 FX_FILESIZE offset = m_dwLastXRefOffset; | |
693 if (dwSize < 512 && dwFileLen > 512) { | |
694 dwSize = 512; | |
695 offset = dwFileLen - 512; | |
696 } | |
697 pHints->AddSegment(offset, dwSize); | |
698 } | |
699 } else { | |
700 m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE; | |
701 } | |
702 | |
703 if (bNeedDownLoad || m_docStatus != PDF_DATAAVAIL_FIRSTPAGE_PREPARE) { | |
704 m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE; | |
705 return FALSE; | |
706 } | |
707 | |
708 m_docStatus = | |
709 m_bSupportHintTable ? PDF_DATAAVAIL_HINTTABLE : PDF_DATAAVAIL_DONE; | |
710 return TRUE; | |
711 } | |
712 | |
713 FX_BOOL CPDF_DataAvail::IsDataAvail(FX_FILESIZE offset, | |
714 FX_DWORD size, | |
715 IPDF_DataAvail::DownloadHints* pHints) { | |
716 if (offset > m_dwFileLen) | |
717 return TRUE; | |
718 | |
719 FX_SAFE_DWORD safeSize = pdfium::base::checked_cast<FX_DWORD>(offset); | |
720 safeSize += size; | |
721 safeSize += 512; | |
722 if (!safeSize.IsValid() || safeSize.ValueOrDie() > m_dwFileLen) | |
723 size = m_dwFileLen - offset; | |
724 else | |
725 size += 512; | |
726 | |
727 if (!m_pFileAvail->IsDataAvail(offset, size)) { | |
728 pHints->AddSegment(offset, size); | |
729 return FALSE; | |
730 } | |
731 return TRUE; | |
732 } | |
733 | |
734 FX_BOOL CPDF_DataAvail::CheckHintTables(IPDF_DataAvail::DownloadHints* pHints) { | |
735 CPDF_Dictionary* pDict = m_pLinearized->GetDict(); | |
736 if (!pDict) { | |
737 m_docStatus = PDF_DATAAVAIL_ERROR; | |
738 return FALSE; | |
739 } | |
740 | |
741 if (!pDict->KeyExist("H") || !pDict->KeyExist("O") || !pDict->KeyExist("N")) { | |
742 m_docStatus = PDF_DATAAVAIL_ERROR; | |
743 return FALSE; | |
744 } | |
745 | |
746 int nPageCount = pDict->GetElementValue("N")->GetInteger(); | |
747 if (nPageCount <= 1) { | |
748 m_docStatus = PDF_DATAAVAIL_DONE; | |
749 return TRUE; | |
750 } | |
751 | |
752 CPDF_Array* pHintStreamRange = pDict->GetArrayBy("H"); | |
753 FX_FILESIZE szHSStart = | |
754 pHintStreamRange->GetElementValue(0) | |
755 ? pHintStreamRange->GetElementValue(0)->GetInteger() | |
756 : 0; | |
757 FX_FILESIZE szHSLength = | |
758 pHintStreamRange->GetElementValue(1) | |
759 ? pHintStreamRange->GetElementValue(1)->GetInteger() | |
760 : 0; | |
761 if (szHSStart < 0 || szHSLength <= 0) { | |
762 m_docStatus = PDF_DATAAVAIL_ERROR; | |
763 return FALSE; | |
764 } | |
765 | |
766 if (!IsDataAvail(szHSStart, szHSLength, pHints)) | |
767 return FALSE; | |
768 | |
769 m_syntaxParser.InitParser(m_pFileRead, m_dwHeaderOffset); | |
770 | |
771 std::unique_ptr<CPDF_HintTables> pHintTables( | |
772 new CPDF_HintTables(this, pDict)); | |
773 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pHintStream( | |
774 ParseIndirectObjectAt(szHSStart, 0)); | |
775 CPDF_Stream* pStream = ToStream(pHintStream.get()); | |
776 if (pStream && pHintTables->LoadHintStream(pStream)) | |
777 m_pHintTables = std::move(pHintTables); | |
778 | |
779 m_docStatus = PDF_DATAAVAIL_DONE; | |
780 return TRUE; | |
781 } | |
782 | |
783 CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt( | |
784 FX_FILESIZE pos, | |
785 FX_DWORD objnum, | |
786 CPDF_IndirectObjectHolder* pObjList) { | |
787 FX_FILESIZE SavedPos = m_syntaxParser.SavePos(); | |
788 m_syntaxParser.RestorePos(pos); | |
789 | |
790 bool bIsNumber; | |
791 CFX_ByteString word = m_syntaxParser.GetNextWord(&bIsNumber); | |
792 if (!bIsNumber) | |
793 return nullptr; | |
794 | |
795 FX_DWORD parser_objnum = FXSYS_atoui(word); | |
796 if (objnum && parser_objnum != objnum) | |
797 return nullptr; | |
798 | |
799 word = m_syntaxParser.GetNextWord(&bIsNumber); | |
800 if (!bIsNumber) | |
801 return nullptr; | |
802 | |
803 FX_DWORD gennum = FXSYS_atoui(word); | |
804 if (m_syntaxParser.GetKeyword() != "obj") { | |
805 m_syntaxParser.RestorePos(SavedPos); | |
806 return nullptr; | |
807 } | |
808 | |
809 CPDF_Object* pObj = | |
810 m_syntaxParser.GetObject(pObjList, parser_objnum, gennum, true); | |
811 m_syntaxParser.RestorePos(SavedPos); | |
812 return pObj; | |
813 } | |
814 | |
815 IPDF_DataAvail::DocLinearizationStatus CPDF_DataAvail::IsLinearizedPDF() { | |
816 FX_DWORD req_size = 1024; | |
817 if (!m_pFileAvail->IsDataAvail(0, req_size)) | |
818 return LinearizationUnknown; | |
819 | |
820 if (!m_pFileRead) | |
821 return NotLinearized; | |
822 | |
823 FX_FILESIZE dwSize = m_pFileRead->GetSize(); | |
824 if (dwSize < (FX_FILESIZE)req_size) | |
825 return LinearizationUnknown; | |
826 | |
827 uint8_t buffer[1024]; | |
828 m_pFileRead->ReadBlock(buffer, 0, req_size); | |
829 if (IsLinearizedFile(buffer, req_size)) | |
830 return Linearized; | |
831 | |
832 return NotLinearized; | |
833 } | |
834 FX_BOOL CPDF_DataAvail::IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen) { | |
835 ScopedFileStream file(FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE)); | |
836 | |
837 int32_t offset = GetHeaderOffset(file.get()); | |
838 if (offset == -1) { | |
839 m_docStatus = PDF_DATAAVAIL_ERROR; | |
840 return FALSE; | |
841 } | |
842 | |
843 m_dwHeaderOffset = offset; | |
844 m_syntaxParser.InitParser(file.get(), offset); | |
845 m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9); | |
846 | |
847 bool bNumber; | |
848 CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(&bNumber); | |
849 if (!bNumber) | |
850 return FALSE; | |
851 | |
852 FX_DWORD objnum = FXSYS_atoui(wordObjNum); | |
853 if (m_pLinearized) { | |
854 m_pLinearized->Release(); | |
855 m_pLinearized = nullptr; | |
856 } | |
857 | |
858 m_pLinearized = | |
859 ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum); | |
860 if (!m_pLinearized) | |
861 return FALSE; | |
862 | |
863 CPDF_Dictionary* pDict = m_pLinearized->GetDict(); | |
864 if (pDict && pDict->GetElement("Linearized")) { | |
865 CPDF_Object* pLen = pDict->GetElement("L"); | |
866 if (!pLen) | |
867 return FALSE; | |
868 | |
869 if ((FX_FILESIZE)pLen->GetInteger() != m_pFileRead->GetSize()) | |
870 return FALSE; | |
871 | |
872 m_bLinearized = TRUE; | |
873 | |
874 if (CPDF_Number* pNo = ToNumber(pDict->GetElement("P"))) | |
875 m_dwFirstPageNo = pNo->GetInteger(); | |
876 | |
877 return TRUE; | |
878 } | |
879 return FALSE; | |
880 } | |
881 | |
882 FX_BOOL CPDF_DataAvail::CheckEnd(IPDF_DataAvail::DownloadHints* pHints) { | |
883 FX_DWORD req_pos = (FX_DWORD)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0); | |
884 FX_DWORD dwSize = (FX_DWORD)(m_dwFileLen - req_pos); | |
885 | |
886 if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) { | |
887 uint8_t buffer[1024]; | |
888 m_pFileRead->ReadBlock(buffer, req_pos, dwSize); | |
889 | |
890 ScopedFileStream file(FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE)); | |
891 m_syntaxParser.InitParser(file.get(), 0); | |
892 m_syntaxParser.RestorePos(dwSize - 1); | |
893 | |
894 if (m_syntaxParser.SearchWord("startxref", TRUE, FALSE, dwSize)) { | |
895 m_syntaxParser.GetNextWord(nullptr); | |
896 | |
897 bool bNumber; | |
898 CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(&bNumber); | |
899 if (!bNumber) { | |
900 m_docStatus = PDF_DATAAVAIL_ERROR; | |
901 return FALSE; | |
902 } | |
903 | |
904 m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str); | |
905 if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) { | |
906 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
907 return TRUE; | |
908 } | |
909 | |
910 m_dwLastXRefOffset = m_dwXRefOffset; | |
911 SetStartOffset(m_dwXRefOffset); | |
912 m_docStatus = PDF_DATAAVAIL_CROSSREF; | |
913 return TRUE; | |
914 } | |
915 | |
916 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
917 return TRUE; | |
918 } | |
919 | |
920 pHints->AddSegment(req_pos, dwSize); | |
921 return FALSE; | |
922 } | |
923 | |
924 int32_t CPDF_DataAvail::CheckCrossRefStream( | |
925 IPDF_DataAvail::DownloadHints* pHints, | |
926 FX_FILESIZE& xref_offset) { | |
927 xref_offset = 0; | |
928 FX_DWORD req_size = | |
929 (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); | |
930 | |
931 if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) { | |
932 int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam); | |
933 CFX_BinaryBuf buf(iSize); | |
934 uint8_t* pBuf = buf.GetBuffer(); | |
935 | |
936 m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize); | |
937 | |
938 ScopedFileStream file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE)); | |
939 m_parser.m_pSyntax->InitParser(file.get(), 0); | |
940 | |
941 bool bNumber; | |
942 CFX_ByteString objnum = m_parser.m_pSyntax->GetNextWord(&bNumber); | |
943 if (!bNumber) | |
944 return -1; | |
945 | |
946 FX_DWORD objNum = FXSYS_atoui(objnum); | |
947 CPDF_Object* pObj = m_parser.ParseIndirectObjectAt(nullptr, 0, objNum); | |
948 if (!pObj) { | |
949 m_Pos += m_parser.m_pSyntax->SavePos(); | |
950 return 0; | |
951 } | |
952 | |
953 CPDF_Dictionary* pDict = pObj->GetDict(); | |
954 CPDF_Name* pName = ToName(pDict ? pDict->GetElement("Type") : nullptr); | |
955 if (pName) { | |
956 if (pName->GetString() == "XRef") { | |
957 m_Pos += m_parser.m_pSyntax->SavePos(); | |
958 xref_offset = pObj->GetDict()->GetIntegerBy("Prev"); | |
959 pObj->Release(); | |
960 return 1; | |
961 } | |
962 } | |
963 pObj->Release(); | |
964 return -1; | |
965 } | |
966 pHints->AddSegment(m_Pos, req_size); | |
967 return 0; | |
968 } | |
969 | |
970 inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset) { | |
971 m_Pos = dwOffset; | |
972 } | |
973 | |
974 FX_BOOL CPDF_DataAvail::GetNextToken(CFX_ByteString& token) { | |
975 uint8_t ch; | |
976 if (!GetNextChar(ch)) | |
977 return FALSE; | |
978 | |
979 while (1) { | |
980 while (PDFCharIsWhitespace(ch)) { | |
981 if (!GetNextChar(ch)) | |
982 return FALSE; | |
983 } | |
984 | |
985 if (ch != '%') | |
986 break; | |
987 | |
988 while (1) { | |
989 if (!GetNextChar(ch)) | |
990 return FALSE; | |
991 if (PDFCharIsLineEnding(ch)) | |
992 break; | |
993 } | |
994 } | |
995 | |
996 uint8_t buffer[256]; | |
997 FX_DWORD index = 0; | |
998 if (PDFCharIsDelimiter(ch)) { | |
999 buffer[index++] = ch; | |
1000 if (ch == '/') { | |
1001 while (1) { | |
1002 if (!GetNextChar(ch)) | |
1003 return FALSE; | |
1004 | |
1005 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) { | |
1006 m_Pos--; | |
1007 CFX_ByteString ret(buffer, index); | |
1008 token = ret; | |
1009 return TRUE; | |
1010 } | |
1011 | |
1012 if (index < sizeof(buffer)) | |
1013 buffer[index++] = ch; | |
1014 } | |
1015 } else if (ch == '<') { | |
1016 if (!GetNextChar(ch)) | |
1017 return FALSE; | |
1018 | |
1019 if (ch == '<') | |
1020 buffer[index++] = ch; | |
1021 else | |
1022 m_Pos--; | |
1023 } else if (ch == '>') { | |
1024 if (!GetNextChar(ch)) | |
1025 return FALSE; | |
1026 | |
1027 if (ch == '>') | |
1028 buffer[index++] = ch; | |
1029 else | |
1030 m_Pos--; | |
1031 } | |
1032 | |
1033 CFX_ByteString ret(buffer, index); | |
1034 token = ret; | |
1035 return TRUE; | |
1036 } | |
1037 | |
1038 while (1) { | |
1039 if (index < sizeof(buffer)) | |
1040 buffer[index++] = ch; | |
1041 | |
1042 if (!GetNextChar(ch)) | |
1043 return FALSE; | |
1044 | |
1045 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) { | |
1046 m_Pos--; | |
1047 break; | |
1048 } | |
1049 } | |
1050 | |
1051 token = CFX_ByteString(buffer, index); | |
1052 return TRUE; | |
1053 } | |
1054 | |
1055 FX_BOOL CPDF_DataAvail::GetNextChar(uint8_t& ch) { | |
1056 FX_FILESIZE pos = m_Pos; | |
1057 if (pos >= m_dwFileLen) | |
1058 return FALSE; | |
1059 | |
1060 if (m_bufferOffset >= pos || | |
1061 (FX_FILESIZE)(m_bufferOffset + m_bufferSize) <= pos) { | |
1062 FX_FILESIZE read_pos = pos; | |
1063 FX_DWORD read_size = 512; | |
1064 if ((FX_FILESIZE)read_size > m_dwFileLen) | |
1065 read_size = (FX_DWORD)m_dwFileLen; | |
1066 | |
1067 if ((FX_FILESIZE)(read_pos + read_size) > m_dwFileLen) | |
1068 read_pos = m_dwFileLen - read_size; | |
1069 | |
1070 if (!m_pFileRead->ReadBlock(m_bufferData, read_pos, read_size)) | |
1071 return FALSE; | |
1072 | |
1073 m_bufferOffset = read_pos; | |
1074 m_bufferSize = read_size; | |
1075 } | |
1076 ch = m_bufferData[pos - m_bufferOffset]; | |
1077 m_Pos++; | |
1078 return TRUE; | |
1079 } | |
1080 | |
1081 FX_BOOL CPDF_DataAvail::CheckCrossRefItem( | |
1082 IPDF_DataAvail::DownloadHints* pHints) { | |
1083 int32_t iSize = 0; | |
1084 CFX_ByteString token; | |
1085 while (1) { | |
1086 if (!GetNextToken(token)) { | |
1087 iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); | |
1088 pHints->AddSegment(m_Pos, iSize); | |
1089 return FALSE; | |
1090 } | |
1091 | |
1092 if (token == "trailer") { | |
1093 m_dwTrailerOffset = m_Pos; | |
1094 m_docStatus = PDF_DATAAVAIL_TRAILER; | |
1095 return TRUE; | |
1096 } | |
1097 } | |
1098 } | |
1099 | |
1100 FX_BOOL CPDF_DataAvail::CheckAllCrossRefStream( | |
1101 IPDF_DataAvail::DownloadHints* pHints) { | |
1102 FX_FILESIZE xref_offset = 0; | |
1103 | |
1104 int32_t nRet = CheckCrossRefStream(pHints, xref_offset); | |
1105 if (nRet == 1) { | |
1106 if (!xref_offset) { | |
1107 m_docStatus = PDF_DATAAVAIL_LOADALLCROSSREF; | |
1108 } else { | |
1109 m_dwCurrentXRefSteam = xref_offset; | |
1110 m_Pos = xref_offset; | |
1111 } | |
1112 return TRUE; | |
1113 } | |
1114 | |
1115 if (nRet == -1) | |
1116 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1117 return FALSE; | |
1118 } | |
1119 | |
1120 FX_BOOL CPDF_DataAvail::CheckCrossRef(IPDF_DataAvail::DownloadHints* pHints) { | |
1121 int32_t iSize = 0; | |
1122 CFX_ByteString token; | |
1123 if (!GetNextToken(token)) { | |
1124 iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); | |
1125 pHints->AddSegment(m_Pos, iSize); | |
1126 return FALSE; | |
1127 } | |
1128 | |
1129 if (token == "xref") { | |
1130 while (1) { | |
1131 if (!GetNextToken(token)) { | |
1132 iSize = | |
1133 (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); | |
1134 pHints->AddSegment(m_Pos, iSize); | |
1135 m_docStatus = PDF_DATAAVAIL_CROSSREF_ITEM; | |
1136 return FALSE; | |
1137 } | |
1138 | |
1139 if (token == "trailer") { | |
1140 m_dwTrailerOffset = m_Pos; | |
1141 m_docStatus = PDF_DATAAVAIL_TRAILER; | |
1142 return TRUE; | |
1143 } | |
1144 } | |
1145 } else { | |
1146 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
1147 return TRUE; | |
1148 } | |
1149 return FALSE; | |
1150 } | |
1151 | |
1152 FX_BOOL CPDF_DataAvail::CheckTrailerAppend( | |
1153 IPDF_DataAvail::DownloadHints* pHints) { | |
1154 if (m_Pos < m_dwFileLen) { | |
1155 FX_FILESIZE dwAppendPos = m_Pos + m_syntaxParser.SavePos(); | |
1156 int32_t iSize = (int32_t)( | |
1157 dwAppendPos + 512 > m_dwFileLen ? m_dwFileLen - dwAppendPos : 512); | |
1158 | |
1159 if (!m_pFileAvail->IsDataAvail(dwAppendPos, iSize)) { | |
1160 pHints->AddSegment(dwAppendPos, iSize); | |
1161 return FALSE; | |
1162 } | |
1163 } | |
1164 | |
1165 if (m_dwPrevXRefOffset) { | |
1166 SetStartOffset(m_dwPrevXRefOffset); | |
1167 m_docStatus = PDF_DATAAVAIL_CROSSREF; | |
1168 } else { | |
1169 m_docStatus = PDF_DATAAVAIL_LOADALLCROSSREF; | |
1170 } | |
1171 return TRUE; | |
1172 } | |
1173 | |
1174 FX_BOOL CPDF_DataAvail::CheckTrailer(IPDF_DataAvail::DownloadHints* pHints) { | |
1175 int32_t iTrailerSize = | |
1176 (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); | |
1177 if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) { | |
1178 int32_t iSize = (int32_t)(m_Pos + iTrailerSize - m_dwTrailerOffset); | |
1179 CFX_BinaryBuf buf(iSize); | |
1180 uint8_t* pBuf = buf.GetBuffer(); | |
1181 if (!pBuf) { | |
1182 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1183 return FALSE; | |
1184 } | |
1185 | |
1186 if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) | |
1187 return FALSE; | |
1188 | |
1189 ScopedFileStream file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE)); | |
1190 m_syntaxParser.InitParser(file.get(), 0); | |
1191 | |
1192 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pTrailer( | |
1193 m_syntaxParser.GetObject(nullptr, 0, 0, true)); | |
1194 if (!pTrailer) { | |
1195 m_Pos += m_syntaxParser.SavePos(); | |
1196 pHints->AddSegment(m_Pos, iTrailerSize); | |
1197 return FALSE; | |
1198 } | |
1199 | |
1200 if (!pTrailer->IsDictionary()) | |
1201 return FALSE; | |
1202 | |
1203 CPDF_Dictionary* pTrailerDict = pTrailer->GetDict(); | |
1204 CPDF_Object* pEncrypt = pTrailerDict->GetElement("Encrypt"); | |
1205 if (ToReference(pEncrypt)) { | |
1206 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
1207 return TRUE; | |
1208 } | |
1209 | |
1210 FX_DWORD xrefpos = GetDirectInteger(pTrailerDict, "Prev"); | |
1211 if (xrefpos) { | |
1212 m_dwPrevXRefOffset = GetDirectInteger(pTrailerDict, "XRefStm"); | |
1213 if (m_dwPrevXRefOffset) { | |
1214 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
1215 } else { | |
1216 m_dwPrevXRefOffset = xrefpos; | |
1217 if (m_dwPrevXRefOffset >= m_dwFileLen) { | |
1218 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | |
1219 } else { | |
1220 SetStartOffset(m_dwPrevXRefOffset); | |
1221 m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; | |
1222 } | |
1223 } | |
1224 return TRUE; | |
1225 } | |
1226 m_dwPrevXRefOffset = 0; | |
1227 m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; | |
1228 return TRUE; | |
1229 } | |
1230 pHints->AddSegment(m_Pos, iTrailerSize); | |
1231 return FALSE; | |
1232 } | |
1233 | |
1234 FX_BOOL CPDF_DataAvail::CheckPage(int32_t iPage, | |
1235 IPDF_DataAvail::DownloadHints* pHints) { | |
1236 while (TRUE) { | |
1237 switch (m_docStatus) { | |
1238 case PDF_DATAAVAIL_PAGETREE: | |
1239 if (!LoadDocPages(pHints)) | |
1240 return FALSE; | |
1241 break; | |
1242 case PDF_DATAAVAIL_PAGE: | |
1243 if (!LoadDocPage(iPage, pHints)) | |
1244 return FALSE; | |
1245 break; | |
1246 case PDF_DATAAVAIL_ERROR: | |
1247 return LoadAllFile(pHints); | |
1248 default: | |
1249 m_bPagesTreeLoad = TRUE; | |
1250 m_bPagesLoad = TRUE; | |
1251 m_bCurPageDictLoadOK = TRUE; | |
1252 m_docStatus = PDF_DATAAVAIL_PAGE; | |
1253 return TRUE; | |
1254 } | |
1255 } | |
1256 } | |
1257 | |
1258 FX_BOOL CPDF_DataAvail::CheckArrayPageNode( | |
1259 FX_DWORD dwPageNo, | |
1260 CPDF_DataAvail::PageNode* pPageNode, | |
1261 IPDF_DataAvail::DownloadHints* pHints) { | |
1262 FX_BOOL bExist = FALSE; | |
1263 CPDF_Object* pPages = GetObject(dwPageNo, pHints, &bExist); | |
1264 if (!bExist) { | |
1265 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1266 return FALSE; | |
1267 } | |
1268 | |
1269 if (!pPages) { | |
1270 if (m_docStatus == PDF_DATAAVAIL_ERROR) { | |
1271 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1272 return FALSE; | |
1273 } | |
1274 return FALSE; | |
1275 } | |
1276 | |
1277 CPDF_Array* pArray = pPages->AsArray(); | |
1278 if (!pArray) { | |
1279 pPages->Release(); | |
1280 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1281 return FALSE; | |
1282 } | |
1283 | |
1284 pPageNode->m_type = PDF_PAGENODE_PAGES; | |
1285 for (FX_DWORD i = 0; i < pArray->GetCount(); ++i) { | |
1286 CPDF_Reference* pKid = ToReference(pArray->GetElement(i)); | |
1287 if (!pKid) | |
1288 continue; | |
1289 | |
1290 PageNode* pNode = new PageNode(); | |
1291 pPageNode->m_childNode.Add(pNode); | |
1292 pNode->m_dwPageNo = pKid->GetRefObjNum(); | |
1293 } | |
1294 pPages->Release(); | |
1295 return TRUE; | |
1296 } | |
1297 | |
1298 FX_BOOL CPDF_DataAvail::CheckUnkownPageNode( | |
1299 FX_DWORD dwPageNo, | |
1300 CPDF_DataAvail::PageNode* pPageNode, | |
1301 IPDF_DataAvail::DownloadHints* pHints) { | |
1302 FX_BOOL bExist = FALSE; | |
1303 CPDF_Object* pPage = GetObject(dwPageNo, pHints, &bExist); | |
1304 if (!bExist) { | |
1305 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1306 return FALSE; | |
1307 } | |
1308 | |
1309 if (!pPage) { | |
1310 if (m_docStatus == PDF_DATAAVAIL_ERROR) | |
1311 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1312 return FALSE; | |
1313 } | |
1314 | |
1315 if (pPage->IsArray()) { | |
1316 pPageNode->m_dwPageNo = dwPageNo; | |
1317 pPageNode->m_type = PDF_PAGENODE_ARRAY; | |
1318 pPage->Release(); | |
1319 return TRUE; | |
1320 } | |
1321 | |
1322 if (!pPage->IsDictionary()) { | |
1323 pPage->Release(); | |
1324 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1325 return FALSE; | |
1326 } | |
1327 | |
1328 pPageNode->m_dwPageNo = dwPageNo; | |
1329 CPDF_Dictionary* pDict = pPage->GetDict(); | |
1330 CFX_ByteString type = pDict->GetStringBy("Type"); | |
1331 if (type == "Pages") { | |
1332 pPageNode->m_type = PDF_PAGENODE_PAGES; | |
1333 CPDF_Object* pKids = pDict->GetElement("Kids"); | |
1334 if (!pKids) { | |
1335 m_docStatus = PDF_DATAAVAIL_PAGE; | |
1336 return TRUE; | |
1337 } | |
1338 | |
1339 switch (pKids->GetType()) { | |
1340 case CPDF_Object::REFERENCE: { | |
1341 CPDF_Reference* pKid = pKids->AsReference(); | |
1342 PageNode* pNode = new PageNode(); | |
1343 pPageNode->m_childNode.Add(pNode); | |
1344 pNode->m_dwPageNo = pKid->GetRefObjNum(); | |
1345 } break; | |
1346 case CPDF_Object::ARRAY: { | |
1347 CPDF_Array* pKidsArray = pKids->AsArray(); | |
1348 for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) { | |
1349 CPDF_Reference* pKid = ToReference(pKidsArray->GetElement(i)); | |
1350 if (!pKid) | |
1351 continue; | |
1352 | |
1353 PageNode* pNode = new PageNode(); | |
1354 pPageNode->m_childNode.Add(pNode); | |
1355 pNode->m_dwPageNo = pKid->GetRefObjNum(); | |
1356 } | |
1357 } break; | |
1358 default: | |
1359 break; | |
1360 } | |
1361 } else if (type == "Page") { | |
1362 pPageNode->m_type = PDF_PAGENODE_PAGE; | |
1363 } else { | |
1364 pPage->Release(); | |
1365 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1366 return FALSE; | |
1367 } | |
1368 pPage->Release(); | |
1369 return TRUE; | |
1370 } | |
1371 | |
1372 FX_BOOL CPDF_DataAvail::CheckPageNode(CPDF_DataAvail::PageNode& pageNodes, | |
1373 int32_t iPage, | |
1374 int32_t& iCount, | |
1375 IPDF_DataAvail::DownloadHints* pHints, | |
1376 int level) { | |
1377 if (level >= kMaxPageRecursionDepth) | |
1378 return FALSE; | |
1379 | |
1380 int32_t iSize = pageNodes.m_childNode.GetSize(); | |
1381 if (iSize <= 0 || iPage >= iSize) { | |
1382 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1383 return FALSE; | |
1384 } | |
1385 | |
1386 for (int32_t i = 0; i < iSize; ++i) { | |
1387 PageNode* pNode = pageNodes.m_childNode.GetAt(i); | |
1388 if (!pNode) | |
1389 continue; | |
1390 | |
1391 switch (pNode->m_type) { | |
1392 case PDF_PAGENODE_UNKNOWN: | |
1393 if (!CheckUnkownPageNode(pNode->m_dwPageNo, pNode, pHints)) { | |
1394 return FALSE; | |
1395 } | |
1396 --i; | |
1397 break; | |
1398 case PDF_PAGENODE_PAGE: | |
1399 iCount++; | |
1400 if (iPage == iCount && m_pDocument) | |
1401 m_pDocument->m_PageList.SetAt(iPage, pNode->m_dwPageNo); | |
1402 break; | |
1403 case PDF_PAGENODE_PAGES: | |
1404 if (!CheckPageNode(*pNode, iPage, iCount, pHints, level + 1)) | |
1405 return FALSE; | |
1406 break; | |
1407 case PDF_PAGENODE_ARRAY: | |
1408 if (!CheckArrayPageNode(pNode->m_dwPageNo, pNode, pHints)) | |
1409 return FALSE; | |
1410 --i; | |
1411 break; | |
1412 } | |
1413 | |
1414 if (iPage == iCount) { | |
1415 m_docStatus = PDF_DATAAVAIL_DONE; | |
1416 return TRUE; | |
1417 } | |
1418 } | |
1419 return TRUE; | |
1420 } | |
1421 | |
1422 FX_BOOL CPDF_DataAvail::LoadDocPage(int32_t iPage, | |
1423 IPDF_DataAvail::DownloadHints* pHints) { | |
1424 if (m_pDocument->GetPageCount() <= iPage || | |
1425 m_pDocument->m_PageList.GetAt(iPage)) { | |
1426 m_docStatus = PDF_DATAAVAIL_DONE; | |
1427 return TRUE; | |
1428 } | |
1429 | |
1430 if (m_pageNodes.m_type == PDF_PAGENODE_PAGE) { | |
1431 if (iPage == 0) { | |
1432 m_docStatus = PDF_DATAAVAIL_DONE; | |
1433 return TRUE; | |
1434 } | |
1435 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1436 return TRUE; | |
1437 } | |
1438 int32_t iCount = -1; | |
1439 return CheckPageNode(m_pageNodes, iPage, iCount, pHints, 0); | |
1440 } | |
1441 | |
1442 FX_BOOL CPDF_DataAvail::CheckPageCount(IPDF_DataAvail::DownloadHints* pHints) { | |
1443 FX_BOOL bExist = FALSE; | |
1444 CPDF_Object* pPages = GetObject(m_PagesObjNum, pHints, &bExist); | |
1445 if (!bExist) { | |
1446 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1447 return FALSE; | |
1448 } | |
1449 | |
1450 if (!pPages) | |
1451 return FALSE; | |
1452 | |
1453 CPDF_Dictionary* pPagesDict = pPages->GetDict(); | |
1454 if (!pPagesDict) { | |
1455 pPages->Release(); | |
1456 m_docStatus = PDF_DATAAVAIL_ERROR; | |
1457 return FALSE; | |
1458 } | |
1459 | |
1460 if (!pPagesDict->KeyExist("Kids")) { | |
1461 pPages->Release(); | |
1462 return TRUE; | |
1463 } | |
1464 | |
1465 int count = pPagesDict->GetIntegerBy("Count"); | |
1466 if (count > 0) { | |
1467 pPages->Release(); | |
1468 return TRUE; | |
1469 } | |
1470 | |
1471 pPages->Release(); | |
1472 return FALSE; | |
1473 } | |
1474 | |
1475 FX_BOOL CPDF_DataAvail::LoadDocPages(IPDF_DataAvail::DownloadHints* pHints) { | |
1476 if (!CheckUnkownPageNode(m_PagesObjNum, &m_pageNodes, pHints)) | |
1477 return FALSE; | |
1478 | |
1479 if (CheckPageCount(pHints)) { | |
1480 m_docStatus = PDF_DATAAVAIL_PAGE; | |
1481 return TRUE; | |
1482 } | |
1483 | |
1484 m_bTotalLoadPageTree = TRUE; | |
1485 return FALSE; | |
1486 } | |
1487 | |
1488 FX_BOOL CPDF_DataAvail::LoadPages(IPDF_DataAvail::DownloadHints* pHints) { | |
1489 while (!m_bPagesTreeLoad) { | |
1490 if (!CheckPageStatus(pHints)) | |
1491 return FALSE; | |
1492 } | |
1493 | |
1494 if (m_bPagesLoad) | |
1495 return TRUE; | |
1496 | |
1497 m_pDocument->LoadPages(); | |
1498 return FALSE; | |
1499 } | |
1500 | |
1501 IPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedData( | |
1502 IPDF_DataAvail::DownloadHints* pHints) { | |
1503 if (m_bLinearedDataOK) | |
1504 return DataAvailable; | |
1505 | |
1506 if (!m_bMainXRefLoadTried) { | |
1507 FX_SAFE_DWORD data_size = m_dwFileLen; | |
1508 data_size -= m_dwLastXRefOffset; | |
1509 if (!data_size.IsValid()) | |
1510 return DataError; | |
1511 | |
1512 if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, | |
1513 data_size.ValueOrDie())) { | |
1514 pHints->AddSegment(m_dwLastXRefOffset, data_size.ValueOrDie()); | |
1515 return DataNotAvailable; | |
1516 } | |
1517 | |
1518 CPDF_Parser::Error eRet = | |
1519 m_pDocument->GetParser()->LoadLinearizedMainXRefTable(); | |
1520 m_bMainXRefLoadTried = TRUE; | |
1521 if (eRet != CPDF_Parser::SUCCESS) | |
1522 return DataError; | |
1523 | |
1524 if (!PreparePageItem()) | |
1525 return DataNotAvailable; | |
1526 | |
1527 m_bMainXRefLoadedOK = TRUE; | |
1528 m_bLinearedDataOK = TRUE; | |
1529 } | |
1530 | |
1531 return m_bLinearedDataOK ? DataAvailable : DataNotAvailable; | |
1532 } | |
1533 | |
1534 FX_BOOL CPDF_DataAvail::CheckPageAnnots(int32_t iPage, | |
1535 IPDF_DataAvail::DownloadHints* pHints) { | |
1536 if (!m_objs_array.GetSize()) { | |
1537 m_objs_array.RemoveAll(); | |
1538 m_ObjectSet.clear(); | |
1539 | |
1540 CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iPage); | |
1541 if (!pPageDict) | |
1542 return TRUE; | |
1543 | |
1544 CPDF_Object* pAnnots = pPageDict->GetElement("Annots"); | |
1545 if (!pAnnots) | |
1546 return TRUE; | |
1547 | |
1548 CFX_ArrayTemplate<CPDF_Object*> obj_array; | |
1549 obj_array.Add(pAnnots); | |
1550 | |
1551 FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array); | |
1552 if (bRet) | |
1553 m_objs_array.RemoveAll(); | |
1554 | |
1555 return bRet; | |
1556 } | |
1557 | |
1558 CFX_ArrayTemplate<CPDF_Object*> new_objs_array; | |
1559 FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); | |
1560 m_objs_array.RemoveAll(); | |
1561 if (!bRet) | |
1562 m_objs_array.Append(new_objs_array); | |
1563 | |
1564 return bRet; | |
1565 } | |
1566 | |
1567 IPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedFirstPage( | |
1568 int32_t iPage, | |
1569 IPDF_DataAvail::DownloadHints* pHints) { | |
1570 if (!m_bAnnotsLoad) { | |
1571 if (!CheckPageAnnots(iPage, pHints)) | |
1572 return DataNotAvailable; | |
1573 m_bAnnotsLoad = TRUE; | |
1574 } | |
1575 | |
1576 DocAvailStatus nRet = CheckLinearizedData(pHints); | |
1577 if (nRet == DataAvailable) | |
1578 m_bPageLoadedOK = FALSE; | |
1579 return nRet; | |
1580 } | |
1581 | |
1582 FX_BOOL CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary* pDict) { | |
1583 CFX_AutoRestorer<int> restorer(&s_CurrentDataAvailRecursionDepth); | |
1584 if (++s_CurrentDataAvailRecursionDepth > kMaxDataAvailRecursionDepth) | |
1585 return FALSE; | |
1586 | |
1587 CPDF_Object* pParent = pDict->GetElement("Parent"); | |
1588 if (!pParent) | |
1589 return FALSE; | |
1590 | |
1591 CPDF_Dictionary* pParentDict = pParent->GetDict(); | |
1592 if (!pParentDict) | |
1593 return FALSE; | |
1594 | |
1595 CPDF_Object* pRet = pParentDict->GetElement("Resources"); | |
1596 if (pRet) { | |
1597 m_pPageResource = pRet; | |
1598 return TRUE; | |
1599 } | |
1600 | |
1601 return HaveResourceAncestor(pParentDict); | |
1602 } | |
1603 | |
1604 IPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsPageAvail( | |
1605 int32_t iPage, | |
1606 IPDF_DataAvail::DownloadHints* pHints) { | |
1607 if (!m_pDocument) | |
1608 return DataError; | |
1609 | |
1610 if (IsFirstCheck(iPage)) { | |
1611 m_bCurPageDictLoadOK = FALSE; | |
1612 m_bPageLoadedOK = FALSE; | |
1613 m_bAnnotsLoad = FALSE; | |
1614 m_bNeedDownLoadResource = FALSE; | |
1615 m_objs_array.RemoveAll(); | |
1616 m_ObjectSet.clear(); | |
1617 } | |
1618 | |
1619 if (pdfium::ContainsKey(m_pagesLoadState, iPage)) | |
1620 return DataAvailable; | |
1621 | |
1622 if (m_bLinearized) { | |
1623 if ((FX_DWORD)iPage == m_dwFirstPageNo) { | |
1624 DocAvailStatus nRet = CheckLinearizedFirstPage(iPage, pHints); | |
1625 if (nRet == DataAvailable) | |
1626 m_pagesLoadState.insert(iPage); | |
1627 return nRet; | |
1628 } | |
1629 | |
1630 DocAvailStatus nResult = CheckLinearizedData(pHints); | |
1631 if (nResult != DataAvailable) | |
1632 return nResult; | |
1633 | |
1634 if (m_pHintTables) { | |
1635 nResult = m_pHintTables->CheckPage(iPage, pHints); | |
1636 if (nResult != DataAvailable) | |
1637 return nResult; | |
1638 m_pagesLoadState.insert(iPage); | |
1639 return DataAvailable; | |
1640 } | |
1641 | |
1642 if (m_bMainXRefLoadedOK) { | |
1643 if (m_bTotalLoadPageTree) { | |
1644 if (!LoadPages(pHints)) | |
1645 return DataNotAvailable; | |
1646 } else { | |
1647 if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints)) | |
1648 return DataNotAvailable; | |
1649 } | |
1650 } else { | |
1651 if (!LoadAllFile(pHints)) | |
1652 return DataNotAvailable; | |
1653 m_pDocument->GetParser()->RebuildCrossRef(); | |
1654 ResetFirstCheck(iPage); | |
1655 return DataAvailable; | |
1656 } | |
1657 } else { | |
1658 if (!m_bTotalLoadPageTree && !m_bCurPageDictLoadOK && | |
1659 !CheckPage(iPage, pHints)) { | |
1660 return DataNotAvailable; | |
1661 } | |
1662 } | |
1663 | |
1664 if (m_bHaveAcroForm && !m_bAcroFormLoad) { | |
1665 if (!CheckAcroFormSubObject(pHints)) | |
1666 return DataNotAvailable; | |
1667 m_bAcroFormLoad = TRUE; | |
1668 } | |
1669 | |
1670 if (!m_bPageLoadedOK) { | |
1671 if (!m_objs_array.GetSize()) { | |
1672 m_objs_array.RemoveAll(); | |
1673 m_ObjectSet.clear(); | |
1674 | |
1675 m_pPageDict = m_pDocument->GetPage(iPage); | |
1676 if (!m_pPageDict) { | |
1677 ResetFirstCheck(iPage); | |
1678 return DataAvailable; | |
1679 } | |
1680 | |
1681 CFX_ArrayTemplate<CPDF_Object*> obj_array; | |
1682 obj_array.Add(m_pPageDict); | |
1683 FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array); | |
1684 if (!bRet) | |
1685 return DataNotAvailable; | |
1686 | |
1687 m_objs_array.RemoveAll(); | |
1688 } else { | |
1689 CFX_ArrayTemplate<CPDF_Object*> new_objs_array; | |
1690 FX_BOOL bRet = | |
1691 IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); | |
1692 | |
1693 m_objs_array.RemoveAll(); | |
1694 if (!bRet) { | |
1695 m_objs_array.Append(new_objs_array); | |
1696 return DataNotAvailable; | |
1697 } | |
1698 } | |
1699 m_bPageLoadedOK = TRUE; | |
1700 } | |
1701 | |
1702 if (!m_bAnnotsLoad) { | |
1703 if (!CheckPageAnnots(iPage, pHints)) | |
1704 return DataNotAvailable; | |
1705 m_bAnnotsLoad = TRUE; | |
1706 } | |
1707 | |
1708 if (m_pPageDict && !m_bNeedDownLoadResource) { | |
1709 m_pPageResource = m_pPageDict->GetElement("Resources"); | |
1710 if (!m_pPageResource) | |
1711 m_bNeedDownLoadResource = HaveResourceAncestor(m_pPageDict); | |
1712 else | |
1713 m_bNeedDownLoadResource = TRUE; | |
1714 } | |
1715 | |
1716 if (m_bNeedDownLoadResource) { | |
1717 FX_BOOL bRet = CheckResources(pHints); | |
1718 if (!bRet) | |
1719 return DataNotAvailable; | |
1720 m_bNeedDownLoadResource = FALSE; | |
1721 } | |
1722 | |
1723 m_bPageLoadedOK = FALSE; | |
1724 m_bAnnotsLoad = FALSE; | |
1725 m_bCurPageDictLoadOK = FALSE; | |
1726 | |
1727 ResetFirstCheck(iPage); | |
1728 m_pagesLoadState.insert(iPage); | |
1729 return DataAvailable; | |
1730 } | |
1731 | |
1732 FX_BOOL CPDF_DataAvail::CheckResources(IPDF_DataAvail::DownloadHints* pHints) { | |
1733 if (!m_objs_array.GetSize()) { | |
1734 m_objs_array.RemoveAll(); | |
1735 CFX_ArrayTemplate<CPDF_Object*> obj_array; | |
1736 obj_array.Add(m_pPageResource); | |
1737 | |
1738 FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array); | |
1739 if (bRet) | |
1740 m_objs_array.RemoveAll(); | |
1741 return bRet; | |
1742 } | |
1743 | |
1744 CFX_ArrayTemplate<CPDF_Object*> new_objs_array; | |
1745 FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); | |
1746 m_objs_array.RemoveAll(); | |
1747 if (!bRet) | |
1748 m_objs_array.Append(new_objs_array); | |
1749 return bRet; | |
1750 } | |
1751 | |
1752 void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE* pPos, | |
1753 FX_DWORD* pSize) { | |
1754 if (pPos) | |
1755 *pPos = m_dwLastXRefOffset; | |
1756 if (pSize) | |
1757 *pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset); | |
1758 } | |
1759 | |
1760 int CPDF_DataAvail::GetPageCount() const { | |
1761 if (m_pLinearized) { | |
1762 CPDF_Dictionary* pDict = m_pLinearized->GetDict(); | |
1763 CPDF_Object* pObj = pDict ? pDict->GetElementValue("N") : nullptr; | |
1764 return pObj ? pObj->GetInteger() : 0; | |
1765 } | |
1766 return m_pDocument ? m_pDocument->GetPageCount() : 0; | |
1767 } | |
1768 | |
1769 CPDF_Dictionary* CPDF_DataAvail::GetPage(int index) { | |
1770 if (!m_pDocument || index < 0 || index >= GetPageCount()) | |
1771 return nullptr; | |
1772 | |
1773 if (m_pLinearized) { | |
1774 CPDF_Dictionary* pDict = m_pLinearized->GetDict(); | |
1775 CPDF_Object* pObj = pDict ? pDict->GetElementValue("P") : nullptr; | |
1776 | |
1777 int pageNum = pObj ? pObj->GetInteger() : 0; | |
1778 if (m_pHintTables && index != pageNum) { | |
1779 FX_FILESIZE szPageStartPos = 0; | |
1780 FX_FILESIZE szPageLength = 0; | |
1781 FX_DWORD dwObjNum = 0; | |
1782 FX_BOOL bPagePosGot = m_pHintTables->GetPagePos(index, szPageStartPos, | |
1783 szPageLength, dwObjNum); | |
1784 if (!bPagePosGot) | |
1785 return nullptr; | |
1786 | |
1787 m_syntaxParser.InitParser(m_pFileRead, (FX_DWORD)szPageStartPos); | |
1788 CPDF_Object* pPageDict = ParseIndirectObjectAt(0, dwObjNum, m_pDocument); | |
1789 if (!pPageDict) | |
1790 return nullptr; | |
1791 | |
1792 if (!m_pDocument->InsertIndirectObject(dwObjNum, pPageDict)) | |
1793 return nullptr; | |
1794 return pPageDict->GetDict(); | |
1795 } | |
1796 } | |
1797 return m_pDocument->GetPage(index); | |
1798 } | |
1799 | |
1800 IPDF_DataAvail::DocFormStatus CPDF_DataAvail::IsFormAvail( | |
1801 IPDF_DataAvail::DownloadHints* pHints) { | |
1802 if (!m_pDocument) | |
1803 return FormAvailable; | |
1804 | |
1805 if (!m_bLinearizedFormParamLoad) { | |
1806 CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); | |
1807 if (!pRoot) | |
1808 return FormAvailable; | |
1809 | |
1810 CPDF_Object* pAcroForm = pRoot->GetElement("AcroForm"); | |
1811 if (!pAcroForm) | |
1812 return FormNotExist; | |
1813 | |
1814 DocAvailStatus nDocStatus = CheckLinearizedData(pHints); | |
1815 if (nDocStatus == DataError) | |
1816 return FormError; | |
1817 if (nDocStatus == DataNotAvailable) | |
1818 return FormNotAvailable; | |
1819 | |
1820 if (!m_objs_array.GetSize()) | |
1821 m_objs_array.Add(pAcroForm->GetDict()); | |
1822 m_bLinearizedFormParamLoad = TRUE; | |
1823 } | |
1824 | |
1825 CFX_ArrayTemplate<CPDF_Object*> new_objs_array; | |
1826 FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array); | |
1827 m_objs_array.RemoveAll(); | |
1828 if (!bRet) { | |
1829 m_objs_array.Append(new_objs_array); | |
1830 return FormNotAvailable; | |
1831 } | |
1832 return FormAvailable; | |
1833 } | |
1834 | |
1835 CPDF_DataAvail::PageNode::PageNode() : m_type(PDF_PAGENODE_UNKNOWN) {} | |
1836 | |
1837 CPDF_DataAvail::PageNode::~PageNode() { | |
1838 for (int32_t i = 0; i < m_childNode.GetSize(); ++i) | |
1839 delete m_childNode[i]; | |
1840 m_childNode.RemoveAll(); | |
1841 } | |
OLD | NEW |