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/cxfa_nodehelper.h"
8
9 #include <utility>
10
11 #include "core/fxcrt/fx_extension.h"
12 #include "fxjs/xfa/cfxjse_engine.h"
13 #include "fxjs/xfa/cjx_object.h"
14 #include "xfa/fxfa/parser/cxfa_document.h"
15 #include "xfa/fxfa/parser/cxfa_localemgr.h"
16 #include "xfa/fxfa/parser/cxfa_node.h"
17 #include "xfa/fxfa/parser/xfa_basic_data.h"
18 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
19 #include "xfa/fxfa/parser/xfa_utils.h"
20
21 CXFA_NodeHelper::CXFA_NodeHelper() = default;
22
23 CXFA_NodeHelper::~CXFA_NodeHelper() = default;
24
CreateNodeForCondition(const WideString & wsCondition)25 bool CXFA_NodeHelper::CreateNodeForCondition(const WideString& wsCondition) {
26 size_t szLen = wsCondition.GetLength();
27 WideString wsIndex(L"0");
28 bool bAll = false;
29 if (szLen == 0) {
30 m_iCreateFlag = XFA_ResolveNode_RSType_CreateNodeOne;
31 return false;
32 }
33 if (wsCondition[0] != '[')
34 return false;
35
36 size_t i = 1;
37 for (; i < szLen; ++i) {
38 wchar_t ch = wsCondition[i];
39 if (ch == ' ')
40 continue;
41
42 if (ch == '*')
43 bAll = true;
44 break;
45 }
46 if (bAll) {
47 wsIndex = L"1";
48 m_iCreateFlag = XFA_ResolveNode_RSType_CreateNodeAll;
49 } else {
50 m_iCreateFlag = XFA_ResolveNode_RSType_CreateNodeOne;
51 wsIndex = wsCondition.Substr(i, szLen - 1 - i);
52 }
53 int32_t iCount = wsIndex.GetInteger();
54 if (iCount < 0)
55 return false;
56
57 m_iCreateCount = iCount;
58 return true;
59 }
60
CreateNode(const WideString & wsName,const WideString & wsCondition,bool bLastNode,CFXJSE_Engine * pScriptContext)61 bool CXFA_NodeHelper::CreateNode(const WideString& wsName,
62 const WideString& wsCondition,
63 bool bLastNode,
64 CFXJSE_Engine* pScriptContext) {
65 if (!m_pCreateParent)
66 return false;
67
68 WideStringView wsNameView = wsName.AsStringView();
69 bool bIsClassName = false;
70 bool bResult = false;
71 if (!wsNameView.IsEmpty() && wsNameView[0] == '!') {
72 wsNameView = wsNameView.Last(wsNameView.GetLength() - 1);
73 m_pCreateParent = ToNode(
74 pScriptContext->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets));
75 }
76 if (!wsNameView.IsEmpty() && wsNameView[0] == '#') {
77 bIsClassName = true;
78 wsNameView = wsNameView.Last(wsNameView.GetLength() - 1);
79 }
80 if (wsNameView.IsEmpty())
81 return false;
82
83 if (m_iCreateCount == 0)
84 CreateNodeForCondition(wsCondition);
85
86 if (bIsClassName) {
87 XFA_Element eType = XFA_GetElementByName(wsNameView);
88 if (eType == XFA_Element::Unknown)
89 return false;
90
91 for (size_t i = 0; i < m_iCreateCount; ++i) {
92 CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eType);
93 if (pNewNode) {
94 m_pCreateParent->InsertChildAndNotify(pNewNode, nullptr);
95 if (i == m_iCreateCount - 1) {
96 m_pCreateParent = pNewNode;
97 }
98 bResult = true;
99 }
100 }
101 } else {
102 XFA_Element eClassType = XFA_Element::DataGroup;
103 if (bLastNode) {
104 eClassType = m_eLastCreateType;
105 }
106 for (size_t i = 0; i < m_iCreateCount; ++i) {
107 CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eClassType);
108 if (pNewNode) {
109 pNewNode->JSObject()->SetAttribute(XFA_Attribute::Name, wsNameView,
110 false);
111 pNewNode->CreateXMLMappingNode();
112 m_pCreateParent->InsertChildAndNotify(pNewNode, nullptr);
113 if (i == m_iCreateCount - 1) {
114 m_pCreateParent = pNewNode;
115 }
116 bResult = true;
117 }
118 }
119 }
120 if (!bResult)
121 m_pCreateParent = nullptr;
122
123 return bResult;
124 }
125
SetCreateNodeType(CXFA_Node * refNode)126 void CXFA_NodeHelper::SetCreateNodeType(CXFA_Node* refNode) {
127 if (!refNode)
128 return;
129
130 if (refNode->GetElementType() == XFA_Element::Subform) {
131 m_eLastCreateType = XFA_Element::DataGroup;
132 } else if (refNode->GetElementType() == XFA_Element::Field) {
133 m_eLastCreateType = XFA_FieldIsMultiListBox(refNode)
134 ? XFA_Element::DataGroup
135 : XFA_Element::DataValue;
136 } else if (refNode->GetElementType() == XFA_Element::ExclGroup) {
137 m_eLastCreateType = XFA_Element::DataValue;
138 }
139 }
140