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/cxfa_fmsimpleexpression.h" 8 9 #include <algorithm> 10 #include <iostream> 11 #include <utility> 12 13 #include "core/fxcrt/autorestorer.h" 14 #include "core/fxcrt/cfx_widetextbuf.h" 15 #include "core/fxcrt/fx_extension.h" 16 #include "third_party/base/logging.h" 17 #include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h" 18 19 namespace { 20 21 // Indexed by XFA_FM_SimpleExpressionType 22 const wchar_t* const gs_lpStrExpFuncName[] = { 23 L"pfm_rt.asgn_val_op", L"pfm_rt.log_or_op", L"pfm_rt.log_and_op", 24 L"pfm_rt.eq_op", L"pfm_rt.neq_op", L"pfm_rt.lt_op", 25 L"pfm_rt.le_op", L"pfm_rt.gt_op", L"pfm_rt.ge_op", 26 L"pfm_rt.plus_op", L"pfm_rt.minus_op", L"pfm_rt.mul_op", 27 L"pfm_rt.div_op", L"pfm_rt.pos_op", L"pfm_rt.neg_op", 28 L"pfm_rt.log_not_op", L"pfm_rt.", L"pfm_rt.dot_acc", 29 L"pfm_rt.dotdot_acc", L"pfm_rt.concat_obj", L"pfm_rt.is_obj", 30 L"pfm_rt.is_ary", L"pfm_rt.get_val", L"pfm_rt.get_jsobj", 31 L"pfm_rt.var_filter", 32 }; 33 34 const wchar_t* const g_BuiltInFuncs[] = { 35 L"Abs", L"Apr", L"At", L"Avg", 36 L"Ceil", L"Choose", L"Concat", L"Count", 37 L"Cterm", L"Date", L"Date2Num", L"DateFmt", 38 L"Decode", L"Encode", L"Eval", L"Exists", 39 L"Floor", L"Format", L"FV", L"Get", 40 L"HasValue", L"If", L"Ipmt", L"IsoDate2Num", 41 L"IsoTime2Num", L"Left", L"Len", L"LocalDateFmt", 42 L"LocalTimeFmt", L"Lower", L"Ltrim", L"Max", 43 L"Min", L"Mod", L"NPV", L"Num2Date", 44 L"Num2GMTime", L"Num2Time", L"Oneof", L"Parse", 45 L"Pmt", L"Post", L"PPmt", L"Put", 46 L"PV", L"Rate", L"Ref", L"Replace", 47 L"Right", L"Round", L"Rtrim", L"Space", 48 L"Str", L"Stuff", L"Substr", L"Sum", 49 L"Term", L"Time", L"Time2Num", L"TimeFmt", 50 L"UnitType", L"UnitValue", L"Upper", L"Uuid", 51 L"Within", L"WordNum", 52 }; 53 54 const size_t g_BuiltInFuncsMaxLen = 12; 55 56 struct XFA_FMSOMMethod { 57 const wchar_t* m_wsSomMethodName; 58 uint32_t m_dParameters; 59 }; 60 61 const XFA_FMSOMMethod gs_FMSomMethods[] = { 62 {L"absPage", 0x01}, 63 {L"absPageInBatch", 0x01}, 64 {L"absPageSpan", 0x01}, 65 {L"append", 0x01}, 66 {L"clear", 0x01}, 67 {L"formNodes", 0x01}, 68 {L"h", 0x01}, 69 {L"insert", 0x03}, 70 {L"isRecordGroup", 0x01}, 71 {L"page", 0x01}, 72 {L"pageSpan", 0x01}, 73 {L"remove", 0x01}, 74 {L"saveFilteredXML", 0x01}, 75 {L"setElement", 0x01}, 76 {L"sheet", 0x01}, 77 {L"sheetInBatch", 0x01}, 78 {L"sign", 0x61}, 79 {L"verify", 0x0d}, 80 {L"w", 0x01}, 81 {L"x", 0x01}, 82 {L"y", 0x01}, 83 }; 84 85 } // namespace 86 87 WideStringView XFA_FM_EXPTypeToString( 88 XFA_FM_SimpleExpressionType simpleExpType) { 89 return gs_lpStrExpFuncName[simpleExpType]; 90 } 91 92 CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op) 93 : m_line(line), m_op(op) {} 94 95 bool CXFA_FMSimpleExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 96 CXFA_FMToJavaScriptDepth depthManager; 97 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); 98 } 99 100 bool CXFA_FMSimpleExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { 101 CXFA_FMToJavaScriptDepth depthManager; 102 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); 103 } 104 105 XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const { 106 return m_op; 107 } 108 109 CXFA_FMNullExpression::CXFA_FMNullExpression(uint32_t line) 110 : CXFA_FMSimpleExpression(line, TOKnull) {} 111 112 bool CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 113 CXFA_FMToJavaScriptDepth depthManager; 114 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 115 return false; 116 117 javascript << L"null"; 118 return !CXFA_IsTooBig(javascript); 119 } 120 121 CXFA_FMNumberExpression::CXFA_FMNumberExpression(uint32_t line, 122 WideStringView wsNumber) 123 : CXFA_FMSimpleExpression(line, TOKnumber), m_wsNumber(wsNumber) {} 124 125 CXFA_FMNumberExpression::~CXFA_FMNumberExpression() {} 126 127 bool CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 128 CXFA_FMToJavaScriptDepth depthManager; 129 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 130 return false; 131 132 javascript << m_wsNumber; 133 return !CXFA_IsTooBig(javascript); 134 } 135 136 CXFA_FMStringExpression::CXFA_FMStringExpression(uint32_t line, 137 WideStringView wsString) 138 : CXFA_FMSimpleExpression(line, TOKstring), m_wsString(wsString) {} 139 140 CXFA_FMStringExpression::~CXFA_FMStringExpression() {} 141 142 bool CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 143 CXFA_FMToJavaScriptDepth depthManager; 144 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 145 return false; 146 147 WideString tempStr(m_wsString); 148 if (tempStr.GetLength() <= 2) { 149 javascript << tempStr; 150 return !CXFA_IsTooBig(javascript); 151 } 152 javascript.AppendChar(L'\"'); 153 for (size_t i = 1; i < tempStr.GetLength() - 1; i++) { 154 wchar_t oneChar = tempStr[i]; 155 switch (oneChar) { 156 case L'\"': 157 i++; 158 javascript << L"\\\""; 159 break; 160 case 0x0d: 161 break; 162 case 0x0a: 163 javascript << L"\\n"; 164 break; 165 default: 166 javascript.AppendChar(oneChar); 167 break; 168 } 169 } 170 javascript.AppendChar(L'\"'); 171 return !CXFA_IsTooBig(javascript); 172 } 173 174 CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression( 175 uint32_t line, 176 WideStringView wsIdentifier) 177 : CXFA_FMSimpleExpression(line, TOKidentifier), 178 m_wsIdentifier(wsIdentifier) {} 179 180 CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() {} 181 182 bool CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 183 CXFA_FMToJavaScriptDepth depthManager; 184 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 185 return false; 186 187 WideString tempStr(m_wsIdentifier); 188 if (tempStr == L"$") { 189 tempStr = L"this"; 190 } else if (tempStr == L"!") { 191 tempStr = L"xfa.datasets"; 192 } else if (tempStr == L"$data") { 193 tempStr = L"xfa.datasets.data"; 194 } else if (tempStr == L"$event") { 195 tempStr = L"xfa.event"; 196 } else if (tempStr == L"$form") { 197 tempStr = L"xfa.form"; 198 } else if (tempStr == L"$host") { 199 tempStr = L"xfa.host"; 200 } else if (tempStr == L"$layout") { 201 tempStr = L"xfa.layout"; 202 } else if (tempStr == L"$template") { 203 tempStr = L"xfa.template"; 204 } else if (tempStr[0] == L'!') { 205 tempStr = 206 EXCLAMATION_IN_IDENTIFIER + tempStr.Right(tempStr.GetLength() - 1); 207 } 208 javascript << tempStr; 209 return !CXFA_IsTooBig(javascript); 210 } 211 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 218 CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() {} 219 220 bool CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 221 CXFA_FMToJavaScriptDepth depthManager; 222 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); 223 } 224 225 CXFA_FMBinExpression::CXFA_FMBinExpression( 226 uint32_t line, 227 XFA_FM_TOKEN op, 228 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 229 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 230 : CXFA_FMSimpleExpression(line, op), 231 m_pExp1(std::move(pExp1)), 232 m_pExp2(std::move(pExp2)) {} 233 234 CXFA_FMBinExpression::~CXFA_FMBinExpression() {} 235 236 bool CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 237 CXFA_FMToJavaScriptDepth depthManager; 238 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); 239 } 240 241 CXFA_FMAssignExpression::CXFA_FMAssignExpression( 242 uint32_t line, 243 XFA_FM_TOKEN op, 244 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 245 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 246 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 247 248 bool CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 249 CXFA_FMToJavaScriptDepth depthManager; 250 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 251 return false; 252 253 javascript << L"if ("; 254 javascript << gs_lpStrExpFuncName[ISFMOBJECT]; 255 javascript << L"("; 256 CFX_WideTextBuf tempExp1; 257 if (!m_pExp1->ToJavaScript(tempExp1)) 258 return false; 259 javascript << tempExp1; 260 javascript << L"))\n{\n"; 261 javascript << gs_lpStrExpFuncName[ASSIGN]; 262 javascript << L"("; 263 javascript << tempExp1; 264 javascript << L", "; 265 266 CFX_WideTextBuf tempExp2; 267 if (!m_pExp2->ToJavaScript(tempExp2)) 268 return false; 269 javascript << tempExp2; 270 javascript << L");\n}\n"; 271 if (m_pExp1->GetOperatorToken() == TOKidentifier && 272 tempExp1.AsStringView() != L"this") { 273 javascript << L"else\n{\n"; 274 javascript << tempExp1; 275 javascript << L" = "; 276 javascript << gs_lpStrExpFuncName[ASSIGN]; 277 javascript << L"("; 278 javascript << tempExp1; 279 javascript << L", "; 280 javascript << tempExp2; 281 javascript << L");\n}\n"; 282 } 283 return !CXFA_IsTooBig(javascript); 284 } 285 286 bool CXFA_FMAssignExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { 287 CXFA_FMToJavaScriptDepth depthManager; 288 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 289 return false; 290 291 javascript << L"if ("; 292 javascript << gs_lpStrExpFuncName[ISFMOBJECT]; 293 javascript << L"("; 294 CFX_WideTextBuf tempExp1; 295 if (!m_pExp1->ToJavaScript(tempExp1)) 296 return false; 297 javascript << tempExp1; 298 javascript << L"))\n{\n"; 299 javascript << RUNTIMEFUNCTIONRETURNVALUE; 300 javascript << L" = "; 301 javascript << gs_lpStrExpFuncName[ASSIGN]; 302 javascript << L"("; 303 javascript << tempExp1; 304 javascript << L", "; 305 306 CFX_WideTextBuf tempExp2; 307 if (!m_pExp2->ToJavaScript(tempExp2)) 308 return false; 309 javascript << tempExp2; 310 javascript << L");\n}\n"; 311 if (m_pExp1->GetOperatorToken() == TOKidentifier && 312 tempExp1.AsStringView() != L"this") { 313 javascript << L"else\n{\n"; 314 javascript << RUNTIMEFUNCTIONRETURNVALUE; 315 javascript << L" = "; 316 javascript << tempExp1; 317 javascript << L" = "; 318 javascript << gs_lpStrExpFuncName[ASSIGN]; 319 javascript << L"("; 320 javascript << tempExp1; 321 javascript << L", "; 322 javascript << tempExp2; 323 javascript << L");\n}\n"; 324 } 325 return !CXFA_IsTooBig(javascript); 326 } 327 328 CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression( 329 uint32_t line, 330 XFA_FM_TOKEN op, 331 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 332 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 333 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 334 335 bool CXFA_FMLogicalOrExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 336 CXFA_FMToJavaScriptDepth depthManager; 337 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 338 return false; 339 340 javascript << gs_lpStrExpFuncName[LOGICALOR]; 341 javascript << L"("; 342 if (!m_pExp1->ToJavaScript(javascript)) 343 return false; 344 javascript << L", "; 345 if (!m_pExp2->ToJavaScript(javascript)) 346 return false; 347 javascript << L")"; 348 return !CXFA_IsTooBig(javascript); 349 } 350 351 CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression( 352 uint32_t line, 353 XFA_FM_TOKEN op, 354 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 355 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 356 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 357 358 bool CXFA_FMLogicalAndExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 359 CXFA_FMToJavaScriptDepth depthManager; 360 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 361 return false; 362 363 javascript << gs_lpStrExpFuncName[LOGICALAND]; 364 javascript << L"("; 365 if (!m_pExp1->ToJavaScript(javascript)) 366 return false; 367 javascript << L", "; 368 if (!m_pExp2->ToJavaScript(javascript)) 369 return false; 370 javascript << L")"; 371 return !CXFA_IsTooBig(javascript); 372 } 373 374 CXFA_FMEqualityExpression::CXFA_FMEqualityExpression( 375 uint32_t line, 376 XFA_FM_TOKEN op, 377 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 378 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 379 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 380 381 bool CXFA_FMEqualityExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 382 CXFA_FMToJavaScriptDepth depthManager; 383 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 384 return false; 385 386 switch (m_op) { 387 case TOKeq: 388 case TOKkseq: 389 javascript << gs_lpStrExpFuncName[EQUALITY]; 390 break; 391 case TOKne: 392 case TOKksne: 393 javascript << gs_lpStrExpFuncName[NOTEQUALITY]; 394 break; 395 default: 396 NOTREACHED(); 397 break; 398 } 399 javascript << L"("; 400 if (!m_pExp1->ToJavaScript(javascript)) 401 return false; 402 javascript << L", "; 403 if (!m_pExp2->ToJavaScript(javascript)) 404 return false; 405 javascript << L")"; 406 return !CXFA_IsTooBig(javascript); 407 } 408 409 CXFA_FMRelationalExpression::CXFA_FMRelationalExpression( 410 uint32_t line, 411 XFA_FM_TOKEN op, 412 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 413 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 414 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 415 416 bool CXFA_FMRelationalExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 417 CXFA_FMToJavaScriptDepth depthManager; 418 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 419 return false; 420 421 switch (m_op) { 422 case TOKlt: 423 case TOKkslt: 424 javascript << gs_lpStrExpFuncName[LESS]; 425 break; 426 case TOKgt: 427 case TOKksgt: 428 javascript << gs_lpStrExpFuncName[GREATER]; 429 break; 430 case TOKle: 431 case TOKksle: 432 javascript << gs_lpStrExpFuncName[LESSEQUAL]; 433 break; 434 case TOKge: 435 case TOKksge: 436 javascript << gs_lpStrExpFuncName[GREATEREQUAL]; 437 break; 438 default: 439 NOTREACHED(); 440 break; 441 } 442 javascript << L"("; 443 if (!m_pExp1->ToJavaScript(javascript)) 444 return false; 445 javascript << L", "; 446 if (!m_pExp2->ToJavaScript(javascript)) 447 return false; 448 javascript << L")"; 449 return !CXFA_IsTooBig(javascript); 450 } 451 452 CXFA_FMAdditiveExpression::CXFA_FMAdditiveExpression( 453 uint32_t line, 454 XFA_FM_TOKEN op, 455 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 456 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 457 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 458 459 bool CXFA_FMAdditiveExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 460 CXFA_FMToJavaScriptDepth depthManager; 461 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 462 return false; 463 464 switch (m_op) { 465 case TOKplus: 466 javascript << gs_lpStrExpFuncName[PLUS]; 467 break; 468 case TOKminus: 469 javascript << gs_lpStrExpFuncName[MINUS]; 470 break; 471 default: 472 NOTREACHED(); 473 break; 474 } 475 javascript << L"("; 476 if (!m_pExp1->ToJavaScript(javascript)) 477 return false; 478 javascript << L", "; 479 if (!m_pExp2->ToJavaScript(javascript)) 480 return false; 481 javascript << L")"; 482 return !CXFA_IsTooBig(javascript); 483 } 484 485 CXFA_FMMultiplicativeExpression::CXFA_FMMultiplicativeExpression( 486 uint32_t line, 487 XFA_FM_TOKEN op, 488 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 489 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 490 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 491 492 bool CXFA_FMMultiplicativeExpression::ToJavaScript( 493 CFX_WideTextBuf& javascript) { 494 CXFA_FMToJavaScriptDepth depthManager; 495 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 496 return false; 497 498 switch (m_op) { 499 case TOKmul: 500 javascript << gs_lpStrExpFuncName[MULTIPLE]; 501 break; 502 case TOKdiv: 503 javascript << gs_lpStrExpFuncName[DIVIDE]; 504 break; 505 default: 506 NOTREACHED(); 507 break; 508 } 509 javascript << L"("; 510 if (!m_pExp1->ToJavaScript(javascript)) 511 return false; 512 javascript << L", "; 513 if (!m_pExp2->ToJavaScript(javascript)) 514 return false; 515 javascript << L")"; 516 return !CXFA_IsTooBig(javascript); 517 } 518 519 CXFA_FMPosExpression::CXFA_FMPosExpression( 520 uint32_t line, 521 std::unique_ptr<CXFA_FMSimpleExpression> pExp) 522 : CXFA_FMUnaryExpression(line, TOKplus, std::move(pExp)) {} 523 524 bool CXFA_FMPosExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 525 CXFA_FMToJavaScriptDepth depthManager; 526 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 527 return false; 528 529 javascript << gs_lpStrExpFuncName[POSITIVE]; 530 javascript << L"("; 531 if (!m_pExp->ToJavaScript(javascript)) 532 return false; 533 javascript << L")"; 534 return !CXFA_IsTooBig(javascript); 535 } 536 537 CXFA_FMNegExpression::CXFA_FMNegExpression( 538 uint32_t line, 539 std::unique_ptr<CXFA_FMSimpleExpression> pExp) 540 : CXFA_FMUnaryExpression(line, TOKminus, std::move(pExp)) {} 541 542 bool CXFA_FMNegExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 543 CXFA_FMToJavaScriptDepth depthManager; 544 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 545 return false; 546 547 javascript << gs_lpStrExpFuncName[NEGATIVE]; 548 javascript << L"("; 549 if (!m_pExp->ToJavaScript(javascript)) 550 return false; 551 javascript << L")"; 552 return !CXFA_IsTooBig(javascript); 553 } 554 555 CXFA_FMNotExpression::CXFA_FMNotExpression( 556 uint32_t line, 557 std::unique_ptr<CXFA_FMSimpleExpression> pExp) 558 : CXFA_FMUnaryExpression(line, TOKksnot, std::move(pExp)) {} 559 560 bool CXFA_FMNotExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 561 CXFA_FMToJavaScriptDepth depthManager; 562 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 563 return false; 564 565 javascript << gs_lpStrExpFuncName[NOT]; 566 javascript << L"("; 567 if (!m_pExp->ToJavaScript(javascript)) 568 return false; 569 javascript << L")"; 570 return !CXFA_IsTooBig(javascript); 571 } 572 573 CXFA_FMCallExpression::CXFA_FMCallExpression( 574 uint32_t line, 575 std::unique_ptr<CXFA_FMSimpleExpression> pExp, 576 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments, 577 bool bIsSomMethod) 578 : CXFA_FMUnaryExpression(line, TOKcall, std::move(pExp)), 579 m_bIsSomMethod(bIsSomMethod), 580 m_Arguments(std::move(pArguments)) {} 581 582 CXFA_FMCallExpression::~CXFA_FMCallExpression() {} 583 584 bool CXFA_FMCallExpression::IsBuiltInFunc(CFX_WideTextBuf* funcName) { 585 if (funcName->GetLength() > g_BuiltInFuncsMaxLen) 586 return false; 587 588 auto cmpFunc = [](const wchar_t* iter, const WideString& val) -> bool { 589 return val.CompareNoCase(iter) > 0; 590 }; 591 WideString str = funcName->MakeString(); 592 const wchar_t* const* pMatchResult = std::lower_bound( 593 std::begin(g_BuiltInFuncs), std::end(g_BuiltInFuncs), str, cmpFunc); 594 if (pMatchResult != std::end(g_BuiltInFuncs) && 595 !str.CompareNoCase(*pMatchResult)) { 596 funcName->Clear(); 597 *funcName << *pMatchResult; 598 return true; 599 } 600 return false; 601 } 602 603 uint32_t CXFA_FMCallExpression::IsMethodWithObjParam( 604 const WideString& methodName) { 605 auto cmpFunc = [](const XFA_FMSOMMethod iter, const WideString& val) { 606 return val.Compare(iter.m_wsSomMethodName) > 0; 607 }; 608 const XFA_FMSOMMethod* result = 609 std::lower_bound(std::begin(gs_FMSomMethods), std::end(gs_FMSomMethods), 610 methodName, cmpFunc); 611 if (result != std::end(gs_FMSomMethods) && 612 !methodName.Compare(result->m_wsSomMethodName)) { 613 return result->m_dParameters; 614 } 615 return 0; 616 } 617 618 bool CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 619 CXFA_FMToJavaScriptDepth depthManager; 620 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 621 return false; 622 623 CFX_WideTextBuf funcName; 624 if (!m_pExp->ToJavaScript(funcName)) 625 return false; 626 if (m_bIsSomMethod) { 627 javascript << funcName; 628 javascript << L"("; 629 uint32_t methodPara = IsMethodWithObjParam(funcName.MakeString()); 630 if (methodPara > 0) { 631 for (size_t i = 0; i < m_Arguments.size(); ++i) { 632 // Currently none of our expressions use objects for a parameter over 633 // the 6th. Make sure we don't overflow the shift when doing this 634 // check. If we ever need more the 32 object params we can revisit. 635 if (i < 32 && (methodPara & (0x01 << i)) > 0) { 636 javascript << gs_lpStrExpFuncName[GETFMJSOBJ]; 637 } else { 638 javascript << gs_lpStrExpFuncName[GETFMVALUE]; 639 } 640 javascript << L"("; 641 const auto& expr = m_Arguments[i]; 642 if (!expr->ToJavaScript(javascript)) 643 return false; 644 javascript << L")"; 645 if (i + 1 < m_Arguments.size()) { 646 javascript << L", "; 647 } 648 } 649 } else { 650 for (const auto& expr : m_Arguments) { 651 javascript << gs_lpStrExpFuncName[GETFMVALUE]; 652 javascript << L"("; 653 if (!expr->ToJavaScript(javascript)) 654 return false; 655 javascript << L")"; 656 if (expr != m_Arguments.back()) 657 javascript << L", "; 658 } 659 } 660 javascript << L")"; 661 } else { 662 bool isEvalFunc = false; 663 bool isExistsFunc = false; 664 if (IsBuiltInFunc(&funcName)) { 665 if (funcName.AsStringView() == L"Eval") { 666 isEvalFunc = true; 667 javascript << L"eval.call(this, "; 668 javascript << gs_lpStrExpFuncName[CALL]; 669 javascript << L"Translate"; 670 } else if (funcName.AsStringView() == L"Exists") { 671 isExistsFunc = true; 672 javascript << gs_lpStrExpFuncName[CALL]; 673 javascript << funcName; 674 } else { 675 javascript << gs_lpStrExpFuncName[CALL]; 676 javascript << funcName; 677 } 678 } else { 679 // If a function is not a SomMethod or a built-in then the input was 680 // invalid, so failing. The scanner/lexer should catch this, but currently 681 // doesn't. This failure will bubble up to the top-level and cause the 682 // transpile to fail. 683 return false; 684 } 685 javascript << L"("; 686 if (isExistsFunc) { 687 javascript << L"\n(\nfunction ()\n{\ntry\n{\n"; 688 if (!m_Arguments.empty()) { 689 const auto& expr = m_Arguments[0]; 690 javascript << L"return "; 691 if (!expr->ToJavaScript(javascript)) 692 return false; 693 javascript << L";\n}\n"; 694 } else { 695 javascript << L"return 0;\n}\n"; 696 } 697 javascript << L"catch(accessExceptions)\n"; 698 javascript << L"{\nreturn 0;\n}\n}\n).call(this)\n"; 699 } else { 700 for (const auto& expr : m_Arguments) { 701 if (!expr->ToJavaScript(javascript)) 702 return false; 703 if (expr != m_Arguments.back()) 704 javascript << L", "; 705 } 706 } 707 javascript << L")"; 708 if (isEvalFunc) { 709 javascript << L")"; 710 } 711 } 712 return !CXFA_IsTooBig(javascript); 713 } 714 715 CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression( 716 uint32_t line, 717 std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, 718 XFA_FM_TOKEN op, 719 WideStringView wsIdentifier, 720 std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp) 721 : CXFA_FMBinExpression(line, 722 op, 723 std::move(pAccessor), 724 std::move(pIndexExp)), 725 m_wsIdentifier(wsIdentifier) {} 726 727 CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() {} 728 729 bool CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 730 CXFA_FMToJavaScriptDepth depthManager; 731 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 732 return false; 733 734 javascript << gs_lpStrExpFuncName[DOT]; 735 javascript << L"("; 736 CFX_WideTextBuf tempExp1; 737 if (m_pExp1) { 738 if (!m_pExp1->ToJavaScript(tempExp1)) 739 return false; 740 javascript << tempExp1; 741 } else { 742 javascript << L"null"; 743 } 744 javascript << L", "; 745 javascript << L"\""; 746 747 if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) 748 javascript << tempExp1; 749 javascript << L"\", "; 750 if (m_op == TOKdotscream) { 751 javascript << L"\"#"; 752 javascript << m_wsIdentifier; 753 javascript << L"\", "; 754 } else if (m_op == TOKdotstar) { 755 javascript << L"\"*\", "; 756 } else if (m_op == TOKcall) { 757 javascript << L"\"\", "; 758 } else { 759 javascript << L"\""; 760 javascript << m_wsIdentifier; 761 javascript << L"\", "; 762 } 763 if (!m_pExp2->ToJavaScript(javascript)) 764 return false; 765 javascript << L")"; 766 return !CXFA_IsTooBig(javascript); 767 } 768 769 CXFA_FMIndexExpression::CXFA_FMIndexExpression( 770 uint32_t line, 771 XFA_FM_AccessorIndex accessorIndex, 772 std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp, 773 bool bIsStarIndex) 774 : CXFA_FMUnaryExpression(line, TOKlbracket, std::move(pIndexExp)), 775 m_accessorIndex(accessorIndex), 776 m_bIsStarIndex(bIsStarIndex) {} 777 778 bool CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 779 CXFA_FMToJavaScriptDepth depthManager; 780 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 781 return false; 782 783 switch (m_accessorIndex) { 784 case ACCESSOR_NO_INDEX: 785 javascript << L"0"; 786 break; 787 case ACCESSOR_NO_RELATIVEINDEX: 788 javascript << L"1"; 789 break; 790 case ACCESSOR_POSITIVE_INDEX: 791 javascript << L"2"; 792 break; 793 case ACCESSOR_NEGATIVE_INDEX: 794 javascript << L"3"; 795 break; 796 default: 797 javascript << L"0"; 798 } 799 if (!m_bIsStarIndex) { 800 javascript << L", "; 801 if (m_pExp) { 802 if (!m_pExp->ToJavaScript(javascript)) 803 return false; 804 } else { 805 javascript << L"0"; 806 } 807 } 808 return !CXFA_IsTooBig(javascript); 809 } 810 811 CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression( 812 uint32_t line, 813 std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, 814 XFA_FM_TOKEN op, 815 WideStringView wsIdentifier, 816 std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp) 817 : CXFA_FMBinExpression(line, 818 op, 819 std::move(pAccessor), 820 std::move(pIndexExp)), 821 m_wsIdentifier(wsIdentifier) {} 822 823 CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() {} 824 825 bool CXFA_FMDotDotAccessorExpression::ToJavaScript( 826 CFX_WideTextBuf& javascript) { 827 CXFA_FMToJavaScriptDepth depthManager; 828 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 829 return false; 830 831 javascript << gs_lpStrExpFuncName[DOTDOT]; 832 javascript << L"("; 833 CFX_WideTextBuf tempExp1; 834 if (!m_pExp1->ToJavaScript(tempExp1)) 835 return false; 836 javascript << tempExp1; 837 javascript << L", "; 838 javascript << L"\""; 839 840 if (m_pExp1->GetOperatorToken() == TOKidentifier) 841 javascript << tempExp1; 842 javascript << L"\", "; 843 javascript << L"\""; 844 javascript << m_wsIdentifier; 845 javascript << L"\", "; 846 if (!m_pExp2->ToJavaScript(javascript)) 847 return false; 848 javascript << L")"; 849 return !CXFA_IsTooBig(javascript); 850 } 851 852 CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression( 853 uint32_t line, 854 std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1, 855 std::unique_ptr<CXFA_FMSimpleExpression> pCallExp) 856 : CXFA_FMBinExpression(line, 857 TOKdot, 858 std::move(pAccessorExp1), 859 std::move(pCallExp)) {} 860 861 bool CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 862 CXFA_FMToJavaScriptDepth depthManager; 863 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) 864 return false; 865 866 javascript << L"(\nfunction ()\n{\n"; 867 javascript << L"var method_return_value = null;\n"; 868 javascript << L"var accessor_object = "; 869 if (!m_pExp1->ToJavaScript(javascript)) 870 return false; 871 javascript << L";\n"; 872 javascript << L"if ("; 873 javascript << gs_lpStrExpFuncName[ISFMARRAY]; 874 javascript << L"(accessor_object))\n{\n"; 875 javascript << L"for(var index = accessor_object.length - 1; index > 1; " 876 L"index--)\n{\n"; 877 javascript << L"method_return_value = accessor_object[index]."; 878 879 CFX_WideTextBuf tempExp2; 880 if (!m_pExp2->ToJavaScript(tempExp2)) 881 return false; 882 javascript << tempExp2; 883 javascript << L";\n}\n}\n"; 884 javascript << L"else\n{\nmethod_return_value = accessor_object."; 885 javascript << tempExp2; 886 javascript << L";\n}\n"; 887 javascript << L"return method_return_value;\n"; 888 javascript << L"}\n).call(this)"; 889 return !CXFA_IsTooBig(javascript); 890 } 891 892 bool CXFA_IsTooBig(const CFX_WideTextBuf& javascript) { 893 return javascript.GetSize() >= 256 * 1024 * 1024; 894 } 895