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 #ifndef CORE_INCLUDE_FPDFAPI_FPDF_OBJECTS_H_ 8 #define CORE_INCLUDE_FPDFAPI_FPDF_OBJECTS_H_ 9 10 #include <map> 11 #include <set> 12 13 #include "core/include/fxcrt/fx_coordinates.h" 14 #include "core/include/fxcrt/fx_system.h" 15 16 class CPDF_Array; 17 class CPDF_Boolean; 18 class CPDF_CryptoHandler; 19 class CPDF_Dictionary; 20 class CPDF_Document; 21 class CPDF_IndirectObjectHolder; 22 class CPDF_Name; 23 class CPDF_Null; 24 class CPDF_Number; 25 class CPDF_Parser; 26 class CPDF_Reference; 27 class CPDF_Stream; 28 class CPDF_StreamAcc; 29 class CPDF_StreamFilter; 30 class CPDF_String; 31 class IFX_FileRead; 32 struct PARSE_CONTEXT; 33 34 #define PDFOBJ_INVALID 0 35 #define PDFOBJ_BOOLEAN 1 36 #define PDFOBJ_NUMBER 2 37 #define PDFOBJ_STRING 3 38 #define PDFOBJ_NAME 4 39 #define PDFOBJ_ARRAY 5 40 #define PDFOBJ_DICTIONARY 6 41 #define PDFOBJ_STREAM 7 42 #define PDFOBJ_NULL 8 43 #define PDFOBJ_REFERENCE 9 44 45 class CPDF_Object { 46 public: 47 int GetType() const { return m_Type; } 48 49 FX_DWORD GetObjNum() const { return m_ObjNum; } 50 51 FX_DWORD GetGenNum() const { return m_GenNum; } 52 53 FX_BOOL IsIdentical(CPDF_Object* pObj) const; 54 55 CPDF_Object* Clone(FX_BOOL bDirect = FALSE) const; 56 57 CPDF_Object* CloneRef(CPDF_IndirectObjectHolder* pObjs) const; 58 59 CPDF_Object* GetDirect() const; 60 61 void Release(); 62 63 CFX_ByteString GetString() const; 64 65 CFX_ByteStringC GetConstString() const; 66 67 CFX_WideString GetUnicodeText(CFX_CharMap* pCharMap = NULL) const; 68 FX_FLOAT GetNumber() const; 69 70 FX_FLOAT GetNumber16() const; 71 72 int GetInteger() const; 73 74 CPDF_Dictionary* GetDict() const; 75 76 CPDF_Array* GetArray() const; 77 78 void SetString(const CFX_ByteString& str); 79 80 void SetUnicodeText(const FX_WCHAR* pUnicodes, int len = -1); 81 82 int GetDirectType() const; 83 84 FX_BOOL IsModified() const { return FALSE; } 85 86 bool IsArray() const { return m_Type == PDFOBJ_ARRAY; } 87 bool IsBoolean() const { return m_Type == PDFOBJ_BOOLEAN; } 88 bool IsDictionary() const { return m_Type == PDFOBJ_DICTIONARY; } 89 bool IsName() const { return m_Type == PDFOBJ_NAME; } 90 bool IsNumber() const { return m_Type == PDFOBJ_NUMBER; } 91 bool IsReference() const { return m_Type == PDFOBJ_REFERENCE; } 92 bool IsStream() const { return m_Type == PDFOBJ_STREAM; } 93 bool IsString() const { return m_Type == PDFOBJ_STRING; } 94 95 CPDF_Array* AsArray(); 96 const CPDF_Array* AsArray() const; 97 98 CPDF_Boolean* AsBoolean(); 99 const CPDF_Boolean* AsBoolean() const; 100 101 CPDF_Dictionary* AsDictionary(); 102 const CPDF_Dictionary* AsDictionary() const; 103 104 CPDF_Name* AsName(); 105 const CPDF_Name* AsName() const; 106 107 CPDF_Number* AsNumber(); 108 const CPDF_Number* AsNumber() const; 109 110 CPDF_Reference* AsReference(); 111 const CPDF_Reference* AsReference() const; 112 113 CPDF_Stream* AsStream(); 114 const CPDF_Stream* AsStream() const; 115 116 CPDF_String* AsString(); 117 const CPDF_String* AsString() const; 118 119 protected: 120 explicit CPDF_Object(FX_DWORD type) 121 : m_Type(type), m_ObjNum(0), m_GenNum(0) {} 122 ~CPDF_Object() {} 123 void Destroy(); 124 125 static const int kObjectRefMaxDepth = 128; 126 static int s_nCurRefDepth; 127 FX_DWORD m_Type; 128 FX_DWORD m_ObjNum; 129 FX_DWORD m_GenNum; 130 131 friend class CPDF_IndirectObjectHolder; 132 friend class CPDF_Parser; 133 friend class CPDF_SyntaxParser; 134 135 private: 136 CPDF_Object(const CPDF_Object& src) {} 137 CPDF_Object* CloneInternal(FX_BOOL bDirect, 138 std::set<FX_DWORD>* visited) const; 139 }; 140 class CPDF_Boolean : public CPDF_Object { 141 public: 142 CPDF_Boolean() : CPDF_Object(PDFOBJ_BOOLEAN), m_bValue(false) {} 143 explicit CPDF_Boolean(FX_BOOL value) 144 : CPDF_Object(PDFOBJ_BOOLEAN), m_bValue(value) {} 145 146 FX_BOOL Identical(CPDF_Boolean* pOther) const { 147 return m_bValue == pOther->m_bValue; 148 } 149 150 protected: 151 FX_BOOL m_bValue; 152 friend class CPDF_Object; 153 }; 154 inline CPDF_Boolean* ToBoolean(CPDF_Object* obj) { 155 return obj ? obj->AsBoolean() : nullptr; 156 } 157 inline const CPDF_Boolean* ToBoolean(const CPDF_Object* obj) { 158 return obj ? obj->AsBoolean() : nullptr; 159 } 160 161 class CPDF_Number : public CPDF_Object { 162 public: 163 CPDF_Number() : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(TRUE), m_Integer(0) {} 164 165 explicit CPDF_Number(int value); 166 167 explicit CPDF_Number(FX_FLOAT value); 168 169 explicit CPDF_Number(const CFX_ByteStringC& str); 170 171 FX_BOOL Identical(CPDF_Number* pOther) const; 172 173 CFX_ByteString GetString() const; 174 175 void SetString(const CFX_ByteStringC& str); 176 177 FX_BOOL IsInteger() const { return m_bInteger; } 178 179 int GetInteger() const { return m_bInteger ? m_Integer : (int)m_Float; } 180 181 FX_FLOAT GetNumber() const { 182 return m_bInteger ? (FX_FLOAT)m_Integer : m_Float; 183 } 184 185 void SetNumber(FX_FLOAT value); 186 187 FX_FLOAT GetNumber16() const { return GetNumber(); } 188 189 FX_FLOAT GetFloat() const { 190 return m_bInteger ? (FX_FLOAT)m_Integer : m_Float; 191 } 192 193 protected: 194 FX_BOOL m_bInteger; 195 196 union { 197 int m_Integer; 198 199 FX_FLOAT m_Float; 200 }; 201 friend class CPDF_Object; 202 }; 203 inline CPDF_Number* ToNumber(CPDF_Object* obj) { 204 return obj ? obj->AsNumber() : nullptr; 205 } 206 inline const CPDF_Number* ToNumber(const CPDF_Object* obj) { 207 return obj ? obj->AsNumber() : nullptr; 208 } 209 210 class CPDF_String : public CPDF_Object { 211 public: 212 CPDF_String() : CPDF_Object(PDFOBJ_STRING), m_bHex(FALSE) {} 213 214 CPDF_String(const CFX_ByteString& str, FX_BOOL bHex) 215 : CPDF_Object(PDFOBJ_STRING), m_String(str), m_bHex(bHex) {} 216 217 explicit CPDF_String(const CFX_WideString& str); 218 219 CFX_ByteString& GetString() { return m_String; } 220 221 FX_BOOL Identical(CPDF_String* pOther) const { 222 return m_String == pOther->m_String; 223 } 224 225 FX_BOOL IsHex() const { return m_bHex; } 226 227 protected: 228 CFX_ByteString m_String; 229 230 FX_BOOL m_bHex; 231 friend class CPDF_Object; 232 }; 233 inline CPDF_String* ToString(CPDF_Object* obj) { 234 return obj ? obj->AsString() : nullptr; 235 } 236 inline const CPDF_String* ToString(const CPDF_Object* obj) { 237 return obj ? obj->AsString() : nullptr; 238 } 239 240 class CPDF_Name : public CPDF_Object { 241 public: 242 explicit CPDF_Name(const CFX_ByteString& str) 243 : CPDF_Object(PDFOBJ_NAME), m_Name(str) {} 244 explicit CPDF_Name(const CFX_ByteStringC& str) 245 : CPDF_Object(PDFOBJ_NAME), m_Name(str) {} 246 explicit CPDF_Name(const FX_CHAR* str) 247 : CPDF_Object(PDFOBJ_NAME), m_Name(str) {} 248 249 CFX_ByteString& GetString() { return m_Name; } 250 251 FX_BOOL Identical(CPDF_Name* pOther) const { 252 return m_Name == pOther->m_Name; 253 } 254 255 protected: 256 CFX_ByteString m_Name; 257 friend class CPDF_Object; 258 }; 259 inline CPDF_Name* ToName(CPDF_Object* obj) { 260 return obj ? obj->AsName() : nullptr; 261 } 262 inline const CPDF_Name* ToName(const CPDF_Object* obj) { 263 return obj ? obj->AsName() : nullptr; 264 } 265 266 class CPDF_Array : public CPDF_Object { 267 public: 268 CPDF_Array() : CPDF_Object(PDFOBJ_ARRAY) {} 269 270 FX_DWORD GetCount() const { return m_Objects.GetSize(); } 271 272 CPDF_Object* GetElement(FX_DWORD index) const; 273 274 CPDF_Object* GetElementValue(FX_DWORD index) const; 275 276 CFX_Matrix GetMatrix(); 277 278 CFX_FloatRect GetRect(); 279 280 CFX_ByteString GetString(FX_DWORD index) const; 281 282 CFX_ByteStringC GetConstString(FX_DWORD index) const; 283 284 int GetInteger(FX_DWORD index) const; 285 286 FX_FLOAT GetNumber(FX_DWORD index) const; 287 288 CPDF_Dictionary* GetDict(FX_DWORD index) const; 289 290 CPDF_Stream* GetStream(FX_DWORD index) const; 291 292 CPDF_Array* GetArray(FX_DWORD index) const; 293 294 FX_FLOAT GetFloat(FX_DWORD index) const { return GetNumber(index); } 295 296 void SetAt(FX_DWORD index, 297 CPDF_Object* pObj, 298 CPDF_IndirectObjectHolder* pObjs = NULL); 299 300 void InsertAt(FX_DWORD index, 301 CPDF_Object* pObj, 302 CPDF_IndirectObjectHolder* pObjs = NULL); 303 304 void RemoveAt(FX_DWORD index, int nCount = 1); 305 306 void Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs = NULL); 307 308 void AddNumber(FX_FLOAT f); 309 310 void AddInteger(int i); 311 312 void AddString(const CFX_ByteString& str); 313 314 void AddName(const CFX_ByteString& str); 315 316 void AddReference(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum); 317 318 void AddReference(CPDF_IndirectObjectHolder* pDoc, CPDF_Object* obj) { 319 AddReference(pDoc, obj->GetObjNum()); 320 } 321 322 FX_FLOAT GetNumber16(FX_DWORD index) const { return GetNumber(index); } 323 324 void AddNumber16(FX_FLOAT value) { AddNumber(value); } 325 326 FX_BOOL Identical(CPDF_Array* pOther) const; 327 328 protected: 329 ~CPDF_Array(); 330 331 CFX_ArrayTemplate<CPDF_Object*> m_Objects; 332 friend class CPDF_Object; 333 }; 334 inline CPDF_Array* ToArray(CPDF_Object* obj) { 335 return obj ? obj->AsArray() : nullptr; 336 } 337 inline const CPDF_Array* ToArray(const CPDF_Object* obj) { 338 return obj ? obj->AsArray() : nullptr; 339 } 340 341 class CPDF_Dictionary : public CPDF_Object { 342 public: 343 using iterator = std::map<CFX_ByteString, CPDF_Object*>::iterator; 344 using const_iterator = std::map<CFX_ByteString, CPDF_Object*>::const_iterator; 345 346 CPDF_Dictionary() : CPDF_Object(PDFOBJ_DICTIONARY) {} 347 348 CPDF_Object* GetElement(const CFX_ByteStringC& key) const; 349 350 CPDF_Object* GetElementValue(const CFX_ByteStringC& key) const; 351 352 CFX_ByteString GetString(const CFX_ByteStringC& key) const; 353 354 CFX_ByteStringC GetConstString(const CFX_ByteStringC& key) const; 355 356 CFX_ByteString GetString(const CFX_ByteStringC& key, 357 const CFX_ByteStringC& default_str) const; 358 359 CFX_ByteStringC GetConstString(const CFX_ByteStringC& key, 360 const CFX_ByteStringC& default_str) const; 361 362 CFX_WideString GetUnicodeText(const CFX_ByteStringC& key, 363 CFX_CharMap* pCharMap = NULL) const; 364 365 int GetInteger(const CFX_ByteStringC& key) const; 366 367 int GetInteger(const CFX_ByteStringC& key, int default_int) const; 368 369 FX_BOOL GetBoolean(const CFX_ByteStringC& key, 370 FX_BOOL bDefault = FALSE) const; 371 372 FX_FLOAT GetNumber(const CFX_ByteStringC& key) const; 373 374 CPDF_Dictionary* GetDict(const CFX_ByteStringC& key) const; 375 376 CPDF_Stream* GetStream(const CFX_ByteStringC& key) const; 377 378 CPDF_Array* GetArray(const CFX_ByteStringC& key) const; 379 380 CFX_FloatRect GetRect(const CFX_ByteStringC& key) const; 381 382 CFX_Matrix GetMatrix(const CFX_ByteStringC& key) const; 383 384 FX_FLOAT GetFloat(const CFX_ByteStringC& key) const { return GetNumber(key); } 385 386 FX_BOOL KeyExist(const CFX_ByteStringC& key) const; 387 388 // Set* functions invalidate iterators for the element with the key |key|. 389 void SetAt(const CFX_ByteStringC& key, CPDF_Object* pObj); 390 391 void SetAtName(const CFX_ByteStringC& key, const CFX_ByteString& name); 392 393 void SetAtString(const CFX_ByteStringC& key, const CFX_ByteString& string); 394 395 void SetAtInteger(const CFX_ByteStringC& key, int i); 396 397 void SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f); 398 399 void SetAtReference(const CFX_ByteStringC& key, 400 CPDF_IndirectObjectHolder* pDoc, 401 FX_DWORD objnum); 402 403 void SetAtReference(const CFX_ByteStringC& key, 404 CPDF_IndirectObjectHolder* pDoc, 405 CPDF_Object* obj) { 406 SetAtReference(key, pDoc, obj->GetObjNum()); 407 } 408 409 void AddReference(const CFX_ByteStringC& key, 410 CPDF_IndirectObjectHolder* pDoc, 411 FX_DWORD objnum); 412 413 void SetAtRect(const CFX_ByteStringC& key, const CFX_FloatRect& rect); 414 415 void SetAtMatrix(const CFX_ByteStringC& key, const CFX_Matrix& matrix); 416 417 void SetAtBoolean(const CFX_ByteStringC& key, FX_BOOL bValue); 418 419 // Invalidates iterators for the element with the key |key|. 420 void RemoveAt(const CFX_ByteStringC& key); 421 422 // Invalidates iterators for the element with the key |oldkey|. 423 void ReplaceKey(const CFX_ByteStringC& oldkey, const CFX_ByteStringC& newkey); 424 425 FX_BOOL Identical(CPDF_Dictionary* pDict) const; 426 427 size_t GetCount() const { return m_Map.size(); } 428 429 iterator begin() { return m_Map.begin(); } 430 431 iterator end() { return m_Map.end(); } 432 433 const_iterator begin() const { return m_Map.begin(); } 434 435 const_iterator end() const { return m_Map.end(); } 436 437 protected: 438 ~CPDF_Dictionary(); 439 440 std::map<CFX_ByteString, CPDF_Object*> m_Map; 441 442 friend class CPDF_Object; 443 }; 444 inline CPDF_Dictionary* ToDictionary(CPDF_Object* obj) { 445 return obj ? obj->AsDictionary() : nullptr; 446 } 447 inline const CPDF_Dictionary* ToDictionary(const CPDF_Object* obj) { 448 return obj ? obj->AsDictionary() : nullptr; 449 } 450 451 class CPDF_Stream : public CPDF_Object { 452 public: 453 CPDF_Stream(uint8_t* pData, FX_DWORD size, CPDF_Dictionary* pDict); 454 455 CPDF_Dictionary* GetDict() const { return m_pDict; } 456 457 void SetData(const uint8_t* pData, 458 FX_DWORD size, 459 FX_BOOL bCompressed, 460 FX_BOOL bKeepBuf); 461 462 void InitStream(uint8_t* pData, FX_DWORD size, CPDF_Dictionary* pDict); 463 464 void InitStreamFromFile(IFX_FileRead* pFile, CPDF_Dictionary* pDict); 465 466 FX_BOOL Identical(CPDF_Stream* pOther) const; 467 468 FX_DWORD GetRawSize() const { return m_dwSize; } 469 470 FX_BOOL ReadRawData(FX_FILESIZE start_pos, 471 uint8_t* pBuf, 472 FX_DWORD buf_size) const; 473 474 FX_BOOL IsMemoryBased() const { return m_GenNum == kMemoryBasedGenNum; } 475 476 protected: 477 friend class CPDF_Object; 478 friend class CPDF_StreamAcc; 479 480 static const FX_DWORD kMemoryBasedGenNum = (FX_DWORD)-1; 481 ~CPDF_Stream(); 482 483 void InitStreamInternal(CPDF_Dictionary* pDict); 484 485 CPDF_Dictionary* m_pDict; 486 487 FX_DWORD m_dwSize; 488 489 FX_DWORD m_GenNum; 490 491 union { 492 uint8_t* m_pDataBuf; 493 494 IFX_FileRead* m_pFile; 495 }; 496 }; 497 inline CPDF_Stream* ToStream(CPDF_Object* obj) { 498 return obj ? obj->AsStream() : nullptr; 499 } 500 inline const CPDF_Stream* ToStream(const CPDF_Object* obj) { 501 return obj ? obj->AsStream() : nullptr; 502 } 503 504 class CPDF_StreamAcc { 505 public: 506 CPDF_StreamAcc(); 507 508 ~CPDF_StreamAcc(); 509 510 void LoadAllData(const CPDF_Stream* pStream, 511 FX_BOOL bRawAccess = FALSE, 512 FX_DWORD estimated_size = 0, 513 FX_BOOL bImageAcc = FALSE); 514 515 const CPDF_Stream* GetStream() const { return m_pStream; } 516 517 CPDF_Dictionary* GetDict() const { 518 return m_pStream ? m_pStream->GetDict() : nullptr; 519 } 520 521 const uint8_t* GetData() const; 522 523 FX_DWORD GetSize() const; 524 525 uint8_t* DetachData(); 526 527 const CFX_ByteString& GetImageDecoder() { return m_ImageDecoder; } 528 529 const CPDF_Dictionary* GetImageParam() { return m_pImageParam; } 530 531 protected: 532 uint8_t* m_pData; 533 534 FX_DWORD m_dwSize; 535 536 FX_BOOL m_bNewBuf; 537 538 CFX_ByteString m_ImageDecoder; 539 540 CPDF_Dictionary* m_pImageParam; 541 542 const CPDF_Stream* m_pStream; 543 544 uint8_t* m_pSrcData; 545 }; 546 547 class CPDF_Null : public CPDF_Object { 548 public: 549 CPDF_Null() : CPDF_Object(PDFOBJ_NULL) {} 550 }; 551 552 class CPDF_Reference : public CPDF_Object { 553 public: 554 CPDF_Reference(CPDF_IndirectObjectHolder* pDoc, int objnum) 555 : CPDF_Object(PDFOBJ_REFERENCE), m_pObjList(pDoc), m_RefObjNum(objnum) {} 556 557 CPDF_IndirectObjectHolder* GetObjList() const { return m_pObjList; } 558 559 FX_DWORD GetRefObjNum() const { return m_RefObjNum; } 560 561 void SetRef(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum); 562 563 FX_BOOL Identical(CPDF_Reference* pOther) const { 564 return m_RefObjNum == pOther->m_RefObjNum; 565 } 566 567 protected: 568 CPDF_IndirectObjectHolder* m_pObjList; 569 570 FX_DWORD m_RefObjNum; 571 friend class CPDF_Object; 572 }; 573 inline CPDF_Reference* ToReference(CPDF_Object* obj) { 574 return obj ? obj->AsReference() : nullptr; 575 } 576 inline const CPDF_Reference* ToReference(const CPDF_Object* obj) { 577 return obj ? obj->AsReference() : nullptr; 578 } 579 580 class CPDF_IndirectObjectHolder { 581 public: 582 using iterator = std::map<FX_DWORD, CPDF_Object*>::iterator; 583 using const_iterator = std::map<FX_DWORD, CPDF_Object*>::const_iterator; 584 585 explicit CPDF_IndirectObjectHolder(CPDF_Parser* pParser); 586 ~CPDF_IndirectObjectHolder(); 587 588 int GetIndirectType(FX_DWORD objnum); 589 CPDF_Object* GetIndirectObject(FX_DWORD objnum, PARSE_CONTEXT* pContext); 590 FX_DWORD AddIndirectObject(CPDF_Object* pObj); 591 void ReleaseIndirectObject(FX_DWORD objnum); 592 593 // Takes ownership of |pObj|. 594 FX_BOOL InsertIndirectObject(FX_DWORD objnum, CPDF_Object* pObj); 595 596 FX_DWORD GetLastObjNum() const { return m_LastObjNum; } 597 iterator begin() { return m_IndirectObjs.begin(); } 598 const_iterator begin() const { return m_IndirectObjs.cbegin(); } 599 iterator end() { return m_IndirectObjs.end(); } 600 const_iterator end() const { return m_IndirectObjs.end(); } 601 602 protected: 603 CPDF_Parser* m_pParser; 604 FX_DWORD m_LastObjNum; 605 std::map<FX_DWORD, CPDF_Object*> m_IndirectObjs; 606 }; 607 608 #endif // CORE_INCLUDE_FPDFAPI_FPDF_OBJECTS_H_ 609