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