1 // Copyright 2016 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 "fpdfsdk/cpdfsdk_interform.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <sstream>
12 #include <string>
13 #include <vector>
14
15 #include "core/fpdfapi/page/cpdf_page.h"
16 #include "core/fpdfapi/parser/cfdf_document.h"
17 #include "core/fpdfapi/parser/cpdf_array.h"
18 #include "core/fpdfapi/parser/cpdf_document.h"
19 #include "core/fpdfapi/parser/cpdf_stream.h"
20 #include "core/fpdfdoc/cpdf_actionfields.h"
21 #include "core/fpdfdoc/cpdf_interform.h"
22 #include "core/fxge/cfx_graphstatedata.h"
23 #include "core/fxge/cfx_pathdata.h"
24 #include "fpdfsdk/cba_annotiterator.h"
25 #include "fpdfsdk/cpdfsdk_annot.h"
26 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
27 #include "fpdfsdk/cpdfsdk_pageview.h"
28 #include "fpdfsdk/cpdfsdk_widget.h"
29 #include "fpdfsdk/formfiller/cffl_formfiller.h"
30 #include "fpdfsdk/fsdk_actionhandler.h"
31 #include "fpdfsdk/fsdk_define.h"
32 #include "fpdfsdk/ipdfsdk_annothandler.h"
33 #include "fxjs/ijs_event_context.h"
34 #include "fxjs/ijs_runtime.h"
35 #include "third_party/base/stl_util.h"
36
37 #ifdef PDF_ENABLE_XFA
38 #include "fpdfsdk/cpdfsdk_xfawidget.h"
39 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
40 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
41 #include "xfa/fxfa/cxfa_eventparam.h"
42 #include "xfa/fxfa/cxfa_ffdocview.h"
43 #include "xfa/fxfa/cxfa_ffwidget.h"
44 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
45 #endif // PDF_ENABLE_XFA
46
47 namespace {
48
IsFormFieldTypeComboOrText(FormFieldType fieldType)49 bool IsFormFieldTypeComboOrText(FormFieldType fieldType) {
50 switch (fieldType) {
51 case FormFieldType::kComboBox:
52 case FormFieldType::kTextField:
53 return true;
54 default:
55 return false;
56 }
57 }
58
59 #ifdef PDF_ENABLE_XFA
IsFormFieldTypeXFA(FormFieldType fieldType)60 bool IsFormFieldTypeXFA(FormFieldType fieldType) {
61 switch (fieldType) {
62 case FormFieldType::kXFA:
63 case FormFieldType::kXFA_CheckBox:
64 case FormFieldType::kXFA_ComboBox:
65 case FormFieldType::kXFA_ImageField:
66 case FormFieldType::kXFA_ListBox:
67 case FormFieldType::kXFA_PushButton:
68 case FormFieldType::kXFA_Signature:
69 case FormFieldType::kXFA_TextField:
70 return true;
71 default:
72 return false;
73 }
74 }
75 #endif // PDF_ENABLE_XFA
76
77 } // namespace
78
CPDFSDK_InterForm(CPDFSDK_FormFillEnvironment * pFormFillEnv)79 CPDFSDK_InterForm::CPDFSDK_InterForm(CPDFSDK_FormFillEnvironment* pFormFillEnv)
80 : m_pFormFillEnv(pFormFillEnv),
81 m_pInterForm(
82 pdfium::MakeUnique<CPDF_InterForm>(m_pFormFillEnv->GetPDFDocument())),
83 #ifdef PDF_ENABLE_XFA
84 m_bXfaCalculate(true),
85 m_bXfaValidationsEnabled(true),
86 #endif // PDF_ENABLE_XFA
87 m_bCalculate(true),
88 m_bBusy(false),
89 m_HighlightAlpha(0) {
90 m_pInterForm->SetFormNotify(this);
91 RemoveAllHighLights();
92 }
93
~CPDFSDK_InterForm()94 CPDFSDK_InterForm::~CPDFSDK_InterForm() {
95 m_Map.clear();
96 #ifdef PDF_ENABLE_XFA
97 m_XFAMap.clear();
98 #endif // PDF_ENABLE_XFA
99 }
100
HighlightWidgets()101 bool CPDFSDK_InterForm::HighlightWidgets() {
102 return false;
103 }
104
GetSibling(CPDFSDK_Widget * pWidget,bool bNext) const105 CPDFSDK_Widget* CPDFSDK_InterForm::GetSibling(CPDFSDK_Widget* pWidget,
106 bool bNext) const {
107 auto pIterator = pdfium::MakeUnique<CBA_AnnotIterator>(
108 pWidget->GetPageView(), CPDF_Annot::Subtype::WIDGET);
109
110 if (bNext)
111 return static_cast<CPDFSDK_Widget*>(pIterator->GetNextAnnot(pWidget));
112
113 return static_cast<CPDFSDK_Widget*>(pIterator->GetPrevAnnot(pWidget));
114 }
115
GetWidget(CPDF_FormControl * pControl) const116 CPDFSDK_Widget* CPDFSDK_InterForm::GetWidget(CPDF_FormControl* pControl) const {
117 if (!pControl || !m_pInterForm)
118 return nullptr;
119
120 CPDFSDK_Widget* pWidget = nullptr;
121 const auto it = m_Map.find(pControl);
122 if (it != m_Map.end())
123 pWidget = it->second;
124 if (pWidget)
125 return pWidget;
126
127 CPDF_Dictionary* pControlDict = pControl->GetWidget();
128 CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
129 CPDFSDK_PageView* pPage = nullptr;
130
131 if (CPDF_Dictionary* pPageDict = pControlDict->GetDictFor("P")) {
132 int nPageIndex = pDocument->GetPageIndex(pPageDict->GetObjNum());
133 if (nPageIndex >= 0)
134 pPage = m_pFormFillEnv->GetPageView(nPageIndex);
135 }
136
137 if (!pPage) {
138 int nPageIndex = GetPageIndexByAnnotDict(pDocument, pControlDict);
139 if (nPageIndex >= 0)
140 pPage = m_pFormFillEnv->GetPageView(nPageIndex);
141 }
142
143 if (!pPage)
144 return nullptr;
145
146 return static_cast<CPDFSDK_Widget*>(pPage->GetAnnotByDict(pControlDict));
147 }
148
GetWidgets(const WideString & sFieldName,std::vector<CPDFSDK_Annot::ObservedPtr> * widgets) const149 void CPDFSDK_InterForm::GetWidgets(
150 const WideString& sFieldName,
151 std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const {
152 for (int i = 0, sz = m_pInterForm->CountFields(sFieldName); i < sz; ++i) {
153 CPDF_FormField* pFormField = m_pInterForm->GetField(i, sFieldName);
154 ASSERT(pFormField);
155 GetWidgets(pFormField, widgets);
156 }
157 }
158
GetWidgets(CPDF_FormField * pField,std::vector<CPDFSDK_Annot::ObservedPtr> * widgets) const159 void CPDFSDK_InterForm::GetWidgets(
160 CPDF_FormField* pField,
161 std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const {
162 for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
163 CPDF_FormControl* pFormCtrl = pField->GetControl(i);
164 ASSERT(pFormCtrl);
165 CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
166 if (pWidget)
167 widgets->emplace_back(pWidget);
168 }
169 }
170
GetPageIndexByAnnotDict(CPDF_Document * pDocument,CPDF_Dictionary * pAnnotDict) const171 int CPDFSDK_InterForm::GetPageIndexByAnnotDict(
172 CPDF_Document* pDocument,
173 CPDF_Dictionary* pAnnotDict) const {
174 ASSERT(pAnnotDict);
175
176 for (int i = 0, sz = pDocument->GetPageCount(); i < sz; i++) {
177 if (CPDF_Dictionary* pPageDict = pDocument->GetPage(i)) {
178 if (CPDF_Array* pAnnots = pPageDict->GetArrayFor("Annots")) {
179 for (int j = 0, jsz = pAnnots->GetCount(); j < jsz; j++) {
180 CPDF_Object* pDict = pAnnots->GetDirectObjectAt(j);
181 if (pAnnotDict == pDict)
182 return i;
183 }
184 }
185 }
186 }
187
188 return -1;
189 }
190
AddMap(CPDF_FormControl * pControl,CPDFSDK_Widget * pWidget)191 void CPDFSDK_InterForm::AddMap(CPDF_FormControl* pControl,
192 CPDFSDK_Widget* pWidget) {
193 m_Map[pControl] = pWidget;
194 }
195
RemoveMap(CPDF_FormControl * pControl)196 void CPDFSDK_InterForm::RemoveMap(CPDF_FormControl* pControl) {
197 m_Map.erase(pControl);
198 }
199
EnableCalculate(bool bEnabled)200 void CPDFSDK_InterForm::EnableCalculate(bool bEnabled) {
201 m_bCalculate = bEnabled;
202 }
203
IsCalculateEnabled() const204 bool CPDFSDK_InterForm::IsCalculateEnabled() const {
205 return m_bCalculate;
206 }
207
208 #ifdef PDF_ENABLE_XFA
AddXFAMap(CXFA_FFWidget * hWidget,CPDFSDK_XFAWidget * pWidget)209 void CPDFSDK_InterForm::AddXFAMap(CXFA_FFWidget* hWidget,
210 CPDFSDK_XFAWidget* pWidget) {
211 ASSERT(hWidget);
212 m_XFAMap[hWidget] = pWidget;
213 }
214
RemoveXFAMap(CXFA_FFWidget * hWidget)215 void CPDFSDK_InterForm::RemoveXFAMap(CXFA_FFWidget* hWidget) {
216 ASSERT(hWidget);
217 m_XFAMap.erase(hWidget);
218 }
219
GetXFAWidget(CXFA_FFWidget * hWidget)220 CPDFSDK_XFAWidget* CPDFSDK_InterForm::GetXFAWidget(CXFA_FFWidget* hWidget) {
221 ASSERT(hWidget);
222 auto it = m_XFAMap.find(hWidget);
223 return it != m_XFAMap.end() ? it->second : nullptr;
224 }
225
XfaEnableCalculate(bool bEnabled)226 void CPDFSDK_InterForm::XfaEnableCalculate(bool bEnabled) {
227 m_bXfaCalculate = bEnabled;
228 }
IsXfaCalculateEnabled() const229 bool CPDFSDK_InterForm::IsXfaCalculateEnabled() const {
230 return m_bXfaCalculate;
231 }
232
IsXfaValidationsEnabled()233 bool CPDFSDK_InterForm::IsXfaValidationsEnabled() {
234 return m_bXfaValidationsEnabled;
235 }
XfaSetValidationsEnabled(bool bEnabled)236 void CPDFSDK_InterForm::XfaSetValidationsEnabled(bool bEnabled) {
237 m_bXfaValidationsEnabled = bEnabled;
238 }
239
SynchronizeField(CPDF_FormField * pFormField,bool bSynchronizeElse)240 void CPDFSDK_InterForm::SynchronizeField(CPDF_FormField* pFormField,
241 bool bSynchronizeElse) {
242 for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
243 CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
244 if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl))
245 pWidget->Synchronize(bSynchronizeElse);
246 }
247 }
248 #endif // PDF_ENABLE_XFA
249
OnCalculate(CPDF_FormField * pFormField)250 void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) {
251 if (!m_pFormFillEnv->IsJSInitiated())
252 return;
253
254 if (m_bBusy)
255 return;
256
257 m_bBusy = true;
258
259 if (!IsCalculateEnabled()) {
260 m_bBusy = false;
261 return;
262 }
263
264 IJS_Runtime* pRuntime = m_pFormFillEnv->GetJSRuntime();
265 int nSize = m_pInterForm->CountFieldsInCalculationOrder();
266 for (int i = 0; i < nSize; i++) {
267 CPDF_FormField* pField = m_pInterForm->GetFieldInCalculationOrder(i);
268 if (!pField)
269 continue;
270
271 FormFieldType fieldType = pField->GetFieldType();
272 if (!IsFormFieldTypeComboOrText(fieldType))
273 continue;
274
275 CPDF_AAction aAction = pField->GetAdditionalAction();
276 if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::Calculate))
277 continue;
278
279 CPDF_Action action = aAction.GetAction(CPDF_AAction::Calculate);
280 if (!action.GetDict())
281 continue;
282
283 WideString csJS = action.GetJavaScript();
284 if (csJS.IsEmpty())
285 continue;
286
287 IJS_EventContext* pContext = pRuntime->NewEventContext();
288 WideString sOldValue = pField->GetValue();
289 WideString sValue = sOldValue;
290 bool bRC = true;
291 pContext->OnField_Calculate(pFormField, pField, sValue, bRC);
292
293 WideString sInfo;
294 bool bRet = pContext->RunScript(csJS, &sInfo);
295 pRuntime->ReleaseEventContext(pContext);
296 if (bRet && bRC && sValue.Compare(sOldValue) != 0)
297 pField->SetValue(sValue, true);
298 }
299 m_bBusy = false;
300 }
301
OnFormat(CPDF_FormField * pFormField,bool & bFormatted)302 WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField,
303 bool& bFormatted) {
304 WideString sValue = pFormField->GetValue();
305 if (!m_pFormFillEnv->IsJSInitiated()) {
306 bFormatted = false;
307 return sValue;
308 }
309
310 IJS_Runtime* pRuntime = m_pFormFillEnv->GetJSRuntime();
311 if (pFormField->GetFieldType() == FormFieldType::kComboBox &&
312 pFormField->CountSelectedItems() > 0) {
313 int index = pFormField->GetSelectedIndex(0);
314 if (index >= 0)
315 sValue = pFormField->GetOptionLabel(index);
316 }
317
318 bFormatted = false;
319
320 CPDF_AAction aAction = pFormField->GetAdditionalAction();
321 if (aAction.GetDict() && aAction.ActionExist(CPDF_AAction::Format)) {
322 CPDF_Action action = aAction.GetAction(CPDF_AAction::Format);
323 if (action.GetDict()) {
324 WideString script = action.GetJavaScript();
325 if (!script.IsEmpty()) {
326 WideString Value = sValue;
327
328 IJS_EventContext* pContext = pRuntime->NewEventContext();
329 pContext->OnField_Format(pFormField, Value, true);
330 WideString sInfo;
331 bool bRet = pContext->RunScript(script, &sInfo);
332 pRuntime->ReleaseEventContext(pContext);
333 if (bRet) {
334 sValue = Value;
335 bFormatted = true;
336 }
337 }
338 }
339 }
340 return sValue;
341 }
342
ResetFieldAppearance(CPDF_FormField * pFormField,const WideString * sValue,bool bValueChanged)343 void CPDFSDK_InterForm::ResetFieldAppearance(CPDF_FormField* pFormField,
344 const WideString* sValue,
345 bool bValueChanged) {
346 for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
347 CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
348 ASSERT(pFormCtrl);
349 if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl))
350 pWidget->ResetAppearance(sValue, bValueChanged);
351 }
352 }
353
UpdateField(CPDF_FormField * pFormField)354 void CPDFSDK_InterForm::UpdateField(CPDF_FormField* pFormField) {
355 auto* formfiller = m_pFormFillEnv->GetInteractiveFormFiller();
356 for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
357 CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
358 ASSERT(pFormCtrl);
359
360 CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
361 if (!pWidget)
362 continue;
363
364 UnderlyingPageType* pPage = pWidget->GetUnderlyingPage();
365 FX_RECT rect = formfiller->GetViewBBox(
366 m_pFormFillEnv->GetPageView(pPage, false), pWidget);
367 m_pFormFillEnv->Invalidate(pPage, rect);
368 }
369 }
370
OnKeyStrokeCommit(CPDF_FormField * pFormField,const WideString & csValue)371 bool CPDFSDK_InterForm::OnKeyStrokeCommit(CPDF_FormField* pFormField,
372 const WideString& csValue) {
373 CPDF_AAction aAction = pFormField->GetAdditionalAction();
374 if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::KeyStroke))
375 return true;
376
377 CPDF_Action action = aAction.GetAction(CPDF_AAction::KeyStroke);
378 if (!action.GetDict())
379 return true;
380
381 CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler();
382 PDFSDK_FieldAction fa;
383 fa.bModifier = false;
384 fa.bShift = false;
385 fa.sValue = csValue;
386 pActionHandler->DoAction_FieldJavaScript(
387 action, CPDF_AAction::KeyStroke, m_pFormFillEnv.Get(), pFormField, fa);
388 return fa.bRC;
389 }
390
OnValidate(CPDF_FormField * pFormField,const WideString & csValue)391 bool CPDFSDK_InterForm::OnValidate(CPDF_FormField* pFormField,
392 const WideString& csValue) {
393 CPDF_AAction aAction = pFormField->GetAdditionalAction();
394 if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::Validate))
395 return true;
396
397 CPDF_Action action = aAction.GetAction(CPDF_AAction::Validate);
398 if (!action.GetDict())
399 return true;
400
401 CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler();
402 PDFSDK_FieldAction fa;
403 fa.bModifier = false;
404 fa.bShift = false;
405 fa.sValue = csValue;
406 pActionHandler->DoAction_FieldJavaScript(
407 action, CPDF_AAction::Validate, m_pFormFillEnv.Get(), pFormField, fa);
408 return fa.bRC;
409 }
410
DoAction_Hide(const CPDF_Action & action)411 bool CPDFSDK_InterForm::DoAction_Hide(const CPDF_Action& action) {
412 ASSERT(action.GetDict());
413
414 CPDF_ActionFields af(&action);
415 std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
416 std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);
417
418 bool bHide = action.GetHideStatus();
419 bool bChanged = false;
420
421 for (CPDF_FormField* pField : fields) {
422 for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
423 CPDF_FormControl* pControl = pField->GetControl(i);
424 ASSERT(pControl);
425
426 if (CPDFSDK_Widget* pWidget = GetWidget(pControl)) {
427 uint32_t nFlags = pWidget->GetFlags();
428 nFlags &= ~ANNOTFLAG_INVISIBLE;
429 nFlags &= ~ANNOTFLAG_NOVIEW;
430 if (bHide)
431 nFlags |= ANNOTFLAG_HIDDEN;
432 else
433 nFlags &= ~ANNOTFLAG_HIDDEN;
434 pWidget->SetFlags(nFlags);
435 pWidget->GetPageView()->UpdateView(pWidget);
436 bChanged = true;
437 }
438 }
439 }
440
441 return bChanged;
442 }
443
DoAction_SubmitForm(const CPDF_Action & action)444 bool CPDFSDK_InterForm::DoAction_SubmitForm(const CPDF_Action& action) {
445 WideString sDestination = action.GetFilePath();
446 if (sDestination.IsEmpty())
447 return false;
448
449 CPDF_Dictionary* pActionDict = action.GetDict();
450 if (pActionDict->KeyExist("Fields")) {
451 CPDF_ActionFields af(&action);
452 uint32_t dwFlags = action.GetFlags();
453 std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
454 std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);
455 if (!fields.empty()) {
456 bool bIncludeOrExclude = !(dwFlags & 0x01);
457 if (!m_pInterForm->CheckRequiredFields(&fields, bIncludeOrExclude))
458 return false;
459
460 return SubmitFields(sDestination, fields, bIncludeOrExclude, false);
461 }
462 }
463 if (!m_pInterForm->CheckRequiredFields(nullptr, true))
464 return false;
465
466 return SubmitForm(sDestination, false);
467 }
468
SubmitFields(const WideString & csDestination,const std::vector<CPDF_FormField * > & fields,bool bIncludeOrExclude,bool bUrlEncoded)469 bool CPDFSDK_InterForm::SubmitFields(const WideString& csDestination,
470 const std::vector<CPDF_FormField*>& fields,
471 bool bIncludeOrExclude,
472 bool bUrlEncoded) {
473 ByteString textBuf = ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude);
474
475 size_t nBufSize = textBuf.GetLength();
476 if (nBufSize == 0)
477 return false;
478
479 uint8_t* pLocalBuffer = FX_Alloc(uint8_t, nBufSize);
480 memcpy(pLocalBuffer, textBuf.c_str(), nBufSize);
481 uint8_t* pBuffer = pLocalBuffer;
482
483 if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) {
484 FX_Free(pLocalBuffer);
485 return false;
486 }
487
488 m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, csDestination.c_str());
489
490 if (pBuffer != pLocalBuffer)
491 FX_Free(pBuffer);
492
493 FX_Free(pLocalBuffer);
494
495 return true;
496 }
497
FDFToURLEncodedData(uint8_t * & pBuf,size_t & nBufSize)498 bool CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf, size_t& nBufSize) {
499 std::unique_ptr<CFDF_Document> pFDF =
500 CFDF_Document::ParseMemory(pBuf, nBufSize);
501 if (!pFDF)
502 return true;
503
504 CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDictFor("FDF");
505 if (!pMainDict)
506 return false;
507
508 CPDF_Array* pFields = pMainDict->GetArrayFor("Fields");
509 if (!pFields)
510 return false;
511
512 std::ostringstream fdfEncodedData;
513 for (uint32_t i = 0; i < pFields->GetCount(); i++) {
514 CPDF_Dictionary* pField = pFields->GetDictAt(i);
515 if (!pField)
516 continue;
517 WideString name;
518 name = pField->GetUnicodeTextFor("T");
519 ByteString name_b = ByteString::FromUnicode(name);
520 ByteString csBValue = pField->GetStringFor("V");
521 WideString csWValue = PDF_DecodeText(csBValue);
522 ByteString csValue_b = ByteString::FromUnicode(csWValue);
523
524 fdfEncodedData << name_b.GetBuffer(name_b.GetLength());
525 name_b.ReleaseBuffer(name_b.GetStringLength());
526 fdfEncodedData << "=";
527 fdfEncodedData << csValue_b.GetBuffer(csValue_b.GetLength());
528 csValue_b.ReleaseBuffer(csValue_b.GetStringLength());
529 if (i != pFields->GetCount() - 1)
530 fdfEncodedData << "&";
531 }
532
533 nBufSize = fdfEncodedData.tellp();
534 if (nBufSize == 0)
535 return false;
536
537 pBuf = FX_Alloc(uint8_t, nBufSize);
538 memcpy(pBuf, fdfEncodedData.str().c_str(), nBufSize);
539 return true;
540 }
541
ExportFieldsToFDFTextBuf(const std::vector<CPDF_FormField * > & fields,bool bIncludeOrExclude)542 ByteString CPDFSDK_InterForm::ExportFieldsToFDFTextBuf(
543 const std::vector<CPDF_FormField*>& fields,
544 bool bIncludeOrExclude) {
545 std::unique_ptr<CFDF_Document> pFDF = m_pInterForm->ExportToFDF(
546 m_pFormFillEnv->JS_docGetFilePath(), fields, bIncludeOrExclude, false);
547
548 return pFDF ? pFDF->WriteToString() : ByteString();
549 }
550
SubmitForm(const WideString & sDestination,bool bUrlEncoded)551 bool CPDFSDK_InterForm::SubmitForm(const WideString& sDestination,
552 bool bUrlEncoded) {
553 if (sDestination.IsEmpty())
554 return false;
555
556 if (!m_pFormFillEnv || !m_pInterForm)
557 return false;
558
559 std::unique_ptr<CFDF_Document> pFDFDoc =
560 m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false);
561 if (!pFDFDoc)
562 return false;
563
564 ByteString fdfBuffer = pFDFDoc->WriteToString();
565
566 if (fdfBuffer.IsEmpty())
567 return false;
568
569 uint8_t* pLocalBuffer = FX_Alloc(uint8_t, fdfBuffer.GetLength());
570 memcpy(pLocalBuffer, fdfBuffer.c_str(), fdfBuffer.GetLength());
571 uint8_t* pBuffer = pLocalBuffer;
572
573 size_t nBufSize = fdfBuffer.GetLength();
574 if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) {
575 FX_Free(pLocalBuffer);
576 return false;
577 }
578
579 m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, sDestination.c_str());
580
581 if (pBuffer != pLocalBuffer)
582 FX_Free(pBuffer);
583
584 FX_Free(pLocalBuffer);
585
586 return true;
587 }
588
ExportFormToFDFTextBuf()589 ByteString CPDFSDK_InterForm::ExportFormToFDFTextBuf() {
590 std::unique_ptr<CFDF_Document> pFDF =
591 m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false);
592
593 return pFDF ? pFDF->WriteToString() : ByteString();
594 }
595
DoAction_ResetForm(const CPDF_Action & action)596 bool CPDFSDK_InterForm::DoAction_ResetForm(const CPDF_Action& action) {
597 ASSERT(action.GetDict());
598
599 CPDF_Dictionary* pActionDict = action.GetDict();
600 if (!pActionDict->KeyExist("Fields"))
601 return m_pInterForm->ResetForm(true);
602
603 CPDF_ActionFields af(&action);
604 uint32_t dwFlags = action.GetFlags();
605
606 std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
607 std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);
608 return m_pInterForm->ResetForm(fields, !(dwFlags & 0x01), true);
609 }
610
DoAction_ImportData(const CPDF_Action & action)611 bool CPDFSDK_InterForm::DoAction_ImportData(const CPDF_Action& action) {
612 return false;
613 }
614
GetFieldFromObjects(const std::vector<CPDF_Object * > & objects) const615 std::vector<CPDF_FormField*> CPDFSDK_InterForm::GetFieldFromObjects(
616 const std::vector<CPDF_Object*>& objects) const {
617 std::vector<CPDF_FormField*> fields;
618 for (CPDF_Object* pObject : objects) {
619 if (pObject && pObject->IsString()) {
620 WideString csName = pObject->GetUnicodeText();
621 CPDF_FormField* pField = m_pInterForm->GetField(0, csName);
622 if (pField)
623 fields.push_back(pField);
624 }
625 }
626 return fields;
627 }
628
BeforeValueChange(CPDF_FormField * pField,const WideString & csValue)629 int CPDFSDK_InterForm::BeforeValueChange(CPDF_FormField* pField,
630 const WideString& csValue) {
631 FormFieldType fieldType = pField->GetFieldType();
632 if (!IsFormFieldTypeComboOrText(fieldType))
633 return 0;
634
635 if (!OnKeyStrokeCommit(pField, csValue))
636 return -1;
637
638 if (!OnValidate(pField, csValue))
639 return -1;
640
641 return 1;
642 }
643
AfterValueChange(CPDF_FormField * pField)644 void CPDFSDK_InterForm::AfterValueChange(CPDF_FormField* pField) {
645 #ifdef PDF_ENABLE_XFA
646 SynchronizeField(pField, false);
647 #endif // PDF_ENABLE_XFA
648 FormFieldType fieldType = pField->GetFieldType();
649 if (IsFormFieldTypeComboOrText(fieldType)) {
650 OnCalculate(pField);
651 bool bFormatted = false;
652 WideString sValue = OnFormat(pField, bFormatted);
653 ResetFieldAppearance(pField, bFormatted ? &sValue : nullptr, true);
654 UpdateField(pField);
655 }
656 }
657
BeforeSelectionChange(CPDF_FormField * pField,const WideString & csValue)658 int CPDFSDK_InterForm::BeforeSelectionChange(CPDF_FormField* pField,
659 const WideString& csValue) {
660 if (pField->GetFieldType() != FormFieldType::kListBox)
661 return 0;
662
663 if (!OnKeyStrokeCommit(pField, csValue))
664 return -1;
665
666 if (!OnValidate(pField, csValue))
667 return -1;
668
669 return 1;
670 }
671
AfterSelectionChange(CPDF_FormField * pField)672 void CPDFSDK_InterForm::AfterSelectionChange(CPDF_FormField* pField) {
673 if (pField->GetFieldType() != FormFieldType::kListBox)
674 return;
675
676 OnCalculate(pField);
677 ResetFieldAppearance(pField, nullptr, true);
678 UpdateField(pField);
679 }
680
AfterCheckedStatusChange(CPDF_FormField * pField)681 void CPDFSDK_InterForm::AfterCheckedStatusChange(CPDF_FormField* pField) {
682 FormFieldType fieldType = pField->GetFieldType();
683 if (fieldType != FormFieldType::kCheckBox &&
684 fieldType != FormFieldType::kRadioButton)
685 return;
686
687 OnCalculate(pField);
688 UpdateField(pField);
689 }
690
BeforeFormReset(CPDF_InterForm * pForm)691 int CPDFSDK_InterForm::BeforeFormReset(CPDF_InterForm* pForm) {
692 return 0;
693 }
694
AfterFormReset(CPDF_InterForm * pForm)695 void CPDFSDK_InterForm::AfterFormReset(CPDF_InterForm* pForm) {
696 OnCalculate(nullptr);
697 }
698
BeforeFormImportData(CPDF_InterForm * pForm)699 int CPDFSDK_InterForm::BeforeFormImportData(CPDF_InterForm* pForm) {
700 return 0;
701 }
702
AfterFormImportData(CPDF_InterForm * pForm)703 void CPDFSDK_InterForm::AfterFormImportData(CPDF_InterForm* pForm) {
704 OnCalculate(nullptr);
705 }
706
IsNeedHighLight(FormFieldType fieldType)707 bool CPDFSDK_InterForm::IsNeedHighLight(FormFieldType fieldType) {
708 if (fieldType == FormFieldType::kUnknown)
709 return false;
710
711 #ifdef PDF_ENABLE_XFA
712 // For the XFA fields, we need to return if the specific field type has
713 // highlight enabled or if the general XFA field type has it enabled.
714 if (IsFormFieldTypeXFA(fieldType)) {
715 if (!m_NeedsHighlight[static_cast<size_t>(fieldType)])
716 return m_NeedsHighlight[static_cast<size_t>(FormFieldType::kXFA)];
717 }
718 #endif // PDF_ENABLE_XFA
719 return m_NeedsHighlight[static_cast<size_t>(fieldType)];
720 }
721
RemoveAllHighLights()722 void CPDFSDK_InterForm::RemoveAllHighLights() {
723 std::fill(m_HighlightColor, m_HighlightColor + kFormFieldTypeCount,
724 FXSYS_RGB(255, 255, 255));
725 std::fill(m_NeedsHighlight, m_NeedsHighlight + kFormFieldTypeCount, false);
726 }
727
SetHighlightColor(FX_COLORREF clr,FormFieldType fieldType)728 void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr,
729 FormFieldType fieldType) {
730 if (fieldType == FormFieldType::kUnknown)
731 return;
732
733 m_HighlightColor[static_cast<size_t>(fieldType)] = clr;
734 m_NeedsHighlight[static_cast<size_t>(fieldType)] = true;
735 }
736
SetAllHighlightColors(FX_COLORREF clr)737 void CPDFSDK_InterForm::SetAllHighlightColors(FX_COLORREF clr) {
738 for (auto type : kFormFieldTypes) {
739 m_HighlightColor[static_cast<size_t>(type)] = clr;
740 m_NeedsHighlight[static_cast<size_t>(type)] = true;
741 }
742 }
743
GetHighlightColor(FormFieldType fieldType)744 FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(FormFieldType fieldType) {
745 if (fieldType == FormFieldType::kUnknown)
746 return FXSYS_RGB(255, 255, 255);
747
748 #ifdef PDF_ENABLE_XFA
749 // For the XFA fields, we need to return the specific field type highlight
750 // colour or the general XFA field type colour if present.
751 if (IsFormFieldTypeXFA(fieldType)) {
752 if (!m_NeedsHighlight[static_cast<size_t>(fieldType)] &&
753 m_NeedsHighlight[static_cast<size_t>(FormFieldType::kXFA)]) {
754 return m_HighlightColor[static_cast<size_t>(FormFieldType::kXFA)];
755 }
756 }
757 #endif // PDF_ENABLE_XFA
758 return m_HighlightColor[static_cast<size_t>(fieldType)];
759 }
760