xref: /aosp_15_r20/external/pdfium/fxjs/xfa/cfxjse_nodehelper.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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