Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp

Issue 1778173002: Split apart the remainder of fpdf_render_render.cpp into per-class files. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: remove more stray includes. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/include/fpdfapi/fpdf_parser.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <set>
12 #include <utility>
13 #include <vector>
14
15 #include "core/include/fpdfapi/cpdf_document.h"
16 #include "core/include/fpdfapi/cpdf_parser.h"
17 #include "core/include/fpdfapi/fpdf_module.h"
18 #include "core/include/fpdfapi/fpdf_page.h"
19 #include "core/include/fxcrt/fx_ext.h"
20 #include "core/include/fxcrt/fx_safe_types.h"
21 #include "core/src/fpdfapi/fpdf_page/pageint.h"
22 #include "core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.h"
23 #include "core/src/fpdfapi/fpdf_parser/fpdf_parser_utility.h"
24 #include "core/src/fpdfapi/fpdf_parser/parser_int.h"
25 #include "third_party/base/stl_util.h"
26
27 namespace {
28
29 bool CanReadFromBitStream(const CFX_BitStream* hStream,
30 const FX_SAFE_DWORD& num_bits) {
31 return num_bits.IsValid() &&
32 hStream->BitsRemaining() >= num_bits.ValueOrDie();
33 }
34
35 } // namespace
36
37 bool IsSignatureDict(const CPDF_Dictionary* pDict) {
38 CPDF_Object* pType = pDict->GetElementValue("Type");
39 if (!pType)
40 pType = pDict->GetElementValue("FT");
41 return pType && pType->GetString() == "Sig";
42 }
43
44
45 class CPDF_DataAvail final : public IPDF_DataAvail {
46 public:
47 CPDF_DataAvail(IFX_FileAvail* pFileAvail,
48 IFX_FileRead* pFileRead,
49 FX_BOOL bSupportHintTable);
50 ~CPDF_DataAvail() override;
51
52 // IPDF_DataAvail:
53 DocAvailStatus IsDocAvail(IFX_DownloadHints* pHints) override;
54 void SetDocument(CPDF_Document* pDoc) override;
55 DocAvailStatus IsPageAvail(int iPage, IFX_DownloadHints* pHints) override;
56 DocFormStatus IsFormAvail(IFX_DownloadHints* pHints) override;
57 DocLinearizationStatus IsLinearizedPDF() override;
58 FX_BOOL IsLinearized() override { return m_bLinearized; }
59 void GetLinearizedMainXRefInfo(FX_FILESIZE* pPos, FX_DWORD* pSize) override;
60
61 int GetPageCount() const;
62 CPDF_Dictionary* GetPage(int index);
63
64 friend class CPDF_HintTables;
65
66 protected:
67 static const int kMaxDataAvailRecursionDepth = 64;
68 static int s_CurrentDataAvailRecursionDepth;
69 static const int kMaxPageRecursionDepth = 1024;
70
71 FX_DWORD GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset);
72 FX_BOOL IsObjectsAvail(CFX_ArrayTemplate<CPDF_Object*>& obj_array,
73 FX_BOOL bParsePage,
74 IFX_DownloadHints* pHints,
75 CFX_ArrayTemplate<CPDF_Object*>& ret_array);
76 FX_BOOL CheckDocStatus(IFX_DownloadHints* pHints);
77 FX_BOOL CheckHeader(IFX_DownloadHints* pHints);
78 FX_BOOL CheckFirstPage(IFX_DownloadHints* pHints);
79 FX_BOOL CheckHintTables(IFX_DownloadHints* pHints);
80 FX_BOOL CheckEnd(IFX_DownloadHints* pHints);
81 FX_BOOL CheckCrossRef(IFX_DownloadHints* pHints);
82 FX_BOOL CheckCrossRefItem(IFX_DownloadHints* pHints);
83 FX_BOOL CheckTrailer(IFX_DownloadHints* pHints);
84 FX_BOOL CheckRoot(IFX_DownloadHints* pHints);
85 FX_BOOL CheckInfo(IFX_DownloadHints* pHints);
86 FX_BOOL CheckPages(IFX_DownloadHints* pHints);
87 FX_BOOL CheckPage(IFX_DownloadHints* pHints);
88 FX_BOOL CheckResources(IFX_DownloadHints* pHints);
89 FX_BOOL CheckAnnots(IFX_DownloadHints* pHints);
90 FX_BOOL CheckAcroForm(IFX_DownloadHints* pHints);
91 FX_BOOL CheckAcroFormSubObject(IFX_DownloadHints* pHints);
92 FX_BOOL CheckTrailerAppend(IFX_DownloadHints* pHints);
93 FX_BOOL CheckPageStatus(IFX_DownloadHints* pHints);
94 FX_BOOL CheckAllCrossRefStream(IFX_DownloadHints* pHints);
95
96 int32_t CheckCrossRefStream(IFX_DownloadHints* pHints,
97 FX_FILESIZE& xref_offset);
98 FX_BOOL IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen);
99 void SetStartOffset(FX_FILESIZE dwOffset);
100 FX_BOOL GetNextToken(CFX_ByteString& token);
101 FX_BOOL GetNextChar(uint8_t& ch);
102 CPDF_Object* ParseIndirectObjectAt(
103 FX_FILESIZE pos,
104 FX_DWORD objnum,
105 CPDF_IndirectObjectHolder* pObjList = nullptr);
106 CPDF_Object* GetObject(FX_DWORD objnum,
107 IFX_DownloadHints* pHints,
108 FX_BOOL* pExistInFile);
109 FX_BOOL GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages);
110 FX_BOOL PreparePageItem();
111 FX_BOOL LoadPages(IFX_DownloadHints* pHints);
112 FX_BOOL LoadAllXref(IFX_DownloadHints* pHints);
113 FX_BOOL LoadAllFile(IFX_DownloadHints* pHints);
114 DocAvailStatus CheckLinearizedData(IFX_DownloadHints* pHints);
115 FX_BOOL CheckPageAnnots(int iPage, IFX_DownloadHints* pHints);
116
117 DocAvailStatus CheckLinearizedFirstPage(int iPage, IFX_DownloadHints* pHints);
118 FX_BOOL HaveResourceAncestor(CPDF_Dictionary* pDict);
119 FX_BOOL CheckPage(int32_t iPage, IFX_DownloadHints* pHints);
120 FX_BOOL LoadDocPages(IFX_DownloadHints* pHints);
121 FX_BOOL LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints);
122 FX_BOOL CheckPageNode(CPDF_PageNode& pageNodes,
123 int32_t iPage,
124 int32_t& iCount,
125 IFX_DownloadHints* pHints,
126 int level);
127 FX_BOOL CheckUnkownPageNode(FX_DWORD dwPageNo,
128 CPDF_PageNode* pPageNode,
129 IFX_DownloadHints* pHints);
130 FX_BOOL CheckArrayPageNode(FX_DWORD dwPageNo,
131 CPDF_PageNode* pPageNode,
132 IFX_DownloadHints* pHints);
133 FX_BOOL CheckPageCount(IFX_DownloadHints* pHints);
134 bool IsFirstCheck(int iPage);
135 void ResetFirstCheck(int iPage);
136 FX_BOOL IsDataAvail(FX_FILESIZE offset,
137 FX_DWORD size,
138 IFX_DownloadHints* pHints);
139
140 CPDF_Parser m_parser;
141 CPDF_SyntaxParser m_syntaxParser;
142 CPDF_Object* m_pRoot;
143 FX_DWORD m_dwRootObjNum;
144 FX_DWORD m_dwInfoObjNum;
145 CPDF_Object* m_pLinearized;
146 CPDF_Object* m_pTrailer;
147 FX_BOOL m_bDocAvail;
148 FX_FILESIZE m_dwHeaderOffset;
149 FX_FILESIZE m_dwLastXRefOffset;
150 FX_FILESIZE m_dwXRefOffset;
151 FX_FILESIZE m_dwTrailerOffset;
152 FX_FILESIZE m_dwCurrentOffset;
153 PDF_DATAAVAIL_STATUS m_docStatus;
154 FX_FILESIZE m_dwFileLen;
155 CPDF_Document* m_pDocument;
156 std::set<FX_DWORD> m_ObjectSet;
157 CFX_ArrayTemplate<CPDF_Object*> m_objs_array;
158 FX_FILESIZE m_Pos;
159 FX_FILESIZE m_bufferOffset;
160 FX_DWORD m_bufferSize;
161 CFX_ByteString m_WordBuf;
162 uint8_t m_bufferData[512];
163 CFX_DWordArray m_XRefStreamList;
164 CFX_DWordArray m_PageObjList;
165 FX_DWORD m_PagesObjNum;
166 FX_BOOL m_bLinearized;
167 FX_DWORD m_dwFirstPageNo;
168 FX_BOOL m_bLinearedDataOK;
169 FX_BOOL m_bMainXRefLoadTried;
170 FX_BOOL m_bMainXRefLoadedOK;
171 FX_BOOL m_bPagesTreeLoad;
172 FX_BOOL m_bPagesLoad;
173 CPDF_Parser* m_pCurrentParser;
174 FX_FILESIZE m_dwCurrentXRefSteam;
175 FX_BOOL m_bAnnotsLoad;
176 FX_BOOL m_bHaveAcroForm;
177 FX_DWORD m_dwAcroFormObjNum;
178 FX_BOOL m_bAcroFormLoad;
179 CPDF_Object* m_pAcroForm;
180 CFX_ArrayTemplate<CPDF_Object*> m_arrayAcroforms;
181 CPDF_Dictionary* m_pPageDict;
182 CPDF_Object* m_pPageResource;
183 FX_BOOL m_bNeedDownLoadResource;
184 FX_BOOL m_bPageLoadedOK;
185 FX_BOOL m_bLinearizedFormParamLoad;
186 CFX_ArrayTemplate<CPDF_Object*> m_PagesArray;
187 FX_DWORD m_dwEncryptObjNum;
188 FX_FILESIZE m_dwPrevXRefOffset;
189 FX_BOOL m_bTotalLoadPageTree;
190 FX_BOOL m_bCurPageDictLoadOK;
191 CPDF_PageNode m_pageNodes;
192 std::set<FX_DWORD> m_pageMapCheckState;
193 std::set<FX_DWORD> m_pagesLoadState;
194 std::unique_ptr<CPDF_HintTables> m_pHintTables;
195 FX_BOOL m_bSupportHintTable;
196 };
197
198 IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail,
199 IFX_FileRead* pFileRead)
200 : m_pFileAvail(pFileAvail), m_pFileRead(pFileRead) {}
201
202 // static
203 IPDF_DataAvail* IPDF_DataAvail::Create(IFX_FileAvail* pFileAvail,
204 IFX_FileRead* pFileRead) {
205 return new CPDF_DataAvail(pFileAvail, pFileRead, TRUE);
206 }
207
208 // static
209 int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0;
210
211 CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail,
212 IFX_FileRead* pFileRead,
213 FX_BOOL bSupportHintTable)
214 : IPDF_DataAvail(pFileAvail, pFileRead) {
215 m_Pos = 0;
216 m_dwFileLen = 0;
217 if (m_pFileRead) {
218 m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
219 }
220 m_dwCurrentOffset = 0;
221 m_dwXRefOffset = 0;
222 m_bufferOffset = 0;
223 m_dwFirstPageNo = 0;
224 m_bufferSize = 0;
225 m_PagesObjNum = 0;
226 m_dwCurrentXRefSteam = 0;
227 m_dwAcroFormObjNum = 0;
228 m_dwInfoObjNum = 0;
229 m_pDocument = 0;
230 m_dwEncryptObjNum = 0;
231 m_dwPrevXRefOffset = 0;
232 m_dwLastXRefOffset = 0;
233 m_bDocAvail = FALSE;
234 m_bMainXRefLoadTried = FALSE;
235 m_bDocAvail = FALSE;
236 m_bLinearized = FALSE;
237 m_bPagesLoad = FALSE;
238 m_bPagesTreeLoad = FALSE;
239 m_bMainXRefLoadedOK = FALSE;
240 m_bAnnotsLoad = FALSE;
241 m_bHaveAcroForm = FALSE;
242 m_bAcroFormLoad = FALSE;
243 m_bPageLoadedOK = FALSE;
244 m_bNeedDownLoadResource = FALSE;
245 m_bLinearizedFormParamLoad = FALSE;
246 m_pLinearized = NULL;
247 m_pRoot = NULL;
248 m_pTrailer = NULL;
249 m_pCurrentParser = NULL;
250 m_pAcroForm = NULL;
251 m_pPageDict = NULL;
252 m_pPageResource = NULL;
253 m_docStatus = PDF_DATAAVAIL_HEADER;
254 m_parser.m_bOwnFileRead = false;
255 m_bTotalLoadPageTree = FALSE;
256 m_bCurPageDictLoadOK = FALSE;
257 m_bLinearedDataOK = FALSE;
258 m_bSupportHintTable = bSupportHintTable;
259 }
260 CPDF_DataAvail::~CPDF_DataAvail() {
261 if (m_pLinearized)
262 m_pLinearized->Release();
263
264 if (m_pRoot)
265 m_pRoot->Release();
266
267 if (m_pTrailer)
268 m_pTrailer->Release();
269
270 int iSize = m_arrayAcroforms.GetSize();
271 for (int i = 0; i < iSize; ++i)
272 m_arrayAcroforms.GetAt(i)->Release();
273 }
274
275 void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc) {
276 m_pDocument = pDoc;
277 }
278
279 FX_DWORD CPDF_DataAvail::GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset) {
280 CPDF_Parser* pParser = m_pDocument->GetParser();
281 if (!pParser || !pParser->IsValidObjectNumber(objnum))
282 return 0;
283
284 if (pParser->GetObjectType(objnum) == 2)
285 objnum = pParser->GetObjectPositionOrZero(objnum);
286
287 if (pParser->GetObjectType(objnum) != 1 &&
288 pParser->GetObjectType(objnum) != 255) {
289 return 0;
290 }
291
292 offset = pParser->GetObjectPositionOrZero(objnum);
293 if (offset == 0)
294 return 0;
295
296 auto it = pParser->m_SortedOffset.find(offset);
297 if (it == pParser->m_SortedOffset.end() ||
298 ++it == pParser->m_SortedOffset.end()) {
299 return 0;
300 }
301 return *it - offset;
302 }
303
304 FX_BOOL CPDF_DataAvail::IsObjectsAvail(
305 CFX_ArrayTemplate<CPDF_Object*>& obj_array,
306 FX_BOOL bParsePage,
307 IFX_DownloadHints* pHints,
308 CFX_ArrayTemplate<CPDF_Object*>& ret_array) {
309 if (!obj_array.GetSize())
310 return TRUE;
311
312 FX_DWORD count = 0;
313 CFX_ArrayTemplate<CPDF_Object*> new_obj_array;
314 int32_t i = 0;
315 for (i = 0; i < obj_array.GetSize(); i++) {
316 CPDF_Object* pObj = obj_array[i];
317 if (!pObj)
318 continue;
319
320 int32_t type = pObj->GetType();
321 switch (type) {
322 case CPDF_Object::ARRAY: {
323 CPDF_Array* pArray = pObj->GetArray();
324 for (FX_DWORD k = 0; k < pArray->GetCount(); ++k)
325 new_obj_array.Add(pArray->GetElement(k));
326 } break;
327 case CPDF_Object::STREAM:
328 pObj = pObj->GetDict();
329 case CPDF_Object::DICTIONARY: {
330 CPDF_Dictionary* pDict = pObj->GetDict();
331 if (pDict && pDict->GetStringBy("Type") == "Page" && !bParsePage)
332 continue;
333
334 for (const auto& it : *pDict) {
335 const CFX_ByteString& key = it.first;
336 CPDF_Object* value = it.second;
337 if (key != "Parent")
338 new_obj_array.Add(value);
339 }
340 } break;
341 case CPDF_Object::REFERENCE: {
342 CPDF_Reference* pRef = pObj->AsReference();
343 FX_DWORD dwNum = pRef->GetRefObjNum();
344
345 FX_FILESIZE offset;
346 FX_DWORD size = GetObjectSize(dwNum, offset);
347 if (size == 0 || offset < 0 || offset >= m_dwFileLen)
348 break;
349
350 if (!IsDataAvail(offset, size, pHints)) {
351 ret_array.Add(pObj);
352 count++;
353 } else if (!pdfium::ContainsKey(m_ObjectSet, dwNum)) {
354 m_ObjectSet.insert(dwNum);
355 CPDF_Object* pReferred =
356 m_pDocument->GetIndirectObject(pRef->GetRefObjNum());
357 if (pReferred)
358 new_obj_array.Add(pReferred);
359 }
360 } break;
361 }
362 }
363
364 if (count > 0) {
365 int32_t iSize = new_obj_array.GetSize();
366 for (i = 0; i < iSize; ++i) {
367 CPDF_Object* pObj = new_obj_array[i];
368 if (CPDF_Reference* pRef = pObj->AsReference()) {
369 FX_DWORD dwNum = pRef->GetRefObjNum();
370 if (!pdfium::ContainsKey(m_ObjectSet, dwNum))
371 ret_array.Add(pObj);
372 } else {
373 ret_array.Add(pObj);
374 }
375 }
376 return FALSE;
377 }
378
379 obj_array.RemoveAll();
380 obj_array.Append(new_obj_array);
381 return IsObjectsAvail(obj_array, FALSE, pHints, ret_array);
382 }
383
384 IPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsDocAvail(
385 IFX_DownloadHints* pHints) {
386 if (!m_dwFileLen && m_pFileRead) {
387 m_dwFileLen = (FX_DWORD)m_pFileRead->GetSize();
388 if (!m_dwFileLen)
389 return DataError;
390 }
391
392 while (!m_bDocAvail) {
393 if (!CheckDocStatus(pHints))
394 return DataNotAvailable;
395 }
396
397 return DataAvailable;
398 }
399
400 FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints) {
401 if (!m_objs_array.GetSize()) {
402 m_objs_array.RemoveAll();
403 m_ObjectSet.clear();
404 CFX_ArrayTemplate<CPDF_Object*> obj_array;
405 obj_array.Append(m_arrayAcroforms);
406 FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array);
407 if (bRet)
408 m_objs_array.RemoveAll();
409 return bRet;
410 }
411
412 CFX_ArrayTemplate<CPDF_Object*> new_objs_array;
413 FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
414 if (bRet) {
415 int32_t iSize = m_arrayAcroforms.GetSize();
416 for (int32_t i = 0; i < iSize; ++i) {
417 m_arrayAcroforms.GetAt(i)->Release();
418 }
419 m_arrayAcroforms.RemoveAll();
420 } else {
421 m_objs_array.RemoveAll();
422 m_objs_array.Append(new_objs_array);
423 }
424 return bRet;
425 }
426
427 FX_BOOL CPDF_DataAvail::CheckAcroForm(IFX_DownloadHints* pHints) {
428 FX_BOOL bExist = FALSE;
429 m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist);
430 if (!bExist) {
431 m_docStatus = PDF_DATAAVAIL_PAGETREE;
432 return TRUE;
433 }
434
435 if (!m_pAcroForm) {
436 if (m_docStatus == PDF_DATAAVAIL_ERROR) {
437 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
438 return TRUE;
439 }
440 return FALSE;
441 }
442
443 m_arrayAcroforms.Add(m_pAcroForm);
444 m_docStatus = PDF_DATAAVAIL_PAGETREE;
445 return TRUE;
446 }
447
448 FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints* pHints) {
449 switch (m_docStatus) {
450 case PDF_DATAAVAIL_HEADER:
451 return CheckHeader(pHints);
452 case PDF_DATAAVAIL_FIRSTPAGE:
453 case PDF_DATAAVAIL_FIRSTPAGE_PREPARE:
454 return CheckFirstPage(pHints);
455 case PDF_DATAAVAIL_HINTTABLE:
456 return CheckHintTables(pHints);
457 case PDF_DATAAVAIL_END:
458 return CheckEnd(pHints);
459 case PDF_DATAAVAIL_CROSSREF:
460 return CheckCrossRef(pHints);
461 case PDF_DATAAVAIL_CROSSREF_ITEM:
462 return CheckCrossRefItem(pHints);
463 case PDF_DATAAVAIL_CROSSREF_STREAM:
464 return CheckAllCrossRefStream(pHints);
465 case PDF_DATAAVAIL_TRAILER:
466 return CheckTrailer(pHints);
467 case PDF_DATAAVAIL_TRAILER_APPEND:
468 return CheckTrailerAppend(pHints);
469 case PDF_DATAAVAIL_LOADALLCROSSREF:
470 return LoadAllXref(pHints);
471 case PDF_DATAAVAIL_LOADALLFILE:
472 return LoadAllFile(pHints);
473 case PDF_DATAAVAIL_ROOT:
474 return CheckRoot(pHints);
475 case PDF_DATAAVAIL_INFO:
476 return CheckInfo(pHints);
477 case PDF_DATAAVAIL_ACROFORM:
478 return CheckAcroForm(pHints);
479 case PDF_DATAAVAIL_PAGETREE:
480 if (m_bTotalLoadPageTree)
481 return CheckPages(pHints);
482 return LoadDocPages(pHints);
483 case PDF_DATAAVAIL_PAGE:
484 if (m_bTotalLoadPageTree)
485 return CheckPage(pHints);
486 m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD;
487 return TRUE;
488 case PDF_DATAAVAIL_ERROR:
489 return LoadAllFile(pHints);
490 case PDF_DATAAVAIL_PAGE_LATERLOAD:
491 m_docStatus = PDF_DATAAVAIL_PAGE;
492 default:
493 m_bDocAvail = TRUE;
494 return TRUE;
495 }
496 }
497
498 FX_BOOL CPDF_DataAvail::CheckPageStatus(IFX_DownloadHints* pHints) {
499 switch (m_docStatus) {
500 case PDF_DATAAVAIL_PAGETREE:
501 return CheckPages(pHints);
502 case PDF_DATAAVAIL_PAGE:
503 return CheckPage(pHints);
504 case PDF_DATAAVAIL_ERROR:
505 return LoadAllFile(pHints);
506 default:
507 m_bPagesTreeLoad = TRUE;
508 m_bPagesLoad = TRUE;
509 return TRUE;
510 }
511 }
512
513 FX_BOOL CPDF_DataAvail::LoadAllFile(IFX_DownloadHints* pHints) {
514 if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) {
515 m_docStatus = PDF_DATAAVAIL_DONE;
516 return TRUE;
517 }
518
519 pHints->AddSegment(0, (FX_DWORD)m_dwFileLen);
520 return FALSE;
521 }
522
523 FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints) {
524 m_parser.m_pSyntax->InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset);
525 m_parser.m_bOwnFileRead = false;
526 if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) &&
527 !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) {
528 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
529 return FALSE;
530 }
531
532 m_dwRootObjNum = m_parser.GetRootObjNum();
533 m_dwInfoObjNum = m_parser.GetInfoObjNum();
534 m_pCurrentParser = &m_parser;
535 m_docStatus = PDF_DATAAVAIL_ROOT;
536 return TRUE;
537 }
538
539 CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum,
540 IFX_DownloadHints* pHints,
541 FX_BOOL* pExistInFile) {
542 CPDF_Object* pRet = nullptr;
543 FX_DWORD size = 0;
544 FX_FILESIZE offset = 0;
545 CPDF_Parser* pParser = nullptr;
546
547 if (pExistInFile)
548 *pExistInFile = TRUE;
549
550 if (m_pDocument) {
551 size = GetObjectSize(objnum, offset);
552 pParser = m_pDocument->GetParser();
553 } else {
554 size = (FX_DWORD)m_parser.GetObjectSize(objnum);
555 offset = m_parser.GetObjectOffset(objnum);
556 pParser = &m_parser;
557 }
558
559 if (!IsDataAvail(offset, size, pHints))
560 return nullptr;
561
562 if (pParser)
563 pRet = pParser->ParseIndirectObject(nullptr, objnum);
564
565 if (!pRet && pExistInFile)
566 *pExistInFile = FALSE;
567
568 return pRet;
569 }
570
571 FX_BOOL CPDF_DataAvail::CheckInfo(IFX_DownloadHints* pHints) {
572 FX_BOOL bExist = FALSE;
573 CPDF_Object* pInfo = GetObject(m_dwInfoObjNum, pHints, &bExist);
574 if (!bExist) {
575 m_docStatus =
576 (m_bHaveAcroForm ? PDF_DATAAVAIL_ACROFORM : PDF_DATAAVAIL_PAGETREE);
577 return TRUE;
578 }
579
580 if (!pInfo) {
581 if (m_docStatus == PDF_DATAAVAIL_ERROR) {
582 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
583 return TRUE;
584 }
585
586 if (m_Pos == m_dwFileLen)
587 m_docStatus = PDF_DATAAVAIL_ERROR;
588 return FALSE;
589 }
590
591 if (pInfo)
592 pInfo->Release();
593
594 m_docStatus =
595 (m_bHaveAcroForm ? PDF_DATAAVAIL_ACROFORM : PDF_DATAAVAIL_PAGETREE);
596
597 return TRUE;
598 }
599
600 FX_BOOL CPDF_DataAvail::CheckRoot(IFX_DownloadHints* pHints) {
601 FX_BOOL bExist = FALSE;
602 m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist);
603 if (!bExist) {
604 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
605 return TRUE;
606 }
607
608 if (!m_pRoot) {
609 if (m_docStatus == PDF_DATAAVAIL_ERROR) {
610 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
611 return TRUE;
612 }
613 return FALSE;
614 }
615
616 CPDF_Dictionary* pDict = m_pRoot->GetDict();
617 if (!pDict) {
618 m_docStatus = PDF_DATAAVAIL_ERROR;
619 return FALSE;
620 }
621
622 CPDF_Reference* pRef = ToReference(pDict->GetElement("Pages"));
623 if (!pRef) {
624 m_docStatus = PDF_DATAAVAIL_ERROR;
625 return FALSE;
626 }
627
628 m_PagesObjNum = pRef->GetRefObjNum();
629 CPDF_Reference* pAcroFormRef =
630 ToReference(m_pRoot->GetDict()->GetElement("AcroForm"));
631 if (pAcroFormRef) {
632 m_bHaveAcroForm = TRUE;
633 m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum();
634 }
635
636 if (m_dwInfoObjNum) {
637 m_docStatus = PDF_DATAAVAIL_INFO;
638 } else {
639 m_docStatus =
640 m_bHaveAcroForm ? PDF_DATAAVAIL_ACROFORM : PDF_DATAAVAIL_PAGETREE;
641 }
642 return TRUE;
643 }
644
645 FX_BOOL CPDF_DataAvail::PreparePageItem() {
646 CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
647 CPDF_Reference* pRef =
648 ToReference(pRoot ? pRoot->GetElement("Pages") : nullptr);
649 if (!pRef) {
650 m_docStatus = PDF_DATAAVAIL_ERROR;
651 return FALSE;
652 }
653
654 m_PagesObjNum = pRef->GetRefObjNum();
655 m_pCurrentParser = m_pDocument->GetParser();
656 m_docStatus = PDF_DATAAVAIL_PAGETREE;
657 return TRUE;
658 }
659
660 bool CPDF_DataAvail::IsFirstCheck(int iPage) {
661 return m_pageMapCheckState.insert(iPage).second;
662 }
663
664 void CPDF_DataAvail::ResetFirstCheck(int iPage) {
665 m_pageMapCheckState.erase(iPage);
666 }
667
668 FX_BOOL CPDF_DataAvail::CheckPage(IFX_DownloadHints* pHints) {
669 FX_DWORD iPageObjs = m_PageObjList.GetSize();
670 CFX_DWordArray UnavailObjList;
671 for (FX_DWORD i = 0; i < iPageObjs; ++i) {
672 FX_DWORD dwPageObjNum = m_PageObjList.GetAt(i);
673 FX_BOOL bExist = FALSE;
674 CPDF_Object* pObj = GetObject(dwPageObjNum, pHints, &bExist);
675 if (!pObj) {
676 if (bExist)
677 UnavailObjList.Add(dwPageObjNum);
678 continue;
679 }
680
681 if (pObj->IsArray()) {
682 CPDF_Array* pArray = pObj->GetArray();
683 if (pArray) {
684 int32_t iSize = pArray->GetCount();
685 for (int32_t j = 0; j < iSize; ++j) {
686 if (CPDF_Reference* pRef = ToReference(pArray->GetElement(j)))
687 UnavailObjList.Add(pRef->GetRefObjNum());
688 }
689 }
690 }
691
692 if (!pObj->IsDictionary()) {
693 pObj->Release();
694 continue;
695 }
696
697 CFX_ByteString type = pObj->GetDict()->GetStringBy("Type");
698 if (type == "Pages") {
699 m_PagesArray.Add(pObj);
700 continue;
701 }
702 pObj->Release();
703 }
704
705 m_PageObjList.RemoveAll();
706 if (UnavailObjList.GetSize()) {
707 m_PageObjList.Append(UnavailObjList);
708 return FALSE;
709 }
710
711 FX_DWORD iPages = m_PagesArray.GetSize();
712 for (FX_DWORD i = 0; i < iPages; i++) {
713 CPDF_Object* pPages = m_PagesArray.GetAt(i);
714 if (!pPages)
715 continue;
716
717 if (!GetPageKids(m_pCurrentParser, pPages)) {
718 pPages->Release();
719 while (++i < iPages) {
720 pPages = m_PagesArray.GetAt(i);
721 pPages->Release();
722 }
723 m_PagesArray.RemoveAll();
724
725 m_docStatus = PDF_DATAAVAIL_ERROR;
726 return FALSE;
727 }
728 pPages->Release();
729 }
730
731 m_PagesArray.RemoveAll();
732 if (!m_PageObjList.GetSize())
733 m_docStatus = PDF_DATAAVAIL_DONE;
734 return TRUE;
735 }
736
737 FX_BOOL CPDF_DataAvail::GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages) {
738 if (!pParser) {
739 m_docStatus = PDF_DATAAVAIL_ERROR;
740 return FALSE;
741 }
742
743 CPDF_Dictionary* pDict = pPages->GetDict();
744 CPDF_Object* pKids = pDict ? pDict->GetElement("Kids") : NULL;
745 if (!pKids)
746 return TRUE;
747
748 switch (pKids->GetType()) {
749 case CPDF_Object::REFERENCE:
750 m_PageObjList.Add(pKids->AsReference()->GetRefObjNum());
751 break;
752 case CPDF_Object::ARRAY: {
753 CPDF_Array* pKidsArray = pKids->AsArray();
754 for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) {
755 if (CPDF_Reference* pRef = ToReference(pKidsArray->GetElement(i)))
756 m_PageObjList.Add(pRef->GetRefObjNum());
757 }
758 } break;
759 default:
760 m_docStatus = PDF_DATAAVAIL_ERROR;
761 return FALSE;
762 }
763 return TRUE;
764 }
765
766 FX_BOOL CPDF_DataAvail::CheckPages(IFX_DownloadHints* pHints) {
767 FX_BOOL bExist = FALSE;
768 CPDF_Object* pPages = GetObject(m_PagesObjNum, pHints, &bExist);
769 if (!bExist) {
770 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
771 return TRUE;
772 }
773
774 if (!pPages) {
775 if (m_docStatus == PDF_DATAAVAIL_ERROR) {
776 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
777 return TRUE;
778 }
779 return FALSE;
780 }
781
782 if (!GetPageKids(m_pCurrentParser, pPages)) {
783 pPages->Release();
784 m_docStatus = PDF_DATAAVAIL_ERROR;
785 return FALSE;
786 }
787
788 pPages->Release();
789 m_docStatus = PDF_DATAAVAIL_PAGE;
790 return TRUE;
791 }
792
793 FX_BOOL CPDF_DataAvail::CheckHeader(IFX_DownloadHints* pHints) {
794 FX_DWORD req_size = 1024;
795 if ((FX_FILESIZE)req_size > m_dwFileLen)
796 req_size = (FX_DWORD)m_dwFileLen;
797
798 if (m_pFileAvail->IsDataAvail(0, req_size)) {
799 uint8_t buffer[1024];
800 m_pFileRead->ReadBlock(buffer, 0, req_size);
801
802 if (IsLinearizedFile(buffer, req_size)) {
803 m_docStatus = PDF_DATAAVAIL_FIRSTPAGE;
804 } else {
805 if (m_docStatus == PDF_DATAAVAIL_ERROR)
806 return FALSE;
807 m_docStatus = PDF_DATAAVAIL_END;
808 }
809 return TRUE;
810 }
811
812 pHints->AddSegment(0, req_size);
813 return FALSE;
814 }
815
816 FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints* pHints) {
817 CPDF_Dictionary* pDict = m_pLinearized->GetDict();
818 CPDF_Object* pEndOffSet = pDict ? pDict->GetElement("E") : NULL;
819 if (!pEndOffSet) {
820 m_docStatus = PDF_DATAAVAIL_ERROR;
821 return FALSE;
822 }
823
824 CPDF_Object* pXRefOffset = pDict ? pDict->GetElement("T") : NULL;
825 if (!pXRefOffset) {
826 m_docStatus = PDF_DATAAVAIL_ERROR;
827 return FALSE;
828 }
829
830 CPDF_Object* pFileLen = pDict ? pDict->GetElement("L") : NULL;
831 if (!pFileLen) {
832 m_docStatus = PDF_DATAAVAIL_ERROR;
833 return FALSE;
834 }
835
836 FX_BOOL bNeedDownLoad = FALSE;
837 if (pEndOffSet->IsNumber()) {
838 FX_DWORD dwEnd = pEndOffSet->GetInteger();
839 dwEnd += 512;
840 if ((FX_FILESIZE)dwEnd > m_dwFileLen)
841 dwEnd = (FX_DWORD)m_dwFileLen;
842
843 int32_t iStartPos = (int32_t)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen);
844 int32_t iSize = dwEnd > 1024 ? dwEnd - 1024 : 0;
845 if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) {
846 pHints->AddSegment(iStartPos, iSize);
847 bNeedDownLoad = TRUE;
848 }
849 }
850
851 m_dwLastXRefOffset = 0;
852 FX_FILESIZE dwFileLen = 0;
853 if (pXRefOffset->IsNumber())
854 m_dwLastXRefOffset = pXRefOffset->GetInteger();
855
856 if (pFileLen->IsNumber())
857 dwFileLen = pFileLen->GetInteger();
858
859 if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset,
860 (FX_DWORD)(dwFileLen - m_dwLastXRefOffset))) {
861 if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE) {
862 FX_DWORD dwSize = (FX_DWORD)(dwFileLen - m_dwLastXRefOffset);
863 FX_FILESIZE offset = m_dwLastXRefOffset;
864 if (dwSize < 512 && dwFileLen > 512) {
865 dwSize = 512;
866 offset = dwFileLen - 512;
867 }
868 pHints->AddSegment(offset, dwSize);
869 }
870 } else {
871 m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
872 }
873
874 if (bNeedDownLoad || m_docStatus != PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
875 m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
876 return FALSE;
877 }
878
879 m_docStatus =
880 m_bSupportHintTable ? PDF_DATAAVAIL_HINTTABLE : PDF_DATAAVAIL_DONE;
881 return TRUE;
882 }
883
884 FX_BOOL CPDF_DataAvail::IsDataAvail(FX_FILESIZE offset,
885 FX_DWORD size,
886 IFX_DownloadHints* pHints) {
887 if (offset > m_dwFileLen)
888 return TRUE;
889
890 FX_SAFE_DWORD safeSize = pdfium::base::checked_cast<FX_DWORD>(offset);
891 safeSize += size;
892 safeSize += 512;
893 if (!safeSize.IsValid() || safeSize.ValueOrDie() > m_dwFileLen)
894 size = m_dwFileLen - offset;
895 else
896 size += 512;
897
898 if (!m_pFileAvail->IsDataAvail(offset, size)) {
899 pHints->AddSegment(offset, size);
900 return FALSE;
901 }
902 return TRUE;
903 }
904
905 FX_BOOL CPDF_DataAvail::CheckHintTables(IFX_DownloadHints* pHints) {
906 CPDF_Dictionary* pDict = m_pLinearized->GetDict();
907 if (!pDict) {
908 m_docStatus = PDF_DATAAVAIL_ERROR;
909 return FALSE;
910 }
911
912 if (!pDict->KeyExist("H") || !pDict->KeyExist("O") || !pDict->KeyExist("N")) {
913 m_docStatus = PDF_DATAAVAIL_ERROR;
914 return FALSE;
915 }
916
917 int nPageCount = pDict->GetElementValue("N")->GetInteger();
918 if (nPageCount <= 1) {
919 m_docStatus = PDF_DATAAVAIL_DONE;
920 return TRUE;
921 }
922
923 CPDF_Array* pHintStreamRange = pDict->GetArrayBy("H");
924 FX_FILESIZE szHSStart =
925 pHintStreamRange->GetElementValue(0)
926 ? pHintStreamRange->GetElementValue(0)->GetInteger()
927 : 0;
928 FX_FILESIZE szHSLength =
929 pHintStreamRange->GetElementValue(1)
930 ? pHintStreamRange->GetElementValue(1)->GetInteger()
931 : 0;
932 if (szHSStart < 0 || szHSLength <= 0) {
933 m_docStatus = PDF_DATAAVAIL_ERROR;
934 return FALSE;
935 }
936
937 if (!IsDataAvail(szHSStart, szHSLength, pHints))
938 return FALSE;
939
940 m_syntaxParser.InitParser(m_pFileRead, m_dwHeaderOffset);
941
942 std::unique_ptr<CPDF_HintTables> pHintTables(
943 new CPDF_HintTables(this, pDict));
944 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pHintStream(
945 ParseIndirectObjectAt(szHSStart, 0));
946 CPDF_Stream* pStream = ToStream(pHintStream.get());
947 if (pStream && pHintTables->LoadHintStream(pStream))
948 m_pHintTables = std::move(pHintTables);
949
950 m_docStatus = PDF_DATAAVAIL_DONE;
951 return TRUE;
952 }
953
954 CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(
955 FX_FILESIZE pos,
956 FX_DWORD objnum,
957 CPDF_IndirectObjectHolder* pObjList) {
958 FX_FILESIZE SavedPos = m_syntaxParser.SavePos();
959 m_syntaxParser.RestorePos(pos);
960
961 bool bIsNumber;
962 CFX_ByteString word = m_syntaxParser.GetNextWord(&bIsNumber);
963 if (!bIsNumber)
964 return nullptr;
965
966 FX_DWORD parser_objnum = FXSYS_atoui(word);
967 if (objnum && parser_objnum != objnum)
968 return nullptr;
969
970 word = m_syntaxParser.GetNextWord(&bIsNumber);
971 if (!bIsNumber)
972 return nullptr;
973
974 FX_DWORD gennum = FXSYS_atoui(word);
975 if (m_syntaxParser.GetKeyword() != "obj") {
976 m_syntaxParser.RestorePos(SavedPos);
977 return nullptr;
978 }
979
980 CPDF_Object* pObj =
981 m_syntaxParser.GetObject(pObjList, parser_objnum, gennum, true);
982 m_syntaxParser.RestorePos(SavedPos);
983 return pObj;
984 }
985
986 IPDF_DataAvail::DocLinearizationStatus CPDF_DataAvail::IsLinearizedPDF() {
987 FX_DWORD req_size = 1024;
988 if (!m_pFileAvail->IsDataAvail(0, req_size))
989 return LinearizationUnknown;
990
991 if (!m_pFileRead)
992 return NotLinearized;
993
994 FX_FILESIZE dwSize = m_pFileRead->GetSize();
995 if (dwSize < (FX_FILESIZE)req_size)
996 return LinearizationUnknown;
997
998 uint8_t buffer[1024];
999 m_pFileRead->ReadBlock(buffer, 0, req_size);
1000 if (IsLinearizedFile(buffer, req_size))
1001 return Linearized;
1002
1003 return NotLinearized;
1004 }
1005 FX_BOOL CPDF_DataAvail::IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen) {
1006 ScopedFileStream file(FX_CreateMemoryStream(pData, (size_t)dwLen, FALSE));
1007
1008 int32_t offset = GetHeaderOffset(file.get());
1009 if (offset == -1) {
1010 m_docStatus = PDF_DATAAVAIL_ERROR;
1011 return FALSE;
1012 }
1013
1014 m_dwHeaderOffset = offset;
1015 m_syntaxParser.InitParser(file.get(), offset);
1016 m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9);
1017
1018 bool bNumber;
1019 CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(&bNumber);
1020 if (!bNumber)
1021 return FALSE;
1022
1023 FX_DWORD objnum = FXSYS_atoui(wordObjNum);
1024 if (m_pLinearized) {
1025 m_pLinearized->Release();
1026 m_pLinearized = nullptr;
1027 }
1028
1029 m_pLinearized =
1030 ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum);
1031 if (!m_pLinearized)
1032 return FALSE;
1033
1034 CPDF_Dictionary* pDict = m_pLinearized->GetDict();
1035 if (pDict && pDict->GetElement("Linearized")) {
1036 CPDF_Object* pLen = pDict->GetElement("L");
1037 if (!pLen)
1038 return FALSE;
1039
1040 if ((FX_FILESIZE)pLen->GetInteger() != m_pFileRead->GetSize())
1041 return FALSE;
1042
1043 m_bLinearized = TRUE;
1044
1045 if (CPDF_Number* pNo = ToNumber(pDict->GetElement("P")))
1046 m_dwFirstPageNo = pNo->GetInteger();
1047
1048 return TRUE;
1049 }
1050 return FALSE;
1051 }
1052
1053 FX_BOOL CPDF_DataAvail::CheckEnd(IFX_DownloadHints* pHints) {
1054 FX_DWORD req_pos = (FX_DWORD)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0);
1055 FX_DWORD dwSize = (FX_DWORD)(m_dwFileLen - req_pos);
1056
1057 if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) {
1058 uint8_t buffer[1024];
1059 m_pFileRead->ReadBlock(buffer, req_pos, dwSize);
1060
1061 ScopedFileStream file(FX_CreateMemoryStream(buffer, (size_t)dwSize, FALSE));
1062 m_syntaxParser.InitParser(file.get(), 0);
1063 m_syntaxParser.RestorePos(dwSize - 1);
1064
1065 if (m_syntaxParser.SearchWord("startxref", TRUE, FALSE, dwSize)) {
1066 m_syntaxParser.GetNextWord(nullptr);
1067
1068 bool bNumber;
1069 CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(&bNumber);
1070 if (!bNumber) {
1071 m_docStatus = PDF_DATAAVAIL_ERROR;
1072 return FALSE;
1073 }
1074
1075 m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
1076 if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) {
1077 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
1078 return TRUE;
1079 }
1080
1081 m_dwLastXRefOffset = m_dwXRefOffset;
1082 SetStartOffset(m_dwXRefOffset);
1083 m_docStatus = PDF_DATAAVAIL_CROSSREF;
1084 return TRUE;
1085 }
1086
1087 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
1088 return TRUE;
1089 }
1090
1091 pHints->AddSegment(req_pos, dwSize);
1092 return FALSE;
1093 }
1094
1095 int32_t CPDF_DataAvail::CheckCrossRefStream(IFX_DownloadHints* pHints,
1096 FX_FILESIZE& xref_offset) {
1097 xref_offset = 0;
1098 FX_DWORD req_size =
1099 (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
1100
1101 if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) {
1102 int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam);
1103 CFX_BinaryBuf buf(iSize);
1104 uint8_t* pBuf = buf.GetBuffer();
1105
1106 m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize);
1107
1108 ScopedFileStream file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
1109 m_parser.m_pSyntax->InitParser(file.get(), 0);
1110
1111 bool bNumber;
1112 CFX_ByteString objnum = m_parser.m_pSyntax->GetNextWord(&bNumber);
1113 if (!bNumber)
1114 return -1;
1115
1116 FX_DWORD objNum = FXSYS_atoui(objnum);
1117 CPDF_Object* pObj = m_parser.ParseIndirectObjectAt(nullptr, 0, objNum);
1118 if (!pObj) {
1119 m_Pos += m_parser.m_pSyntax->SavePos();
1120 return 0;
1121 }
1122
1123 CPDF_Dictionary* pDict = pObj->GetDict();
1124 CPDF_Name* pName = ToName(pDict ? pDict->GetElement("Type") : nullptr);
1125 if (pName) {
1126 if (pName->GetString() == "XRef") {
1127 m_Pos += m_parser.m_pSyntax->SavePos();
1128 xref_offset = pObj->GetDict()->GetIntegerBy("Prev");
1129 pObj->Release();
1130 return 1;
1131 }
1132 }
1133 pObj->Release();
1134 return -1;
1135 }
1136 pHints->AddSegment(m_Pos, req_size);
1137 return 0;
1138 }
1139
1140 inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset) {
1141 m_Pos = dwOffset;
1142 }
1143
1144 FX_BOOL CPDF_DataAvail::GetNextToken(CFX_ByteString& token) {
1145 uint8_t ch;
1146 if (!GetNextChar(ch))
1147 return FALSE;
1148
1149 while (1) {
1150 while (PDFCharIsWhitespace(ch)) {
1151 if (!GetNextChar(ch))
1152 return FALSE;
1153 }
1154
1155 if (ch != '%')
1156 break;
1157
1158 while (1) {
1159 if (!GetNextChar(ch))
1160 return FALSE;
1161 if (PDFCharIsLineEnding(ch))
1162 break;
1163 }
1164 }
1165
1166 uint8_t buffer[256];
1167 FX_DWORD index = 0;
1168 if (PDFCharIsDelimiter(ch)) {
1169 buffer[index++] = ch;
1170 if (ch == '/') {
1171 while (1) {
1172 if (!GetNextChar(ch))
1173 return FALSE;
1174
1175 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) {
1176 m_Pos--;
1177 CFX_ByteString ret(buffer, index);
1178 token = ret;
1179 return TRUE;
1180 }
1181
1182 if (index < sizeof(buffer))
1183 buffer[index++] = ch;
1184 }
1185 } else if (ch == '<') {
1186 if (!GetNextChar(ch))
1187 return FALSE;
1188
1189 if (ch == '<')
1190 buffer[index++] = ch;
1191 else
1192 m_Pos--;
1193 } else if (ch == '>') {
1194 if (!GetNextChar(ch))
1195 return FALSE;
1196
1197 if (ch == '>')
1198 buffer[index++] = ch;
1199 else
1200 m_Pos--;
1201 }
1202
1203 CFX_ByteString ret(buffer, index);
1204 token = ret;
1205 return TRUE;
1206 }
1207
1208 while (1) {
1209 if (index < sizeof(buffer))
1210 buffer[index++] = ch;
1211
1212 if (!GetNextChar(ch))
1213 return FALSE;
1214
1215 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
1216 m_Pos--;
1217 break;
1218 }
1219 }
1220
1221 token = CFX_ByteString(buffer, index);
1222 return TRUE;
1223 }
1224
1225 FX_BOOL CPDF_DataAvail::GetNextChar(uint8_t& ch) {
1226 FX_FILESIZE pos = m_Pos;
1227 if (pos >= m_dwFileLen)
1228 return FALSE;
1229
1230 if (m_bufferOffset >= pos ||
1231 (FX_FILESIZE)(m_bufferOffset + m_bufferSize) <= pos) {
1232 FX_FILESIZE read_pos = pos;
1233 FX_DWORD read_size = 512;
1234 if ((FX_FILESIZE)read_size > m_dwFileLen)
1235 read_size = (FX_DWORD)m_dwFileLen;
1236
1237 if ((FX_FILESIZE)(read_pos + read_size) > m_dwFileLen)
1238 read_pos = m_dwFileLen - read_size;
1239
1240 if (!m_pFileRead->ReadBlock(m_bufferData, read_pos, read_size))
1241 return FALSE;
1242
1243 m_bufferOffset = read_pos;
1244 m_bufferSize = read_size;
1245 }
1246 ch = m_bufferData[pos - m_bufferOffset];
1247 m_Pos++;
1248 return TRUE;
1249 }
1250
1251 FX_BOOL CPDF_DataAvail::CheckCrossRefItem(IFX_DownloadHints* pHints) {
1252 int32_t iSize = 0;
1253 CFX_ByteString token;
1254 while (1) {
1255 if (!GetNextToken(token)) {
1256 iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
1257 pHints->AddSegment(m_Pos, iSize);
1258 return FALSE;
1259 }
1260
1261 if (token == "trailer") {
1262 m_dwTrailerOffset = m_Pos;
1263 m_docStatus = PDF_DATAAVAIL_TRAILER;
1264 return TRUE;
1265 }
1266 }
1267 }
1268
1269 FX_BOOL CPDF_DataAvail::CheckAllCrossRefStream(IFX_DownloadHints* pHints) {
1270 FX_FILESIZE xref_offset = 0;
1271
1272 int32_t nRet = CheckCrossRefStream(pHints, xref_offset);
1273 if (nRet == 1) {
1274 if (!xref_offset) {
1275 m_docStatus = PDF_DATAAVAIL_LOADALLCROSSREF;
1276 } else {
1277 m_dwCurrentXRefSteam = xref_offset;
1278 m_Pos = xref_offset;
1279 }
1280 return TRUE;
1281 }
1282
1283 if (nRet == -1)
1284 m_docStatus = PDF_DATAAVAIL_ERROR;
1285 return FALSE;
1286 }
1287
1288 FX_BOOL CPDF_DataAvail::CheckCrossRef(IFX_DownloadHints* pHints) {
1289 int32_t iSize = 0;
1290 CFX_ByteString token;
1291 if (!GetNextToken(token)) {
1292 iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
1293 pHints->AddSegment(m_Pos, iSize);
1294 return FALSE;
1295 }
1296
1297 if (token == "xref") {
1298 while (1) {
1299 if (!GetNextToken(token)) {
1300 iSize =
1301 (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
1302 pHints->AddSegment(m_Pos, iSize);
1303 m_docStatus = PDF_DATAAVAIL_CROSSREF_ITEM;
1304 return FALSE;
1305 }
1306
1307 if (token == "trailer") {
1308 m_dwTrailerOffset = m_Pos;
1309 m_docStatus = PDF_DATAAVAIL_TRAILER;
1310 return TRUE;
1311 }
1312 }
1313 } else {
1314 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
1315 return TRUE;
1316 }
1317 return FALSE;
1318 }
1319
1320 FX_BOOL CPDF_DataAvail::CheckTrailerAppend(IFX_DownloadHints* pHints) {
1321 if (m_Pos < m_dwFileLen) {
1322 FX_FILESIZE dwAppendPos = m_Pos + m_syntaxParser.SavePos();
1323 int32_t iSize = (int32_t)(
1324 dwAppendPos + 512 > m_dwFileLen ? m_dwFileLen - dwAppendPos : 512);
1325
1326 if (!m_pFileAvail->IsDataAvail(dwAppendPos, iSize)) {
1327 pHints->AddSegment(dwAppendPos, iSize);
1328 return FALSE;
1329 }
1330 }
1331
1332 if (m_dwPrevXRefOffset) {
1333 SetStartOffset(m_dwPrevXRefOffset);
1334 m_docStatus = PDF_DATAAVAIL_CROSSREF;
1335 } else {
1336 m_docStatus = PDF_DATAAVAIL_LOADALLCROSSREF;
1337 }
1338 return TRUE;
1339 }
1340
1341 FX_BOOL CPDF_DataAvail::CheckTrailer(IFX_DownloadHints* pHints) {
1342 int32_t iTrailerSize =
1343 (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512);
1344 if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) {
1345 int32_t iSize = (int32_t)(m_Pos + iTrailerSize - m_dwTrailerOffset);
1346 CFX_BinaryBuf buf(iSize);
1347 uint8_t* pBuf = buf.GetBuffer();
1348 if (!pBuf) {
1349 m_docStatus = PDF_DATAAVAIL_ERROR;
1350 return FALSE;
1351 }
1352
1353 if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize))
1354 return FALSE;
1355
1356 ScopedFileStream file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE));
1357 m_syntaxParser.InitParser(file.get(), 0);
1358
1359 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pTrailer(
1360 m_syntaxParser.GetObject(nullptr, 0, 0, true));
1361 if (!pTrailer) {
1362 m_Pos += m_syntaxParser.SavePos();
1363 pHints->AddSegment(m_Pos, iTrailerSize);
1364 return FALSE;
1365 }
1366
1367 if (!pTrailer->IsDictionary())
1368 return FALSE;
1369
1370 CPDF_Dictionary* pTrailerDict = pTrailer->GetDict();
1371 CPDF_Object* pEncrypt = pTrailerDict->GetElement("Encrypt");
1372 if (ToReference(pEncrypt)) {
1373 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
1374 return TRUE;
1375 }
1376
1377 FX_DWORD xrefpos = GetDirectInteger(pTrailerDict, "Prev");
1378 if (xrefpos) {
1379 m_dwPrevXRefOffset = GetDirectInteger(pTrailerDict, "XRefStm");
1380 if (m_dwPrevXRefOffset) {
1381 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
1382 } else {
1383 m_dwPrevXRefOffset = xrefpos;
1384 if (m_dwPrevXRefOffset >= m_dwFileLen) {
1385 m_docStatus = PDF_DATAAVAIL_LOADALLFILE;
1386 } else {
1387 SetStartOffset(m_dwPrevXRefOffset);
1388 m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND;
1389 }
1390 }
1391 return TRUE;
1392 }
1393 m_dwPrevXRefOffset = 0;
1394 m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND;
1395 return TRUE;
1396 }
1397 pHints->AddSegment(m_Pos, iTrailerSize);
1398 return FALSE;
1399 }
1400
1401 FX_BOOL CPDF_DataAvail::CheckPage(int32_t iPage, IFX_DownloadHints* pHints) {
1402 while (TRUE) {
1403 switch (m_docStatus) {
1404 case PDF_DATAAVAIL_PAGETREE:
1405 if (!LoadDocPages(pHints))
1406 return FALSE;
1407 break;
1408 case PDF_DATAAVAIL_PAGE:
1409 if (!LoadDocPage(iPage, pHints))
1410 return FALSE;
1411 break;
1412 case PDF_DATAAVAIL_ERROR:
1413 return LoadAllFile(pHints);
1414 default:
1415 m_bPagesTreeLoad = TRUE;
1416 m_bPagesLoad = TRUE;
1417 m_bCurPageDictLoadOK = TRUE;
1418 m_docStatus = PDF_DATAAVAIL_PAGE;
1419 return TRUE;
1420 }
1421 }
1422 }
1423
1424 FX_BOOL CPDF_DataAvail::CheckArrayPageNode(FX_DWORD dwPageNo,
1425 CPDF_PageNode* pPageNode,
1426 IFX_DownloadHints* pHints) {
1427 FX_BOOL bExist = FALSE;
1428 CPDF_Object* pPages = GetObject(dwPageNo, pHints, &bExist);
1429 if (!bExist) {
1430 m_docStatus = PDF_DATAAVAIL_ERROR;
1431 return FALSE;
1432 }
1433
1434 if (!pPages) {
1435 if (m_docStatus == PDF_DATAAVAIL_ERROR) {
1436 m_docStatus = PDF_DATAAVAIL_ERROR;
1437 return FALSE;
1438 }
1439 return FALSE;
1440 }
1441
1442 CPDF_Array* pArray = pPages->AsArray();
1443 if (!pArray) {
1444 pPages->Release();
1445 m_docStatus = PDF_DATAAVAIL_ERROR;
1446 return FALSE;
1447 }
1448
1449 pPageNode->m_type = PDF_PAGENODE_PAGES;
1450 for (FX_DWORD i = 0; i < pArray->GetCount(); ++i) {
1451 CPDF_Reference* pKid = ToReference(pArray->GetElement(i));
1452 if (!pKid)
1453 continue;
1454
1455 CPDF_PageNode* pNode = new CPDF_PageNode();
1456 pPageNode->m_childNode.Add(pNode);
1457 pNode->m_dwPageNo = pKid->GetRefObjNum();
1458 }
1459 pPages->Release();
1460 return TRUE;
1461 }
1462
1463 FX_BOOL CPDF_DataAvail::CheckUnkownPageNode(FX_DWORD dwPageNo,
1464 CPDF_PageNode* pPageNode,
1465 IFX_DownloadHints* pHints) {
1466 FX_BOOL bExist = FALSE;
1467 CPDF_Object* pPage = GetObject(dwPageNo, pHints, &bExist);
1468 if (!bExist) {
1469 m_docStatus = PDF_DATAAVAIL_ERROR;
1470 return FALSE;
1471 }
1472
1473 if (!pPage) {
1474 if (m_docStatus == PDF_DATAAVAIL_ERROR)
1475 m_docStatus = PDF_DATAAVAIL_ERROR;
1476 return FALSE;
1477 }
1478
1479 if (pPage->IsArray()) {
1480 pPageNode->m_dwPageNo = dwPageNo;
1481 pPageNode->m_type = PDF_PAGENODE_ARRAY;
1482 pPage->Release();
1483 return TRUE;
1484 }
1485
1486 if (!pPage->IsDictionary()) {
1487 pPage->Release();
1488 m_docStatus = PDF_DATAAVAIL_ERROR;
1489 return FALSE;
1490 }
1491
1492 pPageNode->m_dwPageNo = dwPageNo;
1493 CPDF_Dictionary* pDict = pPage->GetDict();
1494 CFX_ByteString type = pDict->GetStringBy("Type");
1495 if (type == "Pages") {
1496 pPageNode->m_type = PDF_PAGENODE_PAGES;
1497 CPDF_Object* pKids = pDict->GetElement("Kids");
1498 if (!pKids) {
1499 m_docStatus = PDF_DATAAVAIL_PAGE;
1500 return TRUE;
1501 }
1502
1503 switch (pKids->GetType()) {
1504 case CPDF_Object::REFERENCE: {
1505 CPDF_Reference* pKid = pKids->AsReference();
1506 CPDF_PageNode* pNode = new CPDF_PageNode();
1507 pPageNode->m_childNode.Add(pNode);
1508 pNode->m_dwPageNo = pKid->GetRefObjNum();
1509 } break;
1510 case CPDF_Object::ARRAY: {
1511 CPDF_Array* pKidsArray = pKids->AsArray();
1512 for (FX_DWORD i = 0; i < pKidsArray->GetCount(); ++i) {
1513 CPDF_Reference* pKid = ToReference(pKidsArray->GetElement(i));
1514 if (!pKid)
1515 continue;
1516
1517 CPDF_PageNode* pNode = new CPDF_PageNode();
1518 pPageNode->m_childNode.Add(pNode);
1519 pNode->m_dwPageNo = pKid->GetRefObjNum();
1520 }
1521 } break;
1522 default:
1523 break;
1524 }
1525 } else if (type == "Page") {
1526 pPageNode->m_type = PDF_PAGENODE_PAGE;
1527 } else {
1528 pPage->Release();
1529 m_docStatus = PDF_DATAAVAIL_ERROR;
1530 return FALSE;
1531 }
1532 pPage->Release();
1533 return TRUE;
1534 }
1535
1536 FX_BOOL CPDF_DataAvail::CheckPageNode(CPDF_PageNode& pageNodes,
1537 int32_t iPage,
1538 int32_t& iCount,
1539 IFX_DownloadHints* pHints,
1540 int level) {
1541 if (level >= kMaxPageRecursionDepth)
1542 return FALSE;
1543
1544 int32_t iSize = pageNodes.m_childNode.GetSize();
1545 if (iSize <= 0 || iPage >= iSize) {
1546 m_docStatus = PDF_DATAAVAIL_ERROR;
1547 return FALSE;
1548 }
1549
1550 for (int32_t i = 0; i < iSize; ++i) {
1551 CPDF_PageNode* pNode = pageNodes.m_childNode.GetAt(i);
1552 if (!pNode)
1553 continue;
1554
1555 switch (pNode->m_type) {
1556 case PDF_PAGENODE_UNKNOWN:
1557 if (!CheckUnkownPageNode(pNode->m_dwPageNo, pNode, pHints)) {
1558 return FALSE;
1559 }
1560 --i;
1561 break;
1562 case PDF_PAGENODE_PAGE:
1563 iCount++;
1564 if (iPage == iCount && m_pDocument)
1565 m_pDocument->m_PageList.SetAt(iPage, pNode->m_dwPageNo);
1566 break;
1567 case PDF_PAGENODE_PAGES:
1568 if (!CheckPageNode(*pNode, iPage, iCount, pHints, level + 1))
1569 return FALSE;
1570 break;
1571 case PDF_PAGENODE_ARRAY:
1572 if (!CheckArrayPageNode(pNode->m_dwPageNo, pNode, pHints))
1573 return FALSE;
1574 --i;
1575 break;
1576 }
1577
1578 if (iPage == iCount) {
1579 m_docStatus = PDF_DATAAVAIL_DONE;
1580 return TRUE;
1581 }
1582 }
1583 return TRUE;
1584 }
1585
1586 FX_BOOL CPDF_DataAvail::LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints) {
1587 if (m_pDocument->GetPageCount() <= iPage ||
1588 m_pDocument->m_PageList.GetAt(iPage)) {
1589 m_docStatus = PDF_DATAAVAIL_DONE;
1590 return TRUE;
1591 }
1592
1593 if (m_pageNodes.m_type == PDF_PAGENODE_PAGE) {
1594 if (iPage == 0) {
1595 m_docStatus = PDF_DATAAVAIL_DONE;
1596 return TRUE;
1597 }
1598 m_docStatus = PDF_DATAAVAIL_ERROR;
1599 return TRUE;
1600 }
1601 int32_t iCount = -1;
1602 return CheckPageNode(m_pageNodes, iPage, iCount, pHints, 0);
1603 }
1604
1605 FX_BOOL CPDF_DataAvail::CheckPageCount(IFX_DownloadHints* pHints) {
1606 FX_BOOL bExist = FALSE;
1607 CPDF_Object* pPages = GetObject(m_PagesObjNum, pHints, &bExist);
1608 if (!bExist) {
1609 m_docStatus = PDF_DATAAVAIL_ERROR;
1610 return FALSE;
1611 }
1612
1613 if (!pPages)
1614 return FALSE;
1615
1616 CPDF_Dictionary* pPagesDict = pPages->GetDict();
1617 if (!pPagesDict) {
1618 pPages->Release();
1619 m_docStatus = PDF_DATAAVAIL_ERROR;
1620 return FALSE;
1621 }
1622
1623 if (!pPagesDict->KeyExist("Kids")) {
1624 pPages->Release();
1625 return TRUE;
1626 }
1627
1628 int count = pPagesDict->GetIntegerBy("Count");
1629 if (count > 0) {
1630 pPages->Release();
1631 return TRUE;
1632 }
1633
1634 pPages->Release();
1635 return FALSE;
1636 }
1637
1638 FX_BOOL CPDF_DataAvail::LoadDocPages(IFX_DownloadHints* pHints) {
1639 if (!CheckUnkownPageNode(m_PagesObjNum, &m_pageNodes, pHints))
1640 return FALSE;
1641
1642 if (CheckPageCount(pHints)) {
1643 m_docStatus = PDF_DATAAVAIL_PAGE;
1644 return TRUE;
1645 }
1646
1647 m_bTotalLoadPageTree = TRUE;
1648 return FALSE;
1649 }
1650
1651 FX_BOOL CPDF_DataAvail::LoadPages(IFX_DownloadHints* pHints) {
1652 while (!m_bPagesTreeLoad) {
1653 if (!CheckPageStatus(pHints))
1654 return FALSE;
1655 }
1656
1657 if (m_bPagesLoad)
1658 return TRUE;
1659
1660 m_pDocument->LoadPages();
1661 return FALSE;
1662 }
1663
1664 IPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedData(
1665 IFX_DownloadHints* pHints) {
1666 if (m_bLinearedDataOK)
1667 return DataAvailable;
1668
1669 if (!m_bMainXRefLoadTried) {
1670 FX_SAFE_DWORD data_size = m_dwFileLen;
1671 data_size -= m_dwLastXRefOffset;
1672 if (!data_size.IsValid())
1673 return DataError;
1674
1675 if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset,
1676 data_size.ValueOrDie())) {
1677 pHints->AddSegment(m_dwLastXRefOffset, data_size.ValueOrDie());
1678 return DataNotAvailable;
1679 }
1680
1681 CPDF_Parser::Error eRet =
1682 m_pDocument->GetParser()->LoadLinearizedMainXRefTable();
1683 m_bMainXRefLoadTried = TRUE;
1684 if (eRet != CPDF_Parser::SUCCESS)
1685 return DataError;
1686
1687 if (!PreparePageItem())
1688 return DataNotAvailable;
1689
1690 m_bMainXRefLoadedOK = TRUE;
1691 m_bLinearedDataOK = TRUE;
1692 }
1693
1694 return m_bLinearedDataOK ? DataAvailable : DataNotAvailable;
1695 }
1696
1697 FX_BOOL CPDF_DataAvail::CheckPageAnnots(int32_t iPage,
1698 IFX_DownloadHints* pHints) {
1699 if (!m_objs_array.GetSize()) {
1700 m_objs_array.RemoveAll();
1701 m_ObjectSet.clear();
1702
1703 CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iPage);
1704 if (!pPageDict)
1705 return TRUE;
1706
1707 CPDF_Object* pAnnots = pPageDict->GetElement("Annots");
1708 if (!pAnnots)
1709 return TRUE;
1710
1711 CFX_ArrayTemplate<CPDF_Object*> obj_array;
1712 obj_array.Add(pAnnots);
1713
1714 FX_BOOL bRet = IsObjectsAvail(obj_array, FALSE, pHints, m_objs_array);
1715 if (bRet)
1716 m_objs_array.RemoveAll();
1717
1718 return bRet;
1719 }
1720
1721 CFX_ArrayTemplate<CPDF_Object*> new_objs_array;
1722 FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
1723 m_objs_array.RemoveAll();
1724 if (!bRet)
1725 m_objs_array.Append(new_objs_array);
1726
1727 return bRet;
1728 }
1729
1730 IPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedFirstPage(
1731 int32_t iPage,
1732 IFX_DownloadHints* pHints) {
1733 if (!m_bAnnotsLoad) {
1734 if (!CheckPageAnnots(iPage, pHints))
1735 return DataNotAvailable;
1736 m_bAnnotsLoad = TRUE;
1737 }
1738
1739 DocAvailStatus nRet = CheckLinearizedData(pHints);
1740 if (nRet == DataAvailable)
1741 m_bPageLoadedOK = FALSE;
1742 return nRet;
1743 }
1744
1745 FX_BOOL CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary* pDict) {
1746 CFX_AutoRestorer<int> restorer(&s_CurrentDataAvailRecursionDepth);
1747 if (++s_CurrentDataAvailRecursionDepth > kMaxDataAvailRecursionDepth)
1748 return FALSE;
1749
1750 CPDF_Object* pParent = pDict->GetElement("Parent");
1751 if (!pParent)
1752 return FALSE;
1753
1754 CPDF_Dictionary* pParentDict = pParent->GetDict();
1755 if (!pParentDict)
1756 return FALSE;
1757
1758 CPDF_Object* pRet = pParentDict->GetElement("Resources");
1759 if (pRet) {
1760 m_pPageResource = pRet;
1761 return TRUE;
1762 }
1763
1764 return HaveResourceAncestor(pParentDict);
1765 }
1766
1767 IPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsPageAvail(
1768 int32_t iPage,
1769 IFX_DownloadHints* pHints) {
1770 if (!m_pDocument)
1771 return DataError;
1772
1773 if (IsFirstCheck(iPage)) {
1774 m_bCurPageDictLoadOK = FALSE;
1775 m_bPageLoadedOK = FALSE;
1776 m_bAnnotsLoad = FALSE;
1777 m_bNeedDownLoadResource = FALSE;
1778 m_objs_array.RemoveAll();
1779 m_ObjectSet.clear();
1780 }
1781
1782 if (pdfium::ContainsKey(m_pagesLoadState, iPage))
1783 return DataAvailable;
1784
1785 if (m_bLinearized) {
1786 if ((FX_DWORD)iPage == m_dwFirstPageNo) {
1787 DocAvailStatus nRet = CheckLinearizedFirstPage(iPage, pHints);
1788 if (nRet == DataAvailable)
1789 m_pagesLoadState.insert(iPage);
1790 return nRet;
1791 }
1792
1793 DocAvailStatus nResult = CheckLinearizedData(pHints);
1794 if (nResult != DataAvailable)
1795 return nResult;
1796
1797 if (m_pHintTables) {
1798 nResult = m_pHintTables->CheckPage(iPage, pHints);
1799 if (nResult != DataAvailable)
1800 return nResult;
1801 m_pagesLoadState.insert(iPage);
1802 return DataAvailable;
1803 }
1804
1805 if (m_bMainXRefLoadedOK) {
1806 if (m_bTotalLoadPageTree) {
1807 if (!LoadPages(pHints))
1808 return DataNotAvailable;
1809 } else {
1810 if (!m_bCurPageDictLoadOK && !CheckPage(iPage, pHints))
1811 return DataNotAvailable;
1812 }
1813 } else {
1814 if (!LoadAllFile(pHints))
1815 return DataNotAvailable;
1816 m_pDocument->GetParser()->RebuildCrossRef();
1817 ResetFirstCheck(iPage);
1818 return DataAvailable;
1819 }
1820 } else {
1821 if (!m_bTotalLoadPageTree && !m_bCurPageDictLoadOK &&
1822 !CheckPage(iPage, pHints)) {
1823 return DataNotAvailable;
1824 }
1825 }
1826
1827 if (m_bHaveAcroForm && !m_bAcroFormLoad) {
1828 if (!CheckAcroFormSubObject(pHints))
1829 return DataNotAvailable;
1830 m_bAcroFormLoad = TRUE;
1831 }
1832
1833 if (!m_bPageLoadedOK) {
1834 if (!m_objs_array.GetSize()) {
1835 m_objs_array.RemoveAll();
1836 m_ObjectSet.clear();
1837
1838 m_pPageDict = m_pDocument->GetPage(iPage);
1839 if (!m_pPageDict) {
1840 ResetFirstCheck(iPage);
1841 return DataAvailable;
1842 }
1843
1844 CFX_ArrayTemplate<CPDF_Object*> obj_array;
1845 obj_array.Add(m_pPageDict);
1846 FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array);
1847 if (!bRet)
1848 return DataNotAvailable;
1849
1850 m_objs_array.RemoveAll();
1851 } else {
1852 CFX_ArrayTemplate<CPDF_Object*> new_objs_array;
1853 FX_BOOL bRet =
1854 IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
1855
1856 m_objs_array.RemoveAll();
1857 if (!bRet) {
1858 m_objs_array.Append(new_objs_array);
1859 return DataNotAvailable;
1860 }
1861 }
1862 m_bPageLoadedOK = TRUE;
1863 }
1864
1865 if (!m_bAnnotsLoad) {
1866 if (!CheckPageAnnots(iPage, pHints))
1867 return DataNotAvailable;
1868 m_bAnnotsLoad = TRUE;
1869 }
1870
1871 if (m_pPageDict && !m_bNeedDownLoadResource) {
1872 m_pPageResource = m_pPageDict->GetElement("Resources");
1873 if (!m_pPageResource)
1874 m_bNeedDownLoadResource = HaveResourceAncestor(m_pPageDict);
1875 else
1876 m_bNeedDownLoadResource = TRUE;
1877 }
1878
1879 if (m_bNeedDownLoadResource) {
1880 FX_BOOL bRet = CheckResources(pHints);
1881 if (!bRet)
1882 return DataNotAvailable;
1883 m_bNeedDownLoadResource = FALSE;
1884 }
1885
1886 m_bPageLoadedOK = FALSE;
1887 m_bAnnotsLoad = FALSE;
1888 m_bCurPageDictLoadOK = FALSE;
1889
1890 ResetFirstCheck(iPage);
1891 m_pagesLoadState.insert(iPage);
1892 return DataAvailable;
1893 }
1894
1895 FX_BOOL CPDF_DataAvail::CheckResources(IFX_DownloadHints* pHints) {
1896 if (!m_objs_array.GetSize()) {
1897 m_objs_array.RemoveAll();
1898 CFX_ArrayTemplate<CPDF_Object*> obj_array;
1899 obj_array.Add(m_pPageResource);
1900
1901 FX_BOOL bRet = IsObjectsAvail(obj_array, TRUE, pHints, m_objs_array);
1902 if (bRet)
1903 m_objs_array.RemoveAll();
1904 return bRet;
1905 }
1906
1907 CFX_ArrayTemplate<CPDF_Object*> new_objs_array;
1908 FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
1909 m_objs_array.RemoveAll();
1910 if (!bRet)
1911 m_objs_array.Append(new_objs_array);
1912 return bRet;
1913 }
1914
1915 void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE* pPos,
1916 FX_DWORD* pSize) {
1917 if (pPos)
1918 *pPos = m_dwLastXRefOffset;
1919 if (pSize)
1920 *pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset);
1921 }
1922
1923 int CPDF_DataAvail::GetPageCount() const {
1924 if (m_pLinearized) {
1925 CPDF_Dictionary* pDict = m_pLinearized->GetDict();
1926 CPDF_Object* pObj = pDict ? pDict->GetElementValue("N") : nullptr;
1927 return pObj ? pObj->GetInteger() : 0;
1928 }
1929 return m_pDocument ? m_pDocument->GetPageCount() : 0;
1930 }
1931
1932 CPDF_Dictionary* CPDF_DataAvail::GetPage(int index) {
1933 if (!m_pDocument || index < 0 || index >= GetPageCount())
1934 return nullptr;
1935
1936 if (m_pLinearized) {
1937 CPDF_Dictionary* pDict = m_pLinearized->GetDict();
1938 CPDF_Object* pObj = pDict ? pDict->GetElementValue("P") : nullptr;
1939
1940 int pageNum = pObj ? pObj->GetInteger() : 0;
1941 if (m_pHintTables && index != pageNum) {
1942 FX_FILESIZE szPageStartPos = 0;
1943 FX_FILESIZE szPageLength = 0;
1944 FX_DWORD dwObjNum = 0;
1945 FX_BOOL bPagePosGot = m_pHintTables->GetPagePos(index, szPageStartPos,
1946 szPageLength, dwObjNum);
1947 if (!bPagePosGot)
1948 return nullptr;
1949
1950 m_syntaxParser.InitParser(m_pFileRead, (FX_DWORD)szPageStartPos);
1951 CPDF_Object* pPageDict = ParseIndirectObjectAt(0, dwObjNum, m_pDocument);
1952 if (!pPageDict)
1953 return nullptr;
1954
1955 if (!m_pDocument->InsertIndirectObject(dwObjNum, pPageDict))
1956 return nullptr;
1957 return pPageDict->GetDict();
1958 }
1959 }
1960 return m_pDocument->GetPage(index);
1961 }
1962
1963 IPDF_DataAvail::DocFormStatus CPDF_DataAvail::IsFormAvail(
1964 IFX_DownloadHints* pHints) {
1965 if (!m_pDocument)
1966 return FormAvailable;
1967
1968 if (!m_bLinearizedFormParamLoad) {
1969 CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
1970 if (!pRoot)
1971 return FormAvailable;
1972
1973 CPDF_Object* pAcroForm = pRoot->GetElement("AcroForm");
1974 if (!pAcroForm)
1975 return FormNotExist;
1976
1977 DocAvailStatus nDocStatus = CheckLinearizedData(pHints);
1978 if (nDocStatus == DataError)
1979 return FormError;
1980 if (nDocStatus == DataNotAvailable)
1981 return FormNotAvailable;
1982
1983 if (!m_objs_array.GetSize())
1984 m_objs_array.Add(pAcroForm->GetDict());
1985 m_bLinearizedFormParamLoad = TRUE;
1986 }
1987
1988 CFX_ArrayTemplate<CPDF_Object*> new_objs_array;
1989 FX_BOOL bRet = IsObjectsAvail(m_objs_array, FALSE, pHints, new_objs_array);
1990 m_objs_array.RemoveAll();
1991 if (!bRet) {
1992 m_objs_array.Append(new_objs_array);
1993 return FormNotAvailable;
1994 }
1995 return FormAvailable;
1996 }
1997
1998 CPDF_PageNode::CPDF_PageNode() : m_type(PDF_PAGENODE_UNKNOWN) {}
1999
2000 CPDF_PageNode::~CPDF_PageNode() {
2001 for (int32_t i = 0; i < m_childNode.GetSize(); ++i)
2002 delete m_childNode[i];
2003 m_childNode.RemoveAll();
2004 }
2005
2006 CPDF_HintTables::~CPDF_HintTables() {
2007 m_dwDeltaNObjsArray.RemoveAll();
2008 m_dwNSharedObjsArray.RemoveAll();
2009 m_dwSharedObjNumArray.RemoveAll();
2010 m_dwIdentifierArray.RemoveAll();
2011 }
2012
2013 FX_DWORD CPDF_HintTables::GetItemLength(
2014 int index,
2015 const std::vector<FX_FILESIZE>& szArray) {
2016 if (index < 0 || szArray.size() < 2 ||
2017 static_cast<size_t>(index) > szArray.size() - 2 ||
2018 szArray[index] > szArray[index + 1]) {
2019 return 0;
2020 }
2021 return szArray[index + 1] - szArray[index];
2022 }
2023
2024 FX_BOOL CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
2025 if (!hStream || hStream->IsEOF())
2026 return FALSE;
2027
2028 int nStreamOffset = ReadPrimaryHintStreamOffset();
2029 int nStreamLen = ReadPrimaryHintStreamLength();
2030 if (nStreamOffset < 0 || nStreamLen < 1)
2031 return FALSE;
2032
2033 const FX_DWORD kHeaderSize = 288;
2034 if (hStream->BitsRemaining() < kHeaderSize)
2035 return FALSE;
2036
2037 // Item 1: The least number of objects in a page.
2038 FX_DWORD dwObjLeastNum = hStream->GetBits(32);
2039
2040 // Item 2: The location of the first page's page object.
2041 FX_DWORD dwFirstObjLoc = hStream->GetBits(32);
2042 if (dwFirstObjLoc > nStreamOffset) {
2043 FX_SAFE_DWORD safeLoc = pdfium::base::checked_cast<FX_DWORD>(nStreamLen);
2044 safeLoc += dwFirstObjLoc;
2045 if (!safeLoc.IsValid())
2046 return FALSE;
2047 m_szFirstPageObjOffset =
2048 pdfium::base::checked_cast<FX_FILESIZE>(safeLoc.ValueOrDie());
2049 } else {
2050 m_szFirstPageObjOffset =
2051 pdfium::base::checked_cast<FX_FILESIZE>(dwFirstObjLoc);
2052 }
2053
2054 // Item 3: The number of bits needed to represent the difference
2055 // between the greatest and least number of objects in a page.
2056 FX_DWORD dwDeltaObjectsBits = hStream->GetBits(16);
2057
2058 // Item 4: The least length of a page in bytes.
2059 FX_DWORD dwPageLeastLen = hStream->GetBits(32);
2060
2061 // Item 5: The number of bits needed to represent the difference
2062 // between the greatest and least length of a page, in bytes.
2063 FX_DWORD dwDeltaPageLenBits = hStream->GetBits(16);
2064
2065 // Skip Item 6, 7, 8, 9 total 96 bits.
2066 hStream->SkipBits(96);
2067
2068 // Item 10: The number of bits needed to represent the greatest
2069 // number of shared object references.
2070 FX_DWORD dwSharedObjBits = hStream->GetBits(16);
2071
2072 // Item 11: The number of bits needed to represent the numerically
2073 // greatest shared object identifier used by the pages.
2074 FX_DWORD dwSharedIdBits = hStream->GetBits(16);
2075
2076 // Item 12: The number of bits needed to represent the numerator of
2077 // the fractional position for each shared object reference. For each
2078 // shared object referenced from a page, there is an indication of
2079 // where in the page's content stream the object is first referenced.
2080 FX_DWORD dwSharedNumeratorBits = hStream->GetBits(16);
2081
2082 // Item 13: Skip Item 13 which has 16 bits.
2083 hStream->SkipBits(16);
2084
2085 CPDF_Object* pPageNum = m_pLinearizedDict->GetElementValue("N");
2086 int nPages = pPageNum ? pPageNum->GetInteger() : 0;
2087 if (nPages < 1)
2088 return FALSE;
2089
2090 FX_SAFE_DWORD required_bits = dwDeltaObjectsBits;
2091 required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
2092 if (!CanReadFromBitStream(hStream, required_bits))
2093 return FALSE;
2094
2095 for (int i = 0; i < nPages; ++i) {
2096 FX_SAFE_DWORD safeDeltaObj = hStream->GetBits(dwDeltaObjectsBits);
2097 safeDeltaObj += dwObjLeastNum;
2098 if (!safeDeltaObj.IsValid())
2099 return FALSE;
2100 m_dwDeltaNObjsArray.Add(safeDeltaObj.ValueOrDie());
2101 }
2102 hStream->ByteAlign();
2103
2104 required_bits = dwDeltaPageLenBits;
2105 required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
2106 if (!CanReadFromBitStream(hStream, required_bits))
2107 return FALSE;
2108
2109 CFX_DWordArray dwPageLenArray;
2110 for (int i = 0; i < nPages; ++i) {
2111 FX_SAFE_DWORD safePageLen = hStream->GetBits(dwDeltaPageLenBits);
2112 safePageLen += dwPageLeastLen;
2113 if (!safePageLen.IsValid())
2114 return FALSE;
2115 dwPageLenArray.Add(safePageLen.ValueOrDie());
2116 }
2117
2118 CPDF_Object* pOffsetE = m_pLinearizedDict->GetElementValue("E");
2119 int nOffsetE = pOffsetE ? pOffsetE->GetInteger() : -1;
2120 if (nOffsetE < 0)
2121 return FALSE;
2122
2123 CPDF_Object* pFirstPageNum = m_pLinearizedDict->GetElementValue("P");
2124 int nFirstPageNum = pFirstPageNum ? pFirstPageNum->GetInteger() : 0;
2125 for (int i = 0; i < nPages; ++i) {
2126 if (i == nFirstPageNum) {
2127 m_szPageOffsetArray.push_back(m_szFirstPageObjOffset);
2128 } else if (i == nFirstPageNum + 1) {
2129 if (i == 1) {
2130 m_szPageOffsetArray.push_back(nOffsetE);
2131 } else {
2132 m_szPageOffsetArray.push_back(m_szPageOffsetArray[i - 2] +
2133 dwPageLenArray[i - 2]);
2134 }
2135 } else {
2136 if (i == 0) {
2137 m_szPageOffsetArray.push_back(nOffsetE);
2138 } else {
2139 m_szPageOffsetArray.push_back(m_szPageOffsetArray[i - 1] +
2140 dwPageLenArray[i - 1]);
2141 }
2142 }
2143 }
2144
2145 if (nPages > 0) {
2146 m_szPageOffsetArray.push_back(m_szPageOffsetArray[nPages - 1] +
2147 dwPageLenArray[nPages - 1]);
2148 }
2149 hStream->ByteAlign();
2150
2151 // Number of shared objects.
2152 required_bits = dwSharedObjBits;
2153 required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
2154 if (!CanReadFromBitStream(hStream, required_bits))
2155 return FALSE;
2156
2157 for (int i = 0; i < nPages; i++)
2158 m_dwNSharedObjsArray.Add(hStream->GetBits(dwSharedObjBits));
2159 hStream->ByteAlign();
2160
2161 // Array of identifiers, size = nshared_objects.
2162 for (int i = 0; i < nPages; i++) {
2163 required_bits = dwSharedIdBits;
2164 required_bits *= m_dwNSharedObjsArray[i];
2165 if (!CanReadFromBitStream(hStream, required_bits))
2166 return FALSE;
2167
2168 for (int j = 0; j < m_dwNSharedObjsArray[i]; j++)
2169 m_dwIdentifierArray.Add(hStream->GetBits(dwSharedIdBits));
2170 }
2171 hStream->ByteAlign();
2172
2173 for (int i = 0; i < nPages; i++) {
2174 FX_SAFE_DWORD safeSize = m_dwNSharedObjsArray[i];
2175 safeSize *= dwSharedNumeratorBits;
2176 if (!CanReadFromBitStream(hStream, safeSize))
2177 return FALSE;
2178
2179 hStream->SkipBits(safeSize.ValueOrDie());
2180 }
2181 hStream->ByteAlign();
2182
2183 FX_SAFE_DWORD safeTotalPageLen = pdfium::base::checked_cast<FX_DWORD>(nPages);
2184 safeTotalPageLen *= dwDeltaPageLenBits;
2185 if (!CanReadFromBitStream(hStream, safeTotalPageLen))
2186 return FALSE;
2187
2188 hStream->SkipBits(safeTotalPageLen.ValueOrDie());
2189 hStream->ByteAlign();
2190 return TRUE;
2191 }
2192
2193 FX_BOOL CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream,
2194 FX_DWORD offset) {
2195 if (!hStream || hStream->IsEOF())
2196 return FALSE;
2197
2198 int nStreamOffset = ReadPrimaryHintStreamOffset();
2199 int nStreamLen = ReadPrimaryHintStreamLength();
2200 if (nStreamOffset < 0 || nStreamLen < 1)
2201 return FALSE;
2202
2203 FX_SAFE_DWORD bit_offset = offset;
2204 bit_offset *= 8;
2205 if (!bit_offset.IsValid() || hStream->GetPos() > bit_offset.ValueOrDie())
2206 return FALSE;
2207 hStream->SkipBits(bit_offset.ValueOrDie() - hStream->GetPos());
2208
2209 const FX_DWORD kHeaderSize = 192;
2210 if (hStream->BitsRemaining() < kHeaderSize)
2211 return FALSE;
2212
2213 // Item 1: The object number of the first object in the shared objects
2214 // section.
2215 FX_DWORD dwFirstSharedObjNum = hStream->GetBits(32);
2216
2217 // Item 2: The location of the first object in the shared objects section.
2218 FX_DWORD dwFirstSharedObjLoc = hStream->GetBits(32);
2219 if (dwFirstSharedObjLoc > nStreamOffset)
2220 dwFirstSharedObjLoc += nStreamLen;
2221
2222 // Item 3: The number of shared object entries for the first page.
2223 m_nFirstPageSharedObjs = hStream->GetBits(32);
2224
2225 // Item 4: The number of shared object entries for the shared objects
2226 // section, including the number of shared object entries for the first page.
2227 FX_DWORD dwSharedObjTotal = hStream->GetBits(32);
2228
2229 // Item 5: The number of bits needed to represent the greatest number of
2230 // objects in a shared object group. Skipped.
2231 hStream->SkipBits(16);
2232
2233 // Item 6: The least length of a shared object group in bytes.
2234 FX_DWORD dwGroupLeastLen = hStream->GetBits(32);
2235
2236 // Item 7: The number of bits needed to represent the difference between the
2237 // greatest and least length of a shared object group, in bytes.
2238 FX_DWORD dwDeltaGroupLen = hStream->GetBits(16);
2239 CPDF_Object* pFirstPageObj = m_pLinearizedDict->GetElementValue("O");
2240 int nFirstPageObjNum = pFirstPageObj ? pFirstPageObj->GetInteger() : -1;
2241 if (nFirstPageObjNum < 0)
2242 return FALSE;
2243
2244 FX_DWORD dwPrevObjLen = 0;
2245 FX_DWORD dwCurObjLen = 0;
2246 FX_SAFE_DWORD required_bits = dwSharedObjTotal;
2247 required_bits *= dwDeltaGroupLen;
2248 if (!CanReadFromBitStream(hStream, required_bits))
2249 return FALSE;
2250
2251 for (int i = 0; i < dwSharedObjTotal; ++i) {
2252 dwPrevObjLen = dwCurObjLen;
2253 FX_SAFE_DWORD safeObjLen = hStream->GetBits(dwDeltaGroupLen);
2254 safeObjLen += dwGroupLeastLen;
2255 if (!safeObjLen.IsValid())
2256 return FALSE;
2257
2258 dwCurObjLen = safeObjLen.ValueOrDie();
2259 if (i < m_nFirstPageSharedObjs) {
2260 m_dwSharedObjNumArray.Add(nFirstPageObjNum + i);
2261 if (i == 0)
2262 m_szSharedObjOffsetArray.push_back(m_szFirstPageObjOffset);
2263 } else {
2264 FX_SAFE_DWORD safeObjNum = dwFirstSharedObjNum;
2265 safeObjNum += i - m_nFirstPageSharedObjs;
2266 if (!safeObjNum.IsValid())
2267 return FALSE;
2268
2269 m_dwSharedObjNumArray.Add(safeObjNum.ValueOrDie());
2270 if (i == m_nFirstPageSharedObjs) {
2271 m_szSharedObjOffsetArray.push_back(
2272 pdfium::base::checked_cast<int32_t>(dwFirstSharedObjLoc));
2273 }
2274 }
2275
2276 if (i != 0 && i != m_nFirstPageSharedObjs) {
2277 FX_SAFE_INT32 safeLoc = pdfium::base::checked_cast<int32_t>(dwPrevObjLen);
2278 safeLoc += m_szSharedObjOffsetArray[i - 1];
2279 if (!safeLoc.IsValid())
2280 return FALSE;
2281
2282 m_szSharedObjOffsetArray.push_back(safeLoc.ValueOrDie());
2283 }
2284 }
2285
2286 if (dwSharedObjTotal > 0) {
2287 FX_SAFE_INT32 safeLoc = pdfium::base::checked_cast<int32_t>(dwCurObjLen);
2288 safeLoc += m_szSharedObjOffsetArray[dwSharedObjTotal - 1];
2289 if (!safeLoc.IsValid())
2290 return FALSE;
2291
2292 m_szSharedObjOffsetArray.push_back(safeLoc.ValueOrDie());
2293 }
2294
2295 hStream->ByteAlign();
2296 if (hStream->BitsRemaining() < dwSharedObjTotal)
2297 return FALSE;
2298
2299 hStream->SkipBits(dwSharedObjTotal);
2300 hStream->ByteAlign();
2301 return TRUE;
2302 }
2303
2304 FX_BOOL CPDF_HintTables::GetPagePos(int index,
2305 FX_FILESIZE& szPageStartPos,
2306 FX_FILESIZE& szPageLength,
2307 FX_DWORD& dwObjNum) {
2308 if (!m_pLinearizedDict)
2309 return FALSE;
2310
2311 szPageStartPos = m_szPageOffsetArray[index];
2312 szPageLength = GetItemLength(index, m_szPageOffsetArray);
2313
2314 CPDF_Object* pFirstPageNum = m_pLinearizedDict->GetElementValue("P");
2315 int nFirstPageNum = pFirstPageNum ? pFirstPageNum->GetInteger() : 0;
2316
2317 CPDF_Object* pFirstPageObjNum = m_pLinearizedDict->GetElementValue("O");
2318 if (!pFirstPageObjNum)
2319 return FALSE;
2320
2321 int nFirstPageObjNum = pFirstPageObjNum->GetInteger();
2322 if (index == nFirstPageNum) {
2323 dwObjNum = nFirstPageObjNum;
2324 return TRUE;
2325 }
2326
2327 // The object number of remaining pages starts from 1.
2328 dwObjNum = 1;
2329 for (int i = 0; i < index; ++i) {
2330 if (i == nFirstPageNum)
2331 continue;
2332 dwObjNum += m_dwDeltaNObjsArray[i];
2333 }
2334 return TRUE;
2335 }
2336
2337 IPDF_DataAvail::DocAvailStatus CPDF_HintTables::CheckPage(
2338 int index,
2339 IFX_DownloadHints* pHints) {
2340 if (!m_pLinearizedDict || !pHints)
2341 return IPDF_DataAvail::DataError;
2342
2343 CPDF_Object* pFirstAvailPage = m_pLinearizedDict->GetElementValue("P");
2344 int nFirstAvailPage = pFirstAvailPage ? pFirstAvailPage->GetInteger() : 0;
2345 if (index == nFirstAvailPage)
2346 return IPDF_DataAvail::DataAvailable;
2347
2348 FX_DWORD dwLength = GetItemLength(index, m_szPageOffsetArray);
2349 // If two pages have the same offset, it should be treated as an error.
2350 if (!dwLength)
2351 return IPDF_DataAvail::DataError;
2352
2353 if (!m_pDataAvail->IsDataAvail(m_szPageOffsetArray[index], dwLength, pHints))
2354 return IPDF_DataAvail::DataNotAvailable;
2355
2356 // Download data of shared objects in the page.
2357 FX_DWORD offset = 0;
2358 for (int i = 0; i < index; ++i)
2359 offset += m_dwNSharedObjsArray[i];
2360
2361 CPDF_Object* pFirstPageObj = m_pLinearizedDict->GetElementValue("O");
2362 int nFirstPageObjNum = pFirstPageObj ? pFirstPageObj->GetInteger() : -1;
2363 if (nFirstPageObjNum < 0)
2364 return IPDF_DataAvail::DataError;
2365
2366 FX_DWORD dwIndex = 0;
2367 FX_DWORD dwObjNum = 0;
2368 for (int j = 0; j < m_dwNSharedObjsArray[index]; ++j) {
2369 dwIndex = m_dwIdentifierArray[offset + j];
2370 if (dwIndex >= m_dwSharedObjNumArray.GetSize())
2371 return IPDF_DataAvail::DataNotAvailable;
2372
2373 dwObjNum = m_dwSharedObjNumArray[dwIndex];
2374 if (dwObjNum >= nFirstPageObjNum &&
2375 dwObjNum < nFirstPageObjNum + m_nFirstPageSharedObjs) {
2376 continue;
2377 }
2378
2379 dwLength = GetItemLength(dwIndex, m_szSharedObjOffsetArray);
2380 // If two objects have the same offset, it should be treated as an error.
2381 if (!dwLength)
2382 return IPDF_DataAvail::DataError;
2383
2384 if (!m_pDataAvail->IsDataAvail(m_szSharedObjOffsetArray[dwIndex], dwLength,
2385 pHints)) {
2386 return IPDF_DataAvail::DataNotAvailable;
2387 }
2388 }
2389 return IPDF_DataAvail::DataAvailable;
2390 }
2391
2392 FX_BOOL CPDF_HintTables::LoadHintStream(CPDF_Stream* pHintStream) {
2393 if (!pHintStream || !m_pLinearizedDict)
2394 return FALSE;
2395
2396 CPDF_Dictionary* pDict = pHintStream->GetDict();
2397 CPDF_Object* pOffset = pDict ? pDict->GetElement("S") : nullptr;
2398 if (!pOffset || !pOffset->IsNumber())
2399 return FALSE;
2400
2401 int shared_hint_table_offset = pOffset->GetInteger();
2402 CPDF_StreamAcc acc;
2403 acc.LoadAllData(pHintStream);
2404
2405 FX_DWORD size = acc.GetSize();
2406 // The header section of page offset hint table is 36 bytes.
2407 // The header section of shared object hint table is 24 bytes.
2408 // Hint table has at least 60 bytes.
2409 const FX_DWORD MIN_STREAM_LEN = 60;
2410 if (size < MIN_STREAM_LEN || shared_hint_table_offset <= 0 ||
2411 size < shared_hint_table_offset) {
2412 return FALSE;
2413 }
2414
2415 CFX_BitStream bs;
2416 bs.Init(acc.GetData(), size);
2417 return ReadPageHintTable(&bs) &&
2418 ReadSharedObjHintTable(&bs, pdfium::base::checked_cast<FX_DWORD>(
2419 shared_hint_table_offset));
2420 }
2421
2422 int CPDF_HintTables::ReadPrimaryHintStreamOffset() const {
2423 if (!m_pLinearizedDict)
2424 return -1;
2425
2426 CPDF_Array* pRange = m_pLinearizedDict->GetArrayBy("H");
2427 if (!pRange)
2428 return -1;
2429
2430 CPDF_Object* pStreamOffset = pRange->GetElementValue(0);
2431 if (!pStreamOffset)
2432 return -1;
2433
2434 return pStreamOffset->GetInteger();
2435 }
2436
2437 int CPDF_HintTables::ReadPrimaryHintStreamLength() const {
2438 if (!m_pLinearizedDict)
2439 return -1;
2440
2441 CPDF_Array* pRange = m_pLinearizedDict->GetArrayBy("H");
2442 if (!pRange)
2443 return -1;
2444
2445 CPDF_Object* pStreamLen = pRange->GetElementValue(1);
2446 if (!pStreamLen)
2447 return -1;
2448
2449 return pStreamLen->GetInteger();
2450 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698