OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "core/include/fpdfapi/fpdf_parser.h" | 7 #include "core/include/fpdfapi/fpdf_parser.h" |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <memory> | 10 #include <memory> |
11 #include <set> | 11 #include <set> |
12 #include <utility> | 12 #include <utility> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "core/include/fpdfapi/fpdf_module.h" | 15 #include "core/include/fpdfapi/fpdf_module.h" |
16 #include "core/include/fpdfapi/fpdf_page.h" | 16 #include "core/include/fpdfapi/fpdf_page.h" |
17 #include "core/include/fxcrt/fx_ext.h" | 17 #include "core/include/fxcrt/fx_ext.h" |
18 #include "core/include/fxcrt/fx_safe_types.h" | 18 #include "core/include/fxcrt/fx_safe_types.h" |
19 #include "core/src/fpdfapi/fpdf_page/pageint.h" | 19 #include "core/src/fpdfapi/fpdf_page/pageint.h" |
| 20 #include "core/src/fpdfapi/fpdf_parser/cpdf_syntax_parser.h" |
20 #include "core/src/fpdfapi/fpdf_parser/parser_int.h" | 21 #include "core/src/fpdfapi/fpdf_parser/parser_int.h" |
21 #include "third_party/base/stl_util.h" | 22 #include "third_party/base/stl_util.h" |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 // A limit on the size of the xref table. Theoretical limits are higher, but | 26 // A limit on the size of the xref table. Theoretical limits are higher, but |
26 // this may be large enough in practice. | 27 // this may be large enough in practice. |
27 const int32_t kMaxXRefSize = 1048576; | 28 const int32_t kMaxXRefSize = 1048576; |
28 | 29 |
29 // A limit on the maximum object number in the xref table. Theoretical limits | 30 // A limit on the maximum object number in the xref table. Theoretical limits |
30 // are higher, but this may be large enough in practice. | 31 // are higher, but this may be large enough in practice. |
31 const FX_DWORD kMaxObjectNumber = 1048576; | 32 const FX_DWORD kMaxObjectNumber = 1048576; |
32 | 33 |
33 struct SearchTagRecord { | |
34 const char* m_pTag; | |
35 FX_DWORD m_Len; | |
36 FX_DWORD m_Offset; | |
37 }; | |
38 | |
39 int32_t GetHeaderOffset(IFX_FileRead* pFile) { | 34 int32_t GetHeaderOffset(IFX_FileRead* pFile) { |
40 // TODO(dsinclair): This is a complicated way of saying %PDF, simplify? | 35 // TODO(dsinclair): This is a complicated way of saying %PDF, simplify? |
41 const FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025); | 36 const FX_DWORD tag = FXDWORD_FROM_LSBFIRST(0x46445025); |
42 | 37 |
43 const size_t kBufSize = 4; | 38 const size_t kBufSize = 4; |
44 uint8_t buf[kBufSize]; | 39 uint8_t buf[kBufSize]; |
45 int32_t offset = 0; | 40 int32_t offset = 0; |
46 while (offset <= 1024) { | 41 while (offset <= 1024) { |
47 if (!pFile->ReadBlock(buf, offset, kBufSize)) | 42 if (!pFile->ReadBlock(buf, offset, kBufSize)) |
48 return -1; | 43 return -1; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } | 86 } |
92 | 87 |
93 CPDF_Parser::CPDF_Parser() | 88 CPDF_Parser::CPDF_Parser() |
94 : m_pDocument(nullptr), | 89 : m_pDocument(nullptr), |
95 m_bOwnFileRead(true), | 90 m_bOwnFileRead(true), |
96 m_FileVersion(0), | 91 m_FileVersion(0), |
97 m_pTrailer(nullptr), | 92 m_pTrailer(nullptr), |
98 m_pEncryptDict(nullptr), | 93 m_pEncryptDict(nullptr), |
99 m_pLinearized(nullptr), | 94 m_pLinearized(nullptr), |
100 m_dwFirstPageNo(0), | 95 m_dwFirstPageNo(0), |
101 m_dwXrefStartObjNum(0) {} | 96 m_dwXrefStartObjNum(0) { |
| 97 m_pSyntax.reset(new CPDF_SyntaxParser); |
| 98 } |
102 | 99 |
103 CPDF_Parser::~CPDF_Parser() { | 100 CPDF_Parser::~CPDF_Parser() { |
104 CloseParser(); | 101 CloseParser(); |
105 } | 102 } |
106 | 103 |
107 FX_DWORD CPDF_Parser::GetLastObjNum() const { | 104 FX_DWORD CPDF_Parser::GetLastObjNum() const { |
108 return m_ObjectInfo.empty() ? 0 : m_ObjectInfo.rbegin()->first; | 105 return m_ObjectInfo.empty() ? 0 : m_ObjectInfo.rbegin()->first; |
109 } | 106 } |
110 | 107 |
111 bool CPDF_Parser::IsValidObjectNumber(FX_DWORD objnum) const { | 108 bool CPDF_Parser::IsValidObjectNumber(FX_DWORD objnum) const { |
(...skipping 19 matching lines...) Expand all Loading... |
131 | 128 |
132 bool CPDF_Parser::IsObjectFreeOrNull(FX_DWORD objnum) const { | 129 bool CPDF_Parser::IsObjectFreeOrNull(FX_DWORD objnum) const { |
133 uint8_t type = GetObjectType(objnum); | 130 uint8_t type = GetObjectType(objnum); |
134 return type == 0 || type == 255; | 131 return type == 0 || type == 255; |
135 } | 132 } |
136 | 133 |
137 void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) { | 134 void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) { |
138 m_pEncryptDict = pDict; | 135 m_pEncryptDict = pDict; |
139 } | 136 } |
140 | 137 |
| 138 CPDF_CryptoHandler* CPDF_Parser::GetCryptoHandler() { |
| 139 return m_pSyntax->m_pCryptoHandler.get(); |
| 140 } |
| 141 |
| 142 IFX_FileRead* CPDF_Parser::GetFileAccess() const { |
| 143 return m_pSyntax->m_pFileAccess; |
| 144 } |
| 145 |
141 void CPDF_Parser::ShrinkObjectMap(FX_DWORD objnum) { | 146 void CPDF_Parser::ShrinkObjectMap(FX_DWORD objnum) { |
142 if (objnum == 0) { | 147 if (objnum == 0) { |
143 m_ObjectInfo.clear(); | 148 m_ObjectInfo.clear(); |
144 return; | 149 return; |
145 } | 150 } |
146 | 151 |
147 auto it = m_ObjectInfo.lower_bound(objnum); | 152 auto it = m_ObjectInfo.lower_bound(objnum); |
148 while (it != m_ObjectInfo.end()) { | 153 while (it != m_ObjectInfo.end()) { |
149 auto saved_it = it++; | 154 auto saved_it = it++; |
150 m_ObjectInfo.erase(saved_it); | 155 m_ObjectInfo.erase(saved_it); |
151 } | 156 } |
152 | 157 |
153 if (!pdfium::ContainsKey(m_ObjectInfo, objnum - 1)) | 158 if (!pdfium::ContainsKey(m_ObjectInfo, objnum - 1)) |
154 m_ObjectInfo[objnum - 1].pos = 0; | 159 m_ObjectInfo[objnum - 1].pos = 0; |
155 } | 160 } |
156 | 161 |
157 void CPDF_Parser::CloseParser() { | 162 void CPDF_Parser::CloseParser() { |
158 m_bVersionUpdated = FALSE; | 163 m_bVersionUpdated = FALSE; |
159 delete m_pDocument; | 164 delete m_pDocument; |
160 m_pDocument = nullptr; | 165 m_pDocument = nullptr; |
161 | 166 |
162 if (m_pTrailer) { | 167 if (m_pTrailer) { |
163 m_pTrailer->Release(); | 168 m_pTrailer->Release(); |
164 m_pTrailer = nullptr; | 169 m_pTrailer = nullptr; |
165 } | 170 } |
166 ReleaseEncryptHandler(); | 171 ReleaseEncryptHandler(); |
167 SetEncryptDictionary(nullptr); | 172 SetEncryptDictionary(nullptr); |
168 | 173 |
169 if (m_bOwnFileRead && m_Syntax.m_pFileAccess) { | 174 if (m_bOwnFileRead && m_pSyntax->m_pFileAccess) { |
170 m_Syntax.m_pFileAccess->Release(); | 175 m_pSyntax->m_pFileAccess->Release(); |
171 m_Syntax.m_pFileAccess = nullptr; | 176 m_pSyntax->m_pFileAccess = nullptr; |
172 } | 177 } |
173 | 178 |
174 m_ObjectStreamMap.clear(); | 179 m_ObjectStreamMap.clear(); |
175 m_ObjCache.clear(); | 180 m_ObjCache.clear(); |
176 m_SortedOffset.clear(); | 181 m_SortedOffset.clear(); |
177 m_ObjectInfo.clear(); | 182 m_ObjectInfo.clear(); |
178 | 183 |
179 int32_t iLen = m_Trailers.GetSize(); | 184 int32_t iLen = m_Trailers.GetSize(); |
180 for (int32_t i = 0; i < iLen; ++i) { | 185 for (int32_t i = 0; i < iLen; ++i) { |
181 if (CPDF_Dictionary* trailer = m_Trailers.GetAt(i)) | 186 if (CPDF_Dictionary* trailer = m_Trailers.GetAt(i)) |
(...skipping 13 matching lines...) Expand all Loading... |
195 m_bXRefStream = FALSE; | 200 m_bXRefStream = FALSE; |
196 m_LastXRefOffset = 0; | 201 m_LastXRefOffset = 0; |
197 m_bOwnFileRead = true; | 202 m_bOwnFileRead = true; |
198 | 203 |
199 int32_t offset = GetHeaderOffset(pFileAccess); | 204 int32_t offset = GetHeaderOffset(pFileAccess); |
200 if (offset == -1) { | 205 if (offset == -1) { |
201 if (pFileAccess) | 206 if (pFileAccess) |
202 pFileAccess->Release(); | 207 pFileAccess->Release(); |
203 return FORMAT_ERROR; | 208 return FORMAT_ERROR; |
204 } | 209 } |
205 m_Syntax.InitParser(pFileAccess, offset); | 210 m_pSyntax->InitParser(pFileAccess, offset); |
206 | 211 |
207 uint8_t ch; | 212 uint8_t ch; |
208 if (!m_Syntax.GetCharAt(5, ch)) | 213 if (!m_pSyntax->GetCharAt(5, ch)) |
209 return FORMAT_ERROR; | 214 return FORMAT_ERROR; |
210 if (std::isdigit(ch)) | 215 if (std::isdigit(ch)) |
211 m_FileVersion = FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)) * 10; | 216 m_FileVersion = FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)) * 10; |
212 | 217 |
213 if (!m_Syntax.GetCharAt(7, ch)) | 218 if (!m_pSyntax->GetCharAt(7, ch)) |
214 return FORMAT_ERROR; | 219 return FORMAT_ERROR; |
215 if (std::isdigit(ch)) | 220 if (std::isdigit(ch)) |
216 m_FileVersion += FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)); | 221 m_FileVersion += FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)); |
217 | 222 |
218 if (m_Syntax.m_FileLen < m_Syntax.m_HeaderOffset + 9) | 223 if (m_pSyntax->m_FileLen < m_pSyntax->m_HeaderOffset + 9) |
219 return FORMAT_ERROR; | 224 return FORMAT_ERROR; |
220 | 225 |
221 m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9); | 226 m_pSyntax->RestorePos(m_pSyntax->m_FileLen - m_pSyntax->m_HeaderOffset - 9); |
222 m_pDocument = new CPDF_Document(this); | 227 m_pDocument = new CPDF_Document(this); |
223 | 228 |
224 FX_BOOL bXRefRebuilt = FALSE; | 229 FX_BOOL bXRefRebuilt = FALSE; |
225 if (m_Syntax.SearchWord("startxref", TRUE, FALSE, 4096)) { | 230 if (m_pSyntax->SearchWord("startxref", TRUE, FALSE, 4096)) { |
226 m_SortedOffset.insert(m_Syntax.SavePos()); | 231 m_SortedOffset.insert(m_pSyntax->SavePos()); |
227 m_Syntax.GetKeyword(); | 232 m_pSyntax->GetKeyword(); |
228 | 233 |
229 bool bNumber; | 234 bool bNumber; |
230 CFX_ByteString xrefpos_str = m_Syntax.GetNextWord(&bNumber); | 235 CFX_ByteString xrefpos_str = m_pSyntax->GetNextWord(&bNumber); |
231 if (!bNumber) | 236 if (!bNumber) |
232 return FORMAT_ERROR; | 237 return FORMAT_ERROR; |
233 | 238 |
234 m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str); | 239 m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str); |
235 if (!LoadAllCrossRefV4(m_LastXRefOffset) && | 240 if (!LoadAllCrossRefV4(m_LastXRefOffset) && |
236 !LoadAllCrossRefV5(m_LastXRefOffset)) { | 241 !LoadAllCrossRefV5(m_LastXRefOffset)) { |
237 if (!RebuildCrossRef()) | 242 if (!RebuildCrossRef()) |
238 return FORMAT_ERROR; | 243 return FORMAT_ERROR; |
239 | 244 |
240 bXRefRebuilt = TRUE; | 245 bXRefRebuilt = TRUE; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 return FORMAT_ERROR; | 278 return FORMAT_ERROR; |
274 | 279 |
275 eRet = SetEncryptHandler(); | 280 eRet = SetEncryptHandler(); |
276 if (eRet != SUCCESS) | 281 if (eRet != SUCCESS) |
277 return eRet; | 282 return eRet; |
278 } | 283 } |
279 if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) { | 284 if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) { |
280 CPDF_Reference* pMetadata = | 285 CPDF_Reference* pMetadata = |
281 ToReference(m_pDocument->GetRoot()->GetElement("Metadata")); | 286 ToReference(m_pDocument->GetRoot()->GetElement("Metadata")); |
282 if (pMetadata) | 287 if (pMetadata) |
283 m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum(); | 288 m_pSyntax->m_MetadataObjnum = pMetadata->GetRefObjNum(); |
284 } | 289 } |
285 return SUCCESS; | 290 return SUCCESS; |
286 } | 291 } |
287 CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { | 292 CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { |
288 ReleaseEncryptHandler(); | 293 ReleaseEncryptHandler(); |
289 SetEncryptDictionary(nullptr); | 294 SetEncryptDictionary(nullptr); |
290 | 295 |
291 if (!m_pTrailer) | 296 if (!m_pTrailer) |
292 return FORMAT_ERROR; | 297 return FORMAT_ERROR; |
293 | 298 |
(...skipping 20 matching lines...) Expand all Loading... |
314 return HANDLER_ERROR; | 319 return HANDLER_ERROR; |
315 | 320 |
316 if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) | 321 if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) |
317 return err; | 322 return err; |
318 | 323 |
319 m_pSecurityHandler = std::move(pSecurityHandler); | 324 m_pSecurityHandler = std::move(pSecurityHandler); |
320 std::unique_ptr<CPDF_CryptoHandler> pCryptoHandler( | 325 std::unique_ptr<CPDF_CryptoHandler> pCryptoHandler( |
321 m_pSecurityHandler->CreateCryptoHandler()); | 326 m_pSecurityHandler->CreateCryptoHandler()); |
322 if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler.get())) | 327 if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler.get())) |
323 return HANDLER_ERROR; | 328 return HANDLER_ERROR; |
324 m_Syntax.SetEncrypt(std::move(pCryptoHandler)); | 329 m_pSyntax->SetEncrypt(std::move(pCryptoHandler)); |
325 } | 330 } |
326 return SUCCESS; | 331 return SUCCESS; |
327 } | 332 } |
328 | 333 |
329 void CPDF_Parser::ReleaseEncryptHandler() { | 334 void CPDF_Parser::ReleaseEncryptHandler() { |
330 m_Syntax.m_pCryptoHandler.reset(); | 335 m_pSyntax->m_pCryptoHandler.reset(); |
331 m_pSecurityHandler.reset(); | 336 m_pSecurityHandler.reset(); |
332 } | 337 } |
333 | 338 |
334 FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum) const { | 339 FX_FILESIZE CPDF_Parser::GetObjectOffset(FX_DWORD objnum) const { |
335 if (!IsValidObjectNumber(objnum)) | 340 if (!IsValidObjectNumber(objnum)) |
336 return 0; | 341 return 0; |
337 | 342 |
338 if (GetObjectType(objnum) == 1) | 343 if (GetObjectType(objnum) == 1) |
339 return GetObjectPositionOrZero(objnum); | 344 return GetObjectPositionOrZero(objnum); |
340 | 345 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 | 452 |
448 for (size_t i = 1; i < CrossRefList.size(); ++i) { | 453 for (size_t i = 1; i < CrossRefList.size(); ++i) { |
449 if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE)) | 454 if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE)) |
450 return FALSE; | 455 return FALSE; |
451 } | 456 } |
452 return TRUE; | 457 return TRUE; |
453 } | 458 } |
454 | 459 |
455 FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, | 460 FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, |
456 FX_DWORD dwObjCount) { | 461 FX_DWORD dwObjCount) { |
457 FX_FILESIZE dwStartPos = pos - m_Syntax.m_HeaderOffset; | 462 FX_FILESIZE dwStartPos = pos - m_pSyntax->m_HeaderOffset; |
458 | 463 |
459 m_Syntax.RestorePos(dwStartPos); | 464 m_pSyntax->RestorePos(dwStartPos); |
460 m_SortedOffset.insert(pos); | 465 m_SortedOffset.insert(pos); |
461 | 466 |
462 FX_DWORD start_objnum = 0; | 467 FX_DWORD start_objnum = 0; |
463 FX_DWORD count = dwObjCount; | 468 FX_DWORD count = dwObjCount; |
464 FX_FILESIZE SavedPos = m_Syntax.SavePos(); | 469 FX_FILESIZE SavedPos = m_pSyntax->SavePos(); |
465 | 470 |
466 const int32_t recordsize = 20; | 471 const int32_t recordsize = 20; |
467 std::vector<char> buf(1024 * recordsize + 1); | 472 std::vector<char> buf(1024 * recordsize + 1); |
468 buf[1024 * recordsize] = '\0'; | 473 buf[1024 * recordsize] = '\0'; |
469 | 474 |
470 int32_t nBlocks = count / 1024 + 1; | 475 int32_t nBlocks = count / 1024 + 1; |
471 for (int32_t block = 0; block < nBlocks; block++) { | 476 for (int32_t block = 0; block < nBlocks; block++) { |
472 int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; | 477 int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; |
473 FX_DWORD dwReadSize = block_size * recordsize; | 478 FX_DWORD dwReadSize = block_size * recordsize; |
474 if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_Syntax.m_FileLen) | 479 if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_pSyntax->m_FileLen) |
475 return FALSE; | 480 return FALSE; |
476 | 481 |
477 if (!m_Syntax.ReadBlock(reinterpret_cast<uint8_t*>(buf.data()), | 482 if (!m_pSyntax->ReadBlock(reinterpret_cast<uint8_t*>(buf.data()), |
478 dwReadSize)) { | 483 dwReadSize)) { |
479 return FALSE; | 484 return FALSE; |
480 } | 485 } |
481 | 486 |
482 for (int32_t i = 0; i < block_size; i++) { | 487 for (int32_t i = 0; i < block_size; i++) { |
483 FX_DWORD objnum = start_objnum + block * 1024 + i; | 488 FX_DWORD objnum = start_objnum + block * 1024 + i; |
484 char* pEntry = &buf[i * recordsize]; | 489 char* pEntry = &buf[i * recordsize]; |
485 if (pEntry[17] == 'f') { | 490 if (pEntry[17] == 'f') { |
486 m_ObjectInfo[objnum].pos = 0; | 491 m_ObjectInfo[objnum].pos = 0; |
487 m_ObjectInfo[objnum].type = 0; | 492 m_ObjectInfo[objnum].type = 0; |
488 } else { | 493 } else { |
489 int32_t offset = FXSYS_atoi(pEntry); | 494 int32_t offset = FXSYS_atoi(pEntry); |
490 if (offset == 0) { | 495 if (offset == 0) { |
491 for (int32_t c = 0; c < 10; c++) { | 496 for (int32_t c = 0; c < 10; c++) { |
492 if (!std::isdigit(pEntry[c])) | 497 if (!std::isdigit(pEntry[c])) |
493 return FALSE; | 498 return FALSE; |
494 } | 499 } |
495 } | 500 } |
496 | 501 |
497 m_ObjectInfo[objnum].pos = offset; | 502 m_ObjectInfo[objnum].pos = offset; |
498 int32_t version = FXSYS_atoi(pEntry + 11); | 503 int32_t version = FXSYS_atoi(pEntry + 11); |
499 if (version >= 1) | 504 if (version >= 1) |
500 m_bVersionUpdated = TRUE; | 505 m_bVersionUpdated = TRUE; |
501 | 506 |
502 m_ObjectInfo[objnum].gennum = version; | 507 m_ObjectInfo[objnum].gennum = version; |
503 if (m_ObjectInfo[objnum].pos < m_Syntax.m_FileLen) | 508 if (m_ObjectInfo[objnum].pos < m_pSyntax->m_FileLen) |
504 m_SortedOffset.insert(m_ObjectInfo[objnum].pos); | 509 m_SortedOffset.insert(m_ObjectInfo[objnum].pos); |
505 | 510 |
506 m_ObjectInfo[objnum].type = 1; | 511 m_ObjectInfo[objnum].type = 1; |
507 } | 512 } |
508 } | 513 } |
509 } | 514 } |
510 m_Syntax.RestorePos(SavedPos + count * recordsize); | 515 m_pSyntax->RestorePos(SavedPos + count * recordsize); |
511 return TRUE; | 516 return TRUE; |
512 } | 517 } |
513 | 518 |
514 bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, | 519 bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, |
515 FX_FILESIZE streampos, | 520 FX_FILESIZE streampos, |
516 FX_BOOL bSkip) { | 521 FX_BOOL bSkip) { |
517 m_Syntax.RestorePos(pos); | 522 m_pSyntax->RestorePos(pos); |
518 if (m_Syntax.GetKeyword() != "xref") | 523 if (m_pSyntax->GetKeyword() != "xref") |
519 return false; | 524 return false; |
520 | 525 |
521 m_SortedOffset.insert(pos); | 526 m_SortedOffset.insert(pos); |
522 if (streampos) | 527 if (streampos) |
523 m_SortedOffset.insert(streampos); | 528 m_SortedOffset.insert(streampos); |
524 | 529 |
525 while (1) { | 530 while (1) { |
526 FX_FILESIZE SavedPos = m_Syntax.SavePos(); | 531 FX_FILESIZE SavedPos = m_pSyntax->SavePos(); |
527 bool bIsNumber; | 532 bool bIsNumber; |
528 CFX_ByteString word = m_Syntax.GetNextWord(&bIsNumber); | 533 CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); |
529 if (word.IsEmpty()) | 534 if (word.IsEmpty()) |
530 return false; | 535 return false; |
531 | 536 |
532 if (!bIsNumber) { | 537 if (!bIsNumber) { |
533 m_Syntax.RestorePos(SavedPos); | 538 m_pSyntax->RestorePos(SavedPos); |
534 break; | 539 break; |
535 } | 540 } |
536 | 541 |
537 FX_DWORD start_objnum = FXSYS_atoui(word); | 542 FX_DWORD start_objnum = FXSYS_atoui(word); |
538 if (start_objnum >= kMaxObjectNumber) | 543 if (start_objnum >= kMaxObjectNumber) |
539 return false; | 544 return false; |
540 | 545 |
541 FX_DWORD count = m_Syntax.GetDirectNum(); | 546 FX_DWORD count = m_pSyntax->GetDirectNum(); |
542 m_Syntax.ToNextWord(); | 547 m_pSyntax->ToNextWord(); |
543 SavedPos = m_Syntax.SavePos(); | 548 SavedPos = m_pSyntax->SavePos(); |
544 const int32_t recordsize = 20; | 549 const int32_t recordsize = 20; |
545 | 550 |
546 m_dwXrefStartObjNum = start_objnum; | 551 m_dwXrefStartObjNum = start_objnum; |
547 if (!bSkip) { | 552 if (!bSkip) { |
548 std::vector<char> buf(1024 * recordsize + 1); | 553 std::vector<char> buf(1024 * recordsize + 1); |
549 buf[1024 * recordsize] = '\0'; | 554 buf[1024 * recordsize] = '\0'; |
550 | 555 |
551 int32_t nBlocks = count / 1024 + 1; | 556 int32_t nBlocks = count / 1024 + 1; |
552 for (int32_t block = 0; block < nBlocks; block++) { | 557 for (int32_t block = 0; block < nBlocks; block++) { |
553 int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; | 558 int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; |
554 m_Syntax.ReadBlock(reinterpret_cast<uint8_t*>(buf.data()), | 559 m_pSyntax->ReadBlock(reinterpret_cast<uint8_t*>(buf.data()), |
555 block_size * recordsize); | 560 block_size * recordsize); |
556 | 561 |
557 for (int32_t i = 0; i < block_size; i++) { | 562 for (int32_t i = 0; i < block_size; i++) { |
558 FX_DWORD objnum = start_objnum + block * 1024 + i; | 563 FX_DWORD objnum = start_objnum + block * 1024 + i; |
559 char* pEntry = &buf[i * recordsize]; | 564 char* pEntry = &buf[i * recordsize]; |
560 if (pEntry[17] == 'f') { | 565 if (pEntry[17] == 'f') { |
561 m_ObjectInfo[objnum].pos = 0; | 566 m_ObjectInfo[objnum].pos = 0; |
562 m_ObjectInfo[objnum].type = 0; | 567 m_ObjectInfo[objnum].type = 0; |
563 } else { | 568 } else { |
564 FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); | 569 FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); |
565 if (offset == 0) { | 570 if (offset == 0) { |
566 for (int32_t c = 0; c < 10; c++) { | 571 for (int32_t c = 0; c < 10; c++) { |
567 if (!std::isdigit(pEntry[c])) | 572 if (!std::isdigit(pEntry[c])) |
568 return false; | 573 return false; |
569 } | 574 } |
570 } | 575 } |
571 | 576 |
572 m_ObjectInfo[objnum].pos = offset; | 577 m_ObjectInfo[objnum].pos = offset; |
573 int32_t version = FXSYS_atoi(pEntry + 11); | 578 int32_t version = FXSYS_atoi(pEntry + 11); |
574 if (version >= 1) | 579 if (version >= 1) |
575 m_bVersionUpdated = TRUE; | 580 m_bVersionUpdated = TRUE; |
576 | 581 |
577 m_ObjectInfo[objnum].gennum = version; | 582 m_ObjectInfo[objnum].gennum = version; |
578 if (m_ObjectInfo[objnum].pos < m_Syntax.m_FileLen) | 583 if (m_ObjectInfo[objnum].pos < m_pSyntax->m_FileLen) |
579 m_SortedOffset.insert(m_ObjectInfo[objnum].pos); | 584 m_SortedOffset.insert(m_ObjectInfo[objnum].pos); |
580 | 585 |
581 m_ObjectInfo[objnum].type = 1; | 586 m_ObjectInfo[objnum].type = 1; |
582 } | 587 } |
583 } | 588 } |
584 } | 589 } |
585 } | 590 } |
586 m_Syntax.RestorePos(SavedPos + count * recordsize); | 591 m_pSyntax->RestorePos(SavedPos + count * recordsize); |
587 } | 592 } |
588 return !streampos || LoadCrossRefV5(&streampos, FALSE); | 593 return !streampos || LoadCrossRefV5(&streampos, FALSE); |
589 } | 594 } |
590 | 595 |
591 FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { | 596 FX_BOOL CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { |
592 if (!LoadCrossRefV5(&xrefpos, TRUE)) | 597 if (!LoadCrossRefV5(&xrefpos, TRUE)) |
593 return FALSE; | 598 return FALSE; |
594 | 599 |
595 std::set<FX_FILESIZE> seen_xrefpos; | 600 std::set<FX_FILESIZE> seen_xrefpos; |
596 while (xrefpos) { | 601 while (xrefpos) { |
(...skipping 21 matching lines...) Expand all Loading... |
618 ParserState state = ParserState::kDefault; | 623 ParserState state = ParserState::kDefault; |
619 | 624 |
620 int32_t inside_index = 0; | 625 int32_t inside_index = 0; |
621 FX_DWORD objnum = 0; | 626 FX_DWORD objnum = 0; |
622 FX_DWORD gennum = 0; | 627 FX_DWORD gennum = 0; |
623 int32_t depth = 0; | 628 int32_t depth = 0; |
624 | 629 |
625 const FX_DWORD kBufferSize = 4096; | 630 const FX_DWORD kBufferSize = 4096; |
626 std::vector<uint8_t> buffer(kBufferSize); | 631 std::vector<uint8_t> buffer(kBufferSize); |
627 | 632 |
628 FX_FILESIZE pos = m_Syntax.m_HeaderOffset; | 633 FX_FILESIZE pos = m_pSyntax->m_HeaderOffset; |
629 FX_FILESIZE start_pos = 0; | 634 FX_FILESIZE start_pos = 0; |
630 FX_FILESIZE start_pos1 = 0; | 635 FX_FILESIZE start_pos1 = 0; |
631 FX_FILESIZE last_obj = -1; | 636 FX_FILESIZE last_obj = -1; |
632 FX_FILESIZE last_xref = -1; | 637 FX_FILESIZE last_xref = -1; |
633 FX_FILESIZE last_trailer = -1; | 638 FX_FILESIZE last_trailer = -1; |
634 | 639 |
635 while (pos < m_Syntax.m_FileLen) { | 640 while (pos < m_pSyntax->m_FileLen) { |
636 const FX_FILESIZE saved_pos = pos; | 641 const FX_FILESIZE saved_pos = pos; |
637 bool bOverFlow = false; | 642 bool bOverFlow = false; |
638 FX_DWORD size = std::min((FX_DWORD)(m_Syntax.m_FileLen - pos), kBufferSize); | 643 FX_DWORD size = |
639 if (!m_Syntax.m_pFileAccess->ReadBlock(buffer.data(), pos, size)) | 644 std::min((FX_DWORD)(m_pSyntax->m_FileLen - pos), kBufferSize); |
| 645 if (!m_pSyntax->m_pFileAccess->ReadBlock(buffer.data(), pos, size)) |
640 break; | 646 break; |
641 | 647 |
642 for (FX_DWORD i = 0; i < size; i++) { | 648 for (FX_DWORD i = 0; i < size; i++) { |
643 uint8_t byte = buffer[i]; | 649 uint8_t byte = buffer[i]; |
644 switch (state) { | 650 switch (state) { |
645 case ParserState::kDefault: | 651 case ParserState::kDefault: |
646 if (PDFCharIsWhitespace(byte)) { | 652 if (PDFCharIsWhitespace(byte)) { |
647 state = ParserState::kWhitespace; | 653 state = ParserState::kWhitespace; |
648 } else if (std::isdigit(byte)) { | 654 } else if (std::isdigit(byte)) { |
649 --i; | 655 --i; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
753 case 2: | 759 case 2: |
754 if (byte != 'j') { | 760 if (byte != 'j') { |
755 --i; | 761 --i; |
756 state = ParserState::kDefault; | 762 state = ParserState::kDefault; |
757 } else { | 763 } else { |
758 inside_index++; | 764 inside_index++; |
759 } | 765 } |
760 break; | 766 break; |
761 case 3: | 767 case 3: |
762 if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { | 768 if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { |
763 FX_FILESIZE obj_pos = start_pos - m_Syntax.m_HeaderOffset; | 769 FX_FILESIZE obj_pos = start_pos - m_pSyntax->m_HeaderOffset; |
764 m_SortedOffset.insert(obj_pos); | 770 m_SortedOffset.insert(obj_pos); |
765 last_obj = start_pos; | 771 last_obj = start_pos; |
766 FX_FILESIZE obj_end = 0; | 772 FX_FILESIZE obj_end = 0; |
767 CPDF_Object* pObject = ParseIndirectObjectAtByStrict( | 773 CPDF_Object* pObject = ParseIndirectObjectAtByStrict( |
768 m_pDocument, obj_pos, objnum, &obj_end); | 774 m_pDocument, obj_pos, objnum, &obj_end); |
769 if (CPDF_Stream* pStream = ToStream(pObject)) { | 775 if (CPDF_Stream* pStream = ToStream(pObject)) { |
770 if (CPDF_Dictionary* pDict = pStream->GetDict()) { | 776 if (CPDF_Dictionary* pDict = pStream->GetDict()) { |
771 if ((pDict->KeyExist("Type")) && | 777 if ((pDict->KeyExist("Type")) && |
772 (pDict->GetStringBy("Type") == "XRef" && | 778 (pDict->GetStringBy("Type") == "XRef" && |
773 pDict->KeyExist("Size"))) { | 779 pDict->KeyExist("Size"))) { |
774 CPDF_Object* pRoot = pDict->GetElement("Root"); | 780 CPDF_Object* pRoot = pDict->GetElement("Root"); |
775 if (pRoot && pRoot->GetDict() && | 781 if (pRoot && pRoot->GetDict() && |
776 pRoot->GetDict()->GetElement("Pages")) { | 782 pRoot->GetDict()->GetElement("Pages")) { |
777 if (m_pTrailer) | 783 if (m_pTrailer) |
778 m_pTrailer->Release(); | 784 m_pTrailer->Release(); |
779 m_pTrailer = ToDictionary(pDict->Clone()); | 785 m_pTrailer = ToDictionary(pDict->Clone()); |
780 } | 786 } |
781 } | 787 } |
782 } | 788 } |
783 } | 789 } |
784 | 790 |
785 FX_FILESIZE offset = 0; | 791 FX_FILESIZE offset = 0; |
786 m_Syntax.RestorePos(obj_pos); | 792 m_pSyntax->RestorePos(obj_pos); |
787 offset = m_Syntax.FindTag("obj", 0); | 793 offset = m_pSyntax->FindTag("obj", 0); |
788 if (offset == -1) | 794 if (offset == -1) |
789 offset = 0; | 795 offset = 0; |
790 else | 796 else |
791 offset += 3; | 797 offset += 3; |
792 | 798 |
793 FX_FILESIZE nLen = obj_end - obj_pos - offset; | 799 FX_FILESIZE nLen = obj_end - obj_pos - offset; |
794 if ((FX_DWORD)nLen > size - i) { | 800 if ((FX_DWORD)nLen > size - i) { |
795 pos = obj_end + m_Syntax.m_HeaderOffset; | 801 pos = obj_end + m_pSyntax->m_HeaderOffset; |
796 bOverFlow = true; | 802 bOverFlow = true; |
797 } else { | 803 } else { |
798 i += (FX_DWORD)nLen; | 804 i += (FX_DWORD)nLen; |
799 } | 805 } |
800 | 806 |
801 if (!m_ObjectInfo.empty() && IsValidObjectNumber(objnum) && | 807 if (!m_ObjectInfo.empty() && IsValidObjectNumber(objnum) && |
802 m_ObjectInfo[objnum].pos) { | 808 m_ObjectInfo[objnum].pos) { |
803 if (pObject) { | 809 if (pObject) { |
804 FX_DWORD oldgen = GetObjectGenNum(objnum); | 810 FX_DWORD oldgen = GetObjectGenNum(objnum); |
805 m_ObjectInfo[objnum].pos = obj_pos; | 811 m_ObjectInfo[objnum].pos = obj_pos; |
(...skipping 13 matching lines...) Expand all Loading... |
819 --i; | 825 --i; |
820 state = ParserState::kDefault; | 826 state = ParserState::kDefault; |
821 break; | 827 break; |
822 } | 828 } |
823 break; | 829 break; |
824 | 830 |
825 case ParserState::kTrailer: | 831 case ParserState::kTrailer: |
826 if (inside_index == 7) { | 832 if (inside_index == 7) { |
827 if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { | 833 if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { |
828 last_trailer = pos + i - 7; | 834 last_trailer = pos + i - 7; |
829 m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset); | 835 m_pSyntax->RestorePos(pos + i - m_pSyntax->m_HeaderOffset); |
830 | 836 |
831 CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, true); | 837 CPDF_Object* pObj = m_pSyntax->GetObject(m_pDocument, 0, 0, true); |
832 if (pObj) { | 838 if (pObj) { |
833 if (!pObj->IsDictionary() && !pObj->AsStream()) { | 839 if (!pObj->IsDictionary() && !pObj->AsStream()) { |
834 pObj->Release(); | 840 pObj->Release(); |
835 } else { | 841 } else { |
836 CPDF_Stream* pStream = pObj->AsStream(); | 842 CPDF_Stream* pStream = pObj->AsStream(); |
837 if (CPDF_Dictionary* pTrailer = | 843 if (CPDF_Dictionary* pTrailer = |
838 pStream ? pStream->GetDict() : pObj->AsDictionary()) { | 844 pStream ? pStream->GetDict() : pObj->AsDictionary()) { |
839 if (m_pTrailer) { | 845 if (m_pTrailer) { |
840 CPDF_Object* pRoot = pTrailer->GetElement("Root"); | 846 CPDF_Object* pRoot = pTrailer->GetElement("Root"); |
841 CPDF_Reference* pRef = ToReference(pRoot); | 847 CPDF_Reference* pRef = ToReference(pRoot); |
(...skipping 17 matching lines...) Expand all Loading... |
859 } | 865 } |
860 pObj->Release(); | 866 pObj->Release(); |
861 } else { | 867 } else { |
862 if (pObj->IsStream()) { | 868 if (pObj->IsStream()) { |
863 m_pTrailer = ToDictionary(pTrailer->Clone()); | 869 m_pTrailer = ToDictionary(pTrailer->Clone()); |
864 pObj->Release(); | 870 pObj->Release(); |
865 } else { | 871 } else { |
866 m_pTrailer = pTrailer; | 872 m_pTrailer = pTrailer; |
867 } | 873 } |
868 | 874 |
869 FX_FILESIZE dwSavePos = m_Syntax.SavePos(); | 875 FX_FILESIZE dwSavePos = m_pSyntax->SavePos(); |
870 CFX_ByteString strWord = m_Syntax.GetKeyword(); | 876 CFX_ByteString strWord = m_pSyntax->GetKeyword(); |
871 if (!strWord.Compare("startxref")) { | 877 if (!strWord.Compare("startxref")) { |
872 bool bNumber; | 878 bool bNumber; |
873 CFX_ByteString bsOffset = | 879 CFX_ByteString bsOffset = |
874 m_Syntax.GetNextWord(&bNumber); | 880 m_pSyntax->GetNextWord(&bNumber); |
875 if (bNumber) | 881 if (bNumber) |
876 m_LastXRefOffset = FXSYS_atoi(bsOffset); | 882 m_LastXRefOffset = FXSYS_atoi(bsOffset); |
877 } | 883 } |
878 m_Syntax.RestorePos(dwSavePos); | 884 m_pSyntax->RestorePos(dwSavePos); |
879 } | 885 } |
880 } else { | 886 } else { |
881 pObj->Release(); | 887 pObj->Release(); |
882 } | 888 } |
883 } | 889 } |
884 } | 890 } |
885 } | 891 } |
886 --i; | 892 --i; |
887 state = ParserState::kDefault; | 893 state = ParserState::kDefault; |
888 } else if (byte == "trailer"[inside_index]) { | 894 } else if (byte == "trailer"[inside_index]) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 | 966 |
961 // If the position has not changed at all in a loop iteration, then break | 967 // If the position has not changed at all in a loop iteration, then break |
962 // out to prevent infinite looping. | 968 // out to prevent infinite looping. |
963 if (pos == saved_pos) | 969 if (pos == saved_pos) |
964 break; | 970 break; |
965 } | 971 } |
966 | 972 |
967 if (last_xref != -1 && last_xref > last_obj) | 973 if (last_xref != -1 && last_xref > last_obj) |
968 last_trailer = last_xref; | 974 last_trailer = last_xref; |
969 else if (last_trailer == -1 || last_xref < last_obj) | 975 else if (last_trailer == -1 || last_xref < last_obj) |
970 last_trailer = m_Syntax.m_FileLen; | 976 last_trailer = m_pSyntax->m_FileLen; |
971 | 977 |
972 m_SortedOffset.insert(last_trailer - m_Syntax.m_HeaderOffset); | 978 m_SortedOffset.insert(last_trailer - m_pSyntax->m_HeaderOffset); |
973 return m_pTrailer && !m_ObjectInfo.empty(); | 979 return m_pTrailer && !m_ObjectInfo.empty(); |
974 } | 980 } |
975 | 981 |
976 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) { | 982 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) { |
977 CPDF_Object* pObject = ParseIndirectObjectAt(m_pDocument, *pos, 0); | 983 CPDF_Object* pObject = ParseIndirectObjectAt(m_pDocument, *pos, 0); |
978 if (!pObject) | 984 if (!pObject) |
979 return FALSE; | 985 return FALSE; |
980 | 986 |
981 if (m_pDocument) { | 987 if (m_pDocument) { |
982 FX_BOOL bInserted = FALSE; | 988 FX_BOOL bInserted = FALSE; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1159 | 1165 |
1160 FX_FILESIZE pos = m_ObjectInfo[objnum].pos; | 1166 FX_FILESIZE pos = m_ObjectInfo[objnum].pos; |
1161 auto it = m_SortedOffset.find(pos); | 1167 auto it = m_SortedOffset.find(pos); |
1162 if (it == m_SortedOffset.end()) | 1168 if (it == m_SortedOffset.end()) |
1163 return TRUE; | 1169 return TRUE; |
1164 | 1170 |
1165 if (++it == m_SortedOffset.end()) | 1171 if (++it == m_SortedOffset.end()) |
1166 return FALSE; | 1172 return FALSE; |
1167 | 1173 |
1168 FX_FILESIZE size = *it - pos; | 1174 FX_FILESIZE size = *it - pos; |
1169 FX_FILESIZE SavedPos = m_Syntax.SavePos(); | 1175 FX_FILESIZE SavedPos = m_pSyntax->SavePos(); |
1170 m_Syntax.RestorePos(pos); | 1176 m_pSyntax->RestorePos(pos); |
1171 | 1177 |
1172 const char kFormStream[] = "/Form\0stream"; | 1178 const char kFormStream[] = "/Form\0stream"; |
1173 const CFX_ByteStringC kFormStreamStr(kFormStream, sizeof(kFormStream) - 1); | 1179 const CFX_ByteStringC kFormStreamStr(kFormStream, sizeof(kFormStream) - 1); |
1174 bForm = m_Syntax.SearchMultiWord(kFormStreamStr, TRUE, size) == 0; | 1180 bForm = m_pSyntax->SearchMultiWord(kFormStreamStr, TRUE, size) == 0; |
1175 m_Syntax.RestorePos(SavedPos); | 1181 m_pSyntax->RestorePos(SavedPos); |
1176 return TRUE; | 1182 return TRUE; |
1177 } | 1183 } |
1178 | 1184 |
1179 CPDF_Object* CPDF_Parser::ParseIndirectObject( | 1185 CPDF_Object* CPDF_Parser::ParseIndirectObject( |
1180 CPDF_IndirectObjectHolder* pObjList, | 1186 CPDF_IndirectObjectHolder* pObjList, |
1181 FX_DWORD objnum) { | 1187 FX_DWORD objnum) { |
1182 if (!IsValidObjectNumber(objnum)) | 1188 if (!IsValidObjectNumber(objnum)) |
1183 return nullptr; | 1189 return nullptr; |
1184 | 1190 |
1185 // Prevent circular parsing the same object. | 1191 // Prevent circular parsing the same object. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 return; | 1310 return; |
1305 } | 1311 } |
1306 | 1312 |
1307 if (GetObjectType(objnum) != 1) | 1313 if (GetObjectType(objnum) != 1) |
1308 return; | 1314 return; |
1309 | 1315 |
1310 FX_FILESIZE pos = m_ObjectInfo[objnum].pos; | 1316 FX_FILESIZE pos = m_ObjectInfo[objnum].pos; |
1311 if (pos == 0) | 1317 if (pos == 0) |
1312 return; | 1318 return; |
1313 | 1319 |
1314 FX_FILESIZE SavedPos = m_Syntax.SavePos(); | 1320 FX_FILESIZE SavedPos = m_pSyntax->SavePos(); |
1315 m_Syntax.RestorePos(pos); | 1321 m_pSyntax->RestorePos(pos); |
1316 | 1322 |
1317 bool bIsNumber; | 1323 bool bIsNumber; |
1318 CFX_ByteString word = m_Syntax.GetNextWord(&bIsNumber); | 1324 CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); |
1319 if (!bIsNumber) { | 1325 if (!bIsNumber) { |
1320 m_Syntax.RestorePos(SavedPos); | 1326 m_pSyntax->RestorePos(SavedPos); |
1321 return; | 1327 return; |
1322 } | 1328 } |
1323 | 1329 |
1324 FX_DWORD parser_objnum = FXSYS_atoui(word); | 1330 FX_DWORD parser_objnum = FXSYS_atoui(word); |
1325 if (parser_objnum && parser_objnum != objnum) { | 1331 if (parser_objnum && parser_objnum != objnum) { |
1326 m_Syntax.RestorePos(SavedPos); | 1332 m_pSyntax->RestorePos(SavedPos); |
1327 return; | 1333 return; |
1328 } | 1334 } |
1329 | 1335 |
1330 word = m_Syntax.GetNextWord(&bIsNumber); | 1336 word = m_pSyntax->GetNextWord(&bIsNumber); |
1331 if (!bIsNumber) { | 1337 if (!bIsNumber) { |
1332 m_Syntax.RestorePos(SavedPos); | 1338 m_pSyntax->RestorePos(SavedPos); |
1333 return; | 1339 return; |
1334 } | 1340 } |
1335 | 1341 |
1336 if (m_Syntax.GetKeyword() != "obj") { | 1342 if (m_pSyntax->GetKeyword() != "obj") { |
1337 m_Syntax.RestorePos(SavedPos); | 1343 m_pSyntax->RestorePos(SavedPos); |
1338 return; | 1344 return; |
1339 } | 1345 } |
1340 | 1346 |
1341 auto it = m_SortedOffset.find(pos); | 1347 auto it = m_SortedOffset.find(pos); |
1342 if (it == m_SortedOffset.end() || ++it == m_SortedOffset.end()) { | 1348 if (it == m_SortedOffset.end() || ++it == m_SortedOffset.end()) { |
1343 m_Syntax.RestorePos(SavedPos); | 1349 m_pSyntax->RestorePos(SavedPos); |
1344 return; | 1350 return; |
1345 } | 1351 } |
1346 | 1352 |
1347 FX_FILESIZE nextoff = *it; | 1353 FX_FILESIZE nextoff = *it; |
1348 FX_BOOL bNextOffValid = FALSE; | 1354 FX_BOOL bNextOffValid = FALSE; |
1349 if (nextoff != pos) { | 1355 if (nextoff != pos) { |
1350 m_Syntax.RestorePos(nextoff); | 1356 m_pSyntax->RestorePos(nextoff); |
1351 word = m_Syntax.GetNextWord(&bIsNumber); | 1357 word = m_pSyntax->GetNextWord(&bIsNumber); |
1352 if (word == "xref") { | 1358 if (word == "xref") { |
1353 bNextOffValid = TRUE; | 1359 bNextOffValid = TRUE; |
1354 } else if (bIsNumber) { | 1360 } else if (bIsNumber) { |
1355 word = m_Syntax.GetNextWord(&bIsNumber); | 1361 word = m_pSyntax->GetNextWord(&bIsNumber); |
1356 if (bIsNumber && m_Syntax.GetKeyword() == "obj") { | 1362 if (bIsNumber && m_pSyntax->GetKeyword() == "obj") { |
1357 bNextOffValid = TRUE; | 1363 bNextOffValid = TRUE; |
1358 } | 1364 } |
1359 } | 1365 } |
1360 } | 1366 } |
1361 | 1367 |
1362 if (!bNextOffValid) { | 1368 if (!bNextOffValid) { |
1363 m_Syntax.RestorePos(pos); | 1369 m_pSyntax->RestorePos(pos); |
1364 while (1) { | 1370 while (1) { |
1365 if (m_Syntax.GetKeyword() == "endobj") | 1371 if (m_pSyntax->GetKeyword() == "endobj") |
1366 break; | 1372 break; |
1367 | 1373 |
1368 if (m_Syntax.SavePos() == m_Syntax.m_FileLen) | 1374 if (m_pSyntax->SavePos() == m_pSyntax->m_FileLen) |
1369 break; | 1375 break; |
1370 } | 1376 } |
1371 nextoff = m_Syntax.SavePos(); | 1377 nextoff = m_pSyntax->SavePos(); |
1372 } | 1378 } |
1373 | 1379 |
1374 size = (FX_DWORD)(nextoff - pos); | 1380 size = (FX_DWORD)(nextoff - pos); |
1375 pBuffer = FX_Alloc(uint8_t, size); | 1381 pBuffer = FX_Alloc(uint8_t, size); |
1376 m_Syntax.RestorePos(pos); | 1382 m_pSyntax->RestorePos(pos); |
1377 m_Syntax.ReadBlock(pBuffer, size); | 1383 m_pSyntax->ReadBlock(pBuffer, size); |
1378 m_Syntax.RestorePos(SavedPos); | 1384 m_pSyntax->RestorePos(SavedPos); |
1379 } | 1385 } |
1380 | 1386 |
1381 CPDF_Object* CPDF_Parser::ParseIndirectObjectAt( | 1387 CPDF_Object* CPDF_Parser::ParseIndirectObjectAt( |
1382 CPDF_IndirectObjectHolder* pObjList, | 1388 CPDF_IndirectObjectHolder* pObjList, |
1383 FX_FILESIZE pos, | 1389 FX_FILESIZE pos, |
1384 FX_DWORD objnum) { | 1390 FX_DWORD objnum) { |
1385 FX_FILESIZE SavedPos = m_Syntax.SavePos(); | 1391 FX_FILESIZE SavedPos = m_pSyntax->SavePos(); |
1386 m_Syntax.RestorePos(pos); | 1392 m_pSyntax->RestorePos(pos); |
1387 bool bIsNumber; | 1393 bool bIsNumber; |
1388 CFX_ByteString word = m_Syntax.GetNextWord(&bIsNumber); | 1394 CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); |
1389 if (!bIsNumber) { | 1395 if (!bIsNumber) { |
1390 m_Syntax.RestorePos(SavedPos); | 1396 m_pSyntax->RestorePos(SavedPos); |
1391 return nullptr; | 1397 return nullptr; |
1392 } | 1398 } |
1393 | 1399 |
1394 FX_FILESIZE objOffset = m_Syntax.SavePos(); | 1400 FX_FILESIZE objOffset = m_pSyntax->SavePos(); |
1395 objOffset -= word.GetLength(); | 1401 objOffset -= word.GetLength(); |
1396 FX_DWORD parser_objnum = FXSYS_atoui(word); | 1402 FX_DWORD parser_objnum = FXSYS_atoui(word); |
1397 if (objnum && parser_objnum != objnum) { | 1403 if (objnum && parser_objnum != objnum) { |
1398 m_Syntax.RestorePos(SavedPos); | 1404 m_pSyntax->RestorePos(SavedPos); |
1399 return nullptr; | 1405 return nullptr; |
1400 } | 1406 } |
1401 | 1407 |
1402 word = m_Syntax.GetNextWord(&bIsNumber); | 1408 word = m_pSyntax->GetNextWord(&bIsNumber); |
1403 if (!bIsNumber) { | 1409 if (!bIsNumber) { |
1404 m_Syntax.RestorePos(SavedPos); | 1410 m_pSyntax->RestorePos(SavedPos); |
1405 return nullptr; | 1411 return nullptr; |
1406 } | 1412 } |
1407 | 1413 |
1408 FX_DWORD parser_gennum = FXSYS_atoui(word); | 1414 FX_DWORD parser_gennum = FXSYS_atoui(word); |
1409 if (m_Syntax.GetKeyword() != "obj") { | 1415 if (m_pSyntax->GetKeyword() != "obj") { |
1410 m_Syntax.RestorePos(SavedPos); | 1416 m_pSyntax->RestorePos(SavedPos); |
1411 return nullptr; | 1417 return nullptr; |
1412 } | 1418 } |
1413 | 1419 |
1414 CPDF_Object* pObj = m_Syntax.GetObject(pObjList, objnum, parser_gennum, true); | 1420 CPDF_Object* pObj = |
1415 m_Syntax.SavePos(); | 1421 m_pSyntax->GetObject(pObjList, objnum, parser_gennum, true); |
| 1422 m_pSyntax->SavePos(); |
1416 | 1423 |
1417 CFX_ByteString bsWord = m_Syntax.GetKeyword(); | 1424 CFX_ByteString bsWord = m_pSyntax->GetKeyword(); |
1418 if (bsWord == "endobj") | 1425 if (bsWord == "endobj") |
1419 m_Syntax.SavePos(); | 1426 m_pSyntax->SavePos(); |
1420 | 1427 |
1421 m_Syntax.RestorePos(SavedPos); | 1428 m_pSyntax->RestorePos(SavedPos); |
1422 if (pObj) { | 1429 if (pObj) { |
1423 if (!objnum) | 1430 if (!objnum) |
1424 pObj->m_ObjNum = parser_objnum; | 1431 pObj->m_ObjNum = parser_objnum; |
1425 pObj->m_GenNum = parser_gennum; | 1432 pObj->m_GenNum = parser_gennum; |
1426 } | 1433 } |
1427 return pObj; | 1434 return pObj; |
1428 } | 1435 } |
1429 | 1436 |
1430 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict( | 1437 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict( |
1431 CPDF_IndirectObjectHolder* pObjList, | 1438 CPDF_IndirectObjectHolder* pObjList, |
1432 FX_FILESIZE pos, | 1439 FX_FILESIZE pos, |
1433 FX_DWORD objnum, | 1440 FX_DWORD objnum, |
1434 FX_FILESIZE* pResultPos) { | 1441 FX_FILESIZE* pResultPos) { |
1435 FX_FILESIZE SavedPos = m_Syntax.SavePos(); | 1442 FX_FILESIZE SavedPos = m_pSyntax->SavePos(); |
1436 m_Syntax.RestorePos(pos); | 1443 m_pSyntax->RestorePos(pos); |
1437 | 1444 |
1438 bool bIsNumber; | 1445 bool bIsNumber; |
1439 CFX_ByteString word = m_Syntax.GetNextWord(&bIsNumber); | 1446 CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); |
1440 if (!bIsNumber) { | 1447 if (!bIsNumber) { |
1441 m_Syntax.RestorePos(SavedPos); | 1448 m_pSyntax->RestorePos(SavedPos); |
1442 return nullptr; | 1449 return nullptr; |
1443 } | 1450 } |
1444 | 1451 |
1445 FX_DWORD parser_objnum = FXSYS_atoui(word); | 1452 FX_DWORD parser_objnum = FXSYS_atoui(word); |
1446 if (objnum && parser_objnum != objnum) { | 1453 if (objnum && parser_objnum != objnum) { |
1447 m_Syntax.RestorePos(SavedPos); | 1454 m_pSyntax->RestorePos(SavedPos); |
1448 return nullptr; | 1455 return nullptr; |
1449 } | 1456 } |
1450 | 1457 |
1451 word = m_Syntax.GetNextWord(&bIsNumber); | 1458 word = m_pSyntax->GetNextWord(&bIsNumber); |
1452 if (!bIsNumber) { | 1459 if (!bIsNumber) { |
1453 m_Syntax.RestorePos(SavedPos); | 1460 m_pSyntax->RestorePos(SavedPos); |
1454 return nullptr; | 1461 return nullptr; |
1455 } | 1462 } |
1456 | 1463 |
1457 FX_DWORD gennum = FXSYS_atoui(word); | 1464 FX_DWORD gennum = FXSYS_atoui(word); |
1458 if (m_Syntax.GetKeyword() != "obj") { | 1465 if (m_pSyntax->GetKeyword() != "obj") { |
1459 m_Syntax.RestorePos(SavedPos); | 1466 m_pSyntax->RestorePos(SavedPos); |
1460 return nullptr; | 1467 return nullptr; |
1461 } | 1468 } |
1462 | 1469 |
1463 CPDF_Object* pObj = m_Syntax.GetObjectByStrict(pObjList, objnum, gennum); | 1470 CPDF_Object* pObj = m_pSyntax->GetObjectByStrict(pObjList, objnum, gennum); |
1464 if (pResultPos) | 1471 if (pResultPos) |
1465 *pResultPos = m_Syntax.m_Pos; | 1472 *pResultPos = m_pSyntax->m_Pos; |
1466 | 1473 |
1467 m_Syntax.RestorePos(SavedPos); | 1474 m_pSyntax->RestorePos(SavedPos); |
1468 return pObj; | 1475 return pObj; |
1469 } | 1476 } |
1470 | 1477 |
1471 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4() { | 1478 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4() { |
1472 if (m_Syntax.GetKeyword() != "trailer") | 1479 if (m_pSyntax->GetKeyword() != "trailer") |
1473 return nullptr; | 1480 return nullptr; |
1474 | 1481 |
1475 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pObj( | 1482 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pObj( |
1476 m_Syntax.GetObject(m_pDocument, 0, 0, true)); | 1483 m_pSyntax->GetObject(m_pDocument, 0, 0, true)); |
1477 if (!ToDictionary(pObj.get())) | 1484 if (!ToDictionary(pObj.get())) |
1478 return nullptr; | 1485 return nullptr; |
1479 return pObj.release()->AsDictionary(); | 1486 return pObj.release()->AsDictionary(); |
1480 } | 1487 } |
1481 | 1488 |
1482 FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision) { | 1489 FX_DWORD CPDF_Parser::GetPermissions(FX_BOOL bCheckRevision) { |
1483 if (!m_pSecurityHandler) | 1490 if (!m_pSecurityHandler) |
1484 return (FX_DWORD)-1; | 1491 return (FX_DWORD)-1; |
1485 | 1492 |
1486 FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions(); | 1493 FX_DWORD dwPermission = m_pSecurityHandler->GetPermissions(); |
1487 if (m_pEncryptDict && m_pEncryptDict->GetStringBy("Filter") == "Standard") { | 1494 if (m_pEncryptDict && m_pEncryptDict->GetStringBy("Filter") == "Standard") { |
1488 dwPermission &= 0xFFFFFFFC; | 1495 dwPermission &= 0xFFFFFFFC; |
1489 dwPermission |= 0xFFFFF0C0; | 1496 dwPermission |= 0xFFFFF0C0; |
1490 if (bCheckRevision && m_pEncryptDict->GetIntegerBy("R") == 2) | 1497 if (bCheckRevision && m_pEncryptDict->GetIntegerBy("R") == 2) |
1491 dwPermission &= 0xFFFFF0FF; | 1498 dwPermission &= 0xFFFFF0FF; |
1492 } | 1499 } |
1493 return dwPermission; | 1500 return dwPermission; |
1494 } | 1501 } |
1495 | 1502 |
1496 FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, | 1503 FX_BOOL CPDF_Parser::IsLinearizedFile(IFX_FileRead* pFileAccess, |
1497 FX_DWORD offset) { | 1504 FX_DWORD offset) { |
1498 m_Syntax.InitParser(pFileAccess, offset); | 1505 m_pSyntax->InitParser(pFileAccess, offset); |
1499 m_Syntax.RestorePos(m_Syntax.m_HeaderOffset + 9); | 1506 m_pSyntax->RestorePos(m_pSyntax->m_HeaderOffset + 9); |
1500 | 1507 |
1501 FX_FILESIZE SavedPos = m_Syntax.SavePos(); | 1508 FX_FILESIZE SavedPos = m_pSyntax->SavePos(); |
1502 bool bIsNumber; | 1509 bool bIsNumber; |
1503 CFX_ByteString word = m_Syntax.GetNextWord(&bIsNumber); | 1510 CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); |
1504 if (!bIsNumber) | 1511 if (!bIsNumber) |
1505 return FALSE; | 1512 return FALSE; |
1506 | 1513 |
1507 FX_DWORD objnum = FXSYS_atoui(word); | 1514 FX_DWORD objnum = FXSYS_atoui(word); |
1508 word = m_Syntax.GetNextWord(&bIsNumber); | 1515 word = m_pSyntax->GetNextWord(&bIsNumber); |
1509 if (!bIsNumber) | 1516 if (!bIsNumber) |
1510 return FALSE; | 1517 return FALSE; |
1511 | 1518 |
1512 FX_DWORD gennum = FXSYS_atoui(word); | 1519 FX_DWORD gennum = FXSYS_atoui(word); |
1513 if (m_Syntax.GetKeyword() != "obj") { | 1520 if (m_pSyntax->GetKeyword() != "obj") { |
1514 m_Syntax.RestorePos(SavedPos); | 1521 m_pSyntax->RestorePos(SavedPos); |
1515 return FALSE; | 1522 return FALSE; |
1516 } | 1523 } |
1517 | 1524 |
1518 m_pLinearized = m_Syntax.GetObject(nullptr, objnum, gennum, true); | 1525 m_pLinearized = m_pSyntax->GetObject(nullptr, objnum, gennum, true); |
1519 if (!m_pLinearized) | 1526 if (!m_pLinearized) |
1520 return FALSE; | 1527 return FALSE; |
1521 | 1528 |
1522 CPDF_Dictionary* pDict = m_pLinearized->GetDict(); | 1529 CPDF_Dictionary* pDict = m_pLinearized->GetDict(); |
1523 if (pDict && pDict->GetElement("Linearized")) { | 1530 if (pDict && pDict->GetElement("Linearized")) { |
1524 m_Syntax.GetNextWord(nullptr); | 1531 m_pSyntax->GetNextWord(nullptr); |
1525 | 1532 |
1526 CPDF_Object* pLen = pDict->GetElement("L"); | 1533 CPDF_Object* pLen = pDict->GetElement("L"); |
1527 if (!pLen) { | 1534 if (!pLen) { |
1528 m_pLinearized->Release(); | 1535 m_pLinearized->Release(); |
1529 m_pLinearized = nullptr; | 1536 m_pLinearized = nullptr; |
1530 return FALSE; | 1537 return FALSE; |
1531 } | 1538 } |
1532 | 1539 |
1533 if (pLen->GetInteger() != (int)pFileAccess->GetSize()) | 1540 if (pLen->GetInteger() != (int)pFileAccess->GetSize()) |
1534 return FALSE; | 1541 return FALSE; |
(...skipping 15 matching lines...) Expand all Loading... |
1550 CloseParser(); | 1557 CloseParser(); |
1551 m_bXRefStream = FALSE; | 1558 m_bXRefStream = FALSE; |
1552 m_LastXRefOffset = 0; | 1559 m_LastXRefOffset = 0; |
1553 m_bOwnFileRead = true; | 1560 m_bOwnFileRead = true; |
1554 | 1561 |
1555 int32_t offset = GetHeaderOffset(pFileAccess); | 1562 int32_t offset = GetHeaderOffset(pFileAccess); |
1556 if (offset == -1) | 1563 if (offset == -1) |
1557 return FORMAT_ERROR; | 1564 return FORMAT_ERROR; |
1558 | 1565 |
1559 if (!IsLinearizedFile(pFileAccess, offset)) { | 1566 if (!IsLinearizedFile(pFileAccess, offset)) { |
1560 m_Syntax.m_pFileAccess = nullptr; | 1567 m_pSyntax->m_pFileAccess = nullptr; |
1561 return StartParse(pFileAccess); | 1568 return StartParse(pFileAccess); |
1562 } | 1569 } |
1563 | 1570 |
1564 m_pDocument = new CPDF_Document(this); | 1571 m_pDocument = new CPDF_Document(this); |
1565 FX_FILESIZE dwFirstXRefOffset = m_Syntax.SavePos(); | 1572 FX_FILESIZE dwFirstXRefOffset = m_pSyntax->SavePos(); |
1566 | 1573 |
1567 FX_BOOL bXRefRebuilt = FALSE; | 1574 FX_BOOL bXRefRebuilt = FALSE; |
1568 FX_BOOL bLoadV4 = FALSE; | 1575 FX_BOOL bLoadV4 = FALSE; |
1569 if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE)) && | 1576 if (!(bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE)) && |
1570 !LoadCrossRefV5(&dwFirstXRefOffset, TRUE)) { | 1577 !LoadCrossRefV5(&dwFirstXRefOffset, TRUE)) { |
1571 if (!RebuildCrossRef()) | 1578 if (!RebuildCrossRef()) |
1572 return FORMAT_ERROR; | 1579 return FORMAT_ERROR; |
1573 | 1580 |
1574 bXRefRebuilt = TRUE; | 1581 bXRefRebuilt = TRUE; |
1575 m_LastXRefOffset = 0; | 1582 m_LastXRefOffset = 0; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1613 return FORMAT_ERROR; | 1620 return FORMAT_ERROR; |
1614 | 1621 |
1615 eRet = SetEncryptHandler(); | 1622 eRet = SetEncryptHandler(); |
1616 if (eRet != SUCCESS) | 1623 if (eRet != SUCCESS) |
1617 return eRet; | 1624 return eRet; |
1618 } | 1625 } |
1619 | 1626 |
1620 if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) { | 1627 if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) { |
1621 if (CPDF_Reference* pMetadata = | 1628 if (CPDF_Reference* pMetadata = |
1622 ToReference(m_pDocument->GetRoot()->GetElement("Metadata"))) | 1629 ToReference(m_pDocument->GetRoot()->GetElement("Metadata"))) |
1623 m_Syntax.m_MetadataObjnum = pMetadata->GetRefObjNum(); | 1630 m_pSyntax->m_MetadataObjnum = pMetadata->GetRefObjNum(); |
1624 } | 1631 } |
1625 return SUCCESS; | 1632 return SUCCESS; |
1626 } | 1633 } |
1627 | 1634 |
1628 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) { | 1635 FX_BOOL CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) { |
1629 if (!LoadCrossRefV5(&xrefpos, FALSE)) | 1636 if (!LoadCrossRefV5(&xrefpos, FALSE)) |
1630 return FALSE; | 1637 return FALSE; |
1631 | 1638 |
1632 std::set<FX_FILESIZE> seen_xrefpos; | 1639 std::set<FX_FILESIZE> seen_xrefpos; |
1633 while (xrefpos) { | 1640 while (xrefpos) { |
1634 seen_xrefpos.insert(xrefpos); | 1641 seen_xrefpos.insert(xrefpos); |
1635 if (!LoadCrossRefV5(&xrefpos, FALSE)) | 1642 if (!LoadCrossRefV5(&xrefpos, FALSE)) |
1636 return FALSE; | 1643 return FALSE; |
1637 | 1644 |
1638 // Check for circular references. | 1645 // Check for circular references. |
1639 if (pdfium::ContainsKey(seen_xrefpos, xrefpos)) | 1646 if (pdfium::ContainsKey(seen_xrefpos, xrefpos)) |
1640 return FALSE; | 1647 return FALSE; |
1641 } | 1648 } |
1642 m_ObjectStreamMap.clear(); | 1649 m_ObjectStreamMap.clear(); |
1643 m_bXRefStream = TRUE; | 1650 m_bXRefStream = TRUE; |
1644 return TRUE; | 1651 return TRUE; |
1645 } | 1652 } |
1646 | 1653 |
1647 CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() { | 1654 CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() { |
1648 FX_DWORD dwSaveMetadataObjnum = m_Syntax.m_MetadataObjnum; | 1655 FX_DWORD dwSaveMetadataObjnum = m_pSyntax->m_MetadataObjnum; |
1649 m_Syntax.m_MetadataObjnum = 0; | 1656 m_pSyntax->m_MetadataObjnum = 0; |
1650 if (m_pTrailer) { | 1657 if (m_pTrailer) { |
1651 m_pTrailer->Release(); | 1658 m_pTrailer->Release(); |
1652 m_pTrailer = nullptr; | 1659 m_pTrailer = nullptr; |
1653 } | 1660 } |
1654 | 1661 |
1655 m_Syntax.RestorePos(m_LastXRefOffset - m_Syntax.m_HeaderOffset); | 1662 m_pSyntax->RestorePos(m_LastXRefOffset - m_pSyntax->m_HeaderOffset); |
1656 uint8_t ch = 0; | 1663 uint8_t ch = 0; |
1657 FX_DWORD dwCount = 0; | 1664 FX_DWORD dwCount = 0; |
1658 m_Syntax.GetNextChar(ch); | 1665 m_pSyntax->GetNextChar(ch); |
1659 while (PDFCharIsWhitespace(ch)) { | 1666 while (PDFCharIsWhitespace(ch)) { |
1660 ++dwCount; | 1667 ++dwCount; |
1661 if (m_Syntax.m_FileLen >= | 1668 if (m_pSyntax->m_FileLen >= |
1662 (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) { | 1669 (FX_FILESIZE)(m_pSyntax->SavePos() + m_pSyntax->m_HeaderOffset)) { |
1663 break; | 1670 break; |
1664 } | 1671 } |
1665 m_Syntax.GetNextChar(ch); | 1672 m_pSyntax->GetNextChar(ch); |
1666 } | 1673 } |
1667 m_LastXRefOffset += dwCount; | 1674 m_LastXRefOffset += dwCount; |
1668 m_ObjectStreamMap.clear(); | 1675 m_ObjectStreamMap.clear(); |
1669 m_ObjCache.clear(); | 1676 m_ObjCache.clear(); |
1670 | 1677 |
1671 if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && | 1678 if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && |
1672 !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) { | 1679 !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) { |
1673 m_LastXRefOffset = 0; | 1680 m_LastXRefOffset = 0; |
1674 m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum; | 1681 m_pSyntax->m_MetadataObjnum = dwSaveMetadataObjnum; |
1675 return FORMAT_ERROR; | 1682 return FORMAT_ERROR; |
1676 } | 1683 } |
1677 | 1684 |
1678 m_Syntax.m_MetadataObjnum = dwSaveMetadataObjnum; | 1685 m_pSyntax->m_MetadataObjnum = dwSaveMetadataObjnum; |
1679 return SUCCESS; | 1686 return SUCCESS; |
1680 } | 1687 } |
1681 | 1688 |
1682 // static | |
1683 int CPDF_SyntaxParser::s_CurrentRecursionDepth = 0; | |
1684 | |
1685 CPDF_SyntaxParser::CPDF_SyntaxParser() | |
1686 : m_MetadataObjnum(0), | |
1687 m_pFileAccess(nullptr), | |
1688 m_pFileBuf(nullptr), | |
1689 m_BufSize(CPDF_ModuleMgr::kFileBufSize) {} | |
1690 | |
1691 CPDF_SyntaxParser::~CPDF_SyntaxParser() { | |
1692 FX_Free(m_pFileBuf); | |
1693 } | |
1694 | |
1695 FX_BOOL CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, uint8_t& ch) { | |
1696 CFX_AutoRestorer<FX_FILESIZE> save_pos(&m_Pos); | |
1697 m_Pos = pos; | |
1698 return GetNextChar(ch); | |
1699 } | |
1700 | |
1701 FX_BOOL CPDF_SyntaxParser::GetNextChar(uint8_t& ch) { | |
1702 FX_FILESIZE pos = m_Pos + m_HeaderOffset; | |
1703 if (pos >= m_FileLen) | |
1704 return FALSE; | |
1705 | |
1706 if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) { | |
1707 FX_FILESIZE read_pos = pos; | |
1708 FX_DWORD read_size = m_BufSize; | |
1709 if ((FX_FILESIZE)read_size > m_FileLen) | |
1710 read_size = (FX_DWORD)m_FileLen; | |
1711 | |
1712 if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) { | |
1713 if (m_FileLen < (FX_FILESIZE)read_size) { | |
1714 read_pos = 0; | |
1715 read_size = (FX_DWORD)m_FileLen; | |
1716 } else { | |
1717 read_pos = m_FileLen - read_size; | |
1718 } | |
1719 } | |
1720 | |
1721 if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) | |
1722 return FALSE; | |
1723 | |
1724 m_BufOffset = read_pos; | |
1725 } | |
1726 ch = m_pFileBuf[pos - m_BufOffset]; | |
1727 m_Pos++; | |
1728 return TRUE; | |
1729 } | |
1730 | |
1731 FX_BOOL CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, uint8_t& ch) { | |
1732 pos += m_HeaderOffset; | |
1733 if (pos >= m_FileLen) | |
1734 return FALSE; | |
1735 | |
1736 if (m_BufOffset >= pos || (FX_FILESIZE)(m_BufOffset + m_BufSize) <= pos) { | |
1737 FX_FILESIZE read_pos; | |
1738 if (pos < (FX_FILESIZE)m_BufSize) | |
1739 read_pos = 0; | |
1740 else | |
1741 read_pos = pos - m_BufSize + 1; | |
1742 | |
1743 FX_DWORD read_size = m_BufSize; | |
1744 if ((FX_FILESIZE)(read_pos + read_size) > m_FileLen) { | |
1745 if (m_FileLen < (FX_FILESIZE)read_size) { | |
1746 read_pos = 0; | |
1747 read_size = (FX_DWORD)m_FileLen; | |
1748 } else { | |
1749 read_pos = m_FileLen - read_size; | |
1750 } | |
1751 } | |
1752 | |
1753 if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) | |
1754 return FALSE; | |
1755 | |
1756 m_BufOffset = read_pos; | |
1757 } | |
1758 ch = m_pFileBuf[pos - m_BufOffset]; | |
1759 return TRUE; | |
1760 } | |
1761 | |
1762 FX_BOOL CPDF_SyntaxParser::ReadBlock(uint8_t* pBuf, FX_DWORD size) { | |
1763 if (!m_pFileAccess->ReadBlock(pBuf, m_Pos + m_HeaderOffset, size)) | |
1764 return FALSE; | |
1765 m_Pos += size; | |
1766 return TRUE; | |
1767 } | |
1768 | |
1769 void CPDF_SyntaxParser::GetNextWordInternal(bool* bIsNumber) { | |
1770 m_WordSize = 0; | |
1771 if (bIsNumber) | |
1772 *bIsNumber = true; | |
1773 | |
1774 uint8_t ch; | |
1775 if (!GetNextChar(ch)) | |
1776 return; | |
1777 | |
1778 while (1) { | |
1779 while (PDFCharIsWhitespace(ch)) { | |
1780 if (!GetNextChar(ch)) | |
1781 return; | |
1782 } | |
1783 | |
1784 if (ch != '%') | |
1785 break; | |
1786 | |
1787 while (1) { | |
1788 if (!GetNextChar(ch)) | |
1789 return; | |
1790 if (PDFCharIsLineEnding(ch)) | |
1791 break; | |
1792 } | |
1793 } | |
1794 | |
1795 if (PDFCharIsDelimiter(ch)) { | |
1796 if (bIsNumber) | |
1797 *bIsNumber = false; | |
1798 | |
1799 m_WordBuffer[m_WordSize++] = ch; | |
1800 if (ch == '/') { | |
1801 while (1) { | |
1802 if (!GetNextChar(ch)) | |
1803 return; | |
1804 | |
1805 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) { | |
1806 m_Pos--; | |
1807 return; | |
1808 } | |
1809 | |
1810 if (m_WordSize < sizeof(m_WordBuffer) - 1) | |
1811 m_WordBuffer[m_WordSize++] = ch; | |
1812 } | |
1813 } else if (ch == '<') { | |
1814 if (!GetNextChar(ch)) | |
1815 return; | |
1816 | |
1817 if (ch == '<') | |
1818 m_WordBuffer[m_WordSize++] = ch; | |
1819 else | |
1820 m_Pos--; | |
1821 } else if (ch == '>') { | |
1822 if (!GetNextChar(ch)) | |
1823 return; | |
1824 | |
1825 if (ch == '>') | |
1826 m_WordBuffer[m_WordSize++] = ch; | |
1827 else | |
1828 m_Pos--; | |
1829 } | |
1830 return; | |
1831 } | |
1832 | |
1833 while (1) { | |
1834 if (m_WordSize < sizeof(m_WordBuffer) - 1) | |
1835 m_WordBuffer[m_WordSize++] = ch; | |
1836 | |
1837 if (!PDFCharIsNumeric(ch)) { | |
1838 if (bIsNumber) | |
1839 *bIsNumber = false; | |
1840 } | |
1841 | |
1842 if (!GetNextChar(ch)) | |
1843 return; | |
1844 | |
1845 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) { | |
1846 m_Pos--; | |
1847 break; | |
1848 } | |
1849 } | |
1850 } | |
1851 | |
1852 CFX_ByteString CPDF_SyntaxParser::ReadString() { | |
1853 uint8_t ch; | |
1854 if (!GetNextChar(ch)) | |
1855 return CFX_ByteString(); | |
1856 | |
1857 CFX_ByteTextBuf buf; | |
1858 int32_t parlevel = 0; | |
1859 int32_t status = 0; | |
1860 int32_t iEscCode = 0; | |
1861 while (1) { | |
1862 switch (status) { | |
1863 case 0: | |
1864 if (ch == ')') { | |
1865 if (parlevel == 0) { | |
1866 return buf.GetByteString(); | |
1867 } | |
1868 parlevel--; | |
1869 buf.AppendChar(')'); | |
1870 } else if (ch == '(') { | |
1871 parlevel++; | |
1872 buf.AppendChar('('); | |
1873 } else if (ch == '\\') { | |
1874 status = 1; | |
1875 } else { | |
1876 buf.AppendChar(ch); | |
1877 } | |
1878 break; | |
1879 case 1: | |
1880 if (ch >= '0' && ch <= '7') { | |
1881 iEscCode = FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)); | |
1882 status = 2; | |
1883 break; | |
1884 } | |
1885 | |
1886 if (ch == 'n') { | |
1887 buf.AppendChar('\n'); | |
1888 } else if (ch == 'r') { | |
1889 buf.AppendChar('\r'); | |
1890 } else if (ch == 't') { | |
1891 buf.AppendChar('\t'); | |
1892 } else if (ch == 'b') { | |
1893 buf.AppendChar('\b'); | |
1894 } else if (ch == 'f') { | |
1895 buf.AppendChar('\f'); | |
1896 } else if (ch == '\r') { | |
1897 status = 4; | |
1898 break; | |
1899 } else if (ch != '\n') { | |
1900 buf.AppendChar(ch); | |
1901 } | |
1902 status = 0; | |
1903 break; | |
1904 case 2: | |
1905 if (ch >= '0' && ch <= '7') { | |
1906 iEscCode = | |
1907 iEscCode * 8 + FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)); | |
1908 status = 3; | |
1909 } else { | |
1910 buf.AppendChar(iEscCode); | |
1911 status = 0; | |
1912 continue; | |
1913 } | |
1914 break; | |
1915 case 3: | |
1916 if (ch >= '0' && ch <= '7') { | |
1917 iEscCode = | |
1918 iEscCode * 8 + FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)); | |
1919 buf.AppendChar(iEscCode); | |
1920 status = 0; | |
1921 } else { | |
1922 buf.AppendChar(iEscCode); | |
1923 status = 0; | |
1924 continue; | |
1925 } | |
1926 break; | |
1927 case 4: | |
1928 status = 0; | |
1929 if (ch != '\n') | |
1930 continue; | |
1931 break; | |
1932 } | |
1933 | |
1934 if (!GetNextChar(ch)) | |
1935 break; | |
1936 } | |
1937 | |
1938 GetNextChar(ch); | |
1939 return buf.GetByteString(); | |
1940 } | |
1941 | |
1942 CFX_ByteString CPDF_SyntaxParser::ReadHexString() { | |
1943 uint8_t ch; | |
1944 if (!GetNextChar(ch)) | |
1945 return CFX_ByteString(); | |
1946 | |
1947 CFX_ByteTextBuf buf; | |
1948 bool bFirst = true; | |
1949 uint8_t code = 0; | |
1950 while (1) { | |
1951 if (ch == '>') | |
1952 break; | |
1953 | |
1954 if (std::isxdigit(ch)) { | |
1955 int val = FXSYS_toHexDigit(ch); | |
1956 if (bFirst) { | |
1957 code = val * 16; | |
1958 } else { | |
1959 code += val; | |
1960 buf.AppendByte(code); | |
1961 } | |
1962 bFirst = !bFirst; | |
1963 } | |
1964 | |
1965 if (!GetNextChar(ch)) | |
1966 break; | |
1967 } | |
1968 if (!bFirst) | |
1969 buf.AppendByte(code); | |
1970 | |
1971 return buf.GetByteString(); | |
1972 } | |
1973 | |
1974 void CPDF_SyntaxParser::ToNextLine() { | |
1975 uint8_t ch; | |
1976 while (GetNextChar(ch)) { | |
1977 if (ch == '\n') | |
1978 break; | |
1979 | |
1980 if (ch == '\r') { | |
1981 GetNextChar(ch); | |
1982 if (ch != '\n') | |
1983 --m_Pos; | |
1984 break; | |
1985 } | |
1986 } | |
1987 } | |
1988 | |
1989 void CPDF_SyntaxParser::ToNextWord() { | |
1990 uint8_t ch; | |
1991 if (!GetNextChar(ch)) | |
1992 return; | |
1993 | |
1994 while (1) { | |
1995 while (PDFCharIsWhitespace(ch)) { | |
1996 if (!GetNextChar(ch)) | |
1997 return; | |
1998 } | |
1999 | |
2000 if (ch != '%') | |
2001 break; | |
2002 | |
2003 while (1) { | |
2004 if (!GetNextChar(ch)) | |
2005 return; | |
2006 if (PDFCharIsLineEnding(ch)) | |
2007 break; | |
2008 } | |
2009 } | |
2010 m_Pos--; | |
2011 } | |
2012 | |
2013 CFX_ByteString CPDF_SyntaxParser::GetNextWord(bool* bIsNumber) { | |
2014 GetNextWordInternal(bIsNumber); | |
2015 return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize); | |
2016 } | |
2017 | |
2018 CFX_ByteString CPDF_SyntaxParser::GetKeyword() { | |
2019 return GetNextWord(nullptr); | |
2020 } | |
2021 | |
2022 CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjectHolder* pObjList, | |
2023 FX_DWORD objnum, | |
2024 FX_DWORD gennum, | |
2025 FX_BOOL bDecrypt) { | |
2026 CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth); | |
2027 if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) | |
2028 return nullptr; | |
2029 | |
2030 FX_FILESIZE SavedPos = m_Pos; | |
2031 bool bIsNumber; | |
2032 CFX_ByteString word = GetNextWord(&bIsNumber); | |
2033 if (word.GetLength() == 0) | |
2034 return nullptr; | |
2035 | |
2036 if (bIsNumber) { | |
2037 FX_FILESIZE SavedPos = m_Pos; | |
2038 CFX_ByteString nextword = GetNextWord(&bIsNumber); | |
2039 if (bIsNumber) { | |
2040 CFX_ByteString nextword2 = GetNextWord(nullptr); | |
2041 if (nextword2 == "R") { | |
2042 FX_DWORD objnum = FXSYS_atoui(word); | |
2043 return new CPDF_Reference(pObjList, objnum); | |
2044 } | |
2045 } | |
2046 m_Pos = SavedPos; | |
2047 return new CPDF_Number(word); | |
2048 } | |
2049 | |
2050 if (word == "true" || word == "false") | |
2051 return new CPDF_Boolean(word == "true"); | |
2052 | |
2053 if (word == "null") | |
2054 return new CPDF_Null; | |
2055 | |
2056 if (word == "(") { | |
2057 CFX_ByteString str = ReadString(); | |
2058 if (m_pCryptoHandler && bDecrypt) | |
2059 m_pCryptoHandler->Decrypt(objnum, gennum, str); | |
2060 return new CPDF_String(str, FALSE); | |
2061 } | |
2062 | |
2063 if (word == "<") { | |
2064 CFX_ByteString str = ReadHexString(); | |
2065 if (m_pCryptoHandler && bDecrypt) | |
2066 m_pCryptoHandler->Decrypt(objnum, gennum, str); | |
2067 | |
2068 return new CPDF_String(str, TRUE); | |
2069 } | |
2070 | |
2071 if (word == "[") { | |
2072 CPDF_Array* pArray = new CPDF_Array; | |
2073 while (CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, true)) | |
2074 pArray->Add(pObj); | |
2075 | |
2076 return pArray; | |
2077 } | |
2078 | |
2079 if (word[0] == '/') { | |
2080 return new CPDF_Name( | |
2081 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); | |
2082 } | |
2083 | |
2084 if (word == "<<") { | |
2085 int32_t nKeys = 0; | |
2086 FX_FILESIZE dwSignValuePos = 0; | |
2087 | |
2088 std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>> pDict( | |
2089 new CPDF_Dictionary); | |
2090 while (1) { | |
2091 CFX_ByteString key = GetNextWord(nullptr); | |
2092 if (key.IsEmpty()) | |
2093 return nullptr; | |
2094 | |
2095 FX_FILESIZE SavedPos = m_Pos - key.GetLength(); | |
2096 if (key == ">>") | |
2097 break; | |
2098 | |
2099 if (key == "endobj") { | |
2100 m_Pos = SavedPos; | |
2101 break; | |
2102 } | |
2103 | |
2104 if (key[0] != '/') | |
2105 continue; | |
2106 | |
2107 ++nKeys; | |
2108 key = PDF_NameDecode(key); | |
2109 if (key.IsEmpty()) | |
2110 continue; | |
2111 | |
2112 if (key == "/Contents") | |
2113 dwSignValuePos = m_Pos; | |
2114 | |
2115 CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, true); | |
2116 if (!pObj) | |
2117 continue; | |
2118 | |
2119 CFX_ByteStringC keyNoSlash(key.c_str() + 1, key.GetLength() - 1); | |
2120 pDict->SetAt(keyNoSlash, pObj); | |
2121 } | |
2122 | |
2123 // Only when this is a signature dictionary and has contents, we reset the | |
2124 // contents to the un-decrypted form. | |
2125 if (IsSignatureDict(pDict.get()) && dwSignValuePos) { | |
2126 CFX_AutoRestorer<FX_FILESIZE> save_pos(&m_Pos); | |
2127 m_Pos = dwSignValuePos; | |
2128 pDict->SetAt("Contents", GetObject(pObjList, objnum, gennum, false)); | |
2129 } | |
2130 | |
2131 FX_FILESIZE SavedPos = m_Pos; | |
2132 CFX_ByteString nextword = GetNextWord(nullptr); | |
2133 if (nextword != "stream") { | |
2134 m_Pos = SavedPos; | |
2135 return pDict.release(); | |
2136 } | |
2137 return ReadStream(pDict.release(), objnum, gennum); | |
2138 } | |
2139 | |
2140 if (word == ">>") | |
2141 m_Pos = SavedPos; | |
2142 | |
2143 return nullptr; | |
2144 } | |
2145 | |
2146 CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict( | |
2147 CPDF_IndirectObjectHolder* pObjList, | |
2148 FX_DWORD objnum, | |
2149 FX_DWORD gennum) { | |
2150 CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth); | |
2151 if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) | |
2152 return nullptr; | |
2153 | |
2154 FX_FILESIZE SavedPos = m_Pos; | |
2155 bool bIsNumber; | |
2156 CFX_ByteString word = GetNextWord(&bIsNumber); | |
2157 if (word.GetLength() == 0) | |
2158 return nullptr; | |
2159 | |
2160 if (bIsNumber) { | |
2161 FX_FILESIZE SavedPos = m_Pos; | |
2162 CFX_ByteString nextword = GetNextWord(&bIsNumber); | |
2163 if (bIsNumber) { | |
2164 CFX_ByteString nextword2 = GetNextWord(nullptr); | |
2165 if (nextword2 == "R") | |
2166 return new CPDF_Reference(pObjList, FXSYS_atoui(word)); | |
2167 } | |
2168 m_Pos = SavedPos; | |
2169 return new CPDF_Number(word); | |
2170 } | |
2171 | |
2172 if (word == "true" || word == "false") | |
2173 return new CPDF_Boolean(word == "true"); | |
2174 | |
2175 if (word == "null") | |
2176 return new CPDF_Null; | |
2177 | |
2178 if (word == "(") { | |
2179 CFX_ByteString str = ReadString(); | |
2180 if (m_pCryptoHandler) | |
2181 m_pCryptoHandler->Decrypt(objnum, gennum, str); | |
2182 return new CPDF_String(str, FALSE); | |
2183 } | |
2184 | |
2185 if (word == "<") { | |
2186 CFX_ByteString str = ReadHexString(); | |
2187 if (m_pCryptoHandler) | |
2188 m_pCryptoHandler->Decrypt(objnum, gennum, str); | |
2189 return new CPDF_String(str, TRUE); | |
2190 } | |
2191 | |
2192 if (word == "[") { | |
2193 std::unique_ptr<CPDF_Array, ReleaseDeleter<CPDF_Array>> pArray( | |
2194 new CPDF_Array); | |
2195 while (CPDF_Object* pObj = GetObject(pObjList, objnum, gennum, true)) | |
2196 pArray->Add(pObj); | |
2197 | |
2198 return m_WordBuffer[0] == ']' ? pArray.release() : nullptr; | |
2199 } | |
2200 | |
2201 if (word[0] == '/') { | |
2202 return new CPDF_Name( | |
2203 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); | |
2204 } | |
2205 | |
2206 if (word == "<<") { | |
2207 std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>> pDict( | |
2208 new CPDF_Dictionary); | |
2209 while (1) { | |
2210 FX_FILESIZE SavedPos = m_Pos; | |
2211 CFX_ByteString key = GetNextWord(nullptr); | |
2212 if (key.IsEmpty()) | |
2213 return nullptr; | |
2214 | |
2215 if (key == ">>") | |
2216 break; | |
2217 | |
2218 if (key == "endobj") { | |
2219 m_Pos = SavedPos; | |
2220 break; | |
2221 } | |
2222 | |
2223 if (key[0] != '/') | |
2224 continue; | |
2225 | |
2226 key = PDF_NameDecode(key); | |
2227 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> obj( | |
2228 GetObject(pObjList, objnum, gennum, true)); | |
2229 if (!obj) { | |
2230 uint8_t ch; | |
2231 while (GetNextChar(ch) && ch != 0x0A && ch != 0x0D) { | |
2232 continue; | |
2233 } | |
2234 return nullptr; | |
2235 } | |
2236 | |
2237 if (key.GetLength() > 1) { | |
2238 pDict->SetAt(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1), | |
2239 obj.release()); | |
2240 } | |
2241 } | |
2242 | |
2243 FX_FILESIZE SavedPos = m_Pos; | |
2244 CFX_ByteString nextword = GetNextWord(nullptr); | |
2245 if (nextword != "stream") { | |
2246 m_Pos = SavedPos; | |
2247 return pDict.release(); | |
2248 } | |
2249 | |
2250 return ReadStream(pDict.release(), objnum, gennum); | |
2251 } | |
2252 | |
2253 if (word == ">>") | |
2254 m_Pos = SavedPos; | |
2255 | |
2256 return nullptr; | |
2257 } | |
2258 | |
2259 unsigned int CPDF_SyntaxParser::ReadEOLMarkers(FX_FILESIZE pos) { | |
2260 unsigned char byte1 = 0; | |
2261 unsigned char byte2 = 0; | |
2262 | |
2263 GetCharAt(pos, byte1); | |
2264 GetCharAt(pos + 1, byte2); | |
2265 | |
2266 if (byte1 == '\r' && byte2 == '\n') | |
2267 return 2; | |
2268 | |
2269 if (byte1 == '\r' || byte1 == '\n') | |
2270 return 1; | |
2271 | |
2272 return 0; | |
2273 } | |
2274 | |
2275 CPDF_Stream* CPDF_SyntaxParser::ReadStream(CPDF_Dictionary* pDict, | |
2276 FX_DWORD objnum, | |
2277 FX_DWORD gennum) { | |
2278 CPDF_Object* pLenObj = pDict->GetElement("Length"); | |
2279 FX_FILESIZE len = -1; | |
2280 CPDF_Reference* pLenObjRef = ToReference(pLenObj); | |
2281 | |
2282 bool differingObjNum = !pLenObjRef || (pLenObjRef->GetObjList() && | |
2283 pLenObjRef->GetRefObjNum() != objnum); | |
2284 if (pLenObj && differingObjNum) | |
2285 len = pLenObj->GetInteger(); | |
2286 | |
2287 // Locate the start of stream. | |
2288 ToNextLine(); | |
2289 FX_FILESIZE streamStartPos = m_Pos; | |
2290 | |
2291 const CFX_ByteStringC kEndStreamStr("endstream"); | |
2292 const CFX_ByteStringC kEndObjStr("endobj"); | |
2293 | |
2294 CPDF_CryptoHandler* pCryptoHandler = | |
2295 objnum == (FX_DWORD)m_MetadataObjnum ? nullptr : m_pCryptoHandler.get(); | |
2296 if (!pCryptoHandler) { | |
2297 FX_BOOL bSearchForKeyword = TRUE; | |
2298 if (len >= 0) { | |
2299 pdfium::base::CheckedNumeric<FX_FILESIZE> pos = m_Pos; | |
2300 pos += len; | |
2301 if (pos.IsValid() && pos.ValueOrDie() < m_FileLen) | |
2302 m_Pos = pos.ValueOrDie(); | |
2303 | |
2304 m_Pos += ReadEOLMarkers(m_Pos); | |
2305 FXSYS_memset(m_WordBuffer, 0, kEndStreamStr.GetLength() + 1); | |
2306 GetNextWordInternal(nullptr); | |
2307 // Earlier version of PDF specification doesn't require EOL marker before | |
2308 // 'endstream' keyword. If keyword 'endstream' follows the bytes in | |
2309 // specified length, it signals the end of stream. | |
2310 if (FXSYS_memcmp(m_WordBuffer, kEndStreamStr.GetPtr(), | |
2311 kEndStreamStr.GetLength()) == 0) { | |
2312 bSearchForKeyword = FALSE; | |
2313 } | |
2314 } | |
2315 | |
2316 if (bSearchForKeyword) { | |
2317 // If len is not available, len needs to be calculated | |
2318 // by searching the keywords "endstream" or "endobj". | |
2319 m_Pos = streamStartPos; | |
2320 FX_FILESIZE endStreamOffset = 0; | |
2321 while (endStreamOffset >= 0) { | |
2322 endStreamOffset = FindTag(kEndStreamStr, 0); | |
2323 | |
2324 // Can't find "endstream". | |
2325 if (endStreamOffset < 0) | |
2326 break; | |
2327 | |
2328 // Stop searching when "endstream" is found. | |
2329 if (IsWholeWord(m_Pos - kEndStreamStr.GetLength(), m_FileLen, | |
2330 kEndStreamStr, TRUE)) { | |
2331 endStreamOffset = m_Pos - streamStartPos - kEndStreamStr.GetLength(); | |
2332 break; | |
2333 } | |
2334 } | |
2335 | |
2336 m_Pos = streamStartPos; | |
2337 FX_FILESIZE endObjOffset = 0; | |
2338 while (endObjOffset >= 0) { | |
2339 endObjOffset = FindTag(kEndObjStr, 0); | |
2340 | |
2341 // Can't find "endobj". | |
2342 if (endObjOffset < 0) | |
2343 break; | |
2344 | |
2345 // Stop searching when "endobj" is found. | |
2346 if (IsWholeWord(m_Pos - kEndObjStr.GetLength(), m_FileLen, kEndObjStr, | |
2347 TRUE)) { | |
2348 endObjOffset = m_Pos - streamStartPos - kEndObjStr.GetLength(); | |
2349 break; | |
2350 } | |
2351 } | |
2352 | |
2353 // Can't find "endstream" or "endobj". | |
2354 if (endStreamOffset < 0 && endObjOffset < 0) { | |
2355 pDict->Release(); | |
2356 return nullptr; | |
2357 } | |
2358 | |
2359 if (endStreamOffset < 0 && endObjOffset >= 0) { | |
2360 // Correct the position of end stream. | |
2361 endStreamOffset = endObjOffset; | |
2362 } else if (endStreamOffset >= 0 && endObjOffset < 0) { | |
2363 // Correct the position of end obj. | |
2364 endObjOffset = endStreamOffset; | |
2365 } else if (endStreamOffset > endObjOffset) { | |
2366 endStreamOffset = endObjOffset; | |
2367 } | |
2368 | |
2369 len = endStreamOffset; | |
2370 int numMarkers = ReadEOLMarkers(streamStartPos + endStreamOffset - 2); | |
2371 if (numMarkers == 2) { | |
2372 len -= 2; | |
2373 } else { | |
2374 numMarkers = ReadEOLMarkers(streamStartPos + endStreamOffset - 1); | |
2375 if (numMarkers == 1) { | |
2376 len -= 1; | |
2377 } | |
2378 } | |
2379 | |
2380 if (len < 0) { | |
2381 pDict->Release(); | |
2382 return nullptr; | |
2383 } | |
2384 pDict->SetAtInteger("Length", len); | |
2385 } | |
2386 m_Pos = streamStartPos; | |
2387 } | |
2388 | |
2389 if (len < 0) { | |
2390 pDict->Release(); | |
2391 return nullptr; | |
2392 } | |
2393 | |
2394 uint8_t* pData = nullptr; | |
2395 if (len > 0) { | |
2396 pData = FX_Alloc(uint8_t, len); | |
2397 ReadBlock(pData, len); | |
2398 if (pCryptoHandler) { | |
2399 CFX_BinaryBuf dest_buf; | |
2400 dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len)); | |
2401 | |
2402 void* context = pCryptoHandler->DecryptStart(objnum, gennum); | |
2403 pCryptoHandler->DecryptStream(context, pData, len, dest_buf); | |
2404 pCryptoHandler->DecryptFinish(context, dest_buf); | |
2405 | |
2406 FX_Free(pData); | |
2407 pData = dest_buf.GetBuffer(); | |
2408 len = dest_buf.GetSize(); | |
2409 dest_buf.DetachBuffer(); | |
2410 } | |
2411 } | |
2412 | |
2413 CPDF_Stream* pStream = new CPDF_Stream(pData, len, pDict); | |
2414 streamStartPos = m_Pos; | |
2415 FXSYS_memset(m_WordBuffer, 0, kEndObjStr.GetLength() + 1); | |
2416 | |
2417 GetNextWordInternal(nullptr); | |
2418 | |
2419 int numMarkers = ReadEOLMarkers(m_Pos); | |
2420 if (m_WordSize == kEndObjStr.GetLength() && numMarkers != 0 && | |
2421 FXSYS_memcmp(m_WordBuffer, kEndObjStr.GetPtr(), kEndObjStr.GetLength()) == | |
2422 0) { | |
2423 m_Pos = streamStartPos; | |
2424 } | |
2425 return pStream; | |
2426 } | |
2427 | |
2428 void CPDF_SyntaxParser::InitParser(IFX_FileRead* pFileAccess, | |
2429 FX_DWORD HeaderOffset) { | |
2430 FX_Free(m_pFileBuf); | |
2431 | |
2432 m_pFileBuf = FX_Alloc(uint8_t, m_BufSize); | |
2433 m_HeaderOffset = HeaderOffset; | |
2434 m_FileLen = pFileAccess->GetSize(); | |
2435 m_Pos = 0; | |
2436 m_pFileAccess = pFileAccess; | |
2437 m_BufOffset = 0; | |
2438 pFileAccess->ReadBlock( | |
2439 m_pFileBuf, 0, | |
2440 (size_t)((FX_FILESIZE)m_BufSize > m_FileLen ? m_FileLen : m_BufSize)); | |
2441 } | |
2442 | |
2443 uint32_t CPDF_SyntaxParser::GetDirectNum() { | |
2444 bool bIsNumber; | |
2445 GetNextWordInternal(&bIsNumber); | |
2446 if (!bIsNumber) | |
2447 return 0; | |
2448 | |
2449 m_WordBuffer[m_WordSize] = 0; | |
2450 return FXSYS_atoui(reinterpret_cast<const FX_CHAR*>(m_WordBuffer)); | |
2451 } | |
2452 | |
2453 bool CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, | |
2454 FX_FILESIZE limit, | |
2455 const CFX_ByteStringC& tag, | |
2456 FX_BOOL checkKeyword) { | |
2457 const FX_DWORD taglen = tag.GetLength(); | |
2458 | |
2459 bool bCheckLeft = !PDFCharIsDelimiter(tag[0]) && !PDFCharIsWhitespace(tag[0]); | |
2460 bool bCheckRight = !PDFCharIsDelimiter(tag[taglen - 1]) && | |
2461 !PDFCharIsWhitespace(tag[taglen - 1]); | |
2462 | |
2463 uint8_t ch; | |
2464 if (bCheckRight && startpos + (int32_t)taglen <= limit && | |
2465 GetCharAt(startpos + (int32_t)taglen, ch)) { | |
2466 if (PDFCharIsNumeric(ch) || PDFCharIsOther(ch) || | |
2467 (checkKeyword && PDFCharIsDelimiter(ch))) { | |
2468 return false; | |
2469 } | |
2470 } | |
2471 | |
2472 if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) { | |
2473 if (PDFCharIsNumeric(ch) || PDFCharIsOther(ch) || | |
2474 (checkKeyword && PDFCharIsDelimiter(ch))) { | |
2475 return false; | |
2476 } | |
2477 } | |
2478 return true; | |
2479 } | |
2480 | |
2481 // TODO(dsinclair): Split into a SearchWordForward and SearchWordBackwards | |
2482 // and drop the bool. | |
2483 FX_BOOL CPDF_SyntaxParser::SearchWord(const CFX_ByteStringC& tag, | |
2484 FX_BOOL bWholeWord, | |
2485 FX_BOOL bForward, | |
2486 FX_FILESIZE limit) { | |
2487 int32_t taglen = tag.GetLength(); | |
2488 if (taglen == 0) | |
2489 return FALSE; | |
2490 | |
2491 FX_FILESIZE pos = m_Pos; | |
2492 int32_t offset = 0; | |
2493 if (!bForward) | |
2494 offset = taglen - 1; | |
2495 | |
2496 const uint8_t* tag_data = tag.GetPtr(); | |
2497 uint8_t byte; | |
2498 while (1) { | |
2499 if (bForward) { | |
2500 if (limit && pos >= m_Pos + limit) | |
2501 return FALSE; | |
2502 | |
2503 if (!GetCharAt(pos, byte)) | |
2504 return FALSE; | |
2505 | |
2506 } else { | |
2507 if (limit && pos <= m_Pos - limit) | |
2508 return FALSE; | |
2509 | |
2510 if (!GetCharAtBackward(pos, byte)) | |
2511 return FALSE; | |
2512 } | |
2513 | |
2514 if (byte == tag_data[offset]) { | |
2515 if (bForward) { | |
2516 offset++; | |
2517 if (offset < taglen) { | |
2518 pos++; | |
2519 continue; | |
2520 } | |
2521 } else { | |
2522 offset--; | |
2523 if (offset >= 0) { | |
2524 pos--; | |
2525 continue; | |
2526 } | |
2527 } | |
2528 | |
2529 FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos; | |
2530 if (!bWholeWord || IsWholeWord(startpos, limit, tag, FALSE)) { | |
2531 m_Pos = startpos; | |
2532 return TRUE; | |
2533 } | |
2534 } | |
2535 | |
2536 if (bForward) { | |
2537 offset = byte == tag_data[0] ? 1 : 0; | |
2538 pos++; | |
2539 } else { | |
2540 offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1; | |
2541 pos--; | |
2542 } | |
2543 | |
2544 if (pos < 0) | |
2545 return FALSE; | |
2546 } | |
2547 | |
2548 return FALSE; | |
2549 } | |
2550 | |
2551 int32_t CPDF_SyntaxParser::SearchMultiWord(const CFX_ByteStringC& tags, | |
2552 FX_BOOL bWholeWord, | |
2553 FX_FILESIZE limit) { | |
2554 int32_t ntags = 1; | |
2555 for (int i = 0; i < tags.GetLength(); ++i) { | |
2556 if (tags[i] == 0) | |
2557 ++ntags; | |
2558 } | |
2559 | |
2560 std::vector<SearchTagRecord> patterns(ntags); | |
2561 FX_DWORD start = 0; | |
2562 FX_DWORD itag = 0; | |
2563 FX_DWORD max_len = 0; | |
2564 for (int i = 0; i <= tags.GetLength(); ++i) { | |
2565 if (tags[i] == 0) { | |
2566 FX_DWORD len = i - start; | |
2567 max_len = std::max(len, max_len); | |
2568 patterns[itag].m_pTag = tags.GetCStr() + start; | |
2569 patterns[itag].m_Len = len; | |
2570 patterns[itag].m_Offset = 0; | |
2571 start = i + 1; | |
2572 ++itag; | |
2573 } | |
2574 } | |
2575 | |
2576 const FX_FILESIZE pos_limit = m_Pos + limit; | |
2577 for (FX_FILESIZE pos = m_Pos; !limit || pos < pos_limit; ++pos) { | |
2578 uint8_t byte; | |
2579 if (!GetCharAt(pos, byte)) | |
2580 break; | |
2581 | |
2582 for (int i = 0; i < ntags; ++i) { | |
2583 SearchTagRecord& pat = patterns[i]; | |
2584 if (pat.m_pTag[pat.m_Offset] != byte) { | |
2585 pat.m_Offset = (pat.m_pTag[0] == byte) ? 1 : 0; | |
2586 continue; | |
2587 } | |
2588 | |
2589 ++pat.m_Offset; | |
2590 if (pat.m_Offset != pat.m_Len) | |
2591 continue; | |
2592 | |
2593 if (!bWholeWord || | |
2594 IsWholeWord(pos - pat.m_Len, limit, | |
2595 CFX_ByteStringC(pat.m_pTag, pat.m_Len), FALSE)) { | |
2596 return i; | |
2597 } | |
2598 | |
2599 pat.m_Offset = (pat.m_pTag[0] == byte) ? 1 : 0; | |
2600 } | |
2601 } | |
2602 return -1; | |
2603 } | |
2604 | |
2605 FX_FILESIZE CPDF_SyntaxParser::FindTag(const CFX_ByteStringC& tag, | |
2606 FX_FILESIZE limit) { | |
2607 int32_t taglen = tag.GetLength(); | |
2608 int32_t match = 0; | |
2609 limit += m_Pos; | |
2610 FX_FILESIZE startpos = m_Pos; | |
2611 | |
2612 while (1) { | |
2613 uint8_t ch; | |
2614 if (!GetNextChar(ch)) | |
2615 return -1; | |
2616 | |
2617 if (ch == tag[match]) { | |
2618 match++; | |
2619 if (match == taglen) | |
2620 return m_Pos - startpos - taglen; | |
2621 } else { | |
2622 match = ch == tag[0] ? 1 : 0; | |
2623 } | |
2624 | |
2625 if (limit && m_Pos == limit) | |
2626 return -1; | |
2627 } | |
2628 return -1; | |
2629 } | |
2630 | |
2631 void CPDF_SyntaxParser::SetEncrypt( | |
2632 std::unique_ptr<CPDF_CryptoHandler> pCryptoHandler) { | |
2633 m_pCryptoHandler = std::move(pCryptoHandler); | |
2634 } | |
2635 | 1689 |
2636 class CPDF_DataAvail final : public IPDF_DataAvail { | 1690 class CPDF_DataAvail final : public IPDF_DataAvail { |
2637 public: | 1691 public: |
2638 CPDF_DataAvail(IFX_FileAvail* pFileAvail, | 1692 CPDF_DataAvail(IFX_FileAvail* pFileAvail, |
2639 IFX_FileRead* pFileRead, | 1693 IFX_FileRead* pFileRead, |
2640 FX_BOOL bSupportHintTable); | 1694 FX_BOOL bSupportHintTable); |
2641 ~CPDF_DataAvail() override; | 1695 ~CPDF_DataAvail() override; |
2642 | 1696 |
2643 // IPDF_DataAvail: | 1697 // IPDF_DataAvail: |
2644 DocAvailStatus IsDocAvail(IFX_DownloadHints* pHints) override; | 1698 DocAvailStatus IsDocAvail(IFX_DownloadHints* pHints) override; |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3105 if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) { | 2159 if (m_pFileAvail->IsDataAvail(0, (FX_DWORD)m_dwFileLen)) { |
3106 m_docStatus = PDF_DATAAVAIL_DONE; | 2160 m_docStatus = PDF_DATAAVAIL_DONE; |
3107 return TRUE; | 2161 return TRUE; |
3108 } | 2162 } |
3109 | 2163 |
3110 pHints->AddSegment(0, (FX_DWORD)m_dwFileLen); | 2164 pHints->AddSegment(0, (FX_DWORD)m_dwFileLen); |
3111 return FALSE; | 2165 return FALSE; |
3112 } | 2166 } |
3113 | 2167 |
3114 FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints) { | 2168 FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints) { |
3115 m_parser.m_Syntax.InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset); | 2169 m_parser.m_pSyntax->InitParser(m_pFileRead, (FX_DWORD)m_dwHeaderOffset); |
3116 m_parser.m_bOwnFileRead = false; | 2170 m_parser.m_bOwnFileRead = false; |
3117 if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && | 2171 if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && |
3118 !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) { | 2172 !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) { |
3119 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; | 2173 m_docStatus = PDF_DATAAVAIL_LOADALLFILE; |
3120 return FALSE; | 2174 return FALSE; |
3121 } | 2175 } |
3122 | 2176 |
3123 m_dwRootObjNum = m_parser.GetRootObjNum(); | 2177 m_dwRootObjNum = m_parser.GetRootObjNum(); |
3124 m_dwInfoObjNum = m_parser.GetInfoObjNum(); | 2178 m_dwInfoObjNum = m_parser.GetInfoObjNum(); |
3125 m_pCurrentParser = &m_parser; | 2179 m_pCurrentParser = &m_parser; |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3690 (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); | 2744 (FX_DWORD)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); |
3691 | 2745 |
3692 if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) { | 2746 if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) { |
3693 int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam); | 2747 int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam); |
3694 CFX_BinaryBuf buf(iSize); | 2748 CFX_BinaryBuf buf(iSize); |
3695 uint8_t* pBuf = buf.GetBuffer(); | 2749 uint8_t* pBuf = buf.GetBuffer(); |
3696 | 2750 |
3697 m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize); | 2751 m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize); |
3698 | 2752 |
3699 ScopedFileStream file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE)); | 2753 ScopedFileStream file(FX_CreateMemoryStream(pBuf, (size_t)iSize, FALSE)); |
3700 m_parser.m_Syntax.InitParser(file.get(), 0); | 2754 m_parser.m_pSyntax->InitParser(file.get(), 0); |
3701 | 2755 |
3702 bool bNumber; | 2756 bool bNumber; |
3703 CFX_ByteString objnum = m_parser.m_Syntax.GetNextWord(&bNumber); | 2757 CFX_ByteString objnum = m_parser.m_pSyntax->GetNextWord(&bNumber); |
3704 if (!bNumber) | 2758 if (!bNumber) |
3705 return -1; | 2759 return -1; |
3706 | 2760 |
3707 FX_DWORD objNum = FXSYS_atoui(objnum); | 2761 FX_DWORD objNum = FXSYS_atoui(objnum); |
3708 CPDF_Object* pObj = m_parser.ParseIndirectObjectAt(nullptr, 0, objNum); | 2762 CPDF_Object* pObj = m_parser.ParseIndirectObjectAt(nullptr, 0, objNum); |
3709 if (!pObj) { | 2763 if (!pObj) { |
3710 m_Pos += m_parser.m_Syntax.SavePos(); | 2764 m_Pos += m_parser.m_pSyntax->SavePos(); |
3711 return 0; | 2765 return 0; |
3712 } | 2766 } |
3713 | 2767 |
3714 CPDF_Dictionary* pDict = pObj->GetDict(); | 2768 CPDF_Dictionary* pDict = pObj->GetDict(); |
3715 CPDF_Name* pName = ToName(pDict ? pDict->GetElement("Type") : nullptr); | 2769 CPDF_Name* pName = ToName(pDict ? pDict->GetElement("Type") : nullptr); |
3716 if (pName) { | 2770 if (pName) { |
3717 if (pName->GetString() == "XRef") { | 2771 if (pName->GetString() == "XRef") { |
3718 m_Pos += m_parser.m_Syntax.SavePos(); | 2772 m_Pos += m_parser.m_pSyntax->SavePos(); |
3719 xref_offset = pObj->GetDict()->GetIntegerBy("Prev"); | 2773 xref_offset = pObj->GetDict()->GetIntegerBy("Prev"); |
3720 pObj->Release(); | 2774 pObj->Release(); |
3721 return 1; | 2775 return 1; |
3722 } | 2776 } |
3723 } | 2777 } |
3724 pObj->Release(); | 2778 pObj->Release(); |
3725 return -1; | 2779 return -1; |
3726 } | 2780 } |
3727 pHints->AddSegment(m_Pos, req_size); | 2781 pHints->AddSegment(m_Pos, req_size); |
3728 return 0; | 2782 return 0; |
(...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5030 CPDF_Array* pRange = m_pLinearizedDict->GetArrayBy("H"); | 4084 CPDF_Array* pRange = m_pLinearizedDict->GetArrayBy("H"); |
5031 if (!pRange) | 4085 if (!pRange) |
5032 return -1; | 4086 return -1; |
5033 | 4087 |
5034 CPDF_Object* pStreamLen = pRange->GetElementValue(1); | 4088 CPDF_Object* pStreamLen = pRange->GetElementValue(1); |
5035 if (!pStreamLen) | 4089 if (!pStreamLen) |
5036 return -1; | 4090 return -1; |
5037 | 4091 |
5038 return pStreamLen->GetInteger(); | 4092 return pStreamLen->GetInteger(); |
5039 } | 4093 } |
OLD | NEW |