blob: 6040517d9396c1cb1c393d306134d14a89e90255 [file] [log] [blame]
dsinclaira440bb32016-09-14 07:01:54 -07001// 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
dsinclairbec76922016-09-29 16:52:30 -07007#include "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h"
dsinclaira440bb32016-09-14 07:01:54 -07008
tsepez0e606b52016-11-18 16:22:41 -08009#include <memory>
10
dsinclair488b7ad2016-10-04 11:55:50 -070011#include "core/fpdfapi/parser/cpdf_array.h"
12#include "core/fpdfapi/parser/cpdf_stream_acc.h"
13#include "core/fpdfapi/parser/cpdf_string.h"
Dan Sinclair0b950422017-09-21 15:49:49 -040014#include "core/fxcrt/retain_ptr.h"
dsinclair735606d2016-10-05 15:47:02 -070015#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
dsinclair114e46a2016-09-29 17:18:21 -070016#include "fpdfsdk/cpdfsdk_interform.h"
17#include "fpdfsdk/cpdfsdk_pageview.h"
dsinclair521b7502016-11-02 13:02:28 -070018#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
dsinclair4d29e782016-10-04 14:02:47 -070019#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000020#include "fxjs/ijs_runtime.h"
Dan Sinclair80c48782017-03-23 12:11:20 -040021#include "xfa/fxfa/cxfa_ffdocview.h"
22#include "xfa/fxfa/cxfa_ffwidget.h"
23#include "xfa/fxfa/cxfa_ffwidgethandler.h"
24#include "xfa/fxfa/cxfa_widgetacciterator.h"
dsinclaira440bb32016-09-14 07:01:54 -070025
26#define IDS_XFA_Validate_Input \
27 "At least one required field was empty. Please fill in the required " \
28 "fields\r\n(highlighted) before continuing."
29
30// submit
31#define FXFA_CONFIG 0x00000001
32#define FXFA_TEMPLATE 0x00000010
33#define FXFA_LOCALESET 0x00000100
34#define FXFA_DATASETS 0x00001000
35#define FXFA_XMPMETA 0x00010000
36#define FXFA_XFDF 0x00100000
37#define FXFA_FORM 0x01000000
38#define FXFA_PDF 0x10000000
39#define FXFA_XFA_ALL 0x01111111
40
dsinclair521b7502016-11-02 13:02:28 -070041CPDFXFA_DocEnvironment::CPDFXFA_DocEnvironment(CPDFXFA_Context* pContext)
Tom Sepez7dc9fe52017-05-18 09:51:57 -070042 : m_pContext(pContext) {
dsinclair521b7502016-11-02 13:02:28 -070043 ASSERT(m_pContext);
dsinclaira440bb32016-09-14 07:01:54 -070044}
45
Tom Sepez7dc9fe52017-05-18 09:51:57 -070046CPDFXFA_DocEnvironment::~CPDFXFA_DocEnvironment() {}
dsinclaira440bb32016-09-14 07:01:54 -070047
48void CPDFXFA_DocEnvironment::SetChangeMark(CXFA_FFDoc* hDoc) {
dsinclair521b7502016-11-02 13:02:28 -070049 if (hDoc == m_pContext->GetXFADoc() && m_pContext->GetFormFillEnv())
50 m_pContext->GetFormFillEnv()->SetChangeMark();
dsinclaira440bb32016-09-14 07:01:54 -070051}
52
53void CPDFXFA_DocEnvironment::InvalidateRect(CXFA_FFPageView* pPageView,
Dan Sinclaire3978d02017-03-23 09:12:10 -040054 const CFX_RectF& rt) {
dsinclair521b7502016-11-02 13:02:28 -070055 if (!m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
dsinclaira440bb32016-09-14 07:01:54 -070056 return;
57
Ryan Harrison854d71c2017-10-18 12:28:14 -040058 if (m_pContext->GetFormType() != FormType::kXFAFull)
dsinclaira440bb32016-09-14 07:01:54 -070059 return;
60
Dan Sinclair0b950422017-09-21 15:49:49 -040061 RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pPageView);
dsinclaira440bb32016-09-14 07:01:54 -070062 if (!pPage)
63 return;
64
dsinclair521b7502016-11-02 13:02:28 -070065 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -070066 if (!pFormFillEnv)
dsinclaira440bb32016-09-14 07:01:54 -070067 return;
68
Dan Sinclair6ba39e82017-07-26 17:19:40 -040069 pFormFillEnv->Invalidate(pPage.Get(), rt.ToFloatRect().ToFxRect());
dsinclaira440bb32016-09-14 07:01:54 -070070}
71
72void CPDFXFA_DocEnvironment::DisplayCaret(CXFA_FFWidget* hWidget,
tsepez4cf55152016-11-02 14:37:54 -070073 bool bVisible,
dsinclaira440bb32016-09-14 07:01:54 -070074 const CFX_RectF* pRtAnchor) {
dsinclair521b7502016-11-02 13:02:28 -070075 if (!hWidget || !pRtAnchor || !m_pContext->GetXFADoc() ||
76 !m_pContext->GetFormFillEnv() || !m_pContext->GetXFADocView())
dsinclaira440bb32016-09-14 07:01:54 -070077 return;
78
Ryan Harrison854d71c2017-10-18 12:28:14 -040079 if (m_pContext->GetFormType() != FormType::kXFAFull)
dsinclaira440bb32016-09-14 07:01:54 -070080 return;
81
82 CXFA_FFWidgetHandler* pWidgetHandler =
dsinclair521b7502016-11-02 13:02:28 -070083 m_pContext->GetXFADocView()->GetWidgetHandler();
dsinclaira440bb32016-09-14 07:01:54 -070084 if (!pWidgetHandler)
85 return;
86
87 CXFA_FFPageView* pPageView = hWidget->GetPageView();
88 if (!pPageView)
89 return;
90
Dan Sinclair0b950422017-09-21 15:49:49 -040091 RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pPageView);
dsinclaira440bb32016-09-14 07:01:54 -070092 if (!pPage)
93 return;
94
dsinclair521b7502016-11-02 13:02:28 -070095 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -070096 if (!pFormFillEnv)
dsinclaira440bb32016-09-14 07:01:54 -070097 return;
98
Dan Sinclair6ba39e82017-07-26 17:19:40 -040099 CFX_FloatRect rcCaret = pRtAnchor->ToFloatRect();
Lei Zhang671630e2017-05-19 19:25:16 -0700100 pFormFillEnv->DisplayCaret(pPage.Get(), bVisible, rcCaret.left, rcCaret.top,
101 rcCaret.right, rcCaret.bottom);
dsinclaira440bb32016-09-14 07:01:54 -0700102}
103
tsepez4cf55152016-11-02 14:37:54 -0700104bool CPDFXFA_DocEnvironment::GetPopupPos(CXFA_FFWidget* hWidget,
Dan Sinclair05df0752017-03-14 14:43:42 -0400105 float fMinPopup,
106 float fMaxPopup,
tsepez4cf55152016-11-02 14:37:54 -0700107 const CFX_RectF& rtAnchor,
108 CFX_RectF& rtPopup) {
dsinclaira440bb32016-09-14 07:01:54 -0700109 if (!hWidget)
tsepez4cf55152016-11-02 14:37:54 -0700110 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700111
112 CXFA_FFPageView* pXFAPageView = hWidget->GetPageView();
113 if (!pXFAPageView)
tsepez4cf55152016-11-02 14:37:54 -0700114 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700115
Dan Sinclair0b950422017-09-21 15:49:49 -0400116 RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pXFAPageView);
dsinclaira440bb32016-09-14 07:01:54 -0700117 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -0700118 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700119
dsinclair521b7502016-11-02 13:02:28 -0700120 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700121 if (!pFormFillEnv)
tsepez4cf55152016-11-02 14:37:54 -0700122 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700123
124 FS_RECTF pageViewRect = {0.0f, 0.0f, 0.0f, 0.0f};
Tom Sepez9792f162017-05-16 14:11:30 -0700125 pFormFillEnv->GetPageViewRect(pPage.Get(), pageViewRect);
dsinclaira440bb32016-09-14 07:01:54 -0700126
127 int t1;
128 int t2;
Dan Sinclair6ba39e82017-07-26 17:19:40 -0400129 CFX_FloatRect rcAnchor = rtAnchor.ToFloatRect();
Tom Sepez9792f162017-05-16 14:11:30 -0700130 int nRotate = hWidget->GetDataAcc()->GetRotate();
dsinclaira440bb32016-09-14 07:01:54 -0700131 switch (nRotate) {
132 case 90: {
133 t1 = (int)(pageViewRect.right - rcAnchor.right);
134 t2 = (int)(rcAnchor.left - pageViewRect.left);
135 if (rcAnchor.bottom < pageViewRect.bottom)
136 rtPopup.left += rcAnchor.bottom - pageViewRect.bottom;
137 break;
138 }
139 case 180: {
140 t2 = (int)(pageViewRect.top - rcAnchor.top);
141 t1 = (int)(rcAnchor.bottom - pageViewRect.bottom);
142 if (rcAnchor.left < pageViewRect.left)
143 rtPopup.left += rcAnchor.left - pageViewRect.left;
144 break;
145 }
146 case 270: {
147 t1 = (int)(rcAnchor.left - pageViewRect.left);
148 t2 = (int)(pageViewRect.right - rcAnchor.right);
149 if (rcAnchor.top > pageViewRect.top)
150 rtPopup.left -= rcAnchor.top - pageViewRect.top;
151 break;
152 }
153 case 0:
154 default: {
155 t1 = (int)(pageViewRect.top - rcAnchor.top);
156 t2 = (int)(rcAnchor.bottom - pageViewRect.bottom);
157 if (rcAnchor.right > pageViewRect.right)
158 rtPopup.left -= rcAnchor.right - pageViewRect.right;
159 break;
160 }
161 }
162
163 int t;
164 uint32_t dwPos;
165 if (t1 <= 0 && t2 <= 0)
tsepez4cf55152016-11-02 14:37:54 -0700166 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700167 if (t1 <= 0) {
168 t = t2;
169 dwPos = 1;
170 } else if (t2 <= 0) {
171 t = t1;
172 dwPos = 0;
173 } else if (t1 > t2) {
174 t = t1;
175 dwPos = 0;
176 } else {
177 t = t2;
178 dwPos = 1;
179 }
180
Dan Sinclair05df0752017-03-14 14:43:42 -0400181 float fPopupHeight;
dsinclaira440bb32016-09-14 07:01:54 -0700182 if (t < fMinPopup)
183 fPopupHeight = fMinPopup;
184 else if (t > fMaxPopup)
185 fPopupHeight = fMaxPopup;
186 else
Dan Sinclair05df0752017-03-14 14:43:42 -0400187 fPopupHeight = static_cast<float>(t);
dsinclaira440bb32016-09-14 07:01:54 -0700188
189 switch (nRotate) {
190 case 0:
191 case 180: {
192 if (dwPos == 0) {
193 rtPopup.top = rtAnchor.height;
194 rtPopup.height = fPopupHeight;
195 } else {
196 rtPopup.top = -fPopupHeight;
197 rtPopup.height = fPopupHeight;
198 }
199 break;
200 }
201 case 90:
202 case 270: {
203 if (dwPos == 0) {
204 rtPopup.top = rtAnchor.width;
205 rtPopup.height = fPopupHeight;
206 } else {
207 rtPopup.top = -fPopupHeight;
208 rtPopup.height = fPopupHeight;
209 }
210 break;
211 }
212 default:
213 break;
214 }
215
tsepez4cf55152016-11-02 14:37:54 -0700216 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700217}
218
tsepez4cf55152016-11-02 14:37:54 -0700219bool CPDFXFA_DocEnvironment::PopupMenu(CXFA_FFWidget* hWidget,
220 CFX_PointF ptPopup) {
dsinclaira440bb32016-09-14 07:01:54 -0700221 if (!hWidget)
tsepez4cf55152016-11-02 14:37:54 -0700222 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700223
224 CXFA_FFPageView* pXFAPageView = hWidget->GetPageView();
225 if (!pXFAPageView)
tsepez4cf55152016-11-02 14:37:54 -0700226 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700227
Dan Sinclair0b950422017-09-21 15:49:49 -0400228 RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pXFAPageView);
dsinclaira440bb32016-09-14 07:01:54 -0700229 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -0700230 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700231
dsinclair521b7502016-11-02 13:02:28 -0700232 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700233 if (!pFormFillEnv)
tsepez4cf55152016-11-02 14:37:54 -0700234 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700235
236 int menuFlag = 0;
237 if (hWidget->CanUndo())
238 menuFlag |= FXFA_MENU_UNDO;
239 if (hWidget->CanRedo())
240 menuFlag |= FXFA_MENU_REDO;
241 if (hWidget->CanPaste())
242 menuFlag |= FXFA_MENU_PASTE;
243 if (hWidget->CanCopy())
244 menuFlag |= FXFA_MENU_COPY;
245 if (hWidget->CanCut())
246 menuFlag |= FXFA_MENU_CUT;
247 if (hWidget->CanSelectAll())
248 menuFlag |= FXFA_MENU_SELECTALL;
249
Tom Sepez9792f162017-05-16 14:11:30 -0700250 return pFormFillEnv->PopupMenu(pPage.Get(), hWidget, menuFlag, ptPopup);
dsinclaira440bb32016-09-14 07:01:54 -0700251}
252
253void CPDFXFA_DocEnvironment::PageViewEvent(CXFA_FFPageView* pPageView,
254 uint32_t dwFlags) {
dsinclair521b7502016-11-02 13:02:28 -0700255 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700256 if (!pFormFillEnv)
dsinclaira440bb32016-09-14 07:01:54 -0700257 return;
258
dsinclair521b7502016-11-02 13:02:28 -0700259 if (m_pContext->GetLoadStatus() == FXFA_LOADSTATUS_LOADING ||
260 m_pContext->GetLoadStatus() == FXFA_LOADSTATUS_CLOSING ||
dsinclaira440bb32016-09-14 07:01:54 -0700261 XFA_PAGEVIEWEVENT_StopLayout != dwFlags)
262 return;
263
dsinclair521b7502016-11-02 13:02:28 -0700264 int nNewCount = m_pContext->GetPageCount();
265 if (nNewCount == m_pContext->GetOriginalPageCount())
dsinclaira440bb32016-09-14 07:01:54 -0700266 return;
267
dsinclair521b7502016-11-02 13:02:28 -0700268 CXFA_FFDocView* pXFADocView = m_pContext->GetXFADocView();
dsinclaira440bb32016-09-14 07:01:54 -0700269 if (!pXFADocView)
270 return;
271
dsinclair521b7502016-11-02 13:02:28 -0700272 for (int iPageIter = 0; iPageIter < m_pContext->GetOriginalPageCount();
dsinclaira440bb32016-09-14 07:01:54 -0700273 iPageIter++) {
Dan Sinclair0b950422017-09-21 15:49:49 -0400274 RetainPtr<CPDFXFA_Page> pPage = (*m_pContext->GetXFAPageList())[iPageIter];
dsinclaira440bb32016-09-14 07:01:54 -0700275 if (!pPage)
276 continue;
277
Tom Sepez9792f162017-05-16 14:11:30 -0700278 m_pContext->GetFormFillEnv()->RemovePageView(pPage.Get());
dsinclaira440bb32016-09-14 07:01:54 -0700279 pPage->SetXFAPageView(pXFADocView->GetPageView(iPageIter));
280 }
281
dsinclair521b7502016-11-02 13:02:28 -0700282 int flag = (nNewCount < m_pContext->GetOriginalPageCount())
dsinclaira440bb32016-09-14 07:01:54 -0700283 ? FXFA_PAGEVIEWEVENT_POSTREMOVED
284 : FXFA_PAGEVIEWEVENT_POSTADDED;
Dan Sinclair669a4182017-04-03 14:51:45 -0400285 int count = abs(nNewCount - m_pContext->GetOriginalPageCount());
dsinclair521b7502016-11-02 13:02:28 -0700286 m_pContext->SetOriginalPageCount(nNewCount);
dsinclair655fcca2016-10-11 13:53:37 -0700287 pFormFillEnv->PageEvent(count, flag);
dsinclaira440bb32016-09-14 07:01:54 -0700288}
289
290void CPDFXFA_DocEnvironment::WidgetPostAdd(CXFA_FFWidget* hWidget,
291 CXFA_WidgetAcc* pWidgetData) {
Ryan Harrison854d71c2017-10-18 12:28:14 -0400292 if (m_pContext->GetFormType() != FormType::kXFAFull || !hWidget)
dsinclaira440bb32016-09-14 07:01:54 -0700293 return;
294
295 CXFA_FFPageView* pPageView = hWidget->GetPageView();
296 if (!pPageView)
297 return;
298
Dan Sinclair0b950422017-09-21 15:49:49 -0400299 RetainPtr<CPDFXFA_Page> pXFAPage = m_pContext->GetXFAPage(pPageView);
dsinclaira440bb32016-09-14 07:01:54 -0700300 if (!pXFAPage)
301 return;
302
Tom Sepez9792f162017-05-16 14:11:30 -0700303 m_pContext->GetFormFillEnv()
304 ->GetPageView(pXFAPage.Get(), true)
305 ->AddAnnot(hWidget);
dsinclaira440bb32016-09-14 07:01:54 -0700306}
307
308void CPDFXFA_DocEnvironment::WidgetPreRemove(CXFA_FFWidget* hWidget,
309 CXFA_WidgetAcc* pWidgetData) {
Ryan Harrison854d71c2017-10-18 12:28:14 -0400310 if (m_pContext->GetFormType() != FormType::kXFAFull || !hWidget)
dsinclaira440bb32016-09-14 07:01:54 -0700311 return;
312
313 CXFA_FFPageView* pPageView = hWidget->GetPageView();
314 if (!pPageView)
315 return;
316
Dan Sinclair0b950422017-09-21 15:49:49 -0400317 RetainPtr<CPDFXFA_Page> pXFAPage = m_pContext->GetXFAPage(pPageView);
dsinclaira440bb32016-09-14 07:01:54 -0700318 if (!pXFAPage)
319 return;
320
321 CPDFSDK_PageView* pSdkPageView =
Tom Sepez9792f162017-05-16 14:11:30 -0700322 m_pContext->GetFormFillEnv()->GetPageView(pXFAPage.Get(), true);
323 CPDFSDK_Annot* pAnnot = pSdkPageView->GetAnnotByXFAWidget(hWidget);
324 if (pAnnot)
dsinclaira440bb32016-09-14 07:01:54 -0700325 pSdkPageView->DeleteAnnot(pAnnot);
326}
327
328int32_t CPDFXFA_DocEnvironment::CountPages(CXFA_FFDoc* hDoc) {
dsinclair521b7502016-11-02 13:02:28 -0700329 if (hDoc == m_pContext->GetXFADoc() && m_pContext->GetFormFillEnv())
330 return m_pContext->GetPageCount();
dsinclaira440bb32016-09-14 07:01:54 -0700331 return 0;
332}
333
334int32_t CPDFXFA_DocEnvironment::GetCurrentPage(CXFA_FFDoc* hDoc) {
dsinclair521b7502016-11-02 13:02:28 -0700335 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
dsinclaira440bb32016-09-14 07:01:54 -0700336 return -1;
Ryan Harrison854d71c2017-10-18 12:28:14 -0400337 if (m_pContext->GetFormType() != FormType::kXFAFull)
dsinclaira440bb32016-09-14 07:01:54 -0700338 return -1;
339
dsinclair521b7502016-11-02 13:02:28 -0700340 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700341 if (!pFormFillEnv)
dsinclaira440bb32016-09-14 07:01:54 -0700342 return -1;
343
Lei Zhang671630e2017-05-19 19:25:16 -0700344 return pFormFillEnv->GetCurrentPageIndex(m_pContext.Get());
dsinclaira440bb32016-09-14 07:01:54 -0700345}
346
347void CPDFXFA_DocEnvironment::SetCurrentPage(CXFA_FFDoc* hDoc,
348 int32_t iCurPage) {
dsinclair521b7502016-11-02 13:02:28 -0700349 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv() ||
Ryan Harrison854d71c2017-10-18 12:28:14 -0400350 m_pContext->GetFormType() != FormType::kXFAFull || iCurPage < 0 ||
dsinclair521b7502016-11-02 13:02:28 -0700351 iCurPage >= m_pContext->GetFormFillEnv()->GetPageCount()) {
dsinclaira440bb32016-09-14 07:01:54 -0700352 return;
353 }
354
dsinclair521b7502016-11-02 13:02:28 -0700355 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700356 if (!pFormFillEnv)
dsinclaira440bb32016-09-14 07:01:54 -0700357 return;
Lei Zhang671630e2017-05-19 19:25:16 -0700358 pFormFillEnv->SetCurrentPage(m_pContext.Get(), iCurPage);
dsinclaira440bb32016-09-14 07:01:54 -0700359}
360
tsepez4cf55152016-11-02 14:37:54 -0700361bool CPDFXFA_DocEnvironment::IsCalculationsEnabled(CXFA_FFDoc* hDoc) {
dsinclair521b7502016-11-02 13:02:28 -0700362 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
tsepez4cf55152016-11-02 14:37:54 -0700363 return false;
dsinclair521b7502016-11-02 13:02:28 -0700364 if (m_pContext->GetFormFillEnv()->GetInterForm()) {
365 return m_pContext->GetFormFillEnv()
dsinclair655fcca2016-10-11 13:53:37 -0700366 ->GetInterForm()
367 ->IsXfaCalculateEnabled();
dsinclair7cbe68e2016-10-12 11:56:23 -0700368 }
tsepez4cf55152016-11-02 14:37:54 -0700369 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700370}
371
372void CPDFXFA_DocEnvironment::SetCalculationsEnabled(CXFA_FFDoc* hDoc,
tsepez4cf55152016-11-02 14:37:54 -0700373 bool bEnabled) {
dsinclair521b7502016-11-02 13:02:28 -0700374 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
dsinclaira440bb32016-09-14 07:01:54 -0700375 return;
dsinclair521b7502016-11-02 13:02:28 -0700376 if (m_pContext->GetFormFillEnv()->GetInterForm()) {
377 m_pContext->GetFormFillEnv()->GetInterForm()->XfaEnableCalculate(bEnabled);
dsinclair7cbe68e2016-10-12 11:56:23 -0700378 }
dsinclaira440bb32016-09-14 07:01:54 -0700379}
380
Ryan Harrison275e2602017-09-18 14:23:18 -0400381void CPDFXFA_DocEnvironment::GetTitle(CXFA_FFDoc* hDoc, WideString& wsTitle) {
dsinclair521b7502016-11-02 13:02:28 -0700382 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetPDFDoc())
dsinclaira440bb32016-09-14 07:01:54 -0700383 return;
384
Lei Zhang01581062017-08-30 14:19:26 -0700385 const CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo();
dsinclaira440bb32016-09-14 07:01:54 -0700386 if (!pInfoDict)
387 return;
388
Ryan Harrison275e2602017-09-18 14:23:18 -0400389 ByteString csTitle = pInfoDict->GetStringFor("Title");
dsinclaira440bb32016-09-14 07:01:54 -0700390 wsTitle = wsTitle.FromLocal(csTitle.GetBuffer(csTitle.GetLength()));
391 csTitle.ReleaseBuffer(csTitle.GetLength());
392}
393
394void CPDFXFA_DocEnvironment::SetTitle(CXFA_FFDoc* hDoc,
Ryan Harrison275e2602017-09-18 14:23:18 -0400395 const WideString& wsTitle) {
dsinclair521b7502016-11-02 13:02:28 -0700396 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetPDFDoc())
dsinclaira440bb32016-09-14 07:01:54 -0700397 return;
398
Lei Zhang01581062017-08-30 14:19:26 -0700399 CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo();
400 if (pInfoDict)
tsepez0e606b52016-11-18 16:22:41 -0800401 pInfoDict->SetNewFor<CPDF_String>("Title", wsTitle);
dsinclaira440bb32016-09-14 07:01:54 -0700402}
403
404void CPDFXFA_DocEnvironment::ExportData(CXFA_FFDoc* hDoc,
Ryan Harrison275e2602017-09-18 14:23:18 -0400405 const WideString& wsFilePath,
tsepez4cf55152016-11-02 14:37:54 -0700406 bool bXDP) {
dsinclair521b7502016-11-02 13:02:28 -0700407 if (hDoc != m_pContext->GetXFADoc())
dsinclaira440bb32016-09-14 07:01:54 -0700408 return;
409
Ryan Harrison854d71c2017-10-18 12:28:14 -0400410 if (!m_pContext->ContainsXFAForm())
dsinclaira440bb32016-09-14 07:01:54 -0700411 return;
412
dsinclair521b7502016-11-02 13:02:28 -0700413 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700414 if (!pFormFillEnv)
dsinclaira440bb32016-09-14 07:01:54 -0700415 return;
416
417 int fileType = bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML;
Ryan Harrison275e2602017-09-18 14:23:18 -0400418 ByteString bs = wsFilePath.UTF16LE_Encode();
dsinclaira440bb32016-09-14 07:01:54 -0700419 if (wsFilePath.IsEmpty()) {
dsinclair655fcca2016-10-11 13:53:37 -0700420 if (!pFormFillEnv->GetFormFillInfo() ||
dsinclair7cbe68e2016-10-12 11:56:23 -0700421 !pFormFillEnv->GetFormFillInfo()->m_pJsPlatform) {
dsinclaira440bb32016-09-14 07:01:54 -0700422 return;
dsinclair7cbe68e2016-10-12 11:56:23 -0700423 }
dsinclaira440bb32016-09-14 07:01:54 -0700424
Ryan Harrison275e2602017-09-18 14:23:18 -0400425 WideString filepath = pFormFillEnv->JS_fieldBrowse();
dsinclaira440bb32016-09-14 07:01:54 -0700426 bs = filepath.UTF16LE_Encode();
427 }
428 int len = bs.GetLength();
429 FPDF_FILEHANDLER* pFileHandler =
dsinclair655fcca2016-10-11 13:53:37 -0700430 pFormFillEnv->OpenFile(bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML,
431 (FPDF_WIDESTRING)bs.GetBuffer(len), "wb");
dsinclaira440bb32016-09-14 07:01:54 -0700432 bs.ReleaseBuffer(len);
433 if (!pFileHandler)
434 return;
435
Dan Sinclair0b950422017-09-21 15:49:49 -0400436 RetainPtr<IFX_SeekableStream> fileWrite = MakeSeekableStream(pFileHandler);
Ryan Harrison275e2602017-09-18 14:23:18 -0400437 ByteString content;
dsinclaira440bb32016-09-14 07:01:54 -0700438 if (fileType == FXFA_SAVEAS_XML) {
439 content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
tsepezfa89a202016-12-02 09:48:30 -0800440 fileWrite->WriteBlock(content.c_str(), fileWrite->GetSize(),
441 content.GetLength());
tsepez833619b2016-12-07 09:21:17 -0800442 m_pContext->GetXFADocView()->GetDoc()->SavePackage(XFA_HASHCODE_Data,
443 fileWrite, nullptr);
dsinclaira440bb32016-09-14 07:01:54 -0700444 } else if (fileType == FXFA_SAVEAS_XDP) {
dsinclair521b7502016-11-02 13:02:28 -0700445 if (!m_pContext->GetPDFDoc())
dsinclaira440bb32016-09-14 07:01:54 -0700446 return;
447
Lei Zhang01581062017-08-30 14:19:26 -0700448 const CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot();
dsinclaira440bb32016-09-14 07:01:54 -0700449 if (!pRoot)
450 return;
451
dsinclair38fd8442016-09-15 10:15:32 -0700452 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
dsinclaira440bb32016-09-14 07:01:54 -0700453 if (!pAcroForm)
454 return;
455
dsinclair38fd8442016-09-15 10:15:32 -0700456 CPDF_Array* pArray = ToArray(pAcroForm->GetObjectFor("XFA"));
dsinclaira440bb32016-09-14 07:01:54 -0700457 if (!pArray)
458 return;
459
460 int size = pArray->GetCount();
461 for (int i = 1; i < size; i += 2) {
462 CPDF_Object* pPDFObj = pArray->GetObjectAt(i);
463 CPDF_Object* pPrePDFObj = pArray->GetObjectAt(i - 1);
464 if (!pPrePDFObj->IsString())
465 continue;
466 if (!pPDFObj->IsReference())
467 continue;
468
469 CPDF_Stream* pStream = ToStream(pPDFObj->GetDirect());
470 if (!pStream)
471 continue;
472 if (pPrePDFObj->GetString() == "form") {
tsepez833619b2016-12-07 09:21:17 -0800473 m_pContext->GetXFADocView()->GetDoc()->SavePackage(XFA_HASHCODE_Form,
474 fileWrite, nullptr);
dsinclaira440bb32016-09-14 07:01:54 -0700475 continue;
476 }
477 if (pPrePDFObj->GetString() == "datasets") {
dsinclair521b7502016-11-02 13:02:28 -0700478 m_pContext->GetXFADocView()->GetDoc()->SavePackage(
tsepez833619b2016-12-07 09:21:17 -0800479 XFA_HASHCODE_Datasets, fileWrite, nullptr);
dsinclaira440bb32016-09-14 07:01:54 -0700480 continue;
481 }
482 if (i == size - 1) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400483 WideString wPath = WideString::FromUTF16LE(
dsinclaira440bb32016-09-14 07:01:54 -0700484 reinterpret_cast<const unsigned short*>(bs.c_str()),
485 bs.GetLength() / sizeof(unsigned short));
Ryan Harrison275e2602017-09-18 14:23:18 -0400486 ByteString bPath = wPath.UTF8Encode();
dsinclaira440bb32016-09-14 07:01:54 -0700487 const char* szFormat =
488 "\n<pdf href=\"%s\" xmlns=\"http://ns.adobe.com/xdp/pdf/\"/>";
489 content.Format(szFormat, bPath.c_str());
tsepezfa89a202016-12-02 09:48:30 -0800490 fileWrite->WriteBlock(content.c_str(), fileWrite->GetSize(),
491 content.GetLength());
dsinclaira440bb32016-09-14 07:01:54 -0700492 }
Tom Sepezafd0d1f2017-04-04 14:37:18 -0700493 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
494 pAcc->LoadAllData();
tsepezfa89a202016-12-02 09:48:30 -0800495 fileWrite->WriteBlock(pAcc->GetData(), fileWrite->GetSize(),
496 pAcc->GetSize());
dsinclaira440bb32016-09-14 07:01:54 -0700497 }
498 }
tsepezfa89a202016-12-02 09:48:30 -0800499 fileWrite->Flush();
dsinclaira440bb32016-09-14 07:01:54 -0700500}
501
502void CPDFXFA_DocEnvironment::GotoURL(CXFA_FFDoc* hDoc,
Ryan Harrison275e2602017-09-18 14:23:18 -0400503 const WideString& bsURL) {
dsinclair521b7502016-11-02 13:02:28 -0700504 if (hDoc != m_pContext->GetXFADoc())
dsinclaira440bb32016-09-14 07:01:54 -0700505 return;
506
Ryan Harrison854d71c2017-10-18 12:28:14 -0400507 if (m_pContext->GetFormType() != FormType::kXFAFull)
dsinclaira440bb32016-09-14 07:01:54 -0700508 return;
509
dsinclair521b7502016-11-02 13:02:28 -0700510 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700511 if (!pFormFillEnv)
dsinclaira440bb32016-09-14 07:01:54 -0700512 return;
513
Ryan Harrison275e2602017-09-18 14:23:18 -0400514 WideStringView str(bsURL.c_str());
Lei Zhang671630e2017-05-19 19:25:16 -0700515 pFormFillEnv->GotoURL(m_pContext.Get(), str);
dsinclaira440bb32016-09-14 07:01:54 -0700516}
517
tsepez4cf55152016-11-02 14:37:54 -0700518bool CPDFXFA_DocEnvironment::IsValidationsEnabled(CXFA_FFDoc* hDoc) {
dsinclair521b7502016-11-02 13:02:28 -0700519 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
tsepez4cf55152016-11-02 14:37:54 -0700520 return false;
dsinclair521b7502016-11-02 13:02:28 -0700521 if (m_pContext->GetFormFillEnv()->GetInterForm()) {
522 return m_pContext->GetFormFillEnv()
dsinclair655fcca2016-10-11 13:53:37 -0700523 ->GetInterForm()
524 ->IsXfaValidationsEnabled();
dsinclair7cbe68e2016-10-12 11:56:23 -0700525 }
tsepez4cf55152016-11-02 14:37:54 -0700526 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700527}
528
529void CPDFXFA_DocEnvironment::SetValidationsEnabled(CXFA_FFDoc* hDoc,
tsepez4cf55152016-11-02 14:37:54 -0700530 bool bEnabled) {
dsinclair521b7502016-11-02 13:02:28 -0700531 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
dsinclaira440bb32016-09-14 07:01:54 -0700532 return;
dsinclair521b7502016-11-02 13:02:28 -0700533 if (m_pContext->GetFormFillEnv()->GetInterForm()) {
534 m_pContext->GetFormFillEnv()->GetInterForm()->XfaSetValidationsEnabled(
535 bEnabled);
dsinclair7cbe68e2016-10-12 11:56:23 -0700536 }
dsinclaira440bb32016-09-14 07:01:54 -0700537}
538
539void CPDFXFA_DocEnvironment::SetFocusWidget(CXFA_FFDoc* hDoc,
540 CXFA_FFWidget* hWidget) {
dsinclair521b7502016-11-02 13:02:28 -0700541 if (hDoc != m_pContext->GetXFADoc())
dsinclaira440bb32016-09-14 07:01:54 -0700542 return;
543
544 if (!hWidget) {
tsepezf8074ce2016-09-27 14:29:57 -0700545 CPDFSDK_Annot::ObservedPtr pNull;
dsinclair521b7502016-11-02 13:02:28 -0700546 m_pContext->GetFormFillEnv()->SetFocusAnnot(&pNull);
dsinclaira440bb32016-09-14 07:01:54 -0700547 return;
548 }
549
dsinclair521b7502016-11-02 13:02:28 -0700550 int pageViewCount = m_pContext->GetFormFillEnv()->GetPageViewCount();
dsinclaira440bb32016-09-14 07:01:54 -0700551 for (int i = 0; i < pageViewCount; i++) {
dsinclair521b7502016-11-02 13:02:28 -0700552 CPDFSDK_PageView* pPageView = m_pContext->GetFormFillEnv()->GetPageView(i);
dsinclaira440bb32016-09-14 07:01:54 -0700553 if (!pPageView)
554 continue;
555
tsepezf8074ce2016-09-27 14:29:57 -0700556 CPDFSDK_Annot::ObservedPtr pAnnot(pPageView->GetAnnotByXFAWidget(hWidget));
dsinclaira440bb32016-09-14 07:01:54 -0700557 if (pAnnot) {
dsinclair521b7502016-11-02 13:02:28 -0700558 m_pContext->GetFormFillEnv()->SetFocusAnnot(&pAnnot);
dsinclaira440bb32016-09-14 07:01:54 -0700559 break;
560 }
561 }
562}
563
564void CPDFXFA_DocEnvironment::Print(CXFA_FFDoc* hDoc,
565 int32_t nStartPage,
566 int32_t nEndPage,
567 uint32_t dwOptions) {
dsinclair521b7502016-11-02 13:02:28 -0700568 if (hDoc != m_pContext->GetXFADoc())
dsinclaira440bb32016-09-14 07:01:54 -0700569 return;
570
dsinclair521b7502016-11-02 13:02:28 -0700571 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700572 if (!pFormFillEnv || !pFormFillEnv->GetFormFillInfo() ||
573 !pFormFillEnv->GetFormFillInfo()->m_pJsPlatform ||
574 !pFormFillEnv->GetFormFillInfo()->m_pJsPlatform->Doc_print) {
dsinclaira440bb32016-09-14 07:01:54 -0700575 return;
576 }
577
dsinclair655fcca2016-10-11 13:53:37 -0700578 pFormFillEnv->GetFormFillInfo()->m_pJsPlatform->Doc_print(
579 pFormFillEnv->GetFormFillInfo()->m_pJsPlatform,
dsinclaira440bb32016-09-14 07:01:54 -0700580 dwOptions & XFA_PRINTOPT_ShowDialog, nStartPage, nEndPage,
581 dwOptions & XFA_PRINTOPT_CanCancel, dwOptions & XFA_PRINTOPT_ShrinkPage,
582 dwOptions & XFA_PRINTOPT_AsImage, dwOptions & XFA_PRINTOPT_ReverseOrder,
583 dwOptions & XFA_PRINTOPT_PrintAnnot);
584}
585
586FX_ARGB CPDFXFA_DocEnvironment::GetHighlightColor(CXFA_FFDoc* hDoc) {
dsinclair521b7502016-11-02 13:02:28 -0700587 if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
dsinclaira440bb32016-09-14 07:01:54 -0700588 return 0;
589
dsinclair521b7502016-11-02 13:02:28 -0700590 CPDFSDK_InterForm* pInterForm = m_pContext->GetFormFillEnv()->GetInterForm();
dsinclaira440bb32016-09-14 07:01:54 -0700591 if (!pInterForm)
592 return 0;
593
594 return ArgbEncode(pInterForm->GetHighlightAlpha(),
595 pInterForm->GetHighlightColor(FPDF_FORMFIELD_XFA));
596}
597
tsepez4cf55152016-11-02 14:37:54 -0700598bool CPDFXFA_DocEnvironment::NotifySubmit(bool bPrevOrPost) {
dsinclaira440bb32016-09-14 07:01:54 -0700599 if (bPrevOrPost)
600 return OnBeforeNotifySubmit();
601
602 OnAfterNotifySubmit();
tsepez4cf55152016-11-02 14:37:54 -0700603 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700604}
605
tsepez4cf55152016-11-02 14:37:54 -0700606bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() {
Ryan Harrison854d71c2017-10-18 12:28:14 -0400607 if (!m_pContext->ContainsXFAForm())
tsepez4cf55152016-11-02 14:37:54 -0700608 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700609
dsinclair521b7502016-11-02 13:02:28 -0700610 if (!m_pContext->GetXFADocView())
tsepez4cf55152016-11-02 14:37:54 -0700611 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700612
613 CXFA_FFWidgetHandler* pWidgetHandler =
dsinclair521b7502016-11-02 13:02:28 -0700614 m_pContext->GetXFADocView()->GetWidgetHandler();
dsinclaira440bb32016-09-14 07:01:54 -0700615 if (!pWidgetHandler)
tsepez4cf55152016-11-02 14:37:54 -0700616 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700617
Tom Sepez40badde2017-05-01 13:21:39 -0700618 std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator =
619 m_pContext->GetXFADocView()->CreateWidgetAccIterator();
dsinclaira440bb32016-09-14 07:01:54 -0700620 if (pWidgetAccIterator) {
621 CXFA_EventParam Param;
622 Param.m_eType = XFA_EVENT_PreSubmit;
623 while (CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext())
624 pWidgetHandler->ProcessEvent(pWidgetAcc, &Param);
625 }
626
Tom Sepez40badde2017-05-01 13:21:39 -0700627 pWidgetAccIterator = m_pContext->GetXFADocView()->CreateWidgetAccIterator();
dsinclaira440bb32016-09-14 07:01:54 -0700628 if (!pWidgetAccIterator)
tsepez4cf55152016-11-02 14:37:54 -0700629 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700630
631 CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext();
632 pWidgetAcc = pWidgetAccIterator->MoveToNext();
633 while (pWidgetAcc) {
634 int fRet = pWidgetAcc->ProcessValidate(-1);
635 if (fRet == XFA_EVENTERROR_Error) {
dsinclair521b7502016-11-02 13:02:28 -0700636 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700637 if (!pFormFillEnv)
tsepez4cf55152016-11-02 14:37:54 -0700638 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700639
Ryan Harrison275e2602017-09-18 14:23:18 -0400640 WideString ws;
dsinclaira440bb32016-09-14 07:01:54 -0700641 ws.FromLocal(IDS_XFA_Validate_Input);
Ryan Harrison275e2602017-09-18 14:23:18 -0400642 ByteString bs = ws.UTF16LE_Encode();
dsinclaira440bb32016-09-14 07:01:54 -0700643 int len = bs.GetLength();
dsinclair655fcca2016-10-11 13:53:37 -0700644 pFormFillEnv->Alert((FPDF_WIDESTRING)bs.GetBuffer(len),
645 (FPDF_WIDESTRING)L"", 0, 1);
dsinclaira440bb32016-09-14 07:01:54 -0700646 bs.ReleaseBuffer(len);
tsepez4cf55152016-11-02 14:37:54 -0700647 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700648 }
649 pWidgetAcc = pWidgetAccIterator->MoveToNext();
650 }
dsinclair521b7502016-11-02 13:02:28 -0700651 m_pContext->GetXFADocView()->UpdateDocView();
dsinclaira440bb32016-09-14 07:01:54 -0700652
tsepez4cf55152016-11-02 14:37:54 -0700653 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700654}
655
656void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() {
Ryan Harrison854d71c2017-10-18 12:28:14 -0400657 if (!m_pContext->ContainsXFAForm())
dsinclaira440bb32016-09-14 07:01:54 -0700658 return;
659
dsinclair521b7502016-11-02 13:02:28 -0700660 if (!m_pContext->GetXFADocView())
dsinclaira440bb32016-09-14 07:01:54 -0700661 return;
662
663 CXFA_FFWidgetHandler* pWidgetHandler =
dsinclair521b7502016-11-02 13:02:28 -0700664 m_pContext->GetXFADocView()->GetWidgetHandler();
dsinclaira440bb32016-09-14 07:01:54 -0700665 if (!pWidgetHandler)
666 return;
667
Tom Sepez40badde2017-05-01 13:21:39 -0700668 std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator =
669 m_pContext->GetXFADocView()->CreateWidgetAccIterator();
dsinclaira440bb32016-09-14 07:01:54 -0700670 if (!pWidgetAccIterator)
671 return;
672
673 CXFA_EventParam Param;
674 Param.m_eType = XFA_EVENT_PostSubmit;
675 CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext();
676 while (pWidgetAcc) {
677 pWidgetHandler->ProcessEvent(pWidgetAcc, &Param);
678 pWidgetAcc = pWidgetAccIterator->MoveToNext();
679 }
dsinclair521b7502016-11-02 13:02:28 -0700680 m_pContext->GetXFADocView()->UpdateDocView();
dsinclaira440bb32016-09-14 07:01:54 -0700681}
682
tsepez4cf55152016-11-02 14:37:54 -0700683bool CPDFXFA_DocEnvironment::SubmitData(CXFA_FFDoc* hDoc, CXFA_Submit submit) {
684 if (!NotifySubmit(true) || !m_pContext->GetXFADocView())
685 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700686
dsinclair521b7502016-11-02 13:02:28 -0700687 m_pContext->GetXFADocView()->UpdateDocView();
tsepez4cf55152016-11-02 14:37:54 -0700688 bool ret = SubmitDataInternal(hDoc, submit);
689 NotifySubmit(false);
dsinclaira440bb32016-09-14 07:01:54 -0700690 return ret;
691}
692
Dan Sinclair0b950422017-09-21 15:49:49 -0400693RetainPtr<IFX_SeekableReadStream> CPDFXFA_DocEnvironment::OpenLinkedFile(
dsinclaira440bb32016-09-14 07:01:54 -0700694 CXFA_FFDoc* hDoc,
Ryan Harrison275e2602017-09-18 14:23:18 -0400695 const WideString& wsLink) {
dsinclair521b7502016-11-02 13:02:28 -0700696 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700697 if (!pFormFillEnv)
tsepez04c10092016-10-25 15:16:40 -0700698 return nullptr;
dsinclaira440bb32016-09-14 07:01:54 -0700699
Ryan Harrison275e2602017-09-18 14:23:18 -0400700 ByteString bs = wsLink.UTF16LE_Encode();
dsinclaira440bb32016-09-14 07:01:54 -0700701 int len = bs.GetLength();
702 FPDF_FILEHANDLER* pFileHandler =
dsinclair655fcca2016-10-11 13:53:37 -0700703 pFormFillEnv->OpenFile(0, (FPDF_WIDESTRING)bs.GetBuffer(len), "rb");
dsinclaira440bb32016-09-14 07:01:54 -0700704 bs.ReleaseBuffer(len);
dsinclaira440bb32016-09-14 07:01:54 -0700705 if (!pFileHandler)
706 return nullptr;
tsepez04c10092016-10-25 15:16:40 -0700707
tsepezfa89a202016-12-02 09:48:30 -0800708 return MakeSeekableStream(pFileHandler);
dsinclaira440bb32016-09-14 07:01:54 -0700709}
710
tsepez4cf55152016-11-02 14:37:54 -0700711bool CPDFXFA_DocEnvironment::ExportSubmitFile(FPDF_FILEHANDLER* pFileHandler,
712 int fileType,
713 FPDF_DWORD encodeType,
714 FPDF_DWORD flag) {
dsinclair521b7502016-11-02 13:02:28 -0700715 if (!m_pContext->GetXFADocView())
tsepez4cf55152016-11-02 14:37:54 -0700716 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700717
Ryan Harrison275e2602017-09-18 14:23:18 -0400718 ByteString content;
dsinclair521b7502016-11-02 13:02:28 -0700719 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700720 if (!pFormFillEnv)
tsepez4cf55152016-11-02 14:37:54 -0700721 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700722
Dan Sinclair0b950422017-09-21 15:49:49 -0400723 RetainPtr<IFX_SeekableStream> fileStream = MakeSeekableStream(pFileHandler);
tsepezfa89a202016-12-02 09:48:30 -0800724
dsinclaira440bb32016-09-14 07:01:54 -0700725 if (fileType == FXFA_SAVEAS_XML) {
726 const char kContent[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
tsepezfa89a202016-12-02 09:48:30 -0800727 fileStream->WriteBlock(kContent, 0, strlen(kContent));
tsepez833619b2016-12-07 09:21:17 -0800728 m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Data, fileStream,
dsinclair521b7502016-11-02 13:02:28 -0700729 nullptr);
tsepez4cf55152016-11-02 14:37:54 -0700730 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700731 }
732
733 if (fileType != FXFA_SAVEAS_XDP)
tsepez4cf55152016-11-02 14:37:54 -0700734 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700735
736 if (!flag) {
737 flag = FXFA_CONFIG | FXFA_TEMPLATE | FXFA_LOCALESET | FXFA_DATASETS |
738 FXFA_XMPMETA | FXFA_XFDF | FXFA_FORM;
739 }
dsinclair521b7502016-11-02 13:02:28 -0700740 if (!m_pContext->GetPDFDoc()) {
tsepezfa89a202016-12-02 09:48:30 -0800741 fileStream->Flush();
tsepez4cf55152016-11-02 14:37:54 -0700742 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700743 }
744
Lei Zhang01581062017-08-30 14:19:26 -0700745 const CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot();
dsinclaira440bb32016-09-14 07:01:54 -0700746 if (!pRoot) {
tsepezfa89a202016-12-02 09:48:30 -0800747 fileStream->Flush();
tsepez4cf55152016-11-02 14:37:54 -0700748 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700749 }
750
dsinclair38fd8442016-09-15 10:15:32 -0700751 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
dsinclaira440bb32016-09-14 07:01:54 -0700752 if (!pAcroForm) {
tsepezfa89a202016-12-02 09:48:30 -0800753 fileStream->Flush();
tsepez4cf55152016-11-02 14:37:54 -0700754 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700755 }
756
dsinclair38fd8442016-09-15 10:15:32 -0700757 CPDF_Array* pArray = ToArray(pAcroForm->GetObjectFor("XFA"));
dsinclaira440bb32016-09-14 07:01:54 -0700758 if (!pArray) {
tsepezfa89a202016-12-02 09:48:30 -0800759 fileStream->Flush();
tsepez4cf55152016-11-02 14:37:54 -0700760 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700761 }
762
763 int size = pArray->GetCount();
764 for (int i = 1; i < size; i += 2) {
765 CPDF_Object* pPDFObj = pArray->GetObjectAt(i);
766 CPDF_Object* pPrePDFObj = pArray->GetObjectAt(i - 1);
767 if (!pPrePDFObj->IsString())
768 continue;
769 if (!pPDFObj->IsReference())
770 continue;
771
772 CPDF_Object* pDirectObj = pPDFObj->GetDirect();
773 if (!pDirectObj->IsStream())
774 continue;
775 if (pPrePDFObj->GetString() == "config" && !(flag & FXFA_CONFIG))
776 continue;
777 if (pPrePDFObj->GetString() == "template" && !(flag & FXFA_TEMPLATE))
778 continue;
779 if (pPrePDFObj->GetString() == "localeSet" && !(flag & FXFA_LOCALESET))
780 continue;
781 if (pPrePDFObj->GetString() == "datasets" && !(flag & FXFA_DATASETS))
782 continue;
783 if (pPrePDFObj->GetString() == "xmpmeta" && !(flag & FXFA_XMPMETA))
784 continue;
785 if (pPrePDFObj->GetString() == "xfdf" && !(flag & FXFA_XFDF))
786 continue;
787 if (pPrePDFObj->GetString() == "form" && !(flag & FXFA_FORM))
788 continue;
789 if (pPrePDFObj->GetString() == "form") {
tsepez833619b2016-12-07 09:21:17 -0800790 m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Form, fileStream,
dsinclair521b7502016-11-02 13:02:28 -0700791 nullptr);
dsinclaira440bb32016-09-14 07:01:54 -0700792 } else if (pPrePDFObj->GetString() == "datasets") {
tsepez833619b2016-12-07 09:21:17 -0800793 m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Datasets, fileStream,
794 nullptr);
dsinclaira440bb32016-09-14 07:01:54 -0700795 } else {
796 // PDF,creator.
797 }
798 }
tsepez4cf55152016-11-02 14:37:54 -0700799 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700800}
801
Ryan Harrison275e2602017-09-18 14:23:18 -0400802void CPDFXFA_DocEnvironment::ToXFAContentFlags(WideString csSrcContent,
dsinclaira440bb32016-09-14 07:01:54 -0700803 FPDF_DWORD& flag) {
Ryan Harrison12db7512017-08-23 10:39:35 -0400804 if (csSrcContent.Contains(L" config "))
dsinclaira440bb32016-09-14 07:01:54 -0700805 flag |= FXFA_CONFIG;
Ryan Harrison12db7512017-08-23 10:39:35 -0400806 if (csSrcContent.Contains(L" template "))
dsinclaira440bb32016-09-14 07:01:54 -0700807 flag |= FXFA_TEMPLATE;
Ryan Harrison12db7512017-08-23 10:39:35 -0400808 if (csSrcContent.Contains(L" localeSet "))
dsinclaira440bb32016-09-14 07:01:54 -0700809 flag |= FXFA_LOCALESET;
Ryan Harrison12db7512017-08-23 10:39:35 -0400810 if (csSrcContent.Contains(L" datasets "))
dsinclaira440bb32016-09-14 07:01:54 -0700811 flag |= FXFA_DATASETS;
Ryan Harrison12db7512017-08-23 10:39:35 -0400812 if (csSrcContent.Contains(L" xmpmeta "))
dsinclaira440bb32016-09-14 07:01:54 -0700813 flag |= FXFA_XMPMETA;
Ryan Harrison12db7512017-08-23 10:39:35 -0400814 if (csSrcContent.Contains(L" xfdf "))
dsinclaira440bb32016-09-14 07:01:54 -0700815 flag |= FXFA_XFDF;
Ryan Harrison12db7512017-08-23 10:39:35 -0400816 if (csSrcContent.Contains(L" form "))
dsinclaira440bb32016-09-14 07:01:54 -0700817 flag |= FXFA_FORM;
818 if (flag == 0) {
819 flag = FXFA_CONFIG | FXFA_TEMPLATE | FXFA_LOCALESET | FXFA_DATASETS |
820 FXFA_XMPMETA | FXFA_XFDF | FXFA_FORM;
821 }
822}
823
Ryan Harrison275e2602017-09-18 14:23:18 -0400824bool CPDFXFA_DocEnvironment::MailToInfo(WideString& csURL,
825 WideString& csToAddress,
826 WideString& csCCAddress,
827 WideString& csBCCAddress,
828 WideString& csSubject,
829 WideString& csMsg) {
830 WideString srcURL = csURL;
dsinclaira440bb32016-09-14 07:01:54 -0700831 srcURL.TrimLeft();
832 if (srcURL.Left(7).CompareNoCase(L"mailto:") != 0)
tsepez4cf55152016-11-02 14:37:54 -0700833 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700834
Ryan Harrison12db7512017-08-23 10:39:35 -0400835 auto pos = srcURL.Find(L'?');
Ryan Harrison275e2602017-09-18 14:23:18 -0400836 WideString tmp;
Ryan Harrison12db7512017-08-23 10:39:35 -0400837 if (!pos.has_value()) {
838 pos = srcURL.Find(L'@');
839 if (!pos.has_value())
tsepez4cf55152016-11-02 14:37:54 -0700840 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700841
842 tmp = srcURL.Right(csURL.GetLength() - 7);
843 } else {
Ryan Harrison12db7512017-08-23 10:39:35 -0400844 tmp = srcURL.Left(pos.value());
dsinclaira440bb32016-09-14 07:01:54 -0700845 tmp = tmp.Right(tmp.GetLength() - 7);
846 }
847 tmp.TrimLeft();
848 tmp.TrimRight();
849
850 csToAddress = tmp;
851
Ryan Harrison12db7512017-08-23 10:39:35 -0400852 srcURL = srcURL.Right(srcURL.GetLength() - (pos.value() + 1));
dsinclaira440bb32016-09-14 07:01:54 -0700853 while (!srcURL.IsEmpty()) {
854 srcURL.TrimLeft();
855 srcURL.TrimRight();
Ryan Harrison12db7512017-08-23 10:39:35 -0400856 pos = srcURL.Find(L'&');
dsinclaira440bb32016-09-14 07:01:54 -0700857
Ryan Harrison12db7512017-08-23 10:39:35 -0400858 tmp = (!pos.has_value()) ? srcURL : srcURL.Left(pos.value());
dsinclaira440bb32016-09-14 07:01:54 -0700859 tmp.TrimLeft();
860 tmp.TrimRight();
861 if (tmp.GetLength() >= 3 && tmp.Left(3).CompareNoCase(L"cc=") == 0) {
862 tmp = tmp.Right(tmp.GetLength() - 3);
863 if (!csCCAddress.IsEmpty())
864 csCCAddress += L';';
865 csCCAddress += tmp;
866 } else if (tmp.GetLength() >= 4 &&
867 tmp.Left(4).CompareNoCase(L"bcc=") == 0) {
868 tmp = tmp.Right(tmp.GetLength() - 4);
869 if (!csBCCAddress.IsEmpty())
870 csBCCAddress += L';';
871 csBCCAddress += tmp;
872 } else if (tmp.GetLength() >= 8 &&
873 tmp.Left(8).CompareNoCase(L"subject=") == 0) {
874 tmp = tmp.Right(tmp.GetLength() - 8);
875 csSubject += tmp;
876 } else if (tmp.GetLength() >= 5 &&
877 tmp.Left(5).CompareNoCase(L"body=") == 0) {
878 tmp = tmp.Right(tmp.GetLength() - 5);
879 csMsg += tmp;
880 }
Ryan Harrison12db7512017-08-23 10:39:35 -0400881 srcURL = !pos.has_value()
882 ? L""
883 : srcURL.Right(csURL.GetLength() - (pos.value() + 1));
dsinclaira440bb32016-09-14 07:01:54 -0700884 }
885 csToAddress.Replace(L",", L";");
886 csCCAddress.Replace(L",", L";");
887 csBCCAddress.Replace(L",", L";");
tsepez4cf55152016-11-02 14:37:54 -0700888 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700889}
890
tsepez4cf55152016-11-02 14:37:54 -0700891bool CPDFXFA_DocEnvironment::SubmitDataInternal(CXFA_FFDoc* hDoc,
892 CXFA_Submit submit) {
dsinclair521b7502016-11-02 13:02:28 -0700893 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
dsinclair655fcca2016-10-11 13:53:37 -0700894 if (!pFormFillEnv)
tsepez4cf55152016-11-02 14:37:54 -0700895 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700896
Ryan Harrison275e2602017-09-18 14:23:18 -0400897 WideStringView csURLC;
dsinclaira440bb32016-09-14 07:01:54 -0700898 submit.GetSubmitTarget(csURLC);
Ryan Harrison275e2602017-09-18 14:23:18 -0400899 WideString csURL(csURLC);
dsinclaira440bb32016-09-14 07:01:54 -0700900 if (csURL.IsEmpty()) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400901 WideString ws;
dsinclaira440bb32016-09-14 07:01:54 -0700902 ws.FromLocal("Submit cancelled.");
Ryan Harrison275e2602017-09-18 14:23:18 -0400903 ByteString bs = ws.UTF16LE_Encode();
dsinclaira440bb32016-09-14 07:01:54 -0700904 int len = bs.GetLength();
dsinclair655fcca2016-10-11 13:53:37 -0700905 pFormFillEnv->Alert((FPDF_WIDESTRING)bs.GetBuffer(len),
906 (FPDF_WIDESTRING)L"", 0, 4);
dsinclaira440bb32016-09-14 07:01:54 -0700907 bs.ReleaseBuffer(len);
tsepez4cf55152016-11-02 14:37:54 -0700908 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700909 }
910
dsinclaira440bb32016-09-14 07:01:54 -0700911 FPDF_FILEHANDLER* pFileHandler = nullptr;
912 int fileFlag = -1;
913 switch (submit.GetSubmitFormat()) {
914 case XFA_ATTRIBUTEENUM_Xdp: {
Ryan Harrison275e2602017-09-18 14:23:18 -0400915 WideStringView csContentC;
dsinclaira440bb32016-09-14 07:01:54 -0700916 submit.GetSubmitXDPContent(csContentC);
Ryan Harrison275e2602017-09-18 14:23:18 -0400917 WideString csContent;
dsinclaira440bb32016-09-14 07:01:54 -0700918 csContent = csContentC;
919 csContent.TrimLeft();
920 csContent.TrimRight();
Ryan Harrison275e2602017-09-18 14:23:18 -0400921 WideString space;
dsinclaira440bb32016-09-14 07:01:54 -0700922 space.FromLocal(" ");
923 csContent = space + csContent + space;
924 FPDF_DWORD flag = 0;
925 if (submit.IsSubmitEmbedPDF())
926 flag |= FXFA_PDF;
927
928 ToXFAContentFlags(csContent, flag);
dsinclair655fcca2016-10-11 13:53:37 -0700929 pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XDP, nullptr, "wb");
dsinclaira440bb32016-09-14 07:01:54 -0700930 fileFlag = FXFA_SAVEAS_XDP;
931 ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XDP, 0, flag);
932 break;
933 }
934 case XFA_ATTRIBUTEENUM_Xml:
dsinclair655fcca2016-10-11 13:53:37 -0700935 pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XML, nullptr, "wb");
dsinclaira440bb32016-09-14 07:01:54 -0700936 fileFlag = FXFA_SAVEAS_XML;
937 ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0, FXFA_XFA_ALL);
938 break;
939 case XFA_ATTRIBUTEENUM_Pdf:
940 break;
941 case XFA_ATTRIBUTEENUM_Urlencoded:
dsinclair655fcca2016-10-11 13:53:37 -0700942 pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XML, nullptr, "wb");
dsinclaira440bb32016-09-14 07:01:54 -0700943 fileFlag = FXFA_SAVEAS_XML;
944 ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0, FXFA_XFA_ALL);
945 break;
946 default:
947 return false;
948 }
949 if (!pFileHandler)
tsepez4cf55152016-11-02 14:37:54 -0700950 return false;
dsinclaira440bb32016-09-14 07:01:54 -0700951 if (csURL.Left(7).CompareNoCase(L"mailto:") == 0) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400952 WideString csToAddress;
953 WideString csCCAddress;
954 WideString csBCCAddress;
955 WideString csSubject;
956 WideString csMsg;
tsepez16b703c2016-10-26 08:45:31 -0700957 if (!MailToInfo(csURL, csToAddress, csCCAddress, csBCCAddress, csSubject,
958 csMsg)) {
tsepez4cf55152016-11-02 14:37:54 -0700959 return false;
tsepez16b703c2016-10-26 08:45:31 -0700960 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400961 ByteString bsTo = WideString(csToAddress).UTF16LE_Encode();
962 ByteString bsCC = WideString(csCCAddress).UTF16LE_Encode();
963 ByteString bsBcc = WideString(csBCCAddress).UTF16LE_Encode();
964 ByteString bsSubject = WideString(csSubject).UTF16LE_Encode();
965 ByteString bsMsg = WideString(csMsg).UTF16LE_Encode();
dsinclaira440bb32016-09-14 07:01:54 -0700966 FPDF_WIDESTRING pTo = (FPDF_WIDESTRING)bsTo.GetBuffer(bsTo.GetLength());
967 FPDF_WIDESTRING pCC = (FPDF_WIDESTRING)bsCC.GetBuffer(bsCC.GetLength());
968 FPDF_WIDESTRING pBcc = (FPDF_WIDESTRING)bsBcc.GetBuffer(bsBcc.GetLength());
969 FPDF_WIDESTRING pSubject =
970 (FPDF_WIDESTRING)bsSubject.GetBuffer(bsSubject.GetLength());
971 FPDF_WIDESTRING pMsg = (FPDF_WIDESTRING)bsMsg.GetBuffer(bsMsg.GetLength());
dsinclair655fcca2016-10-11 13:53:37 -0700972 pFormFillEnv->EmailTo(pFileHandler, pTo, pSubject, pCC, pBcc, pMsg);
Ryan Harrison0186c182017-08-01 16:20:40 -0400973 bsTo.ReleaseBuffer(bsTo.GetStringLength());
974 bsCC.ReleaseBuffer(bsCC.GetStringLength());
975 bsBcc.ReleaseBuffer(bsBcc.GetStringLength());
976 bsSubject.ReleaseBuffer(bsSubject.GetStringLength());
977 bsMsg.ReleaseBuffer(bsMsg.GetStringLength());
dsinclaira440bb32016-09-14 07:01:54 -0700978 } else {
979 // HTTP or FTP
Ryan Harrison275e2602017-09-18 14:23:18 -0400980 WideString ws;
981 ByteString bs = csURL.UTF16LE_Encode();
dsinclaira440bb32016-09-14 07:01:54 -0700982 int len = bs.GetLength();
dsinclair655fcca2016-10-11 13:53:37 -0700983 pFormFillEnv->UploadTo(pFileHandler, fileFlag,
984 (FPDF_WIDESTRING)bs.GetBuffer(len));
dsinclaira440bb32016-09-14 07:01:54 -0700985 bs.ReleaseBuffer(len);
986 }
tsepez4cf55152016-11-02 14:37:54 -0700987 return true;
dsinclaira440bb32016-09-14 07:01:54 -0700988}
989
Ryan Harrison275e2602017-09-18 14:23:18 -0400990bool CPDFXFA_DocEnvironment::SetGlobalProperty(CXFA_FFDoc* hDoc,
991 const ByteStringView& szPropName,
992 CFXJSE_Value* pValue) {
dsinclair521b7502016-11-02 13:02:28 -0700993 if (hDoc != m_pContext->GetXFADoc())
tsepez4cf55152016-11-02 14:37:54 -0700994 return false;
Tom Sepez7dc9fe52017-05-18 09:51:57 -0700995 if (!m_pContext->GetFormFillEnv() ||
996 !m_pContext->GetFormFillEnv()->GetJSRuntime()) {
997 return false;
dsinclair655fcca2016-10-11 13:53:37 -0700998 }
Tom Sepez7dc9fe52017-05-18 09:51:57 -0700999 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
1000 IJS_EventContext* pContext = pFormFillEnv->GetJSRuntime()->NewEventContext();
1001 bool bRet = pFormFillEnv->GetJSRuntime()->SetValueByName(szPropName, pValue);
1002 pFormFillEnv->GetJSRuntime()->ReleaseEventContext(pContext);
1003 return bRet;
dsinclaira440bb32016-09-14 07:01:54 -07001004}
1005
Ryan Harrison275e2602017-09-18 14:23:18 -04001006bool CPDFXFA_DocEnvironment::GetGlobalProperty(CXFA_FFDoc* hDoc,
1007 const ByteStringView& szPropName,
1008 CFXJSE_Value* pValue) {
dsinclair521b7502016-11-02 13:02:28 -07001009 if (hDoc != m_pContext->GetXFADoc())
tsepez4cf55152016-11-02 14:37:54 -07001010 return false;
dsinclair521b7502016-11-02 13:02:28 -07001011 if (!m_pContext->GetFormFillEnv() ||
1012 !m_pContext->GetFormFillEnv()->GetJSRuntime()) {
tsepez4cf55152016-11-02 14:37:54 -07001013 return false;
dsinclair655fcca2016-10-11 13:53:37 -07001014 }
dsinclair521b7502016-11-02 13:02:28 -07001015 CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
Tom Sepez7dc9fe52017-05-18 09:51:57 -07001016 IJS_EventContext* pContext = pFormFillEnv->GetJSRuntime()->NewEventContext();
1017 bool bRet = pFormFillEnv->GetJSRuntime()->GetValueByName(szPropName, pValue);
1018 pFormFillEnv->GetJSRuntime()->ReleaseEventContext(pContext);
1019 return bRet;
dsinclaira440bb32016-09-14 07:01:54 -07001020}