1 // Copyright 2017 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 "fxjs/xfa/cjx_object.h"
8
9 #include <tuple>
10
11 #include "core/fxcrt/cfx_decimal.h"
12 #include "core/fxcrt/fx_extension.h"
13 #include "core/fxcrt/xml/cfx_xmltext.h"
14 #include "fxjs/cfxjse_engine.h"
15 #include "fxjs/cfxjse_value.h"
16 #include "fxjs/cjs_return.h"
17 #include "fxjs/xfa/cjx_boolean.h"
18 #include "fxjs/xfa/cjx_draw.h"
19 #include "fxjs/xfa/cjx_field.h"
20 #include "fxjs/xfa/cjx_instancemanager.h"
21 #include "third_party/base/ptr_util.h"
22 #include "xfa/fxfa/cxfa_ffnotify.h"
23 #include "xfa/fxfa/cxfa_ffwidget.h"
24 #include "xfa/fxfa/cxfa_widgetacc.h"
25 #include "xfa/fxfa/parser/cxfa_border.h"
26 #include "xfa/fxfa/parser/cxfa_datavalue.h"
27 #include "xfa/fxfa/parser/cxfa_document.h"
28 #include "xfa/fxfa/parser/cxfa_edge.h"
29 #include "xfa/fxfa/parser/cxfa_fill.h"
30 #include "xfa/fxfa/parser/cxfa_font.h"
31 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
32 #include "xfa/fxfa/parser/cxfa_measurement.h"
33 #include "xfa/fxfa/parser/cxfa_node.h"
34 #include "xfa/fxfa/parser/cxfa_object.h"
35 #include "xfa/fxfa/parser/cxfa_occur.h"
36 #include "xfa/fxfa/parser/cxfa_proto.h"
37 #include "xfa/fxfa/parser/cxfa_subform.h"
38 #include "xfa/fxfa/parser/cxfa_validate.h"
39 #include "xfa/fxfa/parser/cxfa_value.h"
40 #include "xfa/fxfa/parser/xfa_utils.h"
41
42 namespace {
43
XFA_DeleteWideString(void * pData)44 void XFA_DeleteWideString(void* pData) {
45 delete static_cast<WideString*>(pData);
46 }
47
XFA_CopyWideString(void * & pData)48 void XFA_CopyWideString(void*& pData) {
49 if (!pData)
50 return;
51 pData = new WideString(*reinterpret_cast<WideString*>(pData));
52 }
53
54 XFA_MAPDATABLOCKCALLBACKINFO deleteWideStringCallBack = {XFA_DeleteWideString,
55 XFA_CopyWideString};
56
57 enum XFA_KEYTYPE {
58 XFA_KEYTYPE_Custom,
59 XFA_KEYTYPE_Element,
60 };
61
GetMapKey_Custom(const WideStringView & wsKey)62 void* GetMapKey_Custom(const WideStringView& wsKey) {
63 uint32_t dwKey = FX_HashCode_GetW(wsKey, false);
64 return (void*)(uintptr_t)((dwKey << 1) | XFA_KEYTYPE_Custom);
65 }
66
GetMapKey_Element(XFA_Element eType,XFA_Attribute eAttribute)67 void* GetMapKey_Element(XFA_Element eType, XFA_Attribute eAttribute) {
68 return (void*)(uintptr_t)((static_cast<uint32_t>(eType) << 16) |
69 (static_cast<uint32_t>(eAttribute) << 8) |
70 XFA_KEYTYPE_Element);
71 }
72
XFA_DefaultFreeData(void * pData)73 void XFA_DefaultFreeData(void* pData) {}
74
75 XFA_MAPDATABLOCKCALLBACKINFO gs_XFADefaultFreeData = {XFA_DefaultFreeData,
76 nullptr};
77
StrToRGB(const WideString & strRGB)78 std::tuple<int32_t, int32_t, int32_t> StrToRGB(const WideString& strRGB) {
79 int32_t r = 0;
80 int32_t g = 0;
81 int32_t b = 0;
82
83 size_t iIndex = 0;
84 for (size_t i = 0; i < strRGB.GetLength(); ++i) {
85 wchar_t ch = strRGB[i];
86 if (ch == L',')
87 ++iIndex;
88 if (iIndex > 2)
89 break;
90
91 int32_t iValue = ch - L'0';
92 if (iValue >= 0 && iValue <= 9) {
93 switch (iIndex) {
94 case 0:
95 r = r * 10 + iValue;
96 break;
97 case 1:
98 g = g * 10 + iValue;
99 break;
100 default:
101 b = b * 10 + iValue;
102 break;
103 }
104 }
105 }
106 return {r, g, b};
107 }
108
109 } // namespace
110
111 struct XFA_MAPDATABLOCK {
GetDataXFA_MAPDATABLOCK112 uint8_t* GetData() const { return (uint8_t*)this + sizeof(XFA_MAPDATABLOCK); }
113
114 XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo;
115 int32_t iBytes;
116 };
117
118 struct XFA_MAPMODULEDATA {
XFA_MAPMODULEDATAXFA_MAPMODULEDATA119 XFA_MAPMODULEDATA() {}
~XFA_MAPMODULEDATAXFA_MAPMODULEDATA120 ~XFA_MAPMODULEDATA() {}
121
122 std::map<void*, void*> m_ValueMap;
123 std::map<void*, XFA_MAPDATABLOCK*> m_BufferMap;
124 };
125
CJX_Object(CXFA_Object * obj)126 CJX_Object::CJX_Object(CXFA_Object* obj) : object_(obj) {}
127
~CJX_Object()128 CJX_Object::~CJX_Object() {
129 ClearMapModuleBuffer();
130 }
131
DefineMethods(const CJX_MethodSpec method_specs[],size_t count)132 void CJX_Object::DefineMethods(const CJX_MethodSpec method_specs[],
133 size_t count) {
134 for (size_t i = 0; i < count; ++i)
135 method_specs_[method_specs[i].pName] = method_specs[i].pMethodCall;
136 }
137
GetDocument() const138 CXFA_Document* CJX_Object::GetDocument() const {
139 return object_->GetDocument();
140 }
141
className(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)142 void CJX_Object::className(CFXJSE_Value* pValue,
143 bool bSetting,
144 XFA_Attribute eAttribute) {
145 if (bSetting) {
146 ThrowInvalidPropertyException();
147 return;
148 }
149 pValue->SetString(
150 FX_UTF8Encode(GetXFAObject()->GetClassName()).AsStringView());
151 }
152
Subform_and_SubformSet_InstanceIndex()153 int32_t CJX_Object::Subform_and_SubformSet_InstanceIndex() {
154 int32_t index = 0;
155 for (CXFA_Node* pNode = ToNode(GetXFAObject())->GetPrevSibling(); pNode;
156 pNode = pNode->GetPrevSibling()) {
157 if ((pNode->GetElementType() != XFA_Element::Subform) &&
158 (pNode->GetElementType() != XFA_Element::SubformSet)) {
159 break;
160 }
161 index++;
162 }
163 return index;
164 }
165
HasMethod(const WideString & func) const166 bool CJX_Object::HasMethod(const WideString& func) const {
167 return pdfium::ContainsKey(method_specs_, func.UTF8Encode());
168 }
169
RunMethod(const WideString & func,const std::vector<v8::Local<v8::Value>> & params)170 CJS_Return CJX_Object::RunMethod(
171 const WideString& func,
172 const std::vector<v8::Local<v8::Value>>& params) {
173 auto it = method_specs_.find(func.UTF8Encode());
174 if (it == method_specs_.end())
175 return CJS_Return(false);
176 return it->second(this, GetXFAObject()->GetDocument()->GetScriptContext(),
177 params);
178 }
179
ThrowTooManyOccurancesException(const WideString & obj) const180 void CJX_Object::ThrowTooManyOccurancesException(const WideString& obj) const {
181 ThrowException(
182 L"The element [%ls] has violated its allowable number of occurrences.",
183 obj.c_str());
184 }
185
ThrowInvalidPropertyException() const186 void CJX_Object::ThrowInvalidPropertyException() const {
187 ThrowException(L"Invalid property set operation.");
188 }
189
ThrowIndexOutOfBoundsException() const190 void CJX_Object::ThrowIndexOutOfBoundsException() const {
191 ThrowException(L"Index value is out of bounds.");
192 }
193
ThrowParamCountMismatchException(const WideString & method) const194 void CJX_Object::ThrowParamCountMismatchException(
195 const WideString& method) const {
196 ThrowException(L"Incorrect number of parameters calling method '%.16s'.",
197 method.c_str());
198 }
199
ThrowArgumentMismatchException() const200 void CJX_Object::ThrowArgumentMismatchException() const {
201 ThrowException(L"Argument mismatch in property or function argument.");
202 }
203
ThrowException(const wchar_t * str,...) const204 void CJX_Object::ThrowException(const wchar_t* str, ...) const {
205 va_list arg_ptr;
206 va_start(arg_ptr, str);
207 WideString wsMessage = WideString::FormatV(str, arg_ptr);
208 va_end(arg_ptr);
209
210 ASSERT(!wsMessage.IsEmpty());
211 FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView());
212 }
213
HasAttribute(XFA_Attribute eAttr)214 bool CJX_Object::HasAttribute(XFA_Attribute eAttr) {
215 void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
216 return HasMapModuleKey(pKey);
217 }
218
SetAttribute(XFA_Attribute eAttr,const WideStringView & wsValue,bool bNotify)219 bool CJX_Object::SetAttribute(XFA_Attribute eAttr,
220 const WideStringView& wsValue,
221 bool bNotify) {
222 switch (ToNode(GetXFAObject())->GetAttributeType(eAttr)) {
223 case XFA_AttributeType::Enum: {
224 Optional<XFA_AttributeEnum> item =
225 CXFA_Node::NameToAttributeEnum(wsValue);
226 return SetEnum(
227 eAttr,
228 item ? *item : *(ToNode(GetXFAObject())->GetDefaultEnum(eAttr)),
229 bNotify);
230 }
231 case XFA_AttributeType::CData:
232 return SetCData(eAttr, WideString(wsValue), bNotify, false);
233 case XFA_AttributeType::Boolean:
234 return SetBoolean(eAttr, wsValue != L"0", bNotify);
235 case XFA_AttributeType::Integer:
236 return SetInteger(eAttr,
237 FXSYS_round(FXSYS_wcstof(wsValue.unterminated_c_str(),
238 wsValue.GetLength(), nullptr)),
239 bNotify);
240 case XFA_AttributeType::Measure:
241 return SetMeasure(eAttr, CXFA_Measurement(wsValue), bNotify);
242 default:
243 break;
244 }
245 return false;
246 }
247
SetMapModuleString(void * pKey,const WideStringView & wsValue)248 void CJX_Object::SetMapModuleString(void* pKey, const WideStringView& wsValue) {
249 SetMapModuleBuffer(pKey, (void*)wsValue.unterminated_c_str(),
250 wsValue.GetLength() * sizeof(wchar_t), nullptr);
251 }
252
SetAttribute(const WideStringView & wsAttr,const WideStringView & wsValue,bool bNotify)253 bool CJX_Object::SetAttribute(const WideStringView& wsAttr,
254 const WideStringView& wsValue,
255 bool bNotify) {
256 XFA_Attribute attr = CXFA_Node::NameToAttribute(wsValue);
257 if (attr != XFA_Attribute::Unknown)
258 return SetAttribute(attr, wsValue, bNotify);
259
260 void* pKey = GetMapKey_Custom(wsAttr);
261 SetMapModuleString(pKey, wsValue);
262 return true;
263 }
264
GetAttribute(const WideStringView & attr)265 WideString CJX_Object::GetAttribute(const WideStringView& attr) {
266 return TryAttribute(attr, true).value_or(WideString());
267 }
268
GetAttribute(XFA_Attribute attr)269 WideString CJX_Object::GetAttribute(XFA_Attribute attr) {
270 return TryAttribute(attr, true).value_or(WideString());
271 }
272
TryAttribute(XFA_Attribute eAttr,bool bUseDefault)273 Optional<WideString> CJX_Object::TryAttribute(XFA_Attribute eAttr,
274 bool bUseDefault) {
275 switch (ToNode(GetXFAObject())->GetAttributeType(eAttr)) {
276 case XFA_AttributeType::Enum: {
277 Optional<XFA_AttributeEnum> value = TryEnum(eAttr, bUseDefault);
278 if (!value)
279 return {};
280
281 return {CXFA_Node::AttributeEnumToName(*value)};
282 }
283 case XFA_AttributeType::CData:
284 return TryCData(eAttr, bUseDefault);
285
286 case XFA_AttributeType::Boolean: {
287 Optional<bool> value = TryBoolean(eAttr, bUseDefault);
288 if (!value)
289 return {};
290 return {*value ? L"1" : L"0"};
291 }
292 case XFA_AttributeType::Integer: {
293 Optional<int32_t> iValue = TryInteger(eAttr, bUseDefault);
294 if (!iValue)
295 return {};
296 return {WideString::Format(L"%d", *iValue)};
297 }
298 case XFA_AttributeType::Measure: {
299 Optional<CXFA_Measurement> value = TryMeasure(eAttr, bUseDefault);
300 if (!value)
301 return {};
302
303 return {value->ToString()};
304 }
305 default:
306 break;
307 }
308 return {};
309 }
310
TryAttribute(const WideStringView & wsAttr,bool bUseDefault)311 Optional<WideString> CJX_Object::TryAttribute(const WideStringView& wsAttr,
312 bool bUseDefault) {
313 XFA_Attribute attr = CXFA_Node::NameToAttribute(wsAttr);
314 if (attr != XFA_Attribute::Unknown)
315 return TryAttribute(attr, bUseDefault);
316
317 void* pKey = GetMapKey_Custom(wsAttr);
318 WideStringView wsValueC;
319 if (!GetMapModuleString(pKey, wsValueC))
320 return {};
321
322 return {WideString(wsValueC)};
323 }
324
RemoveAttribute(const WideStringView & wsAttr)325 void CJX_Object::RemoveAttribute(const WideStringView& wsAttr) {
326 void* pKey = GetMapKey_Custom(wsAttr);
327 if (pKey)
328 RemoveMapModuleKey(pKey);
329 }
330
TryBoolean(XFA_Attribute eAttr,bool bUseDefault)331 Optional<bool> CJX_Object::TryBoolean(XFA_Attribute eAttr, bool bUseDefault) {
332 void* pValue = nullptr;
333 void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
334 if (GetMapModuleValue(pKey, pValue))
335 return {!!pValue};
336 if (!bUseDefault)
337 return {};
338
339 return ToNode(GetXFAObject())->GetDefaultBoolean(eAttr);
340 }
341
SetBoolean(XFA_Attribute eAttr,bool bValue,bool bNotify)342 bool CJX_Object::SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify) {
343 CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Boolean,
344 (void*)(uintptr_t)bValue, bNotify);
345 if (elem)
346 elem->SetString(CXFA_Node::AttributeToName(eAttr), bValue ? L"1" : L"0");
347 return true;
348 }
349
GetBoolean(XFA_Attribute eAttr)350 bool CJX_Object::GetBoolean(XFA_Attribute eAttr) {
351 return TryBoolean(eAttr, true).value_or(false);
352 }
353
SetInteger(XFA_Attribute eAttr,int32_t iValue,bool bNotify)354 bool CJX_Object::SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify) {
355 CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Integer,
356 (void*)(uintptr_t)iValue, bNotify);
357 if (elem) {
358 elem->SetString(CXFA_Node::AttributeToName(eAttr),
359 WideString::Format(L"%d", iValue));
360 }
361 return true;
362 }
363
GetInteger(XFA_Attribute eAttr)364 int32_t CJX_Object::GetInteger(XFA_Attribute eAttr) {
365 return TryInteger(eAttr, true).value_or(0);
366 }
367
TryInteger(XFA_Attribute eAttr,bool bUseDefault)368 Optional<int32_t> CJX_Object::TryInteger(XFA_Attribute eAttr,
369 bool bUseDefault) {
370 void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
371 void* pValue = nullptr;
372 if (GetMapModuleValue(pKey, pValue))
373 return {static_cast<int32_t>(reinterpret_cast<uintptr_t>(pValue))};
374 if (!bUseDefault)
375 return {};
376
377 return ToNode(GetXFAObject())->GetDefaultInteger(eAttr);
378 }
379
TryEnum(XFA_Attribute eAttr,bool bUseDefault)380 Optional<XFA_AttributeEnum> CJX_Object::TryEnum(XFA_Attribute eAttr,
381 bool bUseDefault) {
382 void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
383 void* pValue = nullptr;
384 if (GetMapModuleValue(pKey, pValue)) {
385 return {
386 static_cast<XFA_AttributeEnum>(reinterpret_cast<uintptr_t>(pValue))};
387 }
388 if (!bUseDefault)
389 return {};
390
391 return ToNode(GetXFAObject())->GetDefaultEnum(eAttr);
392 }
393
SetEnum(XFA_Attribute eAttr,XFA_AttributeEnum eValue,bool bNotify)394 bool CJX_Object::SetEnum(XFA_Attribute eAttr,
395 XFA_AttributeEnum eValue,
396 bool bNotify) {
397 CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Enum,
398 (void*)(uintptr_t)eValue, bNotify);
399 if (elem) {
400 elem->SetString(CXFA_Node::AttributeToName(eAttr),
401 CXFA_Node::AttributeEnumToName(eValue));
402 }
403 return true;
404 }
405
GetEnum(XFA_Attribute eAttr)406 XFA_AttributeEnum CJX_Object::GetEnum(XFA_Attribute eAttr) {
407 return TryEnum(eAttr, true).value_or(XFA_AttributeEnum::Unknown);
408 }
409
SetMeasure(XFA_Attribute eAttr,CXFA_Measurement mValue,bool bNotify)410 bool CJX_Object::SetMeasure(XFA_Attribute eAttr,
411 CXFA_Measurement mValue,
412 bool bNotify) {
413 void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
414 OnChanging(eAttr, bNotify);
415 SetMapModuleBuffer(pKey, &mValue, sizeof(CXFA_Measurement), nullptr);
416 OnChanged(eAttr, bNotify, false);
417 return true;
418 }
419
TryMeasure(XFA_Attribute eAttr,bool bUseDefault) const420 Optional<CXFA_Measurement> CJX_Object::TryMeasure(XFA_Attribute eAttr,
421 bool bUseDefault) const {
422 void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
423 void* pValue;
424 int32_t iBytes;
425 if (GetMapModuleBuffer(pKey, pValue, iBytes, true) &&
426 iBytes == sizeof(CXFA_Measurement)) {
427 return {*reinterpret_cast<CXFA_Measurement*>(pValue)};
428 }
429 if (!bUseDefault)
430 return {};
431
432 return ToNode(GetXFAObject())->GetDefaultMeasurement(eAttr);
433 }
434
TryMeasureAsFloat(XFA_Attribute attr) const435 Optional<float> CJX_Object::TryMeasureAsFloat(XFA_Attribute attr) const {
436 Optional<CXFA_Measurement> measure = TryMeasure(attr, false);
437 if (measure)
438 return {measure->ToUnit(XFA_Unit::Pt)};
439 return {};
440 }
441
GetMeasure(XFA_Attribute eAttr) const442 CXFA_Measurement CJX_Object::GetMeasure(XFA_Attribute eAttr) const {
443 return TryMeasure(eAttr, true).value_or(CXFA_Measurement());
444 }
445
GetCData(XFA_Attribute eAttr)446 WideString CJX_Object::GetCData(XFA_Attribute eAttr) {
447 return TryCData(eAttr, true).value_or(WideString());
448 }
449
SetCData(XFA_Attribute eAttr,const WideString & wsValue,bool bNotify,bool bScriptModify)450 bool CJX_Object::SetCData(XFA_Attribute eAttr,
451 const WideString& wsValue,
452 bool bNotify,
453 bool bScriptModify) {
454 CXFA_Node* xfaObj = ToNode(GetXFAObject());
455 void* pKey = GetMapKey_Element(xfaObj->GetElementType(), eAttr);
456 OnChanging(eAttr, bNotify);
457 if (eAttr == XFA_Attribute::Value) {
458 WideString* pClone = new WideString(wsValue);
459 SetUserData(pKey, pClone, &deleteWideStringCallBack);
460 } else {
461 SetMapModuleString(pKey, wsValue.AsStringView());
462 if (eAttr == XFA_Attribute::Name)
463 xfaObj->UpdateNameHash();
464 }
465 OnChanged(eAttr, bNotify, bScriptModify);
466
467 if (!xfaObj->IsNeedSavingXMLNode() || eAttr == XFA_Attribute::QualifiedName ||
468 eAttr == XFA_Attribute::BindingNode) {
469 return true;
470 }
471
472 if (eAttr == XFA_Attribute::Name &&
473 (xfaObj->GetElementType() == XFA_Element::DataValue ||
474 xfaObj->GetElementType() == XFA_Element::DataGroup)) {
475 return true;
476 }
477
478 auto* elem = static_cast<CFX_XMLElement*>(xfaObj->GetXMLMappingNode());
479 if (eAttr == XFA_Attribute::Value) {
480 FX_XMLNODETYPE eXMLType = elem->GetType();
481 switch (eXMLType) {
482 case FX_XMLNODE_Element:
483 if (xfaObj->IsAttributeInXML()) {
484 elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)),
485 wsValue);
486 } else {
487 bool bDeleteChildren = true;
488 if (xfaObj->GetPacketType() == XFA_PacketType::Datasets) {
489 for (CXFA_Node* pChildDataNode = xfaObj->GetFirstChild();
490 pChildDataNode;
491 pChildDataNode = pChildDataNode->GetNextSibling()) {
492 if (!pChildDataNode->GetBindItems()->empty()) {
493 bDeleteChildren = false;
494 break;
495 }
496 }
497 }
498 if (bDeleteChildren)
499 elem->DeleteChildren();
500
501 elem->SetTextData(wsValue);
502 }
503 break;
504 case FX_XMLNODE_Text:
505 static_cast<CFX_XMLText*>(xfaObj->GetXMLMappingNode())
506 ->SetText(wsValue);
507 break;
508 default:
509 NOTREACHED();
510 }
511 return true;
512 }
513 ASSERT(elem->GetType() == FX_XMLNODE_Element);
514
515 WideString wsAttrName = CXFA_Node::AttributeToName(eAttr);
516 if (eAttr == XFA_Attribute::ContentType)
517 wsAttrName = L"xfa:" + wsAttrName;
518
519 elem->SetString(wsAttrName, wsValue);
520 return true;
521 }
522
SetAttributeValue(const WideString & wsValue,const WideString & wsXMLValue,bool bNotify,bool bScriptModify)523 void CJX_Object::SetAttributeValue(const WideString& wsValue,
524 const WideString& wsXMLValue,
525 bool bNotify,
526 bool bScriptModify) {
527 auto* xfaObj = ToNode(GetXFAObject());
528
529 void* pKey =
530 GetMapKey_Element(xfaObj->GetElementType(), XFA_Attribute::Value);
531 OnChanging(XFA_Attribute::Value, bNotify);
532 WideString* pClone = new WideString(wsValue);
533 SetUserData(pKey, pClone, &deleteWideStringCallBack);
534 OnChanged(XFA_Attribute::Value, bNotify, bScriptModify);
535 if (!xfaObj->IsNeedSavingXMLNode())
536 return;
537
538 auto* elem = static_cast<CFX_XMLElement*>(xfaObj->GetXMLMappingNode());
539 FX_XMLNODETYPE eXMLType = elem->GetType();
540 switch (eXMLType) {
541 case FX_XMLNODE_Element:
542 if (xfaObj->IsAttributeInXML()) {
543 elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)),
544 wsXMLValue);
545 } else {
546 bool bDeleteChildren = true;
547 if (xfaObj->GetPacketType() == XFA_PacketType::Datasets) {
548 for (CXFA_Node* pChildDataNode = xfaObj->GetFirstChild();
549 pChildDataNode;
550 pChildDataNode = pChildDataNode->GetNextSibling()) {
551 if (!pChildDataNode->GetBindItems()->empty()) {
552 bDeleteChildren = false;
553 break;
554 }
555 }
556 }
557 if (bDeleteChildren)
558 elem->DeleteChildren();
559
560 elem->SetTextData(wsXMLValue);
561 }
562 break;
563 case FX_XMLNODE_Text:
564 static_cast<CFX_XMLText*>(xfaObj->GetXMLMappingNode())
565 ->SetText(wsXMLValue);
566 break;
567 default:
568 ASSERT(0);
569 }
570 }
571
TryCData(XFA_Attribute eAttr,bool bUseDefault)572 Optional<WideString> CJX_Object::TryCData(XFA_Attribute eAttr,
573 bool bUseDefault) {
574 void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
575 if (eAttr == XFA_Attribute::Value) {
576 void* pData;
577 int32_t iBytes = 0;
578 WideString* pStr = nullptr;
579 if (GetMapModuleBuffer(pKey, pData, iBytes, true) &&
580 iBytes == sizeof(void*)) {
581 memcpy(&pData, pData, iBytes);
582 pStr = reinterpret_cast<WideString*>(pData);
583 }
584 if (pStr)
585 return {*pStr};
586 } else {
587 WideStringView wsValueC;
588 if (GetMapModuleString(pKey, wsValueC))
589 return {WideString(wsValueC)};
590 }
591 if (!bUseDefault)
592 return {};
593
594 return ToNode(GetXFAObject())->GetDefaultCData(eAttr);
595 }
596
SetValue(XFA_Attribute eAttr,XFA_AttributeType eType,void * pValue,bool bNotify)597 CFX_XMLElement* CJX_Object::SetValue(XFA_Attribute eAttr,
598 XFA_AttributeType eType,
599 void* pValue,
600 bool bNotify) {
601 void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
602 OnChanging(eAttr, bNotify);
603 SetMapModuleValue(pKey, pValue);
604 OnChanged(eAttr, bNotify, false);
605 if (!ToNode(GetXFAObject())->IsNeedSavingXMLNode())
606 return nullptr;
607
608 auto* elem =
609 static_cast<CFX_XMLElement*>(ToNode(GetXFAObject())->GetXMLMappingNode());
610 ASSERT(elem->GetType() == FX_XMLNODE_Element);
611
612 return elem;
613 }
614
SetContent(const WideString & wsContent,const WideString & wsXMLValue,bool bNotify,bool bScriptModify,bool bSyncData)615 bool CJX_Object::SetContent(const WideString& wsContent,
616 const WideString& wsXMLValue,
617 bool bNotify,
618 bool bScriptModify,
619 bool bSyncData) {
620 CXFA_Node* pNode = nullptr;
621 CXFA_Node* pBindNode = nullptr;
622 switch (ToNode(GetXFAObject())->GetObjectType()) {
623 case XFA_ObjectType::ContainerNode: {
624 if (XFA_FieldIsMultiListBox(ToNode(GetXFAObject()))) {
625 CXFA_Value* pValue =
626 GetOrCreateProperty<CXFA_Value>(0, XFA_Element::Value);
627 if (!pValue)
628 break;
629
630 CXFA_Node* pChildValue = pValue->GetFirstChild();
631 ASSERT(pChildValue);
632 pChildValue->JSObject()->SetCData(XFA_Attribute::ContentType,
633 L"text/xml", false, false);
634 pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify,
635 bScriptModify, false);
636 CXFA_Node* pBind = ToNode(GetXFAObject())->GetBindData();
637 if (bSyncData && pBind) {
638 std::vector<WideString> wsSaveTextArray;
639 size_t iSize = 0;
640 if (!wsContent.IsEmpty()) {
641 size_t iStart = 0;
642 size_t iLength = wsContent.GetLength();
643 auto iEnd = wsContent.Find(L'\n', iStart);
644 iEnd = !iEnd.has_value() ? iLength : iEnd;
645 while (iEnd.value() >= iStart) {
646 wsSaveTextArray.push_back(
647 wsContent.Mid(iStart, iEnd.value() - iStart));
648 iStart = iEnd.value() + 1;
649 if (iStart >= iLength)
650 break;
651
652 iEnd = wsContent.Find(L'\n', iStart);
653 if (!iEnd.has_value()) {
654 wsSaveTextArray.push_back(
655 wsContent.Mid(iStart, iLength - iStart));
656 }
657 }
658 iSize = wsSaveTextArray.size();
659 }
660 if (iSize == 0) {
661 while (CXFA_Node* pChildNode = pBind->GetFirstChild()) {
662 pBind->RemoveChild(pChildNode, true);
663 }
664 } else {
665 std::vector<CXFA_Node*> valueNodes = pBind->GetNodeList(
666 XFA_NODEFILTER_Children, XFA_Element::DataValue);
667 size_t iDatas = valueNodes.size();
668 if (iDatas < iSize) {
669 size_t iAddNodes = iSize - iDatas;
670 CXFA_Node* pValueNodes = nullptr;
671 while (iAddNodes-- > 0) {
672 pValueNodes =
673 pBind->CreateSamePacketNode(XFA_Element::DataValue);
674 pValueNodes->JSObject()->SetCData(XFA_Attribute::Name, L"value",
675 false, false);
676 pValueNodes->CreateXMLMappingNode();
677 pBind->InsertChild(pValueNodes, nullptr);
678 }
679 pValueNodes = nullptr;
680 } else if (iDatas > iSize) {
681 size_t iDelNodes = iDatas - iSize;
682 while (iDelNodes-- > 0) {
683 pBind->RemoveChild(pBind->GetFirstChild(), true);
684 }
685 }
686 int32_t i = 0;
687 for (CXFA_Node* pValueNode = pBind->GetFirstChild(); pValueNode;
688 pValueNode = pValueNode->GetNextSibling()) {
689 pValueNode->JSObject()->SetAttributeValue(
690 wsSaveTextArray[i], wsSaveTextArray[i], false, false);
691 i++;
692 }
693 }
694 for (const auto& pArrayNode : *(pBind->GetBindItems())) {
695 if (pArrayNode.Get() != ToNode(GetXFAObject())) {
696 pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
697 bScriptModify, false);
698 }
699 }
700 }
701 break;
702 }
703 if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExclGroup) {
704 pNode = ToNode(GetXFAObject());
705 } else {
706 CXFA_Value* pValue =
707 GetOrCreateProperty<CXFA_Value>(0, XFA_Element::Value);
708 if (!pValue)
709 break;
710
711 CXFA_Node* pChildValue = pValue->GetFirstChild();
712 ASSERT(pChildValue);
713 pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify,
714 bScriptModify, false);
715 }
716 pBindNode = ToNode(GetXFAObject())->GetBindData();
717 if (pBindNode && bSyncData) {
718 pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify,
719 bScriptModify, false);
720 for (const auto& pArrayNode : *(pBindNode->GetBindItems())) {
721 if (pArrayNode.Get() != ToNode(GetXFAObject())) {
722 pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
723 true, false);
724 }
725 }
726 }
727 pBindNode = nullptr;
728 break;
729 }
730 case XFA_ObjectType::ContentNode: {
731 WideString wsContentType;
732 if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExData) {
733 Optional<WideString> ret =
734 TryAttribute(XFA_Attribute::ContentType, false);
735 if (ret)
736 wsContentType = *ret;
737 if (wsContentType == L"text/html") {
738 wsContentType = L"";
739 SetAttribute(XFA_Attribute::ContentType, wsContentType.AsStringView(),
740 false);
741 }
742 }
743
744 CXFA_Node* pContentRawDataNode = ToNode(GetXFAObject())->GetFirstChild();
745 if (!pContentRawDataNode) {
746 pContentRawDataNode =
747 ToNode(GetXFAObject())
748 ->CreateSamePacketNode((wsContentType == L"text/xml")
749 ? XFA_Element::Sharpxml
750 : XFA_Element::Sharptext);
751 ToNode(GetXFAObject())->InsertChild(pContentRawDataNode, nullptr);
752 }
753 return pContentRawDataNode->JSObject()->SetContent(
754 wsContent, wsXMLValue, bNotify, bScriptModify, bSyncData);
755 }
756 case XFA_ObjectType::NodeC:
757 case XFA_ObjectType::TextNode:
758 pNode = ToNode(GetXFAObject());
759 break;
760 case XFA_ObjectType::NodeV:
761 pNode = ToNode(GetXFAObject());
762 if (bSyncData &&
763 ToNode(GetXFAObject())->GetPacketType() == XFA_PacketType::Form) {
764 CXFA_Node* pParent = ToNode(GetXFAObject())->GetParent();
765 if (pParent) {
766 pParent = pParent->GetParent();
767 }
768 if (pParent && pParent->GetElementType() == XFA_Element::Value) {
769 pParent = pParent->GetParent();
770 if (pParent && pParent->IsContainerNode()) {
771 pBindNode = pParent->GetBindData();
772 if (pBindNode) {
773 pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify,
774 bScriptModify, false);
775 }
776 }
777 }
778 }
779 break;
780 default:
781 if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue) {
782 pNode = ToNode(GetXFAObject());
783 pBindNode = ToNode(GetXFAObject());
784 }
785 break;
786 }
787 if (!pNode)
788 return false;
789
790 SetAttributeValue(wsContent, wsXMLValue, bNotify, bScriptModify);
791 if (pBindNode && bSyncData) {
792 for (const auto& pArrayNode : *(pBindNode->GetBindItems())) {
793 pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
794 bScriptModify, false);
795 }
796 }
797 return true;
798 }
799
GetContent(bool bScriptModify)800 WideString CJX_Object::GetContent(bool bScriptModify) {
801 return TryContent(bScriptModify, true).value_or(WideString());
802 }
803
TryContent(bool bScriptModify,bool bProto)804 Optional<WideString> CJX_Object::TryContent(bool bScriptModify, bool bProto) {
805 CXFA_Node* pNode = nullptr;
806 switch (ToNode(GetXFAObject())->GetObjectType()) {
807 case XFA_ObjectType::ContainerNode:
808 if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExclGroup) {
809 pNode = ToNode(GetXFAObject());
810 } else {
811 CXFA_Value* pValue =
812 ToNode(GetXFAObject())
813 ->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
814 if (!pValue)
815 return {};
816
817 CXFA_Node* pChildValue = pValue->GetFirstChild();
818 if (pChildValue && XFA_FieldIsMultiListBox(ToNode(GetXFAObject()))) {
819 pChildValue->JSObject()->SetAttribute(XFA_Attribute::ContentType,
820 L"text/xml", false);
821 }
822 if (pChildValue)
823 return pChildValue->JSObject()->TryContent(bScriptModify, bProto);
824 return {};
825 }
826 break;
827 case XFA_ObjectType::ContentNode: {
828 CXFA_Node* pContentRawDataNode = ToNode(GetXFAObject())->GetFirstChild();
829 if (!pContentRawDataNode) {
830 XFA_Element element = XFA_Element::Sharptext;
831 if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExData) {
832 Optional<WideString> contentType =
833 TryAttribute(XFA_Attribute::ContentType, false);
834 if (contentType) {
835 if (*contentType == L"text/html")
836 element = XFA_Element::SharpxHTML;
837 else if (*contentType == L"text/xml")
838 element = XFA_Element::Sharpxml;
839 }
840 }
841 pContentRawDataNode =
842 ToNode(GetXFAObject())->CreateSamePacketNode(element);
843 ToNode(GetXFAObject())->InsertChild(pContentRawDataNode, nullptr);
844 }
845 return pContentRawDataNode->JSObject()->TryContent(bScriptModify, true);
846 }
847 case XFA_ObjectType::NodeC:
848 case XFA_ObjectType::NodeV:
849 case XFA_ObjectType::TextNode:
850 pNode = ToNode(GetXFAObject());
851 default:
852 if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue)
853 pNode = ToNode(GetXFAObject());
854 break;
855 }
856 if (pNode) {
857 if (bScriptModify) {
858 CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
859 if (pScriptContext)
860 GetDocument()->GetScriptContext()->AddNodesOfRunScript(
861 ToNode(GetXFAObject()));
862 }
863 return TryCData(XFA_Attribute::Value, false);
864 }
865 return {};
866 }
867
TryNamespace()868 Optional<WideString> CJX_Object::TryNamespace() {
869 if (ToNode(GetXFAObject())->IsModelNode() ||
870 ToNode(GetXFAObject())->GetElementType() == XFA_Element::Packet) {
871 CFX_XMLNode* pXMLNode = ToNode(GetXFAObject())->GetXMLMappingNode();
872 if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element)
873 return {};
874
875 return {static_cast<CFX_XMLElement*>(pXMLNode)->GetNamespaceURI()};
876 }
877
878 if (ToNode(GetXFAObject())->GetPacketType() != XFA_PacketType::Datasets)
879 return ToNode(GetXFAObject())->GetModelNode()->JSObject()->TryNamespace();
880
881 CFX_XMLNode* pXMLNode = ToNode(GetXFAObject())->GetXMLMappingNode();
882 if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element)
883 return {};
884
885 if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue &&
886 GetEnum(XFA_Attribute::Contains) == XFA_AttributeEnum::MetaData) {
887 WideString wsNamespace;
888 bool ret = XFA_FDEExtension_ResolveNamespaceQualifier(
889 static_cast<CFX_XMLElement*>(pXMLNode),
890 GetCData(XFA_Attribute::QualifiedName), &wsNamespace);
891 if (!ret)
892 return {};
893 return {wsNamespace};
894 }
895 return {static_cast<CFX_XMLElement*>(pXMLNode)->GetNamespaceURI()};
896 }
897
GetPropertyInternal(int32_t index,XFA_Element eProperty) const898 std::pair<CXFA_Node*, int32_t> CJX_Object::GetPropertyInternal(
899 int32_t index,
900 XFA_Element eProperty) const {
901 const CXFA_Node* xfaNode = ToNode(GetXFAObject());
902 if (index < 0 || index >= xfaNode->PropertyOccuranceCount(eProperty))
903 return {nullptr, 0};
904
905 int32_t iCount = 0;
906 for (CXFA_Node* pNode = xfaNode->GetFirstChild(); pNode;
907 pNode = pNode->GetNextSibling()) {
908 if (pNode->GetElementType() == eProperty) {
909 iCount++;
910 if (iCount > index)
911 return {pNode, iCount};
912 }
913 }
914 return {nullptr, iCount};
915 }
916
GetOrCreatePropertyInternal(int32_t index,XFA_Element eProperty)917 CXFA_Node* CJX_Object::GetOrCreatePropertyInternal(int32_t index,
918 XFA_Element eProperty) {
919 CXFA_Node* xfaNode = ToNode(GetXFAObject());
920 if (index < 0 || index >= xfaNode->PropertyOccuranceCount(eProperty))
921 return nullptr;
922
923 int32_t iCount = 0;
924 CXFA_Node* node;
925 std::tie(node, iCount) = GetPropertyInternal(index, eProperty);
926 if (node)
927 return node;
928
929 if (xfaNode->HasPropertyFlags(eProperty, XFA_PROPERTYFLAG_OneOf)) {
930 for (CXFA_Node* pNode = xfaNode->GetFirstChild(); pNode;
931 pNode = pNode->GetNextSibling()) {
932 if (xfaNode->HasPropertyFlags(pNode->GetElementType(),
933 XFA_PROPERTYFLAG_OneOf)) {
934 return nullptr;
935 }
936 }
937 }
938
939 CXFA_Node* pNewNode = nullptr;
940 for (; iCount <= index; ++iCount) {
941 pNewNode = GetDocument()->CreateNode(xfaNode->GetPacketType(), eProperty);
942 if (!pNewNode)
943 return nullptr;
944
945 xfaNode->InsertChild(pNewNode, nullptr);
946 pNewNode->SetFlag(XFA_NodeFlag_Initialized, true);
947 }
948 return pNewNode;
949 }
950
SetUserData(void * pKey,void * pData,XFA_MAPDATABLOCKCALLBACKINFO * pCallbackInfo)951 bool CJX_Object::SetUserData(void* pKey,
952 void* pData,
953 XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) {
954 SetMapModuleBuffer(pKey, &pData, sizeof(void*),
955 pCallbackInfo ? pCallbackInfo : &gs_XFADefaultFreeData);
956 return true;
957 }
958
CreateMapModuleData()959 XFA_MAPMODULEDATA* CJX_Object::CreateMapModuleData() {
960 if (!map_module_data_)
961 map_module_data_ = pdfium::MakeUnique<XFA_MAPMODULEDATA>();
962 return map_module_data_.get();
963 }
964
GetMapModuleData() const965 XFA_MAPMODULEDATA* CJX_Object::GetMapModuleData() const {
966 return map_module_data_.get();
967 }
968
SetMapModuleValue(void * pKey,void * pValue)969 void CJX_Object::SetMapModuleValue(void* pKey, void* pValue) {
970 CreateMapModuleData()->m_ValueMap[pKey] = pValue;
971 }
972
GetMapModuleValue(void * pKey,void * & pValue)973 bool CJX_Object::GetMapModuleValue(void* pKey, void*& pValue) {
974 for (CXFA_Node* pNode = ToNode(GetXFAObject()); pNode;
975 pNode = pNode->GetTemplateNodeIfExists()) {
976 XFA_MAPMODULEDATA* pModule = pNode->JSObject()->GetMapModuleData();
977 if (pModule) {
978 auto it = pModule->m_ValueMap.find(pKey);
979 if (it != pModule->m_ValueMap.end()) {
980 pValue = it->second;
981 return true;
982 }
983 }
984 if (pNode->GetPacketType() == XFA_PacketType::Datasets)
985 break;
986 }
987 return false;
988 }
989
GetMapModuleString(void * pKey,WideStringView & wsValue)990 bool CJX_Object::GetMapModuleString(void* pKey, WideStringView& wsValue) {
991 void* pValue;
992 int32_t iBytes;
993 if (!GetMapModuleBuffer(pKey, pValue, iBytes, true))
994 return false;
995
996 // Defensive measure: no out-of-bounds pointers even if zero length.
997 int32_t iChars = iBytes / sizeof(wchar_t);
998 wsValue = WideStringView(iChars ? (const wchar_t*)pValue : nullptr, iChars);
999 return true;
1000 }
1001
SetMapModuleBuffer(void * pKey,void * pValue,int32_t iBytes,XFA_MAPDATABLOCKCALLBACKINFO * pCallbackInfo)1002 void CJX_Object::SetMapModuleBuffer(
1003 void* pKey,
1004 void* pValue,
1005 int32_t iBytes,
1006 XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) {
1007 XFA_MAPDATABLOCK*& pBuffer = CreateMapModuleData()->m_BufferMap[pKey];
1008 if (!pBuffer) {
1009 pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(
1010 FX_Alloc(uint8_t, sizeof(XFA_MAPDATABLOCK) + iBytes));
1011 } else if (pBuffer->iBytes != iBytes) {
1012 if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
1013 pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
1014
1015 pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(
1016 FX_Realloc(uint8_t, pBuffer, sizeof(XFA_MAPDATABLOCK) + iBytes));
1017 } else if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) {
1018 pBuffer->pCallbackInfo->pFree(
1019 *reinterpret_cast<void**>(pBuffer->GetData()));
1020 }
1021 if (!pBuffer)
1022 return;
1023
1024 pBuffer->pCallbackInfo = pCallbackInfo;
1025 pBuffer->iBytes = iBytes;
1026 memcpy(pBuffer->GetData(), pValue, iBytes);
1027 }
1028
GetMapModuleBuffer(void * pKey,void * & pValue,int32_t & iBytes,bool bProtoAlso) const1029 bool CJX_Object::GetMapModuleBuffer(void* pKey,
1030 void*& pValue,
1031 int32_t& iBytes,
1032 bool bProtoAlso) const {
1033 XFA_MAPDATABLOCK* pBuffer = nullptr;
1034 for (const CXFA_Node* pNode = ToNode(GetXFAObject()); pNode;
1035 pNode = pNode->GetTemplateNodeIfExists()) {
1036 XFA_MAPMODULEDATA* pModule = pNode->JSObject()->GetMapModuleData();
1037 if (pModule) {
1038 auto it = pModule->m_BufferMap.find(pKey);
1039 if (it != pModule->m_BufferMap.end()) {
1040 pBuffer = it->second;
1041 break;
1042 }
1043 }
1044 if (!bProtoAlso || pNode->GetPacketType() == XFA_PacketType::Datasets)
1045 break;
1046 }
1047 if (!pBuffer)
1048 return false;
1049
1050 pValue = pBuffer->GetData();
1051 iBytes = pBuffer->iBytes;
1052 return true;
1053 }
1054
HasMapModuleKey(void * pKey)1055 bool CJX_Object::HasMapModuleKey(void* pKey) {
1056 XFA_MAPMODULEDATA* pModule = GetMapModuleData();
1057 return pModule && (pdfium::ContainsKey(pModule->m_ValueMap, pKey) ||
1058 pdfium::ContainsKey(pModule->m_BufferMap, pKey));
1059 }
1060
ClearMapModuleBuffer()1061 void CJX_Object::ClearMapModuleBuffer() {
1062 XFA_MAPMODULEDATA* pModule = GetMapModuleData();
1063 if (!pModule)
1064 return;
1065
1066 for (auto& pair : pModule->m_BufferMap) {
1067 XFA_MAPDATABLOCK* pBuffer = pair.second;
1068 if (pBuffer) {
1069 if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
1070 pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
1071
1072 FX_Free(pBuffer);
1073 }
1074 }
1075 pModule->m_BufferMap.clear();
1076 pModule->m_ValueMap.clear();
1077 }
1078
RemoveMapModuleKey(void * pKey)1079 void CJX_Object::RemoveMapModuleKey(void* pKey) {
1080 ASSERT(pKey);
1081
1082 XFA_MAPMODULEDATA* pModule = GetMapModuleData();
1083 if (!pModule)
1084 return;
1085
1086 auto it = pModule->m_BufferMap.find(pKey);
1087 if (it != pModule->m_BufferMap.end()) {
1088 XFA_MAPDATABLOCK* pBuffer = it->second;
1089 if (pBuffer) {
1090 if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
1091 pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
1092
1093 FX_Free(pBuffer);
1094 }
1095 pModule->m_BufferMap.erase(it);
1096 }
1097 pModule->m_ValueMap.erase(pKey);
1098 return;
1099 }
1100
MergeAllData(CXFA_Object * pDstModule)1101 void CJX_Object::MergeAllData(CXFA_Object* pDstModule) {
1102 XFA_MAPMODULEDATA* pDstModuleData =
1103 ToNode(pDstModule)->JSObject()->CreateMapModuleData();
1104 XFA_MAPMODULEDATA* pSrcModuleData = GetMapModuleData();
1105 if (!pSrcModuleData)
1106 return;
1107
1108 for (const auto& pair : pSrcModuleData->m_ValueMap)
1109 pDstModuleData->m_ValueMap[pair.first] = pair.second;
1110
1111 for (const auto& pair : pSrcModuleData->m_BufferMap) {
1112 XFA_MAPDATABLOCK* pSrcBuffer = pair.second;
1113 XFA_MAPDATABLOCK*& pDstBuffer = pDstModuleData->m_BufferMap[pair.first];
1114 if (pSrcBuffer->pCallbackInfo && pSrcBuffer->pCallbackInfo->pFree &&
1115 !pSrcBuffer->pCallbackInfo->pCopy) {
1116 if (pDstBuffer) {
1117 pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
1118 pDstModuleData->m_BufferMap.erase(pair.first);
1119 }
1120 continue;
1121 }
1122 if (!pDstBuffer) {
1123 pDstBuffer = (XFA_MAPDATABLOCK*)FX_Alloc(
1124 uint8_t, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes);
1125 } else if (pDstBuffer->iBytes != pSrcBuffer->iBytes) {
1126 if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) {
1127 pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
1128 }
1129 pDstBuffer = (XFA_MAPDATABLOCK*)FX_Realloc(
1130 uint8_t, pDstBuffer, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes);
1131 } else if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) {
1132 pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
1133 }
1134 if (!pDstBuffer)
1135 continue;
1136
1137 pDstBuffer->pCallbackInfo = pSrcBuffer->pCallbackInfo;
1138 pDstBuffer->iBytes = pSrcBuffer->iBytes;
1139 memcpy(pDstBuffer->GetData(), pSrcBuffer->GetData(), pSrcBuffer->iBytes);
1140 if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pCopy) {
1141 pDstBuffer->pCallbackInfo->pCopy(*(void**)pDstBuffer->GetData());
1142 }
1143 }
1144 }
1145
MoveBufferMapData(CXFA_Object * pDstModule)1146 void CJX_Object::MoveBufferMapData(CXFA_Object* pDstModule) {
1147 if (!pDstModule)
1148 return;
1149
1150 bool bNeedMove = true;
1151 if (pDstModule->GetElementType() != GetXFAObject()->GetElementType())
1152 bNeedMove = false;
1153
1154 if (bNeedMove)
1155 ToNode(pDstModule)->JSObject()->SetCalcData(ReleaseCalcData());
1156 if (!pDstModule->IsNodeV())
1157 return;
1158
1159 WideString wsValue = ToNode(pDstModule)->JSObject()->GetContent(false);
1160 WideString wsFormatValue(wsValue);
1161 CXFA_WidgetAcc* pWidgetAcc = ToNode(pDstModule)->GetContainerWidgetAcc();
1162 if (pWidgetAcc)
1163 wsFormatValue = pWidgetAcc->GetFormatDataValue(wsValue);
1164
1165 ToNode(pDstModule)
1166 ->JSObject()
1167 ->SetContent(wsValue, wsFormatValue, true, true, true);
1168 }
1169
MoveBufferMapData(CXFA_Object * pSrcModule,CXFA_Object * pDstModule)1170 void CJX_Object::MoveBufferMapData(CXFA_Object* pSrcModule,
1171 CXFA_Object* pDstModule) {
1172 if (!pSrcModule || !pDstModule)
1173 return;
1174
1175 CXFA_Node* pSrcChild = ToNode(pSrcModule)->GetFirstChild();
1176 CXFA_Node* pDstChild = ToNode(pDstModule)->GetFirstChild();
1177 while (pSrcChild && pDstChild) {
1178 MoveBufferMapData(pSrcChild, pDstChild);
1179
1180 pSrcChild = pSrcChild->GetNextSibling();
1181 pDstChild = pDstChild->GetNextSibling();
1182 }
1183 ToNode(pSrcModule)->JSObject()->MoveBufferMapData(pDstModule);
1184 }
1185
OnChanging(XFA_Attribute eAttr,bool bNotify)1186 void CJX_Object::OnChanging(XFA_Attribute eAttr, bool bNotify) {
1187 if (!bNotify || !ToNode(GetXFAObject())->IsInitialized())
1188 return;
1189
1190 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
1191 if (pNotify)
1192 pNotify->OnValueChanging(ToNode(GetXFAObject()), eAttr);
1193 }
1194
OnChanged(XFA_Attribute eAttr,bool bNotify,bool bScriptModify)1195 void CJX_Object::OnChanged(XFA_Attribute eAttr,
1196 bool bNotify,
1197 bool bScriptModify) {
1198 if (bNotify && ToNode(GetXFAObject())->IsInitialized())
1199 ToNode(GetXFAObject())->SendAttributeChangeMessage(eAttr, bScriptModify);
1200 }
1201
SetCalcData(std::unique_ptr<CXFA_CalcData> data)1202 void CJX_Object::SetCalcData(std::unique_ptr<CXFA_CalcData> data) {
1203 calc_data_ = std::move(data);
1204 }
1205
ReleaseCalcData()1206 std::unique_ptr<CXFA_CalcData> CJX_Object::ReleaseCalcData() {
1207 return std::move(calc_data_);
1208 }
1209
Script_Attribute_String(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1210 void CJX_Object::Script_Attribute_String(CFXJSE_Value* pValue,
1211 bool bSetting,
1212 XFA_Attribute eAttribute) {
1213 if (!bSetting) {
1214 pValue->SetString(GetAttribute(eAttribute).UTF8Encode().AsStringView());
1215 return;
1216 }
1217
1218 WideString wsValue = pValue->ToWideString();
1219 SetAttribute(eAttribute, wsValue.AsStringView(), true);
1220 if (eAttribute != XFA_Attribute::Use ||
1221 GetXFAObject()->GetElementType() != XFA_Element::Desc) {
1222 return;
1223 }
1224
1225 CXFA_Node* pTemplateNode =
1226 ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Template));
1227 CXFA_Proto* pProtoRoot =
1228 pTemplateNode->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform)
1229 ->GetFirstChildByClass<CXFA_Proto>(XFA_Element::Proto);
1230
1231 WideString wsID;
1232 WideString wsSOM;
1233 if (!wsValue.IsEmpty()) {
1234 if (wsValue[0] == '#')
1235 wsID = WideString(wsValue.c_str() + 1, wsValue.GetLength() - 1);
1236 else
1237 wsSOM = wsValue;
1238 }
1239
1240 CXFA_Node* pProtoNode = nullptr;
1241 if (!wsSOM.IsEmpty()) {
1242 XFA_RESOLVENODE_RS resolveNodeRS;
1243 bool iRet = GetDocument()->GetScriptContext()->ResolveObjects(
1244 pProtoRoot, wsSOM.AsStringView(), &resolveNodeRS,
1245 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
1246 XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
1247 XFA_RESOLVENODE_Siblings,
1248 nullptr);
1249 if (iRet && resolveNodeRS.objects.front()->IsNode())
1250 pProtoNode = resolveNodeRS.objects.front()->AsNode();
1251
1252 } else if (!wsID.IsEmpty()) {
1253 pProtoNode = GetDocument()->GetNodeByID(pProtoRoot, wsID.AsStringView());
1254 }
1255 if (!pProtoNode)
1256 return;
1257
1258 CXFA_Node* pHeadChild = ToNode(GetXFAObject())->GetFirstChild();
1259 while (pHeadChild) {
1260 CXFA_Node* pSibling = pHeadChild->GetNextSibling();
1261 ToNode(GetXFAObject())->RemoveChild(pHeadChild, true);
1262 pHeadChild = pSibling;
1263 }
1264
1265 std::unique_ptr<CXFA_Node> pProtoForm(pProtoNode->CloneTemplateToForm(true));
1266 pHeadChild = pProtoForm->GetFirstChild();
1267 while (pHeadChild) {
1268 CXFA_Node* pSibling = pHeadChild->GetNextSibling();
1269 pProtoForm->RemoveChild(pHeadChild, true);
1270 ToNode(GetXFAObject())->InsertChild(pHeadChild, nullptr);
1271 pHeadChild = pSibling;
1272 }
1273
1274 GetDocument()->RemovePurgeNode(pProtoForm.get());
1275 }
1276
Script_Attribute_BOOL(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1277 void CJX_Object::Script_Attribute_BOOL(CFXJSE_Value* pValue,
1278 bool bSetting,
1279 XFA_Attribute eAttribute) {
1280 if (bSetting) {
1281 SetBoolean(eAttribute, pValue->ToBoolean(), true);
1282 return;
1283 }
1284 pValue->SetString(GetBoolean(eAttribute) ? "1" : "0");
1285 }
1286
Script_Attribute_Integer(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1287 void CJX_Object::Script_Attribute_Integer(CFXJSE_Value* pValue,
1288 bool bSetting,
1289 XFA_Attribute eAttribute) {
1290 if (bSetting) {
1291 SetInteger(eAttribute, pValue->ToInteger(), true);
1292 return;
1293 }
1294 pValue->SetInteger(GetInteger(eAttribute));
1295 }
1296
Script_Som_FontColor(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1297 void CJX_Object::Script_Som_FontColor(CFXJSE_Value* pValue,
1298 bool bSetting,
1299 XFA_Attribute eAttribute) {
1300 CXFA_Font* font = ToNode(object_.Get())->GetOrCreateFontIfPossible();
1301 if (!font)
1302 return;
1303
1304 if (bSetting) {
1305 int32_t r;
1306 int32_t g;
1307 int32_t b;
1308 std::tie(r, g, b) = StrToRGB(pValue->ToWideString());
1309 FX_ARGB color = ArgbEncode(0xff, r, g, b);
1310 font->SetColor(color);
1311 return;
1312 }
1313
1314 int32_t a;
1315 int32_t r;
1316 int32_t g;
1317 int32_t b;
1318 std::tie(a, r, g, b) = ArgbDecode(font->GetColor());
1319 pValue->SetString(ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
1320 }
1321
Script_Som_FillColor(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1322 void CJX_Object::Script_Som_FillColor(CFXJSE_Value* pValue,
1323 bool bSetting,
1324 XFA_Attribute eAttribute) {
1325 CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
1326 CXFA_Fill* borderfill = border->GetOrCreateFillIfPossible();
1327 if (!borderfill)
1328 return;
1329
1330 if (bSetting) {
1331 int32_t r;
1332 int32_t g;
1333 int32_t b;
1334 std::tie(r, g, b) = StrToRGB(pValue->ToWideString());
1335 FX_ARGB color = ArgbEncode(0xff, r, g, b);
1336 borderfill->SetColor(color);
1337 return;
1338 }
1339
1340 FX_ARGB color = borderfill->GetColor(false);
1341 int32_t a;
1342 int32_t r;
1343 int32_t g;
1344 int32_t b;
1345 std::tie(a, r, g, b) = ArgbDecode(color);
1346 pValue->SetString(
1347 WideString::Format(L"%d,%d,%d", r, g, b).UTF8Encode().AsStringView());
1348 }
1349
Script_Som_BorderColor(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1350 void CJX_Object::Script_Som_BorderColor(CFXJSE_Value* pValue,
1351 bool bSetting,
1352 XFA_Attribute eAttribute) {
1353 CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
1354 int32_t iSize = border->CountEdges();
1355 if (bSetting) {
1356 int32_t r = 0;
1357 int32_t g = 0;
1358 int32_t b = 0;
1359 std::tie(r, g, b) = StrToRGB(pValue->ToWideString());
1360 FX_ARGB rgb = ArgbEncode(100, r, g, b);
1361 for (int32_t i = 0; i < iSize; ++i) {
1362 CXFA_Edge* edge = border->GetEdgeIfExists(i);
1363 if (edge)
1364 edge->SetColor(rgb);
1365 }
1366
1367 return;
1368 }
1369
1370 CXFA_Edge* edge = border->GetEdgeIfExists(0);
1371 FX_ARGB color = edge ? edge->GetColor() : CXFA_Edge::kDefaultColor;
1372 int32_t a;
1373 int32_t r;
1374 int32_t g;
1375 int32_t b;
1376 std::tie(a, r, g, b) = ArgbDecode(color);
1377 pValue->SetString(
1378 WideString::Format(L"%d,%d,%d", r, g, b).UTF8Encode().AsStringView());
1379 }
1380
Script_Som_BorderWidth(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1381 void CJX_Object::Script_Som_BorderWidth(CFXJSE_Value* pValue,
1382 bool bSetting,
1383 XFA_Attribute eAttribute) {
1384 CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
1385 if (bSetting) {
1386 CXFA_Edge* edge = border->GetEdgeIfExists(0);
1387 CXFA_Measurement thickness =
1388 edge ? edge->GetMSThickness() : CXFA_Measurement(0.5, XFA_Unit::Pt);
1389 pValue->SetString(thickness.ToString().UTF8Encode().AsStringView());
1390 return;
1391 }
1392
1393 WideString wsThickness = pValue->ToWideString();
1394 for (int32_t i = 0; i < border->CountEdges(); ++i) {
1395 CXFA_Edge* edge = border->GetEdgeIfExists(i);
1396 if (edge)
1397 edge->SetMSThickness(CXFA_Measurement(wsThickness.AsStringView()));
1398 }
1399 }
1400
Script_Som_Message(CFXJSE_Value * pValue,bool bSetting,XFA_SOM_MESSAGETYPE iMessageType)1401 void CJX_Object::Script_Som_Message(CFXJSE_Value* pValue,
1402 bool bSetting,
1403 XFA_SOM_MESSAGETYPE iMessageType) {
1404 bool bNew = false;
1405 CXFA_Validate* validate = ToNode(object_.Get())->GetValidateIfExists();
1406 if (!validate) {
1407 validate = ToNode(object_.Get())->GetOrCreateValidateIfPossible();
1408 bNew = true;
1409 }
1410
1411 if (bSetting) {
1412 if (validate) {
1413 switch (iMessageType) {
1414 case XFA_SOM_ValidationMessage:
1415 validate->SetScriptMessageText(pValue->ToWideString());
1416 break;
1417 case XFA_SOM_FormatMessage:
1418 validate->SetFormatMessageText(pValue->ToWideString());
1419 break;
1420 case XFA_SOM_MandatoryMessage:
1421 validate->SetNullMessageText(pValue->ToWideString());
1422 break;
1423 default:
1424 break;
1425 }
1426 }
1427
1428 if (!bNew) {
1429 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
1430 if (!pNotify)
1431 return;
1432
1433 pNotify->AddCalcValidate(ToNode(GetXFAObject()));
1434 }
1435 return;
1436 }
1437
1438 if (!validate) {
1439 // TODO(dsinclair): Better error message?
1440 ThrowInvalidPropertyException();
1441 return;
1442 }
1443
1444 WideString wsMessage;
1445 switch (iMessageType) {
1446 case XFA_SOM_ValidationMessage:
1447 wsMessage = validate->GetScriptMessageText();
1448 break;
1449 case XFA_SOM_FormatMessage:
1450 wsMessage = validate->GetFormatMessageText();
1451 break;
1452 case XFA_SOM_MandatoryMessage:
1453 wsMessage = validate->GetNullMessageText();
1454 break;
1455 default:
1456 break;
1457 }
1458 pValue->SetString(wsMessage.UTF8Encode().AsStringView());
1459 }
1460
Script_Som_ValidationMessage(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1461 void CJX_Object::Script_Som_ValidationMessage(CFXJSE_Value* pValue,
1462 bool bSetting,
1463 XFA_Attribute eAttribute) {
1464 Script_Som_Message(pValue, bSetting, XFA_SOM_ValidationMessage);
1465 }
1466
Script_Som_MandatoryMessage(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1467 void CJX_Object::Script_Som_MandatoryMessage(CFXJSE_Value* pValue,
1468 bool bSetting,
1469 XFA_Attribute eAttribute) {
1470 Script_Som_Message(pValue, bSetting, XFA_SOM_MandatoryMessage);
1471 }
1472
Script_Field_Length(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1473 void CJX_Object::Script_Field_Length(CFXJSE_Value* pValue,
1474 bool bSetting,
1475 XFA_Attribute eAttribute) {
1476 if (bSetting) {
1477 ThrowInvalidPropertyException();
1478 return;
1479 }
1480 if (!ToNode(object_.Get())->GetWidgetAcc()) {
1481 pValue->SetInteger(0);
1482 return;
1483 }
1484 pValue->SetInteger(
1485 ToNode(object_.Get())->GetWidgetAcc()->CountChoiceListItems(true));
1486 }
1487
Script_Som_DefaultValue(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute)1488 void CJX_Object::Script_Som_DefaultValue(CFXJSE_Value* pValue,
1489 bool bSetting,
1490 XFA_Attribute /* unused */) {
1491 XFA_Element eType = ToNode(GetXFAObject())->GetElementType();
1492
1493 // TODO(dsinclair): This should look through the properties on the node to see
1494 // if defaultValue is defined and, if so, call that one. Just have to make
1495 // sure that those defaultValue calls don't call back to this one ....
1496 if (eType == XFA_Element::Field) {
1497 static_cast<CJX_Field*>(this)->defaultValue(pValue, bSetting,
1498 XFA_Attribute::Unknown);
1499 return;
1500 }
1501 if (eType == XFA_Element::Draw) {
1502 static_cast<CJX_Draw*>(this)->defaultValue(pValue, bSetting,
1503 XFA_Attribute::Unknown);
1504 return;
1505 }
1506 if (eType == XFA_Element::Boolean) {
1507 static_cast<CJX_Boolean*>(this)->defaultValue(pValue, bSetting,
1508 XFA_Attribute::Unknown);
1509 return;
1510 }
1511
1512 if (bSetting) {
1513 WideString wsNewValue;
1514 if (pValue && !(pValue->IsNull() || pValue->IsUndefined()))
1515 wsNewValue = pValue->ToWideString();
1516
1517 WideString wsFormatValue(wsNewValue);
1518 CXFA_WidgetAcc* pContainerWidgetAcc = nullptr;
1519 if (ToNode(GetXFAObject())->GetPacketType() == XFA_PacketType::Datasets) {
1520 WideString wsPicture;
1521 for (const auto& pFormNode : *(ToNode(GetXFAObject())->GetBindItems())) {
1522 if (!pFormNode || pFormNode->HasRemovedChildren())
1523 continue;
1524
1525 pContainerWidgetAcc = pFormNode->GetContainerWidgetAcc();
1526 if (pContainerWidgetAcc) {
1527 wsPicture =
1528 pContainerWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind);
1529 }
1530 if (!wsPicture.IsEmpty())
1531 break;
1532
1533 pContainerWidgetAcc = nullptr;
1534 }
1535 } else if (ToNode(GetXFAObject())->GetPacketType() ==
1536 XFA_PacketType::Form) {
1537 pContainerWidgetAcc = ToNode(GetXFAObject())->GetContainerWidgetAcc();
1538 }
1539
1540 if (pContainerWidgetAcc)
1541 wsFormatValue = pContainerWidgetAcc->GetFormatDataValue(wsNewValue);
1542
1543 SetContent(wsNewValue, wsFormatValue, true, true, true);
1544 return;
1545 }
1546
1547 WideString content = GetContent(true);
1548 if (content.IsEmpty() && eType != XFA_Element::Text &&
1549 eType != XFA_Element::SubmitUrl) {
1550 pValue->SetNull();
1551 } else if (eType == XFA_Element::Integer) {
1552 pValue->SetInteger(FXSYS_wtoi(content.c_str()));
1553 } else if (eType == XFA_Element::Float || eType == XFA_Element::Decimal) {
1554 CFX_Decimal decimal(content.AsStringView());
1555 pValue->SetFloat((float)(double)decimal);
1556 } else {
1557 pValue->SetString(content.UTF8Encode().AsStringView());
1558 }
1559 }
1560
Script_Som_DefaultValue_Read(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1561 void CJX_Object::Script_Som_DefaultValue_Read(CFXJSE_Value* pValue,
1562 bool bSetting,
1563 XFA_Attribute eAttribute) {
1564 if (bSetting) {
1565 ThrowInvalidPropertyException();
1566 return;
1567 }
1568
1569 WideString content = GetContent(true);
1570 if (content.IsEmpty()) {
1571 pValue->SetNull();
1572 return;
1573 }
1574 pValue->SetString(content.UTF8Encode().AsStringView());
1575 }
1576
Script_Som_DataNode(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1577 void CJX_Object::Script_Som_DataNode(CFXJSE_Value* pValue,
1578 bool bSetting,
1579 XFA_Attribute eAttribute) {
1580 if (bSetting) {
1581 ThrowInvalidPropertyException();
1582 return;
1583 }
1584
1585 CXFA_Node* pDataNode = ToNode(GetXFAObject())->GetBindData();
1586 if (!pDataNode) {
1587 pValue->SetNull();
1588 return;
1589 }
1590
1591 pValue->Assign(
1592 GetDocument()->GetScriptContext()->GetJSValueFromMap(pDataNode));
1593 }
1594
Script_Som_Mandatory(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1595 void CJX_Object::Script_Som_Mandatory(CFXJSE_Value* pValue,
1596 bool bSetting,
1597 XFA_Attribute eAttribute) {
1598 CXFA_Validate* validate =
1599 ToNode(object_.Get())->GetOrCreateValidateIfPossible();
1600 if (!validate)
1601 return;
1602
1603 if (bSetting) {
1604 validate->SetNullTest(pValue->ToWideString());
1605 return;
1606 }
1607
1608 WideString str = CXFA_Node::AttributeEnumToName(validate->GetNullTest());
1609 pValue->SetString(str.UTF8Encode().AsStringView());
1610 }
1611
Script_Som_InstanceIndex(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1612 void CJX_Object::Script_Som_InstanceIndex(CFXJSE_Value* pValue,
1613 bool bSetting,
1614 XFA_Attribute eAttribute) {
1615 if (!bSetting) {
1616 pValue->SetInteger(Subform_and_SubformSet_InstanceIndex());
1617 return;
1618 }
1619
1620 int32_t iTo = pValue->ToInteger();
1621 int32_t iFrom = Subform_and_SubformSet_InstanceIndex();
1622 CXFA_Node* pManagerNode = nullptr;
1623 for (CXFA_Node* pNode = ToNode(GetXFAObject())->GetPrevSibling(); pNode;
1624 pNode = pNode->GetPrevSibling()) {
1625 if (pNode->GetElementType() == XFA_Element::InstanceManager) {
1626 pManagerNode = pNode;
1627 break;
1628 }
1629 }
1630 if (!pManagerNode)
1631 return;
1632
1633 auto* mgr = static_cast<CJX_InstanceManager*>(pManagerNode->JSObject());
1634 mgr->MoveInstance(iTo, iFrom);
1635 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
1636 if (!pNotify)
1637 return;
1638
1639 CXFA_Node* pToInstance = pManagerNode->GetItemIfExists(iTo);
1640 if (pToInstance && pToInstance->GetElementType() == XFA_Element::Subform) {
1641 pNotify->RunSubformIndexChange(pToInstance);
1642 }
1643
1644 CXFA_Node* pFromInstance = pManagerNode->GetItemIfExists(iFrom);
1645 if (pFromInstance &&
1646 pFromInstance->GetElementType() == XFA_Element::Subform) {
1647 pNotify->RunSubformIndexChange(pFromInstance);
1648 }
1649 }
1650
Script_Subform_InstanceManager(CFXJSE_Value * pValue,bool bSetting,XFA_AttributeEnum eAttribute)1651 void CJX_Object::Script_Subform_InstanceManager(CFXJSE_Value* pValue,
1652 bool bSetting,
1653 XFA_AttributeEnum eAttribute) {
1654 if (bSetting) {
1655 ThrowInvalidPropertyException();
1656 return;
1657 }
1658
1659 WideString wsName = GetCData(XFA_Attribute::Name);
1660 CXFA_Node* pInstanceMgr = nullptr;
1661 for (CXFA_Node* pNode = ToNode(GetXFAObject())->GetPrevSibling(); pNode;
1662 pNode = pNode->GetPrevSibling()) {
1663 if (pNode->GetElementType() == XFA_Element::InstanceManager) {
1664 WideString wsInstMgrName =
1665 pNode->JSObject()->GetCData(XFA_Attribute::Name);
1666 if (wsInstMgrName.GetLength() >= 1 && wsInstMgrName[0] == '_' &&
1667 wsInstMgrName.Right(wsInstMgrName.GetLength() - 1) == wsName) {
1668 pInstanceMgr = pNode;
1669 }
1670 break;
1671 }
1672 }
1673 if (!pInstanceMgr) {
1674 pValue->SetNull();
1675 return;
1676 }
1677
1678 pValue->Assign(
1679 GetDocument()->GetScriptContext()->GetJSValueFromMap(pInstanceMgr));
1680 }
1681
Script_SubmitFormat_Mode(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1682 void CJX_Object::Script_SubmitFormat_Mode(CFXJSE_Value* pValue,
1683 bool bSetting,
1684 XFA_Attribute eAttribute) {}
1685
Script_Form_Checksum(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1686 void CJX_Object::Script_Form_Checksum(CFXJSE_Value* pValue,
1687 bool bSetting,
1688 XFA_Attribute eAttribute) {
1689 if (bSetting) {
1690 SetAttribute(XFA_Attribute::Checksum, pValue->ToWideString().AsStringView(),
1691 false);
1692 return;
1693 }
1694
1695 Optional<WideString> checksum = TryAttribute(XFA_Attribute::Checksum, false);
1696 pValue->SetString(checksum ? checksum->UTF8Encode().AsStringView() : "");
1697 }
1698
Script_ExclGroup_ErrorText(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)1699 void CJX_Object::Script_ExclGroup_ErrorText(CFXJSE_Value* pValue,
1700 bool bSetting,
1701 XFA_Attribute eAttribute) {
1702 if (bSetting)
1703 ThrowInvalidPropertyException();
1704 }
1705