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/xfa_document_datamerger_imp.h"
8
9 #include <map>
10 #include <vector>
11
12 #include "core/fxcrt/fx_extension.h"
13 #include "core/fxcrt/xml/cfx_xmlelement.h"
14 #include "core/fxcrt/xml/cfx_xmlnode.h"
15 #include "fxjs/cfxjse_engine.h"
16 #include "fxjs/xfa/cjx_object.h"
17 #include "third_party/base/logging.h"
18 #include "third_party/base/stl_util.h"
19 #include "xfa/fxfa/parser/cxfa_bind.h"
20 #include "xfa/fxfa/parser/cxfa_datagroup.h"
21 #include "xfa/fxfa/parser/cxfa_document.h"
22 #include "xfa/fxfa/parser/cxfa_exdata.h"
23 #include "xfa/fxfa/parser/cxfa_form.h"
24 #include "xfa/fxfa/parser/cxfa_image.h"
25 #include "xfa/fxfa/parser/cxfa_items.h"
26 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
27 #include "xfa/fxfa/parser/cxfa_localemgr.h"
28 #include "xfa/fxfa/parser/cxfa_node.h"
29 #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
30 #include "xfa/fxfa/parser/cxfa_occur.h"
31 #include "xfa/fxfa/parser/cxfa_pageset.h"
32 #include "xfa/fxfa/parser/cxfa_subform.h"
33 #include "xfa/fxfa/parser/cxfa_template.h"
34 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
35 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
36 #include "xfa/fxfa/parser/cxfa_value.h"
37 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
38 #include "xfa/fxfa/parser/xfa_utils.h"
39
40 namespace {
41
42 class CXFA_TraverseStrategy_DDGroup {
43 public:
GetFirstChild(CXFA_Node * pDDGroupNode)44 static CXFA_Node* GetFirstChild(CXFA_Node* pDDGroupNode) {
45 return pDDGroupNode->GetFirstChildByName(XFA_HASHCODE_Group);
46 }
GetNextSibling(CXFA_Node * pDDGroupNode)47 static CXFA_Node* GetNextSibling(CXFA_Node* pDDGroupNode) {
48 return pDDGroupNode->GetNextSameNameSibling(XFA_HASHCODE_Group);
49 }
GetParent(CXFA_Node * pDDGroupNode)50 static CXFA_Node* GetParent(CXFA_Node* pDDGroupNode) {
51 return pDDGroupNode->GetParent();
52 }
53 };
54
55 struct RecurseRecord {
56 CXFA_Node* pTemplateChild;
57 CXFA_Node* pDataChild;
58 };
59
FormValueNode_CreateChild(CXFA_Node * pValueNode,XFA_Element iType)60 CXFA_Node* FormValueNode_CreateChild(CXFA_Node* pValueNode, XFA_Element iType) {
61 CXFA_Node* pChildNode = pValueNode->GetFirstChild();
62 if (!pChildNode) {
63 if (iType == XFA_Element::Unknown)
64 return nullptr;
65
66 pChildNode =
67 pValueNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, iType);
68 }
69 return pChildNode;
70 }
71
FormValueNode_MatchNoneCreateChild(CXFA_Node * pFormNode)72 void FormValueNode_MatchNoneCreateChild(CXFA_Node* pFormNode) {
73 CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc();
74 ASSERT(pWidgetAcc);
75 pWidgetAcc->GetUIType();
76 }
77
FormValueNode_SetChildContent(CXFA_Node * pValueNode,const WideString & wsContent,XFA_Element iType=XFA_Element::Unknown)78 bool FormValueNode_SetChildContent(CXFA_Node* pValueNode,
79 const WideString& wsContent,
80 XFA_Element iType = XFA_Element::Unknown) {
81 if (!pValueNode)
82 return false;
83
84 ASSERT(pValueNode->GetPacketType() == XFA_PacketType::Form);
85 CXFA_Node* pChildNode = FormValueNode_CreateChild(pValueNode, iType);
86 if (!pChildNode)
87 return false;
88
89 switch (pChildNode->GetObjectType()) {
90 case XFA_ObjectType::ContentNode: {
91 CXFA_Node* pContentRawDataNode = pChildNode->GetFirstChild();
92 if (!pContentRawDataNode) {
93 XFA_Element element = XFA_Element::Sharptext;
94 if (pChildNode->GetElementType() == XFA_Element::ExData) {
95 Optional<WideString> contentType =
96 pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType,
97 false);
98 if (contentType) {
99 if (*contentType == L"text/html")
100 element = XFA_Element::SharpxHTML;
101 else if (*contentType == L"text/xml")
102 element = XFA_Element::Sharpxml;
103 }
104 }
105 pContentRawDataNode = pChildNode->CreateSamePacketNode(element);
106 pChildNode->InsertChild(pContentRawDataNode, nullptr);
107 }
108 pContentRawDataNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent,
109 false, false);
110 break;
111 }
112 case XFA_ObjectType::NodeC:
113 case XFA_ObjectType::TextNode:
114 case XFA_ObjectType::NodeV: {
115 pChildNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, false,
116 false);
117 break;
118 }
119 default:
120 NOTREACHED();
121 break;
122 }
123 return true;
124 }
125
CreateDataBinding(CXFA_Node * pFormNode,CXFA_Node * pDataNode,bool bDataToForm)126 void CreateDataBinding(CXFA_Node* pFormNode,
127 CXFA_Node* pDataNode,
128 bool bDataToForm) {
129 pFormNode->SetBindingNode(pDataNode);
130 pDataNode->AddBindItem(pFormNode);
131 XFA_Element eType = pFormNode->GetElementType();
132 if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
133 return;
134
135 CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc();
136 ASSERT(pWidgetAcc);
137 XFA_Element eUIType = pWidgetAcc->GetUIType();
138 auto* defValue = pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
139 0, XFA_Element::Value);
140 if (!bDataToForm) {
141 WideString wsValue;
142 switch (eUIType) {
143 case XFA_Element::ImageEdit: {
144 CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
145 WideString wsContentType;
146 WideString wsHref;
147 if (image) {
148 wsValue = image->GetContent();
149 wsContentType = image->GetContentType();
150 wsHref = image->GetHref();
151 }
152 CFX_XMLElement* pXMLDataElement =
153 static_cast<CFX_XMLElement*>(pDataNode->GetXMLMappingNode());
154 ASSERT(pXMLDataElement);
155
156 pDataNode->JSObject()->SetAttributeValue(
157 wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
158 pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
159 wsContentType, false, false);
160 if (!wsHref.IsEmpty())
161 pXMLDataElement->SetString(L"href", wsHref);
162
163 break;
164 }
165 case XFA_Element::ChoiceList:
166 wsValue = defValue ? defValue->GetChildValueContent() : L"";
167 if (pWidgetAcc->IsChoiceListMultiSelect()) {
168 std::vector<WideString> wsSelTextArray =
169 pWidgetAcc->GetSelectedItemsValue();
170 if (!wsSelTextArray.empty()) {
171 for (const auto& text : wsSelTextArray) {
172 CXFA_Node* pValue =
173 pDataNode->CreateSamePacketNode(XFA_Element::DataValue);
174 pValue->JSObject()->SetCData(XFA_Attribute::Name, L"value", false,
175 false);
176 pValue->CreateXMLMappingNode();
177 pDataNode->InsertChild(pValue, nullptr);
178 pValue->JSObject()->SetCData(XFA_Attribute::Value, text, false,
179 false);
180 }
181 } else {
182 CFX_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode();
183 ASSERT(pXMLNode->GetType() == FX_XMLNODE_Element);
184 static_cast<CFX_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode",
185 L"dataGroup");
186 }
187 } else if (!wsValue.IsEmpty()) {
188 pDataNode->JSObject()->SetAttributeValue(
189 wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
190 }
191 break;
192 case XFA_Element::CheckButton:
193 wsValue = defValue ? defValue->GetChildValueContent() : L"";
194 if (wsValue.IsEmpty())
195 break;
196
197 pDataNode->JSObject()->SetAttributeValue(
198 wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
199 break;
200 case XFA_Element::ExclGroup: {
201 CXFA_Node* pChecked = nullptr;
202 CXFA_Node* pChild = pFormNode->GetFirstChild();
203 for (; pChild; pChild = pChild->GetNextSibling()) {
204 if (pChild->GetElementType() != XFA_Element::Field)
205 continue;
206
207 auto* pValue =
208 pChild->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
209 if (!pValue)
210 continue;
211
212 wsValue = pValue->GetChildValueContent();
213 if (wsValue.IsEmpty())
214 continue;
215
216 CXFA_Items* pItems =
217 pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
218 if (!pItems)
219 continue;
220
221 CXFA_Node* pText = pItems->GetFirstChild();
222 if (!pText)
223 continue;
224
225 WideString wsContent = pText->JSObject()->GetContent(false);
226 if (wsContent == wsValue) {
227 pChecked = pChild;
228 pDataNode->JSObject()->SetAttributeValue(wsValue, wsValue, false,
229 false);
230 pFormNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent,
231 false, false);
232 break;
233 }
234 }
235 if (!pChecked)
236 break;
237
238 pChild = pFormNode->GetFirstChild();
239 for (; pChild; pChild = pChild->GetNextSibling()) {
240 if (pChild == pChecked)
241 continue;
242 if (pChild->GetElementType() != XFA_Element::Field)
243 continue;
244
245 CXFA_Value* pValue =
246 pChild->JSObject()->GetOrCreateProperty<CXFA_Value>(
247 0, XFA_Element::Value);
248 CXFA_Items* pItems =
249 pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
250 CXFA_Node* pText = pItems ? pItems->GetFirstChild() : nullptr;
251 if (pText)
252 pText = pText->GetNextSibling();
253
254 WideString wsContent;
255 if (pText)
256 wsContent = pText->JSObject()->GetContent(false);
257
258 FormValueNode_SetChildContent(pValue, wsContent, XFA_Element::Text);
259 }
260 break;
261 }
262 case XFA_Element::NumericEdit: {
263 wsValue = defValue ? defValue->GetChildValueContent() : L"";
264 if (wsValue.IsEmpty())
265 break;
266
267 wsValue = pWidgetAcc->NormalizeNumStr(wsValue);
268 pDataNode->JSObject()->SetAttributeValue(
269 wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
270 CXFA_Value* pValue =
271 pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
272 0, XFA_Element::Value);
273 FormValueNode_SetChildContent(pValue, wsValue, XFA_Element::Float);
274 break;
275 }
276 default:
277 wsValue = defValue ? defValue->GetChildValueContent() : L"";
278 if (wsValue.IsEmpty())
279 break;
280
281 pDataNode->JSObject()->SetAttributeValue(
282 wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
283 break;
284 }
285 return;
286 }
287
288 WideString wsXMLValue = pDataNode->JSObject()->GetContent(false);
289 WideString wsNormalizeValue = pWidgetAcc->GetNormalizeDataValue(wsXMLValue);
290
291 pDataNode->JSObject()->SetAttributeValue(wsNormalizeValue, wsXMLValue, false,
292 false);
293 switch (eUIType) {
294 case XFA_Element::ImageEdit: {
295 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
296 XFA_Element::Image);
297 CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
298 if (image) {
299 CFX_XMLElement* pXMLDataElement =
300 static_cast<CFX_XMLElement*>(pDataNode->GetXMLMappingNode());
301 ASSERT(pXMLDataElement);
302
303 WideString wsContentType =
304 pXMLDataElement->GetString(L"xfa:contentType");
305 if (!wsContentType.IsEmpty()) {
306 pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
307 wsContentType, false, false);
308 image->SetContentType(wsContentType);
309 }
310
311 WideString wsHref = pXMLDataElement->GetString(L"href");
312 if (!wsHref.IsEmpty())
313 image->SetHref(wsHref);
314 }
315 break;
316 }
317 case XFA_Element::ChoiceList:
318 if (pWidgetAcc->IsChoiceListMultiSelect()) {
319 std::vector<CXFA_Node*> items = pDataNode->GetNodeList(
320 XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties,
321 XFA_Element::Unknown);
322 if (!items.empty()) {
323 bool single = items.size() == 1;
324 wsNormalizeValue.clear();
325
326 for (CXFA_Node* pNode : items) {
327 WideString wsItem = pNode->JSObject()->GetContent(false);
328 if (single)
329 wsItem += L"\n";
330
331 wsNormalizeValue += wsItem;
332 }
333 CXFA_ExData* exData =
334 defValue ? defValue->GetExDataIfExists() : nullptr;
335 ASSERT(exData);
336
337 exData->SetContentType(single ? L"text/plain" : L"text/xml");
338 }
339 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
340 XFA_Element::ExData);
341 } else {
342 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
343 XFA_Element::Text);
344 }
345 break;
346 case XFA_Element::CheckButton:
347 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
348 XFA_Element::Text);
349 break;
350 case XFA_Element::ExclGroup: {
351 pWidgetAcc->SetSelectedMemberByValue(wsNormalizeValue.AsStringView(),
352 false, false, false);
353 break;
354 }
355 case XFA_Element::DateTimeEdit:
356 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
357 XFA_Element::DateTime);
358 break;
359 case XFA_Element::NumericEdit: {
360 WideString wsPicture =
361 pWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind);
362 if (wsPicture.IsEmpty())
363 wsNormalizeValue = pWidgetAcc->NormalizeNumStr(wsNormalizeValue);
364
365 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
366 XFA_Element::Float);
367 break;
368 }
369 case XFA_Element::Barcode:
370 case XFA_Element::Button:
371 case XFA_Element::PasswordEdit:
372 case XFA_Element::Signature:
373 case XFA_Element::TextEdit:
374 default:
375 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
376 XFA_Element::Text);
377 break;
378 }
379 }
380
GetGlobalBinding(CXFA_Document * pDocument,uint32_t dwNameHash)381 CXFA_Node* GetGlobalBinding(CXFA_Document* pDocument, uint32_t dwNameHash) {
382 auto it = pDocument->m_rgGlobalBinding.find(dwNameHash);
383 return it != pDocument->m_rgGlobalBinding.end() ? it->second : nullptr;
384 }
385
RegisterGlobalBinding(CXFA_Document * pDocument,uint32_t dwNameHash,CXFA_Node * pDataNode)386 void RegisterGlobalBinding(CXFA_Document* pDocument,
387 uint32_t dwNameHash,
388 CXFA_Node* pDataNode) {
389 pDocument->m_rgGlobalBinding[dwNameHash] = pDataNode;
390 }
391
ScopeMatchGlobalBinding(CXFA_Node * pDataScope,uint32_t dwNameHash,XFA_Element eMatchDataNodeType,bool bUpLevel)392 CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope,
393 uint32_t dwNameHash,
394 XFA_Element eMatchDataNodeType,
395 bool bUpLevel) {
396 for (CXFA_Node *pCurDataScope = pDataScope, *pLastDataScope = nullptr;
397 pCurDataScope &&
398 pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
399 pLastDataScope = pCurDataScope,
400 pCurDataScope = pCurDataScope->GetParent()) {
401 for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
402 pDataChild;
403 pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
404 if (pDataChild == pLastDataScope ||
405 (eMatchDataNodeType != XFA_Element::DataModel &&
406 pDataChild->GetElementType() != eMatchDataNodeType) ||
407 pDataChild->HasBindItem()) {
408 continue;
409 }
410 return pDataChild;
411 }
412
413 for (CXFA_DataGroup* pDataChild =
414 pCurDataScope->GetFirstChildByClass<CXFA_DataGroup>(
415 XFA_Element::DataGroup);
416 pDataChild;
417 pDataChild = pDataChild->GetNextSameClassSibling<CXFA_DataGroup>(
418 XFA_Element::DataGroup)) {
419 CXFA_Node* pDataNode = ScopeMatchGlobalBinding(pDataChild, dwNameHash,
420 eMatchDataNodeType, false);
421 if (pDataNode)
422 return pDataNode;
423 }
424 if (!bUpLevel)
425 break;
426 }
427 return nullptr;
428 }
429
FindGlobalDataNode(CXFA_Document * pDocument,const WideString & wsName,CXFA_Node * pDataScope,XFA_Element eMatchNodeType)430 CXFA_Node* FindGlobalDataNode(CXFA_Document* pDocument,
431 const WideString& wsName,
432 CXFA_Node* pDataScope,
433 XFA_Element eMatchNodeType) {
434 if (wsName.IsEmpty())
435 return nullptr;
436
437 uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
438 CXFA_Node* pBounded = GetGlobalBinding(pDocument, dwNameHash);
439 if (!pBounded) {
440 pBounded =
441 ScopeMatchGlobalBinding(pDataScope, dwNameHash, eMatchNodeType, true);
442 if (pBounded)
443 RegisterGlobalBinding(pDocument, dwNameHash, pBounded);
444 }
445 return pBounded;
446 }
447
FindOnceDataNode(CXFA_Document * pDocument,const WideString & wsName,CXFA_Node * pDataScope,XFA_Element eMatchNodeType)448 CXFA_Node* FindOnceDataNode(CXFA_Document* pDocument,
449 const WideString& wsName,
450 CXFA_Node* pDataScope,
451 XFA_Element eMatchNodeType) {
452 if (wsName.IsEmpty())
453 return nullptr;
454
455 uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
456 CXFA_Node* pLastDataScope = nullptr;
457 for (CXFA_Node* pCurDataScope = pDataScope;
458 pCurDataScope &&
459 pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
460 pCurDataScope = pCurDataScope->GetParent()) {
461 for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
462 pDataChild;
463 pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
464 if (pDataChild == pLastDataScope || pDataChild->HasBindItem() ||
465 (eMatchNodeType != XFA_Element::DataModel &&
466 pDataChild->GetElementType() != eMatchNodeType)) {
467 continue;
468 }
469 return pDataChild;
470 }
471 pLastDataScope = pCurDataScope;
472 }
473 return nullptr;
474 }
475
FindDataRefDataNode(CXFA_Document * pDocument,const WideString & wsRef,CXFA_Node * pDataScope,XFA_Element eMatchNodeType,CXFA_Node * pTemplateNode,bool bForceBind,bool bUpLevel)476 CXFA_Node* FindDataRefDataNode(CXFA_Document* pDocument,
477 const WideString& wsRef,
478 CXFA_Node* pDataScope,
479 XFA_Element eMatchNodeType,
480 CXFA_Node* pTemplateNode,
481 bool bForceBind,
482 bool bUpLevel) {
483 uint32_t dFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_BindNew;
484 if (bUpLevel || wsRef != L"name")
485 dFlags |= (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
486
487 XFA_RESOLVENODE_RS rs;
488 pDocument->GetScriptContext()->ResolveObjects(
489 pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
490 if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeAll ||
491 rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeMidAll ||
492 rs.objects.size() > 1) {
493 return pDocument->GetNotBindNode(rs.objects);
494 }
495
496 if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeOne) {
497 CXFA_Object* pObject = !rs.objects.empty() ? rs.objects.front() : nullptr;
498 CXFA_Node* pNode = ToNode(pObject);
499 return (bForceBind || !pNode || !pNode->HasBindItem()) ? pNode : nullptr;
500 }
501 return nullptr;
502 }
503
NeedGenerateForm(CXFA_Node * pTemplateChild,bool bUseInstanceManager)504 bool NeedGenerateForm(CXFA_Node* pTemplateChild, bool bUseInstanceManager) {
505 XFA_Element eType = pTemplateChild->GetElementType();
506 if (eType == XFA_Element::Variables)
507 return true;
508 if (pTemplateChild->IsContainerNode())
509 return false;
510 if (eType == XFA_Element::Proto ||
511 (bUseInstanceManager && eType == XFA_Element::Occur)) {
512 return false;
513 }
514 return true;
515 }
516
CloneOrMergeInstanceManager(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,std::vector<CXFA_Node * > * subforms)517 CXFA_Node* CloneOrMergeInstanceManager(CXFA_Document* pDocument,
518 CXFA_Node* pFormParent,
519 CXFA_Node* pTemplateNode,
520 std::vector<CXFA_Node*>* subforms) {
521 WideString wsSubformName =
522 pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
523 WideString wsInstMgrNodeName = L"_" + wsSubformName;
524 uint32_t dwInstNameHash =
525 FX_HashCode_GetW(wsInstMgrNodeName.AsStringView(), false);
526 CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance(
527 pDocument, XFA_Element::InstanceManager, dwInstNameHash, pFormParent);
528 if (pExistingNode) {
529 uint32_t dwNameHash = pTemplateNode->GetNameHash();
530 for (CXFA_Node* pNode = pExistingNode->GetNextSibling(); pNode;) {
531 XFA_Element eCurType = pNode->GetElementType();
532 if (eCurType == XFA_Element::InstanceManager)
533 break;
534
535 if ((eCurType != XFA_Element::Subform) &&
536 (eCurType != XFA_Element::SubformSet)) {
537 pNode = pNode->GetNextSibling();
538 continue;
539 }
540 if (dwNameHash != pNode->GetNameHash())
541 break;
542
543 CXFA_Node* pNextNode = pNode->GetNextSibling();
544 pFormParent->RemoveChild(pNode, true);
545 subforms->push_back(pNode);
546 pNode = pNextNode;
547 }
548 pFormParent->RemoveChild(pExistingNode, true);
549 pFormParent->InsertChild(pExistingNode, nullptr);
550 pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode);
551 pExistingNode->SetTemplateNode(pTemplateNode);
552 return pExistingNode;
553 }
554
555 CXFA_Node* pNewNode =
556 pDocument->CreateNode(XFA_PacketType::Form, XFA_Element::InstanceManager);
557 wsInstMgrNodeName =
558 L"_" + pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
559 pNewNode->JSObject()->SetCData(XFA_Attribute::Name, wsInstMgrNodeName, false,
560 false);
561 pFormParent->InsertChild(pNewNode, nullptr);
562 pNewNode->SetTemplateNode(pTemplateNode);
563 return pNewNode;
564 }
565
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_AttributeEnum & eBindMatch,bool bUpLevel)566 CXFA_Node* FindMatchingDataNode(
567 CXFA_Document* pDocument,
568 CXFA_Node* pTemplateNode,
569 CXFA_Node* pDataScope,
570 bool& bAccessedDataDOM,
571 bool bForceBind,
572 CXFA_NodeIteratorTemplate<CXFA_Node,
573 CXFA_TraverseStrategy_XFAContainerNode>*
574 pIterator,
575 bool& bSelfMatch,
576 XFA_AttributeEnum& eBindMatch,
577 bool bUpLevel) {
578 CXFA_Node* pResult = nullptr;
579 CXFA_Node* pCurTemplateNode = pIterator->GetCurrent();
580 while (pCurTemplateNode) {
581 XFA_Element eMatchNodeType;
582 switch (pCurTemplateNode->GetElementType()) {
583 case XFA_Element::Subform:
584 eMatchNodeType = XFA_Element::DataGroup;
585 break;
586 case XFA_Element::Field: {
587 eMatchNodeType = XFA_FieldIsMultiListBox(pCurTemplateNode)
588 ? XFA_Element::DataGroup
589 : XFA_Element::DataValue;
590 } break;
591 case XFA_Element::ExclGroup:
592 eMatchNodeType = XFA_Element::DataValue;
593 break;
594 default:
595 pCurTemplateNode = pIterator->MoveToNext();
596 continue;
597 }
598
599 CXFA_Occur* pTemplateNodeOccur =
600 pCurTemplateNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
601 if (pTemplateNodeOccur) {
602 int32_t iMin;
603 int32_t iMax;
604 int32_t iInit;
605 std::tie(iMin, iMax, iInit) = pTemplateNodeOccur->GetOccurInfo();
606 if (iMax == 0) {
607 pCurTemplateNode = pIterator->MoveToNext();
608 continue;
609 }
610 }
611
612 CXFA_Bind* pTemplateNodeBind =
613 pCurTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind);
614 XFA_AttributeEnum eMatch =
615 pTemplateNodeBind
616 ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
617 : XFA_AttributeEnum::Once;
618 eBindMatch = eMatch;
619 switch (eMatch) {
620 case XFA_AttributeEnum::None:
621 pCurTemplateNode = pIterator->MoveToNext();
622 continue;
623 case XFA_AttributeEnum::Global:
624 bAccessedDataDOM = true;
625 if (!bForceBind) {
626 pCurTemplateNode = pIterator->MoveToNext();
627 continue;
628 }
629 if (eMatchNodeType == XFA_Element::DataValue ||
630 (eMatchNodeType == XFA_Element::DataGroup &&
631 XFA_FieldIsMultiListBox(pTemplateNodeBind))) {
632 CXFA_Node* pGlobalBindNode = FindGlobalDataNode(
633 pDocument,
634 pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
635 pDataScope, eMatchNodeType);
636 if (!pGlobalBindNode) {
637 pCurTemplateNode = pIterator->MoveToNext();
638 continue;
639 }
640 pResult = pGlobalBindNode;
641 break;
642 }
643 case XFA_AttributeEnum::Once: {
644 bAccessedDataDOM = true;
645 CXFA_Node* pOnceBindNode = FindOnceDataNode(
646 pDocument,
647 pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
648 pDataScope, eMatchNodeType);
649 if (!pOnceBindNode) {
650 pCurTemplateNode = pIterator->MoveToNext();
651 continue;
652 }
653 pResult = pOnceBindNode;
654 break;
655 }
656 case XFA_AttributeEnum::DataRef: {
657 bAccessedDataDOM = true;
658 CXFA_Node* pDataRefBindNode = FindDataRefDataNode(
659 pDocument,
660 pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref),
661 pDataScope, eMatchNodeType, pTemplateNode, bForceBind, bUpLevel);
662 if (pDataRefBindNode &&
663 pDataRefBindNode->GetElementType() == eMatchNodeType) {
664 pResult = pDataRefBindNode;
665 }
666 if (!pResult) {
667 pCurTemplateNode = pIterator->SkipChildrenAndMoveToNext();
668 continue;
669 }
670 break;
671 }
672 default:
673 break;
674 }
675 if (pCurTemplateNode == pTemplateNode && pResult)
676 bSelfMatch = true;
677 break;
678 }
679 return pResult;
680 }
681
SortRecurseRecord(std::vector<RecurseRecord> * rgRecords,CXFA_Node * pDataScope,bool bChoiceMode)682 void SortRecurseRecord(std::vector<RecurseRecord>* rgRecords,
683 CXFA_Node* pDataScope,
684 bool bChoiceMode) {
685 std::vector<RecurseRecord> rgResultRecord;
686 for (CXFA_Node* pNode = pDataScope->GetFirstChild(); pNode;
687 pNode = pNode->GetNextSibling()) {
688 auto it = std::find_if(rgRecords->begin(), rgRecords->end(),
689 [pNode](const RecurseRecord& record) {
690 return pNode == record.pDataChild;
691 });
692 if (it != rgRecords->end()) {
693 rgResultRecord.push_back(*it);
694 rgRecords->erase(it);
695 if (bChoiceMode)
696 break;
697 }
698 }
699 if (rgResultRecord.empty())
700 return;
701
702 if (!bChoiceMode) {
703 rgResultRecord.insert(rgResultRecord.end(), rgRecords->begin(),
704 rgRecords->end());
705 }
706 *rgRecords = rgResultRecord;
707 }
708
CopyContainer_SubformSet(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pFormParentNode,CXFA_Node * pDataScope,bool bOneInstance,bool bDataMerge)709 CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument,
710 CXFA_Node* pTemplateNode,
711 CXFA_Node* pFormParentNode,
712 CXFA_Node* pDataScope,
713 bool bOneInstance,
714 bool bDataMerge) {
715 XFA_Element eType = pTemplateNode->GetElementType();
716 CXFA_Node* pOccurNode = nullptr;
717 CXFA_Node* pFirstInstance = nullptr;
718 bool bUseInstanceManager =
719 pFormParentNode->GetElementType() != XFA_Element::Area;
720 CXFA_Node* pInstMgrNode = nullptr;
721 std::vector<CXFA_Node*> subformArray;
722 std::vector<CXFA_Node*>* pSearchArray = nullptr;
723 if (!bOneInstance &&
724 (eType == XFA_Element::SubformSet || eType == XFA_Element::Subform)) {
725 pInstMgrNode = bUseInstanceManager ? CloneOrMergeInstanceManager(
726 pDocument, pFormParentNode,
727 pTemplateNode, &subformArray)
728 : nullptr;
729 if (CXFA_Occur* pOccurTemplateNode =
730 pTemplateNode->GetFirstChildByClass<CXFA_Occur>(
731 XFA_Element::Occur)) {
732 pOccurNode = pInstMgrNode ? XFA_NodeMerge_CloneOrMergeContainer(
733 pDocument, pInstMgrNode,
734 pOccurTemplateNode, false, nullptr)
735 : pOccurTemplateNode;
736 } else if (pInstMgrNode) {
737 pOccurNode =
738 pInstMgrNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
739 if (pOccurNode)
740 pOccurNode->ClearFlag(XFA_NodeFlag_UnusedNode);
741 }
742 if (pInstMgrNode) {
743 pInstMgrNode->SetFlag(XFA_NodeFlag_Initialized, true);
744 pSearchArray = &subformArray;
745 if (pFormParentNode->GetElementType() == XFA_Element::PageArea) {
746 bOneInstance = true;
747 if (subformArray.empty())
748 pSearchArray = nullptr;
749 } else if (pTemplateNode->GetNameHash() == 0 && subformArray.empty()) {
750 pSearchArray = nullptr;
751 }
752 }
753 }
754
755 int32_t iMax = 1;
756 int32_t iInit = 1;
757 int32_t iMin = 1;
758 if (!bOneInstance && pOccurNode) {
759 std::tie(iMin, iMax, iInit) =
760 static_cast<CXFA_Occur*>(pOccurNode)->GetOccurInfo();
761 }
762
763 XFA_AttributeEnum eRelation =
764 eType == XFA_Element::SubformSet
765 ? pTemplateNode->JSObject()->GetEnum(XFA_Attribute::Relation)
766 : XFA_AttributeEnum::Ordered;
767 int32_t iCurRepeatIndex = 0;
768 XFA_AttributeEnum eParentBindMatch = XFA_AttributeEnum::None;
769 if (bDataMerge) {
770 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
771 sNodeIterator(pTemplateNode);
772 bool bAccessedDataDOM = false;
773 if (eType == XFA_Element::SubformSet || eType == XFA_Element::Area) {
774 sNodeIterator.MoveToNext();
775 } else {
776 std::map<CXFA_Node*, CXFA_Node*> subformMapArray;
777 std::vector<CXFA_Node*> nodeArray;
778 for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) {
779 bool bSelfMatch = false;
780 XFA_AttributeEnum eBindMatch = XFA_AttributeEnum::None;
781 CXFA_Node* pDataNode = FindMatchingDataNode(
782 pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, false,
783 &sNodeIterator, bSelfMatch, eBindMatch, true);
784 if (!pDataNode || sNodeIterator.GetCurrent() != pTemplateNode)
785 break;
786
787 eParentBindMatch = eBindMatch;
788 CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer(
789 pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
790 if (!pFirstInstance)
791 pFirstInstance = pSubformNode;
792
793 CreateDataBinding(pSubformNode, pDataNode, true);
794 ASSERT(pSubformNode);
795 subformMapArray[pSubformNode] = pDataNode;
796 nodeArray.push_back(pSubformNode);
797 }
798
799 for (CXFA_Node* pSubform : nodeArray) {
800 CXFA_Node* pDataNode = nullptr;
801 auto it = subformMapArray.find(pSubform);
802 if (it != subformMapArray.end())
803 pDataNode = it->second;
804 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
805 pTemplateChild;
806 pTemplateChild = pTemplateChild->GetNextSibling()) {
807 if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
808 XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubform,
809 pTemplateChild, true, nullptr);
810 } else if (pTemplateChild->IsContainerNode()) {
811 pDocument->DataMerge_CopyContainer(pTemplateChild, pSubform,
812 pDataNode, false, true, false);
813 }
814 }
815 }
816 subformMapArray.clear();
817 }
818
819 for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) {
820 bool bSelfMatch = false;
821 XFA_AttributeEnum eBindMatch = XFA_AttributeEnum::None;
822 if (!FindMatchingDataNode(pDocument, pTemplateNode, pDataScope,
823 bAccessedDataDOM, false, &sNodeIterator,
824 bSelfMatch, eBindMatch, true)) {
825 break;
826 }
827 if (eBindMatch == XFA_AttributeEnum::DataRef &&
828 eParentBindMatch == XFA_AttributeEnum::DataRef) {
829 break;
830 }
831
832 if (eRelation == XFA_AttributeEnum::Choice ||
833 eRelation == XFA_AttributeEnum::Unordered) {
834 CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
835 pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
836 ASSERT(pSubformSetNode);
837 if (!pFirstInstance)
838 pFirstInstance = pSubformSetNode;
839
840 std::vector<RecurseRecord> rgItemMatchList;
841 std::vector<CXFA_Node*> rgItemUnmatchList;
842 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
843 pTemplateChild;
844 pTemplateChild = pTemplateChild->GetNextSibling()) {
845 if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
846 XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
847 pTemplateChild, true, nullptr);
848 } else if (pTemplateChild->IsContainerNode()) {
849 bSelfMatch = false;
850 eBindMatch = XFA_AttributeEnum::None;
851 if (eRelation != XFA_AttributeEnum::Ordered) {
852 CXFA_NodeIteratorTemplate<CXFA_Node,
853 CXFA_TraverseStrategy_XFAContainerNode>
854 sChildIter(pTemplateChild);
855 CXFA_Node* pDataMatch = FindMatchingDataNode(
856 pDocument, pTemplateChild, pDataScope, bAccessedDataDOM,
857 false, &sChildIter, bSelfMatch, eBindMatch, true);
858 if (pDataMatch) {
859 RecurseRecord sNewRecord = {pTemplateChild, pDataMatch};
860 if (bSelfMatch)
861 rgItemMatchList.insert(rgItemMatchList.begin(), sNewRecord);
862 else
863 rgItemMatchList.push_back(sNewRecord);
864 } else {
865 rgItemUnmatchList.push_back(pTemplateChild);
866 }
867 } else {
868 rgItemUnmatchList.push_back(pTemplateChild);
869 }
870 }
871 }
872
873 switch (eRelation) {
874 case XFA_AttributeEnum::Choice: {
875 ASSERT(!rgItemMatchList.empty());
876 SortRecurseRecord(&rgItemMatchList, pDataScope, true);
877 pDocument->DataMerge_CopyContainer(
878 rgItemMatchList.front().pTemplateChild, pSubformSetNode,
879 pDataScope, false, true, true);
880 break;
881 }
882 case XFA_AttributeEnum::Unordered: {
883 if (!rgItemMatchList.empty()) {
884 SortRecurseRecord(&rgItemMatchList, pDataScope, false);
885 for (const auto& matched : rgItemMatchList) {
886 pDocument->DataMerge_CopyContainer(matched.pTemplateChild,
887 pSubformSetNode, pDataScope,
888 false, true, true);
889 }
890 }
891 for (auto* unmatched : rgItemUnmatchList) {
892 pDocument->DataMerge_CopyContainer(unmatched, pSubformSetNode,
893 pDataScope, false, true, true);
894 }
895 break;
896 }
897 default:
898 break;
899 }
900 } else {
901 CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
902 pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
903 ASSERT(pSubformSetNode);
904 if (!pFirstInstance)
905 pFirstInstance = pSubformSetNode;
906
907 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
908 pTemplateChild;
909 pTemplateChild = pTemplateChild->GetNextSibling()) {
910 if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
911 XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
912 pTemplateChild, true, nullptr);
913 } else if (pTemplateChild->IsContainerNode()) {
914 pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode,
915 pDataScope, false, true, true);
916 }
917 }
918 }
919 }
920
921 if (iCurRepeatIndex == 0 && bAccessedDataDOM == false) {
922 int32_t iLimit = iMax;
923 if (pInstMgrNode && pTemplateNode->GetNameHash() == 0) {
924 iLimit = pdfium::CollectionSize<int32_t>(subformArray);
925 if (iLimit < iMin)
926 iLimit = iInit;
927 }
928
929 for (; (iLimit < 0 || iCurRepeatIndex < iLimit); iCurRepeatIndex++) {
930 if (pInstMgrNode) {
931 if (pSearchArray && pSearchArray->empty()) {
932 if (pTemplateNode->GetNameHash() != 0)
933 break;
934 pSearchArray = nullptr;
935 }
936 } else if (!XFA_DataMerge_FindFormDOMInstance(
937 pDocument, pTemplateNode->GetElementType(),
938 pTemplateNode->GetNameHash(), pFormParentNode)) {
939 break;
940 }
941 CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer(
942 pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
943 ASSERT(pSubformNode);
944 if (!pFirstInstance)
945 pFirstInstance = pSubformNode;
946
947 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
948 pTemplateChild;
949 pTemplateChild = pTemplateChild->GetNextSibling()) {
950 if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
951 XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformNode,
952 pTemplateChild, true, nullptr);
953 } else if (pTemplateChild->IsContainerNode()) {
954 pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformNode,
955 pDataScope, false, true, true);
956 }
957 }
958 }
959 }
960 }
961
962 int32_t iMinimalLimit = iCurRepeatIndex == 0 ? iInit : iMin;
963 for (; iCurRepeatIndex < iMinimalLimit; iCurRepeatIndex++) {
964 CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
965 pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
966 ASSERT(pSubformSetNode);
967 if (!pFirstInstance)
968 pFirstInstance = pSubformSetNode;
969
970 bool bFound = false;
971 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
972 pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
973 if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
974 XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
975 pTemplateChild, true, nullptr);
976 } else if (pTemplateChild->IsContainerNode()) {
977 if (bFound && eRelation == XFA_AttributeEnum::Choice)
978 continue;
979
980 pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode,
981 pDataScope, false, bDataMerge, true);
982 bFound = true;
983 }
984 }
985 }
986 return pFirstInstance;
987 }
988
CopyContainer_Field(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bDataMerge,bool bUpLevel)989 CXFA_Node* CopyContainer_Field(CXFA_Document* pDocument,
990 CXFA_Node* pTemplateNode,
991 CXFA_Node* pFormNode,
992 CXFA_Node* pDataScope,
993 bool bDataMerge,
994 bool bUpLevel) {
995 CXFA_Node* pFieldNode = XFA_NodeMerge_CloneOrMergeContainer(
996 pDocument, pFormNode, pTemplateNode, false, nullptr);
997 ASSERT(pFieldNode);
998 for (CXFA_Node* pTemplateChildNode = pTemplateNode->GetFirstChild();
999 pTemplateChildNode;
1000 pTemplateChildNode = pTemplateChildNode->GetNextSibling()) {
1001 if (NeedGenerateForm(pTemplateChildNode, true)) {
1002 XFA_NodeMerge_CloneOrMergeContainer(pDocument, pFieldNode,
1003 pTemplateChildNode, true, nullptr);
1004 } else if (pTemplateNode->GetElementType() == XFA_Element::ExclGroup &&
1005 pTemplateChildNode->IsContainerNode()) {
1006 if (pTemplateChildNode->GetElementType() == XFA_Element::Field) {
1007 CopyContainer_Field(pDocument, pTemplateChildNode, pFieldNode, nullptr,
1008 false, true);
1009 }
1010 }
1011 }
1012 if (bDataMerge) {
1013 bool bAccessedDataDOM = false;
1014 bool bSelfMatch = false;
1015 XFA_AttributeEnum eBindMatch;
1016 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
1017 sNodeIter(pTemplateNode);
1018 CXFA_Node* pDataNode = FindMatchingDataNode(
1019 pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, true,
1020 &sNodeIter, bSelfMatch, eBindMatch, bUpLevel);
1021 if (pDataNode)
1022 CreateDataBinding(pFieldNode, pDataNode, true);
1023 } else {
1024 FormValueNode_MatchNoneCreateChild(pFieldNode);
1025 }
1026 return pFieldNode;
1027 }
1028
MaybeCreateDataNode(CXFA_Document * pDocument,CXFA_Node * pDataParent,XFA_Element eNodeType,const WideString & wsName)1029 CXFA_Node* MaybeCreateDataNode(CXFA_Document* pDocument,
1030 CXFA_Node* pDataParent,
1031 XFA_Element eNodeType,
1032 const WideString& wsName) {
1033 if (!pDataParent)
1034 return nullptr;
1035
1036 CXFA_Node* pParentDDNode = pDataParent->GetDataDescriptionNode();
1037 if (!pParentDDNode) {
1038 CXFA_Node* pDataNode =
1039 pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
1040 pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false);
1041 pDataNode->CreateXMLMappingNode();
1042 pDataParent->InsertChild(pDataNode, nullptr);
1043 pDataNode->SetFlag(XFA_NodeFlag_Initialized, false);
1044 return pDataNode;
1045 }
1046
1047 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup> sIterator(
1048 pParentDDNode);
1049 for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
1050 pDDGroupNode = sIterator.MoveToNext()) {
1051 if (pDDGroupNode != pParentDDNode) {
1052 if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
1053 continue;
1054
1055 Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
1056 if (!ns || *ns != L"http://ns.adobe.com/data-description/")
1057 continue;
1058 }
1059
1060 CXFA_Node* pDDNode =
1061 pDDGroupNode->GetFirstChildByName(wsName.AsStringView());
1062 if (!pDDNode)
1063 continue;
1064 if (pDDNode->GetElementType() != eNodeType)
1065 break;
1066
1067 CXFA_Node* pDataNode =
1068 pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
1069 pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false);
1070 pDataNode->CreateXMLMappingNode();
1071 if (eNodeType == XFA_Element::DataValue &&
1072 pDDNode->JSObject()->GetEnum(XFA_Attribute::Contains) ==
1073 XFA_AttributeEnum::MetaData) {
1074 pDataNode->JSObject()->SetEnum(XFA_Attribute::Contains,
1075 XFA_AttributeEnum::MetaData, false);
1076 }
1077 pDataParent->InsertChild(pDataNode, nullptr);
1078 pDataNode->SetDataDescriptionNode(pDDNode);
1079 pDataNode->SetFlag(XFA_NodeFlag_Initialized, false);
1080 return pDataNode;
1081 }
1082 return nullptr;
1083 }
1084
UpdateBindingRelations(CXFA_Document * pDocument,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bDataRef,bool bParentDataRef)1085 void UpdateBindingRelations(CXFA_Document* pDocument,
1086 CXFA_Node* pFormNode,
1087 CXFA_Node* pDataScope,
1088 bool bDataRef,
1089 bool bParentDataRef) {
1090 bool bMatchRef = true;
1091 XFA_Element eType = pFormNode->GetElementType();
1092 CXFA_Node* pDataNode = pFormNode->GetBindData();
1093 if (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup ||
1094 eType == XFA_Element::Field) {
1095 CXFA_Node* pTemplateNode = pFormNode->GetTemplateNodeIfExists();
1096 CXFA_Bind* pTemplateNodeBind =
1097 pTemplateNode
1098 ? pTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind)
1099 : nullptr;
1100 XFA_AttributeEnum eMatch =
1101 pTemplateNodeBind
1102 ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
1103 : XFA_AttributeEnum::Once;
1104 switch (eMatch) {
1105 case XFA_AttributeEnum::None:
1106 if (!bDataRef || bParentDataRef)
1107 FormValueNode_MatchNoneCreateChild(pFormNode);
1108 break;
1109 case XFA_AttributeEnum::Once:
1110 if (!bDataRef || bParentDataRef) {
1111 if (!pDataNode) {
1112 if (pFormNode->GetNameHash() != 0 &&
1113 pFormNode->JSObject()->GetEnum(XFA_Attribute::Scope) !=
1114 XFA_AttributeEnum::None) {
1115 XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1116 XFA_FieldIsMultiListBox(pFormNode))
1117 ? XFA_Element::DataGroup
1118 : XFA_Element::DataValue;
1119 pDataNode = MaybeCreateDataNode(
1120 pDocument, pDataScope, eDataNodeType,
1121 WideString(
1122 pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1123 if (pDataNode)
1124 CreateDataBinding(pFormNode, pDataNode, false);
1125 }
1126 if (!pDataNode)
1127 FormValueNode_MatchNoneCreateChild(pFormNode);
1128
1129 } else {
1130 CXFA_Node* pDataParent = pDataNode->GetParent();
1131 if (pDataParent != pDataScope) {
1132 ASSERT(pDataParent);
1133 pDataParent->RemoveChild(pDataNode, true);
1134 pDataScope->InsertChild(pDataNode, nullptr);
1135 }
1136 }
1137 }
1138 break;
1139 case XFA_AttributeEnum::Global:
1140 if (!bDataRef || bParentDataRef) {
1141 uint32_t dwNameHash = pFormNode->GetNameHash();
1142 if (dwNameHash != 0 && !pDataNode) {
1143 pDataNode = GetGlobalBinding(pDocument, dwNameHash);
1144 if (!pDataNode) {
1145 XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1146 XFA_FieldIsMultiListBox(pFormNode))
1147 ? XFA_Element::DataGroup
1148 : XFA_Element::DataValue;
1149 CXFA_Node* pRecordNode =
1150 ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record));
1151 pDataNode = MaybeCreateDataNode(
1152 pDocument, pRecordNode, eDataNodeType,
1153 WideString(
1154 pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1155 if (pDataNode) {
1156 CreateDataBinding(pFormNode, pDataNode, false);
1157 RegisterGlobalBinding(pDocument, pFormNode->GetNameHash(),
1158 pDataNode);
1159 }
1160 } else {
1161 CreateDataBinding(pFormNode, pDataNode, true);
1162 }
1163 }
1164 if (!pDataNode)
1165 FormValueNode_MatchNoneCreateChild(pFormNode);
1166 }
1167 break;
1168 case XFA_AttributeEnum::DataRef: {
1169 bMatchRef = bDataRef;
1170 bParentDataRef = true;
1171 if (!pDataNode && bDataRef) {
1172 WideString wsRef =
1173 pTemplateNodeBind
1174 ? pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref)
1175 : L"";
1176 uint32_t dFlags =
1177 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_CreateNode;
1178 XFA_RESOLVENODE_RS rs;
1179 pDocument->GetScriptContext()->ResolveObjects(
1180 pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
1181 CXFA_Object* pObject =
1182 !rs.objects.empty() ? rs.objects.front() : nullptr;
1183 pDataNode = ToNode(pObject);
1184 if (pDataNode) {
1185 CreateDataBinding(pFormNode, pDataNode,
1186 rs.dwFlags == XFA_ResolveNode_RSType_ExistNodes);
1187 } else {
1188 FormValueNode_MatchNoneCreateChild(pFormNode);
1189 }
1190 }
1191 break;
1192 }
1193 default:
1194 break;
1195 }
1196 }
1197
1198 if (bMatchRef &&
1199 (eType == XFA_Element::Subform || eType == XFA_Element::SubformSet ||
1200 eType == XFA_Element::Area || eType == XFA_Element::PageArea ||
1201 eType == XFA_Element::PageSet)) {
1202 for (CXFA_Node* pFormChild = pFormNode->GetFirstChild(); pFormChild;
1203 pFormChild = pFormChild->GetNextSibling()) {
1204 if (!pFormChild->IsContainerNode())
1205 continue;
1206 if (pFormChild->IsUnusedNode())
1207 continue;
1208
1209 UpdateBindingRelations(pDocument, pFormChild,
1210 pDataNode ? pDataNode : pDataScope, bDataRef,
1211 bParentDataRef);
1212 }
1213 }
1214 }
1215
UpdateDataRelation(CXFA_Node * pDataNode,CXFA_Node * pDataDescriptionNode)1216 void UpdateDataRelation(CXFA_Node* pDataNode, CXFA_Node* pDataDescriptionNode) {
1217 ASSERT(pDataDescriptionNode);
1218 for (CXFA_Node* pDataChild = pDataNode->GetFirstChild(); pDataChild;
1219 pDataChild = pDataChild->GetNextSibling()) {
1220 uint32_t dwNameHash = pDataChild->GetNameHash();
1221 if (!dwNameHash)
1222 continue;
1223
1224 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup>
1225 sIterator(pDataDescriptionNode);
1226 for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
1227 pDDGroupNode = sIterator.MoveToNext()) {
1228 if (pDDGroupNode != pDataDescriptionNode) {
1229 if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
1230 continue;
1231
1232 Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
1233 if (!ns || *ns != L"http://ns.adobe.com/data-description/")
1234 continue;
1235 }
1236
1237 CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(dwNameHash);
1238 if (!pDDNode)
1239 continue;
1240 if (pDDNode->GetElementType() != pDataChild->GetElementType())
1241 break;
1242
1243 pDataChild->SetDataDescriptionNode(pDDNode);
1244 UpdateDataRelation(pDataChild, pDDNode);
1245 break;
1246 }
1247 }
1248 }
1249
1250 } // namespace
1251
XFA_DataMerge_FindFormDOMInstance(CXFA_Document * pDocument,XFA_Element eType,uint32_t dwNameHash,CXFA_Node * pFormParent)1252 CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument,
1253 XFA_Element eType,
1254 uint32_t dwNameHash,
1255 CXFA_Node* pFormParent) {
1256 CXFA_Node* pFormChild = pFormParent->GetFirstChild();
1257 for (; pFormChild; pFormChild = pFormChild->GetNextSibling()) {
1258 if (pFormChild->GetElementType() == eType &&
1259 pFormChild->GetNameHash() == dwNameHash && pFormChild->IsUnusedNode()) {
1260 return pFormChild;
1261 }
1262 }
1263 return nullptr;
1264 }
1265
XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,bool bRecursive,std::vector<CXFA_Node * > * pSubformArray)1266 CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(
1267 CXFA_Document* pDocument,
1268 CXFA_Node* pFormParent,
1269 CXFA_Node* pTemplateNode,
1270 bool bRecursive,
1271 std::vector<CXFA_Node*>* pSubformArray) {
1272 CXFA_Node* pExistingNode = nullptr;
1273 if (!pSubformArray) {
1274 pExistingNode = XFA_DataMerge_FindFormDOMInstance(
1275 pDocument, pTemplateNode->GetElementType(),
1276 pTemplateNode->GetNameHash(), pFormParent);
1277 } else if (!pSubformArray->empty()) {
1278 pExistingNode = pSubformArray->front();
1279 pSubformArray->erase(pSubformArray->begin());
1280 }
1281 if (pExistingNode) {
1282 if (pSubformArray) {
1283 pFormParent->InsertChild(pExistingNode, nullptr);
1284 } else if (pExistingNode->IsContainerNode()) {
1285 pFormParent->RemoveChild(pExistingNode, true);
1286 pFormParent->InsertChild(pExistingNode, nullptr);
1287 }
1288 pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode);
1289 pExistingNode->SetTemplateNode(pTemplateNode);
1290 if (bRecursive && pExistingNode->GetElementType() != XFA_Element::Items) {
1291 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1292 pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1293 if (NeedGenerateForm(pTemplateChild, true)) {
1294 XFA_NodeMerge_CloneOrMergeContainer(
1295 pDocument, pExistingNode, pTemplateChild, bRecursive, nullptr);
1296 }
1297 }
1298 }
1299 pExistingNode->SetFlag(XFA_NodeFlag_Initialized, true);
1300 return pExistingNode;
1301 }
1302
1303 CXFA_Node* pNewNode = pTemplateNode->CloneTemplateToForm(false);
1304 pFormParent->InsertChild(pNewNode, nullptr);
1305 if (bRecursive) {
1306 for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1307 pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1308 if (NeedGenerateForm(pTemplateChild, true)) {
1309 CXFA_Node* pNewChild = pTemplateChild->CloneTemplateToForm(true);
1310 pNewNode->InsertChild(pNewChild, nullptr);
1311 }
1312 }
1313 }
1314 return pNewNode;
1315 }
1316
XFA_DataMerge_FindDataScope(CXFA_Node * pParentFormNode)1317 CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode) {
1318 for (CXFA_Node* pRootBoundNode = pParentFormNode;
1319 pRootBoundNode && pRootBoundNode->IsContainerNode();
1320 pRootBoundNode = pRootBoundNode->GetParent()) {
1321 CXFA_Node* pDataScope = pRootBoundNode->GetBindData();
1322 if (pDataScope)
1323 return pDataScope;
1324 }
1325 return ToNode(
1326 pParentFormNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Data));
1327 }
1328
DataMerge_CopyContainer(CXFA_Node * pTemplateNode,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bOneInstance,bool bDataMerge,bool bUpLevel)1329 CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode,
1330 CXFA_Node* pFormNode,
1331 CXFA_Node* pDataScope,
1332 bool bOneInstance,
1333 bool bDataMerge,
1334 bool bUpLevel) {
1335 switch (pTemplateNode->GetElementType()) {
1336 case XFA_Element::SubformSet:
1337 case XFA_Element::Subform:
1338 case XFA_Element::Area:
1339 case XFA_Element::PageArea:
1340 return CopyContainer_SubformSet(this, pTemplateNode, pFormNode,
1341 pDataScope, bOneInstance, bDataMerge);
1342 case XFA_Element::ExclGroup:
1343 case XFA_Element::Field:
1344 case XFA_Element::Draw:
1345 case XFA_Element::ContentArea:
1346 return CopyContainer_Field(this, pTemplateNode, pFormNode, pDataScope,
1347 bDataMerge, bUpLevel);
1348 case XFA_Element::PageSet:
1349 case XFA_Element::Variables:
1350 break;
1351 default:
1352 NOTREACHED();
1353 break;
1354 }
1355 return nullptr;
1356 }
1357
DataMerge_UpdateBindingRelations(CXFA_Node * pFormUpdateRoot)1358 void CXFA_Document::DataMerge_UpdateBindingRelations(
1359 CXFA_Node* pFormUpdateRoot) {
1360 CXFA_Node* pDataScope =
1361 XFA_DataMerge_FindDataScope(pFormUpdateRoot->GetParent());
1362 if (!pDataScope)
1363 return;
1364
1365 UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, false, false);
1366 UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, true, false);
1367 }
1368
GetNotBindNode(const std::vector<CXFA_Object * > & arrayObjects)1369 CXFA_Node* CXFA_Document::GetNotBindNode(
1370 const std::vector<CXFA_Object*>& arrayObjects) {
1371 for (CXFA_Object* pObject : arrayObjects) {
1372 CXFA_Node* pNode = pObject->AsNode();
1373 if (pNode && !pNode->HasBindItem())
1374 return pNode;
1375 }
1376 return nullptr;
1377 }
1378
DoDataMerge()1379 void CXFA_Document::DoDataMerge() {
1380 CXFA_Node* pDatasetsRoot = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
1381 if (!pDatasetsRoot) {
1382 CFX_XMLElement* pDatasetsXMLNode = new CFX_XMLElement(L"xfa:datasets");
1383 pDatasetsXMLNode->SetString(L"xmlns:xfa",
1384 L"http://www.xfa.org/schema/xfa-data/1.0/");
1385 pDatasetsRoot =
1386 CreateNode(XFA_PacketType::Datasets, XFA_Element::DataModel);
1387 pDatasetsRoot->JSObject()->SetCData(XFA_Attribute::Name, L"datasets", false,
1388 false);
1389 m_pRootNode->GetXMLMappingNode()->InsertChildNode(pDatasetsXMLNode);
1390 m_pRootNode->InsertChild(pDatasetsRoot, nullptr);
1391 pDatasetsRoot->SetXMLMappingNode(pDatasetsXMLNode);
1392 }
1393 CXFA_Node *pDataRoot = nullptr, *pDDRoot = nullptr;
1394 WideString wsDatasetsURI =
1395 pDatasetsRoot->JSObject()->TryNamespace().value_or(WideString());
1396 for (CXFA_Node* pChildNode = pDatasetsRoot->GetFirstChild(); pChildNode;
1397 pChildNode = pChildNode->GetNextSibling()) {
1398 if (pChildNode->GetElementType() != XFA_Element::DataGroup)
1399 continue;
1400
1401 if (!pDDRoot && pChildNode->GetNameHash() == XFA_HASHCODE_DataDescription) {
1402 Optional<WideString> namespaceURI =
1403 pChildNode->JSObject()->TryNamespace();
1404 if (!namespaceURI)
1405 continue;
1406 if (*namespaceURI == L"http://ns.adobe.com/data-description/")
1407 pDDRoot = pChildNode;
1408 } else if (!pDataRoot && pChildNode->GetNameHash() == XFA_HASHCODE_Data) {
1409 Optional<WideString> namespaceURI =
1410 pChildNode->JSObject()->TryNamespace();
1411 if (!namespaceURI)
1412 continue;
1413 if (*namespaceURI == wsDatasetsURI)
1414 pDataRoot = pChildNode;
1415 }
1416 if (pDataRoot && pDDRoot)
1417 break;
1418 }
1419
1420 if (!pDataRoot) {
1421 CFX_XMLElement* pDataRootXMLNode = new CFX_XMLElement(L"xfa:data");
1422 pDataRoot = CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup);
1423 pDataRoot->JSObject()->SetCData(XFA_Attribute::Name, L"data", false, false);
1424 pDataRoot->SetXMLMappingNode(pDataRootXMLNode);
1425 pDatasetsRoot->InsertChild(pDataRoot, nullptr);
1426 }
1427
1428 CXFA_DataGroup* pDataTopLevel =
1429 pDataRoot->GetFirstChildByClass<CXFA_DataGroup>(XFA_Element::DataGroup);
1430 uint32_t dwNameHash = pDataTopLevel ? pDataTopLevel->GetNameHash() : 0;
1431 CXFA_Template* pTemplateRoot =
1432 m_pRootNode->GetFirstChildByClass<CXFA_Template>(XFA_Element::Template);
1433 if (!pTemplateRoot)
1434 return;
1435
1436 CXFA_Node* pTemplateChosen =
1437 dwNameHash != 0 ? pTemplateRoot->GetFirstChildByName(dwNameHash)
1438 : nullptr;
1439 if (!pTemplateChosen ||
1440 pTemplateChosen->GetElementType() != XFA_Element::Subform) {
1441 pTemplateChosen =
1442 pTemplateRoot->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
1443 }
1444 if (!pTemplateChosen)
1445 return;
1446
1447 CXFA_Form* pFormRoot =
1448 m_pRootNode->GetFirstChildByClass<CXFA_Form>(XFA_Element::Form);
1449 bool bEmptyForm = false;
1450 if (!pFormRoot) {
1451 bEmptyForm = true;
1452 pFormRoot = static_cast<CXFA_Form*>(
1453 CreateNode(XFA_PacketType::Form, XFA_Element::Form));
1454 ASSERT(pFormRoot);
1455 pFormRoot->JSObject()->SetCData(XFA_Attribute::Name, L"form", false, false);
1456 m_pRootNode->InsertChild(pFormRoot, nullptr);
1457 } else {
1458 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode>
1459 sIterator(pFormRoot);
1460 for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode;
1461 pNode = sIterator.MoveToNext()) {
1462 pNode->SetFlag(XFA_NodeFlag_UnusedNode, true);
1463 }
1464 }
1465
1466 CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1467 this, pFormRoot, pTemplateChosen, false, nullptr);
1468 ASSERT(pSubformSetNode);
1469 if (!pDataTopLevel) {
1470 WideString wsFormName =
1471 pSubformSetNode->JSObject()->GetCData(XFA_Attribute::Name);
1472 WideString wsDataTopLevelName(wsFormName.IsEmpty() ? L"form" : wsFormName);
1473 CFX_XMLElement* pDataTopLevelXMLNode =
1474 new CFX_XMLElement(wsDataTopLevelName);
1475
1476 pDataTopLevel = static_cast<CXFA_DataGroup*>(
1477 CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup));
1478 pDataTopLevel->JSObject()->SetCData(XFA_Attribute::Name, wsDataTopLevelName,
1479 false, false);
1480 pDataTopLevel->SetXMLMappingNode(pDataTopLevelXMLNode);
1481 CXFA_Node* pBeforeNode = pDataRoot->GetFirstChild();
1482 pDataRoot->InsertChild(pDataTopLevel, pBeforeNode);
1483 }
1484
1485 ASSERT(pDataTopLevel);
1486 CreateDataBinding(pSubformSetNode, pDataTopLevel, true);
1487 for (CXFA_Node* pTemplateChild = pTemplateChosen->GetFirstChild();
1488 pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1489 if (NeedGenerateForm(pTemplateChild, true)) {
1490 XFA_NodeMerge_CloneOrMergeContainer(this, pSubformSetNode, pTemplateChild,
1491 true, nullptr);
1492 } else if (pTemplateChild->IsContainerNode()) {
1493 DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, pDataTopLevel,
1494 false, true, true);
1495 }
1496 }
1497 if (pDDRoot)
1498 UpdateDataRelation(pDataRoot, pDDRoot);
1499
1500 DataMerge_UpdateBindingRelations(pSubformSetNode);
1501 CXFA_PageSet* pPageSetNode =
1502 pSubformSetNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
1503 while (pPageSetNode) {
1504 m_pPendingPageSet.push_back(pPageSetNode);
1505 CXFA_PageSet* pNextPageSetNode =
1506 pPageSetNode->GetNextSameClassSibling<CXFA_PageSet>(
1507 XFA_Element::PageSet);
1508 pSubformSetNode->RemoveChild(pPageSetNode, true);
1509 pPageSetNode = pNextPageSetNode;
1510 }
1511
1512 if (bEmptyForm)
1513 return;
1514
1515 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(
1516 pFormRoot);
1517 CXFA_Node* pNode = sIterator.MoveToNext();
1518 while (pNode) {
1519 if (pNode->IsUnusedNode()) {
1520 if (pNode->IsContainerNode() ||
1521 pNode->GetElementType() == XFA_Element::InstanceManager) {
1522 CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext();
1523 pNode->GetParent()->RemoveChild(pNode, true);
1524 pNode = pNext;
1525 } else {
1526 pNode->ClearFlag(XFA_NodeFlag_UnusedNode);
1527 pNode->SetFlag(XFA_NodeFlag_Initialized, true);
1528 pNode = sIterator.MoveToNext();
1529 }
1530 } else {
1531 pNode->SetFlag(XFA_NodeFlag_Initialized, true);
1532 pNode = sIterator.MoveToNext();
1533 }
1534 }
1535 }
1536
DoDataRemerge(bool bDoDataMerge)1537 void CXFA_Document::DoDataRemerge(bool bDoDataMerge) {
1538 CXFA_Node* pFormRoot = ToNode(GetXFAObject(XFA_HASHCODE_Form));
1539 if (pFormRoot) {
1540 while (CXFA_Node* pNode = pFormRoot->GetFirstChild())
1541 pFormRoot->RemoveChild(pNode, true);
1542
1543 pFormRoot->SetBindingNode(nullptr);
1544 }
1545 m_rgGlobalBinding.clear();
1546
1547 if (bDoDataMerge)
1548 DoDataMerge();
1549
1550 CXFA_LayoutProcessor* pLayoutProcessor = GetLayoutProcessor();
1551 pLayoutProcessor->SetForceReLayout(true);
1552 }
1553