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/src/foxitlib.h"
      8 #include "xfa/src/fxfa/src/common/xfa_utils.h"
      9 #include "xfa/src/fxfa/src/common/xfa_object.h"
     10 #include "xfa/src/fxfa/src/common/xfa_document.h"
     11 #include "xfa/src/fxfa/src/common/xfa_parser.h"
     12 #include "xfa/src/fxfa/src/common/xfa_script.h"
     13 #include "xfa/src/fxfa/src/common/xfa_docdata.h"
     14 #include "xfa/src/fxfa/src/common/xfa_doclayout.h"
     15 #include "xfa/src/fxfa/src/common/xfa_localemgr.h"
     16 #include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h"
     17 #include "xfa_script_nodehelper.h"
     18 #include "xfa_script_imp.h"
     19 CXFA_NodeHelper::CXFA_NodeHelper(void)
     20     : m_eLastCreateType(XFA_ELEMENT_DataValue),
     21       m_pCreateParent(NULL),
     22       m_iCreateCount(0),
     23       m_iCreateFlag(XFA_RESOLVENODE_RSTYPE_CreateNodeOne),
     24       m_iCurAllStart(-1),
     25       m_pAllStartParent(NULL) {}
     26 CXFA_NodeHelper::~CXFA_NodeHelper(void) {}
     27 CXFA_Node* CXFA_NodeHelper::XFA_ResolveNodes_GetOneChild(
     28     CXFA_Node* parent,
     29     const FX_WCHAR* pwsName,
     30     FX_BOOL bIsClassName) {
     31   if (parent == NULL) {
     32     return NULL;
     33   }
     34   CXFA_NodeArray siblings;
     35   uint32_t uNameHash = FX_HashCode_String_GetW(pwsName, FXSYS_wcslen(pwsName));
     36   XFA_NodeAcc_TraverseAnySiblings(parent, uNameHash, &siblings, bIsClassName);
     37   if (siblings.GetSize() == 0) {
     38     return NULL;
     39   }
     40   return siblings[0];
     41 }
     42 int32_t CXFA_NodeHelper::XFA_CountSiblings(CXFA_Node* pNode,
     43                                            XFA_LOGIC_TYPE eLogicType,
     44                                            CXFA_NodeArray* pSiblings,
     45                                            FX_BOOL bIsClassName) {
     46   CXFA_Node* parent =
     47       XFA_ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent);
     48   if (parent == NULL) {
     49     return 0;
     50   }
     51   XFA_LPCPROPERTY pPropert = XFA_GetPropertyOfElement(
     52       parent->GetClassID(), pNode->GetClassID(), XFA_XDPPACKET_UNKNOWN);
     53   if (!pPropert && eLogicType == XFA_LOGIC_Transparent) {
     54     parent = XFA_ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent);
     55     if (parent == NULL) {
     56       return 0;
     57     }
     58   }
     59   if (bIsClassName) {
     60     return XFA_NodeAcc_TraverseSiblings(parent, pNode->GetClassHashCode(),
     61                                         pSiblings, eLogicType, bIsClassName);
     62   } else {
     63     return XFA_NodeAcc_TraverseSiblings(parent, pNode->GetNameHash(), pSiblings,
     64                                         eLogicType, bIsClassName);
     65   }
     66 }
     67 int32_t CXFA_NodeHelper::XFA_NodeAcc_TraverseAnySiblings(
     68     CXFA_Node* parent,
     69     FX_DWORD dNameHash,
     70     CXFA_NodeArray* pSiblings,
     71     FX_BOOL bIsClassName) {
     72   if (parent == NULL || pSiblings == NULL) {
     73     return 0;
     74   }
     75   int32_t nCount = 0;
     76   int32_t i = 0;
     77   CXFA_NodeArray properties;
     78   parent->GetNodeList(properties, XFA_NODEFILTER_Properties);
     79   int32_t nProperties = properties.GetSize();
     80   for (i = 0; i < nProperties; ++i) {
     81     CXFA_Node* child = properties[i];
     82     if (bIsClassName) {
     83       if (child->GetClassHashCode() == dNameHash) {
     84         pSiblings->Add(child);
     85         nCount++;
     86       }
     87     } else {
     88       if (child->GetNameHash() == dNameHash) {
     89         pSiblings->Add(child);
     90         nCount++;
     91       }
     92     }
     93     if (nCount > 0) {
     94       return nCount;
     95     }
     96     nCount += XFA_NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings,
     97                                               bIsClassName);
     98   }
     99   CXFA_NodeArray children;
    100   parent->GetNodeList(children, XFA_NODEFILTER_Children);
    101   int32_t nChildren = children.GetSize();
    102   for (i = 0; i < nChildren; i++) {
    103     CXFA_Node* child = children[i];
    104     if (bIsClassName) {
    105       if (child->GetClassHashCode() == dNameHash) {
    106         if (pSiblings) {
    107           pSiblings->Add(child);
    108         }
    109         nCount++;
    110       }
    111     } else {
    112       if (child->GetNameHash() == dNameHash) {
    113         if (pSiblings) {
    114           pSiblings->Add(child);
    115         }
    116         nCount++;
    117       }
    118     }
    119     if (nCount > 0) {
    120       return nCount;
    121     }
    122     nCount += XFA_NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings,
    123                                               bIsClassName);
    124   }
    125   return nCount;
    126 }
    127 int32_t CXFA_NodeHelper::XFA_NodeAcc_TraverseSiblings(CXFA_Node* parent,
    128                                                       FX_DWORD dNameHash,
    129                                                       CXFA_NodeArray* pSiblings,
    130                                                       XFA_LOGIC_TYPE eLogicType,
    131                                                       FX_BOOL bIsClassName,
    132                                                       FX_BOOL bIsFindProperty) {
    133   if (parent == NULL || pSiblings == NULL) {
    134     return 0;
    135   }
    136   int32_t nCount = 0;
    137   int32_t i = 0;
    138   if (bIsFindProperty) {
    139     CXFA_NodeArray properties;
    140     parent->GetNodeList(properties, XFA_NODEFILTER_Properties);
    141     int32_t nProperties = properties.GetSize();
    142     for (i = 0; i < nProperties; ++i) {
    143       CXFA_Node* child = properties[i];
    144       if (bIsClassName) {
    145         if (child->GetClassHashCode() == dNameHash) {
    146           pSiblings->Add(child);
    147           nCount++;
    148         }
    149       } else {
    150         if (child->GetNameHash() == dNameHash) {
    151           if (child->GetClassID() != XFA_ELEMENT_PageSet &&
    152               child->GetClassID() != XFA_ELEMENT_Extras &&
    153               child->GetClassID() != XFA_ELEMENT_Items) {
    154             pSiblings->Add(child);
    155             nCount++;
    156           }
    157         }
    158       }
    159       if (child->IsUnnamed() && child->GetClassID() == XFA_ELEMENT_PageSet) {
    160         nCount += XFA_NodeAcc_TraverseSiblings(child, dNameHash, pSiblings,
    161                                                eLogicType, bIsClassName, FALSE);
    162       }
    163     }
    164     if (nCount > 0) {
    165       return nCount;
    166     }
    167   }
    168   CXFA_NodeArray children;
    169   parent->GetNodeList(children, XFA_NODEFILTER_Children);
    170   int32_t nChildren = children.GetSize();
    171   for (i = 0; i < nChildren; i++) {
    172     CXFA_Node* child = children[i];
    173     if (child->GetClassID() == XFA_ELEMENT_Variables) {
    174       continue;
    175     }
    176     if (bIsClassName) {
    177       if (child->GetClassHashCode() == dNameHash) {
    178         if (pSiblings) {
    179           pSiblings->Add(child);
    180         }
    181         nCount++;
    182       }
    183     } else {
    184       if (child->GetNameHash() == dNameHash) {
    185         if (pSiblings) {
    186           pSiblings->Add(child);
    187         }
    188         nCount++;
    189       }
    190     }
    191     if (eLogicType == XFA_LOGIC_NoTransparent) {
    192       continue;
    193     }
    194     if (XFA_NodeIsTransparent(child) &&
    195         child->GetClassID() != XFA_ELEMENT_PageSet) {
    196       nCount += XFA_NodeAcc_TraverseSiblings(child, dNameHash, pSiblings,
    197                                              eLogicType, bIsClassName, FALSE);
    198     }
    199   }
    200   return nCount;
    201 }
    202 CXFA_Node* CXFA_NodeHelper::XFA_ResolveNodes_GetParent(
    203     CXFA_Node* pNode,
    204     XFA_LOGIC_TYPE eLogicType) {
    205   if (!pNode) {
    206     return NULL;
    207   }
    208   if (eLogicType == XFA_LOGIC_NoTransparent) {
    209     return pNode->GetNodeItem(XFA_NODEITEM_Parent);
    210   }
    211   CXFA_Node* parent;
    212   CXFA_Node* node = pNode;
    213   while (TRUE) {
    214     parent = XFA_ResolveNodes_GetParent(node);
    215     if (parent == NULL) {
    216       break;
    217     }
    218     XFA_ELEMENT parentElement = parent->GetClassID();
    219     if ((!parent->IsUnnamed() && parentElement != XFA_ELEMENT_SubformSet) ||
    220         parentElement == XFA_ELEMENT_Variables) {
    221       break;
    222     }
    223     node = parent;
    224   }
    225   return parent;
    226 }
    227 int32_t CXFA_NodeHelper::XFA_GetIndex(CXFA_Node* pNode,
    228                                       XFA_LOGIC_TYPE eLogicType,
    229                                       FX_BOOL bIsProperty,
    230                                       FX_BOOL bIsClassIndex) {
    231   CXFA_Node* parent =
    232       XFA_ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent);
    233   if (parent == NULL) {
    234     return 0;
    235   }
    236   if (!bIsProperty && eLogicType == XFA_LOGIC_Transparent) {
    237     parent = XFA_ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent);
    238     if (parent == NULL) {
    239       return 0;
    240     }
    241   }
    242   FX_DWORD dwHashName = pNode->GetNameHash();
    243   if (bIsClassIndex) {
    244     dwHashName = pNode->GetClassHashCode();
    245   }
    246   CXFA_NodeArray siblings;
    247   int32_t iSize = XFA_NodeAcc_TraverseSiblings(parent, dwHashName, &siblings,
    248                                                eLogicType, bIsClassIndex);
    249   for (int32_t i = 0; i < iSize; ++i) {
    250     CXFA_Node* child = siblings[i];
    251     if (child == pNode) {
    252       return i;
    253     }
    254   }
    255   return 0;
    256 }
    257 void CXFA_NodeHelper::XFA_GetNameExpression(CXFA_Node* refNode,
    258                                             CFX_WideString& wsName,
    259                                             FX_BOOL bIsAllPath,
    260                                             XFA_LOGIC_TYPE eLogicType) {
    261   wsName.Empty();
    262   if (bIsAllPath) {
    263     XFA_GetNameExpression(refNode, wsName, FALSE, eLogicType);
    264     CFX_WideString wsParent;
    265     CXFA_Node* parent =
    266         XFA_ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent);
    267     while (parent != NULL) {
    268       XFA_GetNameExpression(parent, wsParent, FALSE, eLogicType);
    269       wsParent += L".";
    270       wsParent += wsName;
    271       wsName = wsParent;
    272       parent = XFA_ResolveNodes_GetParent(parent, XFA_LOGIC_NoTransparent);
    273     }
    274     return;
    275   } else {
    276     CFX_WideStringC wsTagName;
    277     CFX_WideString ws;
    278     FX_BOOL bIsProperty = XFA_NodeIsProperty(refNode);
    279     if (refNode->IsUnnamed() ||
    280         (bIsProperty && refNode->GetClassID() != XFA_ELEMENT_PageSet)) {
    281       refNode->GetClassName(wsTagName);
    282       ws = wsTagName;
    283       wsName.Format(L"#%s[%d]", (const FX_WCHAR*)ws,
    284                     XFA_GetIndex(refNode, eLogicType, bIsProperty, TRUE));
    285       return;
    286     }
    287     ws = refNode->GetCData(XFA_ATTRIBUTE_Name);
    288     ws.Replace(L".", L"\\.");
    289     wsName.Format(L"%s[%d]", (const FX_WCHAR*)ws,
    290                   XFA_GetIndex(refNode, eLogicType, bIsProperty, FALSE));
    291   }
    292 }
    293 FX_BOOL CXFA_NodeHelper::XFA_NodeIsTransparent(CXFA_Node* refNode) {
    294   if (refNode == NULL) {
    295     return FALSE;
    296   }
    297   XFA_ELEMENT eRefNode = refNode->GetClassID();
    298   if ((refNode->IsUnnamed() && refNode->IsContainerNode()) ||
    299       eRefNode == XFA_ELEMENT_SubformSet || eRefNode == XFA_ELEMENT_Area ||
    300       eRefNode == XFA_ELEMENT_Proto) {
    301     return TRUE;
    302   }
    303   return FALSE;
    304 }
    305 FX_BOOL CXFA_NodeHelper::XFA_CreateNode_ForCondition(
    306     CFX_WideString& wsCondition) {
    307   int32_t iLen = wsCondition.GetLength();
    308   CFX_WideString wsIndex = FX_WSTRC(L"0");
    309   ;
    310   FX_BOOL bAll = FALSE;
    311   if (iLen == 0) {
    312     m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne;
    313     return FALSE;
    314   }
    315   if (wsCondition.GetAt(0) == '[') {
    316     int32_t i = 1;
    317     for (; i < iLen; ++i) {
    318       FX_WCHAR ch = wsCondition[i];
    319       if (ch == ' ') {
    320         continue;
    321       }
    322       if (ch == '+' || ch == '-') {
    323         break;
    324       } else if (ch == '*') {
    325         bAll = TRUE;
    326         break;
    327       } else {
    328         break;
    329       }
    330     }
    331     if (bAll) {
    332       wsIndex = FX_WSTRC(L"1");
    333       m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeAll;
    334     } else {
    335       m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne;
    336       wsIndex = wsCondition.Mid(i, iLen - 1 - i);
    337     }
    338     int32_t iIndex = wsIndex.GetInteger();
    339     m_iCreateCount = iIndex;
    340     return TRUE;
    341   }
    342   return FALSE;
    343 }
    344 FX_BOOL CXFA_NodeHelper::XFA_ResolveNodes_CreateNode(
    345     CFX_WideString wsName,
    346     CFX_WideString wsCondition,
    347     FX_BOOL bLastNode,
    348     CXFA_ScriptContext* pScriptContext) {
    349   if (m_pCreateParent == NULL) {
    350     return FALSE;
    351   }
    352   FX_BOOL bIsClassName = FALSE;
    353   FX_BOOL bResult = FALSE;
    354   if (wsName.GetAt(0) == '!') {
    355     wsName = wsName.Right(wsName.GetLength() - 1);
    356     m_pCreateParent = (CXFA_Node*)pScriptContext->GetDocument()->GetXFANode(
    357         XFA_HASHCODE_Datasets);
    358   }
    359   if (wsName.GetAt(0) == '#') {
    360     bIsClassName = TRUE;
    361     wsName = wsName.Right(wsName.GetLength() - 1);
    362   }
    363   if (m_iCreateCount == 0) {
    364     XFA_CreateNode_ForCondition(wsCondition);
    365   }
    366   if (bIsClassName) {
    367     XFA_LPCELEMENTINFO lpElement = XFA_GetElementByName(wsName);
    368     if (lpElement == NULL) {
    369       return FALSE;
    370     }
    371     for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) {
    372       CXFA_Node* pNewNode =
    373           m_pCreateParent->CreateSamePacketNode(lpElement->eName);
    374       if (pNewNode) {
    375         m_pCreateParent->InsertChild(pNewNode);
    376         if (iIndex == m_iCreateCount - 1) {
    377           m_pCreateParent = pNewNode;
    378         }
    379         bResult = TRUE;
    380       }
    381     }
    382   } else {
    383     XFA_ELEMENT eClassType = XFA_ELEMENT_DataGroup;
    384     if (bLastNode) {
    385       eClassType = m_eLastCreateType;
    386     }
    387     for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) {
    388       CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eClassType);
    389       if (pNewNode) {
    390         pNewNode->SetAttribute(XFA_ATTRIBUTE_Name, wsName);
    391         pNewNode->CreateXMLMappingNode();
    392         m_pCreateParent->InsertChild(pNewNode);
    393         if (iIndex == m_iCreateCount - 1) {
    394           m_pCreateParent = pNewNode;
    395         }
    396         bResult = TRUE;
    397       }
    398     }
    399   }
    400   if (!bResult) {
    401     m_pCreateParent = NULL;
    402   }
    403   return bResult;
    404 }
    405 void CXFA_NodeHelper::XFA_SetCreateNodeType(CXFA_Node* refNode) {
    406   if (refNode == NULL) {
    407     return;
    408   }
    409   if (refNode->GetClassID() == XFA_ELEMENT_Subform) {
    410     m_eLastCreateType = XFA_ELEMENT_DataGroup;
    411   } else if (refNode->GetClassID() == XFA_ELEMENT_Field) {
    412     m_eLastCreateType = XFA_FieldIsMultiListBox(refNode)
    413                             ? XFA_ELEMENT_DataGroup
    414                             : XFA_ELEMENT_DataValue;
    415   } else if (refNode->GetClassID() == XFA_ELEMENT_ExclGroup) {
    416     m_eLastCreateType = XFA_ELEMENT_DataValue;
    417   }
    418 }
    419 FX_BOOL CXFA_NodeHelper::XFA_NodeIsProperty(CXFA_Node* refNode) {
    420   FX_BOOL bRes = FALSE;
    421   CXFA_Node* parent =
    422       XFA_ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent);
    423   if (parent != NULL && refNode != NULL) {
    424     XFA_LPCPROPERTY pPropert = XFA_GetPropertyOfElement(
    425         parent->GetClassID(), refNode->GetClassID(), XFA_XDPPACKET_UNKNOWN);
    426     if (pPropert) {
    427       bRes = TRUE;
    428     }
    429   }
    430   return bRes;
    431 }
    432