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
CPDF_Stream()20 CPDF_Stream::CPDF_Stream() {}
21
CPDF_Stream(std::unique_ptr<uint8_t,FxFreeDeleter> pData,uint32_t size,std::unique_ptr<CPDF_Dictionary> pDict)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
~CPDF_Stream()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
GetType() const35 CPDF_Object::Type CPDF_Stream::GetType() const {
36 return STREAM;
37 }
38
GetDict() const39 CPDF_Dictionary* CPDF_Stream::GetDict() const {
40 return m_pDict.get();
41 }
42
IsStream() const43 bool CPDF_Stream::IsStream() const {
44 return true;
45 }
46
AsStream()47 CPDF_Stream* CPDF_Stream::AsStream() {
48 return this;
49 }
50
AsStream() const51 const CPDF_Stream* CPDF_Stream::AsStream() const {
52 return this;
53 }
54
InitStream(const uint8_t * pData,uint32_t size,std::unique_ptr<CPDF_Dictionary> pDict)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
InitStreamFromFile(const RetainPtr<IFX_SeekableReadStream> & pFile,std::unique_ptr<CPDF_Dictionary> pDict)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
Clone() const74 std::unique_ptr<CPDF_Object> CPDF_Stream::Clone() const {
75 return CloneObjectNonCyclic(false);
76 }
77
CloneNonCyclic(bool bDirect,std::set<const CPDF_Object * > * pVisited) const78 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
SetDataAndRemoveFilter(const uint8_t * pData,uint32_t size)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
SetDataAndRemoveFilter(std::ostringstream * stream)102 void CPDF_Stream::SetDataAndRemoveFilter(std::ostringstream* stream) {
103 SetDataAndRemoveFilter(
104 reinterpret_cast<const uint8_t*>(stream->str().c_str()), stream->tellp());
105 }
106
SetData(const uint8_t * pData,uint32_t size)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
SetData(std::unique_ptr<uint8_t,FxFreeDeleter> pData,uint32_t size)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
SetData(std::ostringstream * stream)127 void CPDF_Stream::SetData(std::ostringstream* stream) {
128 SetData(reinterpret_cast<const uint8_t*>(stream->str().c_str()),
129 stream->tellp());
130 }
131
ReadRawData(FX_FILESIZE offset,uint8_t * buf,uint32_t size) const132 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
HasFilter() const144 bool CPDF_Stream::HasFilter() const {
145 return m_pDict && m_pDict->KeyExist("Filter");
146 }
147
GetUnicodeText() const148 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
WriteTo(IFX_ArchiveStream * archive) const154 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