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