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