blob: 6a0cf8548287e92feebc5f2d6aef82c44c51ab8e [file] [log] [blame]
Dan Sinclair7aba4722018-03-28 17:04:16 +00001// Copyright 2018 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
Dan Sinclair00d47a62018-03-28 18:39:04 +00007#include "fpdfsdk/cpdfsdk_helpers.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +00008
Lei Zhang26170562018-04-17 17:01:52 +00009#include "constants/stream_dict_common.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000010#include "core/fpdfapi/cpdf_modulemgr.h"
Tom Sepeza1d34422018-04-24 20:54:41 +000011#include "core/fpdfapi/page/cpdf_page.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000012#include "core/fpdfapi/parser/cpdf_array.h"
Lei Zhang81535612018-10-09 21:15:17 +000013#include "core/fpdfapi/parser/cpdf_dictionary.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000014#include "core/fpdfapi/parser/cpdf_document.h"
Artem Strygineababa12018-06-06 12:31:18 +000015#include "core/fpdfapi/parser/cpdf_stream_acc.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000016#include "core/fpdfdoc/cpdf_annot.h"
Lei Zhangc3450652018-10-11 16:54:42 +000017#include "core/fpdfdoc/cpdf_interactiveform.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000018#include "core/fpdfdoc/cpdf_metadata.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000019#include "public/fpdf_ext.h"
20
Tom Sepeza1d34422018-04-24 20:54:41 +000021#ifdef PDF_ENABLE_XFA
22#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
23#endif
24
Dan Sinclair7aba4722018-03-28 17:04:16 +000025namespace {
26
Ralf Sippl16381792018-04-12 21:20:26 +000027constexpr char kQuadPoints[] = "QuadPoints";
28
Dan Sinclair7aba4722018-03-28 17:04:16 +000029bool RaiseUnSupportError(int nError) {
30 CFSDK_UnsupportInfo_Adapter* pAdapter =
31 CPDF_ModuleMgr::Get()->GetUnsupportInfoAdapter();
32 if (!pAdapter)
33 return false;
34
35 UNSUPPORT_INFO* info = static_cast<UNSUPPORT_INFO*>(pAdapter->GetUnspInfo());
36 if (info && info->FSDK_UnSupport_Handler)
37 info->FSDK_UnSupport_Handler(info, nError);
38 return true;
39}
40
Dan Sinclair7aba4722018-03-28 17:04:16 +000041#ifdef PDF_ENABLE_XFA
Tom Sepez55865452018-08-27 20:18:04 +000042class FPDF_FileHandlerContext final : public IFX_SeekableStream {
Dan Sinclair7aba4722018-03-28 17:04:16 +000043 public:
44 template <typename T, typename... Args>
45 friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
46
Dan Sinclair7aba4722018-03-28 17:04:16 +000047 // IFX_SeekableStream:
48 FX_FILESIZE GetSize() override;
49 bool IsEOF() override;
50 FX_FILESIZE GetPosition() override;
51 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
52 size_t ReadBlock(void* buffer, size_t size) override;
53 bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
54 bool Flush() override;
55
56 void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
57
Tom Sepezcb798252018-09-17 18:25:32 +000058 private:
Dan Sinclair7aba4722018-03-28 17:04:16 +000059 explicit FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS);
Lei Zhang86688de2018-05-22 22:06:49 +000060 ~FPDF_FileHandlerContext() override;
Dan Sinclair7aba4722018-03-28 17:04:16 +000061
62 FPDF_FILEHANDLER* m_pFS;
63 FX_FILESIZE m_nCurPos;
64};
65
66FPDF_FileHandlerContext::FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS) {
67 m_pFS = pFS;
68 m_nCurPos = 0;
69}
70
71FPDF_FileHandlerContext::~FPDF_FileHandlerContext() {
72 if (m_pFS && m_pFS->Release)
73 m_pFS->Release(m_pFS->clientData);
74}
75
76FX_FILESIZE FPDF_FileHandlerContext::GetSize() {
77 if (m_pFS && m_pFS->GetSize)
78 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
79 return 0;
80}
81
82bool FPDF_FileHandlerContext::IsEOF() {
83 return m_nCurPos >= GetSize();
84}
85
86FX_FILESIZE FPDF_FileHandlerContext::GetPosition() {
87 return m_nCurPos;
88}
89
90bool FPDF_FileHandlerContext::ReadBlock(void* buffer,
91 FX_FILESIZE offset,
92 size_t size) {
93 if (!buffer || !size || !m_pFS->ReadBlock)
94 return false;
95
96 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
97 (FPDF_DWORD)size) == 0) {
98 m_nCurPos = offset + size;
99 return true;
100 }
101 return false;
102}
103
104size_t FPDF_FileHandlerContext::ReadBlock(void* buffer, size_t size) {
105 if (!buffer || !size || !m_pFS->ReadBlock)
106 return 0;
107
108 FX_FILESIZE nSize = GetSize();
109 if (m_nCurPos >= nSize)
110 return 0;
111 FX_FILESIZE dwAvail = nSize - m_nCurPos;
112 if (dwAvail < (FX_FILESIZE)size)
113 size = static_cast<size_t>(dwAvail);
114 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
115 (FPDF_DWORD)size) == 0) {
116 m_nCurPos += size;
117 return size;
118 }
119
120 return 0;
121}
122
123bool FPDF_FileHandlerContext::WriteBlock(const void* buffer,
124 FX_FILESIZE offset,
125 size_t size) {
126 if (!m_pFS || !m_pFS->WriteBlock)
127 return false;
128
129 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
130 (FPDF_DWORD)size) == 0) {
131 m_nCurPos = offset + size;
132 return true;
133 }
134 return false;
135}
136
137bool FPDF_FileHandlerContext::Flush() {
138 if (!m_pFS || !m_pFS->Flush)
139 return true;
140
141 return m_pFS->Flush(m_pFS->clientData) == 0;
142}
143#endif // PDF_ENABLE_XFA
144
145} // namespace
146
Tom Sepez101535f2018-06-12 13:36:05 +0000147IPDF_Page* IPDFPageFromFPDFPage(FPDF_PAGE page) {
148 return reinterpret_cast<IPDF_Page*>(page);
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000149}
150
Tom Sepez101535f2018-06-12 13:36:05 +0000151FPDF_PAGE FPDFPageFromIPDFPage(IPDF_Page* page) {
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000152 return reinterpret_cast<FPDF_PAGE>(page);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000153}
154
155CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000156 return reinterpret_cast<CPDF_Document*>(doc);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000157}
158
159FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000160 return reinterpret_cast<FPDF_DOCUMENT>(doc);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000161}
162
163CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
Tom Sepez101535f2018-06-12 13:36:05 +0000164 return page ? IPDFPageFromFPDFPage(page)->AsPDFPage() : nullptr;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000165}
166
Dan Sinclair7aba4722018-03-28 17:04:16 +0000167ByteString CFXByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string) {
168 return WideString::FromUTF16LE(wide_string,
169 WideString::WStringLength(wide_string))
170 .UTF8Encode();
171}
172
Dan Sinclair7aba4722018-03-28 17:04:16 +0000173void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot) {
174 CPDF_Annot::Subtype nAnnotSubtype = pPDFAnnot->GetSubtype();
175 if (nAnnotSubtype == CPDF_Annot::Subtype::THREED) {
176 RaiseUnSupportError(FPDF_UNSP_ANNOT_3DANNOT);
177 } else if (nAnnotSubtype == CPDF_Annot::Subtype::SCREEN) {
178 const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict();
179 ByteString cbString;
180 if (pAnnotDict->KeyExist("IT"))
181 cbString = pAnnotDict->GetStringFor("IT");
182 if (cbString.Compare("Img") != 0)
183 RaiseUnSupportError(FPDF_UNSP_ANNOT_SCREEN_MEDIA);
184 } else if (nAnnotSubtype == CPDF_Annot::Subtype::MOVIE) {
185 RaiseUnSupportError(FPDF_UNSP_ANNOT_MOVIE);
186 } else if (nAnnotSubtype == CPDF_Annot::Subtype::SOUND) {
187 RaiseUnSupportError(FPDF_UNSP_ANNOT_SOUND);
188 } else if (nAnnotSubtype == CPDF_Annot::Subtype::RICHMEDIA) {
189 RaiseUnSupportError(FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA);
190 } else if (nAnnotSubtype == CPDF_Annot::Subtype::FILEATTACHMENT) {
191 RaiseUnSupportError(FPDF_UNSP_ANNOT_ATTACHMENT);
192 } else if (nAnnotSubtype == CPDF_Annot::Subtype::WIDGET) {
193 const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict();
194 ByteString cbString;
195 if (pAnnotDict->KeyExist("FT"))
196 cbString = pAnnotDict->GetStringFor("FT");
197 if (cbString.Compare("Sig") == 0)
198 RaiseUnSupportError(FPDF_UNSP_ANNOT_SIG);
199 }
200}
201
Tom Sepez81284852018-06-12 19:26:15 +0000202void ReportUnsupportedFeatures(CPDF_Document* pDoc) {
Dan Sinclair7aba4722018-03-28 17:04:16 +0000203 const CPDF_Dictionary* pRootDict = pDoc->GetRoot();
204 if (pRootDict) {
Tom Sepezca0273392018-05-25 23:37:50 +0000205 // Portfolios and Packages
Dan Sinclair7aba4722018-03-28 17:04:16 +0000206 if (pRootDict->KeyExist("Collection")) {
207 RaiseUnSupportError(FPDF_UNSP_DOC_PORTABLECOLLECTION);
208 return;
209 }
210 if (pRootDict->KeyExist("Names")) {
Lei Zhang5cee3f22018-05-25 21:48:49 +0000211 const CPDF_Dictionary* pNameDict = pRootDict->GetDictFor("Names");
Dan Sinclair7aba4722018-03-28 17:04:16 +0000212 if (pNameDict && pNameDict->KeyExist("EmbeddedFiles")) {
213 RaiseUnSupportError(FPDF_UNSP_DOC_ATTACHMENT);
214 return;
215 }
216 if (pNameDict && pNameDict->KeyExist("JavaScript")) {
Lei Zhang5cee3f22018-05-25 21:48:49 +0000217 const CPDF_Dictionary* pJSDict = pNameDict->GetDictFor("JavaScript");
218 const CPDF_Array* pArray =
219 pJSDict ? pJSDict->GetArrayFor("Names") : nullptr;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000220 if (pArray) {
221 for (size_t i = 0; i < pArray->GetCount(); i++) {
222 ByteString cbStr = pArray->GetStringAt(i);
223 if (cbStr.Compare("com.adobe.acrobat.SharedReview.Register") == 0) {
224 RaiseUnSupportError(FPDF_UNSP_DOC_SHAREDREVIEW);
225 return;
226 }
227 }
228 }
229 }
230 }
Tom Sepez81284852018-06-12 19:26:15 +0000231
Tom Sepezca0273392018-05-25 23:37:50 +0000232 // SharedForm
233 const CPDF_Stream* pStream = pRootDict->GetStreamFor("Metadata");
dan sinclaire04b66c2018-04-13 16:43:05 +0000234 if (pStream) {
235 CPDF_Metadata metaData(pStream);
236 for (const auto& err : metaData.CheckForSharedForm())
237 RaiseUnSupportError(static_cast<int>(err));
238 }
239 }
Dan Sinclair7aba4722018-03-28 17:04:16 +0000240
Dan Sinclair7aba4722018-03-28 17:04:16 +0000241 // XFA Forms
Tom Sepeza3843c92018-06-12 19:21:46 +0000242 if (!pDoc->GetExtension() && CPDF_InterForm(pDoc).HasXFAForm())
Dan Sinclair7aba4722018-03-28 17:04:16 +0000243 RaiseUnSupportError(FPDF_UNSP_DOC_XFAFORM);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000244}
245
246#ifndef _WIN32
247int g_LastError;
248void SetLastError(int err) {
249 g_LastError = err;
250}
251
252int GetLastError() {
253 return g_LastError;
254}
255#endif // _WIN32
256
257void ProcessParseError(CPDF_Parser::Error err) {
258 uint32_t err_code = FPDF_ERR_SUCCESS;
259 // Translate FPDFAPI error code to FPDFVIEW error code
260 switch (err) {
261 case CPDF_Parser::SUCCESS:
262 err_code = FPDF_ERR_SUCCESS;
263 break;
264 case CPDF_Parser::FILE_ERROR:
265 err_code = FPDF_ERR_FILE;
266 break;
267 case CPDF_Parser::FORMAT_ERROR:
268 err_code = FPDF_ERR_FORMAT;
269 break;
270 case CPDF_Parser::PASSWORD_ERROR:
271 err_code = FPDF_ERR_PASSWORD;
272 break;
273 case CPDF_Parser::HANDLER_ERROR:
274 err_code = FPDF_ERR_SECURITY;
275 break;
276 }
277 SetLastError(err_code);
278}
279
280// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
281static uint32_t foxit_sandbox_policy = 0xFFFFFFFF;
282
283void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
284 switch (policy) {
285 case FPDF_POLICY_MACHINETIME_ACCESS: {
286 if (enable)
287 foxit_sandbox_policy |= 0x01;
288 else
289 foxit_sandbox_policy &= 0xFFFFFFFE;
290 } break;
291 default:
292 break;
293 }
294}
295
296FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
297 switch (policy) {
298 case FPDF_POLICY_MACHINETIME_ACCESS:
299 return !!(foxit_sandbox_policy & 0x01);
300 default:
301 return false;
302 }
303}
304
305unsigned long DecodeStreamMaybeCopyAndReturnLength(const CPDF_Stream* stream,
306 void* buffer,
307 unsigned long buflen) {
308 ASSERT(stream);
Artem Strygineababa12018-06-06 12:31:18 +0000309 auto stream_acc = pdfium::MakeRetain<CPDF_StreamAcc>(stream);
310 stream_acc->LoadAllDataFiltered();
311 const auto stream_data_size = stream_acc->GetSize();
312 if (!buffer || buflen < stream_data_size)
313 return stream_data_size;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000314
Artem Strygineababa12018-06-06 12:31:18 +0000315 memcpy(buffer, stream_acc->GetData(), stream_data_size);
316 return stream_data_size;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000317}
318
319unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text,
320 void* buffer,
321 unsigned long buflen) {
322 ByteString encoded_text = text.UTF16LE_Encode();
323 unsigned long len = encoded_text.GetLength();
324 if (buffer && len <= buflen)
325 memcpy(buffer, encoded_text.c_str(), len);
326 return len;
327}
328
329void FSRECTFFromCFXFloatRect(const CFX_FloatRect& rect, FS_RECTF* out_rect) {
330 out_rect->left = rect.left;
331 out_rect->top = rect.top;
332 out_rect->right = rect.right;
333 out_rect->bottom = rect.bottom;
334}
335
336CFX_FloatRect CFXFloatRectFromFSRECTF(const FS_RECTF& rect) {
337 return CFX_FloatRect(rect.left, rect.bottom, rect.right, rect.top);
338}
339
Lei Zhang5cee3f22018-05-25 21:48:49 +0000340const CPDF_Array* GetQuadPointsArrayFromDictionary(
341 const CPDF_Dictionary* dict) {
342 return dict ? dict->GetArrayFor("QuadPoints") : nullptr;
343}
344
345CPDF_Array* GetQuadPointsArrayFromDictionary(CPDF_Dictionary* dict) {
Dan Sinclair7aba4722018-03-28 17:04:16 +0000346 return dict ? dict->GetArrayFor("QuadPoints") : nullptr;
347}
348
Ralf Sippl16381792018-04-12 21:20:26 +0000349CPDF_Array* AddQuadPointsArrayToDictionary(CPDF_Dictionary* dict) {
350 if (!dict)
351 return nullptr;
352 return dict->SetNewFor<CPDF_Array>(kQuadPoints);
353}
354
355bool IsValidQuadPointsIndex(const CPDF_Array* array, size_t index) {
356 return array && index < array->GetCount() / 8;
357}
358
359bool GetQuadPointsAtIndex(const CPDF_Array* array,
360 size_t quad_index,
361 FS_QUADPOINTSF* quad_points) {
362 ASSERT(quad_points);
363 ASSERT(array);
364
365 if (!IsValidQuadPointsIndex(array, quad_index))
366 return false;
367
368 quad_index *= 8;
369 quad_points->x1 = array->GetNumberAt(quad_index);
370 quad_points->y1 = array->GetNumberAt(quad_index + 1);
371 quad_points->x2 = array->GetNumberAt(quad_index + 2);
372 quad_points->y2 = array->GetNumberAt(quad_index + 3);
373 quad_points->x3 = array->GetNumberAt(quad_index + 4);
374 quad_points->y3 = array->GetNumberAt(quad_index + 5);
375 quad_points->x4 = array->GetNumberAt(quad_index + 6);
376 quad_points->y4 = array->GetNumberAt(quad_index + 7);
377 return true;
378}
379
Dan Sinclair7aba4722018-03-28 17:04:16 +0000380bool GetQuadPointsFromDictionary(CPDF_Dictionary* dict,
381 size_t quad_index,
382 FS_QUADPOINTSF* quad_points) {
383 ASSERT(quad_points);
384
385 const CPDF_Array* pArray = GetQuadPointsArrayFromDictionary(dict);
386 if (!pArray || quad_index >= pArray->GetCount() / 8)
387 return false;
388
389 quad_index *= 8;
390 quad_points->x1 = pArray->GetNumberAt(quad_index);
391 quad_points->y1 = pArray->GetNumberAt(quad_index + 1);
392 quad_points->x2 = pArray->GetNumberAt(quad_index + 2);
393 quad_points->y2 = pArray->GetNumberAt(quad_index + 3);
394 quad_points->x3 = pArray->GetNumberAt(quad_index + 4);
395 quad_points->y3 = pArray->GetNumberAt(quad_index + 5);
396 quad_points->x4 = pArray->GetNumberAt(quad_index + 6);
397 quad_points->y4 = pArray->GetNumberAt(quad_index + 7);
398 return true;
399}
400
401#ifdef PDF_ENABLE_XFA
402RetainPtr<IFX_SeekableStream> MakeSeekableStream(
403 FPDF_FILEHANDLER* pFilehandler) {
404 return pdfium::MakeRetain<FPDF_FileHandlerContext>(pFilehandler);
405}
406#endif // PDF_ENABLE_XFA