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 "fxjs/cfxjse_resolveprocessor.h" 8 9#include <algorithm> 10#include <utility> 11#include <vector> 12 13#include "core/fxcrt/fx_extension.h" 14#include "fxjs/cfxjse_engine.h" 15#include "fxjs/xfa/cjx_object.h" 16#include "third_party/base/ptr_util.h" 17#include "third_party/base/stl_util.h" 18#include "xfa/fxfa/parser/cxfa_document.h" 19#include "xfa/fxfa/parser/cxfa_localemgr.h" 20#include "xfa/fxfa/parser/cxfa_node.h" 21#include "xfa/fxfa/parser/cxfa_nodehelper.h" 22#include "xfa/fxfa/parser/cxfa_object.h" 23#include "xfa/fxfa/parser/cxfa_occur.h" 24#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" 25#include "xfa/fxfa/parser/xfa_utils.h" 26 27CFXJSE_ResolveProcessor::CFXJSE_ResolveProcessor() 28 : m_iCurStart(0), m_pNodeHelper(pdfium::MakeUnique<CXFA_NodeHelper>()) {} 29 30CFXJSE_ResolveProcessor::~CFXJSE_ResolveProcessor() {} 31 32bool CFXJSE_ResolveProcessor::Resolve(CFXJSE_ResolveNodeData& rnd) { 33 if (!rnd.m_CurObject) 34 return false; 35 36 if (!rnd.m_CurObject->IsNode()) { 37 if (rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) { 38 return ResolveForAttributeRs(rnd.m_CurObject, rnd, 39 rnd.m_wsName.AsStringView()); 40 } 41 return false; 42 } 43 if (rnd.m_dwStyles & XFA_RESOLVENODE_AnyChild) 44 return ResolveAnyChild(rnd); 45 46 if (rnd.m_wsName.GetLength()) { 47 wchar_t wch = rnd.m_wsName[0]; 48 switch (wch) { 49 case '$': 50 return ResolveDollar(rnd); 51 case '!': 52 return ResolveExcalmatory(rnd); 53 case '#': 54 return ResolveNumberSign(rnd); 55 case '*': 56 return ResolveAsterisk(rnd); 57 // TODO(dsinclair): We could probably remove this. 58 case '.': 59 return ResolveAnyChild(rnd); 60 default: 61 break; 62 } 63 } 64 if (rnd.m_uHashName == XFA_HASHCODE_This && rnd.m_nLevel == 0) { 65 rnd.m_Objects.push_back(rnd.m_pSC->GetThisObject()); 66 return true; 67 } 68 if (rnd.m_CurObject->GetElementType() == XFA_Element::Xfa) { 69 CXFA_Object* pObjNode = 70 rnd.m_pSC->GetDocument()->GetXFAObject(rnd.m_uHashName); 71 if (pObjNode) { 72 rnd.m_Objects.push_back(pObjNode); 73 } else if (rnd.m_uHashName == XFA_HASHCODE_Xfa) { 74 rnd.m_Objects.push_back(rnd.m_CurObject); 75 } else if ((rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) && 76 ResolveForAttributeRs(rnd.m_CurObject, rnd, 77 rnd.m_wsName.AsStringView())) { 78 return true; 79 } 80 if (!rnd.m_Objects.empty()) 81 FilterCondition(rnd, rnd.m_wsCondition); 82 83 return !rnd.m_Objects.empty(); 84 } 85 if (!ResolveNormal(rnd) && rnd.m_uHashName == XFA_HASHCODE_Xfa) 86 rnd.m_Objects.push_back(rnd.m_pSC->GetDocument()->GetRoot()); 87 88 return !rnd.m_Objects.empty(); 89} 90 91bool CFXJSE_ResolveProcessor::ResolveAnyChild(CFXJSE_ResolveNodeData& rnd) { 92 WideString wsName = rnd.m_wsName; 93 WideString wsCondition = rnd.m_wsCondition; 94 CXFA_Node* findNode = nullptr; 95 bool bClassName = false; 96 if (wsName.GetLength() && wsName[0] == '#') { 97 bClassName = true; 98 wsName = wsName.Right(wsName.GetLength() - 1); 99 } 100 findNode = m_pNodeHelper->ResolveNodes_GetOneChild( 101 ToNode(rnd.m_CurObject), wsName.c_str(), bClassName); 102 if (!findNode) 103 return false; 104 105 if (wsCondition.IsEmpty()) { 106 rnd.m_Objects.push_back(findNode); 107 return !rnd.m_Objects.empty(); 108 } 109 110 std::vector<CXFA_Node*> tempNodes; 111 for (auto* pObject : rnd.m_Objects) 112 tempNodes.push_back(pObject->AsNode()); 113 m_pNodeHelper->CountSiblings(findNode, XFA_LOGIC_Transparent, &tempNodes, 114 bClassName); 115 rnd.m_Objects = std::vector<CXFA_Object*>(tempNodes.begin(), tempNodes.end()); 116 FilterCondition(rnd, wsCondition); 117 return !rnd.m_Objects.empty(); 118} 119 120bool CFXJSE_ResolveProcessor::ResolveDollar(CFXJSE_ResolveNodeData& rnd) { 121 WideString wsName = rnd.m_wsName; 122 WideString wsCondition = rnd.m_wsCondition; 123 int32_t iNameLen = wsName.GetLength(); 124 if (iNameLen == 1) { 125 rnd.m_Objects.push_back(rnd.m_CurObject); 126 return true; 127 } 128 if (rnd.m_nLevel > 0) 129 return false; 130 131 XFA_HashCode dwNameHash = static_cast<XFA_HashCode>(FX_HashCode_GetW( 132 WideStringView(wsName.c_str() + 1, iNameLen - 1), false)); 133 if (dwNameHash == XFA_HASHCODE_Xfa) { 134 rnd.m_Objects.push_back(rnd.m_pSC->GetDocument()->GetRoot()); 135 } else { 136 CXFA_Object* pObjNode = rnd.m_pSC->GetDocument()->GetXFAObject(dwNameHash); 137 if (pObjNode) 138 rnd.m_Objects.push_back(pObjNode); 139 } 140 if (!rnd.m_Objects.empty()) 141 FilterCondition(rnd, wsCondition); 142 143 return !rnd.m_Objects.empty(); 144} 145 146bool CFXJSE_ResolveProcessor::ResolveExcalmatory(CFXJSE_ResolveNodeData& rnd) { 147 if (rnd.m_nLevel > 0) 148 return false; 149 150 CXFA_Node* datasets = 151 ToNode(rnd.m_pSC->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets)); 152 if (!datasets) 153 return false; 154 155 CFXJSE_ResolveNodeData rndFind(rnd.m_pSC); 156 rndFind.m_CurObject = datasets; 157 rndFind.m_wsName = rnd.m_wsName.Right(rnd.m_wsName.GetLength() - 1); 158 rndFind.m_uHashName = static_cast<XFA_HashCode>( 159 FX_HashCode_GetW(rndFind.m_wsName.AsStringView(), false)); 160 rndFind.m_nLevel = rnd.m_nLevel + 1; 161 rndFind.m_dwStyles = XFA_RESOLVENODE_Children; 162 rndFind.m_wsCondition = rnd.m_wsCondition; 163 Resolve(rndFind); 164 165 rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), 166 rndFind.m_Objects.end()); 167 return !rnd.m_Objects.empty(); 168} 169 170bool CFXJSE_ResolveProcessor::ResolveNumberSign(CFXJSE_ResolveNodeData& rnd) { 171 WideString wsName = rnd.m_wsName.Right(rnd.m_wsName.GetLength() - 1); 172 WideString wsCondition = rnd.m_wsCondition; 173 CXFA_Node* curNode = ToNode(rnd.m_CurObject); 174 if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringView())) 175 return true; 176 177 CFXJSE_ResolveNodeData rndFind(rnd.m_pSC); 178 rndFind.m_nLevel = rnd.m_nLevel + 1; 179 rndFind.m_dwStyles = rnd.m_dwStyles; 180 rndFind.m_dwStyles |= XFA_RESOLVENODE_TagName; 181 rndFind.m_dwStyles &= ~XFA_RESOLVENODE_Attributes; 182 rndFind.m_wsName = wsName; 183 rndFind.m_uHashName = static_cast<XFA_HashCode>( 184 FX_HashCode_GetW(rndFind.m_wsName.AsStringView(), false)); 185 rndFind.m_wsCondition = wsCondition; 186 rndFind.m_CurObject = curNode; 187 ResolveNormal(rndFind); 188 if (rndFind.m_Objects.empty()) 189 return false; 190 191 if (wsCondition.GetLength() == 0 && 192 pdfium::ContainsValue(rndFind.m_Objects, curNode)) { 193 rnd.m_Objects.push_back(curNode); 194 } else { 195 rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), 196 rndFind.m_Objects.end()); 197 } 198 return !rnd.m_Objects.empty(); 199} 200 201bool CFXJSE_ResolveProcessor::ResolveForAttributeRs( 202 CXFA_Object* curNode, 203 CFXJSE_ResolveNodeData& rnd, 204 const WideStringView& strAttr) { 205 const XFA_SCRIPTATTRIBUTEINFO* lpScriptAttribute = 206 XFA_GetScriptAttributeByName(curNode->GetElementType(), strAttr); 207 if (!lpScriptAttribute) 208 return false; 209 210 rnd.m_pScriptAttribute = lpScriptAttribute; 211 rnd.m_Objects.push_back(curNode); 212 rnd.m_dwFlag = XFA_ResolveNode_RSType_Attribute; 213 return true; 214} 215 216bool CFXJSE_ResolveProcessor::ResolveNormal(CFXJSE_ResolveNodeData& rnd) { 217 if (rnd.m_nLevel > 32 || !rnd.m_CurObject->IsNode()) 218 return false; 219 220 CXFA_Node* curNode = rnd.m_CurObject->AsNode(); 221 size_t nNum = rnd.m_Objects.size(); 222 uint32_t dwStyles = rnd.m_dwStyles; 223 WideString& wsName = rnd.m_wsName; 224 XFA_HashCode uNameHash = rnd.m_uHashName; 225 WideString& wsCondition = rnd.m_wsCondition; 226 227 CFXJSE_ResolveNodeData rndFind(rnd.m_pSC); 228 rndFind.m_wsName = rnd.m_wsName; 229 rndFind.m_wsCondition = rnd.m_wsCondition; 230 rndFind.m_nLevel = rnd.m_nLevel + 1; 231 rndFind.m_uHashName = uNameHash; 232 233 std::vector<CXFA_Node*> children; 234 std::vector<CXFA_Node*> properties; 235 CXFA_Node* pVariablesNode = nullptr; 236 CXFA_Node* pPageSetNode = nullptr; 237 for (CXFA_Node* pChild = curNode->GetFirstChild(); pChild; 238 pChild = pChild->GetNextSibling()) { 239 if (pChild->GetElementType() == XFA_Element::Variables) { 240 pVariablesNode = pChild; 241 continue; 242 } 243 if (pChild->GetElementType() == XFA_Element::PageSet) { 244 pPageSetNode = pChild; 245 continue; 246 } 247 if (curNode->HasProperty(pChild->GetElementType())) 248 properties.push_back(pChild); 249 else 250 children.push_back(pChild); 251 } 252 if ((dwStyles & XFA_RESOLVENODE_Properties) && pVariablesNode) { 253 if (pVariablesNode->GetClassHashCode() == uNameHash) { 254 rnd.m_Objects.push_back(pVariablesNode); 255 } else { 256 rndFind.m_CurObject = pVariablesNode; 257 SetStylesForChild(dwStyles, rndFind); 258 WideString wsSaveCondition = rndFind.m_wsCondition; 259 rndFind.m_wsCondition.clear(); 260 ResolveNormal(rndFind); 261 rndFind.m_wsCondition = wsSaveCondition; 262 rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), 263 rndFind.m_Objects.end()); 264 rndFind.m_Objects.clear(); 265 } 266 if (rnd.m_Objects.size() > nNum) { 267 FilterCondition(rnd, wsCondition); 268 return !rnd.m_Objects.empty(); 269 } 270 } 271 272 if (dwStyles & XFA_RESOLVENODE_Children) { 273 bool bSetFlag = false; 274 if (pPageSetNode && (dwStyles & XFA_RESOLVENODE_Properties)) 275 children.push_back(pPageSetNode); 276 277 for (CXFA_Node* child : children) { 278 if (dwStyles & XFA_RESOLVENODE_TagName) { 279 if (child->GetClassHashCode() == uNameHash) 280 rnd.m_Objects.push_back(child); 281 } else if (child->GetNameHash() == uNameHash) { 282 rnd.m_Objects.push_back(child); 283 } 284 285 if (m_pNodeHelper->NodeIsTransparent(child) && 286 child->GetElementType() != XFA_Element::PageSet) { 287 if (!bSetFlag) { 288 SetStylesForChild(dwStyles, rndFind); 289 bSetFlag = true; 290 } 291 rndFind.m_CurObject = child; 292 293 WideString wsSaveCondition = rndFind.m_wsCondition; 294 rndFind.m_wsCondition.clear(); 295 ResolveNormal(rndFind); 296 297 rndFind.m_wsCondition = wsSaveCondition; 298 rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), 299 rndFind.m_Objects.end()); 300 rndFind.m_Objects.clear(); 301 } 302 } 303 if (rnd.m_Objects.size() > nNum) { 304 if (!(dwStyles & XFA_RESOLVENODE_ALL)) { 305 std::vector<CXFA_Node*> upArrayNodes; 306 if (m_pNodeHelper->NodeIsTransparent(ToNode(curNode))) { 307 m_pNodeHelper->CountSiblings(ToNode(rnd.m_Objects[0]), 308 XFA_LOGIC_Transparent, &upArrayNodes, 309 !!(dwStyles & XFA_RESOLVENODE_TagName)); 310 } 311 if (upArrayNodes.size() > rnd.m_Objects.size()) { 312 CXFA_Object* pSaveObject = rnd.m_Objects.front(); 313 rnd.m_Objects = std::vector<CXFA_Object*>(upArrayNodes.begin(), 314 upArrayNodes.end()); 315 rnd.m_Objects.front() = pSaveObject; 316 } 317 } 318 FilterCondition(rnd, wsCondition); 319 return !rnd.m_Objects.empty(); 320 } 321 } 322 if (dwStyles & XFA_RESOLVENODE_Attributes) { 323 if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringView())) 324 return 1; 325 } 326 if (dwStyles & XFA_RESOLVENODE_Properties) { 327 for (CXFA_Node* pChildProperty : properties) { 328 if (pChildProperty->IsUnnamed()) { 329 if (pChildProperty->GetClassHashCode() == uNameHash) 330 rnd.m_Objects.push_back(pChildProperty); 331 continue; 332 } 333 if (pChildProperty->GetNameHash() == uNameHash && 334 pChildProperty->GetElementType() != XFA_Element::Extras && 335 pChildProperty->GetElementType() != XFA_Element::Items) { 336 rnd.m_Objects.push_back(pChildProperty); 337 } 338 } 339 if (rnd.m_Objects.size() > nNum) { 340 FilterCondition(rnd, wsCondition); 341 return !rnd.m_Objects.empty(); 342 } 343 344 CXFA_Node* pProp = nullptr; 345 if (XFA_Element::Subform == curNode->GetElementType() && 346 XFA_HASHCODE_Occur == uNameHash) { 347 CXFA_Node* pInstanceManager = 348 curNode->AsNode()->GetInstanceMgrOfSubform(); 349 if (pInstanceManager) { 350 pProp = pInstanceManager->JSObject()->GetOrCreateProperty<CXFA_Occur>( 351 0, XFA_Element::Occur); 352 } 353 } else { 354 XFA_Element eType = CXFA_Node::NameToElement(wsName); 355 if (eType == XFA_Element::PageSet) { 356 pProp = curNode->AsNode()->JSObject()->GetProperty<CXFA_Node>(0, eType); 357 } else if (eType != XFA_Element::Unknown) { 358 pProp = curNode->AsNode()->JSObject()->GetOrCreateProperty<CXFA_Node>( 359 0, eType); 360 } 361 } 362 if (pProp) { 363 rnd.m_Objects.push_back(pProp); 364 return !rnd.m_Objects.empty(); 365 } 366 } 367 368 CXFA_Node* parentNode = m_pNodeHelper->ResolveNodes_GetParent( 369 curNode->AsNode(), XFA_LOGIC_NoTransparent); 370 uint32_t uCurClassHash = curNode->GetClassHashCode(); 371 if (!parentNode) { 372 if (uCurClassHash == uNameHash) { 373 rnd.m_Objects.push_back(curNode->AsNode()); 374 FilterCondition(rnd, wsCondition); 375 if (!rnd.m_Objects.empty()) 376 return true; 377 } 378 return false; 379 } 380 381 if (dwStyles & XFA_RESOLVENODE_Siblings) { 382 CXFA_Node* child = parentNode->GetFirstChild(); 383 uint32_t dwSubStyles = 384 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties; 385 if (dwStyles & XFA_RESOLVENODE_TagName) 386 dwSubStyles |= XFA_RESOLVENODE_TagName; 387 if (dwStyles & XFA_RESOLVENODE_ALL) 388 dwSubStyles |= XFA_RESOLVENODE_ALL; 389 390 rndFind.m_dwStyles = dwSubStyles; 391 while (child) { 392 if (child == curNode) { 393 if (dwStyles & XFA_RESOLVENODE_TagName) { 394 if (uCurClassHash == uNameHash) 395 rnd.m_Objects.push_back(curNode); 396 } else { 397 if (child->GetNameHash() == uNameHash) { 398 rnd.m_Objects.push_back(curNode); 399 if (rnd.m_nLevel == 0 && wsCondition.GetLength() == 0) { 400 rnd.m_Objects.clear(); 401 rnd.m_Objects.push_back(curNode); 402 return true; 403 } 404 } 405 } 406 child = child->GetNextSibling(); 407 continue; 408 } 409 410 if (dwStyles & XFA_RESOLVENODE_TagName) { 411 if (child->GetClassHashCode() == uNameHash) 412 rnd.m_Objects.push_back(child); 413 } else if (child->GetNameHash() == uNameHash) { 414 rnd.m_Objects.push_back(child); 415 } 416 417 bool bInnerSearch = false; 418 if (parentNode->HasProperty(child->GetElementType())) { 419 if ((child->GetElementType() == XFA_Element::Variables || 420 child->GetElementType() == XFA_Element::PageSet)) { 421 bInnerSearch = true; 422 } 423 } else if (m_pNodeHelper->NodeIsTransparent(child)) { 424 bInnerSearch = true; 425 } 426 if (bInnerSearch) { 427 rndFind.m_CurObject = child; 428 WideString wsOriginCondition = rndFind.m_wsCondition; 429 rndFind.m_wsCondition.clear(); 430 431 uint32_t dwOriginStyle = rndFind.m_dwStyles; 432 rndFind.m_dwStyles = dwOriginStyle | XFA_RESOLVENODE_ALL; 433 ResolveNormal(rndFind); 434 435 rndFind.m_dwStyles = dwOriginStyle; 436 rndFind.m_wsCondition = wsOriginCondition; 437 rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), 438 rndFind.m_Objects.end()); 439 rndFind.m_Objects.clear(); 440 } 441 child = child->GetNextSibling(); 442 } 443 if (rnd.m_Objects.size() > nNum) { 444 if (m_pNodeHelper->NodeIsTransparent(parentNode)) { 445 std::vector<CXFA_Node*> upArrayNodes; 446 m_pNodeHelper->CountSiblings(ToNode(rnd.m_Objects.front()), 447 XFA_LOGIC_Transparent, &upArrayNodes, 448 !!(dwStyles & XFA_RESOLVENODE_TagName)); 449 if (upArrayNodes.size() > rnd.m_Objects.size()) { 450 CXFA_Object* pSaveObject = rnd.m_Objects.front(); 451 rnd.m_Objects = std::vector<CXFA_Object*>(upArrayNodes.begin(), 452 upArrayNodes.end()); 453 rnd.m_Objects.front() = pSaveObject; 454 } 455 } 456 FilterCondition(rnd, wsCondition); 457 return !rnd.m_Objects.empty(); 458 } 459 } 460 461 if (dwStyles & XFA_RESOLVENODE_Parent) { 462 uint32_t dwSubStyles = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | 463 XFA_RESOLVENODE_Properties; 464 if (dwStyles & XFA_RESOLVENODE_TagName) 465 dwSubStyles |= XFA_RESOLVENODE_TagName; 466 if (dwStyles & XFA_RESOLVENODE_ALL) 467 dwSubStyles |= XFA_RESOLVENODE_ALL; 468 469 rndFind.m_dwStyles = dwSubStyles; 470 rndFind.m_CurObject = parentNode; 471 rnd.m_pSC->GetUpObjectArray()->push_back(parentNode); 472 ResolveNormal(rndFind); 473 rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), 474 rndFind.m_Objects.end()); 475 rndFind.m_Objects.clear(); 476 if (rnd.m_Objects.size() > nNum) 477 return true; 478 } 479 return false; 480} 481 482bool CFXJSE_ResolveProcessor::ResolveAsterisk(CFXJSE_ResolveNodeData& rnd) { 483 CXFA_Node* curNode = ToNode(rnd.m_CurObject); 484 std::vector<CXFA_Node*> array = 485 curNode->GetNodeList(XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties, 486 XFA_Element::Unknown); 487 rnd.m_Objects.insert(rnd.m_Objects.end(), array.begin(), array.end()); 488 return !rnd.m_Objects.empty(); 489} 490 491int32_t CFXJSE_ResolveProcessor::GetFilter(const WideStringView& wsExpression, 492 int32_t nStart, 493 CFXJSE_ResolveNodeData& rnd) { 494 ASSERT(nStart > -1); 495 496 int32_t iLength = wsExpression.GetLength(); 497 if (nStart >= iLength) 498 return 0; 499 500 WideString& wsName = rnd.m_wsName; 501 WideString& wsCondition = rnd.m_wsCondition; 502 wchar_t* pNameBuf = wsName.GetBuffer(iLength - nStart); 503 wchar_t* pConditionBuf = wsCondition.GetBuffer(iLength - nStart); 504 int32_t nNameCount = 0; 505 int32_t nConditionCount = 0; 506 std::vector<int32_t> stack; 507 int32_t nType = -1; 508 const wchar_t* pSrc = wsExpression.unterminated_c_str(); 509 wchar_t wPrev = 0; 510 wchar_t wCur; 511 bool bIsCondition = false; 512 while (nStart < iLength) { 513 wCur = pSrc[nStart++]; 514 if (wCur == '.') { 515 if (wPrev == '\\') { 516 pNameBuf[nNameCount - 1] = wPrev = '.'; 517 continue; 518 } 519 if (nNameCount == 0) { 520 rnd.m_dwStyles |= XFA_RESOLVENODE_AnyChild; 521 continue; 522 } 523 524 wchar_t wLookahead = nStart < iLength ? pSrc[nStart] : 0; 525 if (wLookahead != '[' && wLookahead != '(' && nType < 0) 526 break; 527 } 528 if (wCur == '[' || wCur == '(') { 529 bIsCondition = true; 530 } else if (wCur == '.' && nStart < iLength && 531 (pSrc[nStart] == '[' || pSrc[nStart] == '(')) { 532 bIsCondition = true; 533 } 534 if (bIsCondition) 535 pConditionBuf[nConditionCount++] = wCur; 536 else 537 pNameBuf[nNameCount++] = wCur; 538 539 if ((nType == 0 && wCur == ']') || (nType == 1 && wCur == ')') || 540 (nType == 2 && wCur == '"')) { 541 nType = stack.empty() ? -1 : stack.back(); 542 if (!stack.empty()) 543 stack.pop_back(); 544 } else if (wCur == '[') { 545 stack.push_back(nType); 546 nType = 0; 547 } else if (wCur == '(') { 548 stack.push_back(nType); 549 nType = 1; 550 } else if (wCur == '"') { 551 stack.push_back(nType); 552 nType = 2; 553 } 554 wPrev = wCur; 555 } 556 if (!stack.empty()) 557 return -1; 558 559 wsName.ReleaseBuffer(nNameCount); 560 wsName.Trim(); 561 wsCondition.ReleaseBuffer(nConditionCount); 562 wsCondition.Trim(); 563 rnd.m_uHashName = 564 static_cast<XFA_HashCode>(FX_HashCode_GetW(wsName.AsStringView(), false)); 565 return nStart; 566} 567 568void CFXJSE_ResolveProcessor::ConditionArray(int32_t iCurIndex, 569 WideString wsCondition, 570 int32_t iFoundCount, 571 CFXJSE_ResolveNodeData& rnd) { 572 int32_t iLen = wsCondition.GetLength(); 573 bool bRelative = false; 574 bool bAll = false; 575 int32_t i = 1; 576 for (; i < iLen; ++i) { 577 wchar_t ch = wsCondition[i]; 578 if (ch == ' ') 579 continue; 580 if (ch == '+' || ch == '-') 581 bRelative = true; 582 else if (ch == '*') 583 bAll = true; 584 585 break; 586 } 587 if (bAll) { 588 if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { 589 if (rnd.m_dwStyles & XFA_RESOLVENODE_Bind) { 590 m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurObject); 591 m_pNodeHelper->m_iCreateCount = 1; 592 rnd.m_Objects.clear(); 593 m_pNodeHelper->m_iCurAllStart = -1; 594 m_pNodeHelper->m_pAllStartParent = nullptr; 595 } else if (m_pNodeHelper->m_iCurAllStart == -1) { 596 m_pNodeHelper->m_iCurAllStart = m_iCurStart; 597 m_pNodeHelper->m_pAllStartParent = ToNode(rnd.m_CurObject); 598 } 599 } else if (rnd.m_dwStyles & XFA_RESOLVENODE_BindNew) { 600 if (m_pNodeHelper->m_iCurAllStart == -1) 601 m_pNodeHelper->m_iCurAllStart = m_iCurStart; 602 } 603 return; 604 } 605 if (iFoundCount == 1 && !iLen) 606 return; 607 608 int32_t iIndex = wsCondition.Mid(i, iLen - 1 - i).GetInteger(); 609 if (bRelative) 610 iIndex += iCurIndex; 611 612 if (iFoundCount <= iIndex || iIndex < 0) { 613 if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { 614 m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurObject); 615 m_pNodeHelper->m_iCreateCount = iIndex - iFoundCount + 1; 616 } 617 rnd.m_Objects.clear(); 618 } else { 619 CXFA_Object* ret = rnd.m_Objects[iIndex]; 620 rnd.m_Objects.clear(); 621 rnd.m_Objects.push_back(ret); 622 } 623} 624 625void CFXJSE_ResolveProcessor::DoPredicateFilter(int32_t iCurIndex, 626 WideString wsCondition, 627 int32_t iFoundCount, 628 CFXJSE_ResolveNodeData& rnd) { 629 ASSERT(iFoundCount == pdfium::CollectionSize<int32_t>(rnd.m_Objects)); 630 WideString wsExpression; 631 CXFA_Script::Type eLangType = CXFA_Script::Type::Unknown; 632 if (wsCondition.Left(2) == L".[" && wsCondition.Last() == L']') 633 eLangType = CXFA_Script::Type::Formcalc; 634 else if (wsCondition.Left(2) == L".(" && wsCondition.Last() == L')') 635 eLangType = CXFA_Script::Type::Javascript; 636 else 637 return; 638 639 CFXJSE_Engine* pContext = rnd.m_pSC; 640 wsExpression = wsCondition.Mid(2, wsCondition.GetLength() - 3); 641 for (int32_t i = iFoundCount - 1; i >= 0; i--) { 642 auto pRetValue = pdfium::MakeUnique<CFXJSE_Value>(rnd.m_pSC->GetIsolate()); 643 bool bRet = pContext->RunScript(eLangType, wsExpression.AsStringView(), 644 pRetValue.get(), rnd.m_Objects[i]); 645 if (!bRet || !pRetValue->ToBoolean()) 646 rnd.m_Objects.erase(rnd.m_Objects.begin() + i); 647 } 648} 649 650void CFXJSE_ResolveProcessor::FilterCondition(CFXJSE_ResolveNodeData& rnd, 651 WideString wsCondition) { 652 int32_t iCurrIndex = 0; 653 const std::vector<CXFA_Node*>* pArray = rnd.m_pSC->GetUpObjectArray(); 654 if (!pArray->empty()) { 655 CXFA_Node* curNode = pArray->back(); 656 bool bIsProperty = m_pNodeHelper->NodeIsProperty(curNode); 657 if (curNode->IsUnnamed() || 658 (bIsProperty && curNode->GetElementType() != XFA_Element::PageSet)) { 659 iCurrIndex = m_pNodeHelper->GetIndex(curNode, XFA_LOGIC_Transparent, 660 bIsProperty, true); 661 } else { 662 iCurrIndex = m_pNodeHelper->GetIndex(curNode, XFA_LOGIC_Transparent, 663 bIsProperty, false); 664 } 665 } 666 667 int32_t iFoundCount = pdfium::CollectionSize<int32_t>(rnd.m_Objects); 668 wsCondition.Trim(); 669 670 int32_t iLen = wsCondition.GetLength(); 671 if (!iLen) { 672 if (rnd.m_dwStyles & XFA_RESOLVENODE_ALL) 673 return; 674 if (iFoundCount == 1) 675 return; 676 677 if (iFoundCount <= iCurrIndex) { 678 if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { 679 m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurObject); 680 m_pNodeHelper->m_iCreateCount = iCurrIndex - iFoundCount + 1; 681 } 682 rnd.m_Objects.clear(); 683 return; 684 } 685 686 CXFA_Object* ret = rnd.m_Objects[iCurrIndex]; 687 rnd.m_Objects.clear(); 688 rnd.m_Objects.push_back(ret); 689 return; 690 } 691 692 wchar_t wTypeChar = wsCondition[0]; 693 switch (wTypeChar) { 694 case '[': 695 ConditionArray(iCurrIndex, wsCondition, iFoundCount, rnd); 696 return; 697 case '.': 698 if (iLen > 1 && (wsCondition[1] == '[' || wsCondition[1] == '(')) 699 DoPredicateFilter(iCurrIndex, wsCondition, iFoundCount, rnd); 700 return; 701 case '(': 702 case '"': 703 default: 704 return; 705 } 706} 707void CFXJSE_ResolveProcessor::SetStylesForChild(uint32_t dwParentStyles, 708 CFXJSE_ResolveNodeData& rnd) { 709 uint32_t dwSubStyles = XFA_RESOLVENODE_Children; 710 if (dwParentStyles & XFA_RESOLVENODE_TagName) 711 dwSubStyles |= XFA_RESOLVENODE_TagName; 712 713 dwSubStyles &= ~XFA_RESOLVENODE_Parent; 714 dwSubStyles &= ~XFA_RESOLVENODE_Siblings; 715 dwSubStyles &= ~XFA_RESOLVENODE_Properties; 716 dwSubStyles |= XFA_RESOLVENODE_ALL; 717 rnd.m_dwStyles = dwSubStyles; 718} 719 720void CFXJSE_ResolveProcessor::SetIndexDataBind(WideString& wsNextCondition, 721 int32_t& iIndex, 722 int32_t iCount) { 723 if (m_pNodeHelper->CreateNode_ForCondition(wsNextCondition)) { 724 if (m_pNodeHelper->m_eLastCreateType == XFA_Element::DataGroup) { 725 iIndex = 0; 726 } else { 727 iIndex = iCount - 1; 728 } 729 } else { 730 iIndex = iCount - 1; 731 } 732} 733 734CFXJSE_ResolveNodeData::CFXJSE_ResolveNodeData(CFXJSE_Engine* pSC) 735 : m_pSC(pSC), 736 m_CurObject(nullptr), 737 m_wsName(), 738 m_uHashName(XFA_HASHCODE_None), 739 m_wsCondition(), 740 m_nLevel(0), 741 m_Objects(), 742 m_dwStyles(XFA_RESOLVENODE_Children), 743 m_pScriptAttribute(nullptr), 744 m_dwFlag(XFA_ResolveNode_RSType_Nodes) {} 745 746CFXJSE_ResolveNodeData::~CFXJSE_ResolveNodeData() {} 747