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