Home | History | Annotate | Download | only in parser
      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 "third_party/base/numerics/safe_conversions.h"
     16 #include "third_party/base/ptr_util.h"
     17 #include "third_party/base/stl_util.h"
     18 
     19 CPDF_Stream::CPDF_Stream() {}
     20 
     21 CPDF_Stream::CPDF_Stream(std::unique_ptr<uint8_t, FxFreeDeleter> pData,
     22                          uint32_t size,
     23                          std::unique_ptr<CPDF_Dictionary> pDict)
     24     : m_dwSize(size), m_pDict(std::move(pDict)), m_pDataBuf(std::move(pData)) {}
     25 
     26 CPDF_Stream::~CPDF_Stream() {
     27   m_ObjNum = kInvalidObjNum;
     28   if (m_pDict && m_pDict->GetObjNum() == kInvalidObjNum)
     29     m_pDict.release();  // lowercase release, release ownership.
     30 }
     31 
     32 CPDF_Object::Type CPDF_Stream::GetType() const {
     33   return STREAM;
     34 }
     35 
     36 CPDF_Dictionary* CPDF_Stream::GetDict() const {
     37   return m_pDict.get();
     38 }
     39 
     40 bool CPDF_Stream::IsStream() const {
     41   return true;
     42 }
     43 
     44 CPDF_Stream* CPDF_Stream::AsStream() {
     45   return this;
     46 }
     47 
     48 const CPDF_Stream* CPDF_Stream::AsStream() const {
     49   return this;
     50 }
     51 
     52 void CPDF_Stream::InitStream(const uint8_t* pData,
     53                              uint32_t size,
     54                              std::unique_ptr<CPDF_Dictionary> pDict) {
     55   m_pDict = std::move(pDict);
     56   m_bMemoryBased = true;
     57   m_pFile = nullptr;
     58   m_pDataBuf.reset(FX_Alloc(uint8_t, size));
     59   if (pData)
     60     FXSYS_memcpy(m_pDataBuf.get(), pData, size);
     61   m_dwSize = size;
     62   if (m_pDict)
     63     m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize));
     64 }
     65 
     66 void CPDF_Stream::InitStreamFromFile(
     67     const CFX_RetainPtr<IFX_SeekableReadStream>& pFile,
     68     std::unique_ptr<CPDF_Dictionary> pDict) {
     69   m_pDict = std::move(pDict);
     70   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)
     75     m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize));
     76 }
     77 
     78 std::unique_ptr<CPDF_Object> CPDF_Stream::Clone() const {
     79   return CloneObjectNonCyclic(false);
     80 }
     81 
     82 std::unique_ptr<CPDF_Object> CPDF_Stream::CloneNonCyclic(
     83     bool bDirect,
     84     std::set<const CPDF_Object*>* pVisited) const {
     85   pVisited->insert(this);
     86   CPDF_StreamAcc acc;
     87   acc.LoadAllData(this, true);
     88 
     89   uint32_t streamSize = acc.GetSize();
     90   CPDF_Dictionary* pDict = GetDict();
     91   std::unique_ptr<CPDF_Dictionary> pNewDict;
     92   if (pDict && !pdfium::ContainsKey(*pVisited, pDict)) {
     93     pNewDict = ToDictionary(
     94         static_cast<CPDF_Object*>(pDict)->CloneNonCyclic(bDirect, pVisited));
     95   }
     96   return pdfium::MakeUnique<CPDF_Stream>(acc.DetachData(), streamSize,
     97                                          std::move(pNewDict));
     98 }
     99 
    100 void 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)
    104     FXSYS_memcpy(m_pDataBuf.get(), pData, size);
    105   m_dwSize = size;
    106   if (!m_pDict)
    107     m_pDict = pdfium::MakeUnique<CPDF_Dictionary>();
    108   m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size));
    109   m_pDict->RemoveFor("Filter");
    110   m_pDict->RemoveFor("DecodeParms");
    111 }
    112 
    113 bool CPDF_Stream::ReadRawData(FX_FILESIZE offset,
    114                               uint8_t* buf,
    115                               uint32_t size) const {
    116   if (!m_bMemoryBased && m_pFile)
    117     return m_pFile->ReadBlock(buf, offset, size);
    118 
    119   if (m_pDataBuf)
    120     FXSYS_memcpy(buf, m_pDataBuf.get() + offset, size);
    121 
    122   return true;
    123 }
    124 
    125 bool CPDF_Stream::HasFilter() const {
    126   return m_pDict && m_pDict->KeyExist("Filter");
    127 }
    128 
    129 CFX_WideString CPDF_Stream::GetUnicodeText() const {
    130   CPDF_StreamAcc stream;
    131   stream.LoadAllData(this, false);
    132   return PDF_DecodeText(stream.GetData(), stream.GetSize());
    133 }
    134