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