1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_nodehelper.h"
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_extension.h"
10*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_engine.h"
11*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_object.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_localemgr.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_node.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_basic_data.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_utils.h"
17*3ac0a46fSAndroid Build Coastguard Worker
18*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_NodeHelper::CFXJSE_NodeHelper() = default;
19*3ac0a46fSAndroid Build Coastguard Worker
20*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_NodeHelper::~CFXJSE_NodeHelper() = default;
21*3ac0a46fSAndroid Build Coastguard Worker
CreateNodeForCondition(const WideString & wsCondition)22*3ac0a46fSAndroid Build Coastguard Worker bool CFXJSE_NodeHelper::CreateNodeForCondition(const WideString& wsCondition) {
23*3ac0a46fSAndroid Build Coastguard Worker size_t szLen = wsCondition.GetLength();
24*3ac0a46fSAndroid Build Coastguard Worker WideString wsIndex(L"0");
25*3ac0a46fSAndroid Build Coastguard Worker bool bAll = false;
26*3ac0a46fSAndroid Build Coastguard Worker if (szLen == 0) {
27*3ac0a46fSAndroid Build Coastguard Worker m_iCreateFlag = CFXJSE_Engine::ResolveResult::Type::kCreateNodeOne;
28*3ac0a46fSAndroid Build Coastguard Worker return false;
29*3ac0a46fSAndroid Build Coastguard Worker }
30*3ac0a46fSAndroid Build Coastguard Worker if (wsCondition[0] != '[')
31*3ac0a46fSAndroid Build Coastguard Worker return false;
32*3ac0a46fSAndroid Build Coastguard Worker
33*3ac0a46fSAndroid Build Coastguard Worker size_t i = 1;
34*3ac0a46fSAndroid Build Coastguard Worker for (; i < szLen; ++i) {
35*3ac0a46fSAndroid Build Coastguard Worker wchar_t ch = wsCondition[i];
36*3ac0a46fSAndroid Build Coastguard Worker if (ch == ' ')
37*3ac0a46fSAndroid Build Coastguard Worker continue;
38*3ac0a46fSAndroid Build Coastguard Worker
39*3ac0a46fSAndroid Build Coastguard Worker if (ch == '*')
40*3ac0a46fSAndroid Build Coastguard Worker bAll = true;
41*3ac0a46fSAndroid Build Coastguard Worker break;
42*3ac0a46fSAndroid Build Coastguard Worker }
43*3ac0a46fSAndroid Build Coastguard Worker if (bAll) {
44*3ac0a46fSAndroid Build Coastguard Worker wsIndex = L"1";
45*3ac0a46fSAndroid Build Coastguard Worker m_iCreateFlag = CFXJSE_Engine::ResolveResult::Type::kCreateNodeAll;
46*3ac0a46fSAndroid Build Coastguard Worker } else {
47*3ac0a46fSAndroid Build Coastguard Worker m_iCreateFlag = CFXJSE_Engine::ResolveResult::Type::kCreateNodeOne;
48*3ac0a46fSAndroid Build Coastguard Worker wsIndex = wsCondition.Substr(i, szLen - 1 - i);
49*3ac0a46fSAndroid Build Coastguard Worker }
50*3ac0a46fSAndroid Build Coastguard Worker int32_t iCount = wsIndex.GetInteger();
51*3ac0a46fSAndroid Build Coastguard Worker if (iCount < 0)
52*3ac0a46fSAndroid Build Coastguard Worker return false;
53*3ac0a46fSAndroid Build Coastguard Worker
54*3ac0a46fSAndroid Build Coastguard Worker m_iCreateCount = iCount;
55*3ac0a46fSAndroid Build Coastguard Worker return true;
56*3ac0a46fSAndroid Build Coastguard Worker }
57*3ac0a46fSAndroid Build Coastguard Worker
CreateNode(const WideString & wsName,const WideString & wsCondition,bool bLastNode,CFXJSE_Engine * pScriptContext)58*3ac0a46fSAndroid Build Coastguard Worker bool CFXJSE_NodeHelper::CreateNode(const WideString& wsName,
59*3ac0a46fSAndroid Build Coastguard Worker const WideString& wsCondition,
60*3ac0a46fSAndroid Build Coastguard Worker bool bLastNode,
61*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine* pScriptContext) {
62*3ac0a46fSAndroid Build Coastguard Worker if (!m_pCreateParent)
63*3ac0a46fSAndroid Build Coastguard Worker return false;
64*3ac0a46fSAndroid Build Coastguard Worker
65*3ac0a46fSAndroid Build Coastguard Worker WideStringView wsNameView = wsName.AsStringView();
66*3ac0a46fSAndroid Build Coastguard Worker bool bIsClassName = false;
67*3ac0a46fSAndroid Build Coastguard Worker bool bResult = false;
68*3ac0a46fSAndroid Build Coastguard Worker if (!wsNameView.IsEmpty() && wsNameView[0] == '!') {
69*3ac0a46fSAndroid Build Coastguard Worker wsNameView = wsNameView.Last(wsNameView.GetLength() - 1);
70*3ac0a46fSAndroid Build Coastguard Worker m_pCreateParent = ToNode(
71*3ac0a46fSAndroid Build Coastguard Worker pScriptContext->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets));
72*3ac0a46fSAndroid Build Coastguard Worker }
73*3ac0a46fSAndroid Build Coastguard Worker if (!wsNameView.IsEmpty() && wsNameView[0] == '#') {
74*3ac0a46fSAndroid Build Coastguard Worker bIsClassName = true;
75*3ac0a46fSAndroid Build Coastguard Worker wsNameView = wsNameView.Last(wsNameView.GetLength() - 1);
76*3ac0a46fSAndroid Build Coastguard Worker }
77*3ac0a46fSAndroid Build Coastguard Worker if (wsNameView.IsEmpty())
78*3ac0a46fSAndroid Build Coastguard Worker return false;
79*3ac0a46fSAndroid Build Coastguard Worker
80*3ac0a46fSAndroid Build Coastguard Worker if (m_iCreateCount == 0)
81*3ac0a46fSAndroid Build Coastguard Worker CreateNodeForCondition(wsCondition);
82*3ac0a46fSAndroid Build Coastguard Worker
83*3ac0a46fSAndroid Build Coastguard Worker if (bIsClassName) {
84*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eType = XFA_GetElementByName(wsNameView);
85*3ac0a46fSAndroid Build Coastguard Worker if (eType == XFA_Element::Unknown)
86*3ac0a46fSAndroid Build Coastguard Worker return false;
87*3ac0a46fSAndroid Build Coastguard Worker
88*3ac0a46fSAndroid Build Coastguard Worker for (size_t i = 0; i < m_iCreateCount; ++i) {
89*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eType);
90*3ac0a46fSAndroid Build Coastguard Worker if (pNewNode) {
91*3ac0a46fSAndroid Build Coastguard Worker m_pCreateParent->InsertChildAndNotify(pNewNode, nullptr);
92*3ac0a46fSAndroid Build Coastguard Worker if (i == m_iCreateCount - 1) {
93*3ac0a46fSAndroid Build Coastguard Worker m_pCreateParent = pNewNode;
94*3ac0a46fSAndroid Build Coastguard Worker }
95*3ac0a46fSAndroid Build Coastguard Worker bResult = true;
96*3ac0a46fSAndroid Build Coastguard Worker }
97*3ac0a46fSAndroid Build Coastguard Worker }
98*3ac0a46fSAndroid Build Coastguard Worker } else {
99*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eClassType = XFA_Element::DataGroup;
100*3ac0a46fSAndroid Build Coastguard Worker if (bLastNode) {
101*3ac0a46fSAndroid Build Coastguard Worker eClassType = m_eLastCreateType;
102*3ac0a46fSAndroid Build Coastguard Worker }
103*3ac0a46fSAndroid Build Coastguard Worker for (size_t i = 0; i < m_iCreateCount; ++i) {
104*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eClassType);
105*3ac0a46fSAndroid Build Coastguard Worker if (pNewNode) {
106*3ac0a46fSAndroid Build Coastguard Worker pNewNode->JSObject()->SetAttributeByEnum(XFA_Attribute::Name,
107*3ac0a46fSAndroid Build Coastguard Worker WideString(wsNameView), false);
108*3ac0a46fSAndroid Build Coastguard Worker pNewNode->CreateXMLMappingNode();
109*3ac0a46fSAndroid Build Coastguard Worker m_pCreateParent->InsertChildAndNotify(pNewNode, nullptr);
110*3ac0a46fSAndroid Build Coastguard Worker if (i == m_iCreateCount - 1) {
111*3ac0a46fSAndroid Build Coastguard Worker m_pCreateParent = pNewNode;
112*3ac0a46fSAndroid Build Coastguard Worker }
113*3ac0a46fSAndroid Build Coastguard Worker bResult = true;
114*3ac0a46fSAndroid Build Coastguard Worker }
115*3ac0a46fSAndroid Build Coastguard Worker }
116*3ac0a46fSAndroid Build Coastguard Worker }
117*3ac0a46fSAndroid Build Coastguard Worker if (!bResult)
118*3ac0a46fSAndroid Build Coastguard Worker m_pCreateParent = nullptr;
119*3ac0a46fSAndroid Build Coastguard Worker
120*3ac0a46fSAndroid Build Coastguard Worker return bResult;
121*3ac0a46fSAndroid Build Coastguard Worker }
122*3ac0a46fSAndroid Build Coastguard Worker
SetCreateNodeType(CXFA_Node * refNode)123*3ac0a46fSAndroid Build Coastguard Worker void CFXJSE_NodeHelper::SetCreateNodeType(CXFA_Node* refNode) {
124*3ac0a46fSAndroid Build Coastguard Worker if (!refNode)
125*3ac0a46fSAndroid Build Coastguard Worker return;
126*3ac0a46fSAndroid Build Coastguard Worker
127*3ac0a46fSAndroid Build Coastguard Worker if (refNode->GetElementType() == XFA_Element::Subform) {
128*3ac0a46fSAndroid Build Coastguard Worker m_eLastCreateType = XFA_Element::DataGroup;
129*3ac0a46fSAndroid Build Coastguard Worker } else if (refNode->GetElementType() == XFA_Element::Field) {
130*3ac0a46fSAndroid Build Coastguard Worker m_eLastCreateType = XFA_FieldIsMultiListBox(refNode)
131*3ac0a46fSAndroid Build Coastguard Worker ? XFA_Element::DataGroup
132*3ac0a46fSAndroid Build Coastguard Worker : XFA_Element::DataValue;
133*3ac0a46fSAndroid Build Coastguard Worker } else if (refNode->GetElementType() == XFA_Element::ExclGroup) {
134*3ac0a46fSAndroid Build Coastguard Worker m_eLastCreateType = XFA_Element::DataValue;
135*3ac0a46fSAndroid Build Coastguard Worker }
136*3ac0a46fSAndroid Build Coastguard Worker }
137