blob: 19e9ede20fdd87a1911e6ecd9084c11fa1b31868 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclaircfb19442017-04-20 13:13:04 -04007#include "xfa/fxfa/parser/cxfa_document.h"
8
Dan Sinclair80bf5822018-02-13 20:55:03 +00009#include <set>
dan sinclair13aa65a2018-04-17 21:34:18 +000010#include <utility>
Dan Sinclair80bf5822018-02-13 20:55:03 +000011
Dan Sinclaircfb19442017-04-20 13:13:04 -040012#include "core/fxcrt/fx_extension.h"
Dan Sinclair70180642018-05-02 16:02:03 +000013#include "core/fxcrt/xml/cfx_xmldocument.h"
Dan Sinclair3fff90a2017-11-01 13:12:39 +000014#include "fxjs/cfxjse_engine.h"
Tom Sepez76a1a352018-07-23 19:01:14 +000015#include "fxjs/xfa/cjx_object.h"
Lei Zhangdb3c6ce2018-05-17 02:01:42 +000016#include "third_party/base/compiler_specific.h"
Lei Zhang99f5bbb2018-10-09 21:31:28 +000017#include "third_party/base/ptr_util.h"
Dan Sinclair70180642018-05-02 16:02:03 +000018#include "xfa/fxfa/cxfa_ffdoc.h"
Dan Sinclair24ef6332017-07-24 10:52:57 -040019#include "xfa/fxfa/cxfa_ffnotify.h"
dsinclairc1515ef2016-07-20 06:16:06 -070020#include "xfa/fxfa/parser/cscript_datawindow.h"
21#include "xfa/fxfa/parser/cscript_eventpseudomodel.h"
22#include "xfa/fxfa/parser/cscript_hostpseudomodel.h"
23#include "xfa/fxfa/parser/cscript_layoutpseudomodel.h"
24#include "xfa/fxfa/parser/cscript_logpseudomodel.h"
25#include "xfa/fxfa/parser/cscript_signaturepseudomodel.h"
Dan Sinclair4a979702018-04-05 18:32:35 +000026#include "xfa/fxfa/parser/cxfa_bind.h"
Dan Sinclairdf4f30e2017-12-14 20:51:03 +000027#include "xfa/fxfa/parser/cxfa_datagroup.h"
Dan Sinclair4a979702018-04-05 18:32:35 +000028#include "xfa/fxfa/parser/cxfa_exdata.h"
29#include "xfa/fxfa/parser/cxfa_form.h"
30#include "xfa/fxfa/parser/cxfa_image.h"
Dan Sinclair51ef4a62017-12-14 20:43:53 +000031#include "xfa/fxfa/parser/cxfa_interactive.h"
Dan Sinclair4a979702018-04-05 18:32:35 +000032#include "xfa/fxfa/parser/cxfa_items.h"
dsinclair0b851ff2016-07-21 12:03:01 -070033#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
Dan Sinclairec1843d2017-03-28 16:04:41 -040034#include "xfa/fxfa/parser/cxfa_localemgr.h"
Dan Sinclairefcae5d2017-03-29 14:47:46 -040035#include "xfa/fxfa/parser/cxfa_node.h"
Dan Sinclair4a979702018-04-05 18:32:35 +000036#include "xfa/fxfa/parser/cxfa_occur.h"
37#include "xfa/fxfa/parser/cxfa_pageset.h"
Dan Sinclairdf4f30e2017-12-14 20:51:03 +000038#include "xfa/fxfa/parser/cxfa_pdf.h"
39#include "xfa/fxfa/parser/cxfa_present.h"
Dan Sinclair4a979702018-04-05 18:32:35 +000040#include "xfa/fxfa/parser/cxfa_subform.h"
41#include "xfa/fxfa/parser/cxfa_template.h"
42#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
Dan Sinclairefcae5d2017-03-29 14:47:46 -040043#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
Dan Sinclair4a979702018-04-05 18:32:35 +000044#include "xfa/fxfa/parser/cxfa_value.h"
45#include "xfa/fxfa/parser/xfa_document_datamerger_imp.h"
dsinclair31f87402016-07-20 06:34:45 -070046#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040047#include "xfa/fxfa/parser/xfa_utils.h"
48
dsinclair16280242016-07-21 12:03:47 -070049namespace {
50
Dan Sinclairf65f1d32017-11-30 21:56:00 +000051constexpr const wchar_t kTemplateNS[] =
52 L"http://www.xfa.org/schema/xfa-template/";
53
Dan Sinclair4a979702018-04-05 18:32:35 +000054struct RecurseRecord {
55 CXFA_Node* pTemplateChild;
56 CXFA_Node* pDataChild;
57};
58
59class CXFA_TraverseStrategy_DDGroup {
60 public:
61 static CXFA_Node* GetFirstChild(CXFA_Node* pDDGroupNode) {
62 return pDDGroupNode->GetFirstChildByName(XFA_HASHCODE_Group);
63 }
64 static CXFA_Node* GetNextSibling(CXFA_Node* pDDGroupNode) {
65 return pDDGroupNode->GetNextSameNameSibling(XFA_HASHCODE_Group);
66 }
67 static CXFA_Node* GetParent(CXFA_Node* pDDGroupNode) {
68 return pDDGroupNode->GetParent();
69 }
70};
71
72void FormValueNode_MatchNoneCreateChild(CXFA_Node* pFormNode) {
73 ASSERT(pFormNode->IsWidgetReady());
74 // GetUIChildNode has the side effect of creating the UI child.
75 pFormNode->GetUIChildNode();
76}
77
78CXFA_Node* FormValueNode_CreateChild(CXFA_Node* pValueNode, XFA_Element iType) {
79 CXFA_Node* pChildNode = pValueNode->GetFirstChild();
80 if (!pChildNode) {
81 if (iType == XFA_Element::Unknown)
82 return nullptr;
83
84 pChildNode =
85 pValueNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, iType);
86 }
87 return pChildNode;
88}
89
Lei Zhangec86c712018-07-30 17:38:21 +000090void FormValueNode_SetChildContent(CXFA_Node* pValueNode,
Dan Sinclair4a979702018-04-05 18:32:35 +000091 const WideString& wsContent,
Lei Zhangec86c712018-07-30 17:38:21 +000092 XFA_Element iType) {
Dan Sinclair4a979702018-04-05 18:32:35 +000093 if (!pValueNode)
Lei Zhangec86c712018-07-30 17:38:21 +000094 return;
Dan Sinclair4a979702018-04-05 18:32:35 +000095
96 ASSERT(pValueNode->GetPacketType() == XFA_PacketType::Form);
97 CXFA_Node* pChildNode = FormValueNode_CreateChild(pValueNode, iType);
98 if (!pChildNode)
Lei Zhangec86c712018-07-30 17:38:21 +000099 return;
Dan Sinclair4a979702018-04-05 18:32:35 +0000100
101 switch (pChildNode->GetObjectType()) {
102 case XFA_ObjectType::ContentNode: {
103 CXFA_Node* pContentRawDataNode = pChildNode->GetFirstChild();
104 if (!pContentRawDataNode) {
105 XFA_Element element = XFA_Element::Sharptext;
106 if (pChildNode->GetElementType() == XFA_Element::ExData) {
107 Optional<WideString> contentType =
108 pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType,
109 false);
110 if (contentType) {
111 if (*contentType == L"text/html")
112 element = XFA_Element::SharpxHTML;
113 else if (*contentType == L"text/xml")
114 element = XFA_Element::Sharpxml;
115 }
116 }
117 pContentRawDataNode = pChildNode->CreateSamePacketNode(element);
118 pChildNode->InsertChild(pContentRawDataNode, nullptr);
119 }
120 pContentRawDataNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent,
121 false, false);
122 break;
123 }
124 case XFA_ObjectType::NodeC:
125 case XFA_ObjectType::TextNode:
126 case XFA_ObjectType::NodeV: {
127 pChildNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, false,
128 false);
129 break;
130 }
131 default:
Dan Sinclair4a979702018-04-05 18:32:35 +0000132 break;
133 }
Dan Sinclair4a979702018-04-05 18:32:35 +0000134}
135
Dan Sinclair72fe14a2018-04-05 18:33:35 +0000136void MergeNodeRecurse(CXFA_Node* pDestNodeParent, CXFA_Node* pProtoNode) {
dsinclair16280242016-07-21 12:03:47 -0700137 CXFA_Node* pExistingNode = nullptr;
Dan Sinclair18a60692018-01-10 16:30:56 +0000138 for (CXFA_Node* pFormChild = pDestNodeParent->GetFirstChild(); pFormChild;
139 pFormChild = pFormChild->GetNextSibling()) {
dsinclair16280242016-07-21 12:03:47 -0700140 if (pFormChild->GetElementType() == pProtoNode->GetElementType() &&
141 pFormChild->GetNameHash() == pProtoNode->GetNameHash() &&
142 pFormChild->IsUnusedNode()) {
143 pFormChild->ClearFlag(XFA_NodeFlag_UnusedNode);
144 pExistingNode = pFormChild;
145 break;
146 }
147 }
148
149 if (pExistingNode) {
150 pExistingNode->SetTemplateNode(pProtoNode);
Dan Sinclair18a60692018-01-10 16:30:56 +0000151 for (CXFA_Node* pTemplateChild = pProtoNode->GetFirstChild();
152 pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
Dan Sinclair72fe14a2018-04-05 18:33:35 +0000153 MergeNodeRecurse(pExistingNode, pTemplateChild);
dsinclair16280242016-07-21 12:03:47 -0700154 }
155 return;
156 }
tsepezd19e9122016-11-02 15:43:18 -0700157 CXFA_Node* pNewNode = pProtoNode->Clone(true);
dsinclair16280242016-07-21 12:03:47 -0700158 pNewNode->SetTemplateNode(pProtoNode);
159 pDestNodeParent->InsertChild(pNewNode, nullptr);
160}
161
Dan Sinclair72fe14a2018-04-05 18:33:35 +0000162void MergeNode(CXFA_Node* pDestNode, CXFA_Node* pProtoNode) {
dsinclair16280242016-07-21 12:03:47 -0700163 {
164 CXFA_NodeIterator sIterator(pDestNode);
165 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
166 pNode = sIterator.MoveToNext()) {
Dan Sinclair2fa64412018-02-14 16:20:01 +0000167 pNode->SetFlag(XFA_NodeFlag_UnusedNode);
dsinclair16280242016-07-21 12:03:47 -0700168 }
169 }
170 pDestNode->SetTemplateNode(pProtoNode);
Dan Sinclair18a60692018-01-10 16:30:56 +0000171 for (CXFA_Node* pTemplateChild = pProtoNode->GetFirstChild(); pTemplateChild;
172 pTemplateChild = pTemplateChild->GetNextSibling()) {
Dan Sinclair72fe14a2018-04-05 18:33:35 +0000173 MergeNodeRecurse(pDestNode, pTemplateChild);
dsinclair16280242016-07-21 12:03:47 -0700174 }
175 {
176 CXFA_NodeIterator sIterator(pDestNode);
177 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
178 pNode = sIterator.MoveToNext()) {
179 pNode->ClearFlag(XFA_NodeFlag_UnusedNode);
180 }
181 }
182}
183
Dan Sinclair4a979702018-04-05 18:32:35 +0000184CXFA_Node* CloneOrMergeInstanceManager(CXFA_Document* pDocument,
185 CXFA_Node* pFormParent,
186 CXFA_Node* pTemplateNode,
187 std::vector<CXFA_Node*>* subforms) {
188 WideString wsSubformName =
189 pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
190 WideString wsInstMgrNodeName = L"_" + wsSubformName;
191 uint32_t dwInstNameHash =
192 FX_HashCode_GetW(wsInstMgrNodeName.AsStringView(), false);
193 CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance(
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->RemoveChild(pNode, true);
212 subforms->push_back(pNode);
213 pNode = pNextNode;
214 }
215 pFormParent->RemoveChild(pExistingNode, true);
216 pFormParent->InsertChild(pExistingNode, nullptr);
217 pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode);
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, false,
227 false);
228 pFormParent->InsertChild(pNewNode, nullptr);
229 pNewNode->SetTemplateNode(pTemplateNode);
230 return pNewNode;
231}
232
233void SortRecurseRecord(std::vector<RecurseRecord>* rgRecords,
234 CXFA_Node* pDataScope,
235 bool bChoiceMode) {
236 std::vector<RecurseRecord> rgResultRecord;
237 for (CXFA_Node* pNode = pDataScope->GetFirstChild(); pNode;
238 pNode = pNode->GetNextSibling()) {
239 auto it = std::find_if(rgRecords->begin(), rgRecords->end(),
240 [pNode](const RecurseRecord& record) {
241 return pNode == record.pDataChild;
242 });
243 if (it != rgRecords->end()) {
244 rgResultRecord.push_back(*it);
245 rgRecords->erase(it);
246 if (bChoiceMode)
247 break;
248 }
249 }
250 if (rgResultRecord.empty())
251 return;
252
253 if (!bChoiceMode) {
254 rgResultRecord.insert(rgResultRecord.end(), rgRecords->begin(),
255 rgRecords->end());
256 }
257 *rgRecords = rgResultRecord;
258}
259
260CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope,
261 uint32_t dwNameHash,
262 XFA_Element eMatchDataNodeType,
263 bool bUpLevel) {
264 for (CXFA_Node *pCurDataScope = pDataScope, *pLastDataScope = nullptr;
265 pCurDataScope &&
266 pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
267 pLastDataScope = pCurDataScope,
268 pCurDataScope = pCurDataScope->GetParent()) {
269 for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
270 pDataChild;
271 pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
272 if (pDataChild == pLastDataScope ||
273 (eMatchDataNodeType != XFA_Element::DataModel &&
274 pDataChild->GetElementType() != eMatchDataNodeType) ||
275 pDataChild->HasBindItem()) {
276 continue;
277 }
278 return pDataChild;
279 }
280
281 for (CXFA_DataGroup* pDataChild =
282 pCurDataScope->GetFirstChildByClass<CXFA_DataGroup>(
283 XFA_Element::DataGroup);
284 pDataChild;
285 pDataChild = pDataChild->GetNextSameClassSibling<CXFA_DataGroup>(
286 XFA_Element::DataGroup)) {
287 CXFA_Node* pDataNode = ScopeMatchGlobalBinding(pDataChild, dwNameHash,
288 eMatchDataNodeType, false);
289 if (pDataNode)
290 return pDataNode;
291 }
292 if (!bUpLevel)
293 break;
294 }
295 return nullptr;
296}
297
Dan Sinclair4a979702018-04-05 18:32:35 +0000298CXFA_Node* FindGlobalDataNode(CXFA_Document* pDocument,
299 const WideString& wsName,
300 CXFA_Node* pDataScope,
301 XFA_Element eMatchNodeType) {
302 if (wsName.IsEmpty())
303 return nullptr;
304
305 uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
Dan Sinclair5a552532018-04-05 19:05:11 +0000306 CXFA_Node* pBounded = pDocument->GetGlobalBinding(dwNameHash);
Dan Sinclair4a979702018-04-05 18:32:35 +0000307 if (!pBounded) {
308 pBounded =
309 ScopeMatchGlobalBinding(pDataScope, dwNameHash, eMatchNodeType, true);
310 if (pBounded)
Dan Sinclair5a552532018-04-05 19:05:11 +0000311 pDocument->RegisterGlobalBinding(dwNameHash, pBounded);
Dan Sinclair4a979702018-04-05 18:32:35 +0000312 }
313 return pBounded;
314}
315
Dan Sinclair72fe14a2018-04-05 18:33:35 +0000316CXFA_Node* FindOnceDataNode(const WideString& wsName,
Dan Sinclair4a979702018-04-05 18:32:35 +0000317 CXFA_Node* pDataScope,
318 XFA_Element eMatchNodeType) {
319 if (wsName.IsEmpty())
320 return nullptr;
321
322 uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
323 CXFA_Node* pLastDataScope = nullptr;
324 for (CXFA_Node* pCurDataScope = pDataScope;
325 pCurDataScope &&
326 pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
327 pCurDataScope = pCurDataScope->GetParent()) {
328 for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
329 pDataChild;
330 pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
331 if (pDataChild == pLastDataScope || pDataChild->HasBindItem() ||
332 (eMatchNodeType != XFA_Element::DataModel &&
333 pDataChild->GetElementType() != eMatchNodeType)) {
334 continue;
335 }
336 return pDataChild;
337 }
338 pLastDataScope = pCurDataScope;
339 }
340 return nullptr;
341}
342
343CXFA_Node* FindDataRefDataNode(CXFA_Document* pDocument,
344 const WideString& wsRef,
345 CXFA_Node* pDataScope,
346 XFA_Element eMatchNodeType,
347 CXFA_Node* pTemplateNode,
348 bool bForceBind,
349 bool bUpLevel) {
350 uint32_t dFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_BindNew;
351 if (bUpLevel || wsRef != L"name")
352 dFlags |= (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
353
354 XFA_RESOLVENODE_RS rs;
355 pDocument->GetScriptContext()->ResolveObjects(
356 pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
357 if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeAll ||
358 rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeMidAll ||
359 rs.objects.size() > 1) {
360 return pDocument->GetNotBindNode(rs.objects);
361 }
362
363 if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeOne) {
Tom Sepez1a3e1862018-08-21 22:56:37 +0000364 CXFA_Object* pObject =
365 !rs.objects.empty() ? rs.objects.front().Get() : nullptr;
Dan Sinclair4a979702018-04-05 18:32:35 +0000366 CXFA_Node* pNode = ToNode(pObject);
367 return (bForceBind || !pNode || !pNode->HasBindItem()) ? pNode : nullptr;
368 }
369 return nullptr;
370}
371
372CXFA_Node* FindMatchingDataNode(
373 CXFA_Document* pDocument,
374 CXFA_Node* pTemplateNode,
375 CXFA_Node* pDataScope,
376 bool& bAccessedDataDOM,
377 bool bForceBind,
378 CXFA_NodeIteratorTemplate<CXFA_Node,
379 CXFA_TraverseStrategy_XFAContainerNode>*
380 pIterator,
381 bool& bSelfMatch,
382 XFA_AttributeEnum& eBindMatch,
383 bool bUpLevel) {
384 CXFA_Node* pResult = nullptr;
385 CXFA_Node* pCurTemplateNode = pIterator->GetCurrent();
386 while (pCurTemplateNode) {
387 XFA_Element eMatchNodeType;
388 switch (pCurTemplateNode->GetElementType()) {
389 case XFA_Element::Subform:
390 eMatchNodeType = XFA_Element::DataGroup;
391 break;
392 case XFA_Element::Field: {
393 eMatchNodeType = XFA_FieldIsMultiListBox(pCurTemplateNode)
394 ? XFA_Element::DataGroup
395 : XFA_Element::DataValue;
396 } break;
397 case XFA_Element::ExclGroup:
398 eMatchNodeType = XFA_Element::DataValue;
399 break;
400 default:
401 pCurTemplateNode = pIterator->MoveToNext();
402 continue;
403 }
404
405 CXFA_Occur* pTemplateNodeOccur =
406 pCurTemplateNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
407 if (pTemplateNodeOccur) {
408 int32_t iMin;
409 int32_t iMax;
410 int32_t iInit;
411 std::tie(iMin, iMax, iInit) = pTemplateNodeOccur->GetOccurInfo();
412 if (iMax == 0) {
413 pCurTemplateNode = pIterator->MoveToNext();
414 continue;
415 }
416 }
417
418 CXFA_Bind* pTemplateNodeBind =
419 pCurTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind);
420 XFA_AttributeEnum eMatch =
421 pTemplateNodeBind
422 ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
423 : XFA_AttributeEnum::Once;
424 eBindMatch = eMatch;
425 switch (eMatch) {
426 case XFA_AttributeEnum::None:
427 pCurTemplateNode = pIterator->MoveToNext();
428 continue;
429 case XFA_AttributeEnum::Global:
430 bAccessedDataDOM = true;
431 if (!bForceBind) {
432 pCurTemplateNode = pIterator->MoveToNext();
433 continue;
434 }
435 if (eMatchNodeType == XFA_Element::DataValue ||
436 (eMatchNodeType == XFA_Element::DataGroup &&
437 XFA_FieldIsMultiListBox(pTemplateNodeBind))) {
438 CXFA_Node* pGlobalBindNode = FindGlobalDataNode(
439 pDocument,
440 pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
441 pDataScope, eMatchNodeType);
442 if (!pGlobalBindNode) {
443 pCurTemplateNode = pIterator->MoveToNext();
444 continue;
445 }
446 pResult = pGlobalBindNode;
447 break;
448 }
Lei Zhangdb3c6ce2018-05-17 02:01:42 +0000449 FALLTHROUGH;
Dan Sinclair4a979702018-04-05 18:32:35 +0000450 case XFA_AttributeEnum::Once: {
451 bAccessedDataDOM = true;
452 CXFA_Node* pOnceBindNode = FindOnceDataNode(
Dan Sinclair4a979702018-04-05 18:32:35 +0000453 pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
454 pDataScope, eMatchNodeType);
455 if (!pOnceBindNode) {
456 pCurTemplateNode = pIterator->MoveToNext();
457 continue;
458 }
459 pResult = pOnceBindNode;
460 break;
461 }
462 case XFA_AttributeEnum::DataRef: {
463 bAccessedDataDOM = true;
464 CXFA_Node* pDataRefBindNode = FindDataRefDataNode(
465 pDocument,
466 pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref),
467 pDataScope, eMatchNodeType, pTemplateNode, bForceBind, bUpLevel);
468 if (pDataRefBindNode &&
469 pDataRefBindNode->GetElementType() == eMatchNodeType) {
470 pResult = pDataRefBindNode;
471 }
472 if (!pResult) {
473 pCurTemplateNode = pIterator->SkipChildrenAndMoveToNext();
474 continue;
475 }
476 break;
477 }
478 default:
479 break;
480 }
481 if (pCurTemplateNode == pTemplateNode && pResult)
482 bSelfMatch = true;
483 break;
484 }
485 return pResult;
486}
487
488void CreateDataBinding(CXFA_Node* pFormNode,
489 CXFA_Node* pDataNode,
490 bool bDataToForm) {
491 pFormNode->SetBindingNode(pDataNode);
492 pDataNode->AddBindItem(pFormNode);
493 XFA_Element eType = pFormNode->GetElementType();
494 if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
495 return;
496
497 ASSERT(pFormNode->IsWidgetReady());
498 auto* defValue = pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
499 0, XFA_Element::Value);
500 if (!bDataToForm) {
501 WideString wsValue;
502 switch (pFormNode->GetFFWidgetType()) {
503 case XFA_FFWidgetType::kImageEdit: {
504 CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
505 WideString wsContentType;
506 WideString wsHref;
507 if (image) {
508 wsValue = image->GetContent();
509 wsContentType = image->GetContentType();
510 wsHref = image->GetHref();
511 }
512 CFX_XMLElement* pXMLDataElement =
Tom Sepezc9171e12018-07-26 19:34:26 +0000513 ToXMLElement(pDataNode->GetXMLMappingNode());
Dan Sinclair4a979702018-04-05 18:32:35 +0000514 ASSERT(pXMLDataElement);
Dan Sinclair4a979702018-04-05 18:32:35 +0000515 pDataNode->JSObject()->SetAttributeValue(
516 wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
517 pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
518 wsContentType, false, false);
519 if (!wsHref.IsEmpty())
dan sinclair8b0cf762018-04-16 21:24:57 +0000520 pXMLDataElement->SetAttribute(L"href", wsHref);
Dan Sinclair4a979702018-04-05 18:32:35 +0000521
522 break;
523 }
524 case XFA_FFWidgetType::kChoiceList:
525 wsValue = defValue ? defValue->GetChildValueContent() : L"";
526 if (pFormNode->IsChoiceListMultiSelect()) {
527 std::vector<WideString> wsSelTextArray =
528 pFormNode->GetSelectedItemsValue();
529 if (!wsSelTextArray.empty()) {
530 for (const auto& text : wsSelTextArray) {
531 CXFA_Node* pValue =
532 pDataNode->CreateSamePacketNode(XFA_Element::DataValue);
533 pValue->JSObject()->SetCData(XFA_Attribute::Name, L"value", false,
534 false);
535 pValue->CreateXMLMappingNode();
536 pDataNode->InsertChild(pValue, nullptr);
537 pValue->JSObject()->SetCData(XFA_Attribute::Value, text, false,
538 false);
539 }
540 } else {
Tom Sepez96b0d132018-07-25 17:04:49 +0000541 CFX_XMLElement* pElement =
542 ToXMLElement(pDataNode->GetXMLMappingNode());
543 pElement->SetAttribute(L"xfa:dataNode", L"dataGroup");
Dan Sinclair4a979702018-04-05 18:32:35 +0000544 }
545 } else if (!wsValue.IsEmpty()) {
546 pDataNode->JSObject()->SetAttributeValue(
547 wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
548 }
549 break;
550 case XFA_FFWidgetType::kCheckButton:
551 wsValue = defValue ? defValue->GetChildValueContent() : L"";
552 if (wsValue.IsEmpty())
553 break;
554
555 pDataNode->JSObject()->SetAttributeValue(
556 wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
557 break;
558 case XFA_FFWidgetType::kExclGroup: {
559 CXFA_Node* pChecked = nullptr;
560 CXFA_Node* pChild = pFormNode->GetFirstChild();
561 for (; pChild; pChild = pChild->GetNextSibling()) {
562 if (pChild->GetElementType() != XFA_Element::Field)
563 continue;
564
565 auto* pValue =
566 pChild->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
567 if (!pValue)
568 continue;
569
570 wsValue = pValue->GetChildValueContent();
571 if (wsValue.IsEmpty())
572 continue;
573
574 CXFA_Items* pItems =
575 pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
576 if (!pItems)
577 continue;
578
579 CXFA_Node* pText = pItems->GetFirstChild();
580 if (!pText)
581 continue;
582
583 WideString wsContent = pText->JSObject()->GetContent(false);
584 if (wsContent == wsValue) {
585 pChecked = pChild;
586 pDataNode->JSObject()->SetAttributeValue(wsValue, wsValue, false,
587 false);
588 pFormNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent,
589 false, false);
590 break;
591 }
592 }
593 if (!pChecked)
594 break;
595
596 pChild = pFormNode->GetFirstChild();
597 for (; pChild; pChild = pChild->GetNextSibling()) {
598 if (pChild == pChecked)
599 continue;
600 if (pChild->GetElementType() != XFA_Element::Field)
601 continue;
602
603 CXFA_Value* pValue =
604 pChild->JSObject()->GetOrCreateProperty<CXFA_Value>(
605 0, XFA_Element::Value);
606 CXFA_Items* pItems =
607 pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
608 CXFA_Node* pText = pItems ? pItems->GetFirstChild() : nullptr;
609 if (pText)
610 pText = pText->GetNextSibling();
611
612 WideString wsContent;
613 if (pText)
614 wsContent = pText->JSObject()->GetContent(false);
615
616 FormValueNode_SetChildContent(pValue, wsContent, XFA_Element::Text);
617 }
618 break;
619 }
620 case XFA_FFWidgetType::kNumericEdit: {
621 wsValue = defValue ? defValue->GetChildValueContent() : L"";
622 if (wsValue.IsEmpty())
623 break;
624
625 wsValue = pFormNode->NormalizeNumStr(wsValue);
626 pDataNode->JSObject()->SetAttributeValue(
627 wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
628 CXFA_Value* pValue =
629 pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
630 0, XFA_Element::Value);
631 FormValueNode_SetChildContent(pValue, wsValue, XFA_Element::Float);
632 break;
633 }
634 default:
635 wsValue = defValue ? defValue->GetChildValueContent() : L"";
636 if (wsValue.IsEmpty())
637 break;
638
639 pDataNode->JSObject()->SetAttributeValue(
640 wsValue, pFormNode->GetFormatDataValue(wsValue), false, false);
641 break;
642 }
643 return;
644 }
645
646 WideString wsXMLValue = pDataNode->JSObject()->GetContent(false);
647 WideString wsNormalizeValue = pFormNode->GetNormalizeDataValue(wsXMLValue);
648
649 pDataNode->JSObject()->SetAttributeValue(wsNormalizeValue, wsXMLValue, false,
650 false);
651 switch (pFormNode->GetFFWidgetType()) {
652 case XFA_FFWidgetType::kImageEdit: {
653 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
654 XFA_Element::Image);
655 CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
656 if (image) {
657 CFX_XMLElement* pXMLDataElement =
Tom Sepezc9171e12018-07-26 19:34:26 +0000658 ToXMLElement(pDataNode->GetXMLMappingNode());
Dan Sinclair4a979702018-04-05 18:32:35 +0000659 WideString wsContentType =
dan sinclair8b0cf762018-04-16 21:24:57 +0000660 pXMLDataElement->GetAttribute(L"xfa:contentType");
Dan Sinclair4a979702018-04-05 18:32:35 +0000661 if (!wsContentType.IsEmpty()) {
662 pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
663 wsContentType, false, false);
664 image->SetContentType(wsContentType);
665 }
666
dan sinclair8b0cf762018-04-16 21:24:57 +0000667 WideString wsHref = pXMLDataElement->GetAttribute(L"href");
Dan Sinclair4a979702018-04-05 18:32:35 +0000668 if (!wsHref.IsEmpty())
669 image->SetHref(wsHref);
670 }
671 break;
672 }
673 case XFA_FFWidgetType::kChoiceList:
674 if (pFormNode->IsChoiceListMultiSelect()) {
675 std::vector<CXFA_Node*> items = pDataNode->GetNodeList(
676 XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties,
677 XFA_Element::Unknown);
678 if (!items.empty()) {
679 bool single = items.size() == 1;
680 wsNormalizeValue.clear();
681
682 for (CXFA_Node* pNode : items) {
683 WideString wsItem = pNode->JSObject()->GetContent(false);
684 if (single)
685 wsItem += L"\n";
686
687 wsNormalizeValue += wsItem;
688 }
689 CXFA_ExData* exData =
690 defValue ? defValue->GetExDataIfExists() : nullptr;
691 ASSERT(exData);
692
693 exData->SetContentType(single ? L"text/plain" : L"text/xml");
694 }
695 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
696 XFA_Element::ExData);
697 } else {
698 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
699 XFA_Element::Text);
700 }
701 break;
702 case XFA_FFWidgetType::kExclGroup: {
703 pFormNode->SetSelectedMemberByValue(wsNormalizeValue.AsStringView(),
704 false, false, false);
705 break;
706 }
707 case XFA_FFWidgetType::kDateTimeEdit:
708 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
709 XFA_Element::DateTime);
710 break;
711 case XFA_FFWidgetType::kNumericEdit: {
712 WideString wsPicture =
713 pFormNode->GetPictureContent(XFA_VALUEPICTURE_DataBind);
714 if (wsPicture.IsEmpty())
715 wsNormalizeValue = pFormNode->NormalizeNumStr(wsNormalizeValue);
716
717 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
718 XFA_Element::Float);
719 break;
720 }
721 default:
722 FormValueNode_SetChildContent(defValue, wsNormalizeValue,
723 XFA_Element::Text);
724 break;
725 }
726}
727
728CXFA_Node* MaybeCreateDataNode(CXFA_Document* pDocument,
729 CXFA_Node* pDataParent,
730 XFA_Element eNodeType,
731 const WideString& wsName) {
732 if (!pDataParent)
733 return nullptr;
734
735 CXFA_Node* pParentDDNode = pDataParent->GetDataDescriptionNode();
736 if (!pParentDDNode) {
737 CXFA_Node* pDataNode =
738 pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
739 pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false);
740 pDataNode->CreateXMLMappingNode();
741 pDataParent->InsertChild(pDataNode, nullptr);
742 pDataNode->SetFlag(XFA_NodeFlag_Initialized);
743 return pDataNode;
744 }
745
746 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup> sIterator(
747 pParentDDNode);
748 for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
749 pDDGroupNode = sIterator.MoveToNext()) {
750 if (pDDGroupNode != pParentDDNode) {
751 if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
752 continue;
753
754 Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
755 if (!ns || *ns != L"http://ns.adobe.com/data-description/")
756 continue;
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, false, false);
769 pDataNode->CreateXMLMappingNode();
770 if (eNodeType == XFA_Element::DataValue &&
771 pDDNode->JSObject()->GetEnum(XFA_Attribute::Contains) ==
772 XFA_AttributeEnum::MetaData) {
773 pDataNode->JSObject()->SetEnum(XFA_Attribute::Contains,
774 XFA_AttributeEnum::MetaData, false);
775 }
776 pDataParent->InsertChild(pDataNode, nullptr);
777 pDataNode->SetDataDescriptionNode(pDDNode);
778 pDataNode->SetFlag(XFA_NodeFlag_Initialized);
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 ASSERT(pFieldNode);
793 for (CXFA_Node* pTemplateChildNode = pTemplateNode->GetFirstChild();
794 pTemplateChildNode;
795 pTemplateChildNode = pTemplateChildNode->GetNextSibling()) {
796 if (XFA_DataMerge_NeedGenerateForm(pTemplateChildNode, true)) {
797 XFA_NodeMerge_CloneOrMergeContainer(pDocument, pFieldNode,
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_AttributeEnum 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)
855 pOccurNode->ClearFlag(XFA_NodeFlag_UnusedNode);
856 }
857 if (pInstMgrNode) {
858 pInstMgrNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
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_AttributeEnum eRelation =
879 eType == XFA_Element::SubformSet
880 ? pTemplateNode->JSObject()->GetEnum(XFA_Attribute::Relation)
881 : XFA_AttributeEnum::Ordered;
882 int32_t iCurRepeatIndex = 0;
883 XFA_AttributeEnum eParentBindMatch = XFA_AttributeEnum::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_AttributeEnum eBindMatch = XFA_AttributeEnum::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 ASSERT(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_AttributeEnum eBindMatch = XFA_AttributeEnum::None;
938 if (!FindMatchingDataNode(pDocument, pTemplateNode, pDataScope,
939 bAccessedDataDOM, false, &sNodeIterator,
940 bSelfMatch, eBindMatch, true)) {
941 break;
942 }
943 if (eBindMatch == XFA_AttributeEnum::DataRef &&
944 eParentBindMatch == XFA_AttributeEnum::DataRef) {
945 break;
946 }
947
948 if (eRelation == XFA_AttributeEnum::Choice ||
949 eRelation == XFA_AttributeEnum::Unordered) {
950 CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
951 pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
952 ASSERT(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_AttributeEnum::None;
968 if (eRelation != XFA_AttributeEnum::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_AttributeEnum::Choice: {
992 ASSERT(!rgItemMatchList.empty());
993 SortRecurseRecord(&rgItemMatchList, pDataScope, true);
994 pDocument->DataMerge_CopyContainer(
995 rgItemMatchList.front().pTemplateChild, pSubformSetNode,
996 pDataScope, false, true, true);
997 break;
998 }
999 case XFA_AttributeEnum::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 ASSERT(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 == false) {
1040 int32_t iLimit = iMax;
1041 if (pInstMgrNode && pTemplateNode->GetNameHash() == 0) {
1042 iLimit = pdfium::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 ASSERT(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 ASSERT(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_AttributeEnum::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_AttributeEnum eMatch =
1124 pTemplateNodeBind
1125 ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
1126 : XFA_AttributeEnum::Once;
1127 switch (eMatch) {
1128 case XFA_AttributeEnum::None:
1129 if (!bDataRef || bParentDataRef)
1130 FormValueNode_MatchNoneCreateChild(pFormNode);
1131 break;
1132 case XFA_AttributeEnum::Once:
1133 if (!bDataRef || bParentDataRef) {
1134 if (!pDataNode) {
1135 if (pFormNode->GetNameHash() != 0 &&
1136 pFormNode->JSObject()->GetEnum(XFA_Attribute::Scope) !=
1137 XFA_AttributeEnum::None) {
1138 XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1139 XFA_FieldIsMultiListBox(pFormNode))
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 ASSERT(pDataParent);
1156 pDataParent->RemoveChild(pDataNode, true);
1157 pDataScope->InsertChild(pDataNode, nullptr);
1158 }
1159 }
1160 }
1161 break;
1162 case XFA_AttributeEnum::Global:
1163 if (!bDataRef || bParentDataRef) {
1164 uint32_t dwNameHash = pFormNode->GetNameHash();
1165 if (dwNameHash != 0 && !pDataNode) {
Dan Sinclair5a552532018-04-05 19:05:11 +00001166 pDataNode = pDocument->GetGlobalBinding(dwNameHash);
Dan Sinclair4a979702018-04-05 18:32:35 +00001167 if (!pDataNode) {
1168 XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1169 XFA_FieldIsMultiListBox(pFormNode))
1170 ? XFA_Element::DataGroup
1171 : XFA_Element::DataValue;
1172 CXFA_Node* pRecordNode =
1173 ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record));
1174 pDataNode = MaybeCreateDataNode(
1175 pDocument, pRecordNode, eDataNodeType,
1176 WideString(
1177 pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1178 if (pDataNode) {
1179 CreateDataBinding(pFormNode, pDataNode, false);
Dan Sinclair5a552532018-04-05 19:05:11 +00001180 pDocument->RegisterGlobalBinding(pFormNode->GetNameHash(),
1181 pDataNode);
Dan Sinclair4a979702018-04-05 18:32:35 +00001182 }
1183 } else {
1184 CreateDataBinding(pFormNode, pDataNode, true);
1185 }
1186 }
1187 if (!pDataNode)
1188 FormValueNode_MatchNoneCreateChild(pFormNode);
1189 }
1190 break;
1191 case XFA_AttributeEnum::DataRef: {
1192 bMatchRef = bDataRef;
1193 bParentDataRef = true;
1194 if (!pDataNode && bDataRef) {
1195 WideString wsRef =
1196 pTemplateNodeBind
1197 ? pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref)
1198 : L"";
1199 uint32_t dFlags =
1200 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_CreateNode;
1201 XFA_RESOLVENODE_RS rs;
1202 pDocument->GetScriptContext()->ResolveObjects(
1203 pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
1204 CXFA_Object* pObject =
Tom Sepez1a3e1862018-08-21 22:56:37 +00001205 !rs.objects.empty() ? rs.objects.front().Get() : nullptr;
Dan Sinclair4a979702018-04-05 18:32:35 +00001206 pDataNode = ToNode(pObject);
1207 if (pDataNode) {
1208 CreateDataBinding(pFormNode, pDataNode,
1209 rs.dwFlags == XFA_ResolveNode_RSType_ExistNodes);
1210 } else {
1211 FormValueNode_MatchNoneCreateChild(pFormNode);
1212 }
1213 }
1214 break;
1215 }
1216 default:
1217 break;
1218 }
1219 }
1220
1221 if (bMatchRef &&
1222 (eType == XFA_Element::Subform || eType == XFA_Element::SubformSet ||
1223 eType == XFA_Element::Area || eType == XFA_Element::PageArea ||
1224 eType == XFA_Element::PageSet)) {
1225 for (CXFA_Node* pFormChild = pFormNode->GetFirstChild(); pFormChild;
1226 pFormChild = pFormChild->GetNextSibling()) {
1227 if (!pFormChild->IsContainerNode())
1228 continue;
1229 if (pFormChild->IsUnusedNode())
1230 continue;
1231
1232 UpdateBindingRelations(pDocument, pFormChild,
1233 pDataNode ? pDataNode : pDataScope, bDataRef,
1234 bParentDataRef);
1235 }
1236 }
1237}
1238
1239void UpdateDataRelation(CXFA_Node* pDataNode, CXFA_Node* pDataDescriptionNode) {
1240 ASSERT(pDataDescriptionNode);
1241 for (CXFA_Node* pDataChild = pDataNode->GetFirstChild(); pDataChild;
1242 pDataChild = pDataChild->GetNextSibling()) {
1243 uint32_t dwNameHash = pDataChild->GetNameHash();
1244 if (!dwNameHash)
1245 continue;
1246
1247 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup>
1248 sIterator(pDataDescriptionNode);
1249 for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
1250 pDDGroupNode = sIterator.MoveToNext()) {
1251 if (pDDGroupNode != pDataDescriptionNode) {
1252 if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
1253 continue;
1254
1255 Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
1256 if (!ns || *ns != L"http://ns.adobe.com/data-description/")
1257 continue;
1258 }
1259
1260 CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(dwNameHash);
1261 if (!pDDNode)
1262 continue;
1263 if (pDDNode->GetElementType() != pDataChild->GetElementType())
1264 break;
1265
1266 pDataChild->SetDataDescriptionNode(pDDNode);
1267 UpdateDataRelation(pDataChild, pDDNode);
1268 break;
1269 }
1270 }
1271}
1272
dsinclair16280242016-07-21 12:03:47 -07001273} // namespace
1274
Dan Sinclair9c112f92018-02-13 21:27:44 +00001275CXFA_Document::CXFA_Document(CXFA_FFNotify* notify)
Dan Sinclair80bf5822018-02-13 20:55:03 +00001276 : CXFA_NodeOwner(),
Dan Sinclair9c112f92018-02-13 21:27:44 +00001277 notify_(notify),
Dan Sinclair1770c022016-03-14 14:14:16 -04001278 m_pRootNode(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -04001279 m_eCurVersionMode(XFA_VERSION_DEFAULT),
Dan Sinclair9c112f92018-02-13 21:27:44 +00001280 m_dwDocFlags(0) {}
dsinclair16280242016-07-21 12:03:47 -07001281
Dan Sinclair1770c022016-03-14 14:14:16 -04001282CXFA_Document::~CXFA_Document() {
Dan Sinclaird99d5e32018-05-17 17:44:32 +00001283 // The destruction order of the nodes is not known because they're stored in a
1284 // list in the document. Therefore. the binding nodes must be released before
1285 // freeing the nodes to avoid dangling UnownedPtrs.
Dan Sinclair68c77592017-11-20 20:27:43 +00001286 if (m_pRootNode)
1287 m_pRootNode->ReleaseBindingNodes();
Dan Sinclair1770c022016-03-14 14:14:16 -04001288}
thestig495bda12016-04-28 17:29:19 -07001289
Dan Sinclair10def512017-02-06 15:31:38 -05001290CXFA_LayoutProcessor* CXFA_Document::GetLayoutProcessor() {
1291 if (!m_pLayoutProcessor)
Tom Sepez742fa8c2017-03-21 17:08:48 -07001292 m_pLayoutProcessor = pdfium::MakeUnique<CXFA_LayoutProcessor>(this);
1293 return m_pLayoutProcessor.get();
Dan Sinclair10def512017-02-06 15:31:38 -05001294}
1295
Dan Sinclair1770c022016-03-14 14:14:16 -04001296void CXFA_Document::ClearLayoutData() {
Tom Sepez742fa8c2017-03-21 17:08:48 -07001297 m_pLayoutProcessor.reset();
1298 m_pScriptContext.reset();
Lei Zhang5822da72018-07-30 17:46:18 +00001299 m_pLocaleMgr.reset();
Tom Sepez742fa8c2017-03-21 17:08:48 -07001300 m_pScriptDataWindow.reset();
1301 m_pScriptEvent.reset();
1302 m_pScriptHost.reset();
1303 m_pScriptLog.reset();
1304 m_pScriptLayout.reset();
1305 m_pScriptSignature.reset();
Dan Sinclair1770c022016-03-14 14:14:16 -04001306}
thestig495bda12016-04-28 17:29:19 -07001307
dsinclaircbfef572016-05-18 13:16:12 -07001308CXFA_Object* CXFA_Document::GetXFAObject(XFA_HashCode dwNodeNameHash) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001309 switch (dwNodeNameHash) {
1310 case XFA_HASHCODE_Data: {
1311 CXFA_Node* pDatasetsNode = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
dsinclair16280242016-07-21 12:03:47 -07001312 if (!pDatasetsNode)
dsinclair85d1f2c2016-06-23 12:40:16 -07001313 return nullptr;
dsinclair16280242016-07-21 12:03:47 -07001314
Dan Sinclairdf4f30e2017-12-14 20:51:03 +00001315 for (CXFA_DataGroup* pDatasetsChild =
1316 pDatasetsNode->GetFirstChildByClass<CXFA_DataGroup>(
1317 XFA_Element::DataGroup);
Dan Sinclair1770c022016-03-14 14:14:16 -04001318 pDatasetsChild;
Dan Sinclairdf4f30e2017-12-14 20:51:03 +00001319 pDatasetsChild =
1320 pDatasetsChild->GetNextSameClassSibling<CXFA_DataGroup>(
1321 XFA_Element::DataGroup)) {
dsinclair16280242016-07-21 12:03:47 -07001322 if (pDatasetsChild->GetNameHash() != XFA_HASHCODE_Data)
Dan Sinclair1770c022016-03-14 14:14:16 -04001323 continue;
dsinclair16280242016-07-21 12:03:47 -07001324
Ryan Harrisonc560a8c2018-01-04 14:43:27 -05001325 Optional<WideString> namespaceURI =
Dan Sinclair26142502017-12-13 18:29:02 +00001326 pDatasetsChild->JSObject()->TryNamespace();
Dan Sinclair3f9549e2017-11-16 14:23:07 +00001327 if (!namespaceURI)
Dan Sinclair1770c022016-03-14 14:14:16 -04001328 continue;
dsinclair16280242016-07-21 12:03:47 -07001329
Ryan Harrisonc560a8c2018-01-04 14:43:27 -05001330 Optional<WideString> datasetsURI =
Dan Sinclair26142502017-12-13 18:29:02 +00001331 pDatasetsNode->JSObject()->TryNamespace();
Dan Sinclair3f9549e2017-11-16 14:23:07 +00001332 if (!datasetsURI)
Dan Sinclair1770c022016-03-14 14:14:16 -04001333 continue;
Dan Sinclair3f9549e2017-11-16 14:23:07 +00001334 if (*namespaceURI == *datasetsURI)
Dan Sinclair1770c022016-03-14 14:14:16 -04001335 return pDatasetsChild;
Dan Sinclair1770c022016-03-14 14:14:16 -04001336 }
dsinclair85d1f2c2016-06-23 12:40:16 -07001337 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001338 }
Dan Sinclair1770c022016-03-14 14:14:16 -04001339 case XFA_HASHCODE_Record: {
1340 CXFA_Node* pData = ToNode(GetXFAObject(XFA_HASHCODE_Data));
Dan Sinclairdf4f30e2017-12-14 20:51:03 +00001341 return pData ? pData->GetFirstChildByClass<CXFA_DataGroup>(
1342 XFA_Element::DataGroup)
dsinclair85d1f2c2016-06-23 12:40:16 -07001343 : nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001344 }
1345 case XFA_HASHCODE_DataWindow: {
dsinclair85d1f2c2016-06-23 12:40:16 -07001346 if (!m_pScriptDataWindow)
Tom Sepez742fa8c2017-03-21 17:08:48 -07001347 m_pScriptDataWindow = pdfium::MakeUnique<CScript_DataWindow>(this);
1348 return m_pScriptDataWindow.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001349 }
1350 case XFA_HASHCODE_Event: {
dsinclair85d1f2c2016-06-23 12:40:16 -07001351 if (!m_pScriptEvent)
Tom Sepez742fa8c2017-03-21 17:08:48 -07001352 m_pScriptEvent = pdfium::MakeUnique<CScript_EventPseudoModel>(this);
1353 return m_pScriptEvent.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001354 }
1355 case XFA_HASHCODE_Host: {
dsinclair85d1f2c2016-06-23 12:40:16 -07001356 if (!m_pScriptHost)
Tom Sepez742fa8c2017-03-21 17:08:48 -07001357 m_pScriptHost = pdfium::MakeUnique<CScript_HostPseudoModel>(this);
1358 return m_pScriptHost.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001359 }
1360 case XFA_HASHCODE_Log: {
dsinclair85d1f2c2016-06-23 12:40:16 -07001361 if (!m_pScriptLog)
Tom Sepez742fa8c2017-03-21 17:08:48 -07001362 m_pScriptLog = pdfium::MakeUnique<CScript_LogPseudoModel>(this);
1363 return m_pScriptLog.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001364 }
1365 case XFA_HASHCODE_Signature: {
dsinclair85d1f2c2016-06-23 12:40:16 -07001366 if (!m_pScriptSignature)
Tom Sepez742fa8c2017-03-21 17:08:48 -07001367 m_pScriptSignature =
1368 pdfium::MakeUnique<CScript_SignaturePseudoModel>(this);
1369 return m_pScriptSignature.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001370 }
1371 case XFA_HASHCODE_Layout: {
dsinclair85d1f2c2016-06-23 12:40:16 -07001372 if (!m_pScriptLayout)
Tom Sepez742fa8c2017-03-21 17:08:48 -07001373 m_pScriptLayout = pdfium::MakeUnique<CScript_LayoutPseudoModel>(this);
1374 return m_pScriptLayout.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001375 }
1376 default:
1377 return m_pRootNode->GetFirstChildByName(dwNodeNameHash);
1378 }
1379}
dsinclair16280242016-07-21 12:03:47 -07001380
Dan Sinclairc40c5aa2017-11-30 21:29:11 +00001381CXFA_Node* CXFA_Document::CreateNode(XFA_PacketType packet,
dsinclair56a8b192016-06-21 14:15:25 -07001382 XFA_Element eElement) {
Dan Sinclairc40c5aa2017-11-30 21:29:11 +00001383 if (eElement == XFA_Element::Unknown)
Dan Sinclair83cb4362017-11-14 18:40:53 +00001384 return nullptr;
Dan Sinclair80bf5822018-02-13 20:55:03 +00001385 return AddOwnedNode(CXFA_Node::Create(this, eElement, packet));
Dan Sinclair1770c022016-03-14 14:14:16 -04001386}
tsepezaadedf92016-05-12 10:08:06 -07001387
tsepezd19e9122016-11-02 15:43:18 -07001388void CXFA_Document::SetFlag(uint32_t dwFlag, bool bOn) {
dsinclair16280242016-07-21 12:03:47 -07001389 if (bOn)
Dan Sinclair1770c022016-03-14 14:14:16 -04001390 m_dwDocFlags |= dwFlag;
dsinclair16280242016-07-21 12:03:47 -07001391 else
Dan Sinclair1770c022016-03-14 14:14:16 -04001392 m_dwDocFlags &= ~dwFlag;
Dan Sinclair1770c022016-03-14 14:14:16 -04001393}
dsinclair16280242016-07-21 12:03:47 -07001394
tsepezd19e9122016-11-02 15:43:18 -07001395bool CXFA_Document::IsInteractive() {
dsinclair16280242016-07-21 12:03:47 -07001396 if (m_dwDocFlags & XFA_DOCFLAG_HasInteractive)
tsepez7d89e722016-05-04 13:38:11 -07001397 return !!(m_dwDocFlags & XFA_DOCFLAG_Interactive);
dsinclair16280242016-07-21 12:03:47 -07001398
Dan Sinclair1770c022016-03-14 14:14:16 -04001399 CXFA_Node* pConfig = ToNode(GetXFAObject(XFA_HASHCODE_Config));
dsinclair16280242016-07-21 12:03:47 -07001400 if (!pConfig)
tsepezd19e9122016-11-02 15:43:18 -07001401 return false;
dsinclair16280242016-07-21 12:03:47 -07001402
Dan Sinclairdf4f30e2017-12-14 20:51:03 +00001403 CXFA_Present* pPresent =
1404 pConfig->GetFirstChildByClass<CXFA_Present>(XFA_Element::Present);
dsinclair16280242016-07-21 12:03:47 -07001405 if (!pPresent)
tsepezd19e9122016-11-02 15:43:18 -07001406 return false;
dsinclair16280242016-07-21 12:03:47 -07001407
Dan Sinclairdf4f30e2017-12-14 20:51:03 +00001408 CXFA_Pdf* pPDF = pPresent->GetFirstChildByClass<CXFA_Pdf>(XFA_Element::Pdf);
dsinclair16280242016-07-21 12:03:47 -07001409 if (!pPDF)
tsepezd19e9122016-11-02 15:43:18 -07001410 return false;
dsinclair16280242016-07-21 12:03:47 -07001411
Dan Sinclair51ef4a62017-12-14 20:43:53 +00001412 CXFA_Interactive* pFormFiller =
1413 pPDF->GetChild<CXFA_Interactive>(0, XFA_Element::Interactive, false);
dsinclairb94d7c92016-09-21 12:07:00 -07001414 if (pFormFiller) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001415 m_dwDocFlags |= XFA_DOCFLAG_HasInteractive;
Dan Sinclairb0667042017-11-16 13:42:49 +00001416
Dan Sinclair26142502017-12-13 18:29:02 +00001417 WideString wsInteractive = pFormFiller->JSObject()->GetContent(false);
Dan Sinclairb0667042017-11-16 13:42:49 +00001418 if (wsInteractive == L"1") {
Dan Sinclair1770c022016-03-14 14:14:16 -04001419 m_dwDocFlags |= XFA_DOCFLAG_Interactive;
tsepezd19e9122016-11-02 15:43:18 -07001420 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001421 }
1422 }
tsepezd19e9122016-11-02 15:43:18 -07001423 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001424}
dsinclair16280242016-07-21 12:03:47 -07001425
Lei Zhang5822da72018-07-30 17:46:18 +00001426CXFA_LocaleMgr* CXFA_Document::GetLocaleMgr() {
1427 if (!m_pLocaleMgr) {
1428 m_pLocaleMgr = pdfium::MakeUnique<CXFA_LocaleMgr>(
Tom Sepez742fa8c2017-03-21 17:08:48 -07001429 ToNode(GetXFAObject(XFA_HASHCODE_LocaleSet)),
1430 GetNotify()->GetAppProvider()->GetLanguage());
Dan Sinclair1770c022016-03-14 14:14:16 -04001431 }
Lei Zhang5822da72018-07-30 17:46:18 +00001432 return m_pLocaleMgr.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001433}
dsinclair16280242016-07-21 12:03:47 -07001434
Dan Sinclaire9f7db92018-06-05 18:24:12 +00001435CFXJSE_Engine* CXFA_Document::InitScriptContext(CJS_Runtime* fxjs_runtime) {
Dan Sinclair67687892017-11-06 21:35:11 +00001436 ASSERT(!m_pScriptContext);
Dan Sinclaire9f7db92018-06-05 18:24:12 +00001437 m_pScriptContext = pdfium::MakeUnique<CFXJSE_Engine>(this, fxjs_runtime);
Dan Sinclair67687892017-11-06 21:35:11 +00001438 return m_pScriptContext.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001439}
dsinclair16280242016-07-21 12:03:47 -07001440
Dan Sinclair67687892017-11-06 21:35:11 +00001441// We have to call |InitScriptContext| before any calls to |GetScriptContext|
1442// or the context won't have an isolate set into it.
Dan Sinclaird8d6f552018-02-14 15:44:21 +00001443CFXJSE_Engine* CXFA_Document::GetScriptContext() const {
Dan Sinclair67687892017-11-06 21:35:11 +00001444 ASSERT(m_pScriptContext);
Tom Sepez742fa8c2017-03-21 17:08:48 -07001445 return m_pScriptContext.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001446}
dsinclair16280242016-07-21 12:03:47 -07001447
Dan Sinclair1770c022016-03-14 14:14:16 -04001448XFA_VERSION CXFA_Document::RecognizeXFAVersionNumber(
Ryan Harrison275e2602017-09-18 14:23:18 -04001449 const WideString& wsTemplateNS) {
Dan Sinclairf65f1d32017-11-30 21:56:00 +00001450 WideStringView wsTemplateURIPrefix(kTemplateNS);
Dan Sinclairba367062018-05-01 17:02:54 +00001451 if (wsTemplateNS.GetLength() <= wsTemplateURIPrefix.GetLength())
Dan Sinclair1770c022016-03-14 14:14:16 -04001452 return XFA_VERSION_UNKNOWN;
Dan Sinclairba367062018-05-01 17:02:54 +00001453
1454 size_t prefixLength = wsTemplateURIPrefix.GetLength();
1455 if (WideStringView(wsTemplateNS.c_str(), prefixLength) != wsTemplateURIPrefix)
1456 return XFA_VERSION_UNKNOWN;
1457
1458 auto nDotPos = wsTemplateNS.Find('.', prefixLength);
Ryan Harrison12db7512017-08-23 10:39:35 -04001459 if (!nDotPos.has_value())
Dan Sinclair1770c022016-03-14 14:14:16 -04001460 return XFA_VERSION_UNKNOWN;
dsinclair16280242016-07-21 12:03:47 -07001461
tsepezbd9748d2016-04-13 21:40:19 -07001462 int8_t iMajor = FXSYS_wtoi(
Dan Sinclairba367062018-05-01 17:02:54 +00001463 wsTemplateNS.Mid(prefixLength, nDotPos.value() - prefixLength).c_str());
Ryan Harrison12db7512017-08-23 10:39:35 -04001464 int8_t iMinor =
1465 FXSYS_wtoi(wsTemplateNS
1466 .Mid(nDotPos.value() + 1,
1467 wsTemplateNS.GetLength() - nDotPos.value() - 2)
1468 .c_str());
Dan Sinclair1770c022016-03-14 14:14:16 -04001469 XFA_VERSION eVersion = (XFA_VERSION)((int32_t)iMajor * 100 + iMinor);
dsinclair16280242016-07-21 12:03:47 -07001470 if (eVersion < XFA_VERSION_MIN || eVersion > XFA_VERSION_MAX)
Dan Sinclair1770c022016-03-14 14:14:16 -04001471 return XFA_VERSION_UNKNOWN;
dsinclair16280242016-07-21 12:03:47 -07001472
Dan Sinclair1770c022016-03-14 14:14:16 -04001473 m_eCurVersionMode = eVersion;
1474 return eVersion;
1475}
dsinclair16280242016-07-21 12:03:47 -07001476
Henrique Nakashima36b20592018-07-24 20:25:45 +00001477FormType CXFA_Document::GetFormType() const {
1478 return GetNotify()->GetHDOC()->GetFormType();
1479}
1480
Dan Sinclair1770c022016-03-14 14:14:16 -04001481CXFA_Node* CXFA_Document::GetNodeByID(CXFA_Node* pRoot,
Dan Sinclaird8d6f552018-02-14 15:44:21 +00001482 const WideStringView& wsID) const {
dsinclair16280242016-07-21 12:03:47 -07001483 if (!pRoot || wsID.IsEmpty())
dsinclair85d1f2c2016-06-23 12:40:16 -07001484 return nullptr;
dsinclair16280242016-07-21 12:03:47 -07001485
Dan Sinclair1770c022016-03-14 14:14:16 -04001486 CXFA_NodeIterator sIterator(pRoot);
1487 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
1488 pNode = sIterator.MoveToNext()) {
Dan Sinclair26142502017-12-13 18:29:02 +00001489 WideString wsIDVal = pNode->JSObject()->GetCData(XFA_Attribute::Id);
Dan Sinclairb0667042017-11-16 13:42:49 +00001490 if (!wsIDVal.IsEmpty() && wsIDVal == wsID)
1491 return pNode;
Dan Sinclair1770c022016-03-14 14:14:16 -04001492 }
dsinclair85d1f2c2016-06-23 12:40:16 -07001493 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001494}
dsinclair16280242016-07-21 12:03:47 -07001495
Dan Sinclair1770c022016-03-14 14:14:16 -04001496void CXFA_Document::DoProtoMerge() {
1497 CXFA_Node* pTemplateRoot = ToNode(GetXFAObject(XFA_HASHCODE_Template));
dsinclair16280242016-07-21 12:03:47 -07001498 if (!pTemplateRoot)
Dan Sinclair1770c022016-03-14 14:14:16 -04001499 return;
dsinclair16280242016-07-21 12:03:47 -07001500
tsepez6bb3b892017-01-05 12:18:41 -08001501 std::map<uint32_t, CXFA_Node*> mIDMap;
Tom Sepeze47e0c92017-04-26 10:55:54 -07001502 std::set<CXFA_Node*> sUseNodes;
Dan Sinclair1770c022016-03-14 14:14:16 -04001503 CXFA_NodeIterator sIterator(pTemplateRoot);
1504 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
1505 pNode = sIterator.MoveToNext()) {
Dan Sinclair26142502017-12-13 18:29:02 +00001506 WideString wsIDVal = pNode->JSObject()->GetCData(XFA_Attribute::Id);
Dan Sinclairb0667042017-11-16 13:42:49 +00001507 if (!wsIDVal.IsEmpty())
Dan Sinclairaee28692017-11-14 21:19:44 +00001508 mIDMap[FX_HashCode_GetW(wsIDVal.AsStringView(), false)] = pNode;
Dan Sinclairb0667042017-11-16 13:42:49 +00001509
Dan Sinclair26142502017-12-13 18:29:02 +00001510 WideString wsUseVal = pNode->JSObject()->GetCData(XFA_Attribute::Use);
Dan Sinclairb0667042017-11-16 13:42:49 +00001511 if (!wsUseVal.IsEmpty()) {
tsepezaadedf92016-05-12 10:08:06 -07001512 sUseNodes.insert(pNode);
Dan Sinclairb0667042017-11-16 13:42:49 +00001513 } else {
Dan Sinclair26142502017-12-13 18:29:02 +00001514 wsUseVal = pNode->JSObject()->GetCData(XFA_Attribute::Usehref);
Dan Sinclairb0667042017-11-16 13:42:49 +00001515 if (!wsUseVal.IsEmpty())
1516 sUseNodes.insert(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04001517 }
1518 }
dsinclair16280242016-07-21 12:03:47 -07001519
tsepezaadedf92016-05-12 10:08:06 -07001520 for (CXFA_Node* pUseHrefNode : sUseNodes) {
Ryan Harrison9afcfa42018-04-24 18:44:29 +00001521 // Must outlive the WideStringViews below.
1522 WideString wsUseVal =
1523 pUseHrefNode->JSObject()->GetCData(XFA_Attribute::Usehref);
Dan Sinclairb0667042017-11-16 13:42:49 +00001524 WideStringView wsURI;
1525 WideStringView wsID;
1526 WideStringView wsSOM;
1527
Dan Sinclairb0667042017-11-16 13:42:49 +00001528 if (!wsUseVal.IsEmpty()) {
Ryan Harrison12db7512017-08-23 10:39:35 -04001529 auto uSharpPos = wsUseVal.Find('#');
1530 if (!uSharpPos.has_value()) {
Ryan Harrison275e2602017-09-18 14:23:18 -04001531 wsURI = wsUseVal.AsStringView();
Dan Sinclair1770c022016-03-14 14:14:16 -04001532 } else {
Ryan Harrison275e2602017-09-18 14:23:18 -04001533 wsURI = WideStringView(wsUseVal.c_str(), uSharpPos.value());
Ryan Harrison875e98c2017-09-27 10:53:11 -04001534 size_t uLen = wsUseVal.GetLength();
Ryan Harrison12db7512017-08-23 10:39:35 -04001535 if (uLen >= uSharpPos.value() + 5 &&
Ryan Harrison275e2602017-09-18 14:23:18 -04001536 WideStringView(wsUseVal.c_str() + uSharpPos.value(), 5) ==
Ryan Harrison12db7512017-08-23 10:39:35 -04001537 L"#som(" &&
Dan Sinclair1770c022016-03-14 14:14:16 -04001538 wsUseVal[uLen - 1] == ')') {
Ryan Harrison275e2602017-09-18 14:23:18 -04001539 wsSOM = WideStringView(wsUseVal.c_str() + uSharpPos.value() + 5,
1540 uLen - 1 - uSharpPos.value() - 5);
Dan Sinclair1770c022016-03-14 14:14:16 -04001541 } else {
Ryan Harrison275e2602017-09-18 14:23:18 -04001542 wsID = WideStringView(wsUseVal.c_str() + uSharpPos.value() + 1,
1543 uLen - uSharpPos.value() - 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04001544 }
1545 }
Dan Sinclairb0667042017-11-16 13:42:49 +00001546 } else {
Dan Sinclair26142502017-12-13 18:29:02 +00001547 wsUseVal = pUseHrefNode->JSObject()->GetCData(XFA_Attribute::Use);
Dan Sinclairb0667042017-11-16 13:42:49 +00001548 if (!wsUseVal.IsEmpty()) {
1549 if (wsUseVal[0] == '#')
1550 wsID = WideStringView(wsUseVal.c_str() + 1, wsUseVal.GetLength() - 1);
1551 else
1552 wsSOM = WideStringView(wsUseVal.c_str(), wsUseVal.GetLength());
1553 }
Dan Sinclair1770c022016-03-14 14:14:16 -04001554 }
dsinclair16280242016-07-21 12:03:47 -07001555
dan sinclair65c7c232017-02-02 14:05:30 -08001556 if (!wsURI.IsEmpty() && wsURI != L".")
Dan Sinclair1770c022016-03-14 14:14:16 -04001557 continue;
dsinclair16280242016-07-21 12:03:47 -07001558
dsinclair85d1f2c2016-06-23 12:40:16 -07001559 CXFA_Node* pProtoNode = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001560 if (!wsSOM.IsEmpty()) {
tsepez736f28a2016-03-25 14:19:51 -07001561 uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
Dan Sinclair1770c022016-03-14 14:14:16 -04001562 XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
1563 XFA_RESOLVENODE_Siblings;
Dan Sinclair472bb7f2017-11-06 18:17:41 +00001564 XFA_RESOLVENODE_RS resolveNodeRS;
Dan Sinclair9256ad52017-12-04 18:20:07 +00001565 int32_t iRet = m_pScriptContext->ResolveObjects(
1566 pUseHrefNode, wsSOM, &resolveNodeRS, dwFlag, nullptr);
Dan Sinclair472bb7f2017-11-06 18:17:41 +00001567 if (iRet > 0 && resolveNodeRS.objects.front()->IsNode())
1568 pProtoNode = resolveNodeRS.objects.front()->AsNode();
Dan Sinclair1770c022016-03-14 14:14:16 -04001569 } else if (!wsID.IsEmpty()) {
tsepez6bb3b892017-01-05 12:18:41 -08001570 auto it = mIDMap.find(FX_HashCode_GetW(wsID, false));
1571 if (it == mIDMap.end())
Dan Sinclair1770c022016-03-14 14:14:16 -04001572 continue;
tsepez6bb3b892017-01-05 12:18:41 -08001573 pProtoNode = it->second;
Dan Sinclair1770c022016-03-14 14:14:16 -04001574 }
dsinclair16280242016-07-21 12:03:47 -07001575 if (!pProtoNode)
Dan Sinclair1770c022016-03-14 14:14:16 -04001576 continue;
dsinclair16280242016-07-21 12:03:47 -07001577
Dan Sinclair72fe14a2018-04-05 18:33:35 +00001578 MergeNode(pUseHrefNode, pProtoNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04001579 }
1580}
Dan Sinclair4a979702018-04-05 18:32:35 +00001581
1582CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode,
1583 CXFA_Node* pFormNode,
1584 CXFA_Node* pDataScope,
1585 bool bOneInstance,
1586 bool bDataMerge,
1587 bool bUpLevel) {
1588 switch (pTemplateNode->GetElementType()) {
1589 case XFA_Element::SubformSet:
1590 case XFA_Element::Subform:
1591 case XFA_Element::Area:
1592 case XFA_Element::PageArea:
1593 return CopyContainer_SubformSet(this, pTemplateNode, pFormNode,
1594 pDataScope, bOneInstance, bDataMerge);
1595 case XFA_Element::ExclGroup:
1596 case XFA_Element::Field:
1597 case XFA_Element::Draw:
1598 case XFA_Element::ContentArea:
1599 return CopyContainer_Field(this, pTemplateNode, pFormNode, pDataScope,
1600 bDataMerge, bUpLevel);
1601 case XFA_Element::PageSet:
1602 case XFA_Element::Variables:
1603 break;
1604 default:
1605 NOTREACHED();
1606 break;
1607 }
1608 return nullptr;
1609}
1610
1611void CXFA_Document::DataMerge_UpdateBindingRelations(
1612 CXFA_Node* pFormUpdateRoot) {
1613 CXFA_Node* pDataScope =
1614 XFA_DataMerge_FindDataScope(pFormUpdateRoot->GetParent());
1615 if (!pDataScope)
1616 return;
1617
1618 UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, false, false);
1619 UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, true, false);
1620}
1621
1622CXFA_Node* CXFA_Document::GetNotBindNode(
Tom Sepez1a3e1862018-08-21 22:56:37 +00001623 const std::vector<UnownedPtr<CXFA_Object>>& arrayObjects) const {
1624 for (auto& pObject : arrayObjects) {
Dan Sinclair4a979702018-04-05 18:32:35 +00001625 CXFA_Node* pNode = pObject->AsNode();
1626 if (pNode && !pNode->HasBindItem())
1627 return pNode;
1628 }
1629 return nullptr;
1630}
1631
1632void CXFA_Document::DoDataMerge() {
1633 CXFA_Node* pDatasetsRoot = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
1634 if (!pDatasetsRoot) {
1635 // Ownership will be passed in the AppendChild below to the XML tree.
Dan Sinclair70180642018-05-02 16:02:03 +00001636 auto* pDatasetsXMLNode =
1637 notify_->GetHDOC()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1638 L"xfa:datasets");
dan sinclair8b0cf762018-04-16 21:24:57 +00001639 pDatasetsXMLNode->SetAttribute(L"xmlns:xfa",
1640 L"http://www.xfa.org/schema/xfa-data/1.0/");
Dan Sinclair4a979702018-04-05 18:32:35 +00001641 pDatasetsRoot =
1642 CreateNode(XFA_PacketType::Datasets, XFA_Element::DataModel);
1643 pDatasetsRoot->JSObject()->SetCData(XFA_Attribute::Name, L"datasets", false,
1644 false);
1645
Dan Sinclair70180642018-05-02 16:02:03 +00001646 m_pRootNode->GetXMLMappingNode()->AppendChild(pDatasetsXMLNode);
Dan Sinclair4a979702018-04-05 18:32:35 +00001647 m_pRootNode->InsertChild(pDatasetsRoot, nullptr);
Dan Sinclair70180642018-05-02 16:02:03 +00001648
1649 pDatasetsRoot->SetXMLMappingNode(pDatasetsXMLNode);
Dan Sinclair4a979702018-04-05 18:32:35 +00001650 }
1651
Lei Zhangdd92aa52018-09-20 12:56:04 +00001652 CXFA_Node* pDataRoot = nullptr;
1653 CXFA_Node* pDDRoot = nullptr;
Dan Sinclair4a979702018-04-05 18:32:35 +00001654 WideString wsDatasetsURI =
1655 pDatasetsRoot->JSObject()->TryNamespace().value_or(WideString());
1656 for (CXFA_Node* pChildNode = pDatasetsRoot->GetFirstChild(); pChildNode;
1657 pChildNode = pChildNode->GetNextSibling()) {
1658 if (pChildNode->GetElementType() != XFA_Element::DataGroup)
1659 continue;
1660
1661 if (!pDDRoot && pChildNode->GetNameHash() == XFA_HASHCODE_DataDescription) {
1662 Optional<WideString> namespaceURI =
1663 pChildNode->JSObject()->TryNamespace();
1664 if (!namespaceURI)
1665 continue;
1666 if (*namespaceURI == L"http://ns.adobe.com/data-description/")
1667 pDDRoot = pChildNode;
1668 } else if (!pDataRoot && pChildNode->GetNameHash() == XFA_HASHCODE_Data) {
1669 Optional<WideString> namespaceURI =
1670 pChildNode->JSObject()->TryNamespace();
1671 if (!namespaceURI)
1672 continue;
1673 if (*namespaceURI == wsDatasetsURI)
1674 pDataRoot = pChildNode;
1675 }
1676 if (pDataRoot && pDDRoot)
1677 break;
1678 }
1679
1680 if (!pDataRoot) {
1681 pDataRoot = CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup);
1682 pDataRoot->JSObject()->SetCData(XFA_Attribute::Name, L"data", false, false);
Dan Sinclair70180642018-05-02 16:02:03 +00001683
1684 auto* elem =
1685 notify_->GetHDOC()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1686 L"xfa:data");
1687 pDataRoot->SetXMLMappingNode(elem);
Dan Sinclair4a979702018-04-05 18:32:35 +00001688 pDatasetsRoot->InsertChild(pDataRoot, nullptr);
1689 }
1690
1691 CXFA_DataGroup* pDataTopLevel =
1692 pDataRoot->GetFirstChildByClass<CXFA_DataGroup>(XFA_Element::DataGroup);
1693 uint32_t dwNameHash = pDataTopLevel ? pDataTopLevel->GetNameHash() : 0;
1694 CXFA_Template* pTemplateRoot =
1695 m_pRootNode->GetFirstChildByClass<CXFA_Template>(XFA_Element::Template);
1696 if (!pTemplateRoot)
1697 return;
1698
1699 CXFA_Node* pTemplateChosen =
1700 dwNameHash != 0 ? pTemplateRoot->GetFirstChildByName(dwNameHash)
1701 : nullptr;
1702 if (!pTemplateChosen ||
1703 pTemplateChosen->GetElementType() != XFA_Element::Subform) {
1704 pTemplateChosen =
1705 pTemplateRoot->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
1706 }
1707 if (!pTemplateChosen)
1708 return;
1709
1710 CXFA_Form* pFormRoot =
1711 m_pRootNode->GetFirstChildByClass<CXFA_Form>(XFA_Element::Form);
1712 bool bEmptyForm = false;
1713 if (!pFormRoot) {
1714 bEmptyForm = true;
1715 pFormRoot = static_cast<CXFA_Form*>(
1716 CreateNode(XFA_PacketType::Form, XFA_Element::Form));
1717 ASSERT(pFormRoot);
1718 pFormRoot->JSObject()->SetCData(XFA_Attribute::Name, L"form", false, false);
1719 m_pRootNode->InsertChild(pFormRoot, nullptr);
1720 } else {
1721 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode>
1722 sIterator(pFormRoot);
1723 for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode;
1724 pNode = sIterator.MoveToNext()) {
1725 pNode->SetFlag(XFA_NodeFlag_UnusedNode);
1726 }
1727 }
1728
1729 CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1730 this, pFormRoot, pTemplateChosen, false, nullptr);
1731 ASSERT(pSubformSetNode);
1732 if (!pDataTopLevel) {
1733 WideString wsFormName =
1734 pSubformSetNode->JSObject()->GetCData(XFA_Attribute::Name);
1735 WideString wsDataTopLevelName(wsFormName.IsEmpty() ? L"form" : wsFormName);
1736
1737 pDataTopLevel = static_cast<CXFA_DataGroup*>(
1738 CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup));
1739 pDataTopLevel->JSObject()->SetCData(XFA_Attribute::Name, wsDataTopLevelName,
1740 false, false);
Dan Sinclair70180642018-05-02 16:02:03 +00001741
1742 auto* elem =
1743 notify_->GetHDOC()->GetXMLDocument()->CreateNode<CFX_XMLElement>(
1744 wsDataTopLevelName);
1745 pDataTopLevel->SetXMLMappingNode(elem);
Dan Sinclair4a979702018-04-05 18:32:35 +00001746
1747 CXFA_Node* pBeforeNode = pDataRoot->GetFirstChild();
1748 pDataRoot->InsertChild(pDataTopLevel, pBeforeNode);
1749 }
1750
1751 ASSERT(pDataTopLevel);
1752 CreateDataBinding(pSubformSetNode, pDataTopLevel, true);
1753 for (CXFA_Node* pTemplateChild = pTemplateChosen->GetFirstChild();
1754 pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1755 if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
1756 XFA_NodeMerge_CloneOrMergeContainer(this, pSubformSetNode, pTemplateChild,
1757 true, nullptr);
1758 } else if (pTemplateChild->IsContainerNode()) {
1759 DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, pDataTopLevel,
1760 false, true, true);
1761 }
1762 }
1763 if (pDDRoot)
1764 UpdateDataRelation(pDataRoot, pDDRoot);
1765
1766 DataMerge_UpdateBindingRelations(pSubformSetNode);
1767 CXFA_PageSet* pPageSetNode =
1768 pSubformSetNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
1769 while (pPageSetNode) {
1770 m_pPendingPageSet.push_back(pPageSetNode);
1771 CXFA_PageSet* pNextPageSetNode =
1772 pPageSetNode->GetNextSameClassSibling<CXFA_PageSet>(
1773 XFA_Element::PageSet);
1774 pSubformSetNode->RemoveChild(pPageSetNode, true);
1775 pPageSetNode = pNextPageSetNode;
1776 }
1777
1778 if (bEmptyForm)
1779 return;
1780
1781 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(
1782 pFormRoot);
1783 CXFA_Node* pNode = sIterator.MoveToNext();
1784 while (pNode) {
1785 if (pNode->IsUnusedNode()) {
1786 if (pNode->IsContainerNode() ||
1787 pNode->GetElementType() == XFA_Element::InstanceManager) {
1788 CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext();
1789 pNode->GetParent()->RemoveChild(pNode, true);
1790 pNode = pNext;
1791 } else {
1792 pNode->ClearFlag(XFA_NodeFlag_UnusedNode);
1793 pNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
1794 pNode = sIterator.MoveToNext();
1795 }
1796 } else {
1797 pNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
1798 pNode = sIterator.MoveToNext();
1799 }
1800 }
1801}
1802
1803void CXFA_Document::DoDataRemerge(bool bDoDataMerge) {
1804 CXFA_Node* pFormRoot = ToNode(GetXFAObject(XFA_HASHCODE_Form));
1805 if (pFormRoot) {
1806 while (CXFA_Node* pNode = pFormRoot->GetFirstChild())
1807 pFormRoot->RemoveChild(pNode, true);
1808
1809 pFormRoot->SetBindingNode(nullptr);
1810 }
1811 m_rgGlobalBinding.clear();
1812
1813 if (bDoDataMerge)
1814 DoDataMerge();
1815
1816 CXFA_LayoutProcessor* pLayoutProcessor = GetLayoutProcessor();
1817 pLayoutProcessor->SetForceReLayout(true);
1818}
Dan Sinclair5a552532018-04-05 19:05:11 +00001819
1820CXFA_Node* CXFA_Document::GetGlobalBinding(uint32_t dwNameHash) {
1821 auto it = m_rgGlobalBinding.find(dwNameHash);
1822 return it != m_rgGlobalBinding.end() ? it->second : nullptr;
1823}
1824
1825void CXFA_Document::RegisterGlobalBinding(uint32_t dwNameHash,
1826 CXFA_Node* pDataNode) {
1827 m_rgGlobalBinding[dwNameHash] = pDataNode;
1828}