• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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