• 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_field.h"
8 
9 #include <vector>
10 
11 #include "fxjs/cfx_v8.h"
12 #include "fxjs/js_resources.h"
13 #include "fxjs/xfa/cfxjse_value.h"
14 #include "xfa/fgas/crt/cfgas_decimal.h"
15 #include "xfa/fxfa/cxfa_eventparam.h"
16 #include "xfa/fxfa/cxfa_ffnotify.h"
17 #include "xfa/fxfa/fxfa.h"
18 #include "xfa/fxfa/parser/cxfa_document.h"
19 #include "xfa/fxfa/parser/cxfa_field.h"
20 #include "xfa/fxfa/parser/cxfa_value.h"
21 
22 const CJX_MethodSpec CJX_Field::MethodSpecs[] = {
23     {"addItem", addItem_static},
24     {"boundItem", boundItem_static},
25     {"clearItems", clearItems_static},
26     {"deleteItem", deleteItem_static},
27     {"execCalculate", execCalculate_static},
28     {"execEvent", execEvent_static},
29     {"execInitialize", execInitialize_static},
30     {"execValidate", execValidate_static},
31     {"getDisplayItem", getDisplayItem_static},
32     {"getItemState", getItemState_static},
33     {"getSaveItem", getSaveItem_static},
34     {"setItemState", setItemState_static}};
35 
CJX_Field(CXFA_Field * field)36 CJX_Field::CJX_Field(CXFA_Field* field) : CJX_Container(field) {
37   DefineMethods(MethodSpecs);
38 }
39 
~CJX_Field()40 CJX_Field::~CJX_Field() {}
41 
DynamicTypeIs(TypeTag eType) const42 bool CJX_Field::DynamicTypeIs(TypeTag eType) const {
43   return eType == static_type__ || ParentType__::DynamicTypeIs(eType);
44 }
45 
clearItems(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)46 CJS_Result CJX_Field::clearItems(
47     CFX_V8* runtime,
48     const std::vector<v8::Local<v8::Value>>& params) {
49   CXFA_Node* node = GetXFANode();
50   if (node->IsWidgetReady())
51     node->DeleteItem(-1, true, false);
52   return CJS_Result::Success();
53 }
54 
execEvent(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)55 CJS_Result CJX_Field::execEvent(
56     CFX_V8* runtime,
57     const std::vector<v8::Local<v8::Value>>& params) {
58   if (params.size() != 1)
59     return CJS_Result::Failure(JSMessage::kParamError);
60 
61   WideString eventString = runtime->ToWideString(params[0]);
62   XFA_EventError iRet =
63       execSingleEventByName(eventString.AsStringView(), XFA_Element::Field);
64   if (!eventString.EqualsASCII("validate"))
65     return CJS_Result::Success();
66 
67   return CJS_Result::Success(
68       runtime->NewBoolean(iRet != XFA_EventError::kError));
69 }
70 
execInitialize(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)71 CJS_Result CJX_Field::execInitialize(
72     CFX_V8* runtime,
73     const std::vector<v8::Local<v8::Value>>& params) {
74   if (!params.empty())
75     return CJS_Result::Failure(JSMessage::kParamError);
76 
77   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
78   if (pNotify) {
79     pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize, false,
80                                   false);
81   }
82   return CJS_Result::Success();
83 }
84 
deleteItem(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)85 CJS_Result CJX_Field::deleteItem(
86     CFX_V8* runtime,
87     const std::vector<v8::Local<v8::Value>>& params) {
88   if (params.size() != 1)
89     return CJS_Result::Failure(JSMessage::kParamError);
90 
91   CXFA_Node* node = GetXFANode();
92   if (!node->IsWidgetReady())
93     return CJS_Result::Success();
94 
95   bool bValue = node->DeleteItem(runtime->ToInt32(params[0]), true, true);
96   return CJS_Result::Success(runtime->NewBoolean(bValue));
97 }
98 
getSaveItem(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)99 CJS_Result CJX_Field::getSaveItem(
100     CFX_V8* runtime,
101     const std::vector<v8::Local<v8::Value>>& params) {
102   if (params.size() != 1)
103     return CJS_Result::Failure(JSMessage::kParamError);
104 
105   int32_t iIndex = runtime->ToInt32(params[0]);
106   if (iIndex < 0)
107     return CJS_Result::Success(runtime->NewNull());
108 
109   CXFA_Node* node = GetXFANode();
110   if (!node->IsWidgetReady())
111     return CJS_Result::Success(runtime->NewNull());
112 
113   Optional<WideString> value = node->GetChoiceListItem(iIndex, true);
114   if (!value)
115     return CJS_Result::Success(runtime->NewNull());
116 
117   return CJS_Result::Success(
118       runtime->NewString(value->ToUTF8().AsStringView()));
119 }
120 
boundItem(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)121 CJS_Result CJX_Field::boundItem(
122     CFX_V8* runtime,
123     const std::vector<v8::Local<v8::Value>>& params) {
124   if (params.size() != 1)
125     return CJS_Result::Failure(JSMessage::kParamError);
126 
127   CXFA_Node* node = GetXFANode();
128   if (!node->IsWidgetReady())
129     return CJS_Result::Success();
130 
131   WideString value = runtime->ToWideString(params[0]);
132   WideString boundValue = node->GetItemValue(value.AsStringView());
133   return CJS_Result::Success(
134       runtime->NewString(boundValue.ToUTF8().AsStringView()));
135 }
136 
getItemState(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)137 CJS_Result CJX_Field::getItemState(
138     CFX_V8* runtime,
139     const std::vector<v8::Local<v8::Value>>& params) {
140   if (params.size() != 1)
141     return CJS_Result::Failure(JSMessage::kParamError);
142 
143   CXFA_Node* node = GetXFANode();
144   if (!node->IsWidgetReady())
145     return CJS_Result::Success();
146 
147   int32_t state = node->GetItemState(runtime->ToInt32(params[0]));
148   return CJS_Result::Success(runtime->NewBoolean(state != 0));
149 }
150 
execCalculate(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)151 CJS_Result CJX_Field::execCalculate(
152     CFX_V8* runtime,
153     const std::vector<v8::Local<v8::Value>>& params) {
154   if (!params.empty())
155     return CJS_Result::Failure(JSMessage::kParamError);
156 
157   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
158   if (pNotify) {
159     pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate, false,
160                                   false);
161   }
162   return CJS_Result::Success();
163 }
164 
getDisplayItem(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)165 CJS_Result CJX_Field::getDisplayItem(
166     CFX_V8* runtime,
167     const std::vector<v8::Local<v8::Value>>& params) {
168   if (params.size() != 1)
169     return CJS_Result::Failure(JSMessage::kParamError);
170 
171   int32_t iIndex = runtime->ToInt32(params[0]);
172   if (iIndex < 0)
173     return CJS_Result::Success(runtime->NewNull());
174 
175   CXFA_Node* node = GetXFANode();
176   if (!node->IsWidgetReady())
177     return CJS_Result::Success(runtime->NewNull());
178 
179   Optional<WideString> value = node->GetChoiceListItem(iIndex, false);
180   if (!value)
181     return CJS_Result::Success(runtime->NewNull());
182 
183   return CJS_Result::Success(
184       runtime->NewString(value->ToUTF8().AsStringView()));
185 }
186 
setItemState(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)187 CJS_Result CJX_Field::setItemState(
188     CFX_V8* runtime,
189     const std::vector<v8::Local<v8::Value>>& params) {
190   if (params.size() != 2)
191     return CJS_Result::Failure(JSMessage::kParamError);
192 
193   CXFA_Node* node = GetXFANode();
194   if (!node->IsWidgetReady())
195     return CJS_Result::Success();
196 
197   int32_t iIndex = runtime->ToInt32(params[0]);
198   if (runtime->ToInt32(params[1]) != 0) {
199     node->SetItemState(iIndex, true, true, true, true);
200     return CJS_Result::Success();
201   }
202   if (node->GetItemState(iIndex))
203     node->SetItemState(iIndex, false, true, true, true);
204 
205   return CJS_Result::Success();
206 }
207 
addItem(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)208 CJS_Result CJX_Field::addItem(CFX_V8* runtime,
209                               const std::vector<v8::Local<v8::Value>>& params) {
210   if (params.size() != 1 && params.size() != 2)
211     return CJS_Result::Failure(JSMessage::kParamError);
212 
213   CXFA_Node* node = GetXFANode();
214   if (!node->IsWidgetReady())
215     return CJS_Result::Success();
216 
217   WideString label;
218   if (params.size() >= 1)
219     label = runtime->ToWideString(params[0]);
220 
221   WideString value;
222   if (params.size() >= 2)
223     value = runtime->ToWideString(params[1]);
224 
225   node->InsertItem(label, value, true);
226   return CJS_Result::Success();
227 }
228 
execValidate(CFX_V8 * runtime,const std::vector<v8::Local<v8::Value>> & params)229 CJS_Result CJX_Field::execValidate(
230     CFX_V8* runtime,
231     const std::vector<v8::Local<v8::Value>>& params) {
232   if (!params.empty())
233     return CJS_Result::Failure(JSMessage::kParamError);
234 
235   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
236   if (!pNotify)
237     return CJS_Result::Success(runtime->NewBoolean(false));
238 
239   XFA_EventError iRet = pNotify->ExecEventByDeepFirst(
240       GetXFANode(), XFA_EVENT_Validate, false, false);
241   return CJS_Result::Success(
242       runtime->NewBoolean(iRet != XFA_EventError::kError));
243 }
244 
defaultValue(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)245 void CJX_Field::defaultValue(CFXJSE_Value* pValue,
246                              bool bSetting,
247                              XFA_Attribute eAttribute) {
248   CXFA_Node* xfaNode = GetXFANode();
249   if (!xfaNode->IsWidgetReady())
250     return;
251 
252   if (bSetting) {
253     if (pValue) {
254       xfaNode->SetPreNull(xfaNode->IsNull());
255       xfaNode->SetIsNull(pValue->IsNull());
256     }
257 
258     WideString wsNewText;
259     if (pValue && !(pValue->IsNull() || pValue->IsUndefined()))
260       wsNewText = pValue->ToWideString();
261     if (xfaNode->GetUIChildNode()->GetElementType() == XFA_Element::NumericEdit)
262       wsNewText = xfaNode->NumericLimit(wsNewText);
263 
264     CXFA_Node* pContainerNode = xfaNode->GetContainerNode();
265     WideString wsFormatText(wsNewText);
266     if (pContainerNode)
267       wsFormatText = pContainerNode->GetFormatDataValue(wsNewText);
268 
269     SetContent(wsNewText, wsFormatText, true, true, true);
270     return;
271   }
272 
273   WideString content = GetContent(true);
274   if (content.IsEmpty()) {
275     pValue->SetNull();
276     return;
277   }
278 
279   CXFA_Node* formValue = xfaNode->GetFormValueIfExists();
280   CXFA_Node* pNode = formValue ? formValue->GetFirstChild() : nullptr;
281   if (pNode && pNode->GetElementType() == XFA_Element::Decimal) {
282     if (xfaNode->GetUIChildNode()->GetElementType() ==
283             XFA_Element::NumericEdit &&
284         (pNode->JSObject()->GetInteger(XFA_Attribute::FracDigits) == -1)) {
285       pValue->SetString(content.ToUTF8().AsStringView());
286     } else {
287       CFGAS_Decimal decimal(content.AsStringView());
288       pValue->SetFloat(decimal.ToFloat());
289     }
290   } else if (pNode && pNode->GetElementType() == XFA_Element::Integer) {
291     pValue->SetInteger(FXSYS_wtoi(content.c_str()));
292   } else if (pNode && pNode->GetElementType() == XFA_Element::Boolean) {
293     pValue->SetBoolean(FXSYS_wtoi(content.c_str()) != 0);
294   } else if (pNode && pNode->GetElementType() == XFA_Element::Float) {
295     CFGAS_Decimal decimal(content.AsStringView());
296     pValue->SetFloat(decimal.ToFloat());
297   } else {
298     pValue->SetString(content.ToUTF8().AsStringView());
299   }
300 }
301 
editValue(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)302 void CJX_Field::editValue(CFXJSE_Value* pValue,
303                           bool bSetting,
304                           XFA_Attribute eAttribute) {
305   CXFA_Node* node = GetXFANode();
306   if (!node->IsWidgetReady())
307     return;
308 
309   if (bSetting) {
310     node->SetValue(XFA_VALUEPICTURE_Edit, pValue->ToWideString());
311     return;
312   }
313   pValue->SetString(
314       node->GetValue(XFA_VALUEPICTURE_Edit).ToUTF8().AsStringView());
315 }
316 
formatMessage(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)317 void CJX_Field::formatMessage(CFXJSE_Value* pValue,
318                               bool bSetting,
319                               XFA_Attribute eAttribute) {
320   ScriptSomMessage(pValue, bSetting, XFA_SOM_FormatMessage);
321 }
322 
formattedValue(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)323 void CJX_Field::formattedValue(CFXJSE_Value* pValue,
324                                bool bSetting,
325                                XFA_Attribute eAttribute) {
326   CXFA_Node* node = GetXFANode();
327   if (!node->IsWidgetReady())
328     return;
329 
330   if (bSetting) {
331     node->SetValue(XFA_VALUEPICTURE_Display, pValue->ToWideString());
332     return;
333   }
334   pValue->SetString(
335       node->GetValue(XFA_VALUEPICTURE_Display).ToUTF8().AsStringView());
336 }
337 
length(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)338 void CJX_Field::length(CFXJSE_Value* pValue,
339                        bool bSetting,
340                        XFA_Attribute eAttribute) {
341   if (bSetting) {
342     ThrowInvalidPropertyException();
343     return;
344   }
345 
346   CXFA_Node* node = GetXFANode();
347   if (!node->IsWidgetReady()) {
348     pValue->SetInteger(0);
349     return;
350   }
351   pValue->SetInteger(node->CountChoiceListItems(true));
352 }
353 
parentSubform(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)354 void CJX_Field::parentSubform(CFXJSE_Value* pValue,
355                               bool bSetting,
356                               XFA_Attribute eAttribute) {
357   if (bSetting) {
358     ThrowInvalidPropertyException();
359     return;
360   }
361   pValue->SetNull();
362 }
363 
selectedIndex(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)364 void CJX_Field::selectedIndex(CFXJSE_Value* pValue,
365                               bool bSetting,
366                               XFA_Attribute eAttribute) {
367   CXFA_Node* node = GetXFANode();
368   if (!node->IsWidgetReady())
369     return;
370 
371   if (!bSetting) {
372     pValue->SetInteger(node->GetSelectedItem(0));
373     return;
374   }
375 
376   int32_t iIndex = pValue->ToInteger();
377   if (iIndex == -1) {
378     node->ClearAllSelections();
379     return;
380   }
381 
382   node->SetItemState(iIndex, true, true, true, true);
383 }
384 
rawValue(CFXJSE_Value * pValue,bool bSetting,XFA_Attribute eAttribute)385 void CJX_Field::rawValue(CFXJSE_Value* pValue,
386                          bool bSetting,
387                          XFA_Attribute eAttribute) {
388   defaultValue(pValue, bSetting, eAttribute);
389 }
390