1 // Copyright 2016 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/fpdfapi/parser/cpdf_stream.h" 8 9 #include <utility> 10 11 #include "core/fpdfapi/parser/cpdf_dictionary.h" 12 #include "core/fpdfapi/parser/cpdf_number.h" 13 #include "core/fpdfapi/parser/cpdf_stream_acc.h" 14 #include "core/fpdfapi/parser/fpdf_parser_decode.h" 15 #include "third_party/base/numerics/safe_conversions.h" 16 #include "third_party/base/ptr_util.h" 17 #include "third_party/base/stl_util.h" 18 19 CPDF_Stream::CPDF_Stream() {} 20 21 CPDF_Stream::CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData, 22 uint32_t size, 23 std::unique_ptr<CPDF_Dictionary> pDict) 24 : m_dwSize(size), m_pDict(std::move(pDict)), m_pDataBuf(std::move(pData)) {} 25 26 CPDF_Stream::~CPDF_Stream() { 27 m_ObjNum = kInvalidObjNum; 28 if (m_pDict && m_pDict->GetObjNum() == kInvalidObjNum) 29 m_pDict.release(); // lowercase release, release ownership. 30 } 31 32 CPDF_Object::Type CPDF_Stream::GetType() const { 33 return STREAM; 34 } 35 36 CPDF_Dictionary* CPDF_Stream::GetDict() const { 37 return m_pDict.get(); 38 } 39 40 bool CPDF_Stream::IsStream() const { 41 return true; 42 } 43 44 CPDF_Stream* CPDF_Stream::AsStream() { 45 return this; 46 } 47 48 const CPDF_Stream* CPDF_Stream::AsStream() const { 49 return this; 50 } 51 52 void CPDF_Stream::InitStream(const uint8_t* pData, 53 uint32_t size, 54 std::unique_ptr<CPDF_Dictionary> pDict) { 55 m_pDict = std::move(pDict); 56 m_bMemoryBased = true; 57 m_pFile = nullptr; 58 m_pDataBuf.reset(FX_Alloc(uint8_t, size)); 59 if (pData) 60 FXSYS_memcpy(m_pDataBuf.get(), pData, size); 61 m_dwSize = size; 62 if (m_pDict) 63 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize)); 64 } 65 66 void CPDF_Stream::InitStreamFromFile( 67 const CFX_RetainPtr<IFX_SeekableReadStream>& pFile, 68 std::unique_ptr<CPDF_Dictionary> pDict) { 69 m_pDict = std::move(pDict); 70 m_bMemoryBased = false; 71 m_pDataBuf.reset(); 72 m_pFile = pFile; 73 m_dwSize = pdfium::base::checked_cast<uint32_t>(pFile->GetSize()); 74 if (m_pDict) 75 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize)); 76 } 77 78 std::unique_ptr<CPDF_Object> CPDF_Stream::Clone() const { 79 return CloneObjectNonCyclic(false); 80 } 81 82 std::unique_ptr<CPDF_Object> CPDF_Stream::CloneNonCyclic( 83 bool bDirect, 84 std::set<const CPDF_Object*>* pVisited) const { 85 pVisited->insert(this); 86 CPDF_StreamAcc acc; 87 acc.LoadAllData(this, true); 88 89 uint32_t streamSize = acc.GetSize(); 90 CPDF_Dictionary* pDict = GetDict(); 91 std::unique_ptr<CPDF_Dictionary> pNewDict; 92 if (pDict && !pdfium::ContainsKey(*pVisited, pDict)) { 93 pNewDict = ToDictionary( 94 static_cast<CPDF_Object*>(pDict)->CloneNonCyclic(bDirect, pVisited)); 95 } 96 return pdfium::MakeUnique<CPDF_Stream>(acc.DetachData(), streamSize, 97 std::move(pNewDict)); 98 } 99 100 void CPDF_Stream::SetData(const uint8_t* pData, uint32_t size) { 101 m_bMemoryBased = true; 102 m_pDataBuf.reset(FX_Alloc(uint8_t, size)); 103 if (pData) 104 FXSYS_memcpy(m_pDataBuf.get(), pData, size); 105 m_dwSize = size; 106 if (!m_pDict) 107 m_pDict = pdfium::MakeUnique<CPDF_Dictionary>(); 108 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size)); 109 m_pDict->RemoveFor("Filter"); 110 m_pDict->RemoveFor("DecodeParms"); 111 } 112 113 bool CPDF_Stream::ReadRawData(FX_FILESIZE offset, 114 uint8_t* buf, 115 uint32_t size) const { 116 if (!m_bMemoryBased && m_pFile) 117 return m_pFile->ReadBlock(buf, offset, size); 118 119 if (m_pDataBuf) 120 FXSYS_memcpy(buf, m_pDataBuf.get() + offset, size); 121 122 return true; 123 } 124 125 bool CPDF_Stream::HasFilter() const { 126 return m_pDict && m_pDict->KeyExist("Filter"); 127 } 128 129 CFX_WideString CPDF_Stream::GetUnicodeText() const { 130 CPDF_StreamAcc stream; 131 stream.LoadAllData(this, false); 132 return PDF_DecodeText(stream.GetData(), stream.GetSize()); 133 } 134