blob: 383d7d1d9f54739dd0b51b5d865c9264671eea06 [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2018 The PDFium Authors
Dan Sinclair7aba4722018-03-28 17:04:16 +00002// 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
Tom Sepez652d35b2022-09-10 01:42:25 +00009#include <utility>
10
Lei Zhangbc106482019-05-30 23:55:19 +000011#include "build/build_config.h"
Lei Zhang865ffb12019-02-26 20:18:19 +000012#include "constants/form_fields.h"
Lei Zhang26170562018-04-17 17:01:52 +000013#include "constants/stream_dict_common.h"
Tom Sepeza1d34422018-04-24 20:54:41 +000014#include "core/fpdfapi/page/cpdf_page.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000015#include "core/fpdfapi/parser/cpdf_array.h"
Lei Zhang81535612018-10-09 21:15:17 +000016#include "core/fpdfapi/parser/cpdf_dictionary.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000017#include "core/fpdfapi/parser/cpdf_document.h"
Artem Strygineababa12018-06-06 12:31:18 +000018#include "core/fpdfapi/parser/cpdf_stream_acc.h"
Gourab Kundud35a62d2020-04-24 10:29:27 +000019#include "core/fpdfapi/render/cpdf_renderoptions.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000020#include "core/fpdfdoc/cpdf_annot.h"
Lei Zhangc3450652018-10-11 16:54:42 +000021#include "core/fpdfdoc/cpdf_interactiveform.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000022#include "core/fpdfdoc/cpdf_metadata.h"
Lei Zhang91085882024-02-22 00:49:57 +000023#include "core/fxcrt/check.h"
Tom Sepezfb6e3552024-05-07 18:15:23 +000024#include "core/fxcrt/compiler_specific.h"
25#include "core/fxcrt/fx_memcpy_wrappers.h"
Lei Zhangf36006c2024-02-17 00:56:24 +000026#include "core/fxcrt/numerics/safe_conversions.h"
Tom Sepez06943a92022-11-10 20:29:34 +000027#include "core/fxcrt/span_util.h"
Tom Sepez5bfc5f52021-03-31 20:26:42 +000028#include "core/fxcrt/unowned_ptr.h"
Lei Zhange6fcdfa2019-02-14 04:07:09 +000029#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000030
31namespace {
32
Ralf Sippl16381792018-04-12 21:20:26 +000033constexpr char kQuadPoints[] = "QuadPoints";
34
Lei Zhang65a8d5e2018-12-20 19:13:21 +000035// 0 bit: FPDF_POLICY_MACHINETIME_ACCESS
Lei Zhangbc106482019-05-30 23:55:19 +000036uint32_t g_sandbox_policy = 0xFFFFFFFF;
Lei Zhang65a8d5e2018-12-20 19:13:21 +000037
Tom Sepez20c946f2019-07-31 19:33:21 +000038UNSUPPORT_INFO* g_unsupport_info = nullptr;
39
Lei Zhangb7d09ca2019-02-27 23:50:44 +000040bool RaiseUnsupportedError(int nError) {
Tom Sepez20c946f2019-07-31 19:33:21 +000041 if (!g_unsupport_info)
Dan Sinclair7aba4722018-03-28 17:04:16 +000042 return false;
43
Tom Sepez20c946f2019-07-31 19:33:21 +000044 if (g_unsupport_info->FSDK_UnSupport_Handler)
45 g_unsupport_info->FSDK_UnSupport_Handler(g_unsupport_info, nError);
Dan Sinclair7aba4722018-03-28 17:04:16 +000046 return true;
47}
48
Lei Zhang85e09df2020-02-27 14:48:07 +000049// Use the existence of the XFA array as a signal for XFA forms.
50bool DocHasXFA(const CPDF_Document* doc) {
51 const CPDF_Dictionary* root = doc->GetRoot();
52 if (!root)
53 return false;
54
Tom Sepez5313f922022-09-20 18:17:45 +000055 RetainPtr<const CPDF_Dictionary> form = root->GetDictFor("AcroForm");
Lei Zhang85e09df2020-02-27 14:48:07 +000056 return form && form->GetArrayFor("XFA");
57}
58
Tom Sepez06943a92022-11-10 20:29:34 +000059unsigned long GetStreamMaybeCopyAndReturnLengthImpl(
60 RetainPtr<const CPDF_Stream> stream,
61 pdfium::span<uint8_t> buffer,
62 bool decode) {
Tom Sepez9c78c0d2021-01-27 20:13:14 +000063 DCHECK(stream);
Tom Sepez06943a92022-11-10 20:29:34 +000064 auto stream_acc = pdfium::MakeRetain<CPDF_StreamAcc>(std::move(stream));
Jeremy Chinsen617a2e82019-06-20 00:11:12 +000065 if (decode)
66 stream_acc->LoadAllDataFiltered();
67 else
68 stream_acc->LoadAllDataRaw();
69
Tom Sepez06943a92022-11-10 20:29:34 +000070 pdfium::span<const uint8_t> stream_data_span = stream_acc->GetSpan();
71 if (!buffer.empty() && buffer.size() <= stream_data_span.size())
72 fxcrt::spancpy(buffer, stream_data_span);
Jeremy Chinsen617a2e82019-06-20 00:11:12 +000073
Lei Zhangf36006c2024-02-17 00:56:24 +000074 return pdfium::checked_cast<unsigned long>(stream_data_span.size());
Jeremy Chinsen617a2e82019-06-20 00:11:12 +000075}
76
Tom Sepezb079e872024-04-04 19:04:46 +000077// TODO(tsepez): should be UNSAFE_BUFFER_USAGE.
Tom Sepezaad37f12024-02-10 00:32:04 +000078size_t FPDFWideStringLength(const unsigned short* str) {
79 if (!str) {
80 return 0;
81 }
82 size_t len = 0;
Tom Sepezb079e872024-04-04 19:04:46 +000083 // SAFETY: NUL-termination required from caller.
84 UNSAFE_BUFFERS({
85 while (str[len]) {
86 len++;
87 }
88 });
Tom Sepezaad37f12024-02-10 00:32:04 +000089 return len;
90}
91
Dan Sinclair7aba4722018-03-28 17:04:16 +000092#ifdef PDF_ENABLE_XFA
Tom Sepez55865452018-08-27 20:18:04 +000093class FPDF_FileHandlerContext final : public IFX_SeekableStream {
Dan Sinclair7aba4722018-03-28 17:04:16 +000094 public:
Tom Sepezb9d9b612020-06-17 20:47:22 +000095 CONSTRUCT_VIA_MAKE_RETAIN;
Dan Sinclair7aba4722018-03-28 17:04:16 +000096
Dan Sinclair7aba4722018-03-28 17:04:16 +000097 // IFX_SeekableStream:
98 FX_FILESIZE GetSize() override;
Dan Sinclair7aba4722018-03-28 17:04:16 +000099 FX_FILESIZE GetPosition() override;
Tom Sepeze1c2bcf2022-11-02 19:29:55 +0000100 bool IsEOF() override;
101 size_t ReadBlock(pdfium::span<uint8_t> buffer) override;
Tom Sepez6a39df12022-11-01 20:29:35 +0000102 bool ReadBlockAtOffset(pdfium::span<uint8_t> buffer,
103 FX_FILESIZE offset) override;
Tom Sepeze1c2bcf2022-11-02 19:29:55 +0000104 bool WriteBlockAtOffset(pdfium::span<const uint8_t> buffer,
105 FX_FILESIZE offset) override;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000106 bool Flush() override;
107
108 void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
109
Tom Sepezcb798252018-09-17 18:25:32 +0000110 private:
Dan Sinclair7aba4722018-03-28 17:04:16 +0000111 explicit FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS);
Lei Zhang86688de2018-05-22 22:06:49 +0000112 ~FPDF_FileHandlerContext() override;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000113
Tom Sepez5bfc5f52021-03-31 20:26:42 +0000114 UnownedPtr<FPDF_FILEHANDLER> const m_pFS;
115 FX_FILESIZE m_nCurPos = 0;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000116};
117
Tom Sepez5bfc5f52021-03-31 20:26:42 +0000118FPDF_FileHandlerContext::FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS)
119 : m_pFS(pFS) {}
Dan Sinclair7aba4722018-03-28 17:04:16 +0000120
121FPDF_FileHandlerContext::~FPDF_FileHandlerContext() {
122 if (m_pFS && m_pFS->Release)
123 m_pFS->Release(m_pFS->clientData);
124}
125
126FX_FILESIZE FPDF_FileHandlerContext::GetSize() {
127 if (m_pFS && m_pFS->GetSize)
Tom Sepez5bfc5f52021-03-31 20:26:42 +0000128 return static_cast<FX_FILESIZE>(m_pFS->GetSize(m_pFS->clientData));
Dan Sinclair7aba4722018-03-28 17:04:16 +0000129 return 0;
130}
131
132bool FPDF_FileHandlerContext::IsEOF() {
133 return m_nCurPos >= GetSize();
134}
135
136FX_FILESIZE FPDF_FileHandlerContext::GetPosition() {
137 return m_nCurPos;
138}
139
Tom Sepez6a39df12022-11-01 20:29:35 +0000140bool FPDF_FileHandlerContext::ReadBlockAtOffset(pdfium::span<uint8_t> buffer,
141 FX_FILESIZE offset) {
142 if (buffer.empty() || !m_pFS->ReadBlock)
Dan Sinclair7aba4722018-03-28 17:04:16 +0000143 return false;
144
Tom Sepez6a39df12022-11-01 20:29:35 +0000145 if (m_pFS->ReadBlock(m_pFS->clientData, static_cast<FPDF_DWORD>(offset),
146 buffer.data(),
147 static_cast<FPDF_DWORD>(buffer.size())) == 0) {
148 m_nCurPos = offset + buffer.size();
Dan Sinclair7aba4722018-03-28 17:04:16 +0000149 return true;
150 }
151 return false;
152}
153
Tom Sepez1f866362022-11-01 23:54:47 +0000154size_t FPDF_FileHandlerContext::ReadBlock(pdfium::span<uint8_t> buffer) {
155 if (buffer.empty() || !m_pFS->ReadBlock)
Dan Sinclair7aba4722018-03-28 17:04:16 +0000156 return 0;
157
158 FX_FILESIZE nSize = GetSize();
159 if (m_nCurPos >= nSize)
160 return 0;
161 FX_FILESIZE dwAvail = nSize - m_nCurPos;
Tom Sepez1f866362022-11-01 23:54:47 +0000162 if (dwAvail < (FX_FILESIZE)buffer.size())
163 buffer = buffer.first(static_cast<size_t>(dwAvail));
164 if (m_pFS->ReadBlock(m_pFS->clientData, static_cast<FPDF_DWORD>(m_nCurPos),
165 buffer.data(),
166 static_cast<FPDF_DWORD>(buffer.size())) == 0) {
167 m_nCurPos += buffer.size();
168 return buffer.size();
Dan Sinclair7aba4722018-03-28 17:04:16 +0000169 }
170
171 return 0;
172}
173
Tom Sepeze1c2bcf2022-11-02 19:29:55 +0000174bool FPDF_FileHandlerContext::WriteBlockAtOffset(
175 pdfium::span<const uint8_t> buffer,
176 FX_FILESIZE offset) {
Dan Sinclair7aba4722018-03-28 17:04:16 +0000177 if (!m_pFS || !m_pFS->WriteBlock)
178 return false;
179
Tom Sepeze1c2bcf2022-11-02 19:29:55 +0000180 if (m_pFS->WriteBlock(m_pFS->clientData, static_cast<FPDF_DWORD>(offset),
181 buffer.data(),
182 static_cast<FPDF_DWORD>(buffer.size())) == 0) {
183 m_nCurPos = offset + buffer.size();
Dan Sinclair7aba4722018-03-28 17:04:16 +0000184 return true;
185 }
186 return false;
187}
188
189bool FPDF_FileHandlerContext::Flush() {
190 if (!m_pFS || !m_pFS->Flush)
191 return true;
192
193 return m_pFS->Flush(m_pFS->clientData) == 0;
194}
195#endif // PDF_ENABLE_XFA
196
197} // namespace
198
Tom Sepez101535f2018-06-12 13:36:05 +0000199IPDF_Page* IPDFPageFromFPDFPage(FPDF_PAGE page) {
200 return reinterpret_cast<IPDF_Page*>(page);
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000201}
202
Tom Sepez101535f2018-06-12 13:36:05 +0000203FPDF_PAGE FPDFPageFromIPDFPage(IPDF_Page* page) {
Tom Sepez3f3c39d2018-05-01 17:46:34 +0000204 return reinterpret_cast<FPDF_PAGE>(page);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000205}
206
207CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000208 return reinterpret_cast<CPDF_Document*>(doc);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000209}
210
211FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
Tom Sepezfe06d512018-05-01 17:25:25 +0000212 return reinterpret_cast<FPDF_DOCUMENT>(doc);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000213}
214
215CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) {
Tom Sepez101535f2018-06-12 13:36:05 +0000216 return page ? IPDFPageFromFPDFPage(page)->AsPDFPage() : nullptr;
Dan Sinclair7aba4722018-03-28 17:04:16 +0000217}
218
Lei Zhange6fcdfa2019-02-14 04:07:09 +0000219CPDFSDK_InteractiveForm* FormHandleToInteractiveForm(FPDF_FORMHANDLE hHandle) {
220 CPDFSDK_FormFillEnvironment* pFormFillEnv =
221 CPDFSDKFormFillEnvironmentFromFPDFFormHandle(hHandle);
222 return pFormFillEnv ? pFormFillEnv->GetInteractiveForm() : nullptr;
223}
224
Lei Zhangb46a7632019-01-09 02:56:16 +0000225ByteString ByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string) {
Tom Sepez6967ba92024-05-10 00:40:04 +0000226 // SAFETY: caller ensures `wide_string` is NUL-terminated and enforced
227 // by UNSAFE_BUFFER_USAGE in header file.
228 return UNSAFE_BUFFERS(WideStringFromFPDFWideString(wide_string).ToUTF8());
Dan Sinclair7aba4722018-03-28 17:04:16 +0000229}
230
Lei Zhangf5fcd9e2018-12-23 03:11:50 +0000231WideString WideStringFromFPDFWideString(FPDF_WIDESTRING wide_string) {
Tom Sepez6967ba92024-05-10 00:40:04 +0000232 // SAFETY: caller ensures `wide_string` is NUL-terminated and enforced
233 // by UNSAFE_BUFFER_USAGE in header file.
Tom Sepez3b679fe2024-04-09 18:49:32 +0000234 return WideString::FromUTF16LE(UNSAFE_BUFFERS(
235 pdfium::make_span(reinterpret_cast<const uint8_t*>(wide_string),
236 FPDFWideStringLength(wide_string) * 2)));
Lei Zhangf5fcd9e2018-12-23 03:11:50 +0000237}
238
Tom Sepez6967ba92024-05-10 00:40:04 +0000239pdfium::span<char> SpanFromFPDFApiArgs(void* buffer, unsigned long buflen) {
240 if (!buffer) {
241 // API convention is to ignore `buflen` arg when `buffer` is NULL.
242 return pdfium::span<char>();
243 }
244 // SAFETY: required from caller, enforced by UNSAFE_BUFFER_USAGE in header.
245 return UNSAFE_BUFFERS(pdfium::make_span(static_cast<char*>(buffer), buflen));
246}
247
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000248#ifdef PDF_ENABLE_XFA
249RetainPtr<IFX_SeekableStream> MakeSeekableStream(
250 FPDF_FILEHANDLER* pFilehandler) {
251 return pdfium::MakeRetain<FPDF_FileHandlerContext>(pFilehandler);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000252}
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000253#endif // PDF_ENABLE_XFA
Dan Sinclair7aba4722018-03-28 17:04:16 +0000254
Tom Sepez525a4272022-09-28 21:35:24 +0000255RetainPtr<const CPDF_Array> GetQuadPointsArrayFromDictionary(
Lei Zhang5cee3f22018-05-25 21:48:49 +0000256 const CPDF_Dictionary* dict) {
Tom Sepez525a4272022-09-28 21:35:24 +0000257 return dict->GetArrayFor("QuadPoints");
Lei Zhang5cee3f22018-05-25 21:48:49 +0000258}
259
Tom Sepez3d64afa2022-06-24 16:40:17 +0000260RetainPtr<CPDF_Array> GetMutableQuadPointsArrayFromDictionary(
261 CPDF_Dictionary* dict) {
262 return pdfium::WrapRetain(
Tom Sepez525a4272022-09-28 21:35:24 +0000263 const_cast<CPDF_Array*>(GetQuadPointsArrayFromDictionary(dict).Get()));
Dan Sinclair7aba4722018-03-28 17:04:16 +0000264}
265
Tom Sepez8aad22a2022-09-22 18:56:16 +0000266RetainPtr<CPDF_Array> AddQuadPointsArrayToDictionary(CPDF_Dictionary* dict) {
Ralf Sippl16381792018-04-12 21:20:26 +0000267 return dict->SetNewFor<CPDF_Array>(kQuadPoints);
268}
269
270bool IsValidQuadPointsIndex(const CPDF_Array* array, size_t index) {
Lei Zhangf40380f2018-10-12 18:31:51 +0000271 return array && index < array->size() / 8;
Ralf Sippl16381792018-04-12 21:20:26 +0000272}
273
Tom Sepez525a4272022-09-28 21:35:24 +0000274bool GetQuadPointsAtIndex(RetainPtr<const CPDF_Array> array,
Ralf Sippl16381792018-04-12 21:20:26 +0000275 size_t quad_index,
276 FS_QUADPOINTSF* quad_points) {
Tom Sepez9c78c0d2021-01-27 20:13:14 +0000277 DCHECK(quad_points);
278 DCHECK(array);
Ralf Sippl16381792018-04-12 21:20:26 +0000279
280 if (!IsValidQuadPointsIndex(array, quad_index))
281 return false;
282
283 quad_index *= 8;
Tom Sepez3b886ba2022-09-10 00:00:45 +0000284 quad_points->x1 = array->GetFloatAt(quad_index);
285 quad_points->y1 = array->GetFloatAt(quad_index + 1);
286 quad_points->x2 = array->GetFloatAt(quad_index + 2);
287 quad_points->y2 = array->GetFloatAt(quad_index + 3);
288 quad_points->x3 = array->GetFloatAt(quad_index + 4);
289 quad_points->y3 = array->GetFloatAt(quad_index + 5);
290 quad_points->x4 = array->GetFloatAt(quad_index + 6);
291 quad_points->y4 = array->GetFloatAt(quad_index + 7);
Ralf Sippl16381792018-04-12 21:20:26 +0000292 return true;
293}
294
Lei Zhang8da98232019-12-11 23:29:33 +0000295CFX_PointF CFXPointFFromFSPointF(const FS_POINTF& point) {
296 return CFX_PointF(point.x, point.y);
297}
298
299CFX_FloatRect CFXFloatRectFromFSRectF(const FS_RECTF& rect) {
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000300 return CFX_FloatRect(rect.left, rect.bottom, rect.right, rect.top);
Dan Sinclair7aba4722018-03-28 17:04:16 +0000301}
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000302
Lei Zhang8da98232019-12-11 23:29:33 +0000303FS_RECTF FSRectFFromCFXFloatRect(const CFX_FloatRect& rect) {
Lei Zhang3567c612019-11-18 18:10:02 +0000304 return {rect.left, rect.top, rect.right, rect.bottom};
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000305}
306
Lei Zhang6fef1e42018-12-20 19:14:02 +0000307CFX_Matrix CFXMatrixFromFSMatrix(const FS_MATRIX& matrix) {
308 return CFX_Matrix(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f);
309}
310
Lei Zhangc89c5822020-01-21 20:23:56 +0000311FS_MATRIX FSMatrixFromCFXMatrix(const CFX_Matrix& matrix) {
312 return {matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f};
Lei Zhang8da98232019-12-11 23:29:33 +0000313}
314
Tom Sepez6967ba92024-05-10 00:40:04 +0000315unsigned long NulTerminateMaybeCopyAndReturnLength(
316 const ByteString& text,
317 pdfium::span<char> result_span) {
Tom Sepez9e677092024-05-09 15:38:01 +0000318 pdfium::span<const char> text_span = text.span_with_terminator();
Tom Sepez6967ba92024-05-10 00:40:04 +0000319 fxcrt::try_spancpy(result_span, text_span);
Tom Sepez9e677092024-05-09 15:38:01 +0000320 return pdfium::checked_cast<unsigned long>(text_span.size());
Daniel Hosseinian5bc1f982020-04-14 01:05:27 +0000321}
322
Tom Sepez6967ba92024-05-10 00:40:04 +0000323unsigned long Utf16EncodeMaybeCopyAndReturnLength(
324 const WideString& text,
325 pdfium::span<char> result_span) {
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000326 ByteString encoded_text = text.ToUTF16LE();
Tom Sepez9e677092024-05-09 15:38:01 +0000327 pdfium::span<const char> encoded_text_span = encoded_text.span();
Tom Sepez6967ba92024-05-10 00:40:04 +0000328 fxcrt::try_spancpy(result_span, encoded_text_span);
Tom Sepez9e677092024-05-09 15:38:01 +0000329 return pdfium::checked_cast<unsigned long>(encoded_text_span.size());
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000330}
331
Tom Sepez06943a92022-11-10 20:29:34 +0000332unsigned long GetRawStreamMaybeCopyAndReturnLength(
333 RetainPtr<const CPDF_Stream> stream,
334 pdfium::span<uint8_t> buffer) {
335 return GetStreamMaybeCopyAndReturnLengthImpl(std::move(stream), buffer,
Jeremy Chinsen617a2e82019-06-20 00:11:12 +0000336 /*decode=*/false);
337}
338
Tom Sepez06943a92022-11-10 20:29:34 +0000339unsigned long DecodeStreamMaybeCopyAndReturnLength(
340 RetainPtr<const CPDF_Stream> stream,
341 pdfium::span<uint8_t> buffer) {
342 return GetStreamMaybeCopyAndReturnLengthImpl(std::move(stream), buffer,
Jeremy Chinsen617a2e82019-06-20 00:11:12 +0000343 /*decode=*/true);
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000344}
345
Tom Sepez69a4a702019-07-31 17:59:49 +0000346void SetPDFSandboxPolicy(FPDF_DWORD policy, FPDF_BOOL enable) {
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000347 switch (policy) {
348 case FPDF_POLICY_MACHINETIME_ACCESS: {
Tom Sepezfe285c32019-12-04 18:38:03 +0000349 uint32_t mask = 1 << policy;
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000350 if (enable)
Tom Sepezfe285c32019-12-04 18:38:03 +0000351 g_sandbox_policy |= mask;
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000352 else
Tom Sepezfe285c32019-12-04 18:38:03 +0000353 g_sandbox_policy &= ~mask;
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000354 } break;
355 default:
356 break;
357 }
358}
359
Tom Sepez69a4a702019-07-31 17:59:49 +0000360FPDF_BOOL IsPDFSandboxPolicyEnabled(FPDF_DWORD policy) {
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000361 switch (policy) {
Tom Sepezfe285c32019-12-04 18:38:03 +0000362 case FPDF_POLICY_MACHINETIME_ACCESS: {
363 uint32_t mask = 1 << policy;
364 return !!(g_sandbox_policy & mask);
365 }
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000366 default:
367 return false;
368 }
369}
370
Tom Sepez20c946f2019-07-31 19:33:21 +0000371void SetPDFUnsupportInfo(UNSUPPORT_INFO* unsp_info) {
372 g_unsupport_info = unsp_info;
373}
374
Lei Zhang4745a472020-02-27 18:24:58 +0000375void ReportUnsupportedFeatures(const CPDF_Document* pDoc) {
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000376 const CPDF_Dictionary* pRootDict = pDoc->GetRoot();
Lei Zhang4745a472020-02-27 18:24:58 +0000377 if (!pRootDict)
378 return;
379
380 // Portfolios and Packages
Lei Zhang6e8b20f2020-02-27 20:02:49 +0000381 if (pRootDict->KeyExist("Collection"))
Lei Zhang4745a472020-02-27 18:24:58 +0000382 RaiseUnsupportedError(FPDF_UNSP_DOC_PORTABLECOLLECTION);
Lei Zhang6e8b20f2020-02-27 20:02:49 +0000383
Tom Sepez5313f922022-09-20 18:17:45 +0000384 RetainPtr<const CPDF_Dictionary> pNameDict = pRootDict->GetDictFor("Names");
Lei Zhang4745a472020-02-27 18:24:58 +0000385 if (pNameDict) {
Lei Zhang6e8b20f2020-02-27 20:02:49 +0000386 if (pNameDict->KeyExist("EmbeddedFiles"))
Lei Zhang4745a472020-02-27 18:24:58 +0000387 RaiseUnsupportedError(FPDF_UNSP_DOC_ATTACHMENT);
Lei Zhang6e8b20f2020-02-27 20:02:49 +0000388
Tom Sepez5313f922022-09-20 18:17:45 +0000389 RetainPtr<const CPDF_Dictionary> pJSDict =
390 pNameDict->GetDictFor("JavaScript");
Lei Zhang4745a472020-02-27 18:24:58 +0000391 if (pJSDict) {
Tom Sepezc84dc1f2022-09-19 23:06:33 +0000392 RetainPtr<const CPDF_Array> pArray = pJSDict->GetArrayFor("Names");
Lei Zhang4745a472020-02-27 18:24:58 +0000393 if (pArray) {
394 for (size_t i = 0; i < pArray->size(); i++) {
Tom Sepez56902472022-09-14 21:37:14 +0000395 ByteString cbStr = pArray->GetByteStringAt(i);
Lei Zhang814e3bf2021-04-24 01:45:51 +0000396 if (cbStr == "com.adobe.acrobat.SharedReview.Register") {
Lei Zhang4745a472020-02-27 18:24:58 +0000397 RaiseUnsupportedError(FPDF_UNSP_DOC_SHAREDREVIEW);
Lei Zhang6e8b20f2020-02-27 20:02:49 +0000398 break;
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000399 }
400 }
401 }
402 }
Lei Zhang4745a472020-02-27 18:24:58 +0000403 }
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000404
Lei Zhang4745a472020-02-27 18:24:58 +0000405 // SharedForm
Tom Sepez652d35b2022-09-10 01:42:25 +0000406 RetainPtr<const CPDF_Stream> pStream = pRootDict->GetStreamFor("Metadata");
Lei Zhang4745a472020-02-27 18:24:58 +0000407 if (pStream) {
Tom Sepez652d35b2022-09-10 01:42:25 +0000408 CPDF_Metadata metadata(std::move(pStream));
Lei Zhang4745a472020-02-27 18:24:58 +0000409 for (const UnsupportedFeature& feature : metadata.CheckForSharedForm())
410 RaiseUnsupportedError(static_cast<int>(feature));
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000411 }
Daniel Hosseiniana793e972020-01-24 02:51:31 +0000412}
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000413
Lei Zhang85e09df2020-02-27 14:48:07 +0000414void ReportUnsupportedXFA(const CPDF_Document* pDoc) {
415 if (!pDoc->GetExtension() && DocHasXFA(pDoc))
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000416 RaiseUnsupportedError(FPDF_UNSP_DOC_XFAFORM);
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000417}
418
Lei Zhang4efdb512019-02-26 19:48:39 +0000419void CheckForUnsupportedAnnot(const CPDF_Annot* pAnnot) {
420 switch (pAnnot->GetSubtype()) {
421 case CPDF_Annot::Subtype::FILEATTACHMENT:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000422 RaiseUnsupportedError(FPDF_UNSP_ANNOT_ATTACHMENT);
Lei Zhang4efdb512019-02-26 19:48:39 +0000423 break;
424 case CPDF_Annot::Subtype::MOVIE:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000425 RaiseUnsupportedError(FPDF_UNSP_ANNOT_MOVIE);
Lei Zhang4efdb512019-02-26 19:48:39 +0000426 break;
427 case CPDF_Annot::Subtype::RICHMEDIA:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000428 RaiseUnsupportedError(FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA);
Lei Zhang4efdb512019-02-26 19:48:39 +0000429 break;
430 case CPDF_Annot::Subtype::SCREEN: {
431 const CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();
Tom Sepez27151a62022-09-14 19:48:59 +0000432 ByteString cbString = pAnnotDict->GetByteStringFor("IT");
Lei Zhang6c715022019-02-26 20:16:09 +0000433 if (cbString != "Img")
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000434 RaiseUnsupportedError(FPDF_UNSP_ANNOT_SCREEN_MEDIA);
Lei Zhang4efdb512019-02-26 19:48:39 +0000435 break;
436 }
437 case CPDF_Annot::Subtype::SOUND:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000438 RaiseUnsupportedError(FPDF_UNSP_ANNOT_SOUND);
Lei Zhang4efdb512019-02-26 19:48:39 +0000439 break;
440 case CPDF_Annot::Subtype::THREED:
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000441 RaiseUnsupportedError(FPDF_UNSP_ANNOT_3DANNOT);
Lei Zhang4efdb512019-02-26 19:48:39 +0000442 break;
443 case CPDF_Annot::Subtype::WIDGET: {
444 const CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();
Tom Sepez27151a62022-09-14 19:48:59 +0000445 ByteString cbString =
446 pAnnotDict->GetByteStringFor(pdfium::form_fields::kFT);
Lei Zhangf496e252019-02-26 20:20:19 +0000447 if (cbString == pdfium::form_fields::kSig)
Lei Zhangb7d09ca2019-02-27 23:50:44 +0000448 RaiseUnsupportedError(FPDF_UNSP_ANNOT_SIG);
Lei Zhang4efdb512019-02-26 19:48:39 +0000449 break;
450 }
451 default:
452 break;
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000453 }
454}
455
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000456void ProcessParseError(CPDF_Parser::Error err) {
457 uint32_t err_code = FPDF_ERR_SUCCESS;
458 // Translate FPDFAPI error code to FPDFVIEW error code
459 switch (err) {
460 case CPDF_Parser::SUCCESS:
461 err_code = FPDF_ERR_SUCCESS;
462 break;
463 case CPDF_Parser::FILE_ERROR:
464 err_code = FPDF_ERR_FILE;
465 break;
466 case CPDF_Parser::FORMAT_ERROR:
467 err_code = FPDF_ERR_FORMAT;
468 break;
469 case CPDF_Parser::PASSWORD_ERROR:
470 err_code = FPDF_ERR_PASSWORD;
471 break;
472 case CPDF_Parser::HANDLER_ERROR:
473 err_code = FPDF_ERR_SECURITY;
474 break;
475 }
Tom Sepez04e3af82019-08-05 23:41:06 +0000476 FXSYS_SetLastError(err_code);
Lei Zhang65a8d5e2018-12-20 19:13:21 +0000477}
Gourab Kundud35a62d2020-04-24 10:29:27 +0000478
479void SetColorFromScheme(const FPDF_COLORSCHEME* pColorScheme,
480 CPDF_RenderOptions* pRenderOptions) {
481 CPDF_RenderOptions::ColorScheme color_scheme;
Tom Sepez5ea5fa92022-03-08 00:15:23 +0000482 color_scheme.path_fill_color =
483 static_cast<FX_ARGB>(pColorScheme->path_fill_color);
484 color_scheme.path_stroke_color =
485 static_cast<FX_ARGB>(pColorScheme->path_stroke_color);
486 color_scheme.text_fill_color =
487 static_cast<FX_ARGB>(pColorScheme->text_fill_color);
488 color_scheme.text_stroke_color =
489 static_cast<FX_ARGB>(pColorScheme->text_stroke_color);
Gourab Kundud35a62d2020-04-24 10:29:27 +0000490 pRenderOptions->SetColorScheme(color_scheme);
491}
Tom Sepezc524b1f2021-04-06 00:09:39 +0000492
493std::vector<uint32_t> ParsePageRangeString(const ByteString& bsPageRange,
494 uint32_t nCount) {
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000495 ByteStringView alphabet(" 0123456789-,");
496 for (const auto& ch : bsPageRange) {
497 if (!alphabet.Contains(ch))
Tom Sepezc524b1f2021-04-06 00:09:39 +0000498 return std::vector<uint32_t>();
499 }
500
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000501 ByteString bsStrippedPageRange = bsPageRange;
502 bsStrippedPageRange.Remove(' ');
Tom Sepezc524b1f2021-04-06 00:09:39 +0000503
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000504 std::vector<uint32_t> results;
505 for (const auto& entry : fxcrt::Split(bsStrippedPageRange, ',')) {
506 std::vector<ByteString> args = fxcrt::Split(entry, '-');
507 if (args.size() == 1) {
Lei Zhangf36006c2024-02-17 00:56:24 +0000508 uint32_t page_num = pdfium::checked_cast<uint32_t>(atoi(args[0].c_str()));
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000509 if (page_num == 0 || page_num > nCount)
Tom Sepezc524b1f2021-04-06 00:09:39 +0000510 return std::vector<uint32_t>();
Daniel Hosseinianc7cb4052021-06-11 21:00:47 +0000511 results.push_back(page_num - 1);
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000512 } else if (args.size() == 2) {
513 uint32_t first_num =
Lei Zhangf36006c2024-02-17 00:56:24 +0000514 pdfium::checked_cast<uint32_t>(atoi(args[0].c_str()));
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000515 if (first_num == 0)
Tom Sepezc524b1f2021-04-06 00:09:39 +0000516 return std::vector<uint32_t>();
Lei Zhangf36006c2024-02-17 00:56:24 +0000517 uint32_t last_num = pdfium::checked_cast<uint32_t>(atoi(args[1].c_str()));
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000518 if (last_num == 0 || first_num > last_num || last_num > nCount)
519 return std::vector<uint32_t>();
520 for (uint32_t i = first_num; i <= last_num; ++i)
Daniel Hosseinianc7cb4052021-06-11 21:00:47 +0000521 results.push_back(i - 1);
Tom Sepezc524b1f2021-04-06 00:09:39 +0000522 } else {
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000523 return std::vector<uint32_t>();
Tom Sepezc524b1f2021-04-06 00:09:39 +0000524 }
Tom Sepezc524b1f2021-04-06 00:09:39 +0000525 }
Tom Sepez1e2d7df2021-04-07 19:26:06 +0000526 return results;
Tom Sepezc524b1f2021-04-06 00:09:39 +0000527}