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"
CXFA_NodeHelper(void)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) {}
~CXFA_NodeHelper(void)26 CXFA_NodeHelper::~CXFA_NodeHelper(void) {}
XFA_ResolveNodes_GetOneChild(CXFA_Node * parent,const FX_WCHAR * pwsName,FX_BOOL bIsClassName)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 }
XFA_CountSiblings(CXFA_Node * pNode,XFA_LOGIC_TYPE eLogicType,CXFA_NodeArray * pSiblings,FX_BOOL bIsClassName)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 }
XFA_NodeAcc_TraverseAnySiblings(CXFA_Node * parent,FX_DWORD dNameHash,CXFA_NodeArray * pSiblings,FX_BOOL bIsClassName)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 }
XFA_NodeAcc_TraverseSiblings(CXFA_Node * parent,FX_DWORD dNameHash,CXFA_NodeArray * pSiblings,XFA_LOGIC_TYPE eLogicType,FX_BOOL bIsClassName,FX_BOOL bIsFindProperty)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 }
XFA_ResolveNodes_GetParent(CXFA_Node * pNode,XFA_LOGIC_TYPE eLogicType)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 }
XFA_GetIndex(CXFA_Node * pNode,XFA_LOGIC_TYPE eLogicType,FX_BOOL bIsProperty,FX_BOOL bIsClassIndex)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 }
XFA_GetNameExpression(CXFA_Node * refNode,CFX_WideString & wsName,FX_BOOL bIsAllPath,XFA_LOGIC_TYPE eLogicType)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 }
XFA_NodeIsTransparent(CXFA_Node * refNode)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 }
XFA_CreateNode_ForCondition(CFX_WideString & wsCondition)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 }
XFA_ResolveNodes_CreateNode(CFX_WideString wsName,CFX_WideString wsCondition,FX_BOOL bLastNode,CXFA_ScriptContext * pScriptContext)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 }
XFA_SetCreateNodeType(CXFA_Node * refNode)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 }
XFA_NodeIsProperty(CXFA_Node * refNode)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