Home | History | Annotate | Download | only in fpdfxfa
      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 
     40 CPDFXFA_DocEnvironment::CPDFXFA_DocEnvironment(CPDFXFA_Context* pContext)
     41     : m_pContext(pContext), m_pJSEventContext(nullptr) {
     42   ASSERT(m_pContext);
     43 }
     44 
     45 CPDFXFA_DocEnvironment::~CPDFXFA_DocEnvironment() {
     46   if (m_pJSEventContext && m_pContext->GetFormFillEnv()) {
     47     m_pContext->GetFormFillEnv()->GetJSRuntime()->ReleaseEventContext(
     48         m_pJSEventContext);
     49   }
     50 }
     51 
     52 void CPDFXFA_DocEnvironment::SetChangeMark(CXFA_FFDoc* hDoc) {
     53   if (hDoc == m_pContext->GetXFADoc() && m_pContext->GetFormFillEnv())
     54     m_pContext->GetFormFillEnv()->SetChangeMark();
     55 }
     56 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    605 bool CPDFXFA_DocEnvironment::NotifySubmit(bool bPrevOrPost) {
    606   if (bPrevOrPost)
    607     return OnBeforeNotifySubmit();
    608 
    609   OnAfterNotifySubmit();
    610   return true;
    611 }
    612 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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