blob: 7e2529e1d77fbba8deb4737f31825868c9ccce5a [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
dsinclair488b7ad2016-10-04 11:55:50 -070011#include "core/fpdfapi/parser/cpdf_dictionary.h"
tsepez0e606b52016-11-18 16:22:41 -080012#include "core/fpdfapi/parser/cpdf_number.h"
dsinclair488b7ad2016-10-04 11:55:50 -070013#include "core/fpdfapi/parser/cpdf_stream_acc.h"
14#include "core/fpdfapi/parser/fpdf_parser_decode.h"
tsepeze6db16e2016-09-19 10:45:09 -070015#include "third_party/base/numerics/safe_conversions.h"
tsepeza9caab92016-12-14 05:57:10 -080016#include "third_party/base/ptr_util.h"
weilia470b5e2016-08-23 22:08:37 -070017#include "third_party/base/stl_util.h"
Tom Sepez5fc239a2016-03-10 14:10:38 -080018
tsepeze6db16e2016-09-19 10:45:09 -070019CPDF_Stream::CPDF_Stream() {}
20
tsepez47fb8c02016-12-15 13:51:34 -080021CPDF_Stream::CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
tsepez9e05ee12016-11-21 13:19:10 -080022 uint32_t size,
23 std::unique_ptr<CPDF_Dictionary> pDict)
tsepez47fb8c02016-12-15 13:51:34 -080024 : m_dwSize(size), m_pDict(std::move(pDict)), m_pDataBuf(std::move(pData)) {}
Tom Sepez5fc239a2016-03-10 14:10:38 -080025
tsepez836f7d52016-10-10 14:31:05 -070026CPDF_Stream::~CPDF_Stream() {
27 m_ObjNum = kInvalidObjNum;
28 if (m_pDict && m_pDict->GetObjNum() == kInvalidObjNum)
29 m_pDict.release(); // lowercase release, release ownership.
30}
Tom Sepez5fc239a2016-03-10 14:10:38 -080031
32CPDF_Object::Type CPDF_Stream::GetType() const {
33 return STREAM;
34}
35
36CPDF_Dictionary* CPDF_Stream::GetDict() const {
tsepeze6db16e2016-09-19 10:45:09 -070037 return m_pDict.get();
Tom Sepez5fc239a2016-03-10 14:10:38 -080038}
39
40bool CPDF_Stream::IsStream() const {
41 return true;
42}
43
44CPDF_Stream* CPDF_Stream::AsStream() {
45 return this;
46}
47
48const CPDF_Stream* CPDF_Stream::AsStream() const {
49 return this;
50}
51
tsepez596fc4c2016-06-07 06:41:50 -070052void CPDF_Stream::InitStream(const uint8_t* pData,
tsepezb5e8f142016-03-25 15:18:35 -070053 uint32_t size,
tsepez9e05ee12016-11-21 13:19:10 -080054 std::unique_ptr<CPDF_Dictionary> pDict) {
55 m_pDict = std::move(pDict);
tsepeze6db16e2016-09-19 10:45:09 -070056 m_bMemoryBased = true;
57 m_pFile = nullptr;
58 m_pDataBuf.reset(FX_Alloc(uint8_t, size));
Tom Sepez5fc239a2016-03-10 14:10:38 -080059 if (pData)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -040060 memcpy(m_pDataBuf.get(), pData, size);
Tom Sepez5fc239a2016-03-10 14:10:38 -080061 m_dwSize = size;
62 if (m_pDict)
tsepez0e606b52016-11-18 16:22:41 -080063 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize));
tsepeze6db16e2016-09-19 10:45:09 -070064}
65
tsepez833619b2016-12-07 09:21:17 -080066void CPDF_Stream::InitStreamFromFile(
67 const CFX_RetainPtr<IFX_SeekableReadStream>& pFile,
68 std::unique_ptr<CPDF_Dictionary> pDict) {
tsepez9e05ee12016-11-21 13:19:10 -080069 m_pDict = std::move(pDict);
tsepeze6db16e2016-09-19 10:45:09 -070070 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)
tsepez0e606b52016-11-18 16:22:41 -080075 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize));
Tom Sepez5fc239a2016-03-10 14:10:38 -080076}
77
tsepez335cf092016-11-09 13:28:26 -080078std::unique_ptr<CPDF_Object> CPDF_Stream::Clone() const {
weilia470b5e2016-08-23 22:08:37 -070079 return CloneObjectNonCyclic(false);
80}
81
tsepez335cf092016-11-09 13:28:26 -080082std::unique_ptr<CPDF_Object> CPDF_Stream::CloneNonCyclic(
weilia470b5e2016-08-23 22:08:37 -070083 bool bDirect,
84 std::set<const CPDF_Object*>* pVisited) const {
85 pVisited->insert(this);
Tom Sepezafd0d1f2017-04-04 14:37:18 -070086 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this);
87 pAcc->LoadAllData(true);
tsepez9e05ee12016-11-21 13:19:10 -080088
Tom Sepezafd0d1f2017-04-04 14:37:18 -070089 uint32_t streamSize = pAcc->GetSize();
Tom Sepez5fc239a2016-03-10 14:10:38 -080090 CPDF_Dictionary* pDict = GetDict();
tsepez9e05ee12016-11-21 13:19:10 -080091 std::unique_ptr<CPDF_Dictionary> pNewDict;
weilia470b5e2016-08-23 22:08:37 -070092 if (pDict && !pdfium::ContainsKey(*pVisited, pDict)) {
tsepez9e05ee12016-11-21 13:19:10 -080093 pNewDict = ToDictionary(
94 static_cast<CPDF_Object*>(pDict)->CloneNonCyclic(bDirect, pVisited));
weilia470b5e2016-08-23 22:08:37 -070095 }
Tom Sepezafd0d1f2017-04-04 14:37:18 -070096 return pdfium::MakeUnique<CPDF_Stream>(pAcc->DetachData(), streamSize,
tsepez9e05ee12016-11-21 13:19:10 -080097 std::move(pNewDict));
Tom Sepez5fc239a2016-03-10 14:10:38 -080098}
99
tsepeze6db16e2016-09-19 10:45:09 -0700100void 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)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400104 memcpy(m_pDataBuf.get(), pData, size);
Tom Sepez5fc239a2016-03-10 14:10:38 -0800105 m_dwSize = size;
106 if (!m_pDict)
tsepeza9caab92016-12-14 05:57:10 -0800107 m_pDict = pdfium::MakeUnique<CPDF_Dictionary>();
tsepez0e606b52016-11-18 16:22:41 -0800108 m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size));
tsepeze6db16e2016-09-19 10:45:09 -0700109 m_pDict->RemoveFor("Filter");
110 m_pDict->RemoveFor("DecodeParms");
Tom Sepez5fc239a2016-03-10 14:10:38 -0800111}
112
tsepez12f3e4a2016-11-02 15:17:29 -0700113bool CPDF_Stream::ReadRawData(FX_FILESIZE offset,
114 uint8_t* buf,
115 uint32_t size) const {
Graeme Connellbaf318f2017-02-06 10:52:35 -0700116 if (!m_bMemoryBased && m_pFile)
Tom Sepez5fc239a2016-03-10 14:10:38 -0800117 return m_pFile->ReadBlock(buf, offset, size);
118
119 if (m_pDataBuf)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400120 memcpy(buf, m_pDataBuf.get() + offset, size);
Tom Sepez5fc239a2016-03-10 14:10:38 -0800121
tsepez12f3e4a2016-11-02 15:17:29 -0700122 return true;
Tom Sepez5fc239a2016-03-10 14:10:38 -0800123}
124
tsepez430ab832016-11-18 14:48:21 -0800125bool CPDF_Stream::HasFilter() const {
126 return m_pDict && m_pDict->KeyExist("Filter");
127}
128
Tom Sepez5fc239a2016-03-10 14:10:38 -0800129CFX_WideString CPDF_Stream::GetUnicodeText() const {
Tom Sepezafd0d1f2017-04-04 14:37:18 -0700130 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this);
131 pAcc->LoadAllData(false);
132 return PDF_DecodeText(pAcc->GetData(), pAcc->GetSize());
Tom Sepez5fc239a2016-03-10 14:10:38 -0800133}
Dan Sinclairc68b1e72017-05-08 16:59:54 -0400134
135bool CPDF_Stream::WriteTo(CFX_FileBufferArchive* archive,
136 FX_FILESIZE* offset) const {
137 if (!GetDict()->WriteTo(archive, offset))
138 return false;
139 if (archive->AppendString("stream\r\n") < 0)
140 return false;
141 *offset += 8;
142
143 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(this);
144 pAcc->LoadAllData(true);
145 if (archive->AppendBlock(pAcc->GetData(), pAcc->GetSize()) < 0)
146 return false;
147 *offset += pAcc->GetSize();
148
149 int32_t len = archive->AppendString("\r\nendstream");
150 if (len < 0)
151 return false;
152
153 *offset += len;
154 return true;
155}