blob: 28609e74472df3407d312a4190f9b003c8debc1c [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 Zhangbc106482019-05-30 23:55:19 +00009#include "build/build_config.h"
Lei Zhang865ffb12019-02-26 20:18:19 +000010#include "constants/form_fields.h"
Lei Zhang26170562018-04-17 17:01:52 +000011#include "constants/stream_dict_common.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000012#include "core/fpdfapi/cpdf_modulemgr.h"
Tom Sepeza1d34422018-04-24 20:54:41 +000013#include "core/fpdfapi/page/cpdf_page.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000014#include "core/fpdfapi/parser/cpdf_array.h"
Lei Zhang81535612018-10-09 21:15:17 +000015#include "core/fpdfapi/parser/cpdf_dictionary.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000016#include "core/fpdfapi/parser/cpdf_document.h"
Artem Strygineababa12018-06-06 12:31:18 +000017#include "core/fpdfapi/parser/cpdf_stream_acc.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000018#include "core/fpdfdoc/cpdf_annot.h"
Lei Zhangc3450652018-10-11 16:54:42 +000019#include "core/fpdfdoc/cpdf_interactiveform.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000020#include "core/fpdfdoc/cpdf_metadata.h"
Lei Zhange6fcdfa2019-02-14 04:07:09 +000021#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000022#include "public/fpdf_ext.h"
23
Tom Sepeza1d34422018-04-24 20:54:41 +000024#ifdef PDF_ENABLE_XFA
25#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
26#endif
27
Dan Sinclair7aba4722018-03-28 17:04:16 +000028namespace {
29
Ralf Sippl16381792018-04-12 21:20:26 +000030constexpr char kQuadPoints[] = "QuadPoints";
31
Lei Zhang65a8d5e2018-12-20 19:13:21 +000032// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
Lei Zhangbc106482019-05-30 23:55:19 +000033uint32_t g_sandbox_policy = 0xFFFFFFFF;
Lei Zhang65a8d5e2018-12-20 19:13:21 +000034
Lei Zhangbc106482019-05-30 23:55:19 +000035#if !defined(OS_WIN)
36int g_last_error = 0;
37#endif
Lei Zhang65a8d5e2018-12-20 19:13:21 +000038
Lei Zhangb7d09ca2019-02-27 23:50:44 +000039bool RaiseUnsupportedError(int nError) {
40 auto* pAdapter = CPDF_ModuleMgr::Get()->GetUnsupportInfoAdapter();
Dan Sinclair7aba4722018-03-28 17:04:16 +000041 if (!pAdapter)
42 return false;
43
Lei Zhangb7d09ca2019-02-27 23:50:44 +000044 UNSUPPORT_INFO* info = static_cast<UNSUPPORT_INFO*>(pAdapter->info());
Dan Sinclair7aba4722018-03-28 17:04:16 +000045 if (info && info->FSDK_UnSupport_Handler)
46 info->FSDK_UnSupport_Handler(info, nError);
47 return true;
48}
49
Dan Sinclair7aba4722018-03-28 17:04:16 +000050#ifdef PDF_ENABLE_XFA
Tom Sepez55865452018-08-27 20:18:04 +000051class FPDF_FileHandlerContext final : public IFX_SeekableStream {
Dan Sinclair7aba4722018-03-28 17:04:16 +000052 public:
53 template <typename T, typename... Args>
54 friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
55
Dan Sinclair7aba4722018-03-28 17:04:16 +000056 // IFX_SeekableStream:
57 FX_FILESIZE GetSize() override;
58 bool IsEOF() override;
59 FX_FILESIZE GetPosition() override;
Lei Zhangf6a79212018-11-15 20:17:49 +000060 bool ReadBlockAtOffset(void* buffer,
61 FX_FILESIZE offset,
62 size_t size) override;
Dan Sinclair7aba4722018-03-28 17:04:16 +000063 size_t ReadBlock(void* buffer, size_t size) override;
Lei Zhang59f76232018-11-15 20:22:59 +000064 bool WriteBlockAtOffset(const void* buffer,
65 FX_FILESIZE offset,
66 size_t size) override;
Dan Sinclair7aba4722018-03-28 17:04:16 +000067 bool Flush() override;
68
69 void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
70
Tom Sepezcb798252018-09-17 18:25:32 +000071 private:
Dan Sinclair7aba4722018-03-28 17:04:16 +000072 explicit FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS);
Lei Zhang86688de2018-05-22 22:06:49 +000073 ~FPDF_FileHandlerContext() override;
Dan Sinclair7aba4722018-03-28 17:04:16 +000074
75 FPDF_FILEHANDLER* m_pFS;
76 FX_FILESIZE m_nCurPos;
77};
78
79FPDF_FileHandlerContext::FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS) {
80 m_pFS = pFS;
81 m_nCurPos = 0;
82}
83
84FPDF_FileHandlerContext::~FPDF_FileHandlerContext() {
85 if (m_pFS && m_pFS->Release)
86 m_pFS->Release(m_pFS->clientData);
87}
88
89FX_FILESIZE FPDF_FileHandlerContext::GetSize() {
90 if (m_pFS && m_pFS->GetSize)
91 return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
92 return 0;
93}
94
95bool FPDF_FileHandlerContext::IsEOF() {
96 return m_nCurPos >= GetSize();
97}
98
99FX_FILESIZE FPDF_FileHandlerContext::GetPosition() {
100 return m_nCurPos;
101}
102
Lei Zhangf6a79212018-11-15 20:17:49 +0000103bool FPDF_FileHandlerContext::ReadBlockAtOffset(void* buffer,
104 FX_FILESIZE offset,
105 size_t size) {
Dan Sinclair7aba4722018-03-28 17:04:16 +0000106 if (!buffer || !size || !m_pFS->ReadBlock)
107 return false;
108
109 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
110 (FPDF_DWORD)size) == 0) {
111 m_nCurPos = offset + size;
112 return true;
113 }
114 return false;
115}
116
117size_t FPDF_FileHandlerContext::ReadBlock(void* buffer, size_t size) {
118 if (!buffer || !size || !m_pFS->ReadBlock)
119 return 0;
120
121 FX_FILESIZE nSize = GetSize();
122 if (m_nCurPos >= nSize)
123 return 0;
124 FX_FILESIZE dwAvail = nSize - m_nCurPos;
125 if (dwAvail < (FX_FILESIZE)size)
126 size = static_cast<size_t>(dwAvail);
127 if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
128 (FPDF_DWORD)size) == 0) {
129 m_nCurPos += size;
130 return size;
131 }
132
133 return 0;
134}
135
Lei Zhang59f76232018-11-15 20:22:59 +0000136bool FPDF_FileHandlerContext::WriteBlockAtOffset(const void* buffer,
137 FX_FILESIZE offset,
138 size_t size) {
Dan Sinclair7aba4722018-03-28 17:04:16 +0000139 if (!m_pFS || !m_pFS->WriteBlock)
140 return false;
141
142 if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer,
143 (FPDF_DWORD)size) == 0) {
144 m_nCurPos = offset + size;
145 return true;
146 }
147 return false;
148}
149
150bool FPDF_FileHandlerContext::Flush() {
151 if (!m_pFS || !m_pFS->Flush)
152 return true;
153
154 return m_pFS->Flush(m_pFS->clientData) == 0;
155}
156#endif // PDF_ENABLE_XFA
157
158} // namespace
159
Tom Sepez101535f2018-06-12 13:36:05 +0000160IPDF_Page* IPDFPageFromFPDFPage(FPDF_PAGE page) {
161 return reinterpret_cast<IPDF_Page*>(page);
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000162}
163
Tom Sepez101535f2018-06-12 13:36:05 +0000164FPDF_PAGE FPDFPageFromIPDFPage(IPDF_Page* page) {
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000165 return reinterpret_cast<FPDF_PAGE>(page);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000166}
167
168CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000169 return reinterpret_cast<CPDF_Document*>(doc);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000170}
171
172FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000173 return reinterpret_cast<FPDF_DOCUMENT>(doc);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000174}
175
176CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
Tom Sepez101535f2018-06-12 13:36:05 +0000177 return page ? IPDFPageFromFPDFPage(page)->AsPDFPage() : nullptr;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000178}
179
Lei Zhange6fcdfa2019-02-14 04:07:09 +0000180CPDFSDK_InteractiveForm* FormHandleToInteractiveForm(FPDF_FORMHANDLE hHandle) {
181 CPDFSDK_FormFillEnvironment* pFormFillEnv =
182 CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
183 return pFormFillEnv ? pFormFillEnv->GetInteractiveForm() : nullptr;
184}
185
Lei Zhangb46a7632019-01-09 02:56:16 +0000186ByteString ByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string) {
187 return WideStringFromFPDFWideString(wide_string).ToUTF8();
Dan Sinclair7aba4722018-03-28 17:04:16 +0000188}
189
Lei Zhangf5fcd9e2018-12-23 03:11:50 +0000190WideString WideStringFromFPDFWideString(FPDF_WIDESTRING wide_string) {
191 return WideString::FromUTF16LE(wide_string,
192 WideString::WStringLength(wide_string));
193}
194
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000195#ifdef PDF_ENABLE_XFA
196RetainPtr<IFX_SeekableStream> MakeSeekableStream(
197 FPDF_FILEHANDLER* pFilehandler) {
198 return pdfium::MakeRetain<FPDF_FileHandlerContext>(pFilehandler);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000199}
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000200#endif // PDF_ENABLE_XFA
Dan Sinclair7aba4722018-03-28 17:04:16 +0000201
Lei Zhang5cee3f22018-05-25 21:48:49 +0000202const CPDF_Array* GetQuadPointsArrayFromDictionary(
203 const CPDF_Dictionary* dict) {
Lei Zhangd934c642019-03-04 19:42:00 +0000204 return dict->GetArrayFor("QuadPoints");
Lei Zhang5cee3f22018-05-25 21:48:49 +0000205}
206
207CPDF_Array* GetQuadPointsArrayFromDictionary(CPDF_Dictionary* dict) {
Lei Zhangd934c642019-03-04 19:42:00 +0000208 return dict->GetArrayFor("QuadPoints");
Dan Sinclair7aba4722018-03-28 17:04:16 +0000209}
210
Ralf Sippl16381792018-04-12 21:20:26 +0000211CPDF_Array* AddQuadPointsArrayToDictionary(CPDF_Dictionary* dict) {
Ralf Sippl16381792018-04-12 21:20:26 +0000212 return dict->SetNewFor<CPDF_Array>(kQuadPoints);
213}
214
215bool IsValidQuadPointsIndex(const CPDF_Array* array, size_t index) {
Lei Zhangf40380f2018-10-12 18:31:51 +0000216 return array && index < array->size() / 8;
Ralf Sippl16381792018-04-12 21:20:26 +0000217}
218
219bool GetQuadPointsAtIndex(const CPDF_Array* array,
220 size_t quad_index,
221 FS_QUADPOINTSF* quad_points) {
222 ASSERT(quad_points);
223 ASSERT(array);
224
225 if (!IsValidQuadPointsIndex(array, quad_index))
226 return false;
227
228 quad_index *= 8;
229 quad_points->x1 = array->GetNumberAt(quad_index);
230 quad_points->y1 = array->GetNumberAt(quad_index + 1);
231 quad_points->x2 = array->GetNumberAt(quad_index + 2);
232 quad_points->y2 = array->GetNumberAt(quad_index + 3);
233 quad_points->x3 = array->GetNumberAt(quad_index + 4);
234 quad_points->y3 = array->GetNumberAt(quad_index + 5);
235 quad_points->x4 = array->GetNumberAt(quad_index + 6);
236 quad_points->y4 = array->GetNumberAt(quad_index + 7);
237 return true;
238}
239
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000240CFX_FloatRect CFXFloatRectFromFSRECTF(const FS_RECTF& rect) {
241 return CFX_FloatRect(rect.left, rect.bottom, rect.right, rect.top);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000242}
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000243
244void FSRECTFFromCFXFloatRect(const CFX_FloatRect& rect, FS_RECTF* out_rect) {
245 out_rect->left = rect.left;
246 out_rect->top = rect.top;
247 out_rect->right = rect.right;
248 out_rect->bottom = rect.bottom;
249}
250
Lei Zhang6fef1e42018-12-20 19:14:02 +0000251CFX_Matrix CFXMatrixFromFSMatrix(const FS_MATRIX& matrix) {
252 return CFX_Matrix(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f);
253}
254
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000255unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text,
256 void* buffer,
257 unsigned long buflen) {
258 ByteString encoded_text = text.ToUTF16LE();
259 unsigned long len = encoded_text.GetLength();
260 if (buffer && len <= buflen)
261 memcpy(buffer, encoded_text.c_str(), len);
262 return len;
263}
264
265unsigned long DecodeStreamMaybeCopyAndReturnLength(const CPDF_Stream* stream,
266 void* buffer,
267 unsigned long buflen) {
268 ASSERT(stream);
269 auto stream_acc = pdfium::MakeRetain<CPDF_StreamAcc>(stream);
270 stream_acc->LoadAllDataFiltered();
271 const auto stream_data_size = stream_acc->GetSize();
272 if (!buffer || buflen < stream_data_size)
273 return stream_data_size;
274
275 memcpy(buffer, stream_acc->GetData(), stream_data_size);
276 return stream_data_size;
277}
278
279void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
280 switch (policy) {
281 case FPDF_POLICY_MACHINETIME_ACCESS: {
282 if (enable)
283 g_sandbox_policy |= 0x01;
284 else
285 g_sandbox_policy &= 0xFFFFFFFE;
286 } break;
287 default:
288 break;
289 }
290}
291
292FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) {
293 switch (policy) {
294 case FPDF_POLICY_MACHINETIME_ACCESS:
295 return !!(g_sandbox_policy & 0x01);
296 default:
297 return false;
298 }
299}
300
301void ReportUnsupportedFeatures(CPDF_Document* pDoc) {
302 const CPDF_Dictionary* pRootDict = pDoc->GetRoot();
303 if (pRootDict) {
304 // Portfolios and Packages
305 if (pRootDict->KeyExist("Collection")) {
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000306 RaiseUnsupportedError(FPDF_UNSP_DOC_PORTABLECOLLECTION);
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000307 return;
308 }
309 if (pRootDict->KeyExist("Names")) {
310 const CPDF_Dictionary* pNameDict = pRootDict->GetDictFor("Names");
311 if (pNameDict && pNameDict->KeyExist("EmbeddedFiles")) {
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000312 RaiseUnsupportedError(FPDF_UNSP_DOC_ATTACHMENT);
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000313 return;
314 }
315 if (pNameDict && pNameDict->KeyExist("JavaScript")) {
316 const CPDF_Dictionary* pJSDict = pNameDict->GetDictFor("JavaScript");
317 const CPDF_Array* pArray =
318 pJSDict ? pJSDict->GetArrayFor("Names") : nullptr;
319 if (pArray) {
320 for (size_t i = 0; i < pArray->size(); i++) {
321 ByteString cbStr = pArray->GetStringAt(i);
322 if (cbStr.Compare("com.adobe.acrobat.SharedReview.Register") == 0) {
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000323 RaiseUnsupportedError(FPDF_UNSP_DOC_SHAREDREVIEW);
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000324 return;
325 }
326 }
327 }
328 }
329 }
330
331 // SharedForm
332 const CPDF_Stream* pStream = pRootDict->GetStreamFor("Metadata");
333 if (pStream) {
334 CPDF_Metadata metaData(pStream);
335 for (const auto& err : metaData.CheckForSharedForm())
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000336 RaiseUnsupportedError(static_cast<int>(err));
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000337 }
338 }
339
340 // XFA Forms
341 if (!pDoc->GetExtension() && CPDF_InteractiveForm(pDoc).HasXFAForm())
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000342 RaiseUnsupportedError(FPDF_UNSP_DOC_XFAFORM);
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000343}
344
Lei Zhang4efdb512019-02-26 19:48:39 +0000345void CheckForUnsupportedAnnot(const CPDF_Annot* pAnnot) {
346 switch (pAnnot->GetSubtype()) {
347 case CPDF_Annot::Subtype::FILEATTACHMENT:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000348 RaiseUnsupportedError(FPDF_UNSP_ANNOT_ATTACHMENT);
Lei Zhang4efdb512019-02-26 19:48:39 +0000349 break;
350 case CPDF_Annot::Subtype::MOVIE:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000351 RaiseUnsupportedError(FPDF_UNSP_ANNOT_MOVIE);
Lei Zhang4efdb512019-02-26 19:48:39 +0000352 break;
353 case CPDF_Annot::Subtype::RICHMEDIA:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000354 RaiseUnsupportedError(FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA);
Lei Zhang4efdb512019-02-26 19:48:39 +0000355 break;
356 case CPDF_Annot::Subtype::SCREEN: {
357 const CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();
Lei Zhang6c715022019-02-26 20:16:09 +0000358 ByteString cbString = pAnnotDict->GetStringFor("IT");
359 if (cbString != "Img")
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000360 RaiseUnsupportedError(FPDF_UNSP_ANNOT_SCREEN_MEDIA);
Lei Zhang4efdb512019-02-26 19:48:39 +0000361 break;
362 }
363 case CPDF_Annot::Subtype::SOUND:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000364 RaiseUnsupportedError(FPDF_UNSP_ANNOT_SOUND);
Lei Zhang4efdb512019-02-26 19:48:39 +0000365 break;
366 case CPDF_Annot::Subtype::THREED:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000367 RaiseUnsupportedError(FPDF_UNSP_ANNOT_3DANNOT);
Lei Zhang4efdb512019-02-26 19:48:39 +0000368 break;
369 case CPDF_Annot::Subtype::WIDGET: {
370 const CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();
Lei Zhang865ffb12019-02-26 20:18:19 +0000371 ByteString cbString = pAnnotDict->GetStringFor(pdfium::form_fields::kFT);
Lei Zhangf496e252019-02-26 20:20:19 +0000372 if (cbString == pdfium::form_fields::kSig)
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000373 RaiseUnsupportedError(FPDF_UNSP_ANNOT_SIG);
Lei Zhang4efdb512019-02-26 19:48:39 +0000374 break;
375 }
376 default:
377 break;
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000378 }
379}
380
Lei Zhangbc106482019-05-30 23:55:19 +0000381#if !defined(OS_WIN)
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000382void SetLastError(int err) {
383 g_last_error = err;
384}
385
386int GetLastError() {
387 return g_last_error;
388}
Lei Zhangbc106482019-05-30 23:55:19 +0000389#endif
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000390
391void ProcessParseError(CPDF_Parser::Error err) {
392 uint32_t err_code = FPDF_ERR_SUCCESS;
393 // Translate FPDFAPI error code to FPDFVIEW error code
394 switch (err) {
395 case CPDF_Parser::SUCCESS:
396 err_code = FPDF_ERR_SUCCESS;
397 break;
398 case CPDF_Parser::FILE_ERROR:
399 err_code = FPDF_ERR_FILE;
400 break;
401 case CPDF_Parser::FORMAT_ERROR:
402 err_code = FPDF_ERR_FORMAT;
403 break;
404 case CPDF_Parser::PASSWORD_ERROR:
405 err_code = FPDF_ERR_PASSWORD;
406 break;
407 case CPDF_Parser::HANDLER_ERROR:
408 err_code = FPDF_ERR_SECURITY;
409 break;
410 }
411 SetLastError(err_code);
412}