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