cxfa_resolveprocessor.cpp revision 33357cad1fd1321a2b38d2963e2585f27ce980a2
1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "xfa/fxfa/parser/cxfa_resolveprocessor.h"
8
9#include "core/fxcrt/fx_ext.h"
10#include "xfa/fxfa/parser/cxfa_document.h"
11#include "xfa/fxfa/parser/cxfa_nodehelper.h"
12#include "xfa/fxfa/parser/cxfa_scriptcontext.h"
13#include "xfa/fxfa/parser/xfa_localemgr.h"
14#include "xfa/fxfa/parser/xfa_object.h"
15#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
16#include "xfa/fxfa/parser/xfa_utils.h"
17
18CXFA_ResolveProcessor::CXFA_ResolveProcessor()
19    : m_iCurStart(0), m_pNodeHelper(new CXFA_NodeHelper) {}
20
21CXFA_ResolveProcessor::~CXFA_ResolveProcessor() {}
22
23int32_t CXFA_ResolveProcessor::Resolve(CXFA_ResolveNodesData& rnd) {
24  if (!rnd.m_CurNode) {
25    return -1;
26  }
27  if (!rnd.m_CurNode->IsNode()) {
28    if (rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) {
29      return ResolveForAttributeRs(rnd.m_CurNode, rnd,
30                                   rnd.m_wsName.AsStringC());
31    }
32    return 0;
33  }
34  if (rnd.m_dwStyles & XFA_RESOLVENODE_AnyChild) {
35    return ResolveAnyChild(rnd);
36  }
37  FX_WCHAR wch = rnd.m_wsName.GetAt(0);
38  switch (wch) {
39    case '$':
40      return ResolveDollar(rnd);
41    case '!':
42      return ResolveExcalmatory(rnd);
43    case '#':
44      return ResolveNumberSign(rnd);
45    case '*':
46      return ResolveAsterisk(rnd);
47    // TODO(dsinclair): We could probably remove this.
48    case '.':
49      return ResolveAnyChild(rnd);
50    default:
51      break;
52  }
53  if (rnd.m_uHashName == XFA_HASHCODE_This && rnd.m_nLevel == 0) {
54    rnd.m_Nodes.Add(rnd.m_pSC->GetThisObject());
55    return 1;
56  } else if (rnd.m_CurNode->GetElementType() == XFA_Element::Xfa) {
57    CXFA_Object* pObjNode =
58        rnd.m_pSC->GetDocument()->GetXFAObject(rnd.m_uHashName);
59    if (pObjNode) {
60      rnd.m_Nodes.Add(pObjNode);
61    } else if (rnd.m_uHashName == XFA_HASHCODE_Xfa) {
62      rnd.m_Nodes.Add(rnd.m_CurNode);
63    } else if ((rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) &&
64               ResolveForAttributeRs(rnd.m_CurNode, rnd,
65                                     rnd.m_wsName.AsStringC())) {
66      return 1;
67    }
68    if (rnd.m_Nodes.GetSize() > 0) {
69      FilterCondition(rnd, rnd.m_wsCondition);
70    }
71    return rnd.m_Nodes.GetSize();
72  }
73  int32_t nRet = ResolveNormal(rnd);
74  if (nRet < 1 && rnd.m_uHashName == XFA_HASHCODE_Xfa) {
75    rnd.m_Nodes.Add(rnd.m_pSC->GetDocument()->GetRoot());
76  }
77  return rnd.m_Nodes.GetSize();
78}
79int32_t CXFA_ResolveProcessor::ResolveAnyChild(CXFA_ResolveNodesData& rnd) {
80  CFX_WideString wsName = rnd.m_wsName;
81  CFX_WideString wsCondition = rnd.m_wsCondition;
82  CXFA_Node* findNode = nullptr;
83  CXFA_NodeArray siblings;
84  bool bClassName = false;
85  if (wsName.GetAt(0) == '#') {
86    bClassName = true;
87    wsName = wsName.Right(wsName.GetLength() - 1);
88  }
89  findNode = m_pNodeHelper->ResolveNodes_GetOneChild(
90      ToNode(rnd.m_CurNode), wsName.c_str(), bClassName);
91  if (!findNode) {
92    return 0;
93  }
94  if (wsCondition.IsEmpty()) {
95    rnd.m_Nodes.Add(findNode);
96    return rnd.m_Nodes.GetSize();
97  }
98  m_pNodeHelper->CountSiblings(findNode, XFA_LOGIC_Transparent,
99                               (CXFA_NodeArray*)&rnd.m_Nodes, bClassName);
100  FilterCondition(rnd, wsCondition);
101  return rnd.m_Nodes.GetSize();
102}
103int32_t CXFA_ResolveProcessor::ResolveDollar(CXFA_ResolveNodesData& rnd) {
104  CXFA_ObjArray& nodes = rnd.m_Nodes;
105  CFX_WideString wsName = rnd.m_wsName;
106  CFX_WideString wsCondition = rnd.m_wsCondition;
107  int32_t iNameLen = wsName.GetLength();
108  if (iNameLen == 1) {
109    nodes.Add(rnd.m_CurNode);
110    return 1;
111  }
112  if (rnd.m_nLevel > 0) {
113    return -1;
114  }
115  XFA_HashCode dwNameHash = static_cast<XFA_HashCode>(FX_HashCode_GetW(
116      CFX_WideStringC(wsName.c_str() + 1, iNameLen - 1), false));
117  if (dwNameHash == XFA_HASHCODE_Xfa) {
118    nodes.Add(rnd.m_pSC->GetDocument()->GetRoot());
119  } else {
120    CXFA_Object* pObjNode = rnd.m_pSC->GetDocument()->GetXFAObject(dwNameHash);
121    if (pObjNode) {
122      rnd.m_Nodes.Add(pObjNode);
123    }
124  }
125  if (rnd.m_Nodes.GetSize() > 0) {
126    FilterCondition(rnd, wsCondition);
127  }
128  return rnd.m_Nodes.GetSize();
129}
130int32_t CXFA_ResolveProcessor::ResolveExcalmatory(CXFA_ResolveNodesData& rnd) {
131  if (rnd.m_nLevel > 0) {
132    return 0;
133  }
134  CXFA_Node* datasets =
135      ToNode(rnd.m_pSC->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets));
136  if (!datasets) {
137    return 0;
138  }
139  CXFA_ResolveNodesData rndFind;
140  rndFind.m_pSC = rnd.m_pSC;
141  rndFind.m_CurNode = datasets;
142  rndFind.m_wsName = rnd.m_wsName.Right(rnd.m_wsName.GetLength() - 1);
143  rndFind.m_uHashName = static_cast<XFA_HashCode>(
144      FX_HashCode_GetW(rndFind.m_wsName.AsStringC(), false));
145  rndFind.m_nLevel = rnd.m_nLevel + 1;
146  rndFind.m_dwStyles = XFA_RESOLVENODE_Children;
147  rndFind.m_wsCondition = rnd.m_wsCondition;
148  Resolve(rndFind);
149  if (rndFind.m_Nodes.GetSize() > 0) {
150    rnd.m_Nodes.Append(rndFind.m_Nodes);
151    rndFind.m_Nodes.RemoveAll();
152  }
153  return rnd.m_Nodes.GetSize();
154}
155int32_t CXFA_ResolveProcessor::ResolveNumberSign(CXFA_ResolveNodesData& rnd) {
156  CFX_WideString wsName = rnd.m_wsName.Right(rnd.m_wsName.GetLength() - 1);
157  CFX_WideString wsCondition = rnd.m_wsCondition;
158  CXFA_Node* curNode = ToNode(rnd.m_CurNode);
159  if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringC())) {
160    return 1;
161  }
162  CXFA_ResolveNodesData rndFind;
163  rndFind.m_pSC = rnd.m_pSC;
164  rndFind.m_nLevel = rnd.m_nLevel + 1;
165  rndFind.m_dwStyles = rnd.m_dwStyles;
166  rndFind.m_dwStyles |= XFA_RESOLVENODE_TagName;
167  rndFind.m_dwStyles &= ~XFA_RESOLVENODE_Attributes;
168  rndFind.m_wsName = wsName;
169  rndFind.m_uHashName = static_cast<XFA_HashCode>(
170      FX_HashCode_GetW(rndFind.m_wsName.AsStringC(), false));
171  rndFind.m_wsCondition = wsCondition;
172  rndFind.m_CurNode = curNode;
173  ResolveNormal(rndFind);
174  if (rndFind.m_Nodes.GetSize() > 0) {
175    if (wsCondition.GetLength() == 0 && rndFind.m_Nodes.Find(curNode) >= 0) {
176      rnd.m_Nodes.Add(curNode);
177    } else {
178      rnd.m_Nodes.Append(rndFind.m_Nodes);
179      rndFind.m_Nodes.RemoveAll();
180    }
181  }
182  return rnd.m_Nodes.GetSize();
183}
184int32_t CXFA_ResolveProcessor::ResolveForAttributeRs(
185    CXFA_Object* curNode,
186    CXFA_ResolveNodesData& rnd,
187    const CFX_WideStringC& strAttr) {
188  const XFA_SCRIPTATTRIBUTEINFO* lpScriptAttribute =
189      XFA_GetScriptAttributeByName(curNode->GetElementType(), strAttr);
190  if (lpScriptAttribute) {
191    rnd.m_pScriptAttribute = lpScriptAttribute;
192    rnd.m_Nodes.Add(curNode);
193    rnd.m_dwFlag = XFA_RESOVENODE_RSTYPE_Attribute;
194    return 1;
195  }
196  return 0;
197}
198int32_t CXFA_ResolveProcessor::ResolveNormal(CXFA_ResolveNodesData& rnd) {
199  if (rnd.m_nLevel > 32) {
200    return 0;
201  }
202  if (!rnd.m_CurNode->IsNode()) {
203    return 0;
204  }
205  CXFA_Node* curNode = ToNode(rnd.m_CurNode);
206  CXFA_ObjArray& nodes = rnd.m_Nodes;
207  int32_t nNum = nodes.GetSize();
208  uint32_t dwStyles = rnd.m_dwStyles;
209  CFX_WideString& wsName = rnd.m_wsName;
210  XFA_HashCode uNameHash = rnd.m_uHashName;
211  CFX_WideString& wsCondition = rnd.m_wsCondition;
212  CXFA_ResolveNodesData rndFind;
213  rndFind.m_wsName = rnd.m_wsName;
214  rndFind.m_wsCondition = rnd.m_wsCondition;
215  rndFind.m_pSC = rnd.m_pSC;
216  rndFind.m_nLevel = rnd.m_nLevel + 1;
217  rndFind.m_uHashName = uNameHash;
218  CXFA_NodeArray children;
219  CXFA_NodeArray properties;
220  CXFA_Node* pVariablesNode = nullptr;
221  CXFA_Node* pPageSetNode = nullptr;
222  CXFA_Node* pChild = curNode->GetNodeItem(XFA_NODEITEM_FirstChild);
223  while (pChild) {
224    if (pChild->GetElementType() == XFA_Element::Variables) {
225      pVariablesNode = pChild;
226      pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling);
227      continue;
228    } else if (pChild->GetElementType() == XFA_Element::PageSet) {
229      pPageSetNode = pChild;
230      pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling);
231      continue;
232    } else {
233      const XFA_PROPERTY* pPropert = XFA_GetPropertyOfElement(
234          curNode->GetElementType(), pChild->GetElementType(),
235          XFA_XDPPACKET_UNKNOWN);
236      if (pPropert) {
237        properties.Add(pChild);
238      } else {
239        children.Add(pChild);
240      }
241    }
242    pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling);
243  }
244  if ((dwStyles & XFA_RESOLVENODE_Properties) && pVariablesNode) {
245    uint32_t uPropHash = pVariablesNode->GetClassHashCode();
246    if (uPropHash == uNameHash) {
247      nodes.Add(pVariablesNode);
248    } else {
249      rndFind.m_CurNode = pVariablesNode;
250      SetStylesForChild(dwStyles, rndFind);
251      CFX_WideString wsSaveCondition = rndFind.m_wsCondition;
252      rndFind.m_wsCondition.clear();
253      ResolveNormal(rndFind);
254      rndFind.m_wsCondition = wsSaveCondition;
255      if (rndFind.m_Nodes.GetSize() > 0) {
256        nodes.Append(rndFind.m_Nodes);
257        rndFind.m_Nodes.RemoveAll();
258      }
259    }
260    if (nodes.GetSize() > nNum) {
261      FilterCondition(rnd, wsCondition);
262      if (nodes.GetSize() > 0) {
263        return 1;
264      }
265      return 0;
266    }
267  }
268  if (dwStyles & XFA_RESOLVENODE_Children) {
269    bool bSetFlag = false;
270    if (pPageSetNode && (dwStyles & XFA_RESOLVENODE_Properties)) {
271      children.Add(pPageSetNode);
272    }
273    for (int32_t i = 0; i < children.GetSize(); i++) {
274      CXFA_Node* child = children[i];
275      if (dwStyles & XFA_RESOLVENODE_TagName) {
276        if (child->GetClassHashCode() == uNameHash) {
277          nodes.Add(child);
278        }
279      } else if (child->GetNameHash() == uNameHash) {
280        nodes.Add(child);
281      }
282      if (m_pNodeHelper->NodeIsTransparent(child) &&
283          child->GetElementType() != XFA_Element::PageSet) {
284        if (!bSetFlag) {
285          SetStylesForChild(dwStyles, rndFind);
286          bSetFlag = true;
287        }
288        rndFind.m_CurNode = child;
289        CFX_WideString wsSaveCondition = rndFind.m_wsCondition;
290        rndFind.m_wsCondition.clear();
291        ResolveNormal(rndFind);
292        rndFind.m_wsCondition = wsSaveCondition;
293        if (rndFind.m_Nodes.GetSize() > 0) {
294          nodes.Append(rndFind.m_Nodes);
295          rndFind.m_Nodes.RemoveAll();
296        }
297      }
298    }
299    if (nodes.GetSize() > nNum) {
300      if (!(dwStyles & XFA_RESOLVENODE_ALL)) {
301        CXFA_NodeArray upArrayNodes;
302        if (m_pNodeHelper->NodeIsTransparent(ToNode(curNode))) {
303          m_pNodeHelper->CountSiblings(ToNode(nodes[0]), XFA_LOGIC_Transparent,
304                                       &upArrayNodes,
305                                       !!(dwStyles & XFA_RESOLVENODE_TagName));
306        }
307        if (upArrayNodes.GetSize() > nodes.GetSize()) {
308          upArrayNodes[0] = ToNode(nodes[0]);
309          nodes.RemoveAll();
310          nodes.Append((CXFA_ObjArray&)upArrayNodes);
311          upArrayNodes.RemoveAll();
312        }
313      }
314      FilterCondition(rnd, wsCondition);
315      if (nodes.GetSize() > 0) {
316        return 1;
317      }
318      return 0;
319    }
320  }
321  if (dwStyles & XFA_RESOLVENODE_Attributes) {
322    if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringC())) {
323      return 1;
324    }
325  }
326  if (dwStyles & XFA_RESOLVENODE_Properties) {
327    for (int32_t i = 0; i < properties.GetSize(); i++) {
328      CXFA_Node* childProperty = properties[i];
329      if (childProperty->IsUnnamed()) {
330        uint32_t uPropHash = childProperty->GetClassHashCode();
331        if (uPropHash == uNameHash) {
332          nodes.Add(childProperty);
333        }
334      } else if (childProperty->GetNameHash() == uNameHash &&
335                 childProperty->GetElementType() != XFA_Element::Extras &&
336                 childProperty->GetElementType() != XFA_Element::Items) {
337        nodes.Add(childProperty);
338      }
339    }
340    if (nodes.GetSize() > nNum) {
341      FilterCondition(rnd, wsCondition);
342      if (nodes.GetSize() > 0) {
343        return 1;
344      }
345      return 0;
346    }
347    CXFA_Node* pProp = nullptr;
348    if (XFA_Element::Subform == curNode->GetElementType() &&
349        XFA_HASHCODE_Occur == uNameHash) {
350      CXFA_Node* pInstanceManager =
351          curNode->AsNode()->GetInstanceMgrOfSubform();
352      if (pInstanceManager) {
353        pProp = pInstanceManager->GetProperty(0, XFA_Element::Occur, true);
354      }
355    } else {
356      XFA_Element eType = XFA_GetElementTypeForName(wsName.AsStringC());
357      if (eType != XFA_Element::Unknown) {
358        pProp = curNode->AsNode()->GetProperty(0, eType,
359                                               eType != XFA_Element::PageSet);
360      }
361    }
362    if (pProp) {
363      nodes.Add(pProp);
364      return nodes.GetSize();
365    }
366  }
367  CXFA_Node* parentNode = m_pNodeHelper->ResolveNodes_GetParent(
368      curNode->AsNode(), XFA_LOGIC_NoTransparent);
369  uint32_t uCurClassHash = curNode->GetClassHashCode();
370  if (!parentNode) {
371    if (uCurClassHash == uNameHash) {
372      nodes.Add(curNode->AsNode());
373      FilterCondition(rnd, wsCondition);
374      if (nodes.GetSize() > 0) {
375        return 1;
376      }
377    }
378    return 0;
379  }
380  if (dwStyles & XFA_RESOLVENODE_Siblings) {
381    CXFA_Node* child = parentNode->GetNodeItem(XFA_NODEITEM_FirstChild);
382    uint32_t dwSubStyles =
383        XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties;
384    if (dwStyles & XFA_RESOLVENODE_TagName) {
385      dwSubStyles |= XFA_RESOLVENODE_TagName;
386    }
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            nodes.Add(curNode);
396          }
397        } else {
398          if (child->GetNameHash() == uNameHash) {
399            nodes.Add(curNode);
400            if (rnd.m_nLevel == 0 && wsCondition.GetLength() == 0) {
401              nodes.RemoveAll();
402              nodes.Add(curNode);
403              return 1;
404            }
405          }
406        }
407        child = child->GetNodeItem(XFA_NODEITEM_NextSibling);
408        continue;
409      }
410      if (dwStyles & XFA_RESOLVENODE_TagName) {
411        if (child->GetClassHashCode() == uNameHash) {
412          nodes.Add(child);
413        }
414      } else if (child->GetNameHash() == uNameHash) {
415        nodes.Add(child);
416      }
417      const XFA_PROPERTY* pPropert = XFA_GetPropertyOfElement(
418          parentNode->GetElementType(), child->GetElementType(),
419          XFA_XDPPACKET_UNKNOWN);
420      bool bInnerSearch = false;
421      if (pPropert) {
422        if ((child->GetElementType() == XFA_Element::Variables ||
423             child->GetElementType() == XFA_Element::PageSet)) {
424          bInnerSearch = true;
425        }
426      } else {
427        if (m_pNodeHelper->NodeIsTransparent(child)) {
428          bInnerSearch = true;
429        }
430      }
431      if (bInnerSearch) {
432        rndFind.m_CurNode = child;
433        CFX_WideString wsOriginCondition = rndFind.m_wsCondition;
434        rndFind.m_wsCondition.clear();
435        uint32_t dwOriginStyle = rndFind.m_dwStyles;
436        rndFind.m_dwStyles = dwOriginStyle | XFA_RESOLVENODE_ALL;
437        ResolveNormal(rndFind);
438        rndFind.m_dwStyles = dwOriginStyle;
439        rndFind.m_wsCondition = wsOriginCondition;
440        if (rndFind.m_Nodes.GetSize() > 0) {
441          nodes.Append(rndFind.m_Nodes);
442          rndFind.m_Nodes.RemoveAll();
443        }
444      }
445      child = child->GetNodeItem(XFA_NODEITEM_NextSibling);
446    }
447    if (nodes.GetSize() > nNum) {
448      if (m_pNodeHelper->NodeIsTransparent(parentNode)) {
449        CXFA_NodeArray upArrayNodes;
450        m_pNodeHelper->CountSiblings(ToNode(nodes[0]), XFA_LOGIC_Transparent,
451                                     &upArrayNodes,
452                                     !!(dwStyles & XFA_RESOLVENODE_TagName));
453        if (upArrayNodes.GetSize() > nodes.GetSize()) {
454          upArrayNodes[0] = ToNode(nodes[0]);
455          nodes.RemoveAll();
456          nodes.Append((CXFA_ObjArray&)upArrayNodes);
457          upArrayNodes.RemoveAll();
458        }
459      }
460      FilterCondition(rnd, wsCondition);
461      if (nodes.GetSize() > 0) {
462        return 1;
463      }
464      return 0;
465    }
466  }
467  if (dwStyles & XFA_RESOLVENODE_Parent) {
468    uint32_t dwSubStyles = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent |
469                           XFA_RESOLVENODE_Properties;
470    if (dwStyles & XFA_RESOLVENODE_TagName) {
471      dwSubStyles |= XFA_RESOLVENODE_TagName;
472    }
473    if (dwStyles & XFA_RESOLVENODE_ALL) {
474      dwSubStyles |= XFA_RESOLVENODE_ALL;
475    }
476    rndFind.m_dwStyles = dwSubStyles;
477    rndFind.m_CurNode = parentNode;
478    CXFA_NodeArray& array = rnd.m_pSC->GetUpObjectArray();
479    array.Add(parentNode);
480    ResolveNormal(rndFind);
481    if (rndFind.m_Nodes.GetSize() > 0) {
482      nodes.Append(rndFind.m_Nodes);
483      rndFind.m_Nodes.RemoveAll();
484    }
485    if (nodes.GetSize() > nNum) {
486      return 1;
487    }
488  }
489  return 0;
490}
491int32_t CXFA_ResolveProcessor::ResolveAsterisk(CXFA_ResolveNodesData& rnd) {
492  CXFA_Node* curNode = ToNode(rnd.m_CurNode);
493  CXFA_ObjArray& nodes = rnd.m_Nodes;
494  CXFA_NodeArray array;
495  curNode->GetNodeList(array,
496                       XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties);
497  nodes.Append((CXFA_ObjArray&)array);
498  return nodes.GetSize();
499}
500int32_t CXFA_ResolveProcessor::ResolvePopStack(
501    CFX_ArrayTemplate<int32_t>& stack) {
502  int32_t nType = -1;
503  int32_t iSize = stack.GetSize() - 1;
504  if (iSize > -1) {
505    nType = stack[iSize];
506    stack.RemoveAt(iSize, 1);
507  }
508  return nType;
509}
510int32_t CXFA_ResolveProcessor::GetFilter(const CFX_WideStringC& wsExpression,
511                                         int32_t nStart,
512                                         CXFA_ResolveNodesData& rnd) {
513  ASSERT(nStart > -1);
514  int32_t iLength = wsExpression.GetLength();
515  if (nStart >= iLength) {
516    return 0;
517  }
518  CFX_WideString& wsName = rnd.m_wsName;
519  CFX_WideString& wsCondition = rnd.m_wsCondition;
520  FX_WCHAR* pNameBuf = wsName.GetBuffer(iLength - nStart);
521  FX_WCHAR* pConditionBuf = wsCondition.GetBuffer(iLength - nStart);
522  int32_t nNameCount = 0;
523  int32_t nConditionCount = 0;
524  CFX_ArrayTemplate<int32_t> stack;
525  int32_t nType = -1;
526  const FX_WCHAR* pSrc = wsExpression.c_str();
527  FX_WCHAR wPrev = 0, wCur;
528  bool bIsCondition = false;
529  while (nStart < iLength) {
530    wCur = pSrc[nStart++];
531    if (wCur == '.') {
532      if (wPrev == '\\') {
533        pNameBuf[nNameCount - 1] = wPrev = '.';
534        continue;
535      }
536      if (nNameCount == 0) {
537        rnd.m_dwStyles |= XFA_RESOLVENODE_AnyChild;
538        continue;
539      }
540      FX_WCHAR wLookahead = nStart < iLength ? pSrc[nStart] : 0;
541      if (wLookahead != '[' && wLookahead != '(') {
542        if (nType < 0) {
543          break;
544        }
545      }
546    }
547    if (wCur == '[' || wCur == '(') {
548      bIsCondition = true;
549    } else if (wCur == '.' && nStart < iLength &&
550               (pSrc[nStart] == '[' || pSrc[nStart] == '(')) {
551      bIsCondition = true;
552    }
553    if (bIsCondition) {
554      pConditionBuf[nConditionCount++] = wCur;
555    } else {
556      pNameBuf[nNameCount++] = wCur;
557    }
558    bool bRecursive = true;
559    switch (nType) {
560      case 0:
561        if (wCur == ']') {
562          nType = ResolvePopStack(stack);
563          bRecursive = false;
564        }
565        break;
566      case 1:
567        if (wCur == ')') {
568          nType = ResolvePopStack(stack);
569          bRecursive = false;
570        }
571        break;
572      case 2:
573        if (wCur == '"') {
574          nType = ResolvePopStack(stack);
575          bRecursive = false;
576        }
577        break;
578    }
579    if (bRecursive) {
580      switch (wCur) {
581        case '[':
582          stack.Add(nType);
583          nType = 0;
584          break;
585        case '(':
586          stack.Add(nType);
587          nType = 1;
588          break;
589        case '"':
590          stack.Add(nType);
591          nType = 2;
592          break;
593      }
594    }
595    wPrev = wCur;
596  }
597  if (stack.GetSize() > 0) {
598    return -1;
599  }
600  wsName.ReleaseBuffer(nNameCount);
601  wsName.TrimLeft();
602  wsName.TrimRight();
603  wsCondition.ReleaseBuffer(nConditionCount);
604  wsCondition.TrimLeft();
605  wsCondition.TrimRight();
606  rnd.m_uHashName =
607      static_cast<XFA_HashCode>(FX_HashCode_GetW(wsName.AsStringC(), false));
608  return nStart;
609}
610void CXFA_ResolveProcessor::ConditionArray(int32_t iCurIndex,
611                                           CFX_WideString wsCondition,
612                                           int32_t iFoundCount,
613                                           CXFA_ResolveNodesData& rnd) {
614  CXFA_NodeArray& findNodes = (CXFA_NodeArray&)rnd.m_Nodes;
615  int32_t iLen = wsCondition.GetLength();
616  bool bRelative = false;
617  bool bAll = false;
618  int32_t i = 1;
619  for (; i < iLen; ++i) {
620    FX_WCHAR ch = wsCondition[i];
621    if (ch == ' ') {
622      continue;
623    }
624    if (ch == '+' || ch == '-') {
625      bRelative = true;
626      break;
627    } else if (ch == '*') {
628      bAll = true;
629      break;
630    } else {
631      break;
632    }
633  }
634  if (bAll) {
635    if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) {
636      if (rnd.m_dwStyles & XFA_RESOLVENODE_Bind) {
637        m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurNode);
638        m_pNodeHelper->m_iCreateCount = 1;
639        findNodes.RemoveAll();
640        m_pNodeHelper->m_iCurAllStart = -1;
641        m_pNodeHelper->m_pAllStartParent = nullptr;
642      } else {
643        if (m_pNodeHelper->m_iCurAllStart == -1) {
644          m_pNodeHelper->m_iCurAllStart = m_iCurStart;
645          m_pNodeHelper->m_pAllStartParent = ToNode(rnd.m_CurNode);
646        }
647      }
648    } else if (rnd.m_dwStyles & XFA_RESOLVENODE_BindNew) {
649      if (m_pNodeHelper->m_iCurAllStart == -1) {
650        m_pNodeHelper->m_iCurAllStart = m_iCurStart;
651      }
652    }
653    return;
654  }
655  if (iFoundCount == 1 && !iLen) {
656    return;
657  }
658  CFX_WideString wsIndex;
659  wsIndex = wsCondition.Mid(i, iLen - 1 - i);
660  int32_t iIndex = wsIndex.GetInteger();
661  if (bRelative) {
662    iIndex += iCurIndex;
663  }
664  if (iFoundCount <= iIndex || iIndex < 0) {
665    if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) {
666      m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurNode);
667      m_pNodeHelper->m_iCreateCount = iIndex - iFoundCount + 1;
668    }
669    findNodes.RemoveAll();
670  } else {
671    CXFA_Node* ret = findNodes[iIndex];
672    findNodes.RemoveAll();
673    findNodes.Add(ret);
674  }
675}
676void CXFA_ResolveProcessor::DoPredicateFilter(int32_t iCurIndex,
677                                              CFX_WideString wsCondition,
678                                              int32_t iFoundCount,
679                                              CXFA_ResolveNodesData& rnd) {
680  CXFA_NodeArray& findNodes = (CXFA_NodeArray&)rnd.m_Nodes;
681  ASSERT(iFoundCount == findNodes.GetSize());
682  CFX_WideString wsExpression;
683  XFA_SCRIPTLANGTYPE eLangType = XFA_SCRIPTLANGTYPE_Unkown;
684  if (wsCondition.Left(2) == L".[" && wsCondition.Right(1) == L"]") {
685    eLangType = XFA_SCRIPTLANGTYPE_Formcalc;
686  } else if (wsCondition.Left(2) == L".(" && wsCondition.Right(1) == L")") {
687    eLangType = XFA_SCRIPTLANGTYPE_Javascript;
688  } else {
689    return;
690  }
691
692  CXFA_ScriptContext* pContext = rnd.m_pSC;
693  wsExpression = wsCondition.Mid(2, wsCondition.GetLength() - 3);
694  for (int32_t i = iFoundCount - 1; i >= 0; i--) {
695    CXFA_Object* node = findNodes[i];
696    bool bRet = false;
697    std::unique_ptr<CFXJSE_Value> pRetValue(
698        new CFXJSE_Value(rnd.m_pSC->GetRuntime()));
699    bRet = pContext->RunScript(eLangType, wsExpression.AsStringC(),
700                               pRetValue.get(), node);
701    if (!bRet || !pRetValue->ToBoolean())
702      findNodes.RemoveAt(i);
703  }
704}
705
706void CXFA_ResolveProcessor::FilterCondition(CXFA_ResolveNodesData& rnd,
707                                            CFX_WideString wsCondition) {
708  CXFA_NodeArray& findNodes = (CXFA_NodeArray&)rnd.m_Nodes;
709  int32_t iCurrIndex = 0;
710  const CXFA_NodeArray& array = rnd.m_pSC->GetUpObjectArray();
711  int32_t iSize = array.GetSize();
712  if (iSize) {
713    CXFA_Node* curNode = array[iSize - 1];
714    bool bIsProperty = m_pNodeHelper->NodeIsProperty(curNode);
715    if (curNode->IsUnnamed() ||
716        (bIsProperty && curNode->GetElementType() != XFA_Element::PageSet)) {
717      iCurrIndex = m_pNodeHelper->GetIndex(curNode, XFA_LOGIC_Transparent,
718                                           bIsProperty, true);
719    } else {
720      iCurrIndex = m_pNodeHelper->GetIndex(curNode, XFA_LOGIC_Transparent,
721                                           bIsProperty, false);
722    }
723  }
724  int32_t iFoundCount = findNodes.GetSize();
725  wsCondition.TrimLeft();
726  wsCondition.TrimRight();
727  int32_t iLen = wsCondition.GetLength();
728  if (!iLen) {
729    if (rnd.m_dwStyles & XFA_RESOLVENODE_ALL) {
730      return;
731    }
732    if (iFoundCount == 1) {
733      return;
734    }
735    if (iFoundCount <= iCurrIndex) {
736      if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) {
737        m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurNode);
738        m_pNodeHelper->m_iCreateCount = iCurrIndex - iFoundCount + 1;
739      }
740      findNodes.RemoveAll();
741      return;
742    } else {
743      CXFA_Node* ret = findNodes[iCurrIndex];
744      findNodes.RemoveAll();
745      findNodes.Add(ret);
746      return;
747    }
748  }
749  FX_WCHAR wTypeChar = wsCondition[0];
750  switch (wTypeChar) {
751    case '[':
752      ConditionArray(iCurrIndex, wsCondition, iFoundCount, rnd);
753      return;
754    case '(':
755      return;
756    case '"':
757      return;
758    case '.':
759      if (iLen > 1 && (wsCondition[1] == '[' || wsCondition[1] == '(')) {
760        DoPredicateFilter(iCurrIndex, wsCondition, iFoundCount, rnd);
761      }
762    default:
763      return;
764  }
765}
766void CXFA_ResolveProcessor::SetStylesForChild(uint32_t dwParentStyles,
767                                              CXFA_ResolveNodesData& rnd) {
768  uint32_t dwSubStyles = XFA_RESOLVENODE_Children;
769  if (dwParentStyles & XFA_RESOLVENODE_TagName) {
770    dwSubStyles |= XFA_RESOLVENODE_TagName;
771  }
772  dwSubStyles &= ~XFA_RESOLVENODE_Parent;
773  dwSubStyles &= ~XFA_RESOLVENODE_Siblings;
774  dwSubStyles &= ~XFA_RESOLVENODE_Properties;
775  dwSubStyles |= XFA_RESOLVENODE_ALL;
776  rnd.m_dwStyles = dwSubStyles;
777}
778int32_t CXFA_ResolveProcessor::SetResultCreateNode(
779    XFA_RESOLVENODE_RS& resolveNodeRS,
780    CFX_WideString& wsLastCondition) {
781  if (m_pNodeHelper->m_pCreateParent) {
782    resolveNodeRS.nodes.Add(m_pNodeHelper->m_pCreateParent);
783  } else {
784    m_pNodeHelper->CreateNode_ForCondition(wsLastCondition);
785  }
786  resolveNodeRS.dwFlags = m_pNodeHelper->m_iCreateFlag;
787  if (resolveNodeRS.dwFlags == XFA_RESOLVENODE_RSTYPE_CreateNodeOne) {
788    if (m_pNodeHelper->m_iCurAllStart != -1) {
789      resolveNodeRS.dwFlags = XFA_RESOLVENODE_RSTYPE_CreateNodeMidAll;
790    }
791  }
792  return resolveNodeRS.nodes.GetSize();
793}
794void CXFA_ResolveProcessor::SetIndexDataBind(CFX_WideString& wsNextCondition,
795                                             int32_t& iIndex,
796                                             int32_t iCount) {
797  if (m_pNodeHelper->CreateNode_ForCondition(wsNextCondition)) {
798    if (m_pNodeHelper->m_eLastCreateType == XFA_Element::DataGroup) {
799      iIndex = 0;
800    } else {
801      iIndex = iCount - 1;
802    }
803  } else {
804    iIndex = iCount - 1;
805  }
806}
807
808CXFA_ResolveNodesData::CXFA_ResolveNodesData(CXFA_ScriptContext* pSC)
809    : m_pSC(pSC),
810      m_CurNode(nullptr),
811      m_wsName(),
812      m_uHashName(XFA_HASHCODE_None),
813      m_wsCondition(),
814      m_nLevel(0),
815      m_Nodes(),
816      m_dwStyles(XFA_RESOLVENODE_Children),
817      m_pScriptAttribute(nullptr),
818      m_dwFlag(XFA_RESOVENODE_RSTYPE_Nodes) {}
819
820CXFA_ResolveNodesData::~CXFA_ResolveNodesData() {
821  m_Nodes.RemoveAll();
822}
823