1 // Copyright 2016 The PDFium Authors 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_FPDFAPI_PARSER_CPDF_DOCUMENT_H_ 8 #define CORE_FPDFAPI_PARSER_CPDF_DOCUMENT_H_ 9 10 #include <memory> 11 #include <set> 12 #include <utility> 13 #include <vector> 14 15 #include "core/fpdfapi/parser/cpdf_dictionary.h" 16 #include "core/fpdfapi/parser/cpdf_parser.h" 17 #include "core/fxcrt/fx_memory.h" 18 #include "core/fxcrt/observed_ptr.h" 19 #include "core/fxcrt/retain_ptr.h" 20 #include "core/fxcrt/unowned_ptr.h" 21 22 class CPDF_ReadValidator; 23 class CPDF_StreamAcc; 24 class IFX_SeekableReadStream; 25 class JBig2_DocumentContext; 26 27 class CPDF_Document : public Observable, 28 public CPDF_Parser::ParsedObjectsHolder { 29 public: 30 // Type from which the XFA extension can subclass itself. 31 class Extension { 32 public: 33 virtual ~Extension() = default; 34 virtual int GetPageCount() const = 0; 35 virtual void DeletePage(int page_index) = 0; 36 virtual uint32_t GetUserPermissions() const = 0; 37 virtual bool ContainsExtensionForm() const = 0; 38 virtual bool ContainsExtensionFullForm() const = 0; 39 virtual bool ContainsExtensionForegroundForm() const = 0; 40 }; 41 42 class LinkListIface { 43 public: 44 // CPDF_Document merely helps manage the lifetime. 45 virtual ~LinkListIface() = default; 46 }; 47 48 class PageDataIface { 49 public: 50 PageDataIface(); 51 virtual ~PageDataIface(); 52 53 virtual void ClearStockFont() = 0; 54 virtual RetainPtr<CPDF_StreamAcc> GetFontFileStreamAcc( 55 RetainPtr<const CPDF_Stream> pFontStream) = 0; 56 virtual void MaybePurgeFontFileStreamAcc( 57 RetainPtr<CPDF_StreamAcc>&& pStreamAcc) = 0; 58 virtual void MaybePurgeImage(uint32_t objnum) = 0; 59 SetDocument(CPDF_Document * pDoc)60 void SetDocument(CPDF_Document* pDoc) { m_pDoc = pDoc; } 61 62 protected: GetDocument()63 CPDF_Document* GetDocument() const { return m_pDoc; } 64 65 private: 66 UnownedPtr<CPDF_Document> m_pDoc; 67 }; 68 69 class RenderDataIface { 70 public: 71 RenderDataIface(); 72 virtual ~RenderDataIface(); 73 SetDocument(CPDF_Document * pDoc)74 void SetDocument(CPDF_Document* pDoc) { m_pDoc = pDoc; } 75 76 protected: GetDocument()77 CPDF_Document* GetDocument() const { return m_pDoc; } 78 79 private: 80 UnownedPtr<CPDF_Document> m_pDoc; 81 }; 82 83 static constexpr int kPageMaxNum = 0xFFFFF; 84 85 static bool IsValidPageObject(const CPDF_Object* obj); 86 87 CPDF_Document(std::unique_ptr<RenderDataIface> pRenderData, 88 std::unique_ptr<PageDataIface> pPageData); 89 ~CPDF_Document() override; 90 GetExtension()91 Extension* GetExtension() const { return m_pExtension.get(); } SetExtension(std::unique_ptr<Extension> pExt)92 void SetExtension(std::unique_ptr<Extension> pExt) { 93 m_pExtension = std::move(pExt); 94 } 95 GetParser()96 CPDF_Parser* GetParser() const { return m_pParser.get(); } GetRoot()97 const CPDF_Dictionary* GetRoot() const { return m_pRootDict.Get(); } GetMutableRoot()98 RetainPtr<CPDF_Dictionary> GetMutableRoot() { return m_pRootDict; } 99 RetainPtr<CPDF_Dictionary> GetInfo(); 100 RetainPtr<const CPDF_Array> GetFileIdentifier() const; 101 102 void DeletePage(int iPage); 103 int GetPageCount() const; 104 bool IsPageLoaded(int iPage) const; 105 RetainPtr<const CPDF_Dictionary> GetPageDictionary(int iPage); 106 RetainPtr<CPDF_Dictionary> GetMutablePageDictionary(int iPage); 107 int GetPageIndex(uint32_t objnum); 108 uint32_t GetUserPermissions() const; 109 110 // PageDataIface wrappers, try to avoid explicit getter calls. 111 RetainPtr<CPDF_StreamAcc> GetFontFileStreamAcc( 112 RetainPtr<const CPDF_Stream> pFontStream); 113 void MaybePurgeFontFileStreamAcc(RetainPtr<CPDF_StreamAcc>&& pStreamAcc); 114 void MaybePurgeImage(uint32_t objnum); 115 116 // Returns a valid pointer, unless it is called during destruction. GetPageData()117 PageDataIface* GetPageData() const { return m_pDocPage.get(); } GetRenderData()118 RenderDataIface* GetRenderData() const { return m_pDocRender.get(); } 119 120 void SetPageObjNum(int iPage, uint32_t objNum); 121 122 JBig2_DocumentContext* GetOrCreateCodecContext(); GetLinksContext()123 LinkListIface* GetLinksContext() const { return m_pLinksContext.get(); } SetLinksContext(std::unique_ptr<LinkListIface> pContext)124 void SetLinksContext(std::unique_ptr<LinkListIface> pContext) { 125 m_pLinksContext = std::move(pContext); 126 } 127 128 // Behaves like NewIndirect<CPDF_Stream>(), but keeps track of the new stream. 129 RetainPtr<CPDF_Stream> CreateModifiedAPStream(); 130 131 // Returns whether CreateModifiedAPStream() created `stream`. 132 bool IsModifiedAPStream(const CPDF_Stream* stream) const; 133 134 // CPDF_Parser::ParsedObjectsHolder: 135 bool TryInit() override; 136 RetainPtr<CPDF_Object> ParseIndirectObject(uint32_t objnum) override; 137 138 CPDF_Parser::Error LoadDoc(RetainPtr<IFX_SeekableReadStream> pFileAccess, 139 const ByteString& password); 140 CPDF_Parser::Error LoadLinearizedDoc(RetainPtr<CPDF_ReadValidator> validator, 141 const ByteString& password); has_valid_cross_reference_table()142 bool has_valid_cross_reference_table() const { 143 return m_bHasValidCrossReferenceTable; 144 } 145 146 void LoadPages(); 147 void CreateNewDoc(); 148 RetainPtr<CPDF_Dictionary> CreateNewPage(int iPage); 149 IncrementParsedPageCount()150 void IncrementParsedPageCount() { ++m_ParsedPageCount; } GetParsedPageCountForTesting()151 uint32_t GetParsedPageCountForTesting() { return m_ParsedPageCount; } 152 153 protected: 154 void SetParser(std::unique_ptr<CPDF_Parser> pParser); 155 156 void SetRootForTesting(RetainPtr<CPDF_Dictionary> root); 157 void ResizePageListForTesting(size_t size); 158 159 private: 160 class StockFontClearer { 161 public: 162 FX_STACK_ALLOCATED(); 163 164 explicit StockFontClearer(CPDF_Document::PageDataIface* pPageData); 165 ~StockFontClearer(); 166 167 private: 168 UnownedPtr<CPDF_Document::PageDataIface> const m_pPageData; 169 }; 170 171 // Retrieve page count information by getting count value from the tree nodes 172 int RetrievePageCount(); 173 174 // When this method is called, m_pTreeTraversal[level] exists. 175 RetainPtr<CPDF_Dictionary> TraversePDFPages(int iPage, 176 int* nPagesToGo, 177 size_t level); 178 179 RetainPtr<const CPDF_Dictionary> GetPagesDict() const; 180 RetainPtr<CPDF_Dictionary> GetMutablePagesDict(); 181 182 bool InsertDeletePDFPage(RetainPtr<CPDF_Dictionary> pPages, 183 int nPagesToGo, 184 RetainPtr<CPDF_Dictionary> pPageDict, 185 bool bInsert, 186 std::set<RetainPtr<CPDF_Dictionary>>* pVisited); 187 188 bool InsertNewPage(int iPage, RetainPtr<CPDF_Dictionary> pPageDict); 189 void ResetTraversal(); 190 CPDF_Parser::Error HandleLoadResult(CPDF_Parser::Error error); 191 192 std::unique_ptr<CPDF_Parser> m_pParser; 193 RetainPtr<CPDF_Dictionary> m_pRootDict; 194 RetainPtr<CPDF_Dictionary> m_pInfoDict; 195 196 // Vector of pairs to know current position in the page tree. The index in the 197 // vector corresponds to the level being described. The pair contains a 198 // pointer to the dictionary being processed at the level, and an index of the 199 // of the child being processed within the dictionary's /Kids array. 200 std::vector<std::pair<RetainPtr<CPDF_Dictionary>, size_t>> m_pTreeTraversal; 201 202 // True if the CPDF_Parser succeeded without having to rebuild the cross 203 // reference table. 204 bool m_bHasValidCrossReferenceTable = false; 205 206 // Index of the next page that will be traversed from the page tree. 207 bool m_bReachedMaxPageLevel = false; 208 int m_iNextPageToTraverse = 0; 209 uint32_t m_ParsedPageCount = 0; 210 211 std::unique_ptr<RenderDataIface> m_pDocRender; 212 std::unique_ptr<PageDataIface> m_pDocPage; // Must be after |m_pDocRender|. 213 std::unique_ptr<JBig2_DocumentContext> m_pCodecContext; 214 std::unique_ptr<LinkListIface> m_pLinksContext; 215 std::set<uint32_t> m_ModifiedAPStreamIDs; 216 std::vector<uint32_t> m_PageList; // Page number to page's dict objnum. 217 218 // Must be second to last. 219 StockFontClearer m_StockFontClearer; 220 221 // Must be last. Destroy the extension before any non-extension teardown. 222 std::unique_ptr<Extension> m_pExtension; 223 }; 224 225 #endif // CORE_FPDFAPI_PARSER_CPDF_DOCUMENT_H_ 226