Home | History | Annotate | Download | only in fpdfsdk
      1 // Copyright 2014 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 "public/fpdf_dataavail.h"
      8 
      9 #include <memory>
     10 #include <utility>
     11 
     12 #include "core/fpdfapi/parser/cpdf_data_avail.h"
     13 #include "core/fpdfapi/parser/cpdf_document.h"
     14 #include "core/fxcrt/fx_stream.h"
     15 #include "core/fxcrt/retain_ptr.h"
     16 #include "fpdfsdk/fsdk_define.h"
     17 #include "public/fpdf_formfill.h"
     18 #include "third_party/base/ptr_util.h"
     19 
     20 // These checks are here because core/ and public/ cannot depend on each other.
     21 static_assert(CPDF_DataAvail::DataError == PDF_DATA_ERROR,
     22               "CPDF_DataAvail::DataError value mismatch");
     23 static_assert(CPDF_DataAvail::DataNotAvailable == PDF_DATA_NOTAVAIL,
     24               "CPDF_DataAvail::DataNotAvailable value mismatch");
     25 static_assert(CPDF_DataAvail::DataAvailable == PDF_DATA_AVAIL,
     26               "CPDF_DataAvail::DataAvailable value mismatch");
     27 
     28 static_assert(CPDF_DataAvail::LinearizationUnknown == PDF_LINEARIZATION_UNKNOWN,
     29               "CPDF_DataAvail::LinearizationUnknown value mismatch");
     30 static_assert(CPDF_DataAvail::NotLinearized == PDF_NOT_LINEARIZED,
     31               "CPDF_DataAvail::NotLinearized value mismatch");
     32 static_assert(CPDF_DataAvail::Linearized == PDF_LINEARIZED,
     33               "CPDF_DataAvail::Linearized value mismatch");
     34 
     35 static_assert(CPDF_DataAvail::FormError == PDF_FORM_ERROR,
     36               "CPDF_DataAvail::FormError value mismatch");
     37 static_assert(CPDF_DataAvail::FormNotAvailable == PDF_FORM_NOTAVAIL,
     38               "CPDF_DataAvail::FormNotAvailable value mismatch");
     39 static_assert(CPDF_DataAvail::FormAvailable == PDF_FORM_AVAIL,
     40               "CPDF_DataAvail::FormAvailable value mismatch");
     41 static_assert(CPDF_DataAvail::FormNotExist == PDF_FORM_NOTEXIST,
     42               "CPDF_DataAvail::FormNotExist value mismatch");
     43 
     44 namespace {
     45 
     46 class FPDF_FileAvailContext : public CPDF_DataAvail::FileAvail {
     47  public:
     48   FPDF_FileAvailContext() : m_pfileAvail(nullptr) {}
     49   ~FPDF_FileAvailContext() override {}
     50 
     51   void Set(FX_FILEAVAIL* pfileAvail) { m_pfileAvail = pfileAvail; }
     52 
     53   // CPDF_DataAvail::FileAvail:
     54   bool IsDataAvail(FX_FILESIZE offset, size_t size) override {
     55     return !!m_pfileAvail->IsDataAvail(m_pfileAvail, offset, size);
     56   }
     57 
     58  private:
     59   FX_FILEAVAIL* m_pfileAvail;
     60 };
     61 
     62 class FPDF_FileAccessContext : public IFX_SeekableReadStream {
     63  public:
     64   template <typename T, typename... Args>
     65   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
     66 
     67   ~FPDF_FileAccessContext() override {}
     68 
     69   void Set(FPDF_FILEACCESS* pFile) { m_pFileAccess = pFile; }
     70 
     71   // IFX_SeekableReadStream
     72   FX_FILESIZE GetSize() override { return m_pFileAccess->m_FileLen; }
     73 
     74   bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
     75     return !!m_pFileAccess->m_GetBlock(m_pFileAccess->m_Param, offset,
     76                                        (uint8_t*)buffer, size);
     77   }
     78 
     79  private:
     80   FPDF_FileAccessContext() : m_pFileAccess(nullptr) {}
     81 
     82   FPDF_FILEACCESS* m_pFileAccess;
     83 };
     84 
     85 class FPDF_DownloadHintsContext : public CPDF_DataAvail::DownloadHints {
     86  public:
     87   explicit FPDF_DownloadHintsContext(FX_DOWNLOADHINTS* pDownloadHints) {
     88     m_pDownloadHints = pDownloadHints;
     89   }
     90   ~FPDF_DownloadHintsContext() override {}
     91 
     92  public:
     93   // IFX_DownloadHints
     94   void AddSegment(FX_FILESIZE offset, size_t size) override {
     95     if (m_pDownloadHints)
     96       m_pDownloadHints->AddSegment(m_pDownloadHints, offset, size);
     97   }
     98 
     99  private:
    100   FX_DOWNLOADHINTS* m_pDownloadHints;
    101 };
    102 
    103 class FPDF_AvailContext {
    104  public:
    105   FPDF_AvailContext()
    106       : m_FileAvail(pdfium::MakeUnique<FPDF_FileAvailContext>()),
    107         m_FileRead(pdfium::MakeRetain<FPDF_FileAccessContext>()) {}
    108   ~FPDF_AvailContext() {}
    109 
    110   std::unique_ptr<FPDF_FileAvailContext> m_FileAvail;
    111   RetainPtr<FPDF_FileAccessContext> m_FileRead;
    112   std::unique_ptr<CPDF_DataAvail> m_pDataAvail;
    113 };
    114 
    115 FPDF_AvailContext* FPDFAvailContextFromFPDFAvail(FPDF_AVAIL avail) {
    116   return static_cast<FPDF_AvailContext*>(avail);
    117 }
    118 
    119 }  // namespace
    120 
    121 FPDF_EXPORT FPDF_AVAIL FPDF_CALLCONV FPDFAvail_Create(FX_FILEAVAIL* file_avail,
    122                                                       FPDF_FILEACCESS* file) {
    123   auto pAvail = pdfium::MakeUnique<FPDF_AvailContext>();
    124   pAvail->m_FileAvail->Set(file_avail);
    125   pAvail->m_FileRead->Set(file);
    126   pAvail->m_pDataAvail = pdfium::MakeUnique<CPDF_DataAvail>(
    127       pAvail->m_FileAvail.get(), pAvail->m_FileRead, true);
    128   return pAvail.release();  // Caller takes ownership.
    129 }
    130 
    131 FPDF_EXPORT void FPDF_CALLCONV FPDFAvail_Destroy(FPDF_AVAIL avail) {
    132   // Take ownership back from caller and destroy.
    133   std::unique_ptr<FPDF_AvailContext>(FPDFAvailContextFromFPDFAvail(avail));
    134 }
    135 
    136 FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsDocAvail(FPDF_AVAIL avail,
    137                                                    FX_DOWNLOADHINTS* hints) {
    138   if (!avail)
    139     return PDF_DATA_ERROR;
    140   FPDF_DownloadHintsContext hints_context(hints);
    141   return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsDocAvail(
    142       &hints_context);
    143 }
    144 
    145 FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
    146 FPDFAvail_GetDocument(FPDF_AVAIL avail, FPDF_BYTESTRING password) {
    147   auto* pDataAvail = FPDFAvailContextFromFPDFAvail(avail);
    148   if (!pDataAvail)
    149     return nullptr;
    150   CPDF_Parser::Error error;
    151   std::unique_ptr<CPDF_Document> document;
    152   std::tie(error, document) = pDataAvail->m_pDataAvail->ParseDocument(password);
    153   if (error != CPDF_Parser::SUCCESS) {
    154     ProcessParseError(error);
    155     return nullptr;
    156   }
    157   CheckUnSupportError(document.get(), FPDF_ERR_SUCCESS);
    158   return FPDFDocumentFromCPDFDocument(document.release());
    159 }
    160 
    161 FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc) {
    162   CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
    163   return pDoc ? pDoc->GetParser()->GetFirstPageNo() : 0;
    164 }
    165 
    166 FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsPageAvail(FPDF_AVAIL avail,
    167                                                     int page_index,
    168                                                     FX_DOWNLOADHINTS* hints) {
    169   if (!avail)
    170     return PDF_DATA_ERROR;
    171   if (page_index < 0)
    172     return PDF_DATA_NOTAVAIL;
    173   FPDF_DownloadHintsContext hints_context(hints);
    174   return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsPageAvail(
    175       page_index, &hints_context);
    176 }
    177 
    178 FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsFormAvail(FPDF_AVAIL avail,
    179                                                     FX_DOWNLOADHINTS* hints) {
    180   if (!avail)
    181     return PDF_FORM_ERROR;
    182   FPDF_DownloadHintsContext hints_context(hints);
    183   return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsFormAvail(
    184       &hints_context);
    185 }
    186 
    187 FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsLinearized(FPDF_AVAIL avail) {
    188   if (!avail)
    189     return PDF_LINEARIZATION_UNKNOWN;
    190   return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsLinearizedPDF();
    191 }
    192