• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 "xfa/fxfa/parser/cxfa_document.h"
8 
9 #include <set>
10 #include <utility>
11 
12 #include "core/fxcrt/fx_extension.h"
13 #include "core/fxcrt/xml/cfx_xmldocument.h"
14 #include "fxjs/xfa/cfxjse_engine.h"
15 #include "fxjs/xfa/cjx_object.h"
16 #include "third_party/base/compiler_specific.h"
17 #include "third_party/base/ptr_util.h"
18 #include "third_party/base/stl_util.h"
19 #include "xfa/fxfa/cxfa_ffdoc.h"
20 #include "xfa/fxfa/cxfa_ffnotify.h"
21 #include "xfa/fxfa/parser/cscript_datawindow.h"
22 #include "xfa/fxfa/parser/cscript_eventpseudomodel.h"
23 #include "xfa/fxfa/parser/cscript_hostpseudomodel.h"
24 #include "xfa/fxfa/parser/cscript_layoutpseudomodel.h"
25 #include "xfa/fxfa/parser/cscript_logpseudomodel.h"
26 #include "xfa/fxfa/parser/cscript_signaturepseudomodel.h"
27 #include "xfa/fxfa/parser/cxfa_bind.h"
28 #include "xfa/fxfa/parser/cxfa_datagroup.h"
29 #include "xfa/fxfa/parser/cxfa_exdata.h"
30 #include "xfa/fxfa/parser/cxfa_form.h"
31 #include "xfa/fxfa/parser/cxfa_image.h"
32 #include "xfa/fxfa/parser/cxfa_interactive.h"
33 #include "xfa/fxfa/parser/cxfa_items.h"
34 #include "xfa/fxfa/parser/cxfa_localemgr.h"
35 #include "xfa/fxfa/parser/cxfa_node.h"
36 #include "xfa/fxfa/parser/cxfa_occur.h"
37 #include "xfa/fxfa/parser/cxfa_pageset.h"
38 #include "xfa/fxfa/parser/cxfa_pdf.h"
39 #include "xfa/fxfa/parser/cxfa_present.h"
40 #include "xfa/fxfa/parser/cxfa_subform.h"
41 #include "xfa/fxfa/parser/cxfa_template.h"
42 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
43 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
44 #include "xfa/fxfa/parser/cxfa_value.h"
45 #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h"
46 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
47 #include "xfa/fxfa/parser/xfa_utils.h"
48 
49 namespace {
50 
51 const wchar_t kTemplateNS[] = L"http://www.xfa.org/schema/xfa-template/";
52 
53 struct RecurseRecord {
54   CXFA_Node* pTemplateChild;
55   CXFA_Node* pDataChild;
56 };
57 
58 class CXFA_TraverseStrategy_DDGroup {
59  public:
GetFirstChild(CXFA_Node * pDDGroupNode)60   static CXFA_Node* GetFirstChild(CXFA_Node* pDDGroupNode) {
61     return pDDGroupNode->GetFirstChildByName(XFA_HASHCODE_Group);
62   }
GetNextSibling(CXFA_Node * pDDGroupNode)63   static CXFA_Node* GetNextSibling(CXFA_Node* pDDGroupNode) {
64     return pDDGroupNode->GetNextSameNameSibling(XFA_HASHCODE_Group);
65   }
GetParent(CXFA_Node * pDDGroupNode)66   static CXFA_Node* GetParent(CXFA_Node* pDDGroupNode) {
67     return pDDGroupNode->GetParent();
68   }
69 };
70 
FormValueNode_MatchNoneCreateChild(CXFA_Node * pFormNode)71 void FormValueNode_MatchNoneCreateChild(CXFA_Node* pFormNode) {
72   ASSERT(pFormNode->IsWidgetReady());
73   // GetUIChildNode has the side effect of creating the UI child.
74   pFormNode->GetUIChildNode();
75 }
76 
FormValueNode_CreateChild(CXFA_Node * pValueNode,XFA_Element iType)77 CXFA_Node* FormValueNode_CreateChild(CXFA_Node* pValueNode, XFA_Element iType) {
78   CXFA_Node* pChildNode = pValueNode->GetFirstChild();
79   if (!pChildNode) {
80     if (iType == XFA_Element::Unknown)
81       return nullptr;
82 
83     pChildNode =
84         pValueNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, iType);
85   }
86   return pChildNode;
87 }
88 
FormValueNode_SetChildContent(CXFA_Node * pValueNode,const WideString & wsContent,XFA_Element iType)89 void FormValueNode_SetChildContent(CXFA_Node* pValueNode,
90                                    const WideString& wsContent,
91                                    XFA_Element iType) {
92   if (!pValueNode)
93     return;
94 
95   ASSERT(pValueNode->GetPacketType() == XFA_PacketType::Form);
96   CXFA_Node* pChildNode = FormValueNode_CreateChild(pValueNode, iType);
97   if (!pChildNode)
98     return;
99 
100   switch (pChildNode->GetObjectType()) {
101     case XFA_ObjectType::ContentNode: {
102       CXFA_Node* pContentRawDataNode = pChildNode->GetFirstChild();
103       if (!pContentRawDataNode) {
104         XFA_Element element = XFA_Element::Sharptext;
105         if (pChildNode->GetElementType() == XFA_Element::ExData) {
106           Optional<WideString> contentType =
107               pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType,
108                                                    false);
109           if (contentType.has_value()) {
110             if (contentType.value().EqualsASCII("text/html"))
111               element = XFA_Element::SharpxHTML;
112             else if (contentType.value().EqualsASCII("text/xml"))
113               element = XFA_Element::Sharpxml;
114           }
115         }
116         pContentRawDataNode = pChildNode->CreateSamePacketNode(element);
117         pChildNode->InsertChildAndNotify(pContentRawDataNode, nullptr);
118       }
119       pContentRawDataNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent,
120                                                 false, false);
121       break;
122     }
123     case XFA_ObjectType::NodeC:
124     case XFA_ObjectType::TextNode:
125     case XFA_ObjectType::NodeV: {
126       pChildNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, false,
127                                        false);
128       break;
129     }
130     default:
131       break;
132   }
133 }
134 
MergeNodeRecurse(CXFA_Node * pDestNodeParent,CXFA_Node * pProtoNode)135 void MergeNodeRecurse(CXFA_Node* pDestNodeParent, CXFA_Node* pProtoNode) {
136   CXFA_Node* pExistingNode = nullptr;
137   for (CXFA_Node* pFormChild = pDestNodeParent->GetFirstChild(); pFormChild;
138        pFormChild = pFormChild->GetNextSibling()) {
139     if (pFormChild->GetElementType() == pProtoNode->GetElementType() &&
140         pFormChild->GetNameHash() == pProtoNode->GetNameHash() &&
141         pFormChild->IsUnusedNode()) {
142       pFormChild->ClearFlag(XFA_NodeFlag_UnusedNode);
143       pExistingNode = pFormChild;
144       break;
145     }
146   }
147 
148   if (pExistingNode) {
149     pExistingNode->SetTemplateNode(pProtoNode);
150     for (CXFA_Node* pTemplateChild = pProtoNode->GetFirstChild();
151          pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
152       MergeNodeRecurse(pExistingNode, pTemplateChild);
153     }
154     return;
155   }
156   CXFA_Node* pNewNode = pProtoNode->Clone(true);
157   pNewNode->SetTemplateNode(pProtoNode);
158   pDestNodeParent->InsertChildAndNotify(pNewNode, nullptr);
159 }
160 
MergeNode(CXFA_Node * pDestNode,CXFA_Node * pProtoNode)161 void MergeNode(CXFA_Node* pDestNode, CXFA_Node* pProtoNode) {
162   {
163     CXFA_NodeIterator sIterator(pDestNode);
164     for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
165          pNode = sIterator.MoveToNext()) {
166       pNode->SetFlag(XFA_NodeFlag_UnusedNode);
167     }
168   }
169   pDestNode->SetTemplateNode(pProtoNode);
170   for (CXFA_Node* pTemplateChild = pProtoNode->GetFirstChild(); pTemplateChild;
171        pTemplateChild = pTemplateChild->GetNextSibling()) {
172     MergeNodeRecurse(pDestNode, pTemplateChild);
173   }
174   {
175     CXFA_NodeIterator sIterator(pDestNode);
176     for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
177          pNode = sIterator.MoveToNext()) {
178       pNode->ClearFlag(XFA_NodeFlag_UnusedNode);
179     }
180   }
181 }
182 
CloneOrMergeInstanceManager(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,std::vector<CXFA_Node * > * subforms)183 CXFA_Node* CloneOrMergeInstanceManager(CXFA_Document* pDocument,
184                                        CXFA_Node* pFormParent,
185                                        CXFA_Node* pTemplateNode,
186                                        std::vector<CXFA_Node*>* subforms) {
187   WideString wsSubformName =
188       pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
189   WideString wsInstMgrNodeName = L"_" + wsSubformName;
190   uint32_t dwInstNameHash =
191       FX_HashCode_GetW(wsInstMgrNodeName.AsStringView(), false);
192   CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance(
193       pDocument, XFA_Element::InstanceManager, dwInstNameHash, pFormParent);
194   if (pExistingNode) {
195     uint32_t dwNameHash = pTemplateNode->GetNameHash();
196     for (CXFA_Node* pNode = pExistingNode->GetNextSibling(); pNode;) {
197       XFA_Element eCurType = pNode->GetElementType();
198       if (eCurType == XFA_Element::InstanceManager)
199         break;
200 
201       if ((eCurType != XFA_Element::Subform) &&
202           (eCurType != XFA_Element::SubformSet)) {
203         pNode = pNode->GetNextSibling();
204         continue;
205       }
206       if (dwNameHash != pNode->GetNameHash())
207         break;
208 
209       CXFA_Node* pNextNode = pNode->GetNextSibling();
210       pFormParent->RemoveChildAndNotify(pNode, true);
211       subforms->push_back(pNode);
212       pNode = pNextNode;
213     }
214     pFormParent->RemoveChildAndNotify(pExistingNode, true);
215     pFormParent->InsertChildAndNotify(pExistingNode, nullptr);
216     pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode);
217     pExistingNode->SetTemplateNode(pTemplateNode);
218     return pExistingNode;
219   }
220 
221   CXFA_Node* pNewNode =
222       pDocument->CreateNode(XFA_PacketType::Form, XFA_Element::InstanceManager);
223   wsInstMgrNodeName =
224       L"_" + pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
225   pNewNode->JSObject()->SetCData(XFA_Attribute::Name, wsInstMgrNodeName, false,
226                                  false);
227   pFormParent->InsertChildAndNotify(pNewNode, nullptr);
228   pNewNode->SetTemplateNode(pTemplateNode);
229   return pNewNode;
230 }
231 
SortRecurseRecord(std::vector<RecurseRecord> * rgRecords,CXFA_Node * pDataScope,bool bChoiceMode)232 void SortRecurseRecord(std::vector<RecurseRecord>* rgRecords,
233                        CXFA_Node* pDataScope,
234                        bool bChoiceMode) {
235   std::vector<RecurseRecord> rgResultRecord;
236   for (CXFA_Node* pNode = pDataScope->GetFirstChild(); pNode;
237        pNode = pNode->GetNextSibling()) {
238     auto it = std::find_if(rgRecords->begin(), rgRecords->end(),
239                            [pNode](const RecurseRecord& record) {
240                              return pNode == record.pDataChild;
241                            });
242     if (it != rgRecords->end()) {
243       rgResultRecord.push_back(*it);
244       rgRecords->erase(it);
245       if (bChoiceMode)
246         break;
247     }
248   }
249   if (rgResultRecord.empty())
250     return;
251 
252   if (!bChoiceMode) {
253     rgResultRecord.insert(rgResultRecord.end(), rgRecords->begin(),
254                           rgRecords->end());
255   }
256   *rgRecords = rgResultRecord;
257 }
258 
ScopeMatchGlobalBinding(CXFA_Node * pDataScope,uint32_t dwNameHash,XFA_Element eMatchDataNodeType,bool bUpLevel)259 CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope,
260                                    uint32_t dwNameHash,
261                                    XFA_Element eMatchDataNodeType,
262                                    bool bUpLevel) {
263   for (CXFA_Node *pCurDataScope = pDataScope, *pLastDataScope = nullptr;
264        pCurDataScope &&
265        pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
266        pLastDataScope = pCurDataScope,
267                  pCurDataScope = pCurDataScope->GetParent()) {
268     for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
269          pDataChild;
270          pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
271       if (pDataChild == pLastDataScope ||
272           (eMatchDataNodeType != XFA_Element::DataModel &&
273            pDataChild->GetElementType() != eMatchDataNodeType) ||
274           pDataChild->HasBindItem()) {
275         continue;
276       }
277       return pDataChild;
278     }
279 
280     for (CXFA_DataGroup* pDataChild =
281              pCurDataScope->GetFirstChildByClass<CXFA_DataGroup>(
282                  XFA_Element::DataGroup);
283          pDataChild;
284          pDataChild = pDataChild->GetNextSameClassSibling<CXFA_DataGroup>(
285              XFA_Element::DataGroup)) {
286       CXFA_Node* pDataNode = ScopeMatchGlobalBinding(pDataChild, dwNameHash,
287                                                      eMatchDataNodeType, false);
288       if (pDataNode)
289         return pDataNode;
290     }
291     if (!bUpLevel)
292       break;
293   }
294   return nullptr;
295 }
296 
FindGlobalDataNode(CXFA_Document * pDocument,const WideString & wsName,CXFA_Node * pDataScope,XFA_Element eMatchNodeType)297 CXFA_Node* FindGlobalDataNode(CXFA_Document* pDocument,
298                               const WideString& wsName,
299                               CXFA_Node* pDataScope,
300                               XFA_Element eMatchNodeType) {
301   if (wsName.IsEmpty())
302     return nullptr;
303 
304   uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
305   CXFA_Node* pBounded = pDocument->GetGlobalBinding(dwNameHash);
306   if (!pBounded) {
307     pBounded =
308         ScopeMatchGlobalBinding(pDataScope, dwNameHash, eMatchNodeType, true);
309     if (pBounded)
310       pDocument->RegisterGlobalBinding(dwNameHash, pBounded);
311   }
312   return pBounded;
313 }
314 
FindOnceDataNode(const WideString & wsName,CXFA_Node * pDataScope,XFA_Element eMatchNodeType)315 CXFA_Node* FindOnceDataNode(const WideString& wsName,
316                             CXFA_Node* pDataScope,
317                             XFA_Element eMatchNodeType) {
318   if (wsName.IsEmpty())
319     return nullptr;
320 
321   uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
322   CXFA_Node* pLastDataScope = nullptr;
323   for (CXFA_Node* pCurDataScope = pDataScope;
324        pCurDataScope &&
325        pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
326        pCurDataScope = pCurDataScope->GetParent()) {
327     for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
328          pDataChild;
329          pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
330       if (pDataChild == pLastDataScope || pDataChild->HasBindItem() ||
331           (eMatchNodeType != XFA_Element::DataModel &&
332            pDataChild->GetElementType() != eMatchNodeType)) {
333         continue;
334       }
335       return pDataChild;
336     }
337     pLastDataScope = pCurDataScope;
338   }
339   return nullptr;
340 }
341 
FindDataRefDataNode(CXFA_Document * pDocument,const WideString & wsRef,CXFA_Node * pDataScope,XFA_Element eMatchNodeType,CXFA_Node * pTemplateNode,bool bForceBind,bool bUpLevel)342 CXFA_Node* FindDataRefDataNode(CXFA_Document* pDocument,
343                                const WideString& wsRef,
344                                CXFA_Node* pDataScope,
345                                XFA_Element eMatchNodeType,
346                                CXFA_Node* pTemplateNode,
347                                bool bForceBind,
348                                bool bUpLevel) {
349   uint32_t dFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_BindNew;
350   if (bUpLevel || !wsRef.EqualsASCII("name"))
351     dFlags |= (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
352 
353   XFA_RESOLVENODE_RS rs;
354   pDocument->GetScriptContext()->ResolveObjects(
355       pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
356   if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeAll ||
357       rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeMidAll ||
358       rs.objects.size() > 1) {
359     return pDocument->GetNotBindNode(rs.objects);
360   }
361 
362   if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeOne) {
363     CXFA_Object* pObject =
364         !rs.objects.empty() ? rs.objects.front().Get() : nullptr;
365     CXFA_Node* pNode = ToNode(pObject);
366     return (bForceBind || !pNode || !pNode->HasBindItem()) ? pNode : nullptr;
367   }
368   return nullptr;
369 }
370 
FindMatchingDataNode(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pDataScope,bool & bAccessedDataDOM,bool bForceBind,CXFA_NodeIteratorTemplate<CXFA_Node,CXFA_TraverseStrategy_XFAContainerNode> * pIterator,bool & bSelfMatch,XFA_AttributeValue & eBindMatch,bool bUpLevel)371 CXFA_Node* FindMatchingDataNode(
372     CXFA_Document* pDocument,
373     CXFA_Node* pTemplateNode,
374     CXFA_Node* pDataScope,
375     bool& bAccessedDataDOM,
376     bool bForceBind,
377     CXFA_NodeIteratorTemplate<CXFA_Node,
378                               CXFA_TraverseStrategy_XFAContainerNode>*
379         pIterator,
380     bool& bSelfMatch,
381     XFA_AttributeValue& eBindMatch,
382     bool bUpLevel) {
383   CXFA_Node* pResult = nullptr;
384   CXFA_Node* pCurTemplateNode = pIterator->GetCurrent();
385   while (pCurTemplateNode) {
386     XFA_Element eMatchNodeType;
387     switch (pCurTemplateNode->GetElementType()) {
388       case XFA_Element::Subform:
389         eMatchNodeType = XFA_Element::DataGroup;
390         break;
391       case XFA_Element::Field: {
392         eMatchNodeType = XFA_FieldIsMultiListBox(pCurTemplateNode)
393                              ? XFA_Element::DataGroup
394                              : XFA_Element::DataValue;
395       } break;
396       case XFA_Element::ExclGroup:
397         eMatchNodeType = XFA_Element::DataValue;
398         break;
399       default:
400         pCurTemplateNode = pIterator->MoveToNext();
401         continue;
402     }
403 
404     CXFA_Occur* pTemplateNodeOccur =
405         pCurTemplateNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
406     if (pTemplateNodeOccur) {
407       int32_t iMin;
408       int32_t iMax;
409       int32_t iInit;
410       std::tie(iMin, iMax, iInit) = pTemplateNodeOccur->GetOccurInfo();
411       if (iMax == 0) {
412         pCurTemplateNode = pIterator->MoveToNext();
413         continue;
414       }
415     }
416 
417     CXFA_Bind* pTemplateNodeBind =
418         pCurTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind);
419     XFA_AttributeValue eMatch =
420         pTemplateNodeBind
421             ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
422             : XFA_AttributeValue::Once;
423     eBindMatch = eMatch;
424     switch (eMatch) {
425       case XFA_AttributeValue::None:
426         pCurTemplateNode = pIterator->MoveToNext();
427         continue;
428       case XFA_AttributeValue::Global:
429         bAccessedDataDOM = true;
430         if (!bForceBind) {
431           pCurTemplateNode = pIterator->MoveToNext();
432           continue;
433         }
434         if (eMatchNodeType == XFA_Element::DataValue ||
435             (eMatchNodeType == XFA_Element::DataGroup &&
436              XFA_FieldIsMultiListBox(pTemplateNodeBind))) {
437           CXFA_Node* pGlobalBindNode = FindGlobalDataNode(
438               pDocument,
439               pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
440               pDataScope, eMatchNodeType);
441           if (!pGlobalBindNode) {
442             pCurTemplateNode = pIterator->MoveToNext();
443             continue;
444           }
445           pResult = pGlobalBindNode;
446           break;
447         }
448         FALLTHROUGH;
449       case XFA_AttributeValue::Once: {
450         bAccessedDataDOM = true;
451         CXFA_Node* pOnceBindNode = FindOnceDataNode(
452             pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
453             pDataScope, eMatchNodeType);
454         if (!pOnceBindNode) {
455           pCurTemplateNode = pIterator->MoveToNext();
456           continue;
457         }
458         pResult = pOnceBindNode;
459         break;
460       }
461       case XFA_AttributeValue::DataRef: {
462         bAccessedDataDOM = true;
463         CXFA_Node* pDataRefBindNode = FindDataRefDataNode(
464             pDocument,
465             pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref),
466             pDataScope, eMatchNodeType, pTemplateNode, bForceBind, bUpLevel);
467         if (pDataRefBindNode &&
468             pDataRefBindNode->GetElementType() == eMatchNodeType) {
469           pResult = pDataRefBindNode;
470         }
471         if (!pResult) {
472           pCurTemplateNode = pIterator->SkipChildrenAndMoveToNext();
473           continue;
474         }
475         break;
476       }
477       default:
478         break;
479     }
480     if (pCurTemplateNode == pTemplateNode && pResult)
481       bSelfMatch = true;
482     break;
483   }
484   return pResult;
485 }
486 
CreateDataBinding(CXFA_Node * pFormNode,CXFA_Node * pDataNode,bool bDataToForm)487 void CreateDataBinding(CXFA_Node* pFormNode,
488                        CXFA_Node* pDataNode,
489                        bool bDataToForm) {
490   pFormNode->SetBindingNode(pDataNode);
491   pDataNode->AddBindItem(pFormNode);
492   XFA_Element eType = pFormNode->GetElementType();
493   if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
494     return;
495 
496   ASSERT(pFormNode->IsWidgetReady());
497   auto* defValue = pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
498       0, XFA_Element::Value);
499   if (!bDataToForm) {
500     WideString wsValue;
501     switch (pFormNode->GetFFWidgetType()) {
502       case XFA_FFWidgetType::kImageEdit: {
503         CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
504         WideString wsContentType;
505         WideString wsHref;
506         if (image) {
507           wsValue = image->GetContent();
508           wsContentType = image->GetContentType();
509           wsHref = image->GetHref();
510         }
511         CFX_XMLElement* pXMLDataElement =
512             ToXMLElement(pDataNode->GetXMLMappingNode());
513         ASSERT(pXMLDataElement);
514         pDataNode->JSObject()->SetAttributeValue(
515             wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
516         pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
517                                         wsContentType, false, false);
518         if (!wsHref.IsEmpty())
519           pXMLDataElement->SetAttribute(L"href", wsHref);
520 
521         break;
522       }
523       case XFA_FFWidgetType::kChoiceList:
524         wsValue = defValue ? defValue->GetChildValueContent() : WideString();
525         if (pFormNode->IsChoiceListMultiSelect()) {
526           std::vector<WideString> wsSelTextArray =
527               pFormNode->GetSelectedItemsValue();
528           if (!wsSelTextArray.empty()) {
529             for (const auto& text : wsSelTextArray) {
530               CXFA_Node* pValue =
531                   pDataNode->CreateSamePacketNode(XFA_Element::DataValue);
532               pValue->JSObject()->SetCData(XFA_Attribute::Name, L"value", false,
533                                            false);
534               pValue->CreateXMLMappingNode();
535               pDataNode->InsertChildAndNotify(pValue, nullptr);
536               pValue->JSObject()->SetCData(XFA_Attribute::Value, text, false,
537                                            false);
538             }
539           } else {
540             CFX_XMLElement* pElement =
541                 ToXMLElement(pDataNode->GetXMLMappingNode());
542             pElement->SetAttribute(L"xfa:dataNode", L"dataGroup");
543           }
544         } else if (!wsValue.IsEmpty()) {
545           pDataNode->JSObject()->SetAttributeValue(
546               wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
547         }
548         break;
549       case XFA_FFWidgetType::kCheckButton:
550         wsValue = defValue ? defValue->GetChildValueContent() : WideString();
551         if (wsValue.IsEmpty())
552           break;
553 
554         pDataNode->JSObject()->SetAttributeValue(
555             wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
556         break;
557       case XFA_FFWidgetType::kExclGroup: {
558         CXFA_Node* pChecked = nullptr;
559         CXFA_Node* pChild = pFormNode->GetFirstChild();
560         for (; pChild; pChild = pChild->GetNextSibling()) {
561           if (pChild->GetElementType() != XFA_Element::Field)
562             continue;
563 
564           auto* pValue =
565               pChild->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
566           if (!pValue)
567             continue;
568 
569           wsValue = pValue->GetChildValueContent();
570           if (wsValue.IsEmpty())
571             continue;
572 
573           CXFA_Items* pItems =
574               pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
575           if (!pItems)
576             continue;
577 
578           CXFA_Node* pText = pItems->GetFirstChild();
579           if (!pText)
580             continue;
581 
582           WideString wsContent = pText->JSObject()->GetContent(false);
583           if (wsContent == wsValue) {
584             pChecked = pChild;
585             pDataNode->JSObject()->SetAttributeValue(wsValue, wsValue, false,
586                                                      false);
587             pFormNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent,
588                                             false, false);
589             break;
590           }
591         }
592         if (!pChecked)
593           break;
594 
595         pChild = pFormNode->GetFirstChild();
596         for (; pChild; pChild = pChild->GetNextSibling()) {
597           if (pChild == pChecked)
598             continue;
599           if (pChild->GetElementType() != XFA_Element::Field)
600             continue;
601 
602           CXFA_Value* pValue =
603               pChild->JSObject()->GetOrCreateProperty<CXFA_Value>(
604                   0, XFA_Element::Value);
605           CXFA_Items* pItems =
606               pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
607           CXFA_Node* pText = pItems ? pItems->GetFirstChild() : nullptr;
608           if (pText)
609             pText = pText->GetNextSibling();
610 
611           WideString wsContent;
612           if (pText)
613             wsContent = pText->JSObject()->GetContent(false);
614 
615           FormValueNode_SetChildContent(pValue, wsContent, XFA_Element::Text);
616         }
617         break;
618       }
619       case XFA_FFWidgetType::kNumericEdit: {
620         wsValue = defValue ? defValue->GetChildValueContent() : WideString();
621         if (wsValue.IsEmpty())
622           break;
623 
624         wsValue = pFormNode->NormalizeNumStr(wsValue);
625         pDataNode->JSObject()->SetAttributeValue(
626             wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
627         CXFA_Value* pValue =
628             pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
629                 0, XFA_Element::Value);
630         FormValueNode_SetChildContent(pValue, wsValue, XFA_Element::Float);
631         break;
632       }
633       default:
634         wsValue = defValue ? defValue->GetChildValueContent() : WideString();
635         if (wsValue.IsEmpty())
636           break;
637 
638         pDataNode->JSObject()->SetAttributeValue(
639             wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
640         break;
641     }
642     return;
643   }
644 
645   WideString wsXMLValue = pDataNode->JSObject()->GetContent(false);
646   WideString wsNormalizeValue = pFormNode->GetNormalizeDataValue(wsXMLValue);
647 
648   pDataNode->JSObject()->SetAttributeValue(wsNormalizeValue, wsXMLValue, false,
649                                            false);
650   switch (pFormNode->GetFFWidgetType()) {
651     case XFA_FFWidgetType::kImageEdit: {
652       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
653                                     XFA_Element::Image);
654       CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
655       if (image) {
656         CFX_XMLElement* pXMLDataElement =
657             ToXMLElement(pDataNode->GetXMLMappingNode());
658         WideString wsContentType =
659             pXMLDataElement->GetAttribute(L"xfa:contentType");
660         if (!wsContentType.IsEmpty()) {
661           pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
662                                           wsContentType, false, false);
663           image->SetContentType(wsContentType);
664         }
665 
666         WideString wsHref = pXMLDataElement->GetAttribute(L"href");
667         if (!wsHref.IsEmpty())
668           image->SetHref(wsHref);
669       }
670       break;
671     }
672     case XFA_FFWidgetType::kChoiceList:
673       if (pFormNode->IsChoiceListMultiSelect()) {
674         std::vector<CXFA_Node*> items = pDataNode->GetNodeListWithFilter(
675             XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties);
676         if (!items.empty()) {
677           bool single = items.size() == 1;
678           wsNormalizeValue.clear();
679 
680           for (CXFA_Node* pNode : items) {
681             WideString wsItem = pNode->JSObject()->GetContent(false);
682             if (single)
683               wsItem += L"\n";
684 
685             wsNormalizeValue += wsItem;
686           }
687           CXFA_ExData* exData =
688               defValue ? defValue->GetExDataIfExists() : nullptr;
689           if (exData)
690             exData->SetContentType(single ? L"text/plain" : L"text/xml");
691         }
692         FormValueNode_SetChildContent(defValue, wsNormalizeValue,
693                                       XFA_Element::ExData);
694       } else {
695         FormValueNode_SetChildContent(defValue, wsNormalizeValue,
696                                       XFA_Element::Text);
697       }
698       break;
699     case XFA_FFWidgetType::kExclGroup: {
700       pFormNode->SetSelectedMemberByValue(wsNormalizeValue.AsStringView(),
701                                           false, false, false);
702       break;
703     }
704     case XFA_FFWidgetType::kDateTimeEdit:
705       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
706                                     XFA_Element::DateTime);
707       break;
708     case XFA_FFWidgetType::kNumericEdit: {
709       WideString wsPicture =
710           pFormNode->GetPictureContent(XFA_VALUEPICTURE_DataBind);
711       if (wsPicture.IsEmpty())
712         wsNormalizeValue = pFormNode->NormalizeNumStr(wsNormalizeValue);
713 
714       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
715                                     XFA_Element::Float);
716       break;
717     }
718     default:
719       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
720                                     XFA_Element::Text);
721       break;
722   }
723 }
724 
MaybeCreateDataNode(CXFA_Document * pDocument,CXFA_Node * pDataParent,XFA_Element eNodeType,const WideString & wsName)725 CXFA_Node* MaybeCreateDataNode(CXFA_Document* pDocument,
726                                CXFA_Node* pDataParent,
727                                XFA_Element eNodeType,
728                                const WideString& wsName) {
729   if (!pDataParent)
730     return nullptr;
731 
732   CXFA_Node* pParentDDNode = pDataParent->GetDataDescriptionNode();
733   if (!pParentDDNode) {
734     CXFA_Node* pDataNode =
735         pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
736     pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false);
737     pDataNode->CreateXMLMappingNode();
738     pDataParent->InsertChildAndNotify(pDataNode, nullptr);
739     pDataNode->SetFlag(XFA_NodeFlag_Initialized);
740     return pDataNode;
741   }
742 
743   CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup> sIterator(
744       pParentDDNode);
745   for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
746        pDDGroupNode = sIterator.MoveToNext()) {
747     if (pDDGroupNode != pParentDDNode) {
748       if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
749         continue;
750 
751       Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
752       if (!ns.has_value() ||
753           !ns.value().EqualsASCII("http://ns.adobe.com/data-description/")) {
754         continue;
755       }
756     }
757 
758     CXFA_Node* pDDNode =
759         pDDGroupNode->GetFirstChildByName(wsName.AsStringView());
760     if (!pDDNode)
761       continue;
762     if (pDDNode->GetElementType() != eNodeType)
763       break;
764 
765     CXFA_Node* pDataNode =
766         pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
767     pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false);
768     pDataNode->CreateXMLMappingNode();
769     if (eNodeType == XFA_Element::DataValue &&
770         pDDNode->JSObject()->GetEnum(XFA_Attribute::Contains) ==
771             XFA_AttributeValue::MetaData) {
772       pDataNode->JSObject()->SetEnum(XFA_Attribute::Contains,
773                                      XFA_AttributeValue::MetaData, false);
774     }
775     pDataParent->InsertChildAndNotify(pDataNode, nullptr);
776     pDataNode->SetDataDescriptionNode(pDDNode);
777     pDataNode->SetFlag(XFA_NodeFlag_Initialized);
778     return pDataNode;
779   }
780   return nullptr;
781 }
782 
CopyContainer_Field(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bDataMerge,bool bUpLevel)783 CXFA_Node* CopyContainer_Field(CXFA_Document* pDocument,
784                                CXFA_Node* pTemplateNode,
785                                CXFA_Node* pFormNode,
786                                CXFA_Node* pDataScope,
787                                bool bDataMerge,
788                                bool bUpLevel) {
789   CXFA_Node* pFieldNode = XFA_NodeMerge_CloneOrMergeContainer(
790       pDocument, pFormNode, pTemplateNode, false, nullptr);
791   ASSERT(pFieldNode);
792   for (CXFA_Node* pTemplateChildNode = pTemplateNode->GetFirstChild();
793        pTemplateChildNode;
794        pTemplateChildNode = pTemplateChildNode->GetNextSibling()) {
795     if (XFA_DataMerge_NeedGenerateForm(pTemplateChildNode, true)) {
796       XFA_NodeMerge_CloneOrMergeContainer(pDocument, pFieldNode,
797                                           pTemplateChildNode, true, nullptr);
798     } else if (pTemplateNode->GetElementType() == XFA_Element::ExclGroup &&
799                pTemplateChildNode->IsContainerNode()) {
800       if (pTemplateChildNode->GetElementType() == XFA_Element::Field) {
801         CopyContainer_Field(pDocument, pTemplateChildNode, pFieldNode, nullptr,
802                             false, true);
803       }
804     }
805   }
806   if (bDataMerge) {
807     bool bAccessedDataDOM = false;
808     bool bSelfMatch = false;
809     XFA_AttributeValue eBindMatch;
810     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
811         sNodeIter(pTemplateNode);
812     CXFA_Node* pDataNode = FindMatchingDataNode(
813         pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, true,
814         &sNodeIter, bSelfMatch, eBindMatch, bUpLevel);
815     if (pDataNode)
816       CreateDataBinding(pFieldNode, pDataNode, true);
817   } else {
818     FormValueNode_MatchNoneCreateChild(pFieldNode);
819   }
820   return pFieldNode;
821 }
822 
CopyContainer_SubformSet(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pFormParentNode,CXFA_Node * pDataScope,bool bOneInstance,bool bDataMerge)823 CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument,
824                                     CXFA_Node* pTemplateNode,
825                                     CXFA_Node* pFormParentNode,
826                                     CXFA_Node* pDataScope,
827                                     bool bOneInstance,
828                                     bool bDataMerge) {
829   XFA_Element eType = pTemplateNode->GetElementType();
830   CXFA_Node* pOccurNode = nullptr;
831   CXFA_Node* pFirstInstance = nullptr;
832   bool bUseInstanceManager =
833       pFormParentNode->GetElementType() != XFA_Element::Area;
834   CXFA_Node* pInstMgrNode = nullptr;
835   std::vector<CXFA_Node*> subformArray;
836   std::vector<CXFA_Node*>* pSearchArray = nullptr;
837   if (!bOneInstance &&
838       (eType == XFA_Element::SubformSet || eType == XFA_Element::Subform)) {
839     pInstMgrNode = bUseInstanceManager ? CloneOrMergeInstanceManager(
840                                              pDocument, pFormParentNode,
841                                              pTemplateNode, &subformArray)
842                                        : nullptr;
843     if (CXFA_Occur* pOccurTemplateNode =
844             pTemplateNode->GetFirstChildByClass<CXFA_Occur>(
845                 XFA_Element::Occur)) {
846       pOccurNode = pInstMgrNode ? XFA_NodeMerge_CloneOrMergeContainer(
847                                       pDocument, pInstMgrNode,
848                                       pOccurTemplateNode, false, nullptr)
849                                 : pOccurTemplateNode;
850     } else if (pInstMgrNode) {
851       pOccurNode =
852           pInstMgrNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
853       if (pOccurNode)
854         pOccurNode->ClearFlag(XFA_NodeFlag_UnusedNode);
855     }
856     if (pInstMgrNode) {
857       pInstMgrNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
858       pSearchArray = &subformArray;
859       if (pFormParentNode->GetElementType() == XFA_Element::PageArea) {
860         bOneInstance = true;
861         if (subformArray.empty())
862           pSearchArray = nullptr;
863       } else if (pTemplateNode->GetNameHash() == 0 && subformArray.empty()) {
864         pSearchArray = nullptr;
865       }
866     }
867   }
868 
869   int32_t iMax = 1;
870   int32_t iInit = 1;
871   int32_t iMin = 1;
872   if (!bOneInstance && pOccurNode) {
873     std::tie(iMin, iMax, iInit) =
874         static_cast<CXFA_Occur*>(pOccurNode)->GetOccurInfo();
875   }
876 
877   XFA_AttributeValue eRelation =
878       eType == XFA_Element::SubformSet
879           ? pTemplateNode->JSObject()->GetEnum(XFA_Attribute::Relation)
880           : XFA_AttributeValue::Ordered;
881   int32_t iCurRepeatIndex = 0;
882   XFA_AttributeValue eParentBindMatch = XFA_AttributeValue::None;
883   if (bDataMerge) {
884     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
885         sNodeIterator(pTemplateNode);
886     bool bAccessedDataDOM = false;
887     if (eType == XFA_Element::SubformSet || eType == XFA_Element::Area) {
888       sNodeIterator.MoveToNext();
889     } else {
890       std::map<CXFA_Node*, CXFA_Node*> subformMapArray;
891       std::vector<CXFA_Node*> nodeArray;
892       for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) {
893         bool bSelfMatch = false;
894         XFA_AttributeValue eBindMatch = XFA_AttributeValue::None;
895         CXFA_Node* pDataNode = FindMatchingDataNode(
896             pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, false,
897             &sNodeIterator, bSelfMatch, eBindMatch, true);
898         if (!pDataNode || sNodeIterator.GetCurrent() != pTemplateNode)
899           break;
900 
901         eParentBindMatch = eBindMatch;
902         CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer(
903             pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
904         if (!pFirstInstance)
905           pFirstInstance = pSubformNode;
906 
907         CreateDataBinding(pSubformNode, pDataNode, true);
908         ASSERT(pSubformNode);
909         subformMapArray[pSubformNode] = pDataNode;
910         nodeArray.push_back(pSubformNode);
911       }
912 
913       for (CXFA_Node* pSubform : nodeArray) {
914         CXFA_Node* pDataNode = nullptr;
915         auto it = subformMapArray.find(pSubform);
916         if (it != subformMapArray.end())
917           pDataNode = it->second;
918         for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
919              pTemplateChild;
920              pTemplateChild = pTemplateChild->GetNextSibling()) {
921           if (XFA_DataMerge_NeedGenerateForm(pTemplateChild,
922                                              bUseInstanceManager)) {
923             XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubform,
924                                                 pTemplateChild, true, nullptr);
925           } else if (pTemplateChild->IsContainerNode()) {
926             pDocument->DataMerge_CopyContainer(pTemplateChild, pSubform,
927                                                pDataNode, false, true, false);
928           }
929         }
930       }
931       subformMapArray.clear();
932     }
933 
934     for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) {
935       bool bSelfMatch = false;
936       XFA_AttributeValue eBindMatch = XFA_AttributeValue::None;
937       if (!FindMatchingDataNode(pDocument, pTemplateNode, pDataScope,
938                                 bAccessedDataDOM, false, &sNodeIterator,
939                                 bSelfMatch, eBindMatch, true)) {
940         break;
941       }
942       if (eBindMatch == XFA_AttributeValue::DataRef &&
943           eParentBindMatch == XFA_AttributeValue::DataRef) {
944         break;
945       }
946 
947       if (eRelation == XFA_AttributeValue::Choice ||
948           eRelation == XFA_AttributeValue::Unordered) {
949         CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
950             pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
951         ASSERT(pSubformSetNode);
952         if (!pFirstInstance)
953           pFirstInstance = pSubformSetNode;
954 
955         std::vector<RecurseRecord> rgItemMatchList;
956         std::vector<CXFA_Node*> rgItemUnmatchList;
957         for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
958              pTemplateChild;
959              pTemplateChild = pTemplateChild->GetNextSibling()) {
960           if (XFA_DataMerge_NeedGenerateForm(pTemplateChild,
961                                              bUseInstanceManager)) {
962             XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
963                                                 pTemplateChild, true, nullptr);
964           } else if (pTemplateChild->IsContainerNode()) {
965             bSelfMatch = false;
966             eBindMatch = XFA_AttributeValue::None;
967             if (eRelation != XFA_AttributeValue::Ordered) {
968               CXFA_NodeIteratorTemplate<CXFA_Node,
969                                         CXFA_TraverseStrategy_XFAContainerNode>
970                   sChildIter(pTemplateChild);
971               CXFA_Node* pDataMatch = FindMatchingDataNode(
972                   pDocument, pTemplateChild, pDataScope, bAccessedDataDOM,
973                   false, &sChildIter, bSelfMatch, eBindMatch, true);
974               if (pDataMatch) {
975                 RecurseRecord sNewRecord = {pTemplateChild, pDataMatch};
976                 if (bSelfMatch)
977                   rgItemMatchList.insert(rgItemMatchList.begin(), sNewRecord);
978                 else
979                   rgItemMatchList.push_back(sNewRecord);
980               } else {
981                 rgItemUnmatchList.push_back(pTemplateChild);
982               }
983             } else {
984               rgItemUnmatchList.push_back(pTemplateChild);
985             }
986           }
987         }
988 
989         switch (eRelation) {
990           case XFA_AttributeValue::Choice: {
991             ASSERT(!rgItemMatchList.empty());
992             SortRecurseRecord(&rgItemMatchList, pDataScope, true);
993             pDocument->DataMerge_CopyContainer(
994                 rgItemMatchList.front().pTemplateChild, pSubformSetNode,
995                 pDataScope, false, true, true);
996             break;
997           }
998           case XFA_AttributeValue::Unordered: {
999             if (!rgItemMatchList.empty()) {
1000               SortRecurseRecord(&rgItemMatchList, pDataScope, false);
1001               for (const auto& matched : rgItemMatchList) {
1002                 pDocument->DataMerge_CopyContainer(matched.pTemplateChild,
1003                                                    pSubformSetNode, pDataScope,
1004                                                    false, true, true);
1005               }
1006             }
1007             for (auto* unmatched : rgItemUnmatchList) {
1008               pDocument->DataMerge_CopyContainer(unmatched, pSubformSetNode,
1009                                                  pDataScope, false, true, true);
1010             }
1011             break;
1012           }
1013           default:
1014             break;
1015         }
1016       } else {
1017         CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1018             pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
1019         ASSERT(pSubformSetNode);
1020         if (!pFirstInstance)
1021           pFirstInstance = pSubformSetNode;
1022 
1023         for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1024              pTemplateChild;
1025              pTemplateChild = pTemplateChild->GetNextSibling()) {
1026           if (XFA_DataMerge_NeedGenerateForm(pTemplateChild,
1027                                              bUseInstanceManager)) {
1028             XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
1029                                                 pTemplateChild, true, nullptr);
1030           } else if (pTemplateChild->IsContainerNode()) {
1031             pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode,
1032                                                pDataScope, false, true, true);
1033           }
1034         }
1035       }
1036     }
1037 
1038     if (iCurRepeatIndex == 0 && !bAccessedDataDOM) {
1039       int32_t iLimit = iMax;
1040       if (pInstMgrNode && pTemplateNode->GetNameHash() == 0) {
1041         iLimit = pdfium::CollectionSize<int32_t>(subformArray);
1042         if (iLimit < iMin)
1043           iLimit = iInit;
1044       }
1045 
1046       for (; (iLimit < 0 || iCurRepeatIndex < iLimit); iCurRepeatIndex++) {
1047         if (pInstMgrNode) {
1048           if (pSearchArray && pSearchArray->empty()) {
1049             if (pTemplateNode->GetNameHash() != 0)
1050               break;
1051             pSearchArray = nullptr;
1052           }
1053         } else if (!XFA_DataMerge_FindFormDOMInstance(
1054                        pDocument, pTemplateNode->GetElementType(),
1055                        pTemplateNode->GetNameHash(), pFormParentNode)) {
1056           break;
1057         }
1058         CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer(
1059             pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
1060         ASSERT(pSubformNode);
1061         if (!pFirstInstance)
1062           pFirstInstance = pSubformNode;
1063 
1064         for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1065              pTemplateChild;
1066              pTemplateChild = pTemplateChild->GetNextSibling()) {
1067           if (XFA_DataMerge_NeedGenerateForm(pTemplateChild,
1068                                              bUseInstanceManager)) {
1069             XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformNode,
1070                                                 pTemplateChild, true, nullptr);
1071           } else if (pTemplateChild->IsContainerNode()) {
1072             pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformNode,
1073                                                pDataScope, false, true, true);
1074           }
1075         }
1076       }
1077     }
1078   }
1079 
1080   int32_t iMinimalLimit = iCurRepeatIndex == 0 ? iInit : iMin;
1081   for (; iCurRepeatIndex < iMinimalLimit; iCurRepeatIndex++) {
1082     CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1083         pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
1084     ASSERT(pSubformSetNode);
1085     if (!pFirstInstance)
1086       pFirstInstance = pSubformSetNode;
1087 
1088     bool bFound = false;
1089     for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1090          pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1091       if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
1092         XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
1093                                             pTemplateChild, true, nullptr);
1094       } else if (pTemplateChild->IsContainerNode()) {
1095         if (bFound && eRelation == XFA_AttributeValue::Choice)
1096           continue;
1097 
1098         pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode,
1099                                            pDataScope, false, bDataMerge, true);
1100         bFound = true;
1101       }
1102     }
1103   }
1104   return pFirstInstance;
1105 }
1106 
UpdateBindingRelations(CXFA_Document * pDocument,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bDataRef,bool bParentDataRef)1107 void UpdateBindingRelations(CXFA_Document* pDocument,
1108                             CXFA_Node* pFormNode,
1109                             CXFA_Node* pDataScope,
1110                             bool bDataRef,
1111                             bool bParentDataRef) {
1112   bool bMatchRef = true;
1113   XFA_Element eType = pFormNode->GetElementType();
1114   CXFA_Node* pDataNode = pFormNode->GetBindData();
1115   if (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup ||
1116       eType == XFA_Element::Field) {
1117     CXFA_Node* pTemplateNode = pFormNode->GetTemplateNodeIfExists();
1118     CXFA_Bind* pTemplateNodeBind =
1119         pTemplateNode
1120             ? pTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind)
1121             : nullptr;
1122     XFA_AttributeValue eMatch =
1123         pTemplateNodeBind
1124             ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
1125             : XFA_AttributeValue::Once;
1126     switch (eMatch) {
1127       case XFA_AttributeValue::None:
1128         if (!bDataRef || bParentDataRef)
1129           FormValueNode_MatchNoneCreateChild(pFormNode);
1130         break;
1131       case XFA_AttributeValue::Once:
1132         if (!bDataRef || bParentDataRef) {
1133           if (!pDataNode) {
1134             if (pFormNode->GetNameHash() != 0 &&
1135                 pFormNode->JSObject()->GetEnum(XFA_Attribute::Scope) !=
1136                     XFA_AttributeValue::None) {
1137               XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1138                                            XFA_FieldIsMultiListBox(pFormNode))
1139                                               ? XFA_Element::DataGroup
1140                                               : XFA_Element::DataValue;
1141               pDataNode = MaybeCreateDataNode(
1142                   pDocument, pDataScope, eDataNodeType,
1143                   WideString(
1144                       pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1145               if (pDataNode)
1146                 CreateDataBinding(pFormNode, pDataNode, false);
1147             }
1148             if (!pDataNode)
1149               FormValueNode_MatchNoneCreateChild(pFormNode);
1150 
1151           } else {
1152             CXFA_Node* pDataParent = pDataNode->GetParent();
1153             if (pDataParent != pDataScope) {
1154               ASSERT(pDataParent);
1155               pDataParent->RemoveChildAndNotify(pDataNode, true);
1156               pDataScope->InsertChildAndNotify(pDataNode, nullptr);
1157             }
1158           }
1159         }
1160         break;
1161       case XFA_AttributeValue::Global:
1162         if (!bDataRef || bParentDataRef) {
1163           uint32_t dwNameHash = pFormNode->GetNameHash();
1164           if (dwNameHash != 0 && !pDataNode) {
1165             pDataNode = pDocument->GetGlobalBinding(dwNameHash);
1166             if (!pDataNode) {
1167               XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1168                                            XFA_FieldIsMultiListBox(pFormNode))
1169                                               ? XFA_Element::DataGroup
1170                                               : XFA_Element::DataValue;
1171               CXFA_Node* pRecordNode =
1172                   ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record));
1173               pDataNode = MaybeCreateDataNode(
1174                   pDocument, pRecordNode, eDataNodeType,
1175                   WideString(
1176                       pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1177               if (pDataNode) {
1178                 CreateDataBinding(pFormNode, pDataNode, false);
1179                 pDocument->RegisterGlobalBinding(pFormNode->GetNameHash(),
1180                                                  pDataNode);
1181               }
1182             } else {
1183               CreateDataBinding(pFormNode, pDataNode, true);
1184             }
1185           }
1186           if (!pDataNode)
1187             FormValueNode_MatchNoneCreateChild(pFormNode);
1188         }
1189         break;
1190       case XFA_AttributeValue::DataRef: {
1191         bMatchRef = bDataRef;
1192         bParentDataRef = true;
1193         if (!pDataNode && bDataRef) {
1194           WideString wsRef =
1195               pTemplateNodeBind
1196                   ? pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref)
1197                   : WideString();
1198           uint32_t dFlags =
1199               XFA_RESOLVENODE_Children | XFA_RESOLVENODE_CreateNode;
1200           XFA_RESOLVENODE_RS rs;
1201           pDocument->GetScriptContext()->ResolveObjects(
1202               pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
1203           CXFA_Object* pObject =
1204               !rs.objects.empty() ? rs.objects.front().Get() : nullptr;
1205           pDataNode = ToNode(pObject);
1206           if (pDataNode) {
1207             CreateDataBinding(pFormNode, pDataNode,
1208                               rs.dwFlags == XFA_ResolveNode_RSType_ExistNodes);
1209           } else {
1210             FormValueNode_MatchNoneCreateChild(pFormNode);
1211           }
1212         }
1213         break;
1214       }
1215       default:
1216         break;
1217     }
1218   }
1219 
1220   if (bMatchRef &&
1221       (eType == XFA_Element::Subform || eType == XFA_Element::SubformSet ||
1222        eType == XFA_Element::Area || eType == XFA_Element::PageArea ||
1223        eType == XFA_Element::PageSet)) {
1224     for (CXFA_Node* pFormChild = pFormNode->GetFirstChild(); pFormChild;
1225          pFormChild = pFormChild->GetNextSibling()) {
1226       if (!pFormChild->IsContainerNode())
1227         continue;
1228       if (pFormChild->IsUnusedNode())
1229         continue;
1230 
1231       UpdateBindingRelations(pDocument, pFormChild,
1232                              pDataNode ? pDataNode : pDataScope, bDataRef,
1233                              bParentDataRef);
1234     }
1235   }
1236 }
1237 
UpdateDataRelation(CXFA_Node * pDataNode,CXFA_Node * pDataDescriptionNode)1238 void UpdateDataRelation(CXFA_Node* pDataNode, CXFA_Node* pDataDescriptionNode) {
1239   ASSERT(pDataDescriptionNode);
1240   for (CXFA_Node* pDataChild = pDataNode->GetFirstChild(); pDataChild;
1241        pDataChild = pDataChild->GetNextSibling()) {
1242     uint32_t dwNameHash = pDataChild->GetNameHash();
1243     if (!dwNameHash)
1244       continue;
1245 
1246     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup>
1247         sIterator(pDataDescriptionNode);
1248     for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
1249          pDDGroupNode = sIterator.MoveToNext()) {
1250       if (pDDGroupNode != pDataDescriptionNode) {
1251         if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
1252           continue;
1253 
1254         Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
1255         if (!ns.has_value() ||
1256             !ns.value().EqualsASCII("http://ns.adobe.com/data-description/")) {
1257           continue;
1258         }
1259       }
1260 
1261       CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(dwNameHash);
1262       if (!pDDNode)
1263         continue;
1264       if (pDDNode->GetElementType() != pDataChild->GetElementType())
1265         break;
1266 
1267       pDataChild->SetDataDescriptionNode(pDDNode);
1268       UpdateDataRelation(pDataChild, pDDNode);
1269       break;
1270     }
1271   }
1272 }
1273 
1274 }  // namespace
1275 
CXFA_Document(CXFA_FFNotify * notify,std::unique_ptr<LayoutProcessorIface> pLayout)1276 CXFA_Document::CXFA_Document(CXFA_FFNotify* notify,
1277                              std::unique_ptr<LayoutProcessorIface> pLayout)
1278     : CXFA_NodeOwner(),
1279       notify_(notify),
1280       m_pLayoutProcessor(std::move(pLayout)) {
1281   if (m_pLayoutProcessor)
1282     m_pLayoutProcessor->SetDocument(this);
1283 }
1284 
1285 CXFA_Document::~CXFA_Document() = default;
1286 
ClearLayoutData()1287 void CXFA_Document::ClearLayoutData() {
1288   m_pLayoutProcessor.reset();
1289   m_pScriptContext.reset();
1290   m_pLocaleMgr.reset();
1291   m_pScriptDataWindow.reset();
1292   m_pScriptEvent.reset();
1293   m_pScriptHost.reset();
1294   m_pScriptLog.reset();
1295   m_pScriptLayout.reset();
1296   m_pScriptSignature.reset();
1297 }
1298 
GetXFAObject(XFA_HashCode dwNodeNameHash)1299 CXFA_Object* CXFA_Document::GetXFAObject(XFA_HashCode dwNodeNameHash) {
1300   switch (dwNodeNameHash) {
1301     case XFA_HASHCODE_Data: {
1302       CXFA_Node* pDatasetsNode = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
1303       if (!pDatasetsNode)
1304         return nullptr;
1305 
1306       for (CXFA_DataGroup* pDatasetsChild =
1307                pDatasetsNode->GetFirstChildByClass<CXFA_DataGroup>(
1308                    XFA_Element::DataGroup);
1309            pDatasetsChild;
1310            pDatasetsChild =
1311                pDatasetsChild->GetNextSameClassSibling<CXFA_DataGroup>(
1312                    XFA_Element::DataGroup)) {
1313         if (pDatasetsChild->GetNameHash() != XFA_HASHCODE_Data)
1314           continue;
1315 
1316         Optional<WideString> namespaceURI =
1317             pDatasetsChild->JSObject()->TryNamespace();
1318         if (!namespaceURI)
1319           continue;
1320 
1321         Optional<WideString> datasetsURI =
1322             pDatasetsNode->JSObject()->TryNamespace();
1323         if (!datasetsURI)
1324           continue;
1325         if (*namespaceURI == *datasetsURI)
1326           return pDatasetsChild;
1327       }
1328       return nullptr;
1329     }
1330     case XFA_HASHCODE_Record: {
1331       CXFA_Node* pData = ToNode(GetXFAObject(XFA_HASHCODE_Data));
1332       return pData ? pData->GetFirstChildByClass<CXFA_DataGroup>(
1333                          XFA_Element::DataGroup)
1334                    : nullptr;
1335     }
1336     case XFA_HASHCODE_DataWindow: {
1337       if (!m_pScriptDataWindow)
1338         m_pScriptDataWindow = pdfium::MakeUnique<CScript_DataWindow>(this);
1339       return m_pScriptDataWindow.get();
1340     }
1341     case XFA_HASHCODE_Event: {
1342       if (!m_pScriptEvent)
1343         m_pScriptEvent = pdfium::MakeUnique<CScript_EventPseudoModel>(this);
1344       return m_pScriptEvent.get();
1345     }
1346     case XFA_HASHCODE_Host: {
1347       if (!m_pScriptHost)
1348         m_pScriptHost = pdfium::MakeUnique<CScript_HostPseudoModel>(this);
1349       return m_pScriptHost.get();
1350     }
1351     case XFA_HASHCODE_Log: {
1352       if (!m_pScriptLog)
1353         m_pScriptLog = pdfium::MakeUnique<CScript_LogPseudoModel>(this);
1354       return m_pScriptLog.get();
1355     }
1356     case XFA_HASHCODE_Signature: {
1357       if (!m_pScriptSignature)
1358         m_pScriptSignature =
1359             pdfium::MakeUnique<CScript_SignaturePseudoModel>(this);
1360       return m_pScriptSignature.get();
1361     }
1362     case XFA_HASHCODE_Layout: {
1363       if (!m_pScriptLayout)
1364         m_pScriptLayout = pdfium::MakeUnique<CScript_LayoutPseudoModel>(this);
1365       return m_pScriptLayout.get();
1366     }
1367     default:
1368       return m_pRootNode->GetFirstChildByName(dwNodeNameHash);
1369   }
1370 }
1371 
CreateNode(XFA_PacketType packet,XFA_Element eElement)1372 CXFA_Node* CXFA_Document::CreateNode(XFA_PacketType packet,
1373                                      XFA_Element eElement) {
1374   if (eElement == XFA_Element::Unknown)
1375     return nullptr;
1376   return AddOwnedNode(CXFA_Node::Create(this, eElement, packet));
1377 }
1378 
IsInteractive()1379 bool CXFA_Document::IsInteractive() {
1380   if (m_Interactive.has_value())
1381     return m_Interactive.value();
1382 
1383   CXFA_Node* pConfig = ToNode(GetXFAObject(XFA_HASHCODE_Config));
1384   if (!pConfig)
1385     return false;
1386 
1387   CXFA_Present* pPresent =
1388       pConfig->GetFirstChildByClass<CXFA_Present>(XFA_Element::Present);
1389   if (!pPresent)
1390     return false;
1391 
1392   CXFA_Pdf* pPDF = pPresent->GetFirstChildByClass<CXFA_Pdf>(XFA_Element::Pdf);
1393   if (!pPDF)
1394     return false;
1395 
1396   CXFA_Interactive* pFormFiller =
1397       pPDF->GetChild<CXFA_Interactive>(0, XFA_Element::Interactive, false);
1398   if (!pFormFiller)
1399     return false;
1400 
1401   WideString wsInteractive = pFormFiller->JSObject()->GetContent(false);
1402   bool bInteractive = wsInteractive.EqualsASCII("1");
1403   m_Interactive = bInteractive;
1404   return bInteractive;
1405 }
1406 
GetLocaleMgr()1407 CXFA_LocaleMgr* CXFA_Document::GetLocaleMgr() {
1408   if (!m_pLocaleMgr) {
1409     m_pLocaleMgr = pdfium::MakeUnique<CXFA_LocaleMgr>(
1410         ToNode(GetXFAObject(XFA_HASHCODE_LocaleSet)),
1411         GetNotify()->GetAppProvider()->GetLanguage());
1412   }
1413   return m_pLocaleMgr.get();
1414 }
1415 
InitScriptContext(CJS_Runtime * fxjs_runtime)1416 CFXJSE_Engine* CXFA_Document::InitScriptContext(CJS_Runtime* fxjs_runtime) {
1417   ASSERT(!m_pScriptContext);
1418   m_pScriptContext = pdfium::MakeUnique<CFXJSE_Engine>(this, fxjs_runtime);
1419   return m_pScriptContext.get();
1420 }
1421 
GetScriptContext() const1422 CFXJSE_Engine* CXFA_Document::GetScriptContext() const {
1423   ASSERT(m_pScriptContext);
1424   return m_pScriptContext.get();
1425 }
1426 
RecognizeXFAVersionNumber(const WideString & wsTemplateNS)1427 XFA_VERSION CXFA_Document::RecognizeXFAVersionNumber(
1428     const WideString& wsTemplateNS) {
1429   WideStringView wsTemplateURIPrefix(kTemplateNS);
1430   if (wsTemplateNS.GetLength() <= wsTemplateURIPrefix.GetLength())
1431     return XFA_VERSION_UNKNOWN;
1432 
1433   size_t prefixLength = wsTemplateURIPrefix.GetLength();
1434   if (WideStringView(wsTemplateNS.c_str(), prefixLength) != wsTemplateURIPrefix)
1435     return XFA_VERSION_UNKNOWN;
1436 
1437   auto nDotPos = wsTemplateNS.Find('.', prefixLength);
1438   if (!nDotPos.has_value())
1439     return XFA_VERSION_UNKNOWN;
1440 
1441   int8_t iMajor = FXSYS_wtoi(
1442       wsTemplateNS.Substr(prefixLength, nDotPos.value() - prefixLength)
1443           .c_str());
1444   int8_t iMinor =
1445       FXSYS_wtoi(wsTemplateNS
1446                      .Substr(nDotPos.value() + 1,
1447                              wsTemplateNS.GetLength() - nDotPos.value() - 2)
1448                      .c_str());
1449   XFA_VERSION eVersion = (XFA_VERSION)((int32_t)iMajor * 100 + iMinor);
1450   if (eVersion < XFA_VERSION_MIN || eVersion > XFA_VERSION_MAX)
1451     return XFA_VERSION_UNKNOWN;
1452 
1453   m_eCurVersionMode = eVersion;
1454   return eVersion;
1455 }
1456 
GetFormType() const1457 FormType CXFA_Document::GetFormType() const {
1458   return GetNotify()->GetHDOC()->GetFormType();
1459 }
1460 
GetNodeByID(CXFA_Node * pRoot,WideStringView wsID) const1461 CXFA_Node* CXFA_Document::GetNodeByID(CXFA_Node* pRoot,
1462                                       WideStringView wsID) const {
1463   if (!pRoot || wsID.IsEmpty())
1464     return nullptr;
1465 
1466   CXFA_NodeIterator sIterator(pRoot);
1467   for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
1468        pNode = sIterator.MoveToNext()) {
1469     WideString wsIDVal = pNode->JSObject()->GetCData(XFA_Attribute::Id);
1470     if (!wsIDVal.IsEmpty() && wsIDVal == wsID)
1471       return pNode;
1472   }
1473   return nullptr;
1474 }
1475 
DoProtoMerge()1476 void CXFA_Document::DoProtoMerge() {
1477   CXFA_Node* pTemplateRoot = ToNode(GetXFAObject(XFA_HASHCODE_Template));
1478   if (!pTemplateRoot)
1479     return;
1480 
1481   std::map<uint32_t, CXFA_Node*> mIDMap;
1482   std::set<CXFA_Node*> sUseNodes;
1483   CXFA_NodeIterator sIterator(pTemplateRoot);
1484   for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
1485        pNode = sIterator.MoveToNext()) {
1486     WideString wsIDVal = pNode->JSObject()->GetCData(XFA_Attribute::Id);
1487     if (!wsIDVal.IsEmpty())
1488       mIDMap[FX_HashCode_GetW(wsIDVal.AsStringView(), false)] = pNode;
1489 
1490     WideString wsUseVal = pNode->JSObject()->GetCData(XFA_Attribute::Use);
1491     if (!wsUseVal.IsEmpty()) {
1492       sUseNodes.insert(pNode);
1493     } else {
1494       wsUseVal = pNode->JSObject()->GetCData(XFA_Attribute::Usehref);
1495       if (!wsUseVal.IsEmpty())
1496         sUseNodes.insert(pNode);
1497     }
1498   }
1499 
1500   for (CXFA_Node* pUseHrefNode : sUseNodes) {
1501     // Must outlive the WideStringViews below.
1502     WideString wsUseVal =
1503         pUseHrefNode->JSObject()->GetCData(XFA_Attribute::Usehref);
1504     WideStringView wsURI;
1505     WideStringView wsID;
1506     WideStringView wsSOM;
1507 
1508     if (!wsUseVal.IsEmpty()) {
1509       auto uSharpPos = wsUseVal.Find('#');
1510       if (!uSharpPos.has_value()) {
1511         wsURI = wsUseVal.AsStringView();
1512       } else {
1513         wsURI = WideStringView(wsUseVal.c_str(), uSharpPos.value());
1514         size_t uLen = wsUseVal.GetLength();
1515         if (uLen >= uSharpPos.value() + 5 &&
1516             WideStringView(wsUseVal.c_str() + uSharpPos.value(), 5) ==
1517                 L"#som(" &&
1518             wsUseVal[uLen - 1] == ')') {
1519           wsSOM = WideStringView(wsUseVal.c_str() + uSharpPos.value() + 5,
1520                                  uLen - 1 - uSharpPos.value() - 5);
1521         } else {
1522           wsID = WideStringView(wsUseVal.c_str() + uSharpPos.value() + 1,
1523                                 uLen - uSharpPos.value() - 1);
1524         }
1525       }
1526     } else {
1527       wsUseVal = pUseHrefNode->JSObject()->GetCData(XFA_Attribute::Use);
1528       if (!wsUseVal.IsEmpty()) {
1529         if (wsUseVal[0] == '#')
1530           wsID = WideStringView(wsUseVal.c_str() + 1, wsUseVal.GetLength() - 1);
1531         else
1532           wsSOM = WideStringView(wsUseVal.c_str(), wsUseVal.GetLength());
1533       }
1534     }
1535     if (!wsURI.IsEmpty() && !wsURI.EqualsASCII("."))
1536       continue;
1537 
1538     CXFA_Node* pProtoNode = nullptr;
1539     if (!wsSOM.IsEmpty()) {
1540       uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
1541                         XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
1542                         XFA_RESOLVENODE_Siblings;
1543       XFA_RESOLVENODE_RS resolveNodeRS;
1544       if (m_pScriptContext->ResolveObjects(pUseHrefNode, wsSOM, &resolveNodeRS,
1545                                            dwFlag, nullptr)) {
1546         auto* pFirstObject = resolveNodeRS.objects.front().Get();
1547         if (pFirstObject && pFirstObject->IsNode())
1548           pProtoNode = pFirstObject->AsNode();
1549       }
1550     } else if (!wsID.IsEmpty()) {
1551       auto it = mIDMap.find(FX_HashCode_GetW(wsID, false));
1552       if (it == mIDMap.end())
1553         continue;
1554       pProtoNode = it->second;
1555     }
1556     if (!pProtoNode)
1557       continue;
1558 
1559     MergeNode(pUseHrefNode, pProtoNode);
1560   }
1561 }
1562 
DataMerge_CopyContainer(CXFA_Node * pTemplateNode,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bOneInstance,bool bDataMerge,bool bUpLevel)1563 CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode,
1564                                                   CXFA_Node* pFormNode,
1565                                                   CXFA_Node* pDataScope,
1566                                                   bool bOneInstance,
1567                                                   bool bDataMerge,
1568                                                   bool bUpLevel) {
1569   ASSERT(pTemplateNode->IsContainerNode());
1570   switch (pTemplateNode->GetElementType()) {
1571     case XFA_Element::Area:
1572     case XFA_Element::PageArea:
1573     case XFA_Element::Subform:
1574     case XFA_Element::SubformSet:
1575       return CopyContainer_SubformSet(this, pTemplateNode, pFormNode,
1576                                       pDataScope, bOneInstance, bDataMerge);
1577     case XFA_Element::ContentArea:
1578     case XFA_Element::Draw:
1579     case XFA_Element::ExclGroup:
1580     case XFA_Element::Field:
1581       return CopyContainer_Field(this, pTemplateNode, pFormNode, pDataScope,
1582                                  bDataMerge, bUpLevel);
1583     case XFA_Element::PageSet:
1584     case XFA_Element::Variables:
1585       return nullptr;
1586     default:
1587       NOTREACHED();
1588       return nullptr;
1589   }
1590 }
1591 
DataMerge_UpdateBindingRelations(CXFA_Node * pFormUpdateRoot)1592 void CXFA_Document::DataMerge_UpdateBindingRelations(
1593     CXFA_Node* pFormUpdateRoot) {
1594   CXFA_Node* pDataScope =
1595       XFA_DataMerge_FindDataScope(pFormUpdateRoot->GetParent());
1596   if (!pDataScope)
1597     return;
1598 
1599   UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, false, false);
1600   UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, true, false);
1601 }
1602 
GetNotBindNode(const std::vector<UnownedPtr<CXFA_Object>> & arrayObjects) const1603 CXFA_Node* CXFA_Document::GetNotBindNode(
1604     const std::vector<UnownedPtr<CXFA_Object>>& arrayObjects) const {
1605   for (auto& pObject : arrayObjects) {
1606     CXFA_Node* pNode = pObject->AsNode();
1607     if (pNode && !pNode->HasBindItem())
1608       return pNode;
1609   }
1610   return nullptr;
1611 }
1612 
DoDataMerge()1613 void CXFA_Document::DoDataMerge() {
1614   CXFA_Node* pDatasetsRoot = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
1615   if (!pDatasetsRoot) {
1616     // Ownership will be passed in the AppendChild below to the XML tree.
1617     auto* pDatasetsXMLNode =
1618         notify_->GetHDOC()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1619             L"xfa:datasets");
1620     pDatasetsXMLNode->SetAttribute(L"xmlns:xfa",
1621                                    L"http://www.xfa.org/schema/xfa-data/1.0/");
1622     pDatasetsRoot =
1623         CreateNode(XFA_PacketType::Datasets, XFA_Element::DataModel);
1624     pDatasetsRoot->JSObject()->SetCData(XFA_Attribute::Name, L"datasets", false,
1625                                         false);
1626 
1627     m_pRootNode->GetXMLMappingNode()->AppendLastChild(pDatasetsXMLNode);
1628     m_pRootNode->InsertChildAndNotify(pDatasetsRoot, nullptr);
1629     pDatasetsRoot->SetXMLMappingNode(pDatasetsXMLNode);
1630   }
1631 
1632   CXFA_Node* pDataRoot = nullptr;
1633   CXFA_Node* pDDRoot = nullptr;
1634   WideString wsDatasetsURI =
1635       pDatasetsRoot->JSObject()->TryNamespace().value_or(WideString());
1636   for (CXFA_Node* pChildNode = pDatasetsRoot->GetFirstChild(); pChildNode;
1637        pChildNode = pChildNode->GetNextSibling()) {
1638     if (pChildNode->GetElementType() != XFA_Element::DataGroup)
1639       continue;
1640 
1641     if (!pDDRoot && pChildNode->GetNameHash() == XFA_HASHCODE_DataDescription) {
1642       Optional<WideString> namespaceURI =
1643           pChildNode->JSObject()->TryNamespace();
1644       if (!namespaceURI.has_value())
1645         continue;
1646       if (namespaceURI.value().EqualsASCII(
1647               "http://ns.adobe.com/data-description/")) {
1648         pDDRoot = pChildNode;
1649       }
1650     } else if (!pDataRoot && pChildNode->GetNameHash() == XFA_HASHCODE_Data) {
1651       Optional<WideString> namespaceURI =
1652           pChildNode->JSObject()->TryNamespace();
1653       if (!namespaceURI)
1654         continue;
1655       if (*namespaceURI == wsDatasetsURI)
1656         pDataRoot = pChildNode;
1657     }
1658     if (pDataRoot && pDDRoot)
1659       break;
1660   }
1661 
1662   if (!pDataRoot) {
1663     pDataRoot = CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup);
1664     pDataRoot->JSObject()->SetCData(XFA_Attribute::Name, L"data", false, false);
1665 
1666     auto* elem =
1667         notify_->GetHDOC()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1668             L"xfa:data");
1669     pDataRoot->SetXMLMappingNode(elem);
1670     pDatasetsRoot->InsertChildAndNotify(pDataRoot, nullptr);
1671   }
1672 
1673   CXFA_DataGroup* pDataTopLevel =
1674       pDataRoot->GetFirstChildByClass<CXFA_DataGroup>(XFA_Element::DataGroup);
1675   uint32_t dwNameHash = pDataTopLevel ? pDataTopLevel->GetNameHash() : 0;
1676   CXFA_Template* pTemplateRoot =
1677       m_pRootNode->GetFirstChildByClass<CXFA_Template>(XFA_Element::Template);
1678   if (!pTemplateRoot)
1679     return;
1680 
1681   CXFA_Node* pTemplateChosen =
1682       dwNameHash != 0 ? pTemplateRoot->GetFirstChildByName(dwNameHash)
1683                       : nullptr;
1684   if (!pTemplateChosen ||
1685       pTemplateChosen->GetElementType() != XFA_Element::Subform) {
1686     pTemplateChosen =
1687         pTemplateRoot->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
1688   }
1689   if (!pTemplateChosen)
1690     return;
1691 
1692   CXFA_Form* pFormRoot =
1693       m_pRootNode->GetFirstChildByClass<CXFA_Form>(XFA_Element::Form);
1694   bool bEmptyForm = false;
1695   if (!pFormRoot) {
1696     bEmptyForm = true;
1697     pFormRoot = static_cast<CXFA_Form*>(
1698         CreateNode(XFA_PacketType::Form, XFA_Element::Form));
1699     ASSERT(pFormRoot);
1700     pFormRoot->JSObject()->SetCData(XFA_Attribute::Name, L"form", false, false);
1701     m_pRootNode->InsertChildAndNotify(pFormRoot, nullptr);
1702   } else {
1703     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode>
1704         sIterator(pFormRoot);
1705     for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode;
1706          pNode = sIterator.MoveToNext()) {
1707       pNode->SetFlag(XFA_NodeFlag_UnusedNode);
1708     }
1709   }
1710 
1711   CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1712       this, pFormRoot, pTemplateChosen, false, nullptr);
1713   ASSERT(pSubformSetNode);
1714   if (!pDataTopLevel) {
1715     WideString wsFormName =
1716         pSubformSetNode->JSObject()->GetCData(XFA_Attribute::Name);
1717     WideString wsDataTopLevelName(wsFormName.IsEmpty() ? L"form" : wsFormName);
1718 
1719     pDataTopLevel = static_cast<CXFA_DataGroup*>(
1720         CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup));
1721     pDataTopLevel->JSObject()->SetCData(XFA_Attribute::Name, wsDataTopLevelName,
1722                                         false, false);
1723 
1724     auto* elem =
1725         notify_->GetHDOC()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1726             wsDataTopLevelName);
1727     pDataTopLevel->SetXMLMappingNode(elem);
1728 
1729     CXFA_Node* pBeforeNode = pDataRoot->GetFirstChild();
1730     pDataRoot->InsertChildAndNotify(pDataTopLevel, pBeforeNode);
1731   }
1732 
1733   ASSERT(pDataTopLevel);
1734   CreateDataBinding(pSubformSetNode, pDataTopLevel, true);
1735   for (CXFA_Node* pTemplateChild = pTemplateChosen->GetFirstChild();
1736        pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1737     if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
1738       XFA_NodeMerge_CloneOrMergeContainer(this, pSubformSetNode, pTemplateChild,
1739                                           true, nullptr);
1740     } else if (pTemplateChild->IsContainerNode()) {
1741       DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, pDataTopLevel,
1742                               false, true, true);
1743     }
1744   }
1745   if (pDDRoot)
1746     UpdateDataRelation(pDataRoot, pDDRoot);
1747 
1748   DataMerge_UpdateBindingRelations(pSubformSetNode);
1749   CXFA_PageSet* pPageSetNode =
1750       pSubformSetNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
1751   while (pPageSetNode) {
1752     m_pPendingPageSet.push_back(pPageSetNode);
1753     CXFA_PageSet* pNextPageSetNode =
1754         pPageSetNode->GetNextSameClassSibling<CXFA_PageSet>(
1755             XFA_Element::PageSet);
1756     pSubformSetNode->RemoveChildAndNotify(pPageSetNode, true);
1757     pPageSetNode = pNextPageSetNode;
1758   }
1759 
1760   if (bEmptyForm)
1761     return;
1762 
1763   CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(
1764       pFormRoot);
1765   CXFA_Node* pNode = sIterator.MoveToNext();
1766   while (pNode) {
1767     if (pNode->IsUnusedNode()) {
1768       if (pNode->IsContainerNode() ||
1769           pNode->GetElementType() == XFA_Element::InstanceManager) {
1770         CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext();
1771         pNode->GetParent()->RemoveChildAndNotify(pNode, true);
1772         pNode = pNext;
1773       } else {
1774         pNode->ClearFlag(XFA_NodeFlag_UnusedNode);
1775         pNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
1776         pNode = sIterator.MoveToNext();
1777       }
1778     } else {
1779       pNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
1780       pNode = sIterator.MoveToNext();
1781     }
1782   }
1783 }
1784 
DoDataRemerge(bool bDoDataMerge)1785 void CXFA_Document::DoDataRemerge(bool bDoDataMerge) {
1786   CXFA_Node* pFormRoot = ToNode(GetXFAObject(XFA_HASHCODE_Form));
1787   if (pFormRoot) {
1788     while (CXFA_Node* pNode = pFormRoot->GetFirstChild())
1789       pFormRoot->RemoveChildAndNotify(pNode, true);
1790 
1791     pFormRoot->SetBindingNode(nullptr);
1792   }
1793   m_rgGlobalBinding.clear();
1794 
1795   if (bDoDataMerge)
1796     DoDataMerge();
1797 
1798   GetLayoutProcessor()->SetForceRelayout(true);
1799 }
1800 
GetGlobalBinding(uint32_t dwNameHash)1801 CXFA_Node* CXFA_Document::GetGlobalBinding(uint32_t dwNameHash) {
1802   auto it = m_rgGlobalBinding.find(dwNameHash);
1803   return it != m_rgGlobalBinding.end() ? it->second : nullptr;
1804 }
1805 
RegisterGlobalBinding(uint32_t dwNameHash,CXFA_Node * pDataNode)1806 void CXFA_Document::RegisterGlobalBinding(uint32_t dwNameHash,
1807                                           CXFA_Node* pDataNode) {
1808   m_rgGlobalBinding[dwNameHash] = pDataNode;
1809 }
1810 
SetPendingNodesUnusedAndUnbound()1811 void CXFA_Document::SetPendingNodesUnusedAndUnbound() {
1812   for (CXFA_Node* pPageNode : m_pPendingPageSet) {
1813     CXFA_NodeIterator sIterator(pPageNode);
1814     for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
1815          pNode = sIterator.MoveToNext()) {
1816       if (pNode->IsContainerNode()) {
1817         CXFA_Node* pBindNode = pNode->GetBindData();
1818         if (pBindNode) {
1819           pBindNode->RemoveBindItem(pNode);
1820           pNode->SetBindingNode(nullptr);
1821         }
1822       }
1823       pNode->SetFlag(XFA_NodeFlag_UnusedNode);
1824     }
1825   }
1826 }
1827 
1828 CXFA_Document::LayoutProcessorIface::LayoutProcessorIface() = default;
1829 
1830 CXFA_Document::LayoutProcessorIface::~LayoutProcessorIface() = default;
1831