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 "third_party/base/check.h" 17 #include "third_party/base/numerics/safe_conversions.h" 18 CPDF_FlateEncoder(RetainPtr<const CPDF_Stream> pStream,bool bFlateEncode)19CPDF_FlateEncoder::CPDF_FlateEncoder(RetainPtr<const CPDF_Stream> pStream, 20 bool bFlateEncode) 21 : m_pAcc(pdfium::MakeRetain<CPDF_StreamAcc>(pStream)) { 22 m_pAcc->LoadAllDataRaw(); 23 24 bool bHasFilter = pStream->HasFilter(); 25 if (bHasFilter && !bFlateEncode) { 26 auto pDestAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream); 27 pDestAcc->LoadAllDataFiltered(); 28 29 m_Data = m_pAcc->GetSpan(); 30 m_pClonedDict = ToDictionary(pStream->GetDict()->Clone()); 31 m_pClonedDict->RemoveFor("Filter"); 32 DCHECK(!m_pDict); 33 return; 34 } 35 if (bHasFilter || !bFlateEncode) { 36 m_Data = m_pAcc->GetSpan(); 37 m_pDict = pStream->GetDict(); 38 DCHECK(!m_pClonedDict); 39 return; 40 } 41 42 // TODO(thestig): Move to Init() and check for empty return value? 43 m_Data = ::FlateEncode(m_pAcc->GetSpan()); 44 m_pClonedDict = ToDictionary(pStream->GetDict()->Clone()); 45 m_pClonedDict->SetNewFor<CPDF_Number>( 46 "Length", pdfium::base::checked_cast<int>(GetSpan().size())); 47 m_pClonedDict->SetNewFor<CPDF_Name>("Filter", "FlateDecode"); 48 m_pClonedDict->RemoveFor(pdfium::stream::kDecodeParms); 49 DCHECK(!m_pDict); 50 } 51 52 CPDF_FlateEncoder::~CPDF_FlateEncoder() = default; 53 UpdateLength(size_t size)54void CPDF_FlateEncoder::UpdateLength(size_t size) { 55 if (static_cast<size_t>(GetDict()->GetIntegerFor("Length")) == size) 56 return; 57 58 if (!m_pClonedDict) { 59 m_pClonedDict = ToDictionary(m_pDict->Clone()); 60 m_pDict.Reset(); 61 } 62 DCHECK(m_pClonedDict); 63 DCHECK(!m_pDict); 64 m_pClonedDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size)); 65 } 66 WriteDictTo(IFX_ArchiveStream * archive,const CPDF_Encryptor * encryptor) const67bool CPDF_FlateEncoder::WriteDictTo(IFX_ArchiveStream* archive, 68 const CPDF_Encryptor* encryptor) const { 69 return GetDict()->WriteTo(archive, encryptor); 70 } 71 GetDict() const72const CPDF_Dictionary* CPDF_FlateEncoder::GetDict() const { 73 if (m_pClonedDict) { 74 DCHECK(!m_pDict); 75 return m_pClonedDict.Get(); 76 } 77 return m_pDict.Get(); 78 } 79 GetSpan() const80pdfium::span<const uint8_t> CPDF_FlateEncoder::GetSpan() const { 81 if (is_owned()) 82 return absl::get<DataVector<uint8_t>>(m_Data); 83 return absl::get<pdfium::span<const uint8_t>>(m_Data); 84 } 85