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 "fpdfsdk/javascript/app.h" 8 9 #include <map> 10 #include <memory> 11 #include <vector> 12 13 #include "fpdfsdk/cpdfsdk_formfillenvironment.h" 14 #include "fpdfsdk/cpdfsdk_interform.h" 15 #include "fpdfsdk/javascript/Document.h" 16 #include "fpdfsdk/javascript/JS_Define.h" 17 #include "fpdfsdk/javascript/JS_EventHandler.h" 18 #include "fpdfsdk/javascript/JS_Object.h" 19 #include "fpdfsdk/javascript/JS_Value.h" 20 #include "fpdfsdk/javascript/cjs_event_context.h" 21 #include "fpdfsdk/javascript/cjs_runtime.h" 22 #include "fpdfsdk/javascript/resource.h" 23 #include "third_party/base/stl_util.h" 24 25 class GlobalTimer { 26 public: 27 GlobalTimer(app* pObj, 28 CPDFSDK_FormFillEnvironment* pFormFillEnv, 29 CJS_Runtime* pRuntime, 30 int nType, 31 const CFX_WideString& script, 32 uint32_t dwElapse, 33 uint32_t dwTimeOut); 34 ~GlobalTimer(); 35 36 static void Trigger(int nTimerID); 37 static void Cancel(int nTimerID); 38 39 bool IsOneShot() const { return m_nType == 1; } 40 uint32_t GetTimeOut() const { return m_dwTimeOut; } 41 int GetTimerID() const { return m_nTimerID; } 42 CJS_Runtime* GetRuntime() const { return m_pRuntime.Get(); } 43 CFX_WideString GetJScript() const { return m_swJScript; } 44 45 private: 46 using TimerMap = std::map<uint32_t, GlobalTimer*>; 47 static TimerMap* GetGlobalTimerMap(); 48 49 uint32_t m_nTimerID; 50 app* const m_pEmbedObj; 51 bool m_bProcessing; 52 53 // data 54 const int m_nType; // 0:Interval; 1:TimeOut 55 const uint32_t m_dwTimeOut; 56 const CFX_WideString m_swJScript; 57 CJS_Runtime::ObservedPtr m_pRuntime; 58 CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; 59 }; 60 61 GlobalTimer::GlobalTimer(app* pObj, 62 CPDFSDK_FormFillEnvironment* pFormFillEnv, 63 CJS_Runtime* pRuntime, 64 int nType, 65 const CFX_WideString& script, 66 uint32_t dwElapse, 67 uint32_t dwTimeOut) 68 : m_nTimerID(0), 69 m_pEmbedObj(pObj), 70 m_bProcessing(false), 71 m_nType(nType), 72 m_dwTimeOut(dwTimeOut), 73 m_swJScript(script), 74 m_pRuntime(pRuntime), 75 m_pFormFillEnv(pFormFillEnv) { 76 CFX_SystemHandler* pHandler = m_pFormFillEnv->GetSysHandler(); 77 m_nTimerID = pHandler->SetTimer(dwElapse, Trigger); 78 if (m_nTimerID) 79 (*GetGlobalTimerMap())[m_nTimerID] = this; 80 } 81 82 GlobalTimer::~GlobalTimer() { 83 if (!m_nTimerID) 84 return; 85 86 if (GetRuntime()) 87 m_pFormFillEnv->GetSysHandler()->KillTimer(m_nTimerID); 88 89 GetGlobalTimerMap()->erase(m_nTimerID); 90 } 91 92 // static 93 void GlobalTimer::Trigger(int nTimerID) { 94 auto it = GetGlobalTimerMap()->find(nTimerID); 95 if (it == GetGlobalTimerMap()->end()) 96 return; 97 98 GlobalTimer* pTimer = it->second; 99 if (pTimer->m_bProcessing) 100 return; 101 102 pTimer->m_bProcessing = true; 103 if (pTimer->m_pEmbedObj) 104 pTimer->m_pEmbedObj->TimerProc(pTimer); 105 106 // Timer proc may have destroyed timer, find it again. 107 it = GetGlobalTimerMap()->find(nTimerID); 108 if (it == GetGlobalTimerMap()->end()) 109 return; 110 111 pTimer = it->second; 112 pTimer->m_bProcessing = false; 113 if (pTimer->IsOneShot()) 114 pTimer->m_pEmbedObj->CancelProc(pTimer); 115 } 116 117 // static 118 void GlobalTimer::Cancel(int nTimerID) { 119 auto it = GetGlobalTimerMap()->find(nTimerID); 120 if (it == GetGlobalTimerMap()->end()) 121 return; 122 123 GlobalTimer* pTimer = it->second; 124 pTimer->m_pEmbedObj->CancelProc(pTimer); 125 } 126 127 // static 128 GlobalTimer::TimerMap* GlobalTimer::GetGlobalTimerMap() { 129 // Leak the timer array at shutdown. 130 static auto* s_TimerMap = new TimerMap; 131 return s_TimerMap; 132 } 133 134 JSConstSpec CJS_TimerObj::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; 135 136 JSPropertySpec CJS_TimerObj::PropertySpecs[] = {{0, 0, 0}}; 137 138 JSMethodSpec CJS_TimerObj::MethodSpecs[] = {{0, 0}}; 139 140 IMPLEMENT_JS_CLASS(CJS_TimerObj, TimerObj) 141 142 TimerObj::TimerObj(CJS_Object* pJSObject) 143 : CJS_EmbedObj(pJSObject), m_nTimerID(0) {} 144 145 TimerObj::~TimerObj() {} 146 147 void TimerObj::SetTimer(GlobalTimer* pTimer) { 148 m_nTimerID = pTimer->GetTimerID(); 149 } 150 151 #define JS_STR_VIEWERTYPE L"pdfium" 152 #define JS_STR_VIEWERVARIATION L"Full" 153 #define JS_STR_PLATFORM L"WIN" 154 #define JS_STR_LANGUAGE L"ENU" 155 #define JS_NUM_VIEWERVERSION 8 156 #ifdef PDF_ENABLE_XFA 157 #define JS_NUM_VIEWERVERSION_XFA 11 158 #endif // PDF_ENABLE_XFA 159 #define JS_NUM_FORMSVERSION 7 160 161 JSConstSpec CJS_App::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; 162 163 JSPropertySpec CJS_App::PropertySpecs[] = { 164 {"activeDocs", get_activeDocs_static, set_activeDocs_static}, 165 {"calculate", get_calculate_static, set_calculate_static}, 166 {"formsVersion", get_formsVersion_static, set_formsVersion_static}, 167 {"fs", get_fs_static, set_fs_static}, 168 {"fullscreen", get_fullscreen_static, set_fullscreen_static}, 169 {"language", get_language_static, set_language_static}, 170 {"media", get_media_static, set_media_static}, 171 {"platform", get_platform_static, set_platform_static}, 172 {"runtimeHighlight", get_runtimeHighlight_static, 173 set_runtimeHighlight_static}, 174 {"viewerType", get_viewerType_static, set_viewerType_static}, 175 {"viewerVariation", get_viewerVariation_static, set_viewerVariation_static}, 176 {"viewerVersion", get_viewerVersion_static, set_viewerVersion_static}, 177 {0, 0, 0}}; 178 179 JSMethodSpec CJS_App::MethodSpecs[] = {{"alert", alert_static}, 180 {"beep", beep_static}, 181 {"browseForDoc", browseForDoc_static}, 182 {"clearInterval", clearInterval_static}, 183 {"clearTimeOut", clearTimeOut_static}, 184 {"execDialog", execDialog_static}, 185 {"execMenuItem", execMenuItem_static}, 186 {"findComponent", findComponent_static}, 187 {"goBack", goBack_static}, 188 {"goForward", goForward_static}, 189 {"launchURL", launchURL_static}, 190 {"mailMsg", mailMsg_static}, 191 {"newFDF", newFDF_static}, 192 {"newDoc", newDoc_static}, 193 {"openDoc", openDoc_static}, 194 {"openFDF", openFDF_static}, 195 {"popUpMenuEx", popUpMenuEx_static}, 196 {"popUpMenu", popUpMenu_static}, 197 {"response", response_static}, 198 {"setInterval", setInterval_static}, 199 {"setTimeOut", setTimeOut_static}, 200 {0, 0}}; 201 202 IMPLEMENT_JS_CLASS(CJS_App, app) 203 204 app::app(CJS_Object* pJSObject) 205 : CJS_EmbedObj(pJSObject), m_bCalculate(true), m_bRuntimeHighLight(false) {} 206 207 app::~app() { 208 } 209 210 bool app::activeDocs(CJS_Runtime* pRuntime, 211 CJS_PropValue& vp, 212 CFX_WideString& sError) { 213 if (!vp.IsGetting()) 214 return false; 215 216 CJS_Document* pJSDocument = nullptr; 217 v8::Local<v8::Object> pObj = pRuntime->GetThisObj(); 218 if (CFXJS_Engine::GetObjDefnID(pObj) == CJS_Document::g_nObjDefnID) 219 pJSDocument = static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pObj)); 220 221 CJS_Array aDocs; 222 aDocs.SetElement(pRuntime, 0, CJS_Value(pRuntime, pJSDocument)); 223 if (aDocs.GetLength(pRuntime) > 0) 224 vp << aDocs; 225 else 226 vp.GetJSValue()->SetNull(pRuntime); 227 228 return true; 229 } 230 231 bool app::calculate(CJS_Runtime* pRuntime, 232 CJS_PropValue& vp, 233 CFX_WideString& sError) { 234 if (vp.IsSetting()) { 235 bool bVP; 236 vp >> bVP; 237 m_bCalculate = (bool)bVP; 238 pRuntime->GetFormFillEnv()->GetInterForm()->EnableCalculate( 239 (bool)m_bCalculate); 240 } else { 241 vp << (bool)m_bCalculate; 242 } 243 return true; 244 } 245 246 bool app::formsVersion(CJS_Runtime* pRuntime, 247 CJS_PropValue& vp, 248 CFX_WideString& sError) { 249 if (vp.IsGetting()) { 250 vp << JS_NUM_FORMSVERSION; 251 return true; 252 } 253 254 return false; 255 } 256 257 bool app::viewerType(CJS_Runtime* pRuntime, 258 CJS_PropValue& vp, 259 CFX_WideString& sError) { 260 if (vp.IsGetting()) { 261 vp << JS_STR_VIEWERTYPE; 262 return true; 263 } 264 265 return false; 266 } 267 268 bool app::viewerVariation(CJS_Runtime* pRuntime, 269 CJS_PropValue& vp, 270 CFX_WideString& sError) { 271 if (vp.IsGetting()) { 272 vp << JS_STR_VIEWERVARIATION; 273 return true; 274 } 275 276 return false; 277 } 278 279 bool app::viewerVersion(CJS_Runtime* pRuntime, 280 CJS_PropValue& vp, 281 CFX_WideString& sError) { 282 if (!vp.IsGetting()) 283 return false; 284 #ifdef PDF_ENABLE_XFA 285 CPDFXFA_Context* pXFAContext = pRuntime->GetFormFillEnv()->GetXFAContext(); 286 if (pXFAContext->GetDocType() == 1 || pXFAContext->GetDocType() == 2) { 287 vp << JS_NUM_VIEWERVERSION_XFA; 288 return true; 289 } 290 #endif // PDF_ENABLE_XFA 291 vp << JS_NUM_VIEWERVERSION; 292 return true; 293 } 294 295 bool app::platform(CJS_Runtime* pRuntime, 296 CJS_PropValue& vp, 297 CFX_WideString& sError) { 298 if (!vp.IsGetting()) 299 return false; 300 #ifdef PDF_ENABLE_XFA 301 CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); 302 if (!pFormFillEnv) 303 return false; 304 CFX_WideString platfrom = pFormFillEnv->GetPlatform(); 305 if (!platfrom.IsEmpty()) { 306 vp << platfrom; 307 return true; 308 } 309 #endif 310 vp << JS_STR_PLATFORM; 311 return true; 312 } 313 314 bool app::language(CJS_Runtime* pRuntime, 315 CJS_PropValue& vp, 316 CFX_WideString& sError) { 317 if (!vp.IsGetting()) 318 return false; 319 #ifdef PDF_ENABLE_XFA 320 CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); 321 if (!pFormFillEnv) 322 return false; 323 CFX_WideString language = pFormFillEnv->GetLanguage(); 324 if (!language.IsEmpty()) { 325 vp << language; 326 return true; 327 } 328 #endif 329 vp << JS_STR_LANGUAGE; 330 return true; 331 } 332 333 // creates a new fdf object that contains no data 334 // comment: need reader support 335 // note: 336 // CFDF_Document * CPDFSDK_FormFillEnvironment::NewFDF(); 337 bool app::newFDF(CJS_Runtime* pRuntime, 338 const std::vector<CJS_Value>& params, 339 CJS_Value& vRet, 340 CFX_WideString& sError) { 341 return true; 342 } 343 // opens a specified pdf document and returns its document object 344 // comment:need reader support 345 // note: as defined in js reference, the proto of this function's fourth 346 // parmeters, how old an fdf document while do not show it. 347 // CFDF_Document * CPDFSDK_FormFillEnvironment::OpenFDF(string strPath,bool 348 // bUserConv); 349 350 bool app::openFDF(CJS_Runtime* pRuntime, 351 const std::vector<CJS_Value>& params, 352 CJS_Value& vRet, 353 CFX_WideString& sError) { 354 return true; 355 } 356 357 bool app::alert(CJS_Runtime* pRuntime, 358 const std::vector<CJS_Value>& params, 359 CJS_Value& vRet, 360 CFX_WideString& sError) { 361 std::vector<CJS_Value> newParams = JS_ExpandKeywordParams( 362 pRuntime, params, 4, L"cMsg", L"nIcon", L"nType", L"cTitle"); 363 364 if (newParams[0].GetType() == CJS_Value::VT_unknown) { 365 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 366 return false; 367 } 368 369 CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); 370 if (!pFormFillEnv) { 371 vRet = CJS_Value(pRuntime, 0); 372 return true; 373 } 374 375 CFX_WideString swMsg; 376 if (newParams[0].GetType() == CJS_Value::VT_object) { 377 CJS_Array carray; 378 if (newParams[0].ConvertToArray(pRuntime, carray)) { 379 swMsg = L"["; 380 CJS_Value element(pRuntime); 381 for (int i = 0; i < carray.GetLength(pRuntime); ++i) { 382 if (i) 383 swMsg += L", "; 384 carray.GetElement(pRuntime, i, element); 385 swMsg += element.ToCFXWideString(pRuntime); 386 } 387 swMsg += L"]"; 388 } else { 389 swMsg = newParams[0].ToCFXWideString(pRuntime); 390 } 391 } else { 392 swMsg = newParams[0].ToCFXWideString(pRuntime); 393 } 394 395 int iIcon = 0; 396 if (newParams[1].GetType() != CJS_Value::VT_unknown) 397 iIcon = newParams[1].ToInt(pRuntime); 398 399 int iType = 0; 400 if (newParams[2].GetType() != CJS_Value::VT_unknown) 401 iType = newParams[2].ToInt(pRuntime); 402 403 CFX_WideString swTitle; 404 if (newParams[3].GetType() != CJS_Value::VT_unknown) 405 swTitle = newParams[3].ToCFXWideString(pRuntime); 406 else 407 swTitle = JSGetStringFromID(IDS_STRING_JSALERT); 408 409 pRuntime->BeginBlock(); 410 pFormFillEnv->KillFocusAnnot(0); 411 412 vRet = CJS_Value(pRuntime, pFormFillEnv->JS_appAlert( 413 swMsg.c_str(), swTitle.c_str(), iType, iIcon)); 414 pRuntime->EndBlock(); 415 return true; 416 } 417 418 bool app::beep(CJS_Runtime* pRuntime, 419 const std::vector<CJS_Value>& params, 420 CJS_Value& vRet, 421 CFX_WideString& sError) { 422 if (params.size() == 1) { 423 pRuntime->GetFormFillEnv()->JS_appBeep(params[0].ToInt(pRuntime)); 424 return true; 425 } 426 427 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 428 return false; 429 } 430 431 bool app::findComponent(CJS_Runtime* pRuntime, 432 const std::vector<CJS_Value>& params, 433 CJS_Value& vRet, 434 CFX_WideString& sError) { 435 return true; 436 } 437 438 bool app::popUpMenuEx(CJS_Runtime* pRuntime, 439 const std::vector<CJS_Value>& params, 440 CJS_Value& vRet, 441 CFX_WideString& sError) { 442 return false; 443 } 444 445 bool app::fs(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError) { 446 return false; 447 } 448 449 bool app::setInterval(CJS_Runtime* pRuntime, 450 const std::vector<CJS_Value>& params, 451 CJS_Value& vRet, 452 CFX_WideString& sError) { 453 if (params.size() > 2 || params.size() == 0) { 454 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 455 return false; 456 } 457 458 CFX_WideString script = 459 params.size() > 0 ? params[0].ToCFXWideString(pRuntime) : L""; 460 if (script.IsEmpty()) { 461 sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE); 462 return true; 463 } 464 465 uint32_t dwInterval = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000; 466 467 GlobalTimer* timerRef = new GlobalTimer(this, pRuntime->GetFormFillEnv(), 468 pRuntime, 0, script, dwInterval, 0); 469 m_Timers.insert(std::unique_ptr<GlobalTimer>(timerRef)); 470 471 v8::Local<v8::Object> pRetObj = 472 pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID); 473 if (pRetObj.IsEmpty()) 474 return false; 475 476 CJS_TimerObj* pJS_TimerObj = 477 static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj)); 478 TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject()); 479 pTimerObj->SetTimer(timerRef); 480 481 vRet = CJS_Value(pRuntime, pRetObj); 482 return true; 483 } 484 485 bool app::setTimeOut(CJS_Runtime* pRuntime, 486 const std::vector<CJS_Value>& params, 487 CJS_Value& vRet, 488 CFX_WideString& sError) { 489 if (params.size() > 2 || params.size() == 0) { 490 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 491 return false; 492 } 493 494 CFX_WideString script = params[0].ToCFXWideString(pRuntime); 495 if (script.IsEmpty()) { 496 sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE); 497 return true; 498 } 499 500 uint32_t dwTimeOut = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000; 501 GlobalTimer* timerRef = 502 new GlobalTimer(this, pRuntime->GetFormFillEnv(), pRuntime, 1, script, 503 dwTimeOut, dwTimeOut); 504 m_Timers.insert(std::unique_ptr<GlobalTimer>(timerRef)); 505 506 v8::Local<v8::Object> pRetObj = 507 pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID); 508 if (pRetObj.IsEmpty()) 509 return false; 510 511 CJS_TimerObj* pJS_TimerObj = 512 static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj)); 513 TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject()); 514 pTimerObj->SetTimer(timerRef); 515 vRet = CJS_Value(pRuntime, pRetObj); 516 return true; 517 } 518 519 bool app::clearTimeOut(CJS_Runtime* pRuntime, 520 const std::vector<CJS_Value>& params, 521 CJS_Value& vRet, 522 CFX_WideString& sError) { 523 if (params.size() != 1) { 524 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 525 return false; 526 } 527 528 app::ClearTimerCommon(pRuntime, params[0]); 529 return true; 530 } 531 532 bool app::clearInterval(CJS_Runtime* pRuntime, 533 const std::vector<CJS_Value>& params, 534 CJS_Value& vRet, 535 CFX_WideString& sError) { 536 if (params.size() != 1) { 537 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 538 return false; 539 } 540 541 app::ClearTimerCommon(pRuntime, params[0]); 542 return true; 543 } 544 545 void app::ClearTimerCommon(CJS_Runtime* pRuntime, const CJS_Value& param) { 546 if (param.GetType() != CJS_Value::VT_object) 547 return; 548 549 v8::Local<v8::Object> pObj = param.ToV8Object(pRuntime); 550 if (CFXJS_Engine::GetObjDefnID(pObj) != CJS_TimerObj::g_nObjDefnID) 551 return; 552 553 CJS_Object* pJSObj = param.ToCJSObject(pRuntime); 554 if (!pJSObj) 555 return; 556 557 TimerObj* pTimerObj = static_cast<TimerObj*>(pJSObj->GetEmbedObject()); 558 if (!pTimerObj) 559 return; 560 561 GlobalTimer::Cancel(pTimerObj->GetTimerID()); 562 } 563 564 bool app::execMenuItem(CJS_Runtime* pRuntime, 565 const std::vector<CJS_Value>& params, 566 CJS_Value& vRet, 567 CFX_WideString& sError) { 568 return false; 569 } 570 571 void app::TimerProc(GlobalTimer* pTimer) { 572 CJS_Runtime* pRuntime = pTimer->GetRuntime(); 573 if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0)) 574 RunJsScript(pRuntime, pTimer->GetJScript()); 575 } 576 577 void app::CancelProc(GlobalTimer* pTimer) { 578 m_Timers.erase(pdfium::FakeUniquePtr<GlobalTimer>(pTimer)); 579 } 580 581 void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) { 582 if (!pRuntime->IsBlocking()) { 583 IJS_EventContext* pContext = pRuntime->NewEventContext(); 584 pContext->OnExternal_Exec(); 585 CFX_WideString wtInfo; 586 pContext->RunScript(wsScript, &wtInfo); 587 pRuntime->ReleaseEventContext(pContext); 588 } 589 } 590 591 bool app::goBack(CJS_Runtime* pRuntime, 592 const std::vector<CJS_Value>& params, 593 CJS_Value& vRet, 594 CFX_WideString& sError) { 595 // Not supported. 596 return true; 597 } 598 599 bool app::goForward(CJS_Runtime* pRuntime, 600 const std::vector<CJS_Value>& params, 601 CJS_Value& vRet, 602 CFX_WideString& sError) { 603 // Not supported. 604 return true; 605 } 606 607 bool app::mailMsg(CJS_Runtime* pRuntime, 608 const std::vector<CJS_Value>& params, 609 CJS_Value& vRet, 610 CFX_WideString& sError) { 611 std::vector<CJS_Value> newParams = 612 JS_ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc", 613 L"cBcc", L"cSubject", L"cMsg"); 614 615 if (newParams[0].GetType() == CJS_Value::VT_unknown) { 616 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 617 return false; 618 } 619 bool bUI = newParams[0].ToBool(pRuntime); 620 621 CFX_WideString cTo; 622 if (newParams[1].GetType() != CJS_Value::VT_unknown) { 623 cTo = newParams[1].ToCFXWideString(pRuntime); 624 } else { 625 if (!bUI) { 626 // cTo parameter required when UI not invoked. 627 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 628 return false; 629 } 630 } 631 632 CFX_WideString cCc; 633 if (newParams[2].GetType() != CJS_Value::VT_unknown) 634 cCc = newParams[2].ToCFXWideString(pRuntime); 635 636 CFX_WideString cBcc; 637 if (newParams[3].GetType() != CJS_Value::VT_unknown) 638 cBcc = newParams[3].ToCFXWideString(pRuntime); 639 640 CFX_WideString cSubject; 641 if (newParams[4].GetType() != CJS_Value::VT_unknown) 642 cSubject = newParams[4].ToCFXWideString(pRuntime); 643 644 CFX_WideString cMsg; 645 if (newParams[5].GetType() != CJS_Value::VT_unknown) 646 cMsg = newParams[5].ToCFXWideString(pRuntime); 647 648 pRuntime->BeginBlock(); 649 pRuntime->GetFormFillEnv()->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(), 650 cSubject.c_str(), cCc.c_str(), 651 cBcc.c_str(), cMsg.c_str()); 652 pRuntime->EndBlock(); 653 return true; 654 } 655 656 bool app::launchURL(CJS_Runtime* pRuntime, 657 const std::vector<CJS_Value>& params, 658 CJS_Value& vRet, 659 CFX_WideString& sError) { 660 // Unsafe, not supported. 661 return true; 662 } 663 664 bool app::runtimeHighlight(CJS_Runtime* pRuntime, 665 CJS_PropValue& vp, 666 CFX_WideString& sError) { 667 if (vp.IsSetting()) { 668 vp >> m_bRuntimeHighLight; 669 } else { 670 vp << m_bRuntimeHighLight; 671 } 672 return true; 673 } 674 675 bool app::fullscreen(CJS_Runtime* pRuntime, 676 CJS_PropValue& vp, 677 CFX_WideString& sError) { 678 return false; 679 } 680 681 bool app::popUpMenu(CJS_Runtime* pRuntime, 682 const std::vector<CJS_Value>& params, 683 CJS_Value& vRet, 684 CFX_WideString& sError) { 685 return false; 686 } 687 688 bool app::browseForDoc(CJS_Runtime* pRuntime, 689 const std::vector<CJS_Value>& params, 690 CJS_Value& vRet, 691 CFX_WideString& sError) { 692 // Unsafe, not supported. 693 return true; 694 } 695 696 CFX_WideString app::SysPathToPDFPath(const CFX_WideString& sOldPath) { 697 CFX_WideString sRet = L"/"; 698 699 for (int i = 0, sz = sOldPath.GetLength(); i < sz; i++) { 700 wchar_t c = sOldPath.GetAt(i); 701 if (c == L':') { 702 } else { 703 if (c == L'\\') { 704 sRet += L"/"; 705 } else { 706 sRet += c; 707 } 708 } 709 } 710 711 return sRet; 712 } 713 714 bool app::newDoc(CJS_Runtime* pRuntime, 715 const std::vector<CJS_Value>& params, 716 CJS_Value& vRet, 717 CFX_WideString& sError) { 718 return false; 719 } 720 721 bool app::openDoc(CJS_Runtime* pRuntime, 722 const std::vector<CJS_Value>& params, 723 CJS_Value& vRet, 724 CFX_WideString& sError) { 725 return false; 726 } 727 728 bool app::response(CJS_Runtime* pRuntime, 729 const std::vector<CJS_Value>& params, 730 CJS_Value& vRet, 731 CFX_WideString& sError) { 732 std::vector<CJS_Value> newParams = 733 JS_ExpandKeywordParams(pRuntime, params, 5, L"cQuestion", L"cTitle", 734 L"cDefault", L"bPassword", L"cLabel"); 735 736 if (newParams[0].GetType() == CJS_Value::VT_unknown) { 737 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 738 return false; 739 } 740 CFX_WideString swQuestion = newParams[0].ToCFXWideString(pRuntime); 741 742 CFX_WideString swTitle = L"PDF"; 743 if (newParams[1].GetType() != CJS_Value::VT_unknown) 744 swTitle = newParams[1].ToCFXWideString(pRuntime); 745 746 CFX_WideString swDefault; 747 if (newParams[2].GetType() != CJS_Value::VT_unknown) 748 swDefault = newParams[2].ToCFXWideString(pRuntime); 749 750 bool bPassword = false; 751 if (newParams[3].GetType() != CJS_Value::VT_unknown) 752 bPassword = newParams[3].ToBool(pRuntime); 753 754 CFX_WideString swLabel; 755 if (newParams[4].GetType() != CJS_Value::VT_unknown) 756 swLabel = newParams[4].ToCFXWideString(pRuntime); 757 758 const int MAX_INPUT_BYTES = 2048; 759 std::unique_ptr<char[]> pBuff(new char[MAX_INPUT_BYTES + 2]); 760 memset(pBuff.get(), 0, MAX_INPUT_BYTES + 2); 761 762 int nLengthBytes = pRuntime->GetFormFillEnv()->JS_appResponse( 763 swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(), swLabel.c_str(), 764 bPassword, pBuff.get(), MAX_INPUT_BYTES); 765 766 if (nLengthBytes < 0 || nLengthBytes > MAX_INPUT_BYTES) { 767 sError = JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG); 768 return false; 769 } 770 771 vRet = CJS_Value(pRuntime, CFX_WideString::FromUTF16LE( 772 reinterpret_cast<uint16_t*>(pBuff.get()), 773 nLengthBytes / sizeof(uint16_t)) 774 .c_str()); 775 776 return true; 777 } 778 779 bool app::media(CJS_Runtime* pRuntime, 780 CJS_PropValue& vp, 781 CFX_WideString& sError) { 782 return false; 783 } 784 785 bool app::execDialog(CJS_Runtime* pRuntime, 786 const std::vector<CJS_Value>& params, 787 CJS_Value& vRet, 788 CFX_WideString& sError) { 789 return true; 790 } 791