Home | History | Annotate | Download | only in parser
      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 
     18 CXFA_ResolveProcessor::CXFA_ResolveProcessor()
     19     : m_iCurStart(0), m_pNodeHelper(new CXFA_NodeHelper) {}
     20 
     21 CXFA_ResolveProcessor::~CXFA_ResolveProcessor() {}
     22 
     23 int32_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 }
     79 int32_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 }
    103 int32_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 }
    130 int32_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 }
    155 int32_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 }
    184 int32_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 }
    198 int32_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 }
    491 int32_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 }
    500 int32_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 }
    510 int32_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 }
    610 void 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 }
    676 void 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 
    706 void 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 }
    766 void 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 }
    778 int32_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 }
    794 void 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 
    808 CXFA_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 
    820 CXFA_ResolveNodesData::~CXFA_ResolveNodesData() {
    821   m_Nodes.RemoveAll();
    822 }
    823