1// Copyright 2016 PDFium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7#include "xfa/fxfa/parser/cxfa_node.h" 8 9#include <map> 10#include <memory> 11#include <set> 12#include <utility> 13#include <vector> 14 15#include "core/fxcrt/autorestorer.h" 16#include "core/fxcrt/cfx_decimal.h" 17#include "core/fxcrt/cfx_memorystream.h" 18#include "core/fxcrt/fx_codepage.h" 19#include "core/fxcrt/fx_extension.h" 20#include "core/fxcrt/xml/cfx_xmlelement.h" 21#include "core/fxcrt/xml/cfx_xmlnode.h" 22#include "core/fxcrt/xml/cfx_xmltext.h" 23#include "fxjs/cfxjse_engine.h" 24#include "fxjs/cfxjse_value.h" 25#include "fxjs/xfa/cjx_node.h" 26#include "third_party/base/logging.h" 27#include "third_party/base/ptr_util.h" 28#include "third_party/base/stl_util.h" 29#include "xfa/fxfa/cxfa_eventparam.h" 30#include "xfa/fxfa/cxfa_ffapp.h" 31#include "xfa/fxfa/cxfa_ffdocview.h" 32#include "xfa/fxfa/cxfa_ffnotify.h" 33#include "xfa/fxfa/cxfa_ffwidget.h" 34#include "xfa/fxfa/parser/cxfa_arraynodelist.h" 35#include "xfa/fxfa/parser/cxfa_attachnodelist.h" 36#include "xfa/fxfa/parser/cxfa_bind.h" 37#include "xfa/fxfa/parser/cxfa_border.h" 38#include "xfa/fxfa/parser/cxfa_calculate.h" 39#include "xfa/fxfa/parser/cxfa_caption.h" 40#include "xfa/fxfa/parser/cxfa_document.h" 41#include "xfa/fxfa/parser/cxfa_event.h" 42#include "xfa/fxfa/parser/cxfa_font.h" 43#include "xfa/fxfa/parser/cxfa_keep.h" 44#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" 45#include "xfa/fxfa/parser/cxfa_localevalue.h" 46#include "xfa/fxfa/parser/cxfa_margin.h" 47#include "xfa/fxfa/parser/cxfa_measurement.h" 48#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" 49#include "xfa/fxfa/parser/cxfa_occur.h" 50#include "xfa/fxfa/parser/cxfa_para.h" 51#include "xfa/fxfa/parser/cxfa_simple_parser.h" 52#include "xfa/fxfa/parser/cxfa_subform.h" 53#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h" 54#include "xfa/fxfa/parser/cxfa_validate.h" 55#include "xfa/fxfa/parser/cxfa_value.h" 56#include "xfa/fxfa/parser/xfa_basic_data.h" 57#include "xfa/fxfa/parser/xfa_utils.h" 58 59namespace { 60 61constexpr uint8_t kMaxExecuteRecursion = 2; 62 63std::vector<CXFA_Node*> NodesSortedByDocumentIdx( 64 const std::set<CXFA_Node*>& rgNodeSet) { 65 if (rgNodeSet.empty()) 66 return std::vector<CXFA_Node*>(); 67 68 std::vector<CXFA_Node*> rgNodeArray; 69 CXFA_Node* pCommonParent = (*rgNodeSet.begin())->GetParent(); 70 for (CXFA_Node* pNode = pCommonParent->GetFirstChild(); pNode; 71 pNode = pNode->GetNextSibling()) { 72 if (pdfium::ContainsValue(rgNodeSet, pNode)) 73 rgNodeArray.push_back(pNode); 74 } 75 return rgNodeArray; 76} 77 78using CXFA_NodeSetPair = std::pair<std::set<CXFA_Node*>, std::set<CXFA_Node*>>; 79using CXFA_NodeSetPairMap = 80 std::map<uint32_t, std::unique_ptr<CXFA_NodeSetPair>>; 81using CXFA_NodeSetPairMapMap = 82 std::map<CXFA_Node*, std::unique_ptr<CXFA_NodeSetPairMap>>; 83 84CXFA_NodeSetPair* NodeSetPairForNode(CXFA_Node* pNode, 85 CXFA_NodeSetPairMapMap* pMap) { 86 CXFA_Node* pParentNode = pNode->GetParent(); 87 uint32_t dwNameHash = pNode->GetNameHash(); 88 if (!pParentNode || !dwNameHash) 89 return nullptr; 90 91 if (!(*pMap)[pParentNode]) 92 (*pMap)[pParentNode] = pdfium::MakeUnique<CXFA_NodeSetPairMap>(); 93 94 CXFA_NodeSetPairMap* pNodeSetPairMap = (*pMap)[pParentNode].get(); 95 if (!(*pNodeSetPairMap)[dwNameHash]) 96 (*pNodeSetPairMap)[dwNameHash] = pdfium::MakeUnique<CXFA_NodeSetPair>(); 97 98 return (*pNodeSetPairMap)[dwNameHash].get(); 99} 100 101void ReorderDataNodes(const std::set<CXFA_Node*>& sSet1, 102 const std::set<CXFA_Node*>& sSet2, 103 bool bInsertBefore) { 104 CXFA_NodeSetPairMapMap rgMap; 105 for (CXFA_Node* pNode : sSet1) { 106 CXFA_NodeSetPair* pNodeSetPair = NodeSetPairForNode(pNode, &rgMap); 107 if (pNodeSetPair) 108 pNodeSetPair->first.insert(pNode); 109 } 110 for (CXFA_Node* pNode : sSet2) { 111 CXFA_NodeSetPair* pNodeSetPair = NodeSetPairForNode(pNode, &rgMap); 112 if (pNodeSetPair) { 113 if (pdfium::ContainsValue(pNodeSetPair->first, pNode)) 114 pNodeSetPair->first.erase(pNode); 115 else 116 pNodeSetPair->second.insert(pNode); 117 } 118 } 119 for (const auto& iter1 : rgMap) { 120 CXFA_NodeSetPairMap* pNodeSetPairMap = iter1.second.get(); 121 if (!pNodeSetPairMap) 122 continue; 123 124 for (const auto& iter2 : *pNodeSetPairMap) { 125 CXFA_NodeSetPair* pNodeSetPair = iter2.second.get(); 126 if (!pNodeSetPair) 127 continue; 128 if (!pNodeSetPair->first.empty() && !pNodeSetPair->second.empty()) { 129 std::vector<CXFA_Node*> rgNodeArray1 = 130 NodesSortedByDocumentIdx(pNodeSetPair->first); 131 std::vector<CXFA_Node*> rgNodeArray2 = 132 NodesSortedByDocumentIdx(pNodeSetPair->second); 133 CXFA_Node* pParentNode = nullptr; 134 CXFA_Node* pBeforeNode = nullptr; 135 if (bInsertBefore) { 136 pBeforeNode = rgNodeArray2.front(); 137 pParentNode = pBeforeNode->GetParent(); 138 } else { 139 CXFA_Node* pLastNode = rgNodeArray2.back(); 140 pParentNode = pLastNode->GetParent(); 141 pBeforeNode = pLastNode->GetNextSibling(); 142 } 143 for (auto* pCurNode : rgNodeArray1) { 144 pParentNode->RemoveChild(pCurNode, true); 145 pParentNode->InsertChild(pCurNode, pBeforeNode); 146 } 147 } 148 } 149 pNodeSetPairMap->clear(); 150 } 151} 152 153} // namespace 154 155// static 156WideString CXFA_Node::AttributeEnumToName(XFA_AttributeEnum item) { 157 return g_XFAEnumData[static_cast<int32_t>(item)].pName; 158} 159 160// static 161Optional<XFA_AttributeEnum> CXFA_Node::NameToAttributeEnum( 162 const WideStringView& name) { 163 if (name.IsEmpty()) 164 return {}; 165 166 auto* it = std::lower_bound(g_XFAEnumData, g_XFAEnumData + g_iXFAEnumCount, 167 FX_HashCode_GetW(name, false), 168 [](const XFA_AttributeEnumInfo& arg, 169 uint32_t hash) { return arg.uHash < hash; }); 170 if (it != g_XFAEnumData + g_iXFAEnumCount && name == it->pName) 171 return {it->eName}; 172 return {}; 173} 174 175CXFA_Node::CXFA_Node(CXFA_Document* pDoc, 176 XFA_PacketType ePacket, 177 uint32_t validPackets, 178 XFA_ObjectType oType, 179 XFA_Element eType, 180 const PropertyData* properties, 181 const AttributeData* attributes, 182 const WideStringView& elementName, 183 std::unique_ptr<CJX_Object> js_node) 184 : CXFA_Object(pDoc, oType, eType, elementName, std::move(js_node)), 185 m_Properties(properties), 186 m_Attributes(attributes), 187 m_ValidPackets(validPackets), 188 m_pNext(nullptr), 189 m_pChild(nullptr), 190 m_pLastChild(nullptr), 191 m_pParent(nullptr), 192 m_pXMLNode(nullptr), 193 m_ePacket(ePacket), 194 m_uNodeFlags(XFA_NodeFlag_None), 195 m_dwNameHash(0), 196 m_pAuxNode(nullptr) { 197 ASSERT(m_pDocument); 198} 199 200CXFA_Node::CXFA_Node(CXFA_Document* pDoc, 201 XFA_PacketType ePacket, 202 uint32_t validPackets, 203 XFA_ObjectType oType, 204 XFA_Element eType, 205 const PropertyData* properties, 206 const AttributeData* attributes, 207 const WideStringView& elementName) 208 : CXFA_Node(pDoc, 209 ePacket, 210 validPackets, 211 oType, 212 eType, 213 properties, 214 attributes, 215 elementName, 216 pdfium::MakeUnique<CJX_Node>(this)) {} 217 218CXFA_Node::~CXFA_Node() { 219 ASSERT(!m_pParent); 220 221 CXFA_Node* pNode = m_pChild; 222 while (pNode) { 223 CXFA_Node* pNext = pNode->m_pNext; 224 pNode->m_pParent = nullptr; 225 delete pNode; 226 pNode = pNext; 227 } 228 if (m_pXMLNode && IsOwnXMLNode()) 229 delete m_pXMLNode; 230} 231 232CXFA_Node* CXFA_Node::Clone(bool bRecursive) { 233 CXFA_Node* pClone = m_pDocument->CreateNode(m_ePacket, m_elementType); 234 if (!pClone) 235 return nullptr; 236 237 JSObject()->MergeAllData(pClone); 238 pClone->UpdateNameHash(); 239 if (IsNeedSavingXMLNode()) { 240 std::unique_ptr<CFX_XMLNode> pCloneXML; 241 if (IsAttributeInXML()) { 242 WideString wsName = JSObject() 243 ->TryAttribute(XFA_Attribute::Name, false) 244 .value_or(WideString()); 245 auto pCloneXMLElement = pdfium::MakeUnique<CFX_XMLElement>(wsName); 246 WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value); 247 if (!wsValue.IsEmpty()) 248 pCloneXMLElement->SetTextData(WideString(wsValue)); 249 250 pCloneXML.reset(pCloneXMLElement.release()); 251 pClone->JSObject()->SetEnum(XFA_Attribute::Contains, 252 XFA_AttributeEnum::Unknown, false); 253 } else { 254 pCloneXML = m_pXMLNode->Clone(); 255 } 256 pClone->SetXMLMappingNode(pCloneXML.release()); 257 pClone->SetFlag(XFA_NodeFlag_OwnXMLNode, false); 258 } 259 if (bRecursive) { 260 for (CXFA_Node* pChild = GetFirstChild(); pChild; 261 pChild = pChild->GetNextSibling()) { 262 pClone->InsertChild(pChild->Clone(bRecursive), nullptr); 263 } 264 } 265 pClone->SetFlag(XFA_NodeFlag_Initialized, true); 266 pClone->SetBindingNode(nullptr); 267 return pClone; 268} 269 270CXFA_Node* CXFA_Node::GetPrevSibling() const { 271 if (!m_pParent || m_pParent->m_pChild == this) 272 return nullptr; 273 274 for (CXFA_Node* pNode = m_pParent->m_pChild; pNode; pNode = pNode->m_pNext) { 275 if (pNode->m_pNext == this) 276 return pNode; 277 } 278 return nullptr; 279} 280 281CXFA_Node* CXFA_Node::GetNextContainerSibling() const { 282 CXFA_Node* pNode = m_pNext; 283 while (pNode && pNode->GetObjectType() != XFA_ObjectType::ContainerNode) 284 pNode = pNode->m_pNext; 285 return pNode; 286} 287 288CXFA_Node* CXFA_Node::GetPrevContainerSibling() const { 289 if (!m_pParent || m_pParent->m_pChild == this) 290 return nullptr; 291 292 CXFA_Node* container = nullptr; 293 for (CXFA_Node* pNode = m_pParent->m_pChild; pNode; pNode = pNode->m_pNext) { 294 if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode) 295 container = pNode; 296 if (pNode->m_pNext == this) 297 return container; 298 } 299 return nullptr; 300} 301 302CXFA_Node* CXFA_Node::GetFirstContainerChild() const { 303 CXFA_Node* pNode = m_pChild; 304 while (pNode && pNode->GetObjectType() != XFA_ObjectType::ContainerNode) 305 pNode = pNode->m_pNext; 306 return pNode; 307} 308 309CXFA_Node* CXFA_Node::GetContainerParent() const { 310 CXFA_Node* pNode = m_pParent; 311 while (pNode && pNode->GetObjectType() != XFA_ObjectType::ContainerNode) 312 pNode = pNode->m_pParent; 313 return pNode; 314} 315 316bool CXFA_Node::IsValidInPacket(XFA_PacketType packet) const { 317 return !!(m_ValidPackets & (1 << static_cast<uint8_t>(packet))); 318} 319 320const CXFA_Node::PropertyData* CXFA_Node::GetPropertyData( 321 XFA_Element property) const { 322 if (m_Properties == nullptr) 323 return nullptr; 324 325 for (size_t i = 0;; ++i) { 326 const PropertyData* data = m_Properties + i; 327 if (data->property == XFA_Element::Unknown) 328 break; 329 if (data->property == property) 330 return data; 331 } 332 return nullptr; 333} 334 335bool CXFA_Node::HasProperty(XFA_Element property) const { 336 return !!GetPropertyData(property); 337} 338 339bool CXFA_Node::HasPropertyFlags(XFA_Element property, uint8_t flags) const { 340 const PropertyData* data = GetPropertyData(property); 341 return data && !!(data->flags & flags); 342} 343 344uint8_t CXFA_Node::PropertyOccuranceCount(XFA_Element property) const { 345 const PropertyData* data = GetPropertyData(property); 346 return data ? data->occurance_count : 0; 347} 348 349Optional<XFA_Element> CXFA_Node::GetFirstPropertyWithFlag(uint8_t flag) { 350 if (m_Properties == nullptr) 351 return {}; 352 353 for (size_t i = 0;; ++i) { 354 const PropertyData* data = m_Properties + i; 355 if (data->property == XFA_Element::Unknown) 356 break; 357 if (data->flags & flag) 358 return {data->property}; 359 } 360 return {}; 361} 362 363const CXFA_Node::AttributeData* CXFA_Node::GetAttributeData( 364 XFA_Attribute attr) const { 365 if (m_Attributes == nullptr) 366 return nullptr; 367 368 for (size_t i = 0;; ++i) { 369 const AttributeData* cur_attr = &m_Attributes[i]; 370 if (cur_attr->attribute == XFA_Attribute::Unknown) 371 break; 372 if (cur_attr->attribute == attr) 373 return cur_attr; 374 } 375 return nullptr; 376} 377 378bool CXFA_Node::HasAttribute(XFA_Attribute attr) const { 379 return !!GetAttributeData(attr); 380} 381 382// Note: This Method assumes that i is a valid index .... 383XFA_Attribute CXFA_Node::GetAttribute(size_t i) const { 384 if (m_Attributes == nullptr) 385 return XFA_Attribute::Unknown; 386 return m_Attributes[i].attribute; 387} 388 389XFA_AttributeType CXFA_Node::GetAttributeType(XFA_Attribute type) const { 390 const AttributeData* data = GetAttributeData(type); 391 return data ? data->type : XFA_AttributeType::CData; 392} 393 394std::vector<CXFA_Node*> CXFA_Node::GetNodeList(uint32_t dwTypeFilter, 395 XFA_Element eTypeFilter) { 396 if (eTypeFilter != XFA_Element::Unknown) { 397 std::vector<CXFA_Node*> nodes; 398 for (CXFA_Node* pChild = m_pChild; pChild; pChild = pChild->m_pNext) { 399 if (pChild->GetElementType() == eTypeFilter) 400 nodes.push_back(pChild); 401 } 402 return nodes; 403 } 404 405 if (dwTypeFilter == (XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties)) { 406 std::vector<CXFA_Node*> nodes; 407 for (CXFA_Node* pChild = m_pChild; pChild; pChild = pChild->m_pNext) 408 nodes.push_back(pChild); 409 return nodes; 410 } 411 412 if (dwTypeFilter == 0) 413 return std::vector<CXFA_Node*>(); 414 415 bool bFilterChildren = !!(dwTypeFilter & XFA_NODEFILTER_Children); 416 bool bFilterProperties = !!(dwTypeFilter & XFA_NODEFILTER_Properties); 417 bool bFilterOneOfProperties = !!(dwTypeFilter & XFA_NODEFILTER_OneOfProperty); 418 std::vector<CXFA_Node*> nodes; 419 for (CXFA_Node* pChild = m_pChild; pChild; pChild = pChild->m_pNext) { 420 if (!HasProperty(pChild->GetElementType())) { 421 if (bFilterProperties) { 422 nodes.push_back(pChild); 423 } else if (bFilterOneOfProperties && 424 HasPropertyFlags(pChild->GetElementType(), 425 XFA_PROPERTYFLAG_OneOf)) { 426 nodes.push_back(pChild); 427 } else if (bFilterChildren && 428 (pChild->GetElementType() == XFA_Element::Variables || 429 pChild->GetElementType() == XFA_Element::PageSet)) { 430 nodes.push_back(pChild); 431 } 432 } else if (bFilterChildren) { 433 nodes.push_back(pChild); 434 } 435 } 436 437 if (!bFilterOneOfProperties || !nodes.empty()) 438 return nodes; 439 if (m_Properties == nullptr) 440 return nodes; 441 442 Optional<XFA_Element> property = 443 GetFirstPropertyWithFlag(XFA_PROPERTYFLAG_DefaultOneOf); 444 if (!property) 445 return nodes; 446 447 CXFA_Node* pNewNode = m_pDocument->CreateNode(GetPacketType(), *property); 448 if (pNewNode) { 449 InsertChild(pNewNode, nullptr); 450 pNewNode->SetFlag(XFA_NodeFlag_Initialized, true); 451 nodes.push_back(pNewNode); 452 } 453 return nodes; 454} 455 456CXFA_Node* CXFA_Node::CreateSamePacketNode(XFA_Element eType) { 457 CXFA_Node* pNode = m_pDocument->CreateNode(m_ePacket, eType); 458 pNode->SetFlag(XFA_NodeFlag_Initialized, true); 459 return pNode; 460} 461 462CXFA_Node* CXFA_Node::CloneTemplateToForm(bool bRecursive) { 463 ASSERT(m_ePacket == XFA_PacketType::Template); 464 CXFA_Node* pClone = 465 m_pDocument->CreateNode(XFA_PacketType::Form, m_elementType); 466 if (!pClone) 467 return nullptr; 468 469 pClone->SetTemplateNode(this); 470 pClone->UpdateNameHash(); 471 pClone->SetXMLMappingNode(GetXMLMappingNode()); 472 if (bRecursive) { 473 for (CXFA_Node* pChild = GetFirstChild(); pChild; 474 pChild = pChild->GetNextSibling()) { 475 pClone->InsertChild(pChild->CloneTemplateToForm(bRecursive), nullptr); 476 } 477 } 478 pClone->SetFlag(XFA_NodeFlag_Initialized, true); 479 return pClone; 480} 481 482CXFA_Node* CXFA_Node::GetTemplateNodeIfExists() const { 483 return m_pAuxNode; 484} 485 486void CXFA_Node::SetTemplateNode(CXFA_Node* pTemplateNode) { 487 m_pAuxNode = pTemplateNode; 488} 489 490CXFA_Node* CXFA_Node::GetBindData() { 491 ASSERT(GetPacketType() == XFA_PacketType::Form); 492 return GetBindingNode(); 493} 494 495std::vector<UnownedPtr<CXFA_Node>>* CXFA_Node::GetBindItems() { 496 return GetBindingNodes(); 497} 498 499int32_t CXFA_Node::AddBindItem(CXFA_Node* pFormNode) { 500 ASSERT(pFormNode); 501 502 if (BindsFormItems()) { 503 bool found = false; 504 for (auto& v : binding_nodes_) { 505 if (v.Get() == pFormNode) { 506 found = true; 507 break; 508 } 509 } 510 if (!found) 511 binding_nodes_.emplace_back(pFormNode); 512 return pdfium::CollectionSize<int32_t>(binding_nodes_); 513 } 514 515 CXFA_Node* pOldFormItem = GetBindingNode(); 516 if (!pOldFormItem) { 517 SetBindingNode(pFormNode); 518 return 1; 519 } 520 if (pOldFormItem == pFormNode) 521 return 1; 522 523 std::vector<UnownedPtr<CXFA_Node>> items; 524 items.emplace_back(pOldFormItem); 525 items.emplace_back(pFormNode); 526 SetBindingNodes(std::move(items)); 527 528 m_uNodeFlags |= XFA_NodeFlag_BindFormItems; 529 return 2; 530} 531 532int32_t CXFA_Node::RemoveBindItem(CXFA_Node* pFormNode) { 533 if (BindsFormItems()) { 534 auto it = std::find_if(binding_nodes_.begin(), binding_nodes_.end(), 535 [&pFormNode](const UnownedPtr<CXFA_Node>& node) { 536 return node.Get() == pFormNode; 537 }); 538 if (it != binding_nodes_.end()) 539 binding_nodes_.erase(it); 540 541 if (binding_nodes_.size() == 1) { 542 m_uNodeFlags &= ~XFA_NodeFlag_BindFormItems; 543 return 1; 544 } 545 return pdfium::CollectionSize<int32_t>(binding_nodes_); 546 } 547 548 CXFA_Node* pOldFormItem = GetBindingNode(); 549 if (pOldFormItem != pFormNode) 550 return pOldFormItem ? 1 : 0; 551 552 SetBindingNode(nullptr); 553 return 0; 554} 555 556bool CXFA_Node::HasBindItem() { 557 return GetPacketType() == XFA_PacketType::Datasets && GetBindingNode(); 558} 559 560CXFA_WidgetAcc* CXFA_Node::GetContainerWidgetAcc() { 561 if (GetPacketType() != XFA_PacketType::Form) 562 return nullptr; 563 XFA_Element eType = GetElementType(); 564 if (eType == XFA_Element::ExclGroup) 565 return nullptr; 566 CXFA_Node* pParentNode = GetParent(); 567 if (pParentNode && pParentNode->GetElementType() == XFA_Element::ExclGroup) 568 return nullptr; 569 570 if (eType == XFA_Element::Field) { 571 CXFA_WidgetAcc* pFieldWidgetAcc = GetWidgetAcc(); 572 if (pFieldWidgetAcc && pFieldWidgetAcc->IsChoiceListMultiSelect()) 573 return nullptr; 574 575 WideString wsPicture; 576 if (pFieldWidgetAcc) { 577 wsPicture = pFieldWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind); 578 } 579 if (!wsPicture.IsEmpty()) 580 return pFieldWidgetAcc; 581 582 CXFA_Node* pDataNode = GetBindData(); 583 if (!pDataNode) 584 return nullptr; 585 pFieldWidgetAcc = nullptr; 586 for (const auto& pFormNode : *(pDataNode->GetBindItems())) { 587 if (!pFormNode || pFormNode->HasRemovedChildren()) 588 continue; 589 pFieldWidgetAcc = pFormNode->GetWidgetAcc(); 590 if (pFieldWidgetAcc) { 591 wsPicture = 592 pFieldWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind); 593 } 594 if (!wsPicture.IsEmpty()) 595 break; 596 pFieldWidgetAcc = nullptr; 597 } 598 return pFieldWidgetAcc; 599 } 600 601 CXFA_Node* pGrandNode = pParentNode ? pParentNode->GetParent() : nullptr; 602 CXFA_Node* pValueNode = 603 (pParentNode && pParentNode->GetElementType() == XFA_Element::Value) 604 ? pParentNode 605 : nullptr; 606 if (!pValueNode) { 607 pValueNode = 608 (pGrandNode && pGrandNode->GetElementType() == XFA_Element::Value) 609 ? pGrandNode 610 : nullptr; 611 } 612 CXFA_Node* pParentOfValueNode = 613 pValueNode ? pValueNode->GetParent() : nullptr; 614 return pParentOfValueNode ? pParentOfValueNode->GetContainerWidgetAcc() 615 : nullptr; 616} 617 618IFX_Locale* CXFA_Node::GetLocale() { 619 Optional<WideString> localeName = GetLocaleName(); 620 if (!localeName) 621 return nullptr; 622 if (localeName.value() == L"ambient") 623 return GetDocument()->GetLocalMgr()->GetDefLocale(); 624 return GetDocument()->GetLocalMgr()->GetLocaleByName(localeName.value()); 625} 626 627Optional<WideString> CXFA_Node::GetLocaleName() { 628 CXFA_Node* pForm = GetDocument()->GetXFAObject(XFA_HASHCODE_Form)->AsNode(); 629 CXFA_Subform* pTopSubform = 630 pForm->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform); 631 ASSERT(pTopSubform); 632 633 CXFA_Node* pLocaleNode = this; 634 do { 635 Optional<WideString> localeName = 636 pLocaleNode->JSObject()->TryCData(XFA_Attribute::Locale, false); 637 if (localeName) 638 return localeName; 639 640 pLocaleNode = pLocaleNode->GetParent(); 641 } while (pLocaleNode && pLocaleNode != pTopSubform); 642 643 CXFA_Node* pConfig = ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Config)); 644 Optional<WideString> localeName = { 645 WideString(GetDocument()->GetLocalMgr()->GetConfigLocaleName(pConfig))}; 646 if (localeName && !localeName->IsEmpty()) 647 return localeName; 648 649 if (pTopSubform) { 650 localeName = 651 pTopSubform->JSObject()->TryCData(XFA_Attribute::Locale, false); 652 if (localeName) 653 return localeName; 654 } 655 656 IFX_Locale* pLocale = GetDocument()->GetLocalMgr()->GetDefLocale(); 657 if (!pLocale) 658 return {}; 659 660 return {pLocale->GetName()}; 661} 662 663XFA_AttributeEnum CXFA_Node::GetIntact() { 664 CXFA_Keep* pKeep = GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep); 665 XFA_AttributeEnum eLayoutType = JSObject() 666 ->TryEnum(XFA_Attribute::Layout, true) 667 .value_or(XFA_AttributeEnum::Position); 668 if (pKeep) { 669 Optional<XFA_AttributeEnum> intact = 670 pKeep->JSObject()->TryEnum(XFA_Attribute::Intact, false); 671 if (intact) { 672 if (*intact == XFA_AttributeEnum::None && 673 eLayoutType == XFA_AttributeEnum::Row && 674 m_pDocument->GetCurVersionMode() < XFA_VERSION_208) { 675 CXFA_Node* pPreviewRow = GetPrevContainerSibling(); 676 if (pPreviewRow && 677 pPreviewRow->JSObject()->GetEnum(XFA_Attribute::Layout) == 678 XFA_AttributeEnum::Row) { 679 Optional<XFA_AttributeEnum> value = 680 pKeep->JSObject()->TryEnum(XFA_Attribute::Previous, false); 681 if (value && (*value == XFA_AttributeEnum::ContentArea || 682 *value == XFA_AttributeEnum::PageArea)) { 683 return XFA_AttributeEnum::ContentArea; 684 } 685 686 CXFA_Keep* pNode = 687 pPreviewRow->GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep); 688 Optional<XFA_AttributeEnum> ret; 689 if (pNode) 690 ret = pNode->JSObject()->TryEnum(XFA_Attribute::Next, false); 691 if (ret && (*ret == XFA_AttributeEnum::ContentArea || 692 *ret == XFA_AttributeEnum::PageArea)) { 693 return XFA_AttributeEnum::ContentArea; 694 } 695 } 696 } 697 return *intact; 698 } 699 } 700 701 switch (GetElementType()) { 702 case XFA_Element::Subform: 703 switch (eLayoutType) { 704 case XFA_AttributeEnum::Position: 705 case XFA_AttributeEnum::Row: 706 return XFA_AttributeEnum::ContentArea; 707 default: 708 return XFA_AttributeEnum::None; 709 } 710 case XFA_Element::Field: { 711 CXFA_Node* parent = GetParent(); 712 if (!parent || parent->GetElementType() == XFA_Element::PageArea) 713 return XFA_AttributeEnum::ContentArea; 714 if (parent->GetIntact() != XFA_AttributeEnum::None) 715 return XFA_AttributeEnum::ContentArea; 716 717 XFA_AttributeEnum eParLayout = parent->JSObject() 718 ->TryEnum(XFA_Attribute::Layout, true) 719 .value_or(XFA_AttributeEnum::Position); 720 if (eParLayout == XFA_AttributeEnum::Position || 721 eParLayout == XFA_AttributeEnum::Row || 722 eParLayout == XFA_AttributeEnum::Table) { 723 return XFA_AttributeEnum::None; 724 } 725 726 XFA_VERSION version = m_pDocument->GetCurVersionMode(); 727 if (eParLayout == XFA_AttributeEnum::Tb && version < XFA_VERSION_208) { 728 Optional<CXFA_Measurement> measureH = 729 JSObject()->TryMeasure(XFA_Attribute::H, false); 730 if (measureH) 731 return XFA_AttributeEnum::ContentArea; 732 } 733 return XFA_AttributeEnum::None; 734 } 735 case XFA_Element::Draw: 736 return XFA_AttributeEnum::ContentArea; 737 default: 738 return XFA_AttributeEnum::None; 739 } 740} 741 742CXFA_Node* CXFA_Node::GetDataDescriptionNode() { 743 if (m_ePacket == XFA_PacketType::Datasets) 744 return m_pAuxNode; 745 return nullptr; 746} 747 748void CXFA_Node::SetDataDescriptionNode(CXFA_Node* pDataDescriptionNode) { 749 ASSERT(m_ePacket == XFA_PacketType::Datasets); 750 m_pAuxNode = pDataDescriptionNode; 751} 752 753CXFA_Node* CXFA_Node::GetModelNode() { 754 switch (GetPacketType()) { 755 case XFA_PacketType::Xdp: 756 return m_pDocument->GetRoot(); 757 case XFA_PacketType::Config: 758 return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config)); 759 case XFA_PacketType::Template: 760 return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Template)); 761 case XFA_PacketType::Form: 762 return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form)); 763 case XFA_PacketType::Datasets: 764 return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Datasets)); 765 case XFA_PacketType::LocaleSet: 766 return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_LocaleSet)); 767 case XFA_PacketType::ConnectionSet: 768 return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_ConnectionSet)); 769 case XFA_PacketType::SourceSet: 770 return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_SourceSet)); 771 case XFA_PacketType::Xdc: 772 return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Xdc)); 773 default: 774 return this; 775 } 776} 777 778size_t CXFA_Node::CountChildren(XFA_Element eType, bool bOnlyChild) { 779 size_t count = 0; 780 for (CXFA_Node* pNode = m_pChild; pNode; pNode = pNode->GetNextSibling()) { 781 if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown) 782 continue; 783 if (bOnlyChild && HasProperty(pNode->GetElementType())) 784 continue; 785 ++count; 786 } 787 return count; 788} 789 790CXFA_Node* CXFA_Node::GetChildInternal(size_t index, 791 XFA_Element eType, 792 bool bOnlyChild) { 793 size_t count = 0; 794 for (CXFA_Node* pNode = m_pChild; pNode; pNode = pNode->GetNextSibling()) { 795 if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown) 796 continue; 797 if (bOnlyChild && HasProperty(pNode->GetElementType())) 798 continue; 799 if (count == index) 800 return pNode; 801 802 ++count; 803 } 804 return nullptr; 805} 806 807int32_t CXFA_Node::InsertChild(int32_t index, CXFA_Node* pNode) { 808 ASSERT(!pNode->m_pNext); 809 pNode->m_pParent = this; 810 bool ret = m_pDocument->RemovePurgeNode(pNode); 811 ASSERT(ret); 812 (void)ret; // Avoid unused variable warning. 813 814 if (!m_pChild || index == 0) { 815 if (index > 0) { 816 return -1; 817 } 818 pNode->m_pNext = m_pChild; 819 m_pChild = pNode; 820 index = 0; 821 } else if (index < 0) { 822 m_pLastChild->m_pNext = pNode; 823 } else { 824 CXFA_Node* pPrev = m_pChild; 825 int32_t iCount = 0; 826 while (++iCount != index && pPrev->m_pNext) { 827 pPrev = pPrev->m_pNext; 828 } 829 if (index > 0 && index != iCount) { 830 return -1; 831 } 832 pNode->m_pNext = pPrev->m_pNext; 833 pPrev->m_pNext = pNode; 834 index = iCount; 835 } 836 if (!pNode->m_pNext) { 837 m_pLastChild = pNode; 838 } 839 ASSERT(m_pLastChild); 840 ASSERT(!m_pLastChild->m_pNext); 841 pNode->ClearFlag(XFA_NodeFlag_HasRemovedChildren); 842 CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); 843 if (pNotify) 844 pNotify->OnChildAdded(this); 845 846 if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { 847 ASSERT(!pNode->m_pXMLNode->GetNodeItem(CFX_XMLNode::Parent)); 848 m_pXMLNode->InsertChildNode(pNode->m_pXMLNode, index); 849 pNode->ClearFlag(XFA_NodeFlag_OwnXMLNode); 850 } 851 return index; 852} 853 854bool CXFA_Node::InsertChild(CXFA_Node* pNode, CXFA_Node* pBeforeNode) { 855 if (!pNode || pNode->m_pParent || 856 (pBeforeNode && pBeforeNode->m_pParent != this)) { 857 NOTREACHED(); 858 return false; 859 } 860 bool ret = m_pDocument->RemovePurgeNode(pNode); 861 ASSERT(ret); 862 (void)ret; // Avoid unused variable warning. 863 864 int32_t nIndex = -1; 865 pNode->m_pParent = this; 866 if (!m_pChild || pBeforeNode == m_pChild) { 867 pNode->m_pNext = m_pChild; 868 m_pChild = pNode; 869 nIndex = 0; 870 } else if (!pBeforeNode) { 871 pNode->m_pNext = m_pLastChild->m_pNext; 872 m_pLastChild->m_pNext = pNode; 873 } else { 874 nIndex = 1; 875 CXFA_Node* pPrev = m_pChild; 876 while (pPrev->m_pNext != pBeforeNode) { 877 pPrev = pPrev->m_pNext; 878 nIndex++; 879 } 880 pNode->m_pNext = pPrev->m_pNext; 881 pPrev->m_pNext = pNode; 882 } 883 if (!pNode->m_pNext) { 884 m_pLastChild = pNode; 885 } 886 ASSERT(m_pLastChild); 887 ASSERT(!m_pLastChild->m_pNext); 888 pNode->ClearFlag(XFA_NodeFlag_HasRemovedChildren); 889 CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); 890 if (pNotify) 891 pNotify->OnChildAdded(this); 892 893 if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { 894 ASSERT(!pNode->m_pXMLNode->GetNodeItem(CFX_XMLNode::Parent)); 895 m_pXMLNode->InsertChildNode(pNode->m_pXMLNode, nIndex); 896 pNode->ClearFlag(XFA_NodeFlag_OwnXMLNode); 897 } 898 return true; 899} 900 901CXFA_Node* CXFA_Node::Deprecated_GetPrevSibling() { 902 if (!m_pParent) { 903 return nullptr; 904 } 905 for (CXFA_Node* pSibling = m_pParent->m_pChild; pSibling; 906 pSibling = pSibling->m_pNext) { 907 if (pSibling->m_pNext == this) { 908 return pSibling; 909 } 910 } 911 return nullptr; 912} 913 914bool CXFA_Node::RemoveChild(CXFA_Node* pNode, bool bNotify) { 915 if (!pNode || pNode->m_pParent != this) { 916 NOTREACHED(); 917 return false; 918 } 919 if (m_pChild == pNode) { 920 m_pChild = pNode->m_pNext; 921 if (m_pLastChild == pNode) { 922 m_pLastChild = pNode->m_pNext; 923 } 924 pNode->m_pNext = nullptr; 925 pNode->m_pParent = nullptr; 926 } else { 927 CXFA_Node* pPrev = pNode->Deprecated_GetPrevSibling(); 928 pPrev->m_pNext = pNode->m_pNext; 929 if (m_pLastChild == pNode) { 930 m_pLastChild = pNode->m_pNext ? pNode->m_pNext : pPrev; 931 } 932 pNode->m_pNext = nullptr; 933 pNode->m_pParent = nullptr; 934 } 935 ASSERT(!m_pLastChild || !m_pLastChild->m_pNext); 936 OnRemoved(bNotify); 937 pNode->SetFlag(XFA_NodeFlag_HasRemovedChildren, true); 938 m_pDocument->AddPurgeNode(pNode); 939 if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { 940 if (pNode->IsAttributeInXML()) { 941 ASSERT(pNode->m_pXMLNode == m_pXMLNode && 942 m_pXMLNode->GetType() == FX_XMLNODE_Element); 943 if (pNode->m_pXMLNode->GetType() == FX_XMLNODE_Element) { 944 CFX_XMLElement* pXMLElement = 945 static_cast<CFX_XMLElement*>(pNode->m_pXMLNode); 946 WideString wsAttributeName = 947 pNode->JSObject()->GetCData(XFA_Attribute::QualifiedName); 948 pXMLElement->RemoveAttribute(wsAttributeName.c_str()); 949 } 950 951 WideString wsName = pNode->JSObject() 952 ->TryAttribute(XFA_Attribute::Name, false) 953 .value_or(WideString()); 954 CFX_XMLElement* pNewXMLElement = new CFX_XMLElement(wsName); 955 WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value); 956 if (!wsValue.IsEmpty()) 957 pNewXMLElement->SetTextData(WideString(wsValue)); 958 959 pNode->m_pXMLNode = pNewXMLElement; 960 pNode->JSObject()->SetEnum(XFA_Attribute::Contains, 961 XFA_AttributeEnum::Unknown, false); 962 } else { 963 m_pXMLNode->RemoveChildNode(pNode->m_pXMLNode); 964 } 965 pNode->SetFlag(XFA_NodeFlag_OwnXMLNode, false); 966 } 967 return true; 968} 969 970CXFA_Node* CXFA_Node::GetFirstChildByName(const WideStringView& wsName) const { 971 return GetFirstChildByName(FX_HashCode_GetW(wsName, false)); 972} 973 974CXFA_Node* CXFA_Node::GetFirstChildByName(uint32_t dwNameHash) const { 975 for (CXFA_Node* pNode = GetFirstChild(); pNode; 976 pNode = pNode->GetNextSibling()) { 977 if (pNode->GetNameHash() == dwNameHash) { 978 return pNode; 979 } 980 } 981 return nullptr; 982} 983 984CXFA_Node* CXFA_Node::GetFirstChildByClassInternal(XFA_Element eType) const { 985 for (CXFA_Node* pNode = GetFirstChild(); pNode; 986 pNode = pNode->GetNextSibling()) { 987 if (pNode->GetElementType() == eType) { 988 return pNode; 989 } 990 } 991 return nullptr; 992} 993 994CXFA_Node* CXFA_Node::GetNextSameNameSibling(uint32_t dwNameHash) const { 995 for (CXFA_Node* pNode = GetNextSibling(); pNode; 996 pNode = pNode->GetNextSibling()) { 997 if (pNode->GetNameHash() == dwNameHash) { 998 return pNode; 999 } 1000 } 1001 return nullptr; 1002} 1003 1004CXFA_Node* CXFA_Node::GetNextSameNameSiblingInternal( 1005 const WideStringView& wsNodeName) const { 1006 return GetNextSameNameSibling(FX_HashCode_GetW(wsNodeName, false)); 1007} 1008 1009CXFA_Node* CXFA_Node::GetNextSameClassSiblingInternal(XFA_Element eType) const { 1010 for (CXFA_Node* pNode = GetNextSibling(); pNode; 1011 pNode = pNode->GetNextSibling()) { 1012 if (pNode->GetElementType() == eType) { 1013 return pNode; 1014 } 1015 } 1016 return nullptr; 1017} 1018 1019int32_t CXFA_Node::GetNodeSameNameIndex() const { 1020 CFXJSE_Engine* pScriptContext = m_pDocument->GetScriptContext(); 1021 if (!pScriptContext) { 1022 return -1; 1023 } 1024 return pScriptContext->GetIndexByName(const_cast<CXFA_Node*>(this)); 1025} 1026 1027int32_t CXFA_Node::GetNodeSameClassIndex() const { 1028 CFXJSE_Engine* pScriptContext = m_pDocument->GetScriptContext(); 1029 if (!pScriptContext) { 1030 return -1; 1031 } 1032 return pScriptContext->GetIndexByClassName(const_cast<CXFA_Node*>(this)); 1033} 1034 1035CXFA_Node* CXFA_Node::GetInstanceMgrOfSubform() { 1036 CXFA_Node* pInstanceMgr = nullptr; 1037 if (m_ePacket == XFA_PacketType::Form) { 1038 CXFA_Node* pParentNode = GetParent(); 1039 if (!pParentNode || pParentNode->GetElementType() == XFA_Element::Area) { 1040 return pInstanceMgr; 1041 } 1042 for (CXFA_Node* pNode = GetPrevSibling(); pNode; 1043 pNode = pNode->GetPrevSibling()) { 1044 XFA_Element eType = pNode->GetElementType(); 1045 if ((eType == XFA_Element::Subform || eType == XFA_Element::SubformSet) && 1046 pNode->m_dwNameHash != m_dwNameHash) { 1047 break; 1048 } 1049 if (eType == XFA_Element::InstanceManager) { 1050 WideString wsName = JSObject()->GetCData(XFA_Attribute::Name); 1051 WideString wsInstName = 1052 pNode->JSObject()->GetCData(XFA_Attribute::Name); 1053 if (wsInstName.GetLength() > 0 && wsInstName[0] == '_' && 1054 wsInstName.Right(wsInstName.GetLength() - 1) == wsName) { 1055 pInstanceMgr = pNode; 1056 } 1057 break; 1058 } 1059 } 1060 } 1061 return pInstanceMgr; 1062} 1063 1064CXFA_Occur* CXFA_Node::GetOccurIfExists() { 1065 return GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); 1066} 1067 1068bool CXFA_Node::HasFlag(XFA_NodeFlag dwFlag) const { 1069 if (m_uNodeFlags & dwFlag) 1070 return true; 1071 if (dwFlag == XFA_NodeFlag_HasRemovedChildren) 1072 return m_pParent && m_pParent->HasFlag(dwFlag); 1073 return false; 1074} 1075 1076void CXFA_Node::SetFlag(uint32_t dwFlag, bool bNotify) { 1077 if (dwFlag == XFA_NodeFlag_Initialized && bNotify && !IsInitialized()) { 1078 CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); 1079 if (pNotify) { 1080 pNotify->OnNodeReady(this); 1081 } 1082 } 1083 m_uNodeFlags |= dwFlag; 1084} 1085 1086void CXFA_Node::ClearFlag(uint32_t dwFlag) { 1087 m_uNodeFlags &= ~dwFlag; 1088} 1089 1090void CXFA_Node::ReleaseBindingNodes() { 1091 // Clear any binding nodes as we don't necessarily destruct in an order that 1092 // makes sense. 1093 for (auto& node : binding_nodes_) 1094 node.Release(); 1095 1096 for (CXFA_Node* pNode = m_pChild; pNode; pNode = pNode->m_pNext) 1097 pNode->ReleaseBindingNodes(); 1098} 1099 1100bool CXFA_Node::IsAttributeInXML() { 1101 return JSObject()->GetEnum(XFA_Attribute::Contains) == 1102 XFA_AttributeEnum::MetaData; 1103} 1104 1105void CXFA_Node::OnRemoved(bool bNotify) { 1106 if (!bNotify) 1107 return; 1108 1109 CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); 1110 if (pNotify) 1111 pNotify->OnChildRemoved(); 1112} 1113 1114void CXFA_Node::UpdateNameHash() { 1115 WideString wsName = JSObject()->GetCData(XFA_Attribute::Name); 1116 m_dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false); 1117} 1118 1119CFX_XMLNode* CXFA_Node::CreateXMLMappingNode() { 1120 if (!m_pXMLNode) { 1121 WideString wsTag(JSObject()->GetCData(XFA_Attribute::Name)); 1122 m_pXMLNode = new CFX_XMLElement(wsTag); 1123 SetFlag(XFA_NodeFlag_OwnXMLNode, false); 1124 } 1125 return m_pXMLNode; 1126} 1127 1128bool CXFA_Node::IsNeedSavingXMLNode() { 1129 return m_pXMLNode && (GetPacketType() == XFA_PacketType::Datasets || 1130 GetElementType() == XFA_Element::Xfa); 1131} 1132 1133CXFA_Node* CXFA_Node::GetItemIfExists(int32_t iIndex) { 1134 int32_t iCount = 0; 1135 uint32_t dwNameHash = 0; 1136 for (CXFA_Node* pNode = GetNextSibling(); pNode; 1137 pNode = pNode->GetNextSibling()) { 1138 XFA_Element eCurType = pNode->GetElementType(); 1139 if (eCurType == XFA_Element::InstanceManager) 1140 break; 1141 if ((eCurType != XFA_Element::Subform) && 1142 (eCurType != XFA_Element::SubformSet)) { 1143 continue; 1144 } 1145 if (iCount == 0) { 1146 WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name); 1147 WideString wsInstName = JSObject()->GetCData(XFA_Attribute::Name); 1148 if (wsInstName.GetLength() < 1 || wsInstName[0] != '_' || 1149 wsInstName.Right(wsInstName.GetLength() - 1) != wsName) { 1150 return nullptr; 1151 } 1152 dwNameHash = pNode->GetNameHash(); 1153 } 1154 if (dwNameHash != pNode->GetNameHash()) 1155 break; 1156 1157 iCount++; 1158 if (iCount > iIndex) 1159 return pNode; 1160 } 1161 return nullptr; 1162} 1163 1164int32_t CXFA_Node::GetCount() { 1165 int32_t iCount = 0; 1166 uint32_t dwNameHash = 0; 1167 for (CXFA_Node* pNode = GetNextSibling(); pNode; 1168 pNode = pNode->GetNextSibling()) { 1169 XFA_Element eCurType = pNode->GetElementType(); 1170 if (eCurType == XFA_Element::InstanceManager) 1171 break; 1172 if ((eCurType != XFA_Element::Subform) && 1173 (eCurType != XFA_Element::SubformSet)) { 1174 continue; 1175 } 1176 if (iCount == 0) { 1177 WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name); 1178 WideString wsInstName = JSObject()->GetCData(XFA_Attribute::Name); 1179 if (wsInstName.GetLength() < 1 || wsInstName[0] != '_' || 1180 wsInstName.Right(wsInstName.GetLength() - 1) != wsName) { 1181 return iCount; 1182 } 1183 dwNameHash = pNode->GetNameHash(); 1184 } 1185 if (dwNameHash != pNode->GetNameHash()) 1186 break; 1187 1188 iCount++; 1189 } 1190 return iCount; 1191} 1192 1193void CXFA_Node::InsertItem(CXFA_Node* pNewInstance, 1194 int32_t iPos, 1195 int32_t iCount, 1196 bool bMoveDataBindingNodes) { 1197 if (iCount < 0) 1198 iCount = GetCount(); 1199 if (iPos < 0) 1200 iPos = iCount; 1201 if (iPos == iCount) { 1202 CXFA_Node* item = GetItemIfExists(iCount - 1); 1203 if (!item) 1204 return; 1205 1206 CXFA_Node* pNextSibling = 1207 iCount > 0 ? item->GetNextSibling() : GetNextSibling(); 1208 GetParent()->InsertChild(pNewInstance, pNextSibling); 1209 if (bMoveDataBindingNodes) { 1210 std::set<CXFA_Node*> sNew; 1211 std::set<CXFA_Node*> sAfter; 1212 CXFA_NodeIteratorTemplate<CXFA_Node, 1213 CXFA_TraverseStrategy_XFAContainerNode> 1214 sIteratorNew(pNewInstance); 1215 for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode; 1216 pNode = sIteratorNew.MoveToNext()) { 1217 CXFA_Node* pDataNode = pNode->GetBindData(); 1218 if (!pDataNode) 1219 continue; 1220 1221 sNew.insert(pDataNode); 1222 } 1223 CXFA_NodeIteratorTemplate<CXFA_Node, 1224 CXFA_TraverseStrategy_XFAContainerNode> 1225 sIteratorAfter(pNextSibling); 1226 for (CXFA_Node* pNode = sIteratorAfter.GetCurrent(); pNode; 1227 pNode = sIteratorAfter.MoveToNext()) { 1228 CXFA_Node* pDataNode = pNode->GetBindData(); 1229 if (!pDataNode) 1230 continue; 1231 1232 sAfter.insert(pDataNode); 1233 } 1234 ReorderDataNodes(sNew, sAfter, false); 1235 } 1236 } else { 1237 CXFA_Node* pBeforeInstance = GetItemIfExists(iPos); 1238 if (!pBeforeInstance) { 1239 // TODO(dsinclair): What should happen here? 1240 return; 1241 } 1242 1243 GetParent()->InsertChild(pNewInstance, pBeforeInstance); 1244 if (bMoveDataBindingNodes) { 1245 std::set<CXFA_Node*> sNew; 1246 std::set<CXFA_Node*> sBefore; 1247 CXFA_NodeIteratorTemplate<CXFA_Node, 1248 CXFA_TraverseStrategy_XFAContainerNode> 1249 sIteratorNew(pNewInstance); 1250 for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode; 1251 pNode = sIteratorNew.MoveToNext()) { 1252 CXFA_Node* pDataNode = pNode->GetBindData(); 1253 if (!pDataNode) 1254 continue; 1255 1256 sNew.insert(pDataNode); 1257 } 1258 CXFA_NodeIteratorTemplate<CXFA_Node, 1259 CXFA_TraverseStrategy_XFAContainerNode> 1260 sIteratorBefore(pBeforeInstance); 1261 for (CXFA_Node* pNode = sIteratorBefore.GetCurrent(); pNode; 1262 pNode = sIteratorBefore.MoveToNext()) { 1263 CXFA_Node* pDataNode = pNode->GetBindData(); 1264 if (!pDataNode) 1265 continue; 1266 1267 sBefore.insert(pDataNode); 1268 } 1269 ReorderDataNodes(sNew, sBefore, true); 1270 } 1271 } 1272} 1273 1274void CXFA_Node::RemoveItem(CXFA_Node* pRemoveInstance, 1275 bool bRemoveDataBinding) { 1276 GetParent()->RemoveChild(pRemoveInstance, true); 1277 if (!bRemoveDataBinding) 1278 return; 1279 1280 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode> 1281 sIterator(pRemoveInstance); 1282 for (CXFA_Node* pFormNode = sIterator.GetCurrent(); pFormNode; 1283 pFormNode = sIterator.MoveToNext()) { 1284 CXFA_Node* pDataNode = pFormNode->GetBindData(); 1285 if (!pDataNode) 1286 continue; 1287 1288 if (pDataNode->RemoveBindItem(pFormNode) == 0) { 1289 if (CXFA_Node* pDataParent = pDataNode->GetParent()) { 1290 pDataParent->RemoveChild(pDataNode, true); 1291 } 1292 } 1293 pFormNode->SetBindingNode(nullptr); 1294 } 1295} 1296 1297CXFA_Node* CXFA_Node::CreateInstanceIfPossible(bool bDataMerge) { 1298 CXFA_Document* pDocument = GetDocument(); 1299 CXFA_Node* pTemplateNode = GetTemplateNodeIfExists(); 1300 if (!pTemplateNode) 1301 return nullptr; 1302 1303 CXFA_Node* pFormParent = GetParent(); 1304 CXFA_Node* pDataScope = nullptr; 1305 for (CXFA_Node* pRootBoundNode = pFormParent; 1306 pRootBoundNode && pRootBoundNode->IsContainerNode(); 1307 pRootBoundNode = pRootBoundNode->GetParent()) { 1308 pDataScope = pRootBoundNode->GetBindData(); 1309 if (pDataScope) 1310 break; 1311 } 1312 if (!pDataScope) { 1313 pDataScope = ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record)); 1314 ASSERT(pDataScope); 1315 } 1316 1317 CXFA_Node* pInstance = pDocument->DataMerge_CopyContainer( 1318 pTemplateNode, pFormParent, pDataScope, true, bDataMerge, true); 1319 if (pInstance) { 1320 pDocument->DataMerge_UpdateBindingRelations(pInstance); 1321 pFormParent->RemoveChild(pInstance, true); 1322 } 1323 return pInstance; 1324} 1325 1326Optional<bool> CXFA_Node::GetDefaultBoolean(XFA_Attribute attr) const { 1327 Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Boolean); 1328 if (!value) 1329 return {}; 1330 return {!!*value}; 1331} 1332 1333Optional<int32_t> CXFA_Node::GetDefaultInteger(XFA_Attribute attr) const { 1334 Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Integer); 1335 if (!value) 1336 return {}; 1337 return {static_cast<int32_t>(reinterpret_cast<uintptr_t>(*value))}; 1338} 1339 1340Optional<CXFA_Measurement> CXFA_Node::GetDefaultMeasurement( 1341 XFA_Attribute attr) const { 1342 Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Measure); 1343 if (!value) 1344 return {}; 1345 1346 WideString str = WideString(static_cast<const wchar_t*>(*value)); 1347 return {CXFA_Measurement(str.AsStringView())}; 1348} 1349 1350Optional<WideString> CXFA_Node::GetDefaultCData(XFA_Attribute attr) const { 1351 Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::CData); 1352 if (!value) 1353 return {}; 1354 1355 return {WideString(static_cast<const wchar_t*>(*value))}; 1356} 1357 1358Optional<XFA_AttributeEnum> CXFA_Node::GetDefaultEnum( 1359 XFA_Attribute attr) const { 1360 Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Enum); 1361 if (!value) 1362 return {}; 1363 return {static_cast<XFA_AttributeEnum>(reinterpret_cast<uintptr_t>(*value))}; 1364} 1365 1366Optional<void*> CXFA_Node::GetDefaultValue(XFA_Attribute attr, 1367 XFA_AttributeType eType) const { 1368 const AttributeData* data = GetAttributeData(attr); 1369 if (!data) 1370 return {}; 1371 if (data->type == eType) 1372 return {data->default_value}; 1373 return {}; 1374} 1375 1376void CXFA_Node::SendAttributeChangeMessage(XFA_Attribute eAttribute, 1377 bool bScriptModify) { 1378 CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor(); 1379 if (!pLayoutPro) 1380 return; 1381 1382 CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); 1383 if (!pNotify) 1384 return; 1385 1386 if (GetPacketType() != XFA_PacketType::Form) { 1387 pNotify->OnValueChanged(this, eAttribute, this, this); 1388 return; 1389 } 1390 1391 bool bNeedFindContainer = false; 1392 switch (GetElementType()) { 1393 case XFA_Element::Caption: 1394 bNeedFindContainer = true; 1395 pNotify->OnValueChanged(this, eAttribute, this, GetParent()); 1396 break; 1397 case XFA_Element::Font: 1398 case XFA_Element::Para: { 1399 bNeedFindContainer = true; 1400 CXFA_Node* pParentNode = GetParent(); 1401 if (pParentNode->GetElementType() == XFA_Element::Caption) { 1402 pNotify->OnValueChanged(this, eAttribute, pParentNode, 1403 pParentNode->GetParent()); 1404 } else { 1405 pNotify->OnValueChanged(this, eAttribute, this, pParentNode); 1406 } 1407 break; 1408 } 1409 case XFA_Element::Margin: { 1410 bNeedFindContainer = true; 1411 CXFA_Node* pParentNode = GetParent(); 1412 XFA_Element eParentType = pParentNode->GetElementType(); 1413 if (pParentNode->IsContainerNode()) { 1414 pNotify->OnValueChanged(this, eAttribute, this, pParentNode); 1415 } else if (eParentType == XFA_Element::Caption) { 1416 pNotify->OnValueChanged(this, eAttribute, pParentNode, 1417 pParentNode->GetParent()); 1418 } else { 1419 CXFA_Node* pNode = pParentNode->GetParent(); 1420 if (pNode && pNode->GetElementType() == XFA_Element::Ui) { 1421 pNotify->OnValueChanged(this, eAttribute, pNode, pNode->GetParent()); 1422 } 1423 } 1424 break; 1425 } 1426 case XFA_Element::Comb: { 1427 CXFA_Node* pEditNode = GetParent(); 1428 XFA_Element eUIType = pEditNode->GetElementType(); 1429 if (pEditNode && (eUIType == XFA_Element::DateTimeEdit || 1430 eUIType == XFA_Element::NumericEdit || 1431 eUIType == XFA_Element::TextEdit)) { 1432 CXFA_Node* pUINode = pEditNode->GetParent(); 1433 if (pUINode) { 1434 pNotify->OnValueChanged(this, eAttribute, pUINode, 1435 pUINode->GetParent()); 1436 } 1437 } 1438 break; 1439 } 1440 case XFA_Element::Button: 1441 case XFA_Element::Barcode: 1442 case XFA_Element::ChoiceList: 1443 case XFA_Element::DateTimeEdit: 1444 case XFA_Element::NumericEdit: 1445 case XFA_Element::PasswordEdit: 1446 case XFA_Element::TextEdit: { 1447 CXFA_Node* pUINode = GetParent(); 1448 if (pUINode) { 1449 pNotify->OnValueChanged(this, eAttribute, pUINode, 1450 pUINode->GetParent()); 1451 } 1452 break; 1453 } 1454 case XFA_Element::CheckButton: { 1455 bNeedFindContainer = true; 1456 CXFA_Node* pUINode = GetParent(); 1457 if (pUINode) { 1458 pNotify->OnValueChanged(this, eAttribute, pUINode, 1459 pUINode->GetParent()); 1460 } 1461 break; 1462 } 1463 case XFA_Element::Keep: 1464 case XFA_Element::Bookend: 1465 case XFA_Element::Break: 1466 case XFA_Element::BreakAfter: 1467 case XFA_Element::BreakBefore: 1468 case XFA_Element::Overflow: 1469 bNeedFindContainer = true; 1470 break; 1471 case XFA_Element::Area: 1472 case XFA_Element::Draw: 1473 case XFA_Element::ExclGroup: 1474 case XFA_Element::Field: 1475 case XFA_Element::Subform: 1476 case XFA_Element::SubformSet: 1477 pLayoutPro->AddChangedContainer(this); 1478 pNotify->OnValueChanged(this, eAttribute, this, this); 1479 break; 1480 case XFA_Element::Sharptext: 1481 case XFA_Element::Sharpxml: 1482 case XFA_Element::SharpxHTML: { 1483 CXFA_Node* pTextNode = GetParent(); 1484 if (!pTextNode) 1485 return; 1486 1487 CXFA_Node* pValueNode = pTextNode->GetParent(); 1488 if (!pValueNode) 1489 return; 1490 1491 XFA_Element eType = pValueNode->GetElementType(); 1492 if (eType == XFA_Element::Value) { 1493 bNeedFindContainer = true; 1494 CXFA_Node* pNode = pValueNode->GetParent(); 1495 if (pNode && pNode->IsContainerNode()) { 1496 if (bScriptModify) 1497 pValueNode = pNode; 1498 1499 pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode); 1500 } else { 1501 pNotify->OnValueChanged(this, eAttribute, pNode, pNode->GetParent()); 1502 } 1503 } else { 1504 if (eType == XFA_Element::Items) { 1505 CXFA_Node* pNode = pValueNode->GetParent(); 1506 if (pNode && pNode->IsContainerNode()) { 1507 pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode); 1508 } 1509 } 1510 } 1511 break; 1512 } 1513 default: 1514 break; 1515 } 1516 1517 if (!bNeedFindContainer) 1518 return; 1519 1520 CXFA_Node* pParent = this; 1521 while (pParent && !pParent->IsContainerNode()) 1522 pParent = pParent->GetParent(); 1523 1524 if (pParent) 1525 pLayoutPro->AddChangedContainer(pParent); 1526} 1527 1528void CXFA_Node::SyncValue(const WideString& wsValue, bool bNotify) { 1529 WideString wsFormatValue = wsValue; 1530 CXFA_WidgetAcc* pContainerWidgetAcc = GetContainerWidgetAcc(); 1531 if (pContainerWidgetAcc) 1532 wsFormatValue = pContainerWidgetAcc->GetFormatDataValue(wsValue); 1533 1534 JSObject()->SetContent(wsValue, wsFormatValue, bNotify, false, true); 1535} 1536 1537WideString CXFA_Node::GetRawValue() { 1538 return JSObject()->GetContent(false); 1539} 1540 1541int32_t CXFA_Node::GetRotate() { 1542 Optional<int32_t> degrees = 1543 JSObject()->TryInteger(XFA_Attribute::Rotate, false); 1544 return degrees ? XFA_MapRotation(*degrees) / 90 * 90 : 0; 1545} 1546 1547CXFA_Border* CXFA_Node::GetBorderIfExists() const { 1548 return JSObject()->GetProperty<CXFA_Border>(0, XFA_Element::Border); 1549} 1550 1551CXFA_Border* CXFA_Node::GetOrCreateBorderIfPossible() { 1552 return JSObject()->GetOrCreateProperty<CXFA_Border>(0, XFA_Element::Border); 1553} 1554 1555CXFA_Caption* CXFA_Node::GetCaptionIfExists() const { 1556 return JSObject()->GetProperty<CXFA_Caption>(0, XFA_Element::Caption); 1557} 1558 1559CXFA_Font* CXFA_Node::GetOrCreateFontIfPossible() { 1560 return JSObject()->GetOrCreateProperty<CXFA_Font>(0, XFA_Element::Font); 1561} 1562 1563CXFA_Font* CXFA_Node::GetFontIfExists() const { 1564 return JSObject()->GetProperty<CXFA_Font>(0, XFA_Element::Font); 1565} 1566 1567float CXFA_Node::GetFontSize() const { 1568 CXFA_Font* font = GetFontIfExists(); 1569 float fFontSize = font ? font->GetFontSize() : 10.0f; 1570 return fFontSize < 0.1f ? 10.0f : fFontSize; 1571} 1572 1573float CXFA_Node::GetLineHeight() const { 1574 float fLineHeight = 0; 1575 CXFA_Para* para = GetParaIfExists(); 1576 if (para) 1577 fLineHeight = para->GetLineHeight(); 1578 1579 if (fLineHeight < 1) 1580 fLineHeight = GetFontSize() * 1.2f; 1581 return fLineHeight; 1582} 1583 1584FX_ARGB CXFA_Node::GetTextColor() const { 1585 CXFA_Font* font = GetFontIfExists(); 1586 return font ? font->GetColor() : 0xFF000000; 1587} 1588 1589CXFA_Margin* CXFA_Node::GetMarginIfExists() const { 1590 return JSObject()->GetProperty<CXFA_Margin>(0, XFA_Element::Margin); 1591} 1592 1593CXFA_Para* CXFA_Node::GetParaIfExists() const { 1594 return JSObject()->GetProperty<CXFA_Para>(0, XFA_Element::Para); 1595} 1596 1597bool CXFA_Node::IsOpenAccess() { 1598 for (auto* pNode = this; pNode; pNode = pNode->GetContainerParent()) { 1599 XFA_AttributeEnum iAcc = pNode->JSObject()->GetEnum(XFA_Attribute::Access); 1600 if (iAcc != XFA_AttributeEnum::Open) 1601 return false; 1602 } 1603 return true; 1604} 1605 1606CXFA_Value* CXFA_Node::GetDefaultValueIfExists() { 1607 CXFA_Node* pTemNode = GetTemplateNodeIfExists(); 1608 return pTemNode ? pTemNode->JSObject()->GetProperty<CXFA_Value>( 1609 0, XFA_Element::Value) 1610 : nullptr; 1611} 1612 1613CXFA_Value* CXFA_Node::GetFormValueIfExists() const { 1614 return JSObject()->GetProperty<CXFA_Value>(0, XFA_Element::Value); 1615} 1616 1617CXFA_Calculate* CXFA_Node::GetCalculateIfExists() const { 1618 return JSObject()->GetProperty<CXFA_Calculate>(0, XFA_Element::Calculate); 1619} 1620 1621CXFA_Validate* CXFA_Node::GetValidateIfExists() const { 1622 return JSObject()->GetProperty<CXFA_Validate>(0, XFA_Element::Validate); 1623} 1624 1625CXFA_Validate* CXFA_Node::GetOrCreateValidateIfPossible() { 1626 return JSObject()->GetOrCreateProperty<CXFA_Validate>(0, 1627 XFA_Element::Validate); 1628} 1629 1630CXFA_Bind* CXFA_Node::GetBindIfExists() const { 1631 return JSObject()->GetProperty<CXFA_Bind>(0, XFA_Element::Bind); 1632} 1633 1634Optional<float> CXFA_Node::TryWidth() { 1635 return JSObject()->TryMeasureAsFloat(XFA_Attribute::W); 1636} 1637 1638Optional<float> CXFA_Node::TryHeight() { 1639 return JSObject()->TryMeasureAsFloat(XFA_Attribute::H); 1640} 1641 1642Optional<float> CXFA_Node::TryMinWidth() { 1643 return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinW); 1644} 1645 1646Optional<float> CXFA_Node::TryMinHeight() { 1647 return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinH); 1648} 1649 1650Optional<float> CXFA_Node::TryMaxWidth() { 1651 return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxW); 1652} 1653 1654Optional<float> CXFA_Node::TryMaxHeight() { 1655 return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxH); 1656} 1657 1658CXFA_Node* CXFA_Node::GetExclGroupIfExists() { 1659 CXFA_Node* pExcl = GetParent(); 1660 if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup) 1661 return nullptr; 1662 return pExcl; 1663} 1664 1665int32_t CXFA_Node::ProcessEvent(CXFA_FFDocView* docView, 1666 XFA_AttributeEnum iActivity, 1667 CXFA_EventParam* pEventParam) { 1668 if (GetElementType() == XFA_Element::Draw) 1669 return XFA_EVENTERROR_NotExist; 1670 1671 std::vector<CXFA_Event*> eventArray = GetWidgetAcc()->GetEventByActivity( 1672 iActivity, pEventParam->m_bIsFormReady); 1673 bool first = true; 1674 int32_t iRet = XFA_EVENTERROR_NotExist; 1675 for (CXFA_Event* event : eventArray) { 1676 int32_t result = ProcessEvent(docView, event, pEventParam); 1677 if (first || result == XFA_EVENTERROR_Success) 1678 iRet = result; 1679 first = false; 1680 } 1681 return iRet; 1682} 1683 1684int32_t CXFA_Node::ProcessEvent(CXFA_FFDocView* docView, 1685 CXFA_Event* event, 1686 CXFA_EventParam* pEventParam) { 1687 if (!event) 1688 return XFA_EVENTERROR_NotExist; 1689 1690 switch (event->GetEventType()) { 1691 case XFA_Element::Execute: 1692 break; 1693 case XFA_Element::Script: 1694 return ExecuteScript(docView, event->GetScriptIfExists(), pEventParam); 1695 case XFA_Element::SignData: 1696 break; 1697 case XFA_Element::Submit: { 1698 CXFA_Submit* submit = event->GetSubmitIfExists(); 1699 if (!submit) 1700 return XFA_EVENTERROR_NotExist; 1701 return docView->GetDoc()->GetDocEnvironment()->Submit(docView->GetDoc(), 1702 submit); 1703 } 1704 default: 1705 break; 1706 } 1707 return XFA_EVENTERROR_NotExist; 1708} 1709 1710int32_t CXFA_Node::ProcessCalculate(CXFA_FFDocView* docView) { 1711 if (GetElementType() == XFA_Element::Draw) 1712 return XFA_EVENTERROR_NotExist; 1713 1714 CXFA_Calculate* calc = GetCalculateIfExists(); 1715 if (!calc) 1716 return XFA_EVENTERROR_NotExist; 1717 if (IsUserInteractive()) 1718 return XFA_EVENTERROR_Disabled; 1719 1720 CXFA_EventParam EventParam; 1721 EventParam.m_eType = XFA_EVENT_Calculate; 1722 int32_t iRet = ExecuteScript(docView, calc->GetScriptIfExists(), &EventParam); 1723 if (iRet != XFA_EVENTERROR_Success) 1724 return iRet; 1725 1726 if (GetRawValue() != EventParam.m_wsResult) { 1727 GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Raw, EventParam.m_wsResult); 1728 GetWidgetAcc()->UpdateUIDisplay(docView, nullptr); 1729 } 1730 return XFA_EVENTERROR_Success; 1731} 1732 1733void CXFA_Node::ProcessScriptTestValidate(CXFA_FFDocView* docView, 1734 CXFA_Validate* validate, 1735 int32_t iRet, 1736 bool bRetValue, 1737 bool bVersionFlag) { 1738 if (iRet != XFA_EVENTERROR_Success) 1739 return; 1740 if (bRetValue) 1741 return; 1742 1743 IXFA_AppProvider* pAppProvider = 1744 docView->GetDoc()->GetApp()->GetAppProvider(); 1745 if (!pAppProvider) 1746 return; 1747 1748 WideString wsTitle = pAppProvider->GetAppTitle(); 1749 WideString wsScriptMsg = validate->GetScriptMessageText(); 1750 if (validate->GetScriptTest() == XFA_AttributeEnum::Warning) { 1751 if (IsUserInteractive()) 1752 return; 1753 if (wsScriptMsg.IsEmpty()) 1754 wsScriptMsg = GetValidateMessage(false, bVersionFlag); 1755 1756 if (bVersionFlag) { 1757 pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, XFA_MB_OK); 1758 return; 1759 } 1760 if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, 1761 XFA_MB_YesNo) == XFA_IDYes) { 1762 SetFlag(XFA_NodeFlag_UserInteractive, false); 1763 } 1764 return; 1765 } 1766 1767 if (wsScriptMsg.IsEmpty()) 1768 wsScriptMsg = GetValidateMessage(true, bVersionFlag); 1769 pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK); 1770} 1771 1772int32_t CXFA_Node::ProcessFormatTestValidate(CXFA_FFDocView* docView, 1773 CXFA_Validate* validate, 1774 bool bVersionFlag) { 1775 WideString wsRawValue = GetRawValue(); 1776 if (!wsRawValue.IsEmpty()) { 1777 WideString wsPicture = validate->GetPicture(); 1778 if (wsPicture.IsEmpty()) 1779 return XFA_EVENTERROR_NotExist; 1780 1781 IFX_Locale* pLocale = GetLocale(); 1782 if (!pLocale) 1783 return XFA_EVENTERROR_NotExist; 1784 1785 CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this); 1786 if (!lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale, 1787 nullptr)) { 1788 IXFA_AppProvider* pAppProvider = 1789 docView->GetDoc()->GetApp()->GetAppProvider(); 1790 if (!pAppProvider) 1791 return XFA_EVENTERROR_NotExist; 1792 1793 WideString wsFormatMsg = validate->GetFormatMessageText(); 1794 WideString wsTitle = pAppProvider->GetAppTitle(); 1795 if (validate->GetFormatTest() == XFA_AttributeEnum::Error) { 1796 if (wsFormatMsg.IsEmpty()) 1797 wsFormatMsg = GetValidateMessage(true, bVersionFlag); 1798 pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK); 1799 return XFA_EVENTERROR_Success; 1800 } 1801 if (IsUserInteractive()) 1802 return XFA_EVENTERROR_NotExist; 1803 if (wsFormatMsg.IsEmpty()) 1804 wsFormatMsg = GetValidateMessage(false, bVersionFlag); 1805 1806 if (bVersionFlag) { 1807 pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning, 1808 XFA_MB_OK); 1809 return XFA_EVENTERROR_Success; 1810 } 1811 if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning, 1812 XFA_MB_YesNo) == XFA_IDYes) { 1813 SetFlag(XFA_NodeFlag_UserInteractive, false); 1814 } 1815 return XFA_EVENTERROR_Success; 1816 } 1817 } 1818 return XFA_EVENTERROR_NotExist; 1819} 1820 1821int32_t CXFA_Node::ProcessNullTestValidate(CXFA_FFDocView* docView, 1822 CXFA_Validate* validate, 1823 int32_t iFlags, 1824 bool bVersionFlag) { 1825 if (!GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw).IsEmpty()) 1826 return XFA_EVENTERROR_Success; 1827 if (GetWidgetAcc()->IsNull() && GetWidgetAcc()->IsPreNull()) 1828 return XFA_EVENTERROR_Success; 1829 1830 XFA_AttributeEnum eNullTest = validate->GetNullTest(); 1831 WideString wsNullMsg = validate->GetNullMessageText(); 1832 if (iFlags & 0x01) { 1833 int32_t iRet = XFA_EVENTERROR_Success; 1834 if (eNullTest != XFA_AttributeEnum::Disabled) 1835 iRet = XFA_EVENTERROR_Error; 1836 1837 if (!wsNullMsg.IsEmpty()) { 1838 if (eNullTest != XFA_AttributeEnum::Disabled) { 1839 docView->m_arrNullTestMsg.push_back(wsNullMsg); 1840 return XFA_EVENTERROR_Error; 1841 } 1842 return XFA_EVENTERROR_Success; 1843 } 1844 return iRet; 1845 } 1846 if (wsNullMsg.IsEmpty() && bVersionFlag && 1847 eNullTest != XFA_AttributeEnum::Disabled) { 1848 return XFA_EVENTERROR_Error; 1849 } 1850 IXFA_AppProvider* pAppProvider = 1851 docView->GetDoc()->GetApp()->GetAppProvider(); 1852 if (!pAppProvider) 1853 return XFA_EVENTERROR_NotExist; 1854 1855 WideString wsCaptionName; 1856 WideString wsTitle = pAppProvider->GetAppTitle(); 1857 switch (eNullTest) { 1858 case XFA_AttributeEnum::Error: { 1859 if (wsNullMsg.IsEmpty()) { 1860 wsCaptionName = GetValidateCaptionName(bVersionFlag); 1861 wsNullMsg = 1862 WideString::Format(L"%ls cannot be blank.", wsCaptionName.c_str()); 1863 } 1864 pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK); 1865 return XFA_EVENTERROR_Error; 1866 } 1867 case XFA_AttributeEnum::Warning: { 1868 if (IsUserInteractive()) 1869 return true; 1870 1871 if (wsNullMsg.IsEmpty()) { 1872 wsCaptionName = GetValidateCaptionName(bVersionFlag); 1873 wsNullMsg = WideString::Format( 1874 L"%ls cannot be blank. To ignore validations for %ls, click " 1875 L"Ignore.", 1876 wsCaptionName.c_str(), wsCaptionName.c_str()); 1877 } 1878 if (pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Warning, 1879 XFA_MB_YesNo) == XFA_IDYes) { 1880 SetFlag(XFA_NodeFlag_UserInteractive, false); 1881 } 1882 return XFA_EVENTERROR_Error; 1883 } 1884 case XFA_AttributeEnum::Disabled: 1885 default: 1886 break; 1887 } 1888 return XFA_EVENTERROR_Success; 1889} 1890 1891int32_t CXFA_Node::ProcessValidate(CXFA_FFDocView* docView, int32_t iFlags) { 1892 if (GetElementType() == XFA_Element::Draw) 1893 return XFA_EVENTERROR_NotExist; 1894 1895 CXFA_Validate* validate = GetValidateIfExists(); 1896 if (!validate) 1897 return XFA_EVENTERROR_NotExist; 1898 1899 bool bInitDoc = validate->NeedsInitApp(); 1900 bool bStatus = docView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End; 1901 int32_t iFormat = 0; 1902 int32_t iRet = XFA_EVENTERROR_NotExist; 1903 CXFA_Script* script = validate->GetScriptIfExists(); 1904 bool bRet = false; 1905 bool hasBoolResult = (bInitDoc || bStatus) && GetRawValue().IsEmpty(); 1906 if (script) { 1907 CXFA_EventParam eParam; 1908 eParam.m_eType = XFA_EVENT_Validate; 1909 eParam.m_pTarget = GetWidgetAcc(); 1910 std::tie(iRet, bRet) = ExecuteBoolScript(docView, script, &eParam); 1911 } 1912 1913 XFA_VERSION version = docView->GetDoc()->GetXFADoc()->GetCurVersionMode(); 1914 bool bVersionFlag = false; 1915 if (version < XFA_VERSION_208) 1916 bVersionFlag = true; 1917 1918 if (bInitDoc) { 1919 validate->ClearFlag(XFA_NodeFlag_NeedsInitApp); 1920 } else { 1921 iFormat = ProcessFormatTestValidate(docView, validate, bVersionFlag); 1922 if (!bVersionFlag) { 1923 bVersionFlag = 1924 docView->GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting); 1925 } 1926 1927 iRet |= ProcessNullTestValidate(docView, validate, iFlags, bVersionFlag); 1928 } 1929 1930 if (iFormat != XFA_EVENTERROR_Success && hasBoolResult) 1931 ProcessScriptTestValidate(docView, validate, iRet, bRet, bVersionFlag); 1932 1933 return iRet | iFormat; 1934} 1935 1936WideString CXFA_Node::GetValidateCaptionName(bool bVersionFlag) { 1937 WideString wsCaptionName; 1938 1939 if (!bVersionFlag) { 1940 CXFA_Caption* caption = GetCaptionIfExists(); 1941 if (caption) { 1942 CXFA_Value* capValue = caption->GetValueIfExists(); 1943 if (capValue) { 1944 CXFA_Text* captionText = capValue->GetTextIfExists(); 1945 if (captionText) 1946 wsCaptionName = captionText->GetContent(); 1947 } 1948 } 1949 } 1950 if (!wsCaptionName.IsEmpty()) 1951 return wsCaptionName; 1952 return JSObject()->GetCData(XFA_Attribute::Name); 1953} 1954 1955WideString CXFA_Node::GetValidateMessage(bool bError, bool bVersionFlag) { 1956 WideString wsCaptionName = GetValidateCaptionName(bVersionFlag); 1957 if (bVersionFlag) 1958 return WideString::Format(L"%ls validation failed", wsCaptionName.c_str()); 1959 if (bError) { 1960 return WideString::Format(L"The value you entered for %ls is invalid.", 1961 wsCaptionName.c_str()); 1962 } 1963 return WideString::Format( 1964 L"The value you entered for %ls is invalid. To ignore " 1965 L"validations for %ls, click Ignore.", 1966 wsCaptionName.c_str(), wsCaptionName.c_str()); 1967} 1968 1969int32_t CXFA_Node::ExecuteScript(CXFA_FFDocView* docView, 1970 CXFA_Script* script, 1971 CXFA_EventParam* pEventParam) { 1972 bool bRet; 1973 int32_t iRet; 1974 std::tie(iRet, bRet) = ExecuteBoolScript(docView, script, pEventParam); 1975 return iRet; 1976} 1977 1978std::pair<int32_t, bool> CXFA_Node::ExecuteBoolScript( 1979 CXFA_FFDocView* docView, 1980 CXFA_Script* script, 1981 CXFA_EventParam* pEventParam) { 1982 if (m_ExecuteRecursionDepth > kMaxExecuteRecursion) 1983 return {XFA_EVENTERROR_Success, false}; 1984 1985 ASSERT(pEventParam); 1986 if (!script) 1987 return {XFA_EVENTERROR_NotExist, false}; 1988 if (script->GetRunAt() == XFA_AttributeEnum::Server) 1989 return {XFA_EVENTERROR_Disabled, false}; 1990 1991 WideString wsExpression = script->GetExpression(); 1992 if (wsExpression.IsEmpty()) 1993 return {XFA_EVENTERROR_NotExist, false}; 1994 1995 CXFA_Script::Type eScriptType = script->GetContentType(); 1996 if (eScriptType == CXFA_Script::Type::Unknown) 1997 return {XFA_EVENTERROR_Success, false}; 1998 1999 CXFA_FFDoc* pDoc = docView->GetDoc(); 2000 CFXJSE_Engine* pContext = pDoc->GetXFADoc()->GetScriptContext(); 2001 pContext->SetEventParam(*pEventParam); 2002 pContext->SetRunAtType(script->GetRunAt()); 2003 2004 std::vector<CXFA_Node*> refNodes; 2005 if (pEventParam->m_eType == XFA_EVENT_InitCalculate || 2006 pEventParam->m_eType == XFA_EVENT_Calculate) { 2007 pContext->SetNodesOfRunScript(&refNodes); 2008 } 2009 2010 auto pTmpRetValue = pdfium::MakeUnique<CFXJSE_Value>(pContext->GetIsolate()); 2011 bool bRet = false; 2012 { 2013 AutoRestorer<uint8_t> restorer(&m_ExecuteRecursionDepth); 2014 ++m_ExecuteRecursionDepth; 2015 bRet = pContext->RunScript(eScriptType, wsExpression.AsStringView(), 2016 pTmpRetValue.get(), this); 2017 } 2018 2019 int32_t iRet = XFA_EVENTERROR_Error; 2020 if (bRet) { 2021 iRet = XFA_EVENTERROR_Success; 2022 if (pEventParam->m_eType == XFA_EVENT_Calculate || 2023 pEventParam->m_eType == XFA_EVENT_InitCalculate) { 2024 if (!pTmpRetValue->IsUndefined()) { 2025 if (!pTmpRetValue->IsNull()) 2026 pEventParam->m_wsResult = pTmpRetValue->ToWideString(); 2027 2028 iRet = XFA_EVENTERROR_Success; 2029 } else { 2030 iRet = XFA_EVENTERROR_Error; 2031 } 2032 if (pEventParam->m_eType == XFA_EVENT_InitCalculate) { 2033 if ((iRet == XFA_EVENTERROR_Success) && 2034 (GetRawValue() != pEventParam->m_wsResult)) { 2035 GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Raw, 2036 pEventParam->m_wsResult); 2037 docView->AddValidateWidget(GetWidgetAcc()); 2038 } 2039 } 2040 for (CXFA_Node* pRefNode : refNodes) { 2041 if (pRefNode == this) 2042 continue; 2043 2044 CXFA_CalcData* pGlobalData = pRefNode->JSObject()->GetCalcData(); 2045 if (!pGlobalData) { 2046 pRefNode->JSObject()->SetCalcData( 2047 pdfium::MakeUnique<CXFA_CalcData>()); 2048 pGlobalData = pRefNode->JSObject()->GetCalcData(); 2049 } 2050 if (!pdfium::ContainsValue(pGlobalData->m_Globals, this)) 2051 pGlobalData->m_Globals.push_back(this); 2052 } 2053 } 2054 } 2055 pContext->SetNodesOfRunScript(nullptr); 2056 2057 return {iRet, pTmpRetValue->IsBoolean() ? pTmpRetValue->ToBoolean() : false}; 2058} 2059 2060WideString CXFA_Node::GetBarcodeType() { 2061 CXFA_Node* pUIChild = GetWidgetAcc()->GetUIChild(); 2062 return pUIChild 2063 ? WideString(pUIChild->JSObject()->GetCData(XFA_Attribute::Type)) 2064 : WideString(); 2065} 2066 2067Optional<BC_CHAR_ENCODING> CXFA_Node::GetBarcodeAttribute_CharEncoding() { 2068 Optional<WideString> wsCharEncoding = 2069 GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( 2070 XFA_Attribute::CharEncoding, true); 2071 if (!wsCharEncoding) 2072 return {}; 2073 if (wsCharEncoding->CompareNoCase(L"UTF-16")) 2074 return {CHAR_ENCODING_UNICODE}; 2075 if (wsCharEncoding->CompareNoCase(L"UTF-8")) 2076 return {CHAR_ENCODING_UTF8}; 2077 return {}; 2078} 2079 2080Optional<bool> CXFA_Node::GetBarcodeAttribute_Checksum() { 2081 Optional<XFA_AttributeEnum> checksum = 2082 GetWidgetAcc()->GetUIChild()->JSObject()->TryEnum(XFA_Attribute::Checksum, 2083 true); 2084 if (!checksum) 2085 return {}; 2086 2087 switch (*checksum) { 2088 case XFA_AttributeEnum::None: 2089 return {false}; 2090 case XFA_AttributeEnum::Auto: 2091 return {true}; 2092 case XFA_AttributeEnum::Checksum_1mod10: 2093 case XFA_AttributeEnum::Checksum_1mod10_1mod11: 2094 case XFA_AttributeEnum::Checksum_2mod10: 2095 default: 2096 break; 2097 } 2098 return {}; 2099} 2100 2101Optional<int32_t> CXFA_Node::GetBarcodeAttribute_DataLength() { 2102 Optional<WideString> wsDataLength = 2103 GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( 2104 XFA_Attribute::DataLength, true); 2105 if (!wsDataLength) 2106 return {}; 2107 2108 return {FXSYS_wtoi(wsDataLength->c_str())}; 2109} 2110 2111Optional<char> CXFA_Node::GetBarcodeAttribute_StartChar() { 2112 Optional<WideString> wsStartEndChar = 2113 GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( 2114 XFA_Attribute::StartChar, true); 2115 if (!wsStartEndChar || wsStartEndChar->IsEmpty()) 2116 return {}; 2117 2118 return {static_cast<char>((*wsStartEndChar)[0])}; 2119} 2120 2121Optional<char> CXFA_Node::GetBarcodeAttribute_EndChar() { 2122 Optional<WideString> wsStartEndChar = 2123 GetWidgetAcc()->GetUIChild()->JSObject()->TryCData(XFA_Attribute::EndChar, 2124 true); 2125 if (!wsStartEndChar || wsStartEndChar->IsEmpty()) 2126 return {}; 2127 2128 return {static_cast<char>((*wsStartEndChar)[0])}; 2129} 2130 2131Optional<int32_t> CXFA_Node::GetBarcodeAttribute_ECLevel() { 2132 Optional<WideString> wsECLevel = 2133 GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( 2134 XFA_Attribute::ErrorCorrectionLevel, true); 2135 if (!wsECLevel) 2136 return {}; 2137 return {FXSYS_wtoi(wsECLevel->c_str())}; 2138} 2139 2140Optional<int32_t> CXFA_Node::GetBarcodeAttribute_ModuleWidth() { 2141 Optional<CXFA_Measurement> moduleWidthHeight = 2142 GetWidgetAcc()->GetUIChild()->JSObject()->TryMeasure( 2143 XFA_Attribute::ModuleWidth, true); 2144 if (!moduleWidthHeight) 2145 return {}; 2146 2147 return {static_cast<int32_t>(moduleWidthHeight->ToUnit(XFA_Unit::Pt))}; 2148} 2149 2150Optional<int32_t> CXFA_Node::GetBarcodeAttribute_ModuleHeight() { 2151 Optional<CXFA_Measurement> moduleWidthHeight = 2152 GetWidgetAcc()->GetUIChild()->JSObject()->TryMeasure( 2153 XFA_Attribute::ModuleHeight, true); 2154 if (!moduleWidthHeight) 2155 return {}; 2156 2157 return {static_cast<int32_t>(moduleWidthHeight->ToUnit(XFA_Unit::Pt))}; 2158} 2159 2160Optional<bool> CXFA_Node::GetBarcodeAttribute_PrintChecksum() { 2161 return GetWidgetAcc()->GetUIChild()->JSObject()->TryBoolean( 2162 XFA_Attribute::PrintCheckDigit, true); 2163} 2164 2165Optional<BC_TEXT_LOC> CXFA_Node::GetBarcodeAttribute_TextLocation() { 2166 Optional<XFA_AttributeEnum> textLocation = 2167 GetWidgetAcc()->GetUIChild()->JSObject()->TryEnum( 2168 XFA_Attribute::TextLocation, true); 2169 if (!textLocation) 2170 return {}; 2171 2172 switch (*textLocation) { 2173 case XFA_AttributeEnum::None: 2174 return {BC_TEXT_LOC_NONE}; 2175 case XFA_AttributeEnum::Above: 2176 return {BC_TEXT_LOC_ABOVE}; 2177 case XFA_AttributeEnum::Below: 2178 return {BC_TEXT_LOC_BELOW}; 2179 case XFA_AttributeEnum::AboveEmbedded: 2180 return {BC_TEXT_LOC_ABOVEEMBED}; 2181 case XFA_AttributeEnum::BelowEmbedded: 2182 return {BC_TEXT_LOC_BELOWEMBED}; 2183 default: 2184 break; 2185 } 2186 return {}; 2187} 2188 2189Optional<bool> CXFA_Node::GetBarcodeAttribute_Truncate() { 2190 return GetWidgetAcc()->GetUIChild()->JSObject()->TryBoolean( 2191 XFA_Attribute::Truncate, true); 2192} 2193 2194Optional<int8_t> CXFA_Node::GetBarcodeAttribute_WideNarrowRatio() { 2195 Optional<WideString> wsWideNarrowRatio = 2196 GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( 2197 XFA_Attribute::WideNarrowRatio, true); 2198 if (!wsWideNarrowRatio) 2199 return {}; 2200 2201 Optional<size_t> ptPos = wsWideNarrowRatio->Find(':'); 2202 if (!ptPos) 2203 return {static_cast<int8_t>(FXSYS_wtoi(wsWideNarrowRatio->c_str()))}; 2204 2205 int32_t fB = FXSYS_wtoi( 2206 wsWideNarrowRatio->Right(wsWideNarrowRatio->GetLength() - (*ptPos + 1)) 2207 .c_str()); 2208 if (!fB) 2209 return {0}; 2210 2211 int32_t fA = FXSYS_wtoi(wsWideNarrowRatio->Left(*ptPos).c_str()); 2212 float result = static_cast<float>(fA) / static_cast<float>(fB); 2213 return {static_cast<int8_t>(result)}; 2214} 2215