1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/include/fpdfapi/fpdf_objects.h" 8 9 #include <algorithm> 10 11 #include "core/include/fpdfapi/fpdf_parser.h" 12 #include "core/include/fxcrt/fx_string.h" 13 #include "third_party/base/stl_util.h" 14 15 namespace { 16 17 const FX_DWORD kBlockSize = 1024; 18 19 } // namespace 20 21 // static 22 int CPDF_Object::s_nCurRefDepth = 0; 23 24 void CPDF_Object::Release() { 25 if (m_ObjNum) { 26 return; 27 } 28 Destroy(); 29 } 30 void CPDF_Object::Destroy() { 31 switch (m_Type) { 32 case PDFOBJ_STRING: 33 delete AsString(); 34 break; 35 case PDFOBJ_NAME: 36 delete AsName(); 37 break; 38 case PDFOBJ_ARRAY: 39 delete AsArray(); 40 break; 41 case PDFOBJ_DICTIONARY: 42 delete AsDictionary(); 43 break; 44 case PDFOBJ_STREAM: 45 delete AsStream(); 46 break; 47 default: 48 delete this; 49 } 50 } 51 CFX_ByteString CPDF_Object::GetString() const { 52 switch (m_Type) { 53 case PDFOBJ_BOOLEAN: 54 return AsBoolean()->m_bValue ? "true" : "false"; 55 case PDFOBJ_NUMBER: 56 return AsNumber()->GetString(); 57 case PDFOBJ_STRING: 58 return AsString()->m_String; 59 case PDFOBJ_NAME: 60 return AsName()->m_Name; 61 case PDFOBJ_REFERENCE: { 62 const CPDF_Reference* pRef = AsReference(); 63 if (!pRef->m_pObjList) 64 break; 65 66 CPDF_Object* pObj = 67 pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr); 68 return pObj ? pObj->GetString() : CFX_ByteString(); 69 } 70 } 71 return CFX_ByteString(); 72 } 73 CFX_ByteStringC CPDF_Object::GetConstString() const { 74 switch (m_Type) { 75 case PDFOBJ_STRING: { 76 CFX_ByteString str = AsString()->m_String; 77 return CFX_ByteStringC((const uint8_t*)str, str.GetLength()); 78 } 79 case PDFOBJ_NAME: { 80 CFX_ByteString name = AsName()->m_Name; 81 return CFX_ByteStringC((const uint8_t*)name, name.GetLength()); 82 } 83 case PDFOBJ_REFERENCE: { 84 const CPDF_Reference* pRef = AsReference(); 85 if (!pRef->m_pObjList) 86 break; 87 88 CPDF_Object* pObj = 89 pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr); 90 return pObj ? pObj->GetConstString() : CFX_ByteStringC(); 91 } 92 } 93 return CFX_ByteStringC(); 94 } 95 96 FX_FLOAT CPDF_Object::GetNumber() const { 97 switch (m_Type) { 98 case PDFOBJ_NUMBER: 99 return AsNumber()->GetNumber(); 100 case PDFOBJ_REFERENCE: { 101 const CPDF_Reference* pRef = AsReference(); 102 if (!pRef->m_pObjList) 103 break; 104 105 CPDF_Object* pObj = 106 pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr); 107 return pObj ? pObj->GetNumber() : 0; 108 } 109 } 110 return 0; 111 } 112 113 FX_FLOAT CPDF_Object::GetNumber16() const { 114 return GetNumber(); 115 } 116 117 int CPDF_Object::GetInteger() const { 118 CFX_AutoRestorer<int> restorer(&s_nCurRefDepth); 119 if (++s_nCurRefDepth > kObjectRefMaxDepth) 120 return 0; 121 122 switch (m_Type) { 123 case PDFOBJ_BOOLEAN: 124 return AsBoolean()->m_bValue; 125 case PDFOBJ_NUMBER: 126 return AsNumber()->GetInteger(); 127 case PDFOBJ_REFERENCE: { 128 const CPDF_Reference* pRef = AsReference(); 129 PARSE_CONTEXT context; 130 FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT)); 131 if (!pRef->m_pObjList) 132 return 0; 133 134 CPDF_Object* pObj = 135 pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), &context); 136 return pObj ? pObj->GetInteger() : 0; 137 } 138 } 139 return 0; 140 } 141 142 CPDF_Dictionary* CPDF_Object::GetDict() const { 143 switch (m_Type) { 144 case PDFOBJ_DICTIONARY: 145 // The method should be made non-const if we want to not be const. 146 // See bug #234. 147 return const_cast<CPDF_Dictionary*>(AsDictionary()); 148 case PDFOBJ_STREAM: 149 return AsStream()->GetDict(); 150 case PDFOBJ_REFERENCE: { 151 const CPDF_Reference* pRef = AsReference(); 152 CPDF_IndirectObjectHolder* pIndirect = pRef->GetObjList(); 153 if (!pIndirect) 154 return nullptr; 155 CPDF_Object* pObj = 156 pIndirect->GetIndirectObject(pRef->GetRefObjNum(), nullptr); 157 if (!pObj || (pObj == this)) 158 return nullptr; 159 return pObj->GetDict(); 160 } 161 default: 162 return nullptr; 163 } 164 } 165 166 CPDF_Array* CPDF_Object::GetArray() const { 167 // The method should be made non-const if we want to not be const. 168 // See bug #234. 169 return const_cast<CPDF_Array*>(AsArray()); 170 } 171 172 void CPDF_Object::SetString(const CFX_ByteString& str) { 173 switch (m_Type) { 174 case PDFOBJ_BOOLEAN: 175 AsBoolean()->m_bValue = (str == "true"); 176 return; 177 case PDFOBJ_NUMBER: 178 AsNumber()->SetString(str); 179 return; 180 case PDFOBJ_STRING: 181 AsString()->m_String = str; 182 return; 183 case PDFOBJ_NAME: 184 AsName()->m_Name = str; 185 return; 186 } 187 ASSERT(FALSE); 188 } 189 int CPDF_Object::GetDirectType() const { 190 const CPDF_Reference* pRef = AsReference(); 191 if (!pRef) 192 return m_Type; 193 return pRef->m_pObjList->GetIndirectType(pRef->GetRefObjNum()); 194 } 195 FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const { 196 if (this == pOther) 197 return TRUE; 198 if (!pOther) 199 return FALSE; 200 if (pOther->m_Type != m_Type) { 201 if (IsReference() && GetDirect()) 202 return GetDirect()->IsIdentical(pOther); 203 if (pOther->IsReference()) 204 return IsIdentical(pOther->GetDirect()); 205 return FALSE; 206 } 207 switch (m_Type) { 208 case PDFOBJ_BOOLEAN: 209 return AsBoolean()->Identical(pOther->AsBoolean()); 210 case PDFOBJ_NUMBER: 211 return AsNumber()->Identical(pOther->AsNumber()); 212 case PDFOBJ_STRING: 213 return AsString()->Identical(pOther->AsString()); 214 case PDFOBJ_NAME: 215 return AsName()->Identical(pOther->AsName()); 216 case PDFOBJ_ARRAY: 217 return AsArray()->Identical(pOther->AsArray()); 218 case PDFOBJ_DICTIONARY: 219 return AsDictionary()->Identical(pOther->AsDictionary()); 220 case PDFOBJ_NULL: 221 return TRUE; 222 case PDFOBJ_STREAM: 223 return AsStream()->Identical(pOther->AsStream()); 224 case PDFOBJ_REFERENCE: 225 return AsReference()->Identical(pOther->AsReference()); 226 } 227 return FALSE; 228 } 229 230 CPDF_Object* CPDF_Object::GetDirect() const { 231 const CPDF_Reference* pRef = AsReference(); 232 if (!pRef) 233 return const_cast<CPDF_Object*>(this); 234 if (!pRef->m_pObjList) 235 return nullptr; 236 return pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), nullptr); 237 } 238 239 CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const { 240 std::set<FX_DWORD> visited; 241 return CloneInternal(bDirect, &visited); 242 } 243 CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect, 244 std::set<FX_DWORD>* visited) const { 245 switch (m_Type) { 246 case PDFOBJ_BOOLEAN: 247 return new CPDF_Boolean(AsBoolean()->m_bValue); 248 case PDFOBJ_NUMBER: { 249 const CPDF_Number* pThis = AsNumber(); 250 return new CPDF_Number(pThis->m_bInteger ? pThis->m_Integer 251 : pThis->m_Float); 252 } 253 case PDFOBJ_STRING: { 254 const CPDF_String* pString = AsString(); 255 return new CPDF_String(pString->m_String, pString->IsHex()); 256 } 257 case PDFOBJ_NAME: 258 return new CPDF_Name(AsName()->m_Name); 259 case PDFOBJ_ARRAY: { 260 CPDF_Array* pCopy = new CPDF_Array(); 261 const CPDF_Array* pThis = AsArray(); 262 int n = pThis->GetCount(); 263 for (int i = 0; i < n; i++) { 264 CPDF_Object* value = pThis->m_Objects.GetAt(i); 265 pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited)); 266 } 267 return pCopy; 268 } 269 case PDFOBJ_DICTIONARY: { 270 CPDF_Dictionary* pCopy = new CPDF_Dictionary(); 271 const CPDF_Dictionary* pThis = AsDictionary(); 272 for (const auto& it : *pThis) { 273 pCopy->m_Map.insert(std::make_pair( 274 it.first, it.second->CloneInternal(bDirect, visited))); 275 } 276 return pCopy; 277 } 278 case PDFOBJ_NULL: { 279 return new CPDF_Null; 280 } 281 case PDFOBJ_STREAM: { 282 const CPDF_Stream* pThis = AsStream(); 283 CPDF_StreamAcc acc; 284 acc.LoadAllData(pThis, TRUE); 285 FX_DWORD streamSize = acc.GetSize(); 286 CPDF_Dictionary* pDict = pThis->GetDict(); 287 if (pDict) { 288 pDict = ToDictionary(pDict->CloneInternal(bDirect, visited)); 289 } 290 return new CPDF_Stream(acc.DetachData(), streamSize, pDict); 291 } 292 case PDFOBJ_REFERENCE: { 293 const CPDF_Reference* pRef = AsReference(); 294 FX_DWORD obj_num = pRef->GetRefObjNum(); 295 if (bDirect && !pdfium::ContainsKey(*visited, obj_num)) { 296 visited->insert(obj_num); 297 auto* pDirect = pRef->GetDirect(); 298 return pDirect ? pDirect->CloneInternal(TRUE, visited) : nullptr; 299 } 300 return new CPDF_Reference(pRef->m_pObjList, obj_num); 301 } 302 } 303 return NULL; 304 } 305 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjectHolder* pDoc) const { 306 if (m_ObjNum) { 307 return new CPDF_Reference(pDoc, m_ObjNum); 308 } 309 return Clone(); 310 } 311 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const { 312 if (const CPDF_String* pString = AsString()) 313 return PDF_DecodeText(pString->m_String, pCharMap); 314 315 if (const CPDF_Stream* pStream = AsStream()) { 316 CPDF_StreamAcc stream; 317 stream.LoadAllData(pStream, FALSE); 318 CFX_WideString result = 319 PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap); 320 return result; 321 } 322 if (const CPDF_Name* pName = AsName()) 323 return PDF_DecodeText(pName->m_Name, pCharMap); 324 return CFX_WideString(); 325 } 326 void CPDF_Object::SetUnicodeText(const FX_WCHAR* pUnicodes, int len) { 327 if (CPDF_String* pString = AsString()) { 328 pString->m_String = PDF_EncodeText(pUnicodes, len); 329 } else if (CPDF_Stream* pStream = AsStream()) { 330 CFX_ByteString result = PDF_EncodeText(pUnicodes, len); 331 pStream->SetData((uint8_t*)result.c_str(), result.GetLength(), FALSE, 332 FALSE); 333 } 334 } 335 336 CPDF_Array* CPDF_Object::AsArray() { 337 return IsArray() ? static_cast<CPDF_Array*>(this) : nullptr; 338 } 339 340 const CPDF_Array* CPDF_Object::AsArray() const { 341 return IsArray() ? static_cast<const CPDF_Array*>(this) : nullptr; 342 } 343 344 CPDF_Boolean* CPDF_Object::AsBoolean() { 345 return IsBoolean() ? static_cast<CPDF_Boolean*>(this) : nullptr; 346 } 347 348 const CPDF_Boolean* CPDF_Object::AsBoolean() const { 349 return IsBoolean() ? static_cast<const CPDF_Boolean*>(this) : nullptr; 350 } 351 352 CPDF_Dictionary* CPDF_Object::AsDictionary() { 353 return IsDictionary() ? static_cast<CPDF_Dictionary*>(this) : nullptr; 354 } 355 356 const CPDF_Dictionary* CPDF_Object::AsDictionary() const { 357 return IsDictionary() ? static_cast<const CPDF_Dictionary*>(this) : nullptr; 358 } 359 360 CPDF_Name* CPDF_Object::AsName() { 361 return IsName() ? static_cast<CPDF_Name*>(this) : nullptr; 362 } 363 364 const CPDF_Name* CPDF_Object::AsName() const { 365 return IsName() ? static_cast<const CPDF_Name*>(this) : nullptr; 366 } 367 368 CPDF_Number* CPDF_Object::AsNumber() { 369 return IsNumber() ? static_cast<CPDF_Number*>(this) : nullptr; 370 } 371 372 const CPDF_Number* CPDF_Object::AsNumber() const { 373 return IsNumber() ? static_cast<const CPDF_Number*>(this) : nullptr; 374 } 375 376 CPDF_Reference* CPDF_Object::AsReference() { 377 return IsReference() ? static_cast<CPDF_Reference*>(this) : nullptr; 378 } 379 380 const CPDF_Reference* CPDF_Object::AsReference() const { 381 return IsReference() ? static_cast<const CPDF_Reference*>(this) : nullptr; 382 } 383 384 CPDF_Stream* CPDF_Object::AsStream() { 385 return IsStream() ? static_cast<CPDF_Stream*>(this) : nullptr; 386 } 387 388 const CPDF_Stream* CPDF_Object::AsStream() const { 389 return IsStream() ? static_cast<const CPDF_Stream*>(this) : nullptr; 390 } 391 392 CPDF_String* CPDF_Object::AsString() { 393 return IsString() ? static_cast<CPDF_String*>(this) : nullptr; 394 } 395 396 const CPDF_String* CPDF_Object::AsString() const { 397 return IsString() ? static_cast<const CPDF_String*>(this) : nullptr; 398 } 399 400 CPDF_Number::CPDF_Number(int value) 401 : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(TRUE), m_Integer(value) {} 402 403 CPDF_Number::CPDF_Number(FX_FLOAT value) 404 : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(FALSE), m_Float(value) {} 405 406 CPDF_Number::CPDF_Number(const CFX_ByteStringC& str) 407 : CPDF_Object(PDFOBJ_NUMBER) { 408 FX_atonum(str, m_bInteger, &m_Integer); 409 } 410 411 void CPDF_Number::SetString(const CFX_ByteStringC& str) { 412 FX_atonum(str, m_bInteger, &m_Integer); 413 } 414 FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const { 415 return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer; 416 } 417 CFX_ByteString CPDF_Number::GetString() const { 418 return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED) 419 : CFX_ByteString::FormatFloat(m_Float); 420 } 421 void CPDF_Number::SetNumber(FX_FLOAT value) { 422 m_bInteger = FALSE; 423 m_Float = value; 424 } 425 CPDF_String::CPDF_String(const CFX_WideString& str) 426 : CPDF_Object(PDFOBJ_STRING), m_bHex(FALSE) { 427 m_String = PDF_EncodeText(str); 428 } 429 CPDF_Array::~CPDF_Array() { 430 int size = m_Objects.GetSize(); 431 CPDF_Object** pList = m_Objects.GetData(); 432 for (int i = 0; i < size; i++) { 433 if (pList[i]) 434 pList[i]->Release(); 435 } 436 } 437 CFX_FloatRect CPDF_Array::GetRect() { 438 CFX_FloatRect rect; 439 if (!IsArray() || m_Objects.GetSize() != 4) 440 return rect; 441 442 rect.left = GetNumber(0); 443 rect.bottom = GetNumber(1); 444 rect.right = GetNumber(2); 445 rect.top = GetNumber(3); 446 return rect; 447 } 448 CFX_Matrix CPDF_Array::GetMatrix() { 449 CFX_Matrix matrix; 450 if (!IsArray() || m_Objects.GetSize() != 6) 451 return matrix; 452 453 matrix.Set(GetNumber(0), GetNumber(1), GetNumber(2), GetNumber(3), 454 GetNumber(4), GetNumber(5)); 455 return matrix; 456 } 457 CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const { 458 if (i >= (FX_DWORD)m_Objects.GetSize()) 459 return nullptr; 460 return m_Objects.GetAt(i); 461 } 462 CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const { 463 if (i >= (FX_DWORD)m_Objects.GetSize()) 464 return nullptr; 465 return m_Objects.GetAt(i)->GetDirect(); 466 } 467 CFX_ByteString CPDF_Array::GetString(FX_DWORD i) const { 468 if (i >= (FX_DWORD)m_Objects.GetSize()) 469 return CFX_ByteString(); 470 return m_Objects.GetAt(i)->GetString(); 471 } 472 CFX_ByteStringC CPDF_Array::GetConstString(FX_DWORD i) const { 473 if (i >= (FX_DWORD)m_Objects.GetSize()) 474 return CFX_ByteStringC(); 475 return m_Objects.GetAt(i)->GetConstString(); 476 } 477 int CPDF_Array::GetInteger(FX_DWORD i) const { 478 if (i >= (FX_DWORD)m_Objects.GetSize()) 479 return 0; 480 return m_Objects.GetAt(i)->GetInteger(); 481 } 482 FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const { 483 if (i >= (FX_DWORD)m_Objects.GetSize()) 484 return 0; 485 return m_Objects.GetAt(i)->GetNumber(); 486 } 487 CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const { 488 CPDF_Object* p = GetElementValue(i); 489 if (!p) 490 return NULL; 491 if (CPDF_Dictionary* pDict = p->AsDictionary()) 492 return pDict; 493 if (CPDF_Stream* pStream = p->AsStream()) 494 return pStream->GetDict(); 495 return NULL; 496 } 497 CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const { 498 return ToStream(GetElementValue(i)); 499 } 500 CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const { 501 return ToArray(GetElementValue(i)); 502 } 503 void CPDF_Array::RemoveAt(FX_DWORD i, int nCount) { 504 if (i >= (FX_DWORD)m_Objects.GetSize()) 505 return; 506 507 if (nCount <= 0 || nCount > m_Objects.GetSize() - i) 508 return; 509 510 for (int j = 0; j < nCount; ++j) { 511 if (CPDF_Object* p = m_Objects.GetAt(i + j)) 512 p->Release(); 513 } 514 m_Objects.RemoveAt(i, nCount); 515 } 516 void CPDF_Array::SetAt(FX_DWORD i, 517 CPDF_Object* pObj, 518 CPDF_IndirectObjectHolder* pObjs) { 519 ASSERT(IsArray()); 520 ASSERT(i < (FX_DWORD)m_Objects.GetSize()); 521 if (i >= (FX_DWORD)m_Objects.GetSize()) 522 return; 523 if (CPDF_Object* pOld = m_Objects.GetAt(i)) 524 pOld->Release(); 525 if (pObj->GetObjNum()) { 526 ASSERT(pObjs); 527 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); 528 } 529 m_Objects.SetAt(i, pObj); 530 } 531 void CPDF_Array::InsertAt(FX_DWORD index, 532 CPDF_Object* pObj, 533 CPDF_IndirectObjectHolder* pObjs) { 534 if (pObj->GetObjNum()) { 535 ASSERT(pObjs); 536 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); 537 } 538 m_Objects.InsertAt(index, pObj); 539 } 540 void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs) { 541 if (pObj->GetObjNum()) { 542 ASSERT(pObjs); 543 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); 544 } 545 m_Objects.Add(pObj); 546 } 547 void CPDF_Array::AddName(const CFX_ByteString& str) { 548 ASSERT(IsArray()); 549 Add(new CPDF_Name(str)); 550 } 551 void CPDF_Array::AddString(const CFX_ByteString& str) { 552 ASSERT(IsArray()); 553 Add(new CPDF_String(str, FALSE)); 554 } 555 void CPDF_Array::AddInteger(int i) { 556 ASSERT(IsArray()); 557 Add(new CPDF_Number(i)); 558 } 559 void CPDF_Array::AddNumber(FX_FLOAT f) { 560 ASSERT(IsArray()); 561 CPDF_Number* pNumber = new CPDF_Number; 562 pNumber->SetNumber(f); 563 Add(pNumber); 564 } 565 void CPDF_Array::AddReference(CPDF_IndirectObjectHolder* pDoc, 566 FX_DWORD objnum) { 567 ASSERT(IsArray()); 568 Add(new CPDF_Reference(pDoc, objnum)); 569 } 570 FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const { 571 if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) { 572 return FALSE; 573 } 574 for (int i = 0; i < m_Objects.GetSize(); i++) { 575 if (!m_Objects[i]->IsIdentical(pOther->m_Objects[i])) 576 return FALSE; 577 } 578 return TRUE; 579 } 580 CPDF_Dictionary::~CPDF_Dictionary() { 581 for (const auto& it : m_Map) { 582 it.second->Release(); 583 } 584 } 585 CPDF_Object* CPDF_Dictionary::GetElement(const CFX_ByteStringC& key) const { 586 auto it = m_Map.find(key); 587 if (it == m_Map.end()) 588 return nullptr; 589 return it->second; 590 } 591 CPDF_Object* CPDF_Dictionary::GetElementValue( 592 const CFX_ByteStringC& key) const { 593 CPDF_Object* p = GetElement(key); 594 return p ? p->GetDirect() : nullptr; 595 } 596 CFX_ByteString CPDF_Dictionary::GetString(const CFX_ByteStringC& key) const { 597 CPDF_Object* p = GetElement(key); 598 if (p) { 599 return p->GetString(); 600 } 601 return CFX_ByteString(); 602 } 603 CFX_ByteStringC CPDF_Dictionary::GetConstString( 604 const CFX_ByteStringC& key) const { 605 CPDF_Object* p = GetElement(key); 606 if (p) { 607 return p->GetConstString(); 608 } 609 return CFX_ByteStringC(); 610 } 611 CFX_WideString CPDF_Dictionary::GetUnicodeText(const CFX_ByteStringC& key, 612 CFX_CharMap* pCharMap) const { 613 CPDF_Object* p = GetElement(key); 614 if (CPDF_Reference* pRef = ToReference(p)) 615 p = pRef->GetDirect(); 616 return p ? p->GetUnicodeText(pCharMap) : CFX_WideString(); 617 } 618 CFX_ByteString CPDF_Dictionary::GetString(const CFX_ByteStringC& key, 619 const CFX_ByteStringC& def) const { 620 CPDF_Object* p = GetElement(key); 621 if (p) { 622 return p->GetString(); 623 } 624 return CFX_ByteString(def); 625 } 626 CFX_ByteStringC CPDF_Dictionary::GetConstString( 627 const CFX_ByteStringC& key, 628 const CFX_ByteStringC& def) const { 629 CPDF_Object* p = GetElement(key); 630 if (p) { 631 return p->GetConstString(); 632 } 633 return CFX_ByteStringC(def); 634 } 635 int CPDF_Dictionary::GetInteger(const CFX_ByteStringC& key) const { 636 CPDF_Object* p = GetElement(key); 637 if (p) { 638 return p->GetInteger(); 639 } 640 return 0; 641 } 642 int CPDF_Dictionary::GetInteger(const CFX_ByteStringC& key, int def) const { 643 CPDF_Object* p = GetElement(key); 644 if (p) { 645 return p->GetInteger(); 646 } 647 return def; 648 } 649 FX_FLOAT CPDF_Dictionary::GetNumber(const CFX_ByteStringC& key) const { 650 CPDF_Object* p = GetElement(key); 651 if (p) { 652 return p->GetNumber(); 653 } 654 return 0; 655 } 656 FX_BOOL CPDF_Dictionary::GetBoolean(const CFX_ByteStringC& key, 657 FX_BOOL bDefault) const { 658 CPDF_Object* p = GetElement(key); 659 if (ToBoolean(p)) 660 return p->GetInteger(); 661 return bDefault; 662 } 663 CPDF_Dictionary* CPDF_Dictionary::GetDict(const CFX_ByteStringC& key) const { 664 CPDF_Object* p = GetElementValue(key); 665 if (!p) 666 return nullptr; 667 if (CPDF_Dictionary* pDict = p->AsDictionary()) 668 return pDict; 669 if (CPDF_Stream* pStream = p->AsStream()) 670 return pStream->GetDict(); 671 return nullptr; 672 } 673 CPDF_Array* CPDF_Dictionary::GetArray(const CFX_ByteStringC& key) const { 674 return ToArray(GetElementValue(key)); 675 } 676 CPDF_Stream* CPDF_Dictionary::GetStream(const CFX_ByteStringC& key) const { 677 return ToStream(GetElementValue(key)); 678 } 679 CFX_FloatRect CPDF_Dictionary::GetRect(const CFX_ByteStringC& key) const { 680 CFX_FloatRect rect; 681 CPDF_Array* pArray = GetArray(key); 682 if (pArray) 683 rect = pArray->GetRect(); 684 return rect; 685 } 686 CFX_Matrix CPDF_Dictionary::GetMatrix(const CFX_ByteStringC& key) const { 687 CFX_Matrix matrix; 688 CPDF_Array* pArray = GetArray(key); 689 if (pArray) 690 matrix = pArray->GetMatrix(); 691 return matrix; 692 } 693 FX_BOOL CPDF_Dictionary::KeyExist(const CFX_ByteStringC& key) const { 694 return pdfium::ContainsKey(m_Map, key); 695 } 696 697 void CPDF_Dictionary::SetAt(const CFX_ByteStringC& key, CPDF_Object* pObj) { 698 ASSERT(IsDictionary()); 699 // Avoid 2 constructions of CFX_ByteString. 700 CFX_ByteString key_bytestring = key; 701 auto it = m_Map.find(key_bytestring); 702 if (it == m_Map.end()) { 703 if (pObj) { 704 m_Map.insert(std::make_pair(key_bytestring, pObj)); 705 } 706 return; 707 } 708 709 if (it->second == pObj) 710 return; 711 it->second->Release(); 712 713 if (pObj) 714 it->second = pObj; 715 else 716 m_Map.erase(it); 717 } 718 void CPDF_Dictionary::RemoveAt(const CFX_ByteStringC& key) { 719 ASSERT(m_Type == PDFOBJ_DICTIONARY); 720 auto it = m_Map.find(key); 721 if (it == m_Map.end()) 722 return; 723 724 it->second->Release(); 725 m_Map.erase(it); 726 } 727 void CPDF_Dictionary::ReplaceKey(const CFX_ByteStringC& oldkey, 728 const CFX_ByteStringC& newkey) { 729 ASSERT(m_Type == PDFOBJ_DICTIONARY); 730 auto old_it = m_Map.find(oldkey); 731 if (old_it == m_Map.end()) 732 return; 733 734 // Avoid 2 constructions of CFX_ByteString. 735 CFX_ByteString newkey_bytestring = newkey; 736 auto new_it = m_Map.find(newkey_bytestring); 737 if (new_it == old_it) 738 return; 739 740 if (new_it != m_Map.end()) { 741 new_it->second->Release(); 742 new_it->second = old_it->second; 743 } else { 744 m_Map.insert(std::make_pair(newkey_bytestring, old_it->second)); 745 } 746 m_Map.erase(old_it); 747 } 748 FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const { 749 if (!pOther) { 750 return FALSE; 751 } 752 if (m_Map.size() != pOther->m_Map.size()) { 753 return FALSE; 754 } 755 for (const auto& it : m_Map) { 756 const CFX_ByteString& key = it.first; 757 if (!it.second->IsIdentical(pOther->GetElement(key))) 758 return FALSE; 759 } 760 return TRUE; 761 } 762 void CPDF_Dictionary::SetAtInteger(const CFX_ByteStringC& key, int i) { 763 SetAt(key, new CPDF_Number(i)); 764 } 765 void CPDF_Dictionary::SetAtName(const CFX_ByteStringC& key, 766 const CFX_ByteString& name) { 767 SetAt(key, new CPDF_Name(name)); 768 } 769 void CPDF_Dictionary::SetAtString(const CFX_ByteStringC& key, 770 const CFX_ByteString& str) { 771 SetAt(key, new CPDF_String(str, FALSE)); 772 } 773 void CPDF_Dictionary::SetAtReference(const CFX_ByteStringC& key, 774 CPDF_IndirectObjectHolder* pDoc, 775 FX_DWORD objnum) { 776 SetAt(key, new CPDF_Reference(pDoc, objnum)); 777 } 778 void CPDF_Dictionary::AddReference(const CFX_ByteStringC& key, 779 CPDF_IndirectObjectHolder* pDoc, 780 FX_DWORD objnum) { 781 SetAt(key, new CPDF_Reference(pDoc, objnum)); 782 } 783 void CPDF_Dictionary::SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f) { 784 CPDF_Number* pNumber = new CPDF_Number; 785 pNumber->SetNumber(f); 786 SetAt(key, pNumber); 787 } 788 void CPDF_Dictionary::SetAtBoolean(const CFX_ByteStringC& key, FX_BOOL bValue) { 789 SetAt(key, new CPDF_Boolean(bValue)); 790 } 791 void CPDF_Dictionary::SetAtRect(const CFX_ByteStringC& key, 792 const CFX_FloatRect& rect) { 793 CPDF_Array* pArray = new CPDF_Array; 794 pArray->AddNumber(rect.left); 795 pArray->AddNumber(rect.bottom); 796 pArray->AddNumber(rect.right); 797 pArray->AddNumber(rect.top); 798 SetAt(key, pArray); 799 } 800 void CPDF_Dictionary::SetAtMatrix(const CFX_ByteStringC& key, 801 const CFX_Matrix& matrix) { 802 CPDF_Array* pArray = new CPDF_Array; 803 pArray->AddNumber16(matrix.a); 804 pArray->AddNumber16(matrix.b); 805 pArray->AddNumber16(matrix.c); 806 pArray->AddNumber16(matrix.d); 807 pArray->AddNumber(matrix.e); 808 pArray->AddNumber(matrix.f); 809 SetAt(key, pArray); 810 } 811 CPDF_Stream::CPDF_Stream(uint8_t* pData, FX_DWORD size, CPDF_Dictionary* pDict) 812 : CPDF_Object(PDFOBJ_STREAM), 813 m_pDict(pDict), 814 m_dwSize(size), 815 m_GenNum(kMemoryBasedGenNum), 816 m_pDataBuf(pData) {} 817 818 CPDF_Stream::~CPDF_Stream() { 819 if (IsMemoryBased()) 820 FX_Free(m_pDataBuf); 821 822 if (m_pDict) 823 m_pDict->Release(); 824 } 825 826 void CPDF_Stream::InitStreamInternal(CPDF_Dictionary* pDict) { 827 if (pDict) { 828 if (m_pDict) 829 m_pDict->Release(); 830 m_pDict = pDict; 831 } 832 if (IsMemoryBased()) 833 FX_Free(m_pDataBuf); 834 835 m_GenNum = 0; 836 m_pFile = nullptr; 837 } 838 839 void CPDF_Stream::InitStream(uint8_t* pData, 840 FX_DWORD size, 841 CPDF_Dictionary* pDict) { 842 InitStreamInternal(pDict); 843 m_GenNum = kMemoryBasedGenNum; 844 m_pDataBuf = FX_Alloc(uint8_t, size); 845 if (pData) { 846 FXSYS_memcpy(m_pDataBuf, pData, size); 847 } 848 m_dwSize = size; 849 if (m_pDict) { 850 m_pDict->SetAtInteger("Length", size); 851 } 852 } 853 void CPDF_Stream::SetData(const uint8_t* pData, 854 FX_DWORD size, 855 FX_BOOL bCompressed, 856 FX_BOOL bKeepBuf) { 857 if (IsMemoryBased()) 858 FX_Free(m_pDataBuf); 859 m_GenNum = kMemoryBasedGenNum; 860 861 if (bKeepBuf) { 862 m_pDataBuf = (uint8_t*)pData; 863 } else { 864 m_pDataBuf = FX_Alloc(uint8_t, size); 865 if (pData) { 866 FXSYS_memcpy(m_pDataBuf, pData, size); 867 } 868 } 869 m_dwSize = size; 870 if (!m_pDict) 871 m_pDict = new CPDF_Dictionary; 872 m_pDict->SetAtInteger("Length", size); 873 if (!bCompressed) { 874 m_pDict->RemoveAt("Filter"); 875 m_pDict->RemoveAt("DecodeParms"); 876 } 877 } 878 FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset, 879 uint8_t* buf, 880 FX_DWORD size) const { 881 if (!IsMemoryBased() && m_pFile) 882 return m_pFile->ReadBlock(buf, offset, size); 883 884 if (m_pDataBuf) 885 FXSYS_memcpy(buf, m_pDataBuf + offset, size); 886 return TRUE; 887 } 888 void CPDF_Stream::InitStreamFromFile(IFX_FileRead* pFile, 889 CPDF_Dictionary* pDict) { 890 InitStreamInternal(pDict); 891 m_pFile = pFile; 892 m_dwSize = (FX_DWORD)pFile->GetSize(); 893 if (m_pDict) { 894 m_pDict->SetAtInteger("Length", m_dwSize); 895 } 896 } 897 898 FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const { 899 if (!m_pDict) 900 return !pOther->m_pDict; 901 902 if (!m_pDict->Identical(pOther->m_pDict)) 903 return FALSE; 904 905 if (m_dwSize != pOther->m_dwSize) 906 return FALSE; 907 908 if (!IsMemoryBased() && !pOther->IsMemoryBased()) { 909 if (m_pFile == pOther->m_pFile && !m_pFile) 910 return TRUE; 911 912 if (!m_pFile || !pOther->m_pFile) 913 return FALSE; 914 915 uint8_t srcBuf[kBlockSize]; 916 uint8_t destBuf[kBlockSize]; 917 FX_DWORD size = m_dwSize; 918 if (m_pFile == pOther->m_pFile) 919 return TRUE; 920 921 FX_DWORD offset = 0; 922 while (size > 0) { 923 FX_DWORD actualSize = std::min(size, kBlockSize); 924 m_pFile->ReadBlock(srcBuf, offset, actualSize); 925 pOther->m_pFile->ReadBlock(destBuf, offset, actualSize); 926 if (FXSYS_memcmp(srcBuf, destBuf, actualSize) != 0) 927 return FALSE; 928 929 size -= actualSize; 930 offset += actualSize; 931 } 932 return TRUE; 933 } 934 935 if (!IsMemoryBased() || !pOther->IsMemoryBased()) { 936 IFX_FileRead* pFile = nullptr; 937 uint8_t* pBuf = nullptr; 938 if (!pOther->IsMemoryBased()) { 939 pFile = pOther->m_pFile; 940 pBuf = m_pDataBuf; 941 } else if (!IsMemoryBased()) { 942 pFile = m_pFile; 943 pBuf = pOther->m_pDataBuf; 944 } 945 if (!pBuf) 946 return FALSE; 947 948 uint8_t srcBuf[kBlockSize]; 949 FX_DWORD size = m_dwSize; 950 FX_DWORD offset = 0; 951 while (size > 0) { 952 FX_DWORD actualSize = std::min(size, kBlockSize); 953 pFile->ReadBlock(srcBuf, offset, actualSize); 954 if (FXSYS_memcmp(srcBuf, pBuf, actualSize) != 0) 955 return FALSE; 956 957 pBuf += actualSize; 958 size -= actualSize; 959 offset += actualSize; 960 } 961 return TRUE; 962 } 963 return FXSYS_memcmp(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0; 964 } 965 966 CPDF_StreamAcc::CPDF_StreamAcc() { 967 m_bNewBuf = FALSE; 968 m_pData = NULL; 969 m_dwSize = 0; 970 m_pImageParam = NULL; 971 m_pStream = NULL; 972 m_pSrcData = NULL; 973 } 974 void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, 975 FX_BOOL bRawAccess, 976 FX_DWORD estimated_size, 977 FX_BOOL bImageAcc) { 978 if (!pStream) 979 return; 980 981 m_pStream = pStream; 982 if (pStream->IsMemoryBased() && 983 (!pStream->GetDict()->KeyExist("Filter") || bRawAccess)) { 984 m_dwSize = pStream->m_dwSize; 985 m_pData = (uint8_t*)pStream->m_pDataBuf; 986 return; 987 } 988 uint8_t* pSrcData; 989 FX_DWORD dwSrcSize = pStream->m_dwSize; 990 if (dwSrcSize == 0) 991 return; 992 993 if (!pStream->IsMemoryBased()) { 994 pSrcData = m_pSrcData = FX_Alloc(uint8_t, dwSrcSize); 995 if (!pStream->ReadRawData(0, pSrcData, dwSrcSize)) 996 return; 997 } else { 998 pSrcData = pStream->m_pDataBuf; 999 } 1000 uint8_t* pDecryptedData = pSrcData; 1001 FX_DWORD dwDecryptedSize = dwSrcSize; 1002 if (!pStream->GetDict()->KeyExist("Filter") || bRawAccess) { 1003 m_pData = pDecryptedData; 1004 m_dwSize = dwDecryptedSize; 1005 } else { 1006 FX_BOOL bRet = PDF_DataDecode( 1007 pDecryptedData, dwDecryptedSize, m_pStream->GetDict(), m_pData, 1008 m_dwSize, m_ImageDecoder, m_pImageParam, estimated_size, bImageAcc); 1009 if (!bRet) { 1010 m_pData = pDecryptedData; 1011 m_dwSize = dwDecryptedSize; 1012 } 1013 } 1014 if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) { 1015 FX_Free(pSrcData); 1016 } 1017 if (pDecryptedData != pSrcData && pDecryptedData != m_pData) { 1018 FX_Free(pDecryptedData); 1019 } 1020 m_pSrcData = NULL; 1021 m_bNewBuf = m_pData != pStream->m_pDataBuf; 1022 } 1023 CPDF_StreamAcc::~CPDF_StreamAcc() { 1024 if (m_bNewBuf) { 1025 FX_Free(m_pData); 1026 } 1027 FX_Free(m_pSrcData); 1028 } 1029 const uint8_t* CPDF_StreamAcc::GetData() const { 1030 if (m_bNewBuf) { 1031 return m_pData; 1032 } 1033 if (!m_pStream) { 1034 return NULL; 1035 } 1036 return m_pStream->m_pDataBuf; 1037 } 1038 FX_DWORD CPDF_StreamAcc::GetSize() const { 1039 if (m_bNewBuf) { 1040 return m_dwSize; 1041 } 1042 if (!m_pStream) { 1043 return 0; 1044 } 1045 return m_pStream->m_dwSize; 1046 } 1047 uint8_t* CPDF_StreamAcc::DetachData() { 1048 if (m_bNewBuf) { 1049 uint8_t* p = m_pData; 1050 m_pData = NULL; 1051 m_dwSize = 0; 1052 return p; 1053 } 1054 uint8_t* p = FX_Alloc(uint8_t, m_dwSize); 1055 FXSYS_memcpy(p, m_pData, m_dwSize); 1056 return p; 1057 } 1058 void CPDF_Reference::SetRef(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum) { 1059 m_pObjList = pDoc; 1060 m_RefObjNum = objnum; 1061 } 1062 CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder(CPDF_Parser* pParser) 1063 : m_pParser(pParser), m_LastObjNum(0) { 1064 if (pParser) 1065 m_LastObjNum = m_pParser->GetLastObjNum(); 1066 } 1067 CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() { 1068 for (const auto& pair : m_IndirectObjs) { 1069 pair.second->Destroy(); 1070 } 1071 } 1072 CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject( 1073 FX_DWORD objnum, 1074 PARSE_CONTEXT* pContext) { 1075 if (objnum == 0) 1076 return nullptr; 1077 1078 auto it = m_IndirectObjs.find(objnum); 1079 if (it != m_IndirectObjs.end()) 1080 return it->second->GetObjNum() != -1 ? it->second : nullptr; 1081 1082 if (!m_pParser) 1083 return nullptr; 1084 1085 CPDF_Object* pObj = m_pParser->ParseIndirectObject(this, objnum, pContext); 1086 if (!pObj) 1087 return nullptr; 1088 1089 pObj->m_ObjNum = objnum; 1090 m_LastObjNum = std::max(m_LastObjNum, objnum); 1091 if (m_IndirectObjs[objnum]) 1092 m_IndirectObjs[objnum]->Destroy(); 1093 1094 m_IndirectObjs[objnum] = pObj; 1095 return pObj; 1096 } 1097 int CPDF_IndirectObjectHolder::GetIndirectType(FX_DWORD objnum) { 1098 auto it = m_IndirectObjs.find(objnum); 1099 if (it != m_IndirectObjs.end()) 1100 return it->second->GetType(); 1101 1102 if (!m_pParser) 1103 return 0; 1104 1105 PARSE_CONTEXT context; 1106 FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT)); 1107 context.m_Flags = PDFPARSE_TYPEONLY; 1108 return (int)(uintptr_t)m_pParser->ParseIndirectObject(this, objnum, &context); 1109 } 1110 FX_DWORD CPDF_IndirectObjectHolder::AddIndirectObject(CPDF_Object* pObj) { 1111 if (pObj->m_ObjNum) { 1112 return pObj->m_ObjNum; 1113 } 1114 m_LastObjNum++; 1115 m_IndirectObjs[m_LastObjNum] = pObj; 1116 pObj->m_ObjNum = m_LastObjNum; 1117 return m_LastObjNum; 1118 } 1119 void CPDF_IndirectObjectHolder::ReleaseIndirectObject(FX_DWORD objnum) { 1120 auto it = m_IndirectObjs.find(objnum); 1121 if (it == m_IndirectObjs.end() || it->second->GetObjNum() == -1) 1122 return; 1123 it->second->Destroy(); 1124 m_IndirectObjs.erase(it); 1125 } 1126 FX_BOOL CPDF_IndirectObjectHolder::InsertIndirectObject(FX_DWORD objnum, 1127 CPDF_Object* pObj) { 1128 if (!objnum || !pObj) 1129 return FALSE; 1130 auto it = m_IndirectObjs.find(objnum); 1131 if (it != m_IndirectObjs.end()) { 1132 if (pObj->GetGenNum() <= it->second->GetGenNum()) { 1133 pObj->Destroy(); 1134 return FALSE; 1135 } 1136 it->second->Destroy(); 1137 } 1138 pObj->m_ObjNum = objnum; 1139 m_IndirectObjs[objnum] = pObj; 1140 m_LastObjNum = std::max(m_LastObjNum, objnum); 1141 return TRUE; 1142 } 1143