blob: a594ffddbef804aaa8597cceb0d83347c49bffce [file] [log] [blame]
kumarashishg826308d2023-06-23 13:21:22 +00001// Copyright 2014 The PDFium Authors
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -07002// 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/xfa_utils.h"
8
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -07009#include <algorithm>
10#include <vector>
11
12#include "core/fxcrt/cfx_memorystream.h"
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070013#include "core/fxcrt/fx_codepage.h"
14#include "core/fxcrt/fx_extension.h"
kumarashishg826308d2023-06-23 13:21:22 +000015#include "core/fxcrt/widetext_buffer.h"
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070016#include "core/fxcrt/xml/cfx_xmlchardata.h"
17#include "core/fxcrt/xml/cfx_xmlelement.h"
18#include "core/fxcrt/xml/cfx_xmlnode.h"
19#include "core/fxcrt/xml/cfx_xmltext.h"
20#include "fxjs/xfa/cjx_object.h"
kumarashishg826308d2023-06-23 13:21:22 +000021#include "third_party/base/check.h"
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070022#include "xfa/fxfa/parser/cxfa_document.h"
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070023#include "xfa/fxfa/parser/cxfa_localemgr.h"
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070024#include "xfa/fxfa/parser/cxfa_measurement.h"
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070025#include "xfa/fxfa/parser/cxfa_node.h"
26#include "xfa/fxfa/parser/cxfa_ui.h"
27#include "xfa/fxfa/parser/cxfa_value.h"
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070028#include "xfa/fxfa/parser/xfa_basic_data.h"
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070029
30namespace {
31
Haibo Huang49cc9302020-04-27 16:14:24 -070032const char kFormNS[] = "http://www.xfa.org/schema/xfa-form/";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070033
34WideString ExportEncodeAttribute(const WideString& str) {
kumarashishg826308d2023-06-23 13:21:22 +000035 WideString textBuf;
36 textBuf.Reserve(str.GetLength()); // Result always at least as big as input.
37 for (size_t i = 0; i < str.GetLength(); i++) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070038 switch (str[i]) {
39 case '&':
kumarashishg826308d2023-06-23 13:21:22 +000040 textBuf += L"&amp;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070041 break;
42 case '<':
kumarashishg826308d2023-06-23 13:21:22 +000043 textBuf += L"&lt;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070044 break;
45 case '>':
kumarashishg826308d2023-06-23 13:21:22 +000046 textBuf += L"&gt;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070047 break;
48 case '\'':
kumarashishg826308d2023-06-23 13:21:22 +000049 textBuf += L"&apos;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070050 break;
51 case '\"':
kumarashishg826308d2023-06-23 13:21:22 +000052 textBuf += L"&quot;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070053 break;
54 default:
kumarashishg826308d2023-06-23 13:21:22 +000055 textBuf += str[i];
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070056 }
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -070057 }
kumarashishg826308d2023-06-23 13:21:22 +000058 return textBuf;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070059}
60
61bool IsXMLValidChar(wchar_t ch) {
62 return ch == 0x09 || ch == 0x0A || ch == 0x0D ||
63 (ch >= 0x20 && ch <= 0xD7FF) || (ch >= 0xE000 && ch <= 0xFFFD);
64}
65
66WideString ExportEncodeContent(const WideString& str) {
kumarashishg826308d2023-06-23 13:21:22 +000067 WideTextBuffer textBuf;
68 size_t iLen = str.GetLength();
69 for (size_t i = 0; i < iLen; i++) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070070 wchar_t ch = str[i];
71 if (!IsXMLValidChar(ch))
72 continue;
73
74 if (ch == '&') {
Haibo Huang49cc9302020-04-27 16:14:24 -070075 textBuf << "&amp;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070076 } else if (ch == '<') {
Haibo Huang49cc9302020-04-27 16:14:24 -070077 textBuf << "&lt;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070078 } else if (ch == '>') {
Haibo Huang49cc9302020-04-27 16:14:24 -070079 textBuf << "&gt;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070080 } else if (ch == '\'') {
Haibo Huang49cc9302020-04-27 16:14:24 -070081 textBuf << "&apos;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070082 } else if (ch == '\"') {
Haibo Huang49cc9302020-04-27 16:14:24 -070083 textBuf << "&quot;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070084 } else if (ch == ' ') {
85 if (i && str[i - 1] != ' ') {
86 textBuf.AppendChar(' ');
87 } else {
Haibo Huang49cc9302020-04-27 16:14:24 -070088 textBuf << "&#x20;";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070089 }
90 } else {
91 textBuf.AppendChar(str[i]);
92 }
93 }
94 return textBuf.MakeString();
95}
96
97bool AttributeSaveInDataModel(CXFA_Node* pNode, XFA_Attribute eAttribute) {
98 bool bSaveInDataModel = false;
99 if (pNode->GetElementType() != XFA_Element::Image)
100 return bSaveInDataModel;
101
102 CXFA_Node* pValueNode = pNode->GetParent();
103 if (!pValueNode || pValueNode->GetElementType() != XFA_Element::Value)
104 return bSaveInDataModel;
105
106 CXFA_Node* pFieldNode = pValueNode->GetParent();
107 if (pFieldNode && pFieldNode->GetBindData() &&
108 eAttribute == XFA_Attribute::Href) {
109 bSaveInDataModel = true;
110 }
111 return bSaveInDataModel;
112}
113
114bool ContentNodeNeedtoExport(CXFA_Node* pContentNode) {
kumarashishg826308d2023-06-23 13:21:22 +0000115 absl::optional<WideString> wsContent =
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700116 pContentNode->JSObject()->TryContent(false, false);
kumarashishg826308d2023-06-23 13:21:22 +0000117 if (!wsContent.has_value())
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700118 return false;
119
kumarashishg826308d2023-06-23 13:21:22 +0000120 DCHECK(pContentNode->IsContentNode());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700121 CXFA_Node* pParentNode = pContentNode->GetParent();
122 if (!pParentNode || pParentNode->GetElementType() != XFA_Element::Value)
123 return true;
124
125 CXFA_Node* pGrandParentNode = pParentNode->GetParent();
126 if (!pGrandParentNode || !pGrandParentNode->IsContainerNode())
127 return true;
Haibo Huang49cc9302020-04-27 16:14:24 -0700128 if (!pGrandParentNode->GetBindData())
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700129 return false;
Haibo Huang49cc9302020-04-27 16:14:24 -0700130 if (pGrandParentNode->GetFFWidgetType() == XFA_FFWidgetType::kPasswordEdit)
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700131 return false;
132 return true;
133}
134
kumarashishg826308d2023-06-23 13:21:22 +0000135WideString SaveAttribute(CXFA_Node* pNode,
136 XFA_Attribute eName,
137 WideStringView wsName,
138 bool bProto) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700139 if (!bProto && !pNode->JSObject()->HasAttribute(eName))
kumarashishg826308d2023-06-23 13:21:22 +0000140 return WideString();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700141
kumarashishg826308d2023-06-23 13:21:22 +0000142 absl::optional<WideString> value =
143 pNode->JSObject()->TryAttribute(eName, false);
144 if (!value.has_value())
145 return WideString();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700146
kumarashishg826308d2023-06-23 13:21:22 +0000147 WideString wsEncoded = ExportEncodeAttribute(value.value());
148 return WideString{L" ", wsName, L"=\"", wsEncoded.AsStringView(), L"\""};
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700149}
150
151void RegenerateFormFile_Changed(CXFA_Node* pNode,
kumarashishg826308d2023-06-23 13:21:22 +0000152 WideTextBuffer& buf,
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700153 bool bSaveXML) {
154 WideString wsAttrs;
155 for (size_t i = 0;; ++i) {
156 XFA_Attribute attr = pNode->GetAttribute(i);
157 if (attr == XFA_Attribute::Unknown)
158 break;
159
160 if (attr == XFA_Attribute::Name ||
161 (AttributeSaveInDataModel(pNode, attr) && !bSaveXML)) {
162 continue;
163 }
kumarashishg826308d2023-06-23 13:21:22 +0000164 WideString wsAttr = WideString::FromASCII(XFA_AttributeToName(attr));
165 wsAttrs += SaveAttribute(pNode, attr, wsAttr.AsStringView(), bSaveXML);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700166 }
167
168 WideString wsChildren;
169 switch (pNode->GetObjectType()) {
170 case XFA_ObjectType::ContentNode: {
171 if (!bSaveXML && !ContentNodeNeedtoExport(pNode))
172 break;
173
174 CXFA_Node* pRawValueNode = pNode->GetFirstChild();
175 while (pRawValueNode &&
176 pRawValueNode->GetElementType() != XFA_Element::SharpxHTML &&
177 pRawValueNode->GetElementType() != XFA_Element::Sharptext &&
178 pRawValueNode->GetElementType() != XFA_Element::Sharpxml) {
179 pRawValueNode = pRawValueNode->GetNextSibling();
180 }
181 if (!pRawValueNode)
182 break;
183
kumarashishg826308d2023-06-23 13:21:22 +0000184 absl::optional<WideString> contentType =
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700185 pNode->JSObject()->TryAttribute(XFA_Attribute::ContentType, false);
186 if (pRawValueNode->GetElementType() == XFA_Element::SharpxHTML &&
Haibo Huang49cc9302020-04-27 16:14:24 -0700187 contentType.has_value() &&
188 contentType.value().EqualsASCII("text/html")) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700189 CFX_XMLNode* pExDataXML = pNode->GetXMLMappingNode();
190 if (!pExDataXML)
191 break;
192
Haibo Huang49cc9302020-04-27 16:14:24 -0700193 CFX_XMLNode* pRichTextXML = pExDataXML->GetFirstChild();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700194 if (!pRichTextXML)
195 break;
196
Haibo Huang49cc9302020-04-27 16:14:24 -0700197 auto pMemStream = pdfium::MakeRetain<CFX_MemoryStream>();
198 pRichTextXML->Save(pMemStream);
kumarashishg826308d2023-06-23 13:21:22 +0000199 wsChildren +=
200 WideString::FromUTF8(ByteStringView(pMemStream->GetSpan()));
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700201 } else if (pRawValueNode->GetElementType() == XFA_Element::Sharpxml &&
Haibo Huang49cc9302020-04-27 16:14:24 -0700202 contentType.has_value() &&
203 contentType.value().EqualsASCII("text/xml")) {
kumarashishg826308d2023-06-23 13:21:22 +0000204 absl::optional<WideString> rawValue =
205 pRawValueNode->JSObject()->TryAttribute(XFA_Attribute::Value,
206 false);
207 if (!rawValue.has_value() || rawValue->IsEmpty())
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700208 break;
209
Haibo Huang49cc9302020-04-27 16:14:24 -0700210 std::vector<WideString> wsSelTextArray =
211 fxcrt::Split(rawValue.value(), L'\n');
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700212
213 CXFA_Node* pParentNode = pNode->GetParent();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700214 CXFA_Node* pGrandparentNode = pParentNode->GetParent();
Haibo Huang49cc9302020-04-27 16:14:24 -0700215 WideString bodyTagName =
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700216 pGrandparentNode->JSObject()->GetCData(XFA_Attribute::Name);
217 if (bodyTagName.IsEmpty())
218 bodyTagName = L"ListBox1";
219
kumarashishg826308d2023-06-23 13:21:22 +0000220 buf << "<" << bodyTagName << " xmlns=\"\">\n";
221 for (const WideString& text : wsSelTextArray)
222 buf << "<value>" << ExportEncodeContent(text) << "</value>\n";
223 buf << "</" << bodyTagName << ">\n";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700224 wsChildren += buf.AsStringView();
225 buf.Clear();
226 } else {
227 WideString wsValue =
228 pRawValueNode->JSObject()->GetCData(XFA_Attribute::Value);
229 wsChildren += ExportEncodeContent(wsValue);
230 }
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700231 break;
232 }
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700233 case XFA_ObjectType::TextNode:
234 case XFA_ObjectType::NodeC:
235 case XFA_ObjectType::NodeV: {
236 WideString wsValue = pNode->JSObject()->GetCData(XFA_Attribute::Value);
237 wsChildren += ExportEncodeContent(wsValue);
238 break;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700239 }
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700240 default:
241 if (pNode->GetElementType() == XFA_Element::Items) {
242 CXFA_Node* pTemplateNode = pNode->GetTemplateNodeIfExists();
243 if (!pTemplateNode ||
244 pTemplateNode->CountChildren(XFA_Element::Unknown, false) !=
245 pNode->CountChildren(XFA_Element::Unknown, false)) {
246 bSaveXML = true;
247 }
248 }
kumarashishg826308d2023-06-23 13:21:22 +0000249 WideTextBuffer newBuf;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700250 CXFA_Node* pChildNode = pNode->GetFirstChild();
251 while (pChildNode) {
252 RegenerateFormFile_Changed(pChildNode, newBuf, bSaveXML);
253 wsChildren += newBuf.AsStringView();
254 newBuf.Clear();
255 pChildNode = pChildNode->GetNextSibling();
256 }
257 if (!bSaveXML && !wsChildren.IsEmpty() &&
258 pNode->GetElementType() == XFA_Element::Items) {
259 wsChildren.clear();
260 bSaveXML = true;
261 CXFA_Node* pChild = pNode->GetFirstChild();
262 while (pChild) {
263 RegenerateFormFile_Changed(pChild, newBuf, bSaveXML);
264 wsChildren += newBuf.AsStringView();
265 newBuf.Clear();
266 pChild = pChild->GetNextSibling();
267 }
268 }
269 break;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700270 }
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700271
272 if (!wsChildren.IsEmpty() || !wsAttrs.IsEmpty() ||
273 pNode->JSObject()->HasAttribute(XFA_Attribute::Name)) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700274 WideString wsElement = WideString::FromASCII(pNode->GetClassName());
Haibo Huang49cc9302020-04-27 16:14:24 -0700275 buf << "<";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700276 buf << wsElement;
kumarashishg826308d2023-06-23 13:21:22 +0000277 buf << SaveAttribute(pNode, XFA_Attribute::Name, L"name", true);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700278 buf << wsAttrs;
279 if (wsChildren.IsEmpty()) {
kumarashishg826308d2023-06-23 13:21:22 +0000280 buf << "/>\n";
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700281 } else {
kumarashishg826308d2023-06-23 13:21:22 +0000282 buf << ">\n" << wsChildren << "</" << wsElement << ">\n";
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700283 }
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700284 }
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700285}
286
Haibo Huang49cc9302020-04-27 16:14:24 -0700287void RegenerateFormFile_Container(CXFA_Node* pNode,
288 const RetainPtr<IFX_SeekableStream>& pStream,
289 bool bSaveXML) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700290 XFA_Element eType = pNode->GetElementType();
291 if (eType == XFA_Element::Field || eType == XFA_Element::Draw ||
292 !pNode->IsContainerNode()) {
kumarashishg826308d2023-06-23 13:21:22 +0000293 WideTextBuffer buf;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700294 RegenerateFormFile_Changed(pNode, buf, bSaveXML);
295 size_t nLen = buf.GetLength();
296 if (nLen > 0)
Haibo Huang49cc9302020-04-27 16:14:24 -0700297 pStream->WriteString(buf.MakeString().ToUTF8().AsStringView());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700298 return;
299 }
300
Haibo Huang49cc9302020-04-27 16:14:24 -0700301 WideString wsElement = WideString::FromASCII(pNode->GetClassName());
302 pStream->WriteString("<");
303 pStream->WriteString(wsElement.ToUTF8().AsStringView());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700304
kumarashishg826308d2023-06-23 13:21:22 +0000305 WideString wsOutput =
306 SaveAttribute(pNode, XFA_Attribute::Name, L"name", true);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700307 for (size_t i = 0;; ++i) {
308 XFA_Attribute attr = pNode->GetAttribute(i);
309 if (attr == XFA_Attribute::Unknown)
310 break;
311 if (attr == XFA_Attribute::Name)
312 continue;
313
kumarashishg826308d2023-06-23 13:21:22 +0000314 WideString wsAttr = WideString::FromASCII(XFA_AttributeToName(attr));
315 wsOutput += SaveAttribute(pNode, attr, wsAttr.AsStringView(), false);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700316 }
317
318 if (!wsOutput.IsEmpty())
Haibo Huang49cc9302020-04-27 16:14:24 -0700319 pStream->WriteString(wsOutput.ToUTF8().AsStringView());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700320
321 CXFA_Node* pChildNode = pNode->GetFirstChild();
Haibo Huang49cc9302020-04-27 16:14:24 -0700322 if (!pChildNode) {
323 pStream->WriteString(" />\n");
324 return;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700325 }
Haibo Huang49cc9302020-04-27 16:14:24 -0700326
327 pStream->WriteString(">\n");
328 while (pChildNode) {
329 RegenerateFormFile_Container(pChildNode, pStream, bSaveXML);
330 pChildNode = pChildNode->GetNextSibling();
331 }
332 pStream->WriteString("</");
333 pStream->WriteString(wsElement.ToUTF8().AsStringView());
334 pStream->WriteString(">\n");
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700335}
336
337WideString RecognizeXFAVersionNumber(CXFA_Node* pTemplateRoot) {
338 if (!pTemplateRoot)
339 return WideString();
340
kumarashishg826308d2023-06-23 13:21:22 +0000341 absl::optional<WideString> templateNS =
342 pTemplateRoot->JSObject()->TryNamespace();
343 if (!templateNS.has_value())
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700344 return WideString();
345
346 XFA_VERSION eVersion =
kumarashishg826308d2023-06-23 13:21:22 +0000347 pTemplateRoot->GetDocument()->RecognizeXFAVersionNumber(
348 templateNS.value());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700349 if (eVersion == XFA_VERSION_UNKNOWN)
350 eVersion = XFA_VERSION_DEFAULT;
351
352 return WideString::Format(L"%i.%i", eVersion / 100, eVersion % 100);
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700353}
354
355} // namespace
356
kumarashishg826308d2023-06-23 13:21:22 +0000357CXFA_LocaleValue XFA_GetLocaleValue(const CXFA_Node* pNode) {
358 const auto* pNodeValue =
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700359 pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
360 if (!pNodeValue)
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700361 return CXFA_LocaleValue();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700362
363 CXFA_Node* pValueChild = pNodeValue->GetFirstChild();
364 if (!pValueChild)
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700365 return CXFA_LocaleValue();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700366
kumarashishg826308d2023-06-23 13:21:22 +0000367 return CXFA_LocaleValue(XFA_GetLocaleValueType(pValueChild->GetElementType()),
368 pNode->GetRawValue(),
Haibo Huang49cc9302020-04-27 16:14:24 -0700369 pNode->GetDocument()->GetLocaleMgr());
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700370}
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700371
kumarashishg826308d2023-06-23 13:21:22 +0000372CXFA_LocaleValue::ValueType XFA_GetLocaleValueType(XFA_Element element) {
373 switch (element) {
374 case XFA_Element::Decimal:
375 return CXFA_LocaleValue::ValueType::kDecimal;
376 case XFA_Element::Float:
377 return CXFA_LocaleValue::ValueType::kFloat;
378 case XFA_Element::Date:
379 return CXFA_LocaleValue::ValueType::kDate;
380 case XFA_Element::Time:
381 return CXFA_LocaleValue::ValueType::kTime;
382 case XFA_Element::DateTime:
383 return CXFA_LocaleValue::ValueType::kDateTime;
384 case XFA_Element::Boolean:
385 return CXFA_LocaleValue::ValueType::kBoolean;
386 case XFA_Element::Integer:
387 return CXFA_LocaleValue::ValueType::kInteger;
388 case XFA_Element::Text:
389 return CXFA_LocaleValue::ValueType::kText;
390 default:
391 return CXFA_LocaleValue::ValueType::kNull;
392 }
393}
394
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700395bool XFA_FDEExtension_ResolveNamespaceQualifier(CFX_XMLElement* pNode,
396 const WideString& wsQualifier,
397 WideString* wsNamespaceURI) {
398 if (!pNode)
399 return false;
400
Haibo Huang49cc9302020-04-27 16:14:24 -0700401 CFX_XMLNode* pFakeRoot = pNode->GetRoot();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700402 WideString wsNSAttribute;
403 bool bRet = false;
404 if (wsQualifier.IsEmpty()) {
405 wsNSAttribute = L"xmlns";
406 bRet = true;
407 } else {
408 wsNSAttribute = L"xmlns:" + wsQualifier;
409 }
410 for (CFX_XMLNode* pParent = pNode; pParent != pFakeRoot;
Haibo Huang49cc9302020-04-27 16:14:24 -0700411 pParent = pParent->GetParent()) {
412 CFX_XMLElement* pElement = ToXMLElement(pParent);
413 if (pElement && pElement->HasAttribute(wsNSAttribute)) {
414 *wsNamespaceURI = pElement->GetAttribute(wsNSAttribute);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700415 return true;
416 }
417 }
418 wsNamespaceURI->clear();
419 return bRet;
420}
421
422void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode) {
423 if (!pDataNode || pDataNode->GetElementType() == XFA_Element::DataValue)
424 return;
425
426 int32_t iChildNum = 0;
427 for (CXFA_Node* pChildNode = pDataNode->GetFirstChild(); pChildNode;
428 pChildNode = pChildNode->GetNextSibling()) {
429 iChildNum++;
430 XFA_DataExporter_DealWithDataGroupNode(pChildNode);
431 }
432
433 if (pDataNode->GetElementType() != XFA_Element::DataGroup)
434 return;
435
Haibo Huang49cc9302020-04-27 16:14:24 -0700436 CFX_XMLElement* pElement = ToXMLElement(pDataNode->GetXMLMappingNode());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700437 if (iChildNum > 0) {
kumarashishg826308d2023-06-23 13:21:22 +0000438 pElement->RemoveAttribute(L"xfa:dataNode");
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700439 return;
440 }
Haibo Huang49cc9302020-04-27 16:14:24 -0700441 pElement->SetAttribute(L"xfa:dataNode", L"dataGroup");
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700442}
443
444void XFA_DataExporter_RegenerateFormFile(
445 CXFA_Node* pNode,
Haibo Huang49cc9302020-04-27 16:14:24 -0700446 const RetainPtr<IFX_SeekableStream>& pStream,
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700447 bool bSaveXML) {
448 if (pNode->IsModelNode()) {
Haibo Huang49cc9302020-04-27 16:14:24 -0700449 pStream->WriteString("<form xmlns=\"");
450 pStream->WriteString(kFormNS);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700451
452 WideString wsVersionNumber = RecognizeXFAVersionNumber(
453 ToNode(pNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Template)));
454 if (wsVersionNumber.IsEmpty())
455 wsVersionNumber = L"2.8";
456
kumarashishg826308d2023-06-23 13:21:22 +0000457 wsVersionNumber += L"/\">\n";
Haibo Huang49cc9302020-04-27 16:14:24 -0700458 pStream->WriteString(wsVersionNumber.ToUTF8().AsStringView());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700459
460 CXFA_Node* pChildNode = pNode->GetFirstChild();
461 while (pChildNode) {
462 RegenerateFormFile_Container(pChildNode, pStream, false);
463 pChildNode = pChildNode->GetNextSibling();
464 }
kumarashishg826308d2023-06-23 13:21:22 +0000465 pStream->WriteString("</form>\n");
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700466 } else {
467 RegenerateFormFile_Container(pNode, pStream, bSaveXML);
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700468 }
469}
470
kumarashishg826308d2023-06-23 13:21:22 +0000471bool XFA_FieldIsMultiListBox(const CXFA_Node* pFieldNode) {
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700472 if (!pFieldNode)
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700473 return false;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700474
kumarashishg826308d2023-06-23 13:21:22 +0000475 const auto* pUIChild =
476 pFieldNode->GetChild<CXFA_Ui>(0, XFA_Element::Ui, false);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700477 if (!pUIChild)
478 return false;
479
480 CXFA_Node* pFirstChild = pUIChild->GetFirstChild();
481 if (!pFirstChild ||
482 pFirstChild->GetElementType() != XFA_Element::ChoiceList) {
483 return false;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700484 }
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700485
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700486 return pFirstChild->JSObject()->GetEnum(XFA_Attribute::Open) ==
Haibo Huang49cc9302020-04-27 16:14:24 -0700487 XFA_AttributeValue::MultiSelect;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700488}
489
490int32_t XFA_MapRotation(int32_t nRotation) {
491 nRotation = nRotation % 360;
492 nRotation = nRotation < 0 ? nRotation + 360 : nRotation;
493 return nRotation;
494}
495
Haibo Huang49cc9302020-04-27 16:14:24 -0700496void XFA_EventErrorAccumulate(XFA_EventError* pAcc, XFA_EventError eNew) {
497 if (*pAcc == XFA_EventError::kNotExist || eNew == XFA_EventError::kError)
498 *pAcc = eNew;
Philip P. Moltmann4d3acf42017-03-20 11:05:52 -0700499}