// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #ifndef _FPDF_OBJECTS_ #define _FPDF_OBJECTS_ #ifndef _FXCRT_EXTENSION_ #include "../fxcrt/fx_ext.h" #endif class CPDF_Document; class CPDF_IndirectObjects; class CPDF_Null; class CPDF_Boolean; class CPDF_Number; class CPDF_String; class CPDF_Stream; class CPDF_StreamAcc; class CPDF_StreamFilter; class CPDF_Array; class CPDF_Dictionary; class CPDF_Reference; class IPDF_DocParser; class IFX_FileRead; class CPDF_CryptoHandler; #define PDFOBJ_INVALID 0 #define PDFOBJ_BOOLEAN 1 #define PDFOBJ_NUMBER 2 #define PDFOBJ_STRING 3 #define PDFOBJ_NAME 4 #define PDFOBJ_ARRAY 5 #define PDFOBJ_DICTIONARY 6 #define PDFOBJ_STREAM 7 #define PDFOBJ_NULL 8 #define PDFOBJ_REFERENCE 9 typedef IFX_FileStream* (*FPDF_LPFCloneStreamCallback)(CPDF_Stream *pStream, FX_LPVOID pUserData); class CPDF_Object : public CFX_Object { public: int GetType() const { return m_Type; } FX_DWORD GetObjNum() const { return m_ObjNum; } FX_DWORD GetGenNum() const { return m_GenNum; } FX_BOOL IsIdentical(CPDF_Object* pObj) const; CPDF_Object* Clone(FX_BOOL bDirect = FALSE) const; CPDF_Object* CloneRef(CPDF_IndirectObjects* pObjs) const; CPDF_Object* GetDirect() const; void Release(); CFX_ByteString GetString() const; CFX_ByteStringC GetConstString() const; CFX_WideString GetUnicodeText(CFX_CharMap* pCharMap = NULL) const; FX_FLOAT GetNumber() const; FX_FLOAT GetNumber16() const; int GetInteger() const; CPDF_Dictionary* GetDict() const; CPDF_Array* GetArray() const; void SetString(const CFX_ByteString& str); void SetUnicodeText(FX_LPCWSTR pUnicodes, int len = -1); int GetDirectType() const; FX_BOOL IsModified() const { return FALSE; } protected: FX_DWORD m_Type; CPDF_Object() { m_ObjNum = 0; m_GenNum = 0; } FX_DWORD m_ObjNum; FX_DWORD m_GenNum; void Destroy(); ~CPDF_Object() {} friend class CPDF_IndirectObjects; friend class CPDF_Parser; friend class CPDF_SyntaxParser; private: CPDF_Object(const CPDF_Object& src) {} CPDF_Object* CloneInternal(FX_BOOL bDirect, CFX_MapPtrToPtr* visited) const; }; class CPDF_Boolean : public CPDF_Object { public: static CPDF_Boolean* Create(FX_BOOL value) { return FX_NEW CPDF_Boolean(value); } CPDF_Boolean() { m_Type = PDFOBJ_BOOLEAN; } CPDF_Boolean(FX_BOOL value) { m_Type = PDFOBJ_BOOLEAN; m_bValue = value; } FX_BOOL Identical(CPDF_Boolean* pOther) const { return m_bValue == pOther->m_bValue; } protected: FX_BOOL m_bValue; friend class CPDF_Object; }; class CPDF_Number : public CPDF_Object { public: static CPDF_Number* Create(int value) { return FX_NEW CPDF_Number(value); } static CPDF_Number* Create(FX_FLOAT value) { return FX_NEW CPDF_Number(value); } static CPDF_Number* Create(FX_BSTR str) { return FX_NEW CPDF_Number(str); } static CPDF_Number* Create(FX_BOOL bInteger, void* pData) { return FX_NEW CPDF_Number(bInteger, pData); } CPDF_Number(): m_Integer(0) { m_Type = PDFOBJ_NUMBER; } CPDF_Number(FX_BOOL bInteger, void* pData); CPDF_Number(int value); CPDF_Number(FX_FLOAT value); CPDF_Number(FX_BSTR str); FX_BOOL Identical(CPDF_Number* pOther) const; CFX_ByteString GetString() const; void SetString(FX_BSTR str); FX_BOOL IsInteger() const { return m_bInteger; } int GetInteger() const { return m_bInteger ? m_Integer : (int)m_Float; } FX_FLOAT GetNumber() const { return m_bInteger ? (FX_FLOAT)m_Integer : m_Float; } void SetNumber(FX_FLOAT value); FX_FLOAT GetNumber16() const { return GetNumber(); } FX_FLOAT GetFloat() const { return m_bInteger ? (FX_FLOAT)m_Integer : m_Float; } protected: FX_BOOL m_bInteger; union { int m_Integer; FX_FLOAT m_Float; }; friend class CPDF_Object; }; class CPDF_String : public CPDF_Object { public: static CPDF_String* Create(const CFX_ByteString& str, FX_BOOL bHex = FALSE) { return FX_NEW CPDF_String(str, bHex); } static CPDF_String* Create(const CFX_WideString& str) { return FX_NEW CPDF_String(str); } CPDF_String() { m_Type = PDFOBJ_STRING; m_bHex = FALSE; } CPDF_String(const CFX_ByteString& str, FX_BOOL bHex = FALSE) : m_String(str) { m_Type = PDFOBJ_STRING; m_bHex = bHex; } CPDF_String(const CFX_WideString& str); CFX_ByteString& GetString() { return m_String; } FX_BOOL Identical(CPDF_String* pOther) const { return m_String == pOther->m_String; } FX_BOOL IsHex() const { return m_bHex; } protected: CFX_ByteString m_String; FX_BOOL m_bHex; friend class CPDF_Object; }; class CPDF_Name : public CPDF_Object { public: static CPDF_Name* Create(const CFX_ByteString& str) { return FX_NEW CPDF_Name(str); } static CPDF_Name* Create(FX_BSTR str) { return FX_NEW CPDF_Name(str); } static CPDF_Name* Create(FX_LPCSTR str) { return FX_NEW CPDF_Name(str); } CPDF_Name(const CFX_ByteString& str) : m_Name(str) { m_Type = PDFOBJ_NAME; } CPDF_Name(FX_BSTR str) : m_Name(str) { m_Type = PDFOBJ_NAME; } CPDF_Name(FX_LPCSTR str) : m_Name(str) { m_Type = PDFOBJ_NAME; } CFX_ByteString& GetString() { return m_Name; } FX_BOOL Identical(CPDF_Name* pOther) const { return m_Name == pOther->m_Name; } protected: CFX_ByteString m_Name; friend class CPDF_Object; }; class CPDF_Array : public CPDF_Object { public: static CPDF_Array* Create() { return FX_NEW CPDF_Array(); } CPDF_Array() { m_Type = PDFOBJ_ARRAY; } FX_DWORD GetCount() const { return m_Objects.GetSize(); } CPDF_Object* GetElement(FX_DWORD index) const; CPDF_Object* GetElementValue(FX_DWORD index) const; CFX_AffineMatrix GetMatrix(); CFX_FloatRect GetRect(); CFX_ByteString GetString(FX_DWORD index) const; CFX_ByteStringC GetConstString(FX_DWORD index) const; int GetInteger(FX_DWORD index) const; FX_FLOAT GetNumber(FX_DWORD index) const; CPDF_Dictionary* GetDict(FX_DWORD index) const; CPDF_Stream* GetStream(FX_DWORD index) const; CPDF_Array* GetArray(FX_DWORD index) const; FX_FLOAT GetFloat(FX_DWORD index) const { return GetNumber(index); } void SetAt(FX_DWORD index, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL); void InsertAt(FX_DWORD index, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL); void RemoveAt(FX_DWORD index); void Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL); void AddNumber(FX_FLOAT f); void AddInteger(int i); void AddString(const CFX_ByteString& str); void AddName(const CFX_ByteString& str); void AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum); void AddReference(CPDF_IndirectObjects* pDoc, CPDF_Object* obj) { AddReference(pDoc, obj->GetObjNum()); } FX_FLOAT GetNumber16(FX_DWORD index) const { return GetNumber(index); } void AddNumber16(FX_FLOAT value) { AddNumber(value); } FX_BOOL Identical(CPDF_Array* pOther) const; protected: ~CPDF_Array(); CFX_PtrArray m_Objects; friend class CPDF_Object; }; class CPDF_Dictionary : public CPDF_Object { public: static CPDF_Dictionary* Create() { return FX_NEW CPDF_Dictionary(); } CPDF_Dictionary() { m_Type = PDFOBJ_DICTIONARY; } CPDF_Object* GetElement(FX_BSTR key) const; CPDF_Object* GetElementValue(FX_BSTR key) const; CFX_ByteString GetString(FX_BSTR key) const; CFX_ByteStringC GetConstString(FX_BSTR key) const; CFX_ByteString GetString(FX_BSTR key, FX_BSTR default_str) const; CFX_ByteStringC GetConstString(FX_BSTR key, FX_BSTR default_str) const; CFX_WideString GetUnicodeText(FX_BSTR key, CFX_CharMap* pCharMap = NULL) const; int GetInteger(FX_BSTR key) const; int GetInteger(FX_BSTR key, int default_int) const; FX_BOOL GetBoolean(FX_BSTR key, FX_BOOL bDefault = FALSE) const; FX_FLOAT GetNumber(FX_BSTR key) const; CPDF_Dictionary* GetDict(FX_BSTR key) const; CPDF_Stream* GetStream(FX_BSTR key) const; CPDF_Array* GetArray(FX_BSTR key) const; CFX_FloatRect GetRect(FX_BSTR key) const; CFX_AffineMatrix GetMatrix(FX_BSTR key) const; FX_FLOAT GetFloat(FX_BSTR key) const { return GetNumber(key); } FX_BOOL KeyExist(FX_BSTR key) const; FX_POSITION GetStartPos() const; CPDF_Object* GetNextElement(FX_POSITION& pos, CFX_ByteString& key) const; void SetAt(FX_BSTR key, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL); void SetAtName(FX_BSTR key, const CFX_ByteString& name); void SetAtString(FX_BSTR key, const CFX_ByteString& string); void SetAtInteger(FX_BSTR key, int i); void SetAtNumber(FX_BSTR key, FX_FLOAT f); void SetAtReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum); void SetAtReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, CPDF_Object* obj) { SetAtReference(key, pDoc, obj->GetObjNum()); } void AddReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum); void AddReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, CPDF_Object* obj) { AddReference(key, pDoc, obj->GetObjNum()); } void SetAtRect(FX_BSTR key, const CFX_FloatRect& rect); void SetAtMatrix(FX_BSTR key, const CFX_AffineMatrix& matrix); void SetAtBoolean(FX_BSTR key, FX_BOOL bValue); void RemoveAt(FX_BSTR key); void ReplaceKey(FX_BSTR oldkey, FX_BSTR newkey); FX_BOOL Identical(CPDF_Dictionary* pDict) const; int GetCount() const { return m_Map.GetCount(); } void AddValue(FX_BSTR key, CPDF_Object* pObj); protected: ~CPDF_Dictionary(); CFX_CMapByteStringToPtr m_Map; friend class CPDF_Object; }; class CPDF_Stream : public CPDF_Object { public: static CPDF_Stream* Create(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict) { return FX_NEW CPDF_Stream(pData, size, pDict); } CPDF_Stream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict); CPDF_Dictionary* GetDict() const { return m_pDict; } void SetData(FX_LPCBYTE pData, FX_DWORD size, FX_BOOL bCompressed, FX_BOOL bKeepBuf); void InitStream(FX_BYTE* pData, FX_DWORD size, CPDF_Dictionary* pDict); void InitStream(IFX_FileRead *pFile, CPDF_Dictionary* pDict); FX_BOOL Identical(CPDF_Stream* pOther) const; CPDF_StreamFilter* GetStreamFilter(FX_BOOL bRaw = FALSE) const; FX_DWORD GetRawSize() const { return m_dwSize; } FX_BOOL ReadRawData(FX_FILESIZE start_pos, FX_LPBYTE pBuf, FX_DWORD buf_size) const; FX_BOOL IsMemoryBased() const { return m_GenNum == (FX_DWORD) - 1; } CPDF_Stream* Clone(FX_BOOL bDirect, FPDF_LPFCloneStreamCallback lpfCallback, FX_LPVOID pUserData) const; protected: ~CPDF_Stream(); CPDF_Dictionary* m_pDict; FX_DWORD m_dwSize; FX_DWORD m_GenNum; union { FX_LPBYTE m_pDataBuf; IFX_FileRead* m_pFile; }; FX_FILESIZE m_FileOffset; CPDF_CryptoHandler* m_pCryptoHandler; void InitStream(CPDF_Dictionary* pDict); friend class CPDF_Object; friend class CPDF_StreamAcc; friend class CPDF_AttachmentAcc; }; class CPDF_StreamAcc : public CFX_Object { public: CPDF_StreamAcc(); ~CPDF_StreamAcc(); void LoadAllData(const CPDF_Stream* pStream, FX_BOOL bRawAccess = FALSE, FX_DWORD estimated_size = 0, FX_BOOL bImageAcc = FALSE); const CPDF_Stream* GetStream() const { return m_pStream; } CPDF_Dictionary* GetDict() const { return m_pStream? m_pStream->GetDict() : NULL; } FX_LPCBYTE GetData() const; FX_DWORD GetSize() const; FX_LPBYTE DetachData(); const CFX_ByteString& GetImageDecoder() { return m_ImageDecoder; } const CPDF_Dictionary* GetImageParam() { return m_pImageParam; } protected: FX_LPBYTE m_pData; FX_DWORD m_dwSize; FX_BOOL m_bNewBuf; CFX_ByteString m_ImageDecoder; CPDF_Dictionary* m_pImageParam; const CPDF_Stream* m_pStream; FX_LPBYTE m_pSrcData; }; CFX_DataFilter* FPDF_CreateFilter(FX_BSTR name, const CPDF_Dictionary* pParam, int width = 0, int height = 0); #define FPDF_FILTER_BUFFER_SIZE 20480 class CPDF_StreamFilter : public CFX_Object { public: ~CPDF_StreamFilter(); FX_DWORD ReadBlock(FX_LPBYTE buffer, FX_DWORD size); FX_DWORD GetSrcPos() { return m_SrcOffset; } const CPDF_Stream* GetStream() { return m_pStream; } protected: CPDF_StreamFilter() {} FX_DWORD ReadLeftOver(FX_LPBYTE buffer, FX_DWORD buf_size); const CPDF_Stream* m_pStream; CFX_DataFilter* m_pFilter; CFX_BinaryBuf* m_pBuffer; FX_DWORD m_BufOffset; FX_DWORD m_SrcOffset; FX_BYTE m_SrcBuffer[FPDF_FILTER_BUFFER_SIZE]; friend class CPDF_Stream; }; class CPDF_Null : public CPDF_Object { public: static CPDF_Null* Create() { return FX_NEW CPDF_Null(); } CPDF_Null() { m_Type = PDFOBJ_NULL; } }; class CPDF_Reference : public CPDF_Object { public: static CPDF_Reference* Create(CPDF_IndirectObjects* pDoc, int objnum) { return FX_NEW CPDF_Reference(pDoc, objnum); } CPDF_Reference(CPDF_IndirectObjects* pDoc, int objnum) { m_Type = PDFOBJ_REFERENCE; m_pObjList = pDoc; m_RefObjNum = objnum; } CPDF_IndirectObjects* GetObjList() const { return m_pObjList; } FX_DWORD GetRefObjNum() const { return m_RefObjNum; } void SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum); FX_BOOL Identical(CPDF_Reference* pOther) const { return m_RefObjNum == pOther->m_RefObjNum; } protected: CPDF_IndirectObjects* m_pObjList; FX_DWORD m_RefObjNum; friend class CPDF_Object; }; class CPDF_IndirectObjects : public CFX_Object { public: CPDF_IndirectObjects(IPDF_DocParser* pParser); ~CPDF_IndirectObjects(); CPDF_Object* GetIndirectObject(FX_DWORD objnum, struct PARSE_CONTEXT* pContext = NULL); int GetIndirectType(FX_DWORD objnum); FX_DWORD AddIndirectObject(CPDF_Object* pObj); void ReleaseIndirectObject(FX_DWORD objnum); void InsertIndirectObject(FX_DWORD objnum, CPDF_Object* pObj); FX_DWORD GetLastObjNum() const; FX_POSITION GetStartPosition() const { return m_IndirectObjs.GetStartPosition(); } void GetNextAssoc(FX_POSITION& rPos, FX_DWORD& objnum, CPDF_Object*& pObject) const { m_IndirectObjs.GetNextAssoc(rPos, (void*&)objnum, (void*&)pObject); } protected: CFX_MapPtrToPtr m_IndirectObjs; IPDF_DocParser* m_pParser; FX_DWORD m_LastObjNum; }; #endif