• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 "xfa/fxfa/fm2js/xfa_simpleexpression.h"
8 
9 #include <utility>
10 
11 #include "core/fxcrt/fx_ext.h"
12 
13 namespace {
14 
15 const FX_WCHAR* const gs_lpStrExpFuncName[] = {
16     L"foxit_xfa_formcalc_runtime.assign_value_operator",
17     L"foxit_xfa_formcalc_runtime.logical_or_operator",
18     L"foxit_xfa_formcalc_runtime.logical_and_operator",
19     L"foxit_xfa_formcalc_runtime.equality_operator",
20     L"foxit_xfa_formcalc_runtime.notequality_operator",
21     L"foxit_xfa_formcalc_runtime.less_operator",
22     L"foxit_xfa_formcalc_runtime.lessequal_operator",
23     L"foxit_xfa_formcalc_runtime.greater_operator",
24     L"foxit_xfa_formcalc_runtime.greaterequal_operator",
25     L"foxit_xfa_formcalc_runtime.plus_operator",
26     L"foxit_xfa_formcalc_runtime.minus_operator",
27     L"foxit_xfa_formcalc_runtime.multiple_operator",
28     L"foxit_xfa_formcalc_runtime.divide_operator",
29     L"foxit_xfa_formcalc_runtime.positive_operator",
30     L"foxit_xfa_formcalc_runtime.negative_operator",
31     L"foxit_xfa_formcalc_runtime.logical_not_operator",
32     L"foxit_xfa_formcalc_runtime.",
33     L"foxit_xfa_formcalc_runtime.dot_accessor",
34     L"foxit_xfa_formcalc_runtime.dotdot_accessor",
35     L"foxit_xfa_formcalc_runtime.concat_fm_object",
36     L"foxit_xfa_formcalc_runtime.is_fm_object",
37     L"foxit_xfa_formcalc_runtime.is_fm_array",
38     L"foxit_xfa_formcalc_runtime.get_fm_value",
39     L"foxit_xfa_formcalc_runtime.get_fm_jsobj",
40     L"foxit_xfa_formcalc_runtime.fm_var_filter",
41 };
42 
43 struct XFA_FMBuildInFunc {
44   uint32_t m_uHash;
45   const FX_WCHAR* m_buildinfunc;
46 };
47 
48 const XFA_FMBuildInFunc g_BuildInFuncs[] = {
49     {0x0001f1f5, L"At"},           {0x00020b9c, L"FV"},
50     {0x00021aef, L"If"},           {0x00023ee6, L"PV"},
51     {0x04b5c9ee, L"Encode"},       {0x08e96685, L"DateFmt"},
52     {0x09f99db6, L"Abs"},          {0x09f9e583, L"Apr"},
53     {0x09fa043e, L"Avg"},          {0x0a9782a0, L"Get"},
54     {0x0b1b09df, L"Len"},          {0x0b3543a6, L"Max"},
55     {0x0b356ca4, L"Min"},          {0x0b358b60, L"Mod"},
56     {0x0b4fded4, L"NPV"},          {0x0b846bf1, L"Pmt"},
57     {0x0b8494f9, L"Put"},          {0x0bb8df5d, L"Ref"},
58     {0x0bd37a99, L"Str"},          {0x0bd37fb5, L"Sum"},
59     {0x1048469b, L"Cterm"},        {0x11e03660, L"Exists"},
60     {0x126236e6, L"Post"},         {0x127c6661, L"PPmt"},
61     {0x193ade3e, L"Right"},        {0x1ec8ab2c, L"Rate"},
62     {0x20e476dc, L"IsoTime2Num"},  {0x23eb6816, L"TimeFmt"},
63     {0x24fb17b0, L"LocalDateFmt"}, {0x28dee6e9, L"Format"},
64     {0x2d0890b8, L"Term"},         {0x2d71b00f, L"Time"},
65     {0x2f890fb1, L"Num2Time"},     {0x3767511d, L"Ceil"},
66     {0x3ffd1941, L"LocalTimeFmt"}, {0x442f68c8, L"Round"},
67     {0x46fd1128, L"Eval"},         {0x4d629440, L"Date2Num"},
68     {0x4dcf25f8, L"Concat"},       {0x4e00255d, L"UnitValue"},
69     {0x55a5cc29, L"Lower"},        {0x5e43e04c, L"WordNum"},
70     {0x620ce6ba, L"Ipmt"},         {0x6f544d49, L"Count"},
71     {0x7e241013, L"Within"},       {0x9b9a6e2b, L"IsoDate2Num"},
72     {0xb2c941c2, L"UnitType"},     {0xb598a1f7, L"Uuid"},
73     {0xbde9abde, L"Date"},         {0xc0010b80, L"Num2Date"},
74     {0xc1f6144c, L"Upper"},        {0xc44028f7, L"Oneof"},
75     {0xc62c1b2c, L"Space"},        {0xd0ff50f9, L"HasValue"},
76     {0xd1537042, L"Floor"},        {0xd2ac9cf1, L"Time2Num"},
77     {0xd907aee5, L"Num2GMTime"},   {0xdf24f7c4, L"Decode"},
78     {0xe2664803, L"Substr"},       {0xe3e7b528, L"Stuff"},
79     {0xe6792d4e, L"Rtrim"},        {0xe8c23f5b, L"Parse"},
80     {0xea18d121, L"Choose"},       {0xebfef69c, L"Replace"},
81     {0xf5ad782b, L"Left"},         {0xf7bb2248, L"Ltrim"},
82 };
83 
84 struct XFA_FMSOMMethod {
85   uint32_t m_uHash;
86   const FX_WCHAR* m_wsSomMethodName;
87   uint32_t m_dParameters;
88 };
89 const XFA_FMSOMMethod gs_FMSomMethods[] = {
90     {0x00000068, L"h", 0x01},
91     {0x00000077, L"w", 0x01},
92     {0x00000078, L"x", 0x01},
93     {0x00000079, L"y", 0x01},
94     {0x05eb5b0f, L"pageSpan", 0x01},
95     {0x10f1b1bd, L"page", 0x01},
96     {0x3bf1c2a5, L"absPageSpan", 0x01},
97     {0x3c752495, L"verify", 0x0d},
98     {0x44c352ad, L"formNodes", 0x01},
99     {0x5775c2cc, L"absPageInBatch", 0x01},
100     {0x5ee00996, L"setElement", 0x01},
101     {0x7033bfd5, L"insert", 0x03},
102     {0x8c5feb32, L"sheetInBatch", 0x01},
103     {0x8f3a8379, L"sheet", 0x01},
104     {0x92dada4f, L"saveFilteredXML", 0x01},
105     {0x9cab7cae, L"remove", 0x01},
106     {0xa68635f1, L"sign", 0x61},
107     {0xaac241c8, L"isRecordGroup", 0x01},
108     {0xd8ed1467, L"clear", 0x01},
109     {0xda12e518, L"append", 0x01},
110     {0xe74f0653, L"absPage", 0x01},
111 };
112 
113 }  // namespace
114 
XFA_FM_EXPTypeToString(XFA_FM_SimpleExpressionType simpleExpType)115 CFX_WideStringC XFA_FM_EXPTypeToString(
116     XFA_FM_SimpleExpressionType simpleExpType) {
117   return gs_lpStrExpFuncName[simpleExpType];
118 }
119 
CXFA_FMSimpleExpression(uint32_t line,XFA_FM_TOKEN op)120 CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op)
121     : m_line(line), m_op(op) {}
122 
ToJavaScript(CFX_WideTextBuf & javascript)123 void CXFA_FMSimpleExpression::ToJavaScript(CFX_WideTextBuf& javascript) {}
124 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)125 void CXFA_FMSimpleExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {}
126 
GetOperatorToken() const127 XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const {
128   return m_op;
129 }
130 
CXFA_FMNullExpression(uint32_t line)131 CXFA_FMNullExpression::CXFA_FMNullExpression(uint32_t line)
132     : CXFA_FMSimpleExpression(line, TOKnull) {}
133 
ToJavaScript(CFX_WideTextBuf & javascript)134 void CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
135   javascript << L"null";
136 }
137 
CXFA_FMNumberExpression(uint32_t line,CFX_WideStringC wsNumber)138 CXFA_FMNumberExpression::CXFA_FMNumberExpression(uint32_t line,
139                                                  CFX_WideStringC wsNumber)
140     : CXFA_FMSimpleExpression(line, TOKnumber), m_wsNumber(wsNumber) {}
141 
~CXFA_FMNumberExpression()142 CXFA_FMNumberExpression::~CXFA_FMNumberExpression() {}
143 
ToJavaScript(CFX_WideTextBuf & javascript)144 void CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
145   javascript << m_wsNumber;
146 }
147 
CXFA_FMStringExpression(uint32_t line,CFX_WideStringC wsString)148 CXFA_FMStringExpression::CXFA_FMStringExpression(uint32_t line,
149                                                  CFX_WideStringC wsString)
150     : CXFA_FMSimpleExpression(line, TOKstring), m_wsString(wsString) {}
151 
~CXFA_FMStringExpression()152 CXFA_FMStringExpression::~CXFA_FMStringExpression() {}
153 
ToJavaScript(CFX_WideTextBuf & javascript)154 void CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
155   CFX_WideString tempStr(m_wsString);
156   if (tempStr.GetLength() > 2) {
157     javascript.AppendChar(L'\"');
158     FX_WCHAR oneChar;
159     for (int16_t i = 1; i < tempStr.GetLength() - 1; i++) {
160       oneChar = tempStr[i];
161       switch (oneChar) {
162         case L'\"': {
163           i++;
164           javascript << L"\\\"";
165         } break;
166         case 0x0d:
167           break;
168         case 0x0a: {
169           javascript << L"\\n";
170         } break;
171         default: { javascript.AppendChar(oneChar); } break;
172       }
173     }
174     javascript.AppendChar(L'\"');
175   } else {
176     javascript << tempStr;
177   }
178 }
179 
CXFA_FMIdentifierExpression(uint32_t line,CFX_WideStringC wsIdentifier)180 CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression(
181     uint32_t line,
182     CFX_WideStringC wsIdentifier)
183     : CXFA_FMSimpleExpression(line, TOKidentifier),
184       m_wsIdentifier(wsIdentifier) {}
185 
~CXFA_FMIdentifierExpression()186 CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() {}
187 
ToJavaScript(CFX_WideTextBuf & javascript)188 void CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
189   CFX_WideString tempStr(m_wsIdentifier);
190   if (tempStr == L"$") {
191     tempStr = L"this";
192   } else if (tempStr == L"!") {
193     tempStr = L"xfa.datasets";
194   } else if (tempStr == L"$data") {
195     tempStr = L"xfa.datasets.data";
196   } else if (tempStr == L"$event") {
197     tempStr = L"xfa.event";
198   } else if (tempStr == L"$form") {
199     tempStr = L"xfa.form";
200   } else if (tempStr == L"$host") {
201     tempStr = L"xfa.host";
202   } else if (tempStr == L"$layout") {
203     tempStr = L"xfa.layout";
204   } else if (tempStr == L"$template") {
205     tempStr = L"xfa.template";
206   } else if (tempStr[0] == L'!') {
207     tempStr = EXCLAMATION_IN_IDENTIFIER + tempStr.Mid(1);
208   }
209   javascript << tempStr;
210 }
211 
CXFA_FMUnaryExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp)212 CXFA_FMUnaryExpression::CXFA_FMUnaryExpression(
213     uint32_t line,
214     XFA_FM_TOKEN op,
215     std::unique_ptr<CXFA_FMSimpleExpression> pExp)
216     : CXFA_FMSimpleExpression(line, op), m_pExp(std::move(pExp)) {}
217 
~CXFA_FMUnaryExpression()218 CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() {}
219 
ToJavaScript(CFX_WideTextBuf & javascript)220 void CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf& javascript) {}
221 
CXFA_FMBinExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)222 CXFA_FMBinExpression::CXFA_FMBinExpression(
223     uint32_t line,
224     XFA_FM_TOKEN op,
225     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
226     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
227     : CXFA_FMSimpleExpression(line, op),
228       m_pExp1(std::move(pExp1)),
229       m_pExp2(std::move(pExp2)) {}
230 
~CXFA_FMBinExpression()231 CXFA_FMBinExpression::~CXFA_FMBinExpression() {}
232 
ToJavaScript(CFX_WideTextBuf & javascript)233 void CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf& javascript) {}
234 
CXFA_FMAssignExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)235 CXFA_FMAssignExpression::CXFA_FMAssignExpression(
236     uint32_t line,
237     XFA_FM_TOKEN op,
238     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
239     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
240     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
241 
ToJavaScript(CFX_WideTextBuf & javascript)242 void CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
243   javascript << L"if (";
244   javascript << gs_lpStrExpFuncName[ISFMOBJECT];
245   javascript << L"(";
246   m_pExp1->ToJavaScript(javascript);
247   javascript << L"))\n{\n";
248   javascript << gs_lpStrExpFuncName[ASSIGN];
249   javascript << L"(";
250   m_pExp1->ToJavaScript(javascript);
251   javascript << L", ";
252   m_pExp2->ToJavaScript(javascript);
253   javascript << L");\n}\n";
254   CFX_WideTextBuf tempExp1;
255   m_pExp1->ToJavaScript(tempExp1);
256   if (m_pExp1->GetOperatorToken() == TOKidentifier &&
257       tempExp1.AsStringC() != L"this") {
258     javascript << L"else\n{\n";
259     javascript << tempExp1;
260     javascript << L" = ";
261     javascript << gs_lpStrExpFuncName[ASSIGN];
262     javascript << L"(";
263     m_pExp1->ToJavaScript(javascript);
264     javascript << L", ";
265     m_pExp2->ToJavaScript(javascript);
266     javascript << L");\n}\n";
267   }
268 }
269 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)270 void CXFA_FMAssignExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
271   javascript << L"if (";
272   javascript << gs_lpStrExpFuncName[ISFMOBJECT];
273   javascript << L"(";
274   m_pExp1->ToJavaScript(javascript);
275   javascript << L"))\n{\n";
276   javascript << RUNTIMEFUNCTIONRETURNVALUE;
277   javascript << L" = ";
278   javascript << gs_lpStrExpFuncName[ASSIGN];
279   javascript << L"(";
280   m_pExp1->ToJavaScript(javascript);
281   javascript << L", ";
282   m_pExp2->ToJavaScript(javascript);
283   javascript << L");\n}\n";
284   CFX_WideTextBuf tempExp1;
285   m_pExp1->ToJavaScript(tempExp1);
286   if (m_pExp1->GetOperatorToken() == TOKidentifier &&
287       tempExp1.AsStringC() != L"this") {
288     javascript << L"else\n{\n";
289     javascript << RUNTIMEFUNCTIONRETURNVALUE;
290     javascript << L" = ";
291     javascript << tempExp1;
292     javascript << L" = ";
293     javascript << gs_lpStrExpFuncName[ASSIGN];
294     javascript << L"(";
295     m_pExp1->ToJavaScript(javascript);
296     javascript << L", ";
297     m_pExp2->ToJavaScript(javascript);
298     javascript << L");\n}\n";
299   }
300 }
301 
CXFA_FMLogicalOrExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)302 CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression(
303     uint32_t line,
304     XFA_FM_TOKEN op,
305     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
306     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
307     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
308 
ToJavaScript(CFX_WideTextBuf & javascript)309 void CXFA_FMLogicalOrExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
310   javascript << gs_lpStrExpFuncName[LOGICALOR];
311   javascript << L"(";
312   m_pExp1->ToJavaScript(javascript);
313   javascript << L", ";
314   m_pExp2->ToJavaScript(javascript);
315   javascript << L")";
316 }
317 
CXFA_FMLogicalAndExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)318 CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression(
319     uint32_t line,
320     XFA_FM_TOKEN op,
321     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
322     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
323     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
324 
ToJavaScript(CFX_WideTextBuf & javascript)325 void CXFA_FMLogicalAndExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
326   javascript << gs_lpStrExpFuncName[LOGICALAND];
327   javascript << L"(";
328   m_pExp1->ToJavaScript(javascript);
329   javascript << L", ";
330   m_pExp2->ToJavaScript(javascript);
331   javascript << L")";
332 }
333 
CXFA_FMEqualityExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)334 CXFA_FMEqualityExpression::CXFA_FMEqualityExpression(
335     uint32_t line,
336     XFA_FM_TOKEN op,
337     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
338     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
339     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
340 
ToJavaScript(CFX_WideTextBuf & javascript)341 void CXFA_FMEqualityExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
342   switch (m_op) {
343     case TOKeq:
344     case TOKkseq:
345       javascript << gs_lpStrExpFuncName[EQUALITY];
346       break;
347     case TOKne:
348     case TOKksne:
349       javascript << gs_lpStrExpFuncName[NOTEQUALITY];
350       break;
351     default:
352       ASSERT(false);
353       break;
354   }
355   javascript << L"(";
356   m_pExp1->ToJavaScript(javascript);
357   javascript << L", ";
358   m_pExp2->ToJavaScript(javascript);
359   javascript << L")";
360 }
361 
CXFA_FMRelationalExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)362 CXFA_FMRelationalExpression::CXFA_FMRelationalExpression(
363     uint32_t line,
364     XFA_FM_TOKEN op,
365     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
366     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
367     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
368 
ToJavaScript(CFX_WideTextBuf & javascript)369 void CXFA_FMRelationalExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
370   switch (m_op) {
371     case TOKlt:
372     case TOKkslt:
373       javascript << gs_lpStrExpFuncName[LESS];
374       break;
375     case TOKgt:
376     case TOKksgt:
377       javascript << gs_lpStrExpFuncName[GREATER];
378       break;
379     case TOKle:
380     case TOKksle:
381       javascript << gs_lpStrExpFuncName[LESSEQUAL];
382       break;
383     case TOKge:
384     case TOKksge:
385       javascript << gs_lpStrExpFuncName[GREATEREQUAL];
386       break;
387     default:
388       ASSERT(false);
389       break;
390   }
391   javascript << L"(";
392   m_pExp1->ToJavaScript(javascript);
393   javascript << L", ";
394   m_pExp2->ToJavaScript(javascript);
395   javascript << L")";
396 }
397 
CXFA_FMAdditiveExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)398 CXFA_FMAdditiveExpression::CXFA_FMAdditiveExpression(
399     uint32_t line,
400     XFA_FM_TOKEN op,
401     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
402     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
403     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
404 
ToJavaScript(CFX_WideTextBuf & javascript)405 void CXFA_FMAdditiveExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
406   switch (m_op) {
407     case TOKplus:
408       javascript << gs_lpStrExpFuncName[PLUS];
409       break;
410     case TOKminus:
411       javascript << gs_lpStrExpFuncName[MINUS];
412       break;
413     default:
414       ASSERT(false);
415       break;
416   }
417   javascript << L"(";
418   m_pExp1->ToJavaScript(javascript);
419   javascript << L", ";
420   m_pExp2->ToJavaScript(javascript);
421   javascript << L")";
422 }
423 
CXFA_FMMultiplicativeExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)424 CXFA_FMMultiplicativeExpression::CXFA_FMMultiplicativeExpression(
425     uint32_t line,
426     XFA_FM_TOKEN op,
427     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
428     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
429     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
430 
ToJavaScript(CFX_WideTextBuf & javascript)431 void CXFA_FMMultiplicativeExpression::ToJavaScript(
432     CFX_WideTextBuf& javascript) {
433   switch (m_op) {
434     case TOKmul:
435       javascript << gs_lpStrExpFuncName[MULTIPLE];
436       break;
437     case TOKdiv:
438       javascript << gs_lpStrExpFuncName[DIVIDE];
439       break;
440     default:
441       ASSERT(false);
442       break;
443   }
444   javascript << L"(";
445   m_pExp1->ToJavaScript(javascript);
446   javascript << L", ";
447   m_pExp2->ToJavaScript(javascript);
448   javascript << L")";
449 }
450 
CXFA_FMPosExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExp)451 CXFA_FMPosExpression::CXFA_FMPosExpression(
452     uint32_t line,
453     std::unique_ptr<CXFA_FMSimpleExpression> pExp)
454     : CXFA_FMUnaryExpression(line, TOKplus, std::move(pExp)) {}
455 
ToJavaScript(CFX_WideTextBuf & javascript)456 void CXFA_FMPosExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
457   javascript << gs_lpStrExpFuncName[POSITIVE];
458   javascript << L"(";
459   m_pExp->ToJavaScript(javascript);
460   javascript << L")";
461 }
462 
CXFA_FMNegExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExp)463 CXFA_FMNegExpression::CXFA_FMNegExpression(
464     uint32_t line,
465     std::unique_ptr<CXFA_FMSimpleExpression> pExp)
466     : CXFA_FMUnaryExpression(line, TOKminus, std::move(pExp)) {}
467 
ToJavaScript(CFX_WideTextBuf & javascript)468 void CXFA_FMNegExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
469   javascript << gs_lpStrExpFuncName[NEGATIVE];
470   javascript << L"(";
471   m_pExp->ToJavaScript(javascript);
472   javascript << L")";
473 }
474 
CXFA_FMNotExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExp)475 CXFA_FMNotExpression::CXFA_FMNotExpression(
476     uint32_t line,
477     std::unique_ptr<CXFA_FMSimpleExpression> pExp)
478     : CXFA_FMUnaryExpression(line, TOKksnot, std::move(pExp)) {}
479 
ToJavaScript(CFX_WideTextBuf & javascript)480 void CXFA_FMNotExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
481   javascript << gs_lpStrExpFuncName[NOT];
482   javascript << L"(";
483   m_pExp->ToJavaScript(javascript);
484   javascript << L")";
485 }
486 
CXFA_FMCallExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExp,std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> && pArguments,bool bIsSomMethod)487 CXFA_FMCallExpression::CXFA_FMCallExpression(
488     uint32_t line,
489     std::unique_ptr<CXFA_FMSimpleExpression> pExp,
490     std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments,
491     bool bIsSomMethod)
492     : CXFA_FMUnaryExpression(line, TOKcall, std::move(pExp)),
493       m_bIsSomMethod(bIsSomMethod),
494       m_Arguments(std::move(pArguments)) {}
495 
~CXFA_FMCallExpression()496 CXFA_FMCallExpression::~CXFA_FMCallExpression() {}
497 
IsBuildInFunc(CFX_WideTextBuf * funcName)498 bool CXFA_FMCallExpression::IsBuildInFunc(CFX_WideTextBuf* funcName) {
499   uint32_t uHash = FX_HashCode_GetW(funcName->AsStringC(), true);
500   const XFA_FMBuildInFunc* pEnd = g_BuildInFuncs + FX_ArraySize(g_BuildInFuncs);
501   const XFA_FMBuildInFunc* pFunc =
502       std::lower_bound(g_BuildInFuncs, pEnd, uHash,
503                        [](const XFA_FMBuildInFunc& func, uint32_t hash) {
504                          return func.m_uHash < hash;
505                        });
506   if (pFunc < pEnd && uHash == pFunc->m_uHash) {
507     funcName->Clear();
508     *funcName << pFunc->m_buildinfunc;
509     return true;
510   }
511   return false;
512 }
513 
IsMethodWithObjParam(const CFX_WideStringC & methodName)514 uint32_t CXFA_FMCallExpression::IsMethodWithObjParam(
515     const CFX_WideStringC& methodName) {
516   uint32_t uHash = FX_HashCode_GetW(methodName, false);
517   XFA_FMSOMMethod somMethodWithObjPara;
518   uint32_t parameters = 0x00;
519   int32_t iStart = 0,
520           iEnd = (sizeof(gs_FMSomMethods) / sizeof(gs_FMSomMethods[0])) - 1;
521   int32_t iMid = (iStart + iEnd) / 2;
522   do {
523     iMid = (iStart + iEnd) / 2;
524     somMethodWithObjPara = gs_FMSomMethods[iMid];
525     if (uHash == somMethodWithObjPara.m_uHash) {
526       parameters = somMethodWithObjPara.m_dParameters;
527       break;
528     } else if (uHash < somMethodWithObjPara.m_uHash) {
529       iEnd = iMid - 1;
530     } else {
531       iStart = iMid + 1;
532     }
533   } while (iStart <= iEnd);
534   return parameters;
535 }
536 
ToJavaScript(CFX_WideTextBuf & javascript)537 void CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
538   CFX_WideTextBuf funcName;
539   m_pExp->ToJavaScript(funcName);
540   if (m_bIsSomMethod) {
541     javascript << funcName;
542     javascript << L"(";
543     uint32_t methodPara = IsMethodWithObjParam(funcName.AsStringC());
544     if (methodPara > 0) {
545       for (size_t i = 0; i < m_Arguments.size(); ++i) {
546         // Currently none of our expressions use objects for a parameter over
547         // the 6th. Make sure we don't overflow the shift when doing this
548         // check. If we ever need more the 32 object params we can revisit.
549         if (i < 32 && (methodPara & (0x01 << i)) > 0) {
550           javascript << gs_lpStrExpFuncName[GETFMJSOBJ];
551         } else {
552           javascript << gs_lpStrExpFuncName[GETFMVALUE];
553         }
554         javascript << L"(";
555         const auto& expr = m_Arguments[i];
556         expr->ToJavaScript(javascript);
557         javascript << L")";
558         if (i + 1 < m_Arguments.size()) {
559           javascript << L", ";
560         }
561       }
562     } else {
563       for (const auto& expr : m_Arguments) {
564         javascript << gs_lpStrExpFuncName[GETFMVALUE];
565         javascript << L"(";
566         expr->ToJavaScript(javascript);
567         javascript << L")";
568         if (expr != m_Arguments.back())
569           javascript << L", ";
570       }
571     }
572     javascript << L")";
573   } else {
574     bool isEvalFunc = false;
575     bool isExistsFunc = false;
576     if (IsBuildInFunc(&funcName)) {
577       if (funcName.AsStringC() == L"Eval") {
578         isEvalFunc = true;
579         javascript << L"eval.call(this, ";
580         javascript << gs_lpStrExpFuncName[CALL];
581         javascript << L"Translate";
582       } else if (funcName.AsStringC() == L"Exists") {
583         isExistsFunc = true;
584         javascript << gs_lpStrExpFuncName[CALL];
585         javascript << funcName;
586       } else {
587         javascript << gs_lpStrExpFuncName[CALL];
588         javascript << funcName;
589       }
590     } else {
591       javascript << funcName;
592     }
593     javascript << L"(";
594     if (isExistsFunc) {
595       javascript << L"\n(\nfunction ()\n{\ntry\n{\n";
596       if (!m_Arguments.empty()) {
597         const auto& expr = m_Arguments[0];
598         javascript << L"return ";
599         expr->ToJavaScript(javascript);
600         javascript << L";\n}\n";
601       } else {
602         javascript << L"return 0;\n}\n";
603       }
604       javascript
605           << L"catch(accessExceptions)\n{\nreturn 0;\n}\n}\n).call(this)\n";
606     } else {
607       for (const auto& expr : m_Arguments) {
608         expr->ToJavaScript(javascript);
609         if (expr != m_Arguments.back())
610           javascript << L", ";
611       }
612     }
613     javascript << L")";
614     if (isEvalFunc) {
615       javascript << L")";
616     }
617   }
618 }
619 
CXFA_FMDotAccessorExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,XFA_FM_TOKEN op,CFX_WideStringC wsIdentifier,std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)620 CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression(
621     uint32_t line,
622     std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
623     XFA_FM_TOKEN op,
624     CFX_WideStringC wsIdentifier,
625     std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)
626     : CXFA_FMBinExpression(line,
627                            op,
628                            std::move(pAccessor),
629                            std::move(pIndexExp)),
630       m_wsIdentifier(wsIdentifier) {}
631 
~CXFA_FMDotAccessorExpression()632 CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() {}
633 
ToJavaScript(CFX_WideTextBuf & javascript)634 void CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
635   javascript << gs_lpStrExpFuncName[DOT];
636   javascript << L"(";
637   if (m_pExp1) {
638     m_pExp1->ToJavaScript(javascript);
639   } else {
640     javascript << L"null";
641   }
642   javascript << L", ";
643   javascript << L"\"";
644   if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) {
645     m_pExp1->ToJavaScript(javascript);
646   }
647   javascript << L"\", ";
648   if (m_op == TOKdotscream) {
649     javascript << L"\"#";
650     javascript << m_wsIdentifier;
651     javascript << L"\", ";
652   } else if (m_op == TOKdotstar) {
653     javascript << L"\"*\", ";
654   } else if (m_op == TOKcall) {
655     javascript << L"\"\", ";
656   } else {
657     javascript << L"\"";
658     javascript << m_wsIdentifier;
659     javascript << L"\", ";
660   }
661   m_pExp2->ToJavaScript(javascript);
662   javascript << L")";
663 }
664 
CXFA_FMIndexExpression(uint32_t line,XFA_FM_AccessorIndex accessorIndex,std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp,bool bIsStarIndex)665 CXFA_FMIndexExpression::CXFA_FMIndexExpression(
666     uint32_t line,
667     XFA_FM_AccessorIndex accessorIndex,
668     std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp,
669     bool bIsStarIndex)
670     : CXFA_FMUnaryExpression(line, TOKlbracket, std::move(pIndexExp)),
671       m_accessorIndex(accessorIndex),
672       m_bIsStarIndex(bIsStarIndex) {}
673 
ToJavaScript(CFX_WideTextBuf & javascript)674 void CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
675   switch (m_accessorIndex) {
676     case ACCESSOR_NO_INDEX:
677       javascript << L"0";
678       break;
679     case ACCESSOR_NO_RELATIVEINDEX:
680       javascript << L"1";
681       break;
682     case ACCESSOR_POSITIVE_INDEX:
683       javascript << L"2";
684       break;
685     case ACCESSOR_NEGATIVE_INDEX:
686       javascript << L"3";
687       break;
688     default:
689       javascript << L"0";
690   }
691   if (!m_bIsStarIndex) {
692     javascript << L", ";
693     if (m_pExp) {
694       m_pExp->ToJavaScript(javascript);
695     } else {
696       javascript << L"0";
697     }
698   }
699 }
700 
CXFA_FMDotDotAccessorExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,XFA_FM_TOKEN op,CFX_WideStringC wsIdentifier,std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)701 CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression(
702     uint32_t line,
703     std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
704     XFA_FM_TOKEN op,
705     CFX_WideStringC wsIdentifier,
706     std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)
707     : CXFA_FMBinExpression(line,
708                            op,
709                            std::move(pAccessor),
710                            std::move(pIndexExp)),
711       m_wsIdentifier(wsIdentifier) {}
712 
~CXFA_FMDotDotAccessorExpression()713 CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() {}
714 
ToJavaScript(CFX_WideTextBuf & javascript)715 void CXFA_FMDotDotAccessorExpression::ToJavaScript(
716     CFX_WideTextBuf& javascript) {
717   javascript << gs_lpStrExpFuncName[DOTDOT];
718   javascript << L"(";
719   m_pExp1->ToJavaScript(javascript);
720   javascript << L", ";
721   javascript << L"\"";
722   if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) {
723     m_pExp1->ToJavaScript(javascript);
724   }
725   javascript << L"\", ";
726   javascript << L"\"";
727   javascript << m_wsIdentifier;
728   javascript << L"\", ";
729   m_pExp2->ToJavaScript(javascript);
730   javascript << L")";
731 }
732 
CXFA_FMMethodCallExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1,std::unique_ptr<CXFA_FMSimpleExpression> pCallExp)733 CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression(
734     uint32_t line,
735     std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1,
736     std::unique_ptr<CXFA_FMSimpleExpression> pCallExp)
737     : CXFA_FMBinExpression(line,
738                            TOKdot,
739                            std::move(pAccessorExp1),
740                            std::move(pCallExp)) {}
741 
ToJavaScript(CFX_WideTextBuf & javascript)742 void CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
743   javascript << L"(\nfunction ()\n{\n";
744   javascript << L"var method_return_value = null;\n";
745   javascript << L"var accessor_object = ";
746   m_pExp1->ToJavaScript(javascript);
747   javascript << L";\n";
748   javascript << L"if (";
749   javascript << gs_lpStrExpFuncName[ISFMARRAY];
750   javascript << L"(accessor_object))\n{\n";
751   javascript << L"for(var index = accessor_object.length - 1; index > 1; "
752                 L"index--)\n{\n";
753   javascript << L"method_return_value = accessor_object[index].";
754   m_pExp2->ToJavaScript(javascript);
755   javascript << L";\n}\n}\n";
756   javascript << L"else\n{\nmethod_return_value = accessor_object.";
757   m_pExp2->ToJavaScript(javascript);
758   javascript << L";\n}\n";
759   javascript << L"return method_return_value;\n";
760   javascript << L"}\n).call(this)";
761 }
762