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 "core/fxcrt/fx_stream.h" 16 #include "third_party/base/numerics/safe_conversions.h" 17 #include "third_party/base/ptr_util.h" 18 #include "third_party/base/stl_util.h" 19 20 CPDF_Stream::CPDF_Stream() {} 21 22 CPDF_Stream::CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData, 23 uint32_t size, 24 std::unique_ptr<CPDF_Dictionary> pDict) 25 : m_pDict(std::move(pDict)) { 26 SetData(std::move(pData), size); 27 } 28 29 CPDF_Stream::~CPDF_Stream() { 30 m_ObjNum = kInvalidObjNum; 31 if (m_pDict && m_pDict->GetObjNum() == kInvalidObjNum) 32 m_pDict.release(); // lowercase release, release ownership. 33 } 34 35 CPDF_Object::Type CPDF_Stream::GetType() const { 36 return STREAM; 37 } 38 39 CPDF_Dictionary* CPDF_Stream::GetDict() const { 40 return m_pDict.get(); 41 } 42 43 bool CPDF_Stream::IsStream() const { 44 return true; 45 } 46 47 CPDF_Stream* CPDF_Stream::AsStream() { 48 return this; 49 } 50 51 const CPDF_Stream* CPDF_Stream::AsStream() const { 52 return this; 53 } 54 55 void CPDF_Stream::InitStream(const uint8_t* pData, 56 uint32_t size, 57 std::unique_ptr<CPDF_Dictionary> pDict) { 58 m_pDict = std::move(pDict); 59 SetData(pData, size); 60 } 61 62 void CPDF_Stream::InitStreamFromFile( 63 const RetainPtr<IFX_SeekableReadStream>& pFile, 64 std::unique_ptr<CPDF_Dictionary> pDict) { 65 m_pDict = std::move(pDict); 66 m_bMemoryBased = false; 67 m_pDataBuf.reset(); 68 m_pFile = pFile; 69 m_dwSize = pdfium::base::checked_cast<uint32_t>(pFile->GetSize()); 70 if (m_pDict) 71 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize)); 72 } 73 74 std::unique_ptr<CPDF_Object> CPDF_Stream::Clone() const { 75 return CloneObjectNonCyclic(false); 76 } 77 78 std::unique_ptr<CPDF_Object> CPDF_Stream::CloneNonCyclic( 79 bool bDirect, 80 std::set<const CPDF_Object*>* pVisited) const { 81 pVisited->insert(this); 82 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this); 83 pAcc->LoadAllDataRaw(); 84 85 uint32_t streamSize = pAcc->GetSize(); 86 CPDF_Dictionary* pDict = GetDict(); 87 std::unique_ptr<CPDF_Dictionary> pNewDict; 88 if (pDict && !pdfium::ContainsKey(*pVisited, pDict)) { 89 pNewDict = ToDictionary( 90 static_cast<CPDF_Object*>(pDict)->CloneNonCyclic(bDirect, pVisited)); 91 } 92 return pdfium::MakeUnique<CPDF_Stream>(pAcc->DetachData(), streamSize, 93 std::move(pNewDict)); 94 } 95 96 void CPDF_Stream::SetDataAndRemoveFilter(const uint8_t* pData, uint32_t size) { 97 SetData(pData, size); 98 m_pDict->RemoveFor("Filter"); 99 m_pDict->RemoveFor("DecodeParms"); 100 } 101 102 void CPDF_Stream::SetDataAndRemoveFilter(std::ostringstream* stream) { 103 SetDataAndRemoveFilter( 104 reinterpret_cast<const uint8_t*>(stream->str().c_str()), stream->tellp()); 105 } 106 107 void CPDF_Stream::SetData(const uint8_t* pData, uint32_t size) { 108 std::unique_ptr<uint8_t, FxFreeDeleter> data_copy; 109 if (pData) { 110 data_copy.reset(FX_Alloc(uint8_t, size)); 111 memcpy(data_copy.get(), pData, size); 112 } 113 SetData(std::move(data_copy), size); 114 } 115 116 void CPDF_Stream::SetData(std::unique_ptr<uint8_t, FxFreeDeleter> pData, 117 uint32_t size) { 118 m_bMemoryBased = true; 119 m_pFile = nullptr; 120 m_pDataBuf = std::move(pData); 121 m_dwSize = size; 122 if (!m_pDict) 123 m_pDict = pdfium::MakeUnique<CPDF_Dictionary>(); 124 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size)); 125 } 126 127 void CPDF_Stream::SetData(std::ostringstream* stream) { 128 SetData(reinterpret_cast<const uint8_t*>(stream->str().c_str()), 129 stream->tellp()); 130 } 131 132 bool CPDF_Stream::ReadRawData(FX_FILESIZE offset, 133 uint8_t* buf, 134 uint32_t size) const { 135 if (!m_bMemoryBased && m_pFile) 136 return m_pFile->ReadBlock(buf, offset, size); 137 138 if (m_pDataBuf) 139 memcpy(buf, m_pDataBuf.get() + offset, size); 140 141 return true; 142 } 143 144 bool CPDF_Stream::HasFilter() const { 145 return m_pDict && m_pDict->KeyExist("Filter"); 146 } 147 148 WideString CPDF_Stream::GetUnicodeText() const { 149 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this); 150 pAcc->LoadAllDataFiltered(); 151 return PDF_DecodeText(pAcc->GetData(), pAcc->GetSize()); 152 } 153 154 bool CPDF_Stream::WriteTo(IFX_ArchiveStream* archive) const { 155 if (!GetDict()->WriteTo(archive) || !archive->WriteString("stream\r\n")) 156 return false; 157 158 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this); 159 pAcc->LoadAllDataRaw(); 160 return archive->WriteBlock(pAcc->GetData(), pAcc->GetSize()) && 161 archive->WriteString("\r\nendstream"); 162 } 163