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