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/fpdfxfa/cpdfxfa_docenvironment.h"
8
9 #include <memory>
10
11 #include "core/fpdfapi/parser/cpdf_array.h"
12 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
13 #include "core/fpdfapi/parser/cpdf_string.h"
14 #include "core/fxcrt/cfx_retain_ptr.h"
15 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
16 #include "fpdfsdk/cpdfsdk_interform.h"
17 #include "fpdfsdk/cpdfsdk_pageview.h"
18 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
19 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
20 #include "fpdfsdk/javascript/ijs_runtime.h"
21 #include "xfa/fxfa/xfa_ffdocview.h"
22 #include "xfa/fxfa/xfa_ffwidget.h"
23 #include "xfa/fxfa/xfa_ffwidgethandler.h"
24
25 #define IDS_XFA_Validate_Input \
26 "At least one required field was empty. Please fill in the required " \
27 "fields\r\n(highlighted) before continuing."
28
29 // submit
30 #define FXFA_CONFIG 0x00000001
31 #define FXFA_TEMPLATE 0x00000010
32 #define FXFA_LOCALESET 0x00000100
33 #define FXFA_DATASETS 0x00001000
34 #define FXFA_XMPMETA 0x00010000
35 #define FXFA_XFDF 0x00100000
36 #define FXFA_FORM 0x01000000
37 #define FXFA_PDF 0x10000000
38 #define FXFA_XFA_ALL 0x01111111
39
CPDFXFA_DocEnvironment(CPDFXFA_Context * pContext)40 CPDFXFA_DocEnvironment::CPDFXFA_DocEnvironment(CPDFXFA_Context* pContext)
41 : m_pContext(pContext), m_pJSEventContext(nullptr) {
42 ASSERT(m_pContext);
43 }
44
~CPDFXFA_DocEnvironment()45 CPDFXFA_DocEnvironment::~CPDFXFA_DocEnvironment() {
46 if (m_pJSEventContext && m_pContext->GetFormFillEnv()) {
47 m_pContext->GetFormFillEnv()->GetJSRuntime()->ReleaseEventContext(
48 m_pJSEventContext);
49 }
50 }
51
SetChangeMark(CXFA_FFDoc * hDoc)52 void CPDFXFA_DocEnvironment::SetChangeMark(CXFA_FFDoc* hDoc) {
53 if (hDoc == m_pContext->GetXFADoc() && m_pContext->GetFormFillEnv())
54 m_pContext->GetFormFillEnv()->SetChangeMark();
55 }
56
InvalidateRect(CXFA_FFPageView * pPageView,const CFX_RectF & rt,uint32_t dwFlags)57 void CPDFXFA_DocEnvironment::InvalidateRect(CXFA_FFPageView* pPageView,
58 const CFX_RectF& rt,
59 uint32_t dwFlags /* = 0 */) {
60 if (!m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
61 return;
62
63 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA)
64 return;
65
66 CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pPageView);
67 if (!pPage)
68 return;
69
70 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
71 if (!pFormFillEnv)
72 return;
73
74 pFormFillEnv->Invalidate(static_cast<FPDF_PAGE>(pPage),
75 CFX_FloatRect::FromCFXRectF(rt).ToFxRect());
76 }
77
DisplayCaret(CXFA_FFWidget * hWidget,bool bVisible,const CFX_RectF * pRtAnchor)78 void CPDFXFA_DocEnvironment::DisplayCaret(CXFA_FFWidget* hWidget,
79 bool bVisible,
80 const CFX_RectF* pRtAnchor) {
81 if (!hWidget || !pRtAnchor || !m_pContext->GetXFADoc() ||
82 !m_pContext->GetFormFillEnv() || !m_pContext->GetXFADocView())
83 return;
84
85 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA)
86 return;
87
88 CXFA_FFWidgetHandler* pWidgetHandler =
89 m_pContext->GetXFADocView()->GetWidgetHandler();
90 if (!pWidgetHandler)
91 return;
92
93 CXFA_FFPageView* pPageView = hWidget->GetPageView();
94 if (!pPageView)
95 return;
96
97 CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pPageView);
98 if (!pPage)
99 return;
100
101 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
102 if (!pFormFillEnv)
103 return;
104
105 CFX_FloatRect rcCaret = CFX_FloatRect::FromCFXRectF(*pRtAnchor);
106 pFormFillEnv->DisplayCaret((FPDF_PAGE)pPage, bVisible, rcCaret.left,
107 rcCaret.top, rcCaret.right, rcCaret.bottom);
108 }
109
GetPopupPos(CXFA_FFWidget * hWidget,FX_FLOAT fMinPopup,FX_FLOAT fMaxPopup,const CFX_RectF & rtAnchor,CFX_RectF & rtPopup)110 bool CPDFXFA_DocEnvironment::GetPopupPos(CXFA_FFWidget* hWidget,
111 FX_FLOAT fMinPopup,
112 FX_FLOAT fMaxPopup,
113 const CFX_RectF& rtAnchor,
114 CFX_RectF& rtPopup) {
115 if (!hWidget)
116 return false;
117
118 CXFA_FFPageView* pXFAPageView = hWidget->GetPageView();
119 if (!pXFAPageView)
120 return false;
121
122 CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pXFAPageView);
123 if (!pPage)
124 return false;
125
126 CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc();
127 int nRotate = pWidgetAcc->GetRotate();
128 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
129 if (!pFormFillEnv)
130 return false;
131
132 FS_RECTF pageViewRect = {0.0f, 0.0f, 0.0f, 0.0f};
133 pFormFillEnv->GetPageViewRect(pPage, pageViewRect);
134
135 int t1;
136 int t2;
137 CFX_FloatRect rcAnchor = CFX_FloatRect::FromCFXRectF(rtAnchor);
138 switch (nRotate) {
139 case 90: {
140 t1 = (int)(pageViewRect.right - rcAnchor.right);
141 t2 = (int)(rcAnchor.left - pageViewRect.left);
142 if (rcAnchor.bottom < pageViewRect.bottom)
143 rtPopup.left += rcAnchor.bottom - pageViewRect.bottom;
144 break;
145 }
146 case 180: {
147 t2 = (int)(pageViewRect.top - rcAnchor.top);
148 t1 = (int)(rcAnchor.bottom - pageViewRect.bottom);
149 if (rcAnchor.left < pageViewRect.left)
150 rtPopup.left += rcAnchor.left - pageViewRect.left;
151 break;
152 }
153 case 270: {
154 t1 = (int)(rcAnchor.left - pageViewRect.left);
155 t2 = (int)(pageViewRect.right - rcAnchor.right);
156 if (rcAnchor.top > pageViewRect.top)
157 rtPopup.left -= rcAnchor.top - pageViewRect.top;
158 break;
159 }
160 case 0:
161 default: {
162 t1 = (int)(pageViewRect.top - rcAnchor.top);
163 t2 = (int)(rcAnchor.bottom - pageViewRect.bottom);
164 if (rcAnchor.right > pageViewRect.right)
165 rtPopup.left -= rcAnchor.right - pageViewRect.right;
166 break;
167 }
168 }
169
170 int t;
171 uint32_t dwPos;
172 if (t1 <= 0 && t2 <= 0)
173 return false;
174 if (t1 <= 0) {
175 t = t2;
176 dwPos = 1;
177 } else if (t2 <= 0) {
178 t = t1;
179 dwPos = 0;
180 } else if (t1 > t2) {
181 t = t1;
182 dwPos = 0;
183 } else {
184 t = t2;
185 dwPos = 1;
186 }
187
188 FX_FLOAT fPopupHeight;
189 if (t < fMinPopup)
190 fPopupHeight = fMinPopup;
191 else if (t > fMaxPopup)
192 fPopupHeight = fMaxPopup;
193 else
194 fPopupHeight = static_cast<FX_FLOAT>(t);
195
196 switch (nRotate) {
197 case 0:
198 case 180: {
199 if (dwPos == 0) {
200 rtPopup.top = rtAnchor.height;
201 rtPopup.height = fPopupHeight;
202 } else {
203 rtPopup.top = -fPopupHeight;
204 rtPopup.height = fPopupHeight;
205 }
206 break;
207 }
208 case 90:
209 case 270: {
210 if (dwPos == 0) {
211 rtPopup.top = rtAnchor.width;
212 rtPopup.height = fPopupHeight;
213 } else {
214 rtPopup.top = -fPopupHeight;
215 rtPopup.height = fPopupHeight;
216 }
217 break;
218 }
219 default:
220 break;
221 }
222
223 return true;
224 }
225
PopupMenu(CXFA_FFWidget * hWidget,CFX_PointF ptPopup)226 bool CPDFXFA_DocEnvironment::PopupMenu(CXFA_FFWidget* hWidget,
227 CFX_PointF ptPopup) {
228 if (!hWidget)
229 return false;
230
231 CXFA_FFPageView* pXFAPageView = hWidget->GetPageView();
232 if (!pXFAPageView)
233 return false;
234
235 CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pXFAPageView);
236 if (!pPage)
237 return false;
238
239 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
240 if (!pFormFillEnv)
241 return false;
242
243 int menuFlag = 0;
244 if (hWidget->CanUndo())
245 menuFlag |= FXFA_MENU_UNDO;
246 if (hWidget->CanRedo())
247 menuFlag |= FXFA_MENU_REDO;
248 if (hWidget->CanPaste())
249 menuFlag |= FXFA_MENU_PASTE;
250 if (hWidget->CanCopy())
251 menuFlag |= FXFA_MENU_COPY;
252 if (hWidget->CanCut())
253 menuFlag |= FXFA_MENU_CUT;
254 if (hWidget->CanSelectAll())
255 menuFlag |= FXFA_MENU_SELECTALL;
256
257 return pFormFillEnv->PopupMenu(pPage, hWidget, menuFlag, ptPopup);
258 }
259
PageViewEvent(CXFA_FFPageView * pPageView,uint32_t dwFlags)260 void CPDFXFA_DocEnvironment::PageViewEvent(CXFA_FFPageView* pPageView,
261 uint32_t dwFlags) {
262 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
263 if (!pFormFillEnv)
264 return;
265
266 if (m_pContext->GetLoadStatus() == FXFA_LOADSTATUS_LOADING ||
267 m_pContext->GetLoadStatus() == FXFA_LOADSTATUS_CLOSING ||
268 XFA_PAGEVIEWEVENT_StopLayout != dwFlags)
269 return;
270
271 int nNewCount = m_pContext->GetPageCount();
272 if (nNewCount == m_pContext->GetOriginalPageCount())
273 return;
274
275 CXFA_FFDocView* pXFADocView = m_pContext->GetXFADocView();
276 if (!pXFADocView)
277 return;
278
279 for (int iPageIter = 0; iPageIter < m_pContext->GetOriginalPageCount();
280 iPageIter++) {
281 CPDFXFA_Page* pPage = (*m_pContext->GetXFAPageList())[iPageIter];
282 if (!pPage)
283 continue;
284
285 m_pContext->GetFormFillEnv()->RemovePageView(pPage);
286 pPage->SetXFAPageView(pXFADocView->GetPageView(iPageIter));
287 }
288
289 int flag = (nNewCount < m_pContext->GetOriginalPageCount())
290 ? FXFA_PAGEVIEWEVENT_POSTREMOVED
291 : FXFA_PAGEVIEWEVENT_POSTADDED;
292 int count = FXSYS_abs(nNewCount - m_pContext->GetOriginalPageCount());
293 m_pContext->SetOriginalPageCount(nNewCount);
294 pFormFillEnv->PageEvent(count, flag);
295 }
296
WidgetPostAdd(CXFA_FFWidget * hWidget,CXFA_WidgetAcc * pWidgetData)297 void CPDFXFA_DocEnvironment::WidgetPostAdd(CXFA_FFWidget* hWidget,
298 CXFA_WidgetAcc* pWidgetData) {
299 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || !hWidget)
300 return;
301
302 CXFA_FFPageView* pPageView = hWidget->GetPageView();
303 if (!pPageView)
304 return;
305
306 CPDFXFA_Page* pXFAPage = m_pContext->GetXFAPage(pPageView);
307 if (!pXFAPage)
308 return;
309
310 m_pContext->GetFormFillEnv()->GetPageView(pXFAPage, true)->AddAnnot(hWidget);
311 }
312
WidgetPreRemove(CXFA_FFWidget * hWidget,CXFA_WidgetAcc * pWidgetData)313 void CPDFXFA_DocEnvironment::WidgetPreRemove(CXFA_FFWidget* hWidget,
314 CXFA_WidgetAcc* pWidgetData) {
315 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || !hWidget)
316 return;
317
318 CXFA_FFPageView* pPageView = hWidget->GetPageView();
319 if (!pPageView)
320 return;
321
322 CPDFXFA_Page* pXFAPage = m_pContext->GetXFAPage(pPageView);
323 if (!pXFAPage)
324 return;
325
326 CPDFSDK_PageView* pSdkPageView =
327 m_pContext->GetFormFillEnv()->GetPageView(pXFAPage, true);
328 if (CPDFSDK_Annot* pAnnot = pSdkPageView->GetAnnotByXFAWidget(hWidget))
329 pSdkPageView->DeleteAnnot(pAnnot);
330 }
331
CountPages(CXFA_FFDoc * hDoc)332 int32_t CPDFXFA_DocEnvironment::CountPages(CXFA_FFDoc* hDoc) {
333 if (hDoc == m_pContext->GetXFADoc() && m_pContext->GetFormFillEnv())
334 return m_pContext->GetPageCount();
335 return 0;
336 }
337
GetCurrentPage(CXFA_FFDoc * hDoc)338 int32_t CPDFXFA_DocEnvironment::GetCurrentPage(CXFA_FFDoc* hDoc) {
339 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
340 return -1;
341 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA)
342 return -1;
343
344 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
345 if (!pFormFillEnv)
346 return -1;
347
348 return pFormFillEnv->GetCurrentPageIndex(this);
349 }
350
SetCurrentPage(CXFA_FFDoc * hDoc,int32_t iCurPage)351 void CPDFXFA_DocEnvironment::SetCurrentPage(CXFA_FFDoc* hDoc,
352 int32_t iCurPage) {
353 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv() ||
354 m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || iCurPage < 0 ||
355 iCurPage >= m_pContext->GetFormFillEnv()->GetPageCount()) {
356 return;
357 }
358
359 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
360 if (!pFormFillEnv)
361 return;
362 pFormFillEnv->SetCurrentPage(this, iCurPage);
363 }
364
IsCalculationsEnabled(CXFA_FFDoc * hDoc)365 bool CPDFXFA_DocEnvironment::IsCalculationsEnabled(CXFA_FFDoc* hDoc) {
366 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
367 return false;
368 if (m_pContext->GetFormFillEnv()->GetInterForm()) {
369 return m_pContext->GetFormFillEnv()
370 ->GetInterForm()
371 ->IsXfaCalculateEnabled();
372 }
373 return false;
374 }
375
SetCalculationsEnabled(CXFA_FFDoc * hDoc,bool bEnabled)376 void CPDFXFA_DocEnvironment::SetCalculationsEnabled(CXFA_FFDoc* hDoc,
377 bool bEnabled) {
378 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
379 return;
380 if (m_pContext->GetFormFillEnv()->GetInterForm()) {
381 m_pContext->GetFormFillEnv()->GetInterForm()->XfaEnableCalculate(bEnabled);
382 }
383 }
384
GetTitle(CXFA_FFDoc * hDoc,CFX_WideString & wsTitle)385 void CPDFXFA_DocEnvironment::GetTitle(CXFA_FFDoc* hDoc,
386 CFX_WideString& wsTitle) {
387 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetPDFDoc())
388 return;
389
390 CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo();
391 if (!pInfoDict)
392 return;
393
394 CFX_ByteString csTitle = pInfoDict->GetStringFor("Title");
395 wsTitle = wsTitle.FromLocal(csTitle.GetBuffer(csTitle.GetLength()));
396 csTitle.ReleaseBuffer(csTitle.GetLength());
397 }
398
SetTitle(CXFA_FFDoc * hDoc,const CFX_WideString & wsTitle)399 void CPDFXFA_DocEnvironment::SetTitle(CXFA_FFDoc* hDoc,
400 const CFX_WideString& wsTitle) {
401 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetPDFDoc())
402 return;
403
404 if (CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo())
405 pInfoDict->SetNewFor<CPDF_String>("Title", wsTitle);
406 }
407
ExportData(CXFA_FFDoc * hDoc,const CFX_WideString & wsFilePath,bool bXDP)408 void CPDFXFA_DocEnvironment::ExportData(CXFA_FFDoc* hDoc,
409 const CFX_WideString& wsFilePath,
410 bool bXDP) {
411 if (hDoc != m_pContext->GetXFADoc())
412 return;
413
414 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
415 m_pContext->GetDocType() != DOCTYPE_STATIC_XFA) {
416 return;
417 }
418
419 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
420 if (!pFormFillEnv)
421 return;
422
423 int fileType = bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML;
424 CFX_ByteString bs = wsFilePath.UTF16LE_Encode();
425 if (wsFilePath.IsEmpty()) {
426 if (!pFormFillEnv->GetFormFillInfo() ||
427 !pFormFillEnv->GetFormFillInfo()->m_pJsPlatform) {
428 return;
429 }
430
431 CFX_WideString filepath = pFormFillEnv->JS_fieldBrowse();
432 bs = filepath.UTF16LE_Encode();
433 }
434 int len = bs.GetLength();
435 FPDF_FILEHANDLER* pFileHandler =
436 pFormFillEnv->OpenFile(bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML,
437 (FPDF_WIDESTRING)bs.GetBuffer(len), "wb");
438 bs.ReleaseBuffer(len);
439 if (!pFileHandler)
440 return;
441
442 CFX_RetainPtr<IFX_SeekableStream> fileWrite =
443 MakeSeekableStream(pFileHandler);
444 CFX_ByteString content;
445 if (fileType == FXFA_SAVEAS_XML) {
446 content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
447 fileWrite->WriteBlock(content.c_str(), fileWrite->GetSize(),
448 content.GetLength());
449 m_pContext->GetXFADocView()->GetDoc()->SavePackage(XFA_HASHCODE_Data,
450 fileWrite, nullptr);
451 } else if (fileType == FXFA_SAVEAS_XDP) {
452 if (!m_pContext->GetPDFDoc())
453 return;
454
455 CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot();
456 if (!pRoot)
457 return;
458
459 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
460 if (!pAcroForm)
461 return;
462
463 CPDF_Array* pArray = ToArray(pAcroForm->GetObjectFor("XFA"));
464 if (!pArray)
465 return;
466
467 int size = pArray->GetCount();
468 for (int i = 1; i < size; i += 2) {
469 CPDF_Object* pPDFObj = pArray->GetObjectAt(i);
470 CPDF_Object* pPrePDFObj = pArray->GetObjectAt(i - 1);
471 if (!pPrePDFObj->IsString())
472 continue;
473 if (!pPDFObj->IsReference())
474 continue;
475
476 CPDF_Stream* pStream = ToStream(pPDFObj->GetDirect());
477 if (!pStream)
478 continue;
479 if (pPrePDFObj->GetString() == "form") {
480 m_pContext->GetXFADocView()->GetDoc()->SavePackage(XFA_HASHCODE_Form,
481 fileWrite, nullptr);
482 continue;
483 }
484 if (pPrePDFObj->GetString() == "datasets") {
485 m_pContext->GetXFADocView()->GetDoc()->SavePackage(
486 XFA_HASHCODE_Datasets, fileWrite, nullptr);
487 continue;
488 }
489 if (i == size - 1) {
490 CFX_WideString wPath = CFX_WideString::FromUTF16LE(
491 reinterpret_cast<const unsigned short*>(bs.c_str()),
492 bs.GetLength() / sizeof(unsigned short));
493 CFX_ByteString bPath = wPath.UTF8Encode();
494 const char* szFormat =
495 "\n<pdf href=\"%s\" xmlns=\"http://ns.adobe.com/xdp/pdf/\"/>";
496 content.Format(szFormat, bPath.c_str());
497 fileWrite->WriteBlock(content.c_str(), fileWrite->GetSize(),
498 content.GetLength());
499 }
500 std::unique_ptr<CPDF_StreamAcc> pAcc(new CPDF_StreamAcc);
501 pAcc->LoadAllData(pStream);
502 fileWrite->WriteBlock(pAcc->GetData(), fileWrite->GetSize(),
503 pAcc->GetSize());
504 }
505 }
506 fileWrite->Flush();
507 }
508
GotoURL(CXFA_FFDoc * hDoc,const CFX_WideString & bsURL)509 void CPDFXFA_DocEnvironment::GotoURL(CXFA_FFDoc* hDoc,
510 const CFX_WideString& bsURL) {
511 if (hDoc != m_pContext->GetXFADoc())
512 return;
513
514 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA)
515 return;
516
517 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
518 if (!pFormFillEnv)
519 return;
520
521 CFX_WideStringC str(bsURL.c_str());
522 pFormFillEnv->GotoURL(this, str);
523 }
524
IsValidationsEnabled(CXFA_FFDoc * hDoc)525 bool CPDFXFA_DocEnvironment::IsValidationsEnabled(CXFA_FFDoc* hDoc) {
526 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
527 return false;
528 if (m_pContext->GetFormFillEnv()->GetInterForm()) {
529 return m_pContext->GetFormFillEnv()
530 ->GetInterForm()
531 ->IsXfaValidationsEnabled();
532 }
533 return true;
534 }
535
SetValidationsEnabled(CXFA_FFDoc * hDoc,bool bEnabled)536 void CPDFXFA_DocEnvironment::SetValidationsEnabled(CXFA_FFDoc* hDoc,
537 bool bEnabled) {
538 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
539 return;
540 if (m_pContext->GetFormFillEnv()->GetInterForm()) {
541 m_pContext->GetFormFillEnv()->GetInterForm()->XfaSetValidationsEnabled(
542 bEnabled);
543 }
544 }
545
SetFocusWidget(CXFA_FFDoc * hDoc,CXFA_FFWidget * hWidget)546 void CPDFXFA_DocEnvironment::SetFocusWidget(CXFA_FFDoc* hDoc,
547 CXFA_FFWidget* hWidget) {
548 if (hDoc != m_pContext->GetXFADoc())
549 return;
550
551 if (!hWidget) {
552 CPDFSDK_Annot::ObservedPtr pNull;
553 m_pContext->GetFormFillEnv()->SetFocusAnnot(&pNull);
554 return;
555 }
556
557 int pageViewCount = m_pContext->GetFormFillEnv()->GetPageViewCount();
558 for (int i = 0; i < pageViewCount; i++) {
559 CPDFSDK_PageView* pPageView = m_pContext->GetFormFillEnv()->GetPageView(i);
560 if (!pPageView)
561 continue;
562
563 CPDFSDK_Annot::ObservedPtr pAnnot(pPageView->GetAnnotByXFAWidget(hWidget));
564 if (pAnnot) {
565 m_pContext->GetFormFillEnv()->SetFocusAnnot(&pAnnot);
566 break;
567 }
568 }
569 }
570
Print(CXFA_FFDoc * hDoc,int32_t nStartPage,int32_t nEndPage,uint32_t dwOptions)571 void CPDFXFA_DocEnvironment::Print(CXFA_FFDoc* hDoc,
572 int32_t nStartPage,
573 int32_t nEndPage,
574 uint32_t dwOptions) {
575 if (hDoc != m_pContext->GetXFADoc())
576 return;
577
578 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
579 if (!pFormFillEnv || !pFormFillEnv->GetFormFillInfo() ||
580 !pFormFillEnv->GetFormFillInfo()->m_pJsPlatform ||
581 !pFormFillEnv->GetFormFillInfo()->m_pJsPlatform->Doc_print) {
582 return;
583 }
584
585 pFormFillEnv->GetFormFillInfo()->m_pJsPlatform->Doc_print(
586 pFormFillEnv->GetFormFillInfo()->m_pJsPlatform,
587 dwOptions & XFA_PRINTOPT_ShowDialog, nStartPage, nEndPage,
588 dwOptions & XFA_PRINTOPT_CanCancel, dwOptions & XFA_PRINTOPT_ShrinkPage,
589 dwOptions & XFA_PRINTOPT_AsImage, dwOptions & XFA_PRINTOPT_ReverseOrder,
590 dwOptions & XFA_PRINTOPT_PrintAnnot);
591 }
592
GetHighlightColor(CXFA_FFDoc * hDoc)593 FX_ARGB CPDFXFA_DocEnvironment::GetHighlightColor(CXFA_FFDoc* hDoc) {
594 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
595 return 0;
596
597 CPDFSDK_InterForm* pInterForm = m_pContext->GetFormFillEnv()->GetInterForm();
598 if (!pInterForm)
599 return 0;
600
601 return ArgbEncode(pInterForm->GetHighlightAlpha(),
602 pInterForm->GetHighlightColor(FPDF_FORMFIELD_XFA));
603 }
604
NotifySubmit(bool bPrevOrPost)605 bool CPDFXFA_DocEnvironment::NotifySubmit(bool bPrevOrPost) {
606 if (bPrevOrPost)
607 return OnBeforeNotifySubmit();
608
609 OnAfterNotifySubmit();
610 return true;
611 }
612
OnBeforeNotifySubmit()613 bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() {
614 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
615 m_pContext->GetDocType() != DOCTYPE_STATIC_XFA) {
616 return true;
617 }
618
619 if (!m_pContext->GetXFADocView())
620 return true;
621
622 CXFA_FFWidgetHandler* pWidgetHandler =
623 m_pContext->GetXFADocView()->GetWidgetHandler();
624 if (!pWidgetHandler)
625 return true;
626
627 std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator(
628 m_pContext->GetXFADocView()->CreateWidgetAccIterator());
629 if (pWidgetAccIterator) {
630 CXFA_EventParam Param;
631 Param.m_eType = XFA_EVENT_PreSubmit;
632 while (CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext())
633 pWidgetHandler->ProcessEvent(pWidgetAcc, &Param);
634 }
635
636 pWidgetAccIterator.reset(
637 m_pContext->GetXFADocView()->CreateWidgetAccIterator());
638 if (!pWidgetAccIterator)
639 return true;
640
641 CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext();
642 pWidgetAcc = pWidgetAccIterator->MoveToNext();
643 while (pWidgetAcc) {
644 int fRet = pWidgetAcc->ProcessValidate(-1);
645 if (fRet == XFA_EVENTERROR_Error) {
646 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
647 if (!pFormFillEnv)
648 return false;
649
650 CFX_WideString ws;
651 ws.FromLocal(IDS_XFA_Validate_Input);
652 CFX_ByteString bs = ws.UTF16LE_Encode();
653 int len = bs.GetLength();
654 pFormFillEnv->Alert((FPDF_WIDESTRING)bs.GetBuffer(len),
655 (FPDF_WIDESTRING)L"", 0, 1);
656 bs.ReleaseBuffer(len);
657 return false;
658 }
659 pWidgetAcc = pWidgetAccIterator->MoveToNext();
660 }
661 m_pContext->GetXFADocView()->UpdateDocView();
662
663 return true;
664 }
665
OnAfterNotifySubmit()666 void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() {
667 if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
668 m_pContext->GetDocType() != DOCTYPE_STATIC_XFA)
669 return;
670
671 if (!m_pContext->GetXFADocView())
672 return;
673
674 CXFA_FFWidgetHandler* pWidgetHandler =
675 m_pContext->GetXFADocView()->GetWidgetHandler();
676 if (!pWidgetHandler)
677 return;
678
679 std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator(
680 m_pContext->GetXFADocView()->CreateWidgetAccIterator());
681 if (!pWidgetAccIterator)
682 return;
683
684 CXFA_EventParam Param;
685 Param.m_eType = XFA_EVENT_PostSubmit;
686 CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext();
687 while (pWidgetAcc) {
688 pWidgetHandler->ProcessEvent(pWidgetAcc, &Param);
689 pWidgetAcc = pWidgetAccIterator->MoveToNext();
690 }
691 m_pContext->GetXFADocView()->UpdateDocView();
692 }
693
SubmitData(CXFA_FFDoc * hDoc,CXFA_Submit submit)694 bool CPDFXFA_DocEnvironment::SubmitData(CXFA_FFDoc* hDoc, CXFA_Submit submit) {
695 if (!NotifySubmit(true) || !m_pContext->GetXFADocView())
696 return false;
697
698 m_pContext->GetXFADocView()->UpdateDocView();
699 bool ret = SubmitDataInternal(hDoc, submit);
700 NotifySubmit(false);
701 return ret;
702 }
703
OpenLinkedFile(CXFA_FFDoc * hDoc,const CFX_WideString & wsLink)704 CFX_RetainPtr<IFX_SeekableReadStream> CPDFXFA_DocEnvironment::OpenLinkedFile(
705 CXFA_FFDoc* hDoc,
706 const CFX_WideString& wsLink) {
707 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
708 if (!pFormFillEnv)
709 return nullptr;
710
711 CFX_ByteString bs = wsLink.UTF16LE_Encode();
712 int len = bs.GetLength();
713 FPDF_FILEHANDLER* pFileHandler =
714 pFormFillEnv->OpenFile(0, (FPDF_WIDESTRING)bs.GetBuffer(len), "rb");
715 bs.ReleaseBuffer(len);
716 if (!pFileHandler)
717 return nullptr;
718
719 return MakeSeekableStream(pFileHandler);
720 }
721
ExportSubmitFile(FPDF_FILEHANDLER * pFileHandler,int fileType,FPDF_DWORD encodeType,FPDF_DWORD flag)722 bool CPDFXFA_DocEnvironment::ExportSubmitFile(FPDF_FILEHANDLER* pFileHandler,
723 int fileType,
724 FPDF_DWORD encodeType,
725 FPDF_DWORD flag) {
726 if (!m_pContext->GetXFADocView())
727 return false;
728
729 CFX_ByteString content;
730 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
731 if (!pFormFillEnv)
732 return false;
733
734 CFX_RetainPtr<IFX_SeekableStream> fileStream =
735 MakeSeekableStream(pFileHandler);
736
737 if (fileType == FXFA_SAVEAS_XML) {
738 const char kContent[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
739 fileStream->WriteBlock(kContent, 0, strlen(kContent));
740 m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Data, fileStream,
741 nullptr);
742 return true;
743 }
744
745 if (fileType != FXFA_SAVEAS_XDP)
746 return true;
747
748 if (!flag) {
749 flag = FXFA_CONFIG | FXFA_TEMPLATE | FXFA_LOCALESET | FXFA_DATASETS |
750 FXFA_XMPMETA | FXFA_XFDF | FXFA_FORM;
751 }
752 if (!m_pContext->GetPDFDoc()) {
753 fileStream->Flush();
754 return false;
755 }
756
757 CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot();
758 if (!pRoot) {
759 fileStream->Flush();
760 return false;
761 }
762
763 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
764 if (!pAcroForm) {
765 fileStream->Flush();
766 return false;
767 }
768
769 CPDF_Array* pArray = ToArray(pAcroForm->GetObjectFor("XFA"));
770 if (!pArray) {
771 fileStream->Flush();
772 return false;
773 }
774
775 int size = pArray->GetCount();
776 for (int i = 1; i < size; i += 2) {
777 CPDF_Object* pPDFObj = pArray->GetObjectAt(i);
778 CPDF_Object* pPrePDFObj = pArray->GetObjectAt(i - 1);
779 if (!pPrePDFObj->IsString())
780 continue;
781 if (!pPDFObj->IsReference())
782 continue;
783
784 CPDF_Object* pDirectObj = pPDFObj->GetDirect();
785 if (!pDirectObj->IsStream())
786 continue;
787 if (pPrePDFObj->GetString() == "config" && !(flag & FXFA_CONFIG))
788 continue;
789 if (pPrePDFObj->GetString() == "template" && !(flag & FXFA_TEMPLATE))
790 continue;
791 if (pPrePDFObj->GetString() == "localeSet" && !(flag & FXFA_LOCALESET))
792 continue;
793 if (pPrePDFObj->GetString() == "datasets" && !(flag & FXFA_DATASETS))
794 continue;
795 if (pPrePDFObj->GetString() == "xmpmeta" && !(flag & FXFA_XMPMETA))
796 continue;
797 if (pPrePDFObj->GetString() == "xfdf" && !(flag & FXFA_XFDF))
798 continue;
799 if (pPrePDFObj->GetString() == "form" && !(flag & FXFA_FORM))
800 continue;
801 if (pPrePDFObj->GetString() == "form") {
802 m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Form, fileStream,
803 nullptr);
804 } else if (pPrePDFObj->GetString() == "datasets") {
805 m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Datasets, fileStream,
806 nullptr);
807 } else {
808 // PDF,creator.
809 }
810 }
811 return true;
812 }
813
ToXFAContentFlags(CFX_WideString csSrcContent,FPDF_DWORD & flag)814 void CPDFXFA_DocEnvironment::ToXFAContentFlags(CFX_WideString csSrcContent,
815 FPDF_DWORD& flag) {
816 if (csSrcContent.Find(L" config ", 0) != -1)
817 flag |= FXFA_CONFIG;
818 if (csSrcContent.Find(L" template ", 0) != -1)
819 flag |= FXFA_TEMPLATE;
820 if (csSrcContent.Find(L" localeSet ", 0) != -1)
821 flag |= FXFA_LOCALESET;
822 if (csSrcContent.Find(L" datasets ", 0) != -1)
823 flag |= FXFA_DATASETS;
824 if (csSrcContent.Find(L" xmpmeta ", 0) != -1)
825 flag |= FXFA_XMPMETA;
826 if (csSrcContent.Find(L" xfdf ", 0) != -1)
827 flag |= FXFA_XFDF;
828 if (csSrcContent.Find(L" form ", 0) != -1)
829 flag |= FXFA_FORM;
830 if (flag == 0) {
831 flag = FXFA_CONFIG | FXFA_TEMPLATE | FXFA_LOCALESET | FXFA_DATASETS |
832 FXFA_XMPMETA | FXFA_XFDF | FXFA_FORM;
833 }
834 }
835
MailToInfo(CFX_WideString & csURL,CFX_WideString & csToAddress,CFX_WideString & csCCAddress,CFX_WideString & csBCCAddress,CFX_WideString & csSubject,CFX_WideString & csMsg)836 bool CPDFXFA_DocEnvironment::MailToInfo(CFX_WideString& csURL,
837 CFX_WideString& csToAddress,
838 CFX_WideString& csCCAddress,
839 CFX_WideString& csBCCAddress,
840 CFX_WideString& csSubject,
841 CFX_WideString& csMsg) {
842 CFX_WideString srcURL = csURL;
843 srcURL.TrimLeft();
844 if (srcURL.Left(7).CompareNoCase(L"mailto:") != 0)
845 return false;
846
847 int pos = srcURL.Find(L'?', 0);
848 CFX_WideString tmp;
849 if (pos == -1) {
850 pos = srcURL.Find(L'@', 0);
851 if (pos == -1)
852 return false;
853
854 tmp = srcURL.Right(csURL.GetLength() - 7);
855 } else {
856 tmp = srcURL.Left(pos);
857 tmp = tmp.Right(tmp.GetLength() - 7);
858 }
859 tmp.TrimLeft();
860 tmp.TrimRight();
861
862 csToAddress = tmp;
863
864 srcURL = srcURL.Right(srcURL.GetLength() - (pos + 1));
865 while (!srcURL.IsEmpty()) {
866 srcURL.TrimLeft();
867 srcURL.TrimRight();
868 pos = srcURL.Find(L'&', 0);
869
870 tmp = (pos == -1) ? srcURL : srcURL.Left(pos);
871 tmp.TrimLeft();
872 tmp.TrimRight();
873 if (tmp.GetLength() >= 3 && tmp.Left(3).CompareNoCase(L"cc=") == 0) {
874 tmp = tmp.Right(tmp.GetLength() - 3);
875 if (!csCCAddress.IsEmpty())
876 csCCAddress += L';';
877 csCCAddress += tmp;
878 } else if (tmp.GetLength() >= 4 &&
879 tmp.Left(4).CompareNoCase(L"bcc=") == 0) {
880 tmp = tmp.Right(tmp.GetLength() - 4);
881 if (!csBCCAddress.IsEmpty())
882 csBCCAddress += L';';
883 csBCCAddress += tmp;
884 } else if (tmp.GetLength() >= 8 &&
885 tmp.Left(8).CompareNoCase(L"subject=") == 0) {
886 tmp = tmp.Right(tmp.GetLength() - 8);
887 csSubject += tmp;
888 } else if (tmp.GetLength() >= 5 &&
889 tmp.Left(5).CompareNoCase(L"body=") == 0) {
890 tmp = tmp.Right(tmp.GetLength() - 5);
891 csMsg += tmp;
892 }
893 srcURL = (pos == -1) ? L"" : srcURL.Right(csURL.GetLength() - (pos + 1));
894 }
895 csToAddress.Replace(L",", L";");
896 csCCAddress.Replace(L",", L";");
897 csBCCAddress.Replace(L",", L";");
898 return true;
899 }
900
SubmitDataInternal(CXFA_FFDoc * hDoc,CXFA_Submit submit)901 bool CPDFXFA_DocEnvironment::SubmitDataInternal(CXFA_FFDoc* hDoc,
902 CXFA_Submit submit) {
903 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
904 if (!pFormFillEnv)
905 return false;
906
907 CFX_WideStringC csURLC;
908 submit.GetSubmitTarget(csURLC);
909 CFX_WideString csURL(csURLC);
910 if (csURL.IsEmpty()) {
911 CFX_WideString ws;
912 ws.FromLocal("Submit cancelled.");
913 CFX_ByteString bs = ws.UTF16LE_Encode();
914 int len = bs.GetLength();
915 pFormFillEnv->Alert((FPDF_WIDESTRING)bs.GetBuffer(len),
916 (FPDF_WIDESTRING)L"", 0, 4);
917 bs.ReleaseBuffer(len);
918 return false;
919 }
920
921 FPDF_FILEHANDLER* pFileHandler = nullptr;
922 int fileFlag = -1;
923 switch (submit.GetSubmitFormat()) {
924 case XFA_ATTRIBUTEENUM_Xdp: {
925 CFX_WideStringC csContentC;
926 submit.GetSubmitXDPContent(csContentC);
927 CFX_WideString csContent;
928 csContent = csContentC;
929 csContent.TrimLeft();
930 csContent.TrimRight();
931 CFX_WideString space;
932 space.FromLocal(" ");
933 csContent = space + csContent + space;
934 FPDF_DWORD flag = 0;
935 if (submit.IsSubmitEmbedPDF())
936 flag |= FXFA_PDF;
937
938 ToXFAContentFlags(csContent, flag);
939 pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XDP, nullptr, "wb");
940 fileFlag = FXFA_SAVEAS_XDP;
941 ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XDP, 0, flag);
942 break;
943 }
944 case XFA_ATTRIBUTEENUM_Xml:
945 pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XML, nullptr, "wb");
946 fileFlag = FXFA_SAVEAS_XML;
947 ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0, FXFA_XFA_ALL);
948 break;
949 case XFA_ATTRIBUTEENUM_Pdf:
950 break;
951 case XFA_ATTRIBUTEENUM_Urlencoded:
952 pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XML, nullptr, "wb");
953 fileFlag = FXFA_SAVEAS_XML;
954 ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0, FXFA_XFA_ALL);
955 break;
956 default:
957 return false;
958 }
959 if (!pFileHandler)
960 return false;
961 if (csURL.Left(7).CompareNoCase(L"mailto:") == 0) {
962 CFX_WideString csToAddress;
963 CFX_WideString csCCAddress;
964 CFX_WideString csBCCAddress;
965 CFX_WideString csSubject;
966 CFX_WideString csMsg;
967 if (!MailToInfo(csURL, csToAddress, csCCAddress, csBCCAddress, csSubject,
968 csMsg)) {
969 return false;
970 }
971 CFX_ByteString bsTo = CFX_WideString(csToAddress).UTF16LE_Encode();
972 CFX_ByteString bsCC = CFX_WideString(csCCAddress).UTF16LE_Encode();
973 CFX_ByteString bsBcc = CFX_WideString(csBCCAddress).UTF16LE_Encode();
974 CFX_ByteString bsSubject = CFX_WideString(csSubject).UTF16LE_Encode();
975 CFX_ByteString bsMsg = CFX_WideString(csMsg).UTF16LE_Encode();
976 FPDF_WIDESTRING pTo = (FPDF_WIDESTRING)bsTo.GetBuffer(bsTo.GetLength());
977 FPDF_WIDESTRING pCC = (FPDF_WIDESTRING)bsCC.GetBuffer(bsCC.GetLength());
978 FPDF_WIDESTRING pBcc = (FPDF_WIDESTRING)bsBcc.GetBuffer(bsBcc.GetLength());
979 FPDF_WIDESTRING pSubject =
980 (FPDF_WIDESTRING)bsSubject.GetBuffer(bsSubject.GetLength());
981 FPDF_WIDESTRING pMsg = (FPDF_WIDESTRING)bsMsg.GetBuffer(bsMsg.GetLength());
982 pFormFillEnv->EmailTo(pFileHandler, pTo, pSubject, pCC, pBcc, pMsg);
983 bsTo.ReleaseBuffer();
984 bsCC.ReleaseBuffer();
985 bsBcc.ReleaseBuffer();
986 bsSubject.ReleaseBuffer();
987 bsMsg.ReleaseBuffer();
988 } else {
989 // HTTP or FTP
990 CFX_WideString ws;
991 CFX_ByteString bs = csURL.UTF16LE_Encode();
992 int len = bs.GetLength();
993 pFormFillEnv->UploadTo(pFileHandler, fileFlag,
994 (FPDF_WIDESTRING)bs.GetBuffer(len));
995 bs.ReleaseBuffer(len);
996 }
997 return true;
998 }
999
SetGlobalProperty(CXFA_FFDoc * hDoc,const CFX_ByteStringC & szPropName,CFXJSE_Value * pValue)1000 bool CPDFXFA_DocEnvironment::SetGlobalProperty(
1001 CXFA_FFDoc* hDoc,
1002 const CFX_ByteStringC& szPropName,
1003 CFXJSE_Value* pValue) {
1004 if (hDoc != m_pContext->GetXFADoc())
1005 return false;
1006
1007 if (m_pContext->GetFormFillEnv() &&
1008 m_pContext->GetFormFillEnv()->GetJSRuntime()) {
1009 return m_pContext->GetFormFillEnv()->GetJSRuntime()->SetValueByName(
1010 szPropName, pValue);
1011 }
1012 return false;
1013 }
1014
GetGlobalProperty(CXFA_FFDoc * hDoc,const CFX_ByteStringC & szPropName,CFXJSE_Value * pValue)1015 bool CPDFXFA_DocEnvironment::GetGlobalProperty(
1016 CXFA_FFDoc* hDoc,
1017 const CFX_ByteStringC& szPropName,
1018 CFXJSE_Value* pValue) {
1019 if (hDoc != m_pContext->GetXFADoc())
1020 return false;
1021 if (!m_pContext->GetFormFillEnv() ||
1022 !m_pContext->GetFormFillEnv()->GetJSRuntime()) {
1023 return false;
1024 }
1025
1026 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
1027 if (!m_pJSEventContext)
1028 m_pJSEventContext = pFormFillEnv->GetJSRuntime()->NewEventContext();
1029
1030 return pFormFillEnv->GetJSRuntime()->GetValueByName(szPropName, pValue);
1031 }
1032