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