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
CFXJSE_ResolveProcessor()27 CFXJSE_ResolveProcessor::CFXJSE_ResolveProcessor()
28 : m_iCurStart(0), m_pNodeHelper(pdfium::MakeUnique<CXFA_NodeHelper>()) {}
29
~CFXJSE_ResolveProcessor()30 CFXJSE_ResolveProcessor::~CFXJSE_ResolveProcessor() {}
31
Resolve(CFXJSE_ResolveNodeData & rnd)32 bool 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
ResolveAnyChild(CFXJSE_ResolveNodeData & rnd)91 bool 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
ResolveDollar(CFXJSE_ResolveNodeData & rnd)120 bool 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
ResolveExcalmatory(CFXJSE_ResolveNodeData & rnd)146 bool 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
ResolveNumberSign(CFXJSE_ResolveNodeData & rnd)170 bool 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
ResolveForAttributeRs(CXFA_Object * curNode,CFXJSE_ResolveNodeData & rnd,const WideStringView & strAttr)201 bool 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
ResolveNormal(CFXJSE_ResolveNodeData & rnd)216 bool 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
ResolveAsterisk(CFXJSE_ResolveNodeData & rnd)482 bool 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
GetFilter(const WideStringView & wsExpression,int32_t nStart,CFXJSE_ResolveNodeData & rnd)491 int32_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
ConditionArray(int32_t iCurIndex,WideString wsCondition,int32_t iFoundCount,CFXJSE_ResolveNodeData & rnd)568 void 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
DoPredicateFilter(int32_t iCurIndex,WideString wsCondition,int32_t iFoundCount,CFXJSE_ResolveNodeData & rnd)625 void 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
FilterCondition(CFXJSE_ResolveNodeData & rnd,WideString wsCondition)650 void 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 }
SetStylesForChild(uint32_t dwParentStyles,CFXJSE_ResolveNodeData & rnd)707 void 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
SetIndexDataBind(WideString & wsNextCondition,int32_t & iIndex,int32_t iCount)720 void 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
CFXJSE_ResolveNodeData(CFXJSE_Engine * pSC)734 CFXJSE_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
~CFXJSE_ResolveNodeData()746 CFXJSE_ResolveNodeData::~CFXJSE_ResolveNodeData() {}
747