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. 21static_assert(CPDF_DataAvail::DataError == PDF_DATA_ERROR, 22 "CPDF_DataAvail::DataError value mismatch"); 23static_assert(CPDF_DataAvail::DataNotAvailable == PDF_DATA_NOTAVAIL, 24 "CPDF_DataAvail::DataNotAvailable value mismatch"); 25static_assert(CPDF_DataAvail::DataAvailable == PDF_DATA_AVAIL, 26 "CPDF_DataAvail::DataAvailable value mismatch"); 27 28static_assert(CPDF_DataAvail::LinearizationUnknown == PDF_LINEARIZATION_UNKNOWN, 29 "CPDF_DataAvail::LinearizationUnknown value mismatch"); 30static_assert(CPDF_DataAvail::NotLinearized == PDF_NOT_LINEARIZED, 31 "CPDF_DataAvail::NotLinearized value mismatch"); 32static_assert(CPDF_DataAvail::Linearized == PDF_LINEARIZED, 33 "CPDF_DataAvail::Linearized value mismatch"); 34 35static_assert(CPDF_DataAvail::FormError == PDF_FORM_ERROR, 36 "CPDF_DataAvail::FormError value mismatch"); 37static_assert(CPDF_DataAvail::FormNotAvailable == PDF_FORM_NOTAVAIL, 38 "CPDF_DataAvail::FormNotAvailable value mismatch"); 39static_assert(CPDF_DataAvail::FormAvailable == PDF_FORM_AVAIL, 40 "CPDF_DataAvail::FormAvailable value mismatch"); 41static_assert(CPDF_DataAvail::FormNotExist == PDF_FORM_NOTEXIST, 42 "CPDF_DataAvail::FormNotExist value mismatch"); 43 44namespace { 45 46class 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 62class 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 85class 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 103class 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 115FPDF_AvailContext* FPDFAvailContextFromFPDFAvail(FPDF_AVAIL avail) { 116 return static_cast<FPDF_AvailContext*>(avail); 117} 118 119} // namespace 120 121FPDF_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 131FPDF_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 136FPDF_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 145FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV 146FPDFAvail_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 161FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc) { 162 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc); 163 return pDoc ? pDoc->GetParser()->GetFirstPageNo() : 0; 164} 165 166FPDF_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 178FPDF_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 187FPDF_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