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