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