| 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/fxfa/parser/xfa_script_nodehelper.h" | |
| 8 | |
| 9 #include "core/fxcrt/include/fx_ext.h" | |
| 10 #include "xfa/fxfa/parser/xfa_doclayout.h" | |
| 11 #include "xfa/fxfa/parser/xfa_document.h" | |
| 12 #include "xfa/fxfa/parser/xfa_localemgr.h" | |
| 13 #include "xfa/fxfa/parser/xfa_object.h" | |
| 14 #include "xfa/fxfa/parser/xfa_script.h" | |
| 15 #include "xfa/fxfa/parser/xfa_script_imp.h" | |
| 16 #include "xfa/fxfa/parser/xfa_utils.h" | |
| 17 | |
| 18 CXFA_NodeHelper::CXFA_NodeHelper() | |
| 19 : m_eLastCreateType(XFA_Element::DataValue), | |
| 20 m_pCreateParent(nullptr), | |
| 21 m_iCreateCount(0), | |
| 22 m_iCreateFlag(XFA_RESOLVENODE_RSTYPE_CreateNodeOne), | |
| 23 m_iCurAllStart(-1), | |
| 24 m_pAllStartParent(nullptr) {} | |
| 25 | |
| 26 CXFA_NodeHelper::~CXFA_NodeHelper() {} | |
| 27 | |
| 28 CXFA_Node* CXFA_NodeHelper::ResolveNodes_GetOneChild(CXFA_Node* parent, | |
| 29 const FX_WCHAR* pwsName, | |
| 30 FX_BOOL bIsClassName) { | |
| 31 if (!parent) { | |
| 32 return nullptr; | |
| 33 } | |
| 34 CXFA_NodeArray siblings; | |
| 35 uint32_t uNameHash = FX_HashCode_GetW(CFX_WideStringC(pwsName), false); | |
| 36 NodeAcc_TraverseAnySiblings(parent, uNameHash, &siblings, bIsClassName); | |
| 37 if (siblings.GetSize() == 0) { | |
| 38 return nullptr; | |
| 39 } | |
| 40 return siblings[0]; | |
| 41 } | |
| 42 | |
| 43 int32_t CXFA_NodeHelper::CountSiblings(CXFA_Node* pNode, | |
| 44 XFA_LOGIC_TYPE eLogicType, | |
| 45 CXFA_NodeArray* pSiblings, | |
| 46 FX_BOOL bIsClassName) { | |
| 47 if (!pNode) | |
| 48 return 0; | |
| 49 CXFA_Node* parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent); | |
| 50 if (!parent) | |
| 51 return 0; | |
| 52 const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement( | |
| 53 parent->GetElementType(), pNode->GetElementType(), XFA_XDPPACKET_UNKNOWN); | |
| 54 if (!pProperty && eLogicType == XFA_LOGIC_Transparent) { | |
| 55 parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent); | |
| 56 if (!parent) { | |
| 57 return 0; | |
| 58 } | |
| 59 } | |
| 60 if (bIsClassName) { | |
| 61 return NodeAcc_TraverseSiblings(parent, pNode->GetClassHashCode(), | |
| 62 pSiblings, eLogicType, bIsClassName); | |
| 63 } else { | |
| 64 return NodeAcc_TraverseSiblings(parent, pNode->GetNameHash(), pSiblings, | |
| 65 eLogicType, bIsClassName); | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 int32_t CXFA_NodeHelper::NodeAcc_TraverseAnySiblings(CXFA_Node* parent, | |
| 70 uint32_t dNameHash, | |
| 71 CXFA_NodeArray* pSiblings, | |
| 72 FX_BOOL bIsClassName) { | |
| 73 if (!parent || !pSiblings) { | |
| 74 return 0; | |
| 75 } | |
| 76 int32_t nCount = 0; | |
| 77 int32_t i = 0; | |
| 78 CXFA_NodeArray properties; | |
| 79 parent->GetNodeList(properties, XFA_NODEFILTER_Properties); | |
| 80 int32_t nProperties = properties.GetSize(); | |
| 81 for (i = 0; i < nProperties; ++i) { | |
| 82 CXFA_Node* child = properties[i]; | |
| 83 if (bIsClassName) { | |
| 84 if (child->GetClassHashCode() == dNameHash) { | |
| 85 pSiblings->Add(child); | |
| 86 nCount++; | |
| 87 } | |
| 88 } else { | |
| 89 if (child->GetNameHash() == dNameHash) { | |
| 90 pSiblings->Add(child); | |
| 91 nCount++; | |
| 92 } | |
| 93 } | |
| 94 if (nCount > 0) { | |
| 95 return nCount; | |
| 96 } | |
| 97 nCount += | |
| 98 NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName); | |
| 99 } | |
| 100 CXFA_NodeArray children; | |
| 101 parent->GetNodeList(children, XFA_NODEFILTER_Children); | |
| 102 int32_t nChildren = children.GetSize(); | |
| 103 for (i = 0; i < nChildren; i++) { | |
| 104 CXFA_Node* child = children[i]; | |
| 105 if (bIsClassName) { | |
| 106 if (child->GetClassHashCode() == dNameHash) { | |
| 107 if (pSiblings) { | |
| 108 pSiblings->Add(child); | |
| 109 } | |
| 110 nCount++; | |
| 111 } | |
| 112 } else { | |
| 113 if (child->GetNameHash() == dNameHash) { | |
| 114 if (pSiblings) { | |
| 115 pSiblings->Add(child); | |
| 116 } | |
| 117 nCount++; | |
| 118 } | |
| 119 } | |
| 120 if (nCount > 0) { | |
| 121 return nCount; | |
| 122 } | |
| 123 nCount += | |
| 124 NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName); | |
| 125 } | |
| 126 return nCount; | |
| 127 } | |
| 128 | |
| 129 int32_t CXFA_NodeHelper::NodeAcc_TraverseSiblings(CXFA_Node* parent, | |
| 130 uint32_t dNameHash, | |
| 131 CXFA_NodeArray* pSiblings, | |
| 132 XFA_LOGIC_TYPE eLogicType, | |
| 133 FX_BOOL bIsClassName, | |
| 134 FX_BOOL bIsFindProperty) { | |
| 135 if (!parent || !pSiblings) { | |
| 136 return 0; | |
| 137 } | |
| 138 int32_t nCount = 0; | |
| 139 int32_t i = 0; | |
| 140 if (bIsFindProperty) { | |
| 141 CXFA_NodeArray properties; | |
| 142 parent->GetNodeList(properties, XFA_NODEFILTER_Properties); | |
| 143 int32_t nProperties = properties.GetSize(); | |
| 144 for (i = 0; i < nProperties; ++i) { | |
| 145 CXFA_Node* child = properties[i]; | |
| 146 if (bIsClassName) { | |
| 147 if (child->GetClassHashCode() == dNameHash) { | |
| 148 pSiblings->Add(child); | |
| 149 nCount++; | |
| 150 } | |
| 151 } else { | |
| 152 if (child->GetNameHash() == dNameHash) { | |
| 153 if (child->GetElementType() != XFA_Element::PageSet && | |
| 154 child->GetElementType() != XFA_Element::Extras && | |
| 155 child->GetElementType() != XFA_Element::Items) { | |
| 156 pSiblings->Add(child); | |
| 157 nCount++; | |
| 158 } | |
| 159 } | |
| 160 } | |
| 161 if (child->IsUnnamed() && | |
| 162 child->GetElementType() == XFA_Element::PageSet) { | |
| 163 nCount += 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->GetElementType() == 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 (NodeIsTransparent(child) && | |
| 198 child->GetElementType() != XFA_Element::PageSet) { | |
| 199 nCount += NodeAcc_TraverseSiblings(child, dNameHash, pSiblings, | |
| 200 eLogicType, bIsClassName, FALSE); | |
| 201 } | |
| 202 } | |
| 203 return nCount; | |
| 204 } | |
| 205 | |
| 206 CXFA_Node* CXFA_NodeHelper::ResolveNodes_GetParent(CXFA_Node* pNode, | |
| 207 XFA_LOGIC_TYPE eLogicType) { | |
| 208 if (!pNode) { | |
| 209 return nullptr; | |
| 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 = ResolveNodes_GetParent(node); | |
| 218 if (!parent) { | |
| 219 break; | |
| 220 } | |
| 221 XFA_Element parentType = parent->GetElementType(); | |
| 222 if ((!parent->IsUnnamed() && parentType != XFA_Element::SubformSet) || | |
| 223 parentType == XFA_Element::Variables) { | |
| 224 break; | |
| 225 } | |
| 226 node = parent; | |
| 227 } | |
| 228 return parent; | |
| 229 } | |
| 230 | |
| 231 int32_t CXFA_NodeHelper::GetIndex(CXFA_Node* pNode, | |
| 232 XFA_LOGIC_TYPE eLogicType, | |
| 233 FX_BOOL bIsProperty, | |
| 234 FX_BOOL bIsClassIndex) { | |
| 235 CXFA_Node* parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent); | |
| 236 if (!parent) { | |
| 237 return 0; | |
| 238 } | |
| 239 if (!bIsProperty && eLogicType == XFA_LOGIC_Transparent) { | |
| 240 parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent); | |
| 241 if (!parent) { | |
| 242 return 0; | |
| 243 } | |
| 244 } | |
| 245 uint32_t dwHashName = pNode->GetNameHash(); | |
| 246 if (bIsClassIndex) { | |
| 247 dwHashName = pNode->GetClassHashCode(); | |
| 248 } | |
| 249 CXFA_NodeArray siblings; | |
| 250 int32_t iSize = 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 | |
| 261 void CXFA_NodeHelper::GetNameExpression(CXFA_Node* refNode, | |
| 262 CFX_WideString& wsName, | |
| 263 FX_BOOL bIsAllPath, | |
| 264 XFA_LOGIC_TYPE eLogicType) { | |
| 265 wsName.clear(); | |
| 266 if (bIsAllPath) { | |
| 267 GetNameExpression(refNode, wsName, FALSE, eLogicType); | |
| 268 CFX_WideString wsParent; | |
| 269 CXFA_Node* parent = | |
| 270 ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent); | |
| 271 while (parent) { | |
| 272 GetNameExpression(parent, wsParent, FALSE, eLogicType); | |
| 273 wsParent += L"."; | |
| 274 wsParent += wsName; | |
| 275 wsName = wsParent; | |
| 276 parent = ResolveNodes_GetParent(parent, XFA_LOGIC_NoTransparent); | |
| 277 } | |
| 278 return; | |
| 279 } | |
| 280 | |
| 281 CFX_WideString ws; | |
| 282 FX_BOOL bIsProperty = NodeIsProperty(refNode); | |
| 283 if (refNode->IsUnnamed() || | |
| 284 (bIsProperty && refNode->GetElementType() != XFA_Element::PageSet)) { | |
| 285 ws = refNode->GetClassName(); | |
| 286 wsName.Format(L"#%s[%d]", ws.c_str(), | |
| 287 GetIndex(refNode, eLogicType, bIsProperty, TRUE)); | |
| 288 return; | |
| 289 } | |
| 290 ws = refNode->GetCData(XFA_ATTRIBUTE_Name); | |
| 291 ws.Replace(L".", L"\\."); | |
| 292 wsName.Format(L"%s[%d]", ws.c_str(), | |
| 293 GetIndex(refNode, eLogicType, bIsProperty, FALSE)); | |
| 294 } | |
| 295 | |
| 296 FX_BOOL CXFA_NodeHelper::NodeIsTransparent(CXFA_Node* refNode) { | |
| 297 if (!refNode) { | |
| 298 return FALSE; | |
| 299 } | |
| 300 XFA_Element refNodeType = refNode->GetElementType(); | |
| 301 if ((refNode->IsUnnamed() && refNode->IsContainerNode()) || | |
| 302 refNodeType == XFA_Element::SubformSet || | |
| 303 refNodeType == XFA_Element::Area || refNodeType == XFA_Element::Proto) { | |
| 304 return TRUE; | |
| 305 } | |
| 306 return FALSE; | |
| 307 } | |
| 308 | |
| 309 FX_BOOL CXFA_NodeHelper::CreateNode_ForCondition(CFX_WideString& wsCondition) { | |
| 310 int32_t iLen = wsCondition.GetLength(); | |
| 311 CFX_WideString wsIndex(L"0"); | |
| 312 FX_BOOL bAll = FALSE; | |
| 313 if (iLen == 0) { | |
| 314 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne; | |
| 315 return FALSE; | |
| 316 } | |
| 317 if (wsCondition.GetAt(0) == '[') { | |
| 318 int32_t i = 1; | |
| 319 for (; i < iLen; ++i) { | |
| 320 FX_WCHAR ch = wsCondition[i]; | |
| 321 if (ch == ' ') { | |
| 322 continue; | |
| 323 } | |
| 324 if (ch == '+' || ch == '-') { | |
| 325 break; | |
| 326 } else if (ch == '*') { | |
| 327 bAll = TRUE; | |
| 328 break; | |
| 329 } else { | |
| 330 break; | |
| 331 } | |
| 332 } | |
| 333 if (bAll) { | |
| 334 wsIndex = FX_WSTRC(L"1"); | |
| 335 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeAll; | |
| 336 } else { | |
| 337 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne; | |
| 338 wsIndex = wsCondition.Mid(i, iLen - 1 - i); | |
| 339 } | |
| 340 int32_t iIndex = wsIndex.GetInteger(); | |
| 341 m_iCreateCount = iIndex; | |
| 342 return TRUE; | |
| 343 } | |
| 344 return FALSE; | |
| 345 } | |
| 346 | |
| 347 FX_BOOL CXFA_NodeHelper::ResolveNodes_CreateNode( | |
| 348 CFX_WideString wsName, | |
| 349 CFX_WideString wsCondition, | |
| 350 FX_BOOL bLastNode, | |
| 351 CXFA_ScriptContext* pScriptContext) { | |
| 352 if (!m_pCreateParent) { | |
| 353 return FALSE; | |
| 354 } | |
| 355 FX_BOOL bIsClassName = FALSE; | |
| 356 FX_BOOL bResult = FALSE; | |
| 357 if (wsName.GetAt(0) == '!') { | |
| 358 wsName = wsName.Right(wsName.GetLength() - 1); | |
| 359 m_pCreateParent = ToNode( | |
| 360 pScriptContext->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets)); | |
| 361 } | |
| 362 if (wsName.GetAt(0) == '#') { | |
| 363 bIsClassName = TRUE; | |
| 364 wsName = wsName.Right(wsName.GetLength() - 1); | |
| 365 } | |
| 366 if (m_iCreateCount == 0) { | |
| 367 CreateNode_ForCondition(wsCondition); | |
| 368 } | |
| 369 if (bIsClassName) { | |
| 370 XFA_Element eType = XFA_GetElementTypeForName(wsName.AsStringC()); | |
| 371 if (eType == XFA_Element::Unknown) | |
| 372 return FALSE; | |
| 373 | |
| 374 for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) { | |
| 375 CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eType); | |
| 376 if (pNewNode) { | |
| 377 m_pCreateParent->InsertChild(pNewNode); | |
| 378 if (iIndex == m_iCreateCount - 1) { | |
| 379 m_pCreateParent = pNewNode; | |
| 380 } | |
| 381 bResult = TRUE; | |
| 382 } | |
| 383 } | |
| 384 } else { | |
| 385 XFA_Element eClassType = XFA_Element::DataGroup; | |
| 386 if (bLastNode) { | |
| 387 eClassType = m_eLastCreateType; | |
| 388 } | |
| 389 for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) { | |
| 390 CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eClassType); | |
| 391 if (pNewNode) { | |
| 392 pNewNode->SetAttribute(XFA_ATTRIBUTE_Name, wsName.AsStringC()); | |
| 393 pNewNode->CreateXMLMappingNode(); | |
| 394 m_pCreateParent->InsertChild(pNewNode); | |
| 395 if (iIndex == m_iCreateCount - 1) { | |
| 396 m_pCreateParent = pNewNode; | |
| 397 } | |
| 398 bResult = TRUE; | |
| 399 } | |
| 400 } | |
| 401 } | |
| 402 if (!bResult) { | |
| 403 m_pCreateParent = nullptr; | |
| 404 } | |
| 405 return bResult; | |
| 406 } | |
| 407 | |
| 408 void CXFA_NodeHelper::SetCreateNodeType(CXFA_Node* refNode) { | |
| 409 if (!refNode) { | |
| 410 return; | |
| 411 } | |
| 412 if (refNode->GetElementType() == XFA_Element::Subform) { | |
| 413 m_eLastCreateType = XFA_Element::DataGroup; | |
| 414 } else if (refNode->GetElementType() == XFA_Element::Field) { | |
| 415 m_eLastCreateType = XFA_FieldIsMultiListBox(refNode) | |
| 416 ? XFA_Element::DataGroup | |
| 417 : XFA_Element::DataValue; | |
| 418 } else if (refNode->GetElementType() == XFA_Element::ExclGroup) { | |
| 419 m_eLastCreateType = XFA_Element::DataValue; | |
| 420 } | |
| 421 } | |
| 422 | |
| 423 FX_BOOL CXFA_NodeHelper::NodeIsProperty(CXFA_Node* refNode) { | |
| 424 CXFA_Node* parent = ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent); | |
| 425 return parent && refNode && | |
| 426 XFA_GetPropertyOfElement(parent->GetElementType(), | |
| 427 refNode->GetElementType(), | |
| 428 XFA_XDPPACKET_UNKNOWN); | |
| 429 } | |
| OLD | NEW |