blob: 45d2ebb30db99e212ea660050f0ddcdbbc02900c [file] [log] [blame]
Tom Sepez5fc239a2016-03-10 14:10:38 -08001// 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
dsinclair488b7ad2016-10-04 11:55:50 -07007#include "core/fpdfapi/parser/cpdf_stream.h"
Tom Sepez5fc239a2016-03-10 14:10:38 -08008
tsepez9e05ee12016-11-21 13:19:10 -08009#include <utility>
10
Lei Zhang26170562018-04-17 17:01:52 +000011#include "constants/stream_dict_common.h"
dsinclair488b7ad2016-10-04 11:55:50 -070012#include "core/fpdfapi/parser/cpdf_dictionary.h"
tsepez0e606b52016-11-18 16:22:41 -080013#include "core/fpdfapi/parser/cpdf_number.h"
dsinclair488b7ad2016-10-04 11:55:50 -070014#include "core/fpdfapi/parser/cpdf_stream_acc.h"
15#include "core/fpdfapi/parser/fpdf_parser_decode.h"
Dan Sinclairbcd1e702017-08-31 13:19:18 -040016#include "core/fxcrt/fx_stream.h"
tsepeze6db16e2016-09-19 10:45:09 -070017#include "third_party/base/numerics/safe_conversions.h"
tsepeza9caab92016-12-14 05:57:10 -080018#include "third_party/base/ptr_util.h"
weilia470b5e2016-08-23 22:08:37 -070019#include "third_party/base/stl_util.h"
Tom Sepez5fc239a2016-03-10 14:10:38 -080020
tsepeze6db16e2016-09-19 10:45:09 -070021CPDF_Stream::CPDF_Stream() {}
22
tsepez47fb8c02016-12-15 13:51:34 -080023CPDF_Stream::CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
tsepez9e05ee12016-11-21 13:19:10 -080024 uint32_t size,
25 std::unique_ptr<CPDF_Dictionary> pDict)
Artem Strygin4fde70e2017-09-04 17:01:41 +030026 : m_pDict(std::move(pDict)) {
27 SetData(std::move(pData), size);
28}
Tom Sepez5fc239a2016-03-10 14:10:38 -080029
tsepez836f7d52016-10-10 14:31:05 -070030CPDF_Stream::~CPDF_Stream() {
31 m_ObjNum = kInvalidObjNum;
32 if (m_pDict && m_pDict->GetObjNum() == kInvalidObjNum)
33 m_pDict.release(); // lowercase release, release ownership.
34}
Tom Sepez5fc239a2016-03-10 14:10:38 -080035
36CPDF_Object::Type CPDF_Stream::GetType() const {
37 return STREAM;
38}
39
40CPDF_Dictionary* CPDF_Stream::GetDict() const {
tsepeze6db16e2016-09-19 10:45:09 -070041 return m_pDict.get();
Tom Sepez5fc239a2016-03-10 14:10:38 -080042}
43
44bool CPDF_Stream::IsStream() const {
45 return true;
46}
47
48CPDF_Stream* CPDF_Stream::AsStream() {
49 return this;
50}
51
52const CPDF_Stream* CPDF_Stream::AsStream() const {
53 return this;
54}
55
tsepez596fc4c2016-06-07 06:41:50 -070056void CPDF_Stream::InitStream(const uint8_t* pData,
tsepezb5e8f142016-03-25 15:18:35 -070057 uint32_t size,
tsepez9e05ee12016-11-21 13:19:10 -080058 std::unique_ptr<CPDF_Dictionary> pDict) {
59 m_pDict = std::move(pDict);
Artem Strygin4fde70e2017-09-04 17:01:41 +030060 SetData(pData, size);
tsepeze6db16e2016-09-19 10:45:09 -070061}
62
tsepez833619b2016-12-07 09:21:17 -080063void CPDF_Stream::InitStreamFromFile(
Dan Sinclair0b950422017-09-21 15:49:49 -040064 const RetainPtr<IFX_SeekableReadStream>& pFile,
tsepez833619b2016-12-07 09:21:17 -080065 std::unique_ptr<CPDF_Dictionary> pDict) {
tsepez9e05ee12016-11-21 13:19:10 -080066 m_pDict = std::move(pDict);
tsepeze6db16e2016-09-19 10:45:09 -070067 m_bMemoryBased = false;
68 m_pDataBuf.reset();
69 m_pFile = pFile;
70 m_dwSize = pdfium::base::checked_cast<uint32_t>(pFile->GetSize());
71 if (m_pDict)
tsepez0e606b52016-11-18 16:22:41 -080072 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize));
Tom Sepez5fc239a2016-03-10 14:10:38 -080073}
74
tsepez335cf092016-11-09 13:28:26 -080075std::unique_ptr<CPDF_Object> CPDF_Stream::Clone() const {
weilia470b5e2016-08-23 22:08:37 -070076 return CloneObjectNonCyclic(false);
77}
78
tsepez335cf092016-11-09 13:28:26 -080079std::unique_ptr<CPDF_Object> CPDF_Stream::CloneNonCyclic(
weilia470b5e2016-08-23 22:08:37 -070080 bool bDirect,
81 std::set<const CPDF_Object*>* pVisited) const {
82 pVisited->insert(this);
Tom Sepezafd0d1f2017-04-04 14:37:18 -070083 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this);
Lei Zhang07401ba2017-12-11 22:12:08 +000084 pAcc->LoadAllDataRaw();
tsepez9e05ee12016-11-21 13:19:10 -080085
Tom Sepezafd0d1f2017-04-04 14:37:18 -070086 uint32_t streamSize = pAcc->GetSize();
Tom Sepez5fc239a2016-03-10 14:10:38 -080087 CPDF_Dictionary* pDict = GetDict();
tsepez9e05ee12016-11-21 13:19:10 -080088 std::unique_ptr<CPDF_Dictionary> pNewDict;
weilia470b5e2016-08-23 22:08:37 -070089 if (pDict && !pdfium::ContainsKey(*pVisited, pDict)) {
tsepez9e05ee12016-11-21 13:19:10 -080090 pNewDict = ToDictionary(
91 static_cast<CPDF_Object*>(pDict)->CloneNonCyclic(bDirect, pVisited));
weilia470b5e2016-08-23 22:08:37 -070092 }
Tom Sepezafd0d1f2017-04-04 14:37:18 -070093 return pdfium::MakeUnique<CPDF_Stream>(pAcc->DetachData(), streamSize,
tsepez9e05ee12016-11-21 13:19:10 -080094 std::move(pNewDict));
Tom Sepez5fc239a2016-03-10 14:10:38 -080095}
96
Artem Strygin90555e02017-07-28 19:41:59 +030097void CPDF_Stream::SetDataAndRemoveFilter(const uint8_t* pData, uint32_t size) {
98 SetData(pData, size);
99 m_pDict->RemoveFor("Filter");
Lei Zhang26170562018-04-17 17:01:52 +0000100 m_pDict->RemoveFor(pdfium::stream::kDecodeParms);
Artem Strygin90555e02017-07-28 19:41:59 +0300101}
102
103void CPDF_Stream::SetDataAndRemoveFilter(std::ostringstream* stream) {
Henrique Nakashimaaa1c7872018-01-30 19:12:10 +0000104 if (stream->tellp() <= 0) {
105 SetDataAndRemoveFilter(nullptr, 0);
106 return;
107 }
108
Artem Strygin90555e02017-07-28 19:41:59 +0300109 SetDataAndRemoveFilter(
110 reinterpret_cast<const uint8_t*>(stream->str().c_str()), stream->tellp());
111}
112
tsepeze6db16e2016-09-19 10:45:09 -0700113void CPDF_Stream::SetData(const uint8_t* pData, uint32_t size) {
Artem Strygin4fde70e2017-09-04 17:01:41 +0300114 std::unique_ptr<uint8_t, FxFreeDeleter> data_copy;
115 if (pData) {
116 data_copy.reset(FX_Alloc(uint8_t, size));
117 memcpy(data_copy.get(), pData, size);
118 }
119 SetData(std::move(data_copy), size);
120}
121
122void CPDF_Stream::SetData(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
123 uint32_t size) {
tsepeze6db16e2016-09-19 10:45:09 -0700124 m_bMemoryBased = true;
Artem Strygin4fde70e2017-09-04 17:01:41 +0300125 m_pFile = nullptr;
126 m_pDataBuf = std::move(pData);
Tom Sepez5fc239a2016-03-10 14:10:38 -0800127 m_dwSize = size;
128 if (!m_pDict)
tsepeza9caab92016-12-14 05:57:10 -0800129 m_pDict = pdfium::MakeUnique<CPDF_Dictionary>();
tsepez0e606b52016-11-18 16:22:41 -0800130 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size));
Tom Sepez5fc239a2016-03-10 14:10:38 -0800131}
132
Henrique Nakashimad39443e2017-06-27 16:13:17 -0400133void CPDF_Stream::SetData(std::ostringstream* stream) {
Henrique Nakashimaaa1c7872018-01-30 19:12:10 +0000134 if (stream->tellp() <= 0) {
135 SetData(nullptr, 0);
136 return;
137 }
138
Henrique Nakashimad39443e2017-06-27 16:13:17 -0400139 SetData(reinterpret_cast<const uint8_t*>(stream->str().c_str()),
140 stream->tellp());
141}
142
tsepez12f3e4a2016-11-02 15:17:29 -0700143bool CPDF_Stream::ReadRawData(FX_FILESIZE offset,
144 uint8_t* buf,
145 uint32_t size) const {
Graeme Connellbaf318f2017-02-06 10:52:35 -0700146 if (!m_bMemoryBased && m_pFile)
Tom Sepez5fc239a2016-03-10 14:10:38 -0800147 return m_pFile->ReadBlock(buf, offset, size);
148
149 if (m_pDataBuf)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400150 memcpy(buf, m_pDataBuf.get() + offset, size);
Tom Sepez5fc239a2016-03-10 14:10:38 -0800151
tsepez12f3e4a2016-11-02 15:17:29 -0700152 return true;
Tom Sepez5fc239a2016-03-10 14:10:38 -0800153}
154
tsepez430ab832016-11-18 14:48:21 -0800155bool CPDF_Stream::HasFilter() const {
156 return m_pDict && m_pDict->KeyExist("Filter");
157}
158
Ryan Harrison275e2602017-09-18 14:23:18 -0400159WideString CPDF_Stream::GetUnicodeText() const {
Tom Sepezafd0d1f2017-04-04 14:37:18 -0700160 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this);
Lei Zhang07401ba2017-12-11 22:12:08 +0000161 pAcc->LoadAllDataFiltered();
Tom Sepezafd0d1f2017-04-04 14:37:18 -0700162 return PDF_DecodeText(pAcc->GetData(), pAcc->GetSize());
Tom Sepez5fc239a2016-03-10 14:10:38 -0800163}
Dan Sinclairc68b1e72017-05-08 16:59:54 -0400164
Dan Sinclair5b590332017-05-10 13:59:14 -0400165bool CPDF_Stream::WriteTo(IFX_ArchiveStream* archive) const {
166 if (!GetDict()->WriteTo(archive) || !archive->WriteString("stream\r\n"))
Dan Sinclairc68b1e72017-05-08 16:59:54 -0400167 return false;
Dan Sinclairc68b1e72017-05-08 16:59:54 -0400168
169 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this);
Lei Zhang07401ba2017-12-11 22:12:08 +0000170 pAcc->LoadAllDataRaw();
Dan Sinclair5b590332017-05-10 13:59:14 -0400171 return archive->WriteBlock(pAcc->GetData(), pAcc->GetSize()) &&
172 archive->WriteString("\r\nendstream");
Dan Sinclairc68b1e72017-05-08 16:59:54 -0400173}