1 // Copyright 2017 The PDFium Authors 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_flateencoder.h" 8 9 #include "constants/stream_dict_common.h" 10 #include "core/fpdfapi/parser/cpdf_dictionary.h" 11 #include "core/fpdfapi/parser/cpdf_name.h" 12 #include "core/fpdfapi/parser/cpdf_number.h" 13 #include "core/fpdfapi/parser/cpdf_stream.h" 14 #include "core/fpdfapi/parser/cpdf_stream_acc.h" 15 #include "core/fpdfapi/parser/fpdf_parser_decode.h" 16 #include "core/fxcodec/flate/flatemodule.h" 17 #include "core/fxcrt/check.h" 18 #include "core/fxcrt/numerics/safe_conversions.h" 19 CPDF_FlateEncoder(RetainPtr<const CPDF_Stream> pStream,bool bFlateEncode)20CPDF_FlateEncoder::CPDF_FlateEncoder(RetainPtr<const CPDF_Stream> pStream, 21 bool bFlateEncode) 22 : m_pAcc(pdfium::MakeRetain<CPDF_StreamAcc>(pStream)) { 23 m_pAcc->LoadAllDataRaw(); 24 25 bool bHasFilter = pStream->HasFilter(); 26 if (bHasFilter && !bFlateEncode) { 27 auto pDestAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream); 28 pDestAcc->LoadAllDataFiltered(); 29 30 m_Data = m_pAcc->GetSpan(); 31 m_pClonedDict = ToDictionary(pStream->GetDict()->Clone()); 32 m_pClonedDict->RemoveFor("Filter"); 33 DCHECK(!m_pDict); 34 return; 35 } 36 if (bHasFilter || !bFlateEncode) { 37 m_Data = m_pAcc->GetSpan(); 38 m_pDict = pStream->GetDict(); 39 DCHECK(!m_pClonedDict); 40 return; 41 } 42 43 // TODO(thestig): Move to Init() and check for empty return value? 44 m_Data = FlateModule::Encode(m_pAcc->GetSpan()); 45 m_pClonedDict = ToDictionary(pStream->GetDict()->Clone()); 46 m_pClonedDict->SetNewFor<CPDF_Number>( 47 "Length", pdfium::checked_cast<int>(GetSpan().size())); 48 m_pClonedDict->SetNewFor<CPDF_Name>("Filter", "FlateDecode"); 49 m_pClonedDict->RemoveFor(pdfium::stream::kDecodeParms); 50 DCHECK(!m_pDict); 51 } 52 53 CPDF_FlateEncoder::~CPDF_FlateEncoder() = default; 54 UpdateLength(size_t size)55void CPDF_FlateEncoder::UpdateLength(size_t size) { 56 if (static_cast<size_t>(GetDict()->GetIntegerFor("Length")) == size) 57 return; 58 59 if (!m_pClonedDict) { 60 m_pClonedDict = ToDictionary(m_pDict->Clone()); 61 m_pDict.Reset(); 62 } 63 DCHECK(m_pClonedDict); 64 DCHECK(!m_pDict); 65 m_pClonedDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size)); 66 } 67 WriteDictTo(IFX_ArchiveStream * archive,const CPDF_Encryptor * encryptor) const68bool CPDF_FlateEncoder::WriteDictTo(IFX_ArchiveStream* archive, 69 const CPDF_Encryptor* encryptor) const { 70 return GetDict()->WriteTo(archive, encryptor); 71 } 72 GetDict() const73const CPDF_Dictionary* CPDF_FlateEncoder::GetDict() const { 74 if (m_pClonedDict) { 75 DCHECK(!m_pDict); 76 return m_pClonedDict.Get(); 77 } 78 return m_pDict.Get(); 79 } 80 GetSpan() const81pdfium::span<const uint8_t> CPDF_FlateEncoder::GetSpan() const { 82 if (is_owned()) 83 return absl::get<DataVector<uint8_t>>(m_Data); 84 return absl::get<pdfium::raw_span<const uint8_t>>(m_Data); 85 } 86