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