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