• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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