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/Document.h" 8 9 #include <algorithm> 10 #include <utility> 11 #include <vector> 12 13 #include "core/fpdfapi/font/cpdf_font.h" 14 #include "core/fpdfapi/page/cpdf_page.h" 15 #include "core/fpdfapi/parser/cpdf_array.h" 16 #include "core/fpdfapi/parser/cpdf_document.h" 17 #include "core/fpdfapi/parser/cpdf_string.h" 18 #include "core/fpdfapi/parser/fpdf_parser_decode.h" 19 #include "core/fpdfdoc/cpdf_interform.h" 20 #include "core/fpdfdoc/cpdf_nametree.h" 21 #include "fpdfsdk/cpdfsdk_annotiteration.h" 22 #include "fpdfsdk/cpdfsdk_formfillenvironment.h" 23 #include "fpdfsdk/cpdfsdk_interform.h" 24 #include "fpdfsdk/cpdfsdk_pageview.h" 25 #include "fpdfsdk/cpdfsdk_widget.h" 26 #include "fpdfsdk/javascript/Annot.h" 27 #include "fpdfsdk/javascript/Field.h" 28 #include "fpdfsdk/javascript/Icon.h" 29 #include "fpdfsdk/javascript/JS_Define.h" 30 #include "fpdfsdk/javascript/JS_EventHandler.h" 31 #include "fpdfsdk/javascript/JS_Object.h" 32 #include "fpdfsdk/javascript/JS_Value.h" 33 #include "fpdfsdk/javascript/app.h" 34 #include "fpdfsdk/javascript/cjs_event_context.h" 35 #include "fpdfsdk/javascript/cjs_runtime.h" 36 #include "fpdfsdk/javascript/resource.h" 37 #include "third_party/base/numerics/safe_math.h" 38 #include "third_party/base/ptr_util.h" 39 40 JSConstSpec CJS_PrintParamsObj::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; 41 42 JSPropertySpec CJS_PrintParamsObj::PropertySpecs[] = {{0, 0, 0}}; 43 44 JSMethodSpec CJS_PrintParamsObj::MethodSpecs[] = {{0, 0}}; 45 46 IMPLEMENT_JS_CLASS(CJS_PrintParamsObj, PrintParamsObj) 47 48 PrintParamsObj::PrintParamsObj(CJS_Object* pJSObject) 49 : CJS_EmbedObj(pJSObject) { 50 bUI = true; 51 nStart = 0; 52 nEnd = 0; 53 bSilent = false; 54 bShrinkToFit = false; 55 bPrintAsImage = false; 56 bReverse = false; 57 bAnnotations = true; 58 } 59 60 #define MINWIDTH 5.0f 61 #define MINHEIGHT 5.0f 62 63 JSConstSpec CJS_Document::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; 64 65 JSPropertySpec CJS_Document::PropertySpecs[] = { 66 {"ADBE", get_ADBE_static, set_ADBE_static}, 67 {"author", get_author_static, set_author_static}, 68 {"baseURL", get_baseURL_static, set_baseURL_static}, 69 {"bookmarkRoot", get_bookmarkRoot_static, set_bookmarkRoot_static}, 70 {"calculate", get_calculate_static, set_calculate_static}, 71 {"Collab", get_Collab_static, set_Collab_static}, 72 {"creationDate", get_creationDate_static, set_creationDate_static}, 73 {"creator", get_creator_static, set_creator_static}, 74 {"delay", get_delay_static, set_delay_static}, 75 {"dirty", get_dirty_static, set_dirty_static}, 76 {"documentFileName", get_documentFileName_static, 77 set_documentFileName_static}, 78 {"external", get_external_static, set_external_static}, 79 {"filesize", get_filesize_static, set_filesize_static}, 80 {"icons", get_icons_static, set_icons_static}, 81 {"info", get_info_static, set_info_static}, 82 {"keywords", get_keywords_static, set_keywords_static}, 83 {"layout", get_layout_static, set_layout_static}, 84 {"media", get_media_static, set_media_static}, 85 {"modDate", get_modDate_static, set_modDate_static}, 86 {"mouseX", get_mouseX_static, set_mouseX_static}, 87 {"mouseY", get_mouseY_static, set_mouseY_static}, 88 {"numFields", get_numFields_static, set_numFields_static}, 89 {"numPages", get_numPages_static, set_numPages_static}, 90 {"pageNum", get_pageNum_static, set_pageNum_static}, 91 {"pageWindowRect", get_pageWindowRect_static, set_pageWindowRect_static}, 92 {"path", get_path_static, set_path_static}, 93 {"producer", get_producer_static, set_producer_static}, 94 {"subject", get_subject_static, set_subject_static}, 95 {"title", get_title_static, set_title_static}, 96 {"URL", get_URL_static, set_URL_static}, 97 {"zoom", get_zoom_static, set_zoom_static}, 98 {"zoomType", get_zoomType_static, set_zoomType_static}, 99 {0, 0, 0}}; 100 101 JSMethodSpec CJS_Document::MethodSpecs[] = { 102 {"addAnnot", addAnnot_static}, 103 {"addField", addField_static}, 104 {"addLink", addLink_static}, 105 {"addIcon", addIcon_static}, 106 {"calculateNow", calculateNow_static}, 107 {"closeDoc", closeDoc_static}, 108 {"createDataObject", createDataObject_static}, 109 {"deletePages", deletePages_static}, 110 {"exportAsText", exportAsText_static}, 111 {"exportAsFDF", exportAsFDF_static}, 112 {"exportAsXFDF", exportAsXFDF_static}, 113 {"extractPages", extractPages_static}, 114 {"getAnnot", getAnnot_static}, 115 {"getAnnots", getAnnots_static}, 116 {"getAnnot3D", getAnnot3D_static}, 117 {"getAnnots3D", getAnnots3D_static}, 118 {"getField", getField_static}, 119 {"getIcon", getIcon_static}, 120 {"getLinks", getLinks_static}, 121 {"getNthFieldName", getNthFieldName_static}, 122 {"getOCGs", getOCGs_static}, 123 {"getPageBox", getPageBox_static}, 124 {"getPageNthWord", getPageNthWord_static}, 125 {"getPageNthWordQuads", getPageNthWordQuads_static}, 126 {"getPageNumWords", getPageNumWords_static}, 127 {"getPrintParams", getPrintParams_static}, 128 {"getURL", getURL_static}, 129 {"gotoNamedDest", gotoNamedDest_static}, 130 {"importAnFDF", importAnFDF_static}, 131 {"importAnXFDF", importAnXFDF_static}, 132 {"importTextData", importTextData_static}, 133 {"insertPages", insertPages_static}, 134 {"mailForm", mailForm_static}, 135 {"print", print_static}, 136 {"removeField", removeField_static}, 137 {"replacePages", replacePages_static}, 138 {"resetForm", resetForm_static}, 139 {"removeIcon", removeIcon_static}, 140 {"saveAs", saveAs_static}, 141 {"submitForm", submitForm_static}, 142 {"syncAnnotScan", syncAnnotScan_static}, 143 {"mailDoc", mailDoc_static}, 144 {0, 0}}; 145 146 IMPLEMENT_JS_CLASS(CJS_Document, Document) 147 148 void CJS_Document::InitInstance(IJS_Runtime* pIRuntime) { 149 CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime); 150 Document* pDoc = static_cast<Document*>(GetEmbedObject()); 151 pDoc->SetFormFillEnv(pRuntime->GetFormFillEnv()); 152 } 153 154 Document::Document(CJS_Object* pJSObject) 155 : CJS_EmbedObj(pJSObject), 156 m_pFormFillEnv(nullptr), 157 m_cwBaseURL(L""), 158 m_bDelay(false) {} 159 160 Document::~Document() { 161 } 162 163 // the total number of fileds in document. 164 bool Document::numFields(CJS_Runtime* pRuntime, 165 CJS_PropValue& vp, 166 CFX_WideString& sError) { 167 if (vp.IsSetting()) { 168 sError = JSGetStringFromID(IDS_STRING_JSREADONLY); 169 return false; 170 } 171 if (!m_pFormFillEnv) { 172 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 173 return false; 174 } 175 CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); 176 CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); 177 vp << static_cast<int>(pPDFForm->CountFields(CFX_WideString())); 178 return true; 179 } 180 181 bool Document::dirty(CJS_Runtime* pRuntime, 182 CJS_PropValue& vp, 183 CFX_WideString& sError) { 184 if (!m_pFormFillEnv) { 185 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 186 return false; 187 } 188 if (vp.IsGetting()) { 189 vp << !!m_pFormFillEnv->GetChangeMark(); 190 return true; 191 } 192 bool bChanged = false; 193 vp >> bChanged; 194 if (bChanged) 195 m_pFormFillEnv->SetChangeMark(); 196 else 197 m_pFormFillEnv->ClearChangeMark(); 198 199 return true; 200 } 201 202 bool Document::ADBE(CJS_Runtime* pRuntime, 203 CJS_PropValue& vp, 204 CFX_WideString& sError) { 205 if (vp.IsGetting()) 206 vp.GetJSValue()->SetNull(pRuntime); 207 208 return true; 209 } 210 211 bool Document::pageNum(CJS_Runtime* pRuntime, 212 CJS_PropValue& vp, 213 CFX_WideString& sError) { 214 if (!m_pFormFillEnv) { 215 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 216 return false; 217 } 218 if (vp.IsGetting()) { 219 if (CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetCurrentView()) 220 vp << pPageView->GetPageIndex(); 221 return true; 222 } 223 int iPageCount = m_pFormFillEnv->GetPageCount(); 224 int iPageNum = 0; 225 vp >> iPageNum; 226 if (iPageNum >= 0 && iPageNum < iPageCount) 227 m_pFormFillEnv->JS_docgotoPage(iPageNum); 228 else if (iPageNum >= iPageCount) 229 m_pFormFillEnv->JS_docgotoPage(iPageCount - 1); 230 else if (iPageNum < 0) 231 m_pFormFillEnv->JS_docgotoPage(0); 232 233 return true; 234 } 235 236 bool Document::addAnnot(CJS_Runtime* pRuntime, 237 const std::vector<CJS_Value>& params, 238 CJS_Value& vRet, 239 CFX_WideString& sError) { 240 // Not supported. 241 return true; 242 } 243 244 bool Document::addField(CJS_Runtime* pRuntime, 245 const std::vector<CJS_Value>& params, 246 CJS_Value& vRet, 247 CFX_WideString& sError) { 248 // Not supported. 249 return true; 250 } 251 252 bool Document::exportAsText(CJS_Runtime* pRuntime, 253 const std::vector<CJS_Value>& params, 254 CJS_Value& vRet, 255 CFX_WideString& sError) { 256 // Unsafe, not supported. 257 return true; 258 } 259 260 bool Document::exportAsFDF(CJS_Runtime* pRuntime, 261 const std::vector<CJS_Value>& params, 262 CJS_Value& vRet, 263 CFX_WideString& sError) { 264 // Unsafe, not supported. 265 return true; 266 } 267 268 bool Document::exportAsXFDF(CJS_Runtime* pRuntime, 269 const std::vector<CJS_Value>& params, 270 CJS_Value& vRet, 271 CFX_WideString& sError) { 272 // Unsafe, not supported. 273 return true; 274 } 275 276 // Maps a field object in PDF document to a JavaScript variable 277 // comment: 278 // note: the paremter cName, this is clue how to treat if the cName is not a 279 // valiable filed name in this document 280 281 bool Document::getField(CJS_Runtime* pRuntime, 282 const std::vector<CJS_Value>& params, 283 CJS_Value& vRet, 284 CFX_WideString& sError) { 285 if (params.size() < 1) { 286 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 287 return false; 288 } 289 if (!m_pFormFillEnv) { 290 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 291 return false; 292 } 293 CFX_WideString wideName = params[0].ToCFXWideString(pRuntime); 294 CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); 295 CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); 296 if (pPDFForm->CountFields(wideName) <= 0) { 297 vRet.SetNull(pRuntime); 298 return true; 299 } 300 301 v8::Local<v8::Object> pFieldObj = 302 pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); 303 if (pFieldObj.IsEmpty()) 304 return false; 305 306 CJS_Field* pJSField = 307 static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj)); 308 Field* pField = static_cast<Field*>(pJSField->GetEmbedObject()); 309 pField->AttachField(this, wideName); 310 vRet = CJS_Value(pRuntime, pJSField); 311 return true; 312 } 313 314 // Gets the name of the nth field in the document 315 bool Document::getNthFieldName(CJS_Runtime* pRuntime, 316 const std::vector<CJS_Value>& params, 317 CJS_Value& vRet, 318 CFX_WideString& sError) { 319 if (params.size() != 1) { 320 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 321 return false; 322 } 323 if (!m_pFormFillEnv) { 324 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 325 return false; 326 } 327 int nIndex = params[0].ToInt(pRuntime); 328 if (nIndex < 0) { 329 sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR); 330 return false; 331 } 332 CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); 333 CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); 334 CPDF_FormField* pField = pPDFForm->GetField(nIndex, CFX_WideString()); 335 if (!pField) 336 return false; 337 338 vRet = CJS_Value(pRuntime, pField->GetFullName().c_str()); 339 return true; 340 } 341 342 bool Document::importAnFDF(CJS_Runtime* pRuntime, 343 const std::vector<CJS_Value>& params, 344 CJS_Value& vRet, 345 CFX_WideString& sError) { 346 // Unsafe, not supported. 347 return true; 348 } 349 350 bool Document::importAnXFDF(CJS_Runtime* pRuntime, 351 const std::vector<CJS_Value>& params, 352 CJS_Value& vRet, 353 CFX_WideString& sError) { 354 // Unsafe, not supported. 355 return true; 356 } 357 358 bool Document::importTextData(CJS_Runtime* pRuntime, 359 const std::vector<CJS_Value>& params, 360 CJS_Value& vRet, 361 CFX_WideString& sError) { 362 // Unsafe, not supported. 363 return true; 364 } 365 366 // exports the form data and mails the resulting fdf file as an attachment to 367 // all recipients. 368 // comment: need reader supports 369 bool Document::mailForm(CJS_Runtime* pRuntime, 370 const std::vector<CJS_Value>& params, 371 CJS_Value& vRet, 372 CFX_WideString& sError) { 373 if (!m_pFormFillEnv) { 374 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 375 return false; 376 } 377 if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) { 378 sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); 379 return false; 380 } 381 int iLength = params.size(); 382 bool bUI = iLength > 0 ? params[0].ToBool(pRuntime) : true; 383 CFX_WideString cTo = iLength > 1 ? params[1].ToCFXWideString(pRuntime) : L""; 384 CFX_WideString cCc = iLength > 2 ? params[2].ToCFXWideString(pRuntime) : L""; 385 CFX_WideString cBcc = iLength > 3 ? params[3].ToCFXWideString(pRuntime) : L""; 386 CFX_WideString cSubject = 387 iLength > 4 ? params[4].ToCFXWideString(pRuntime) : L""; 388 CFX_WideString cMsg = iLength > 5 ? params[5].ToCFXWideString(pRuntime) : L""; 389 CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); 390 CFX_ByteTextBuf textBuf; 391 if (!pInterForm->ExportFormToFDFTextBuf(textBuf)) 392 return false; 393 394 pRuntime->BeginBlock(); 395 CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); 396 pFormFillEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI, 397 cTo.c_str(), cSubject.c_str(), cCc.c_str(), 398 cBcc.c_str(), cMsg.c_str()); 399 pRuntime->EndBlock(); 400 return true; 401 } 402 403 bool Document::print(CJS_Runtime* pRuntime, 404 const std::vector<CJS_Value>& params, 405 CJS_Value& vRet, 406 CFX_WideString& sError) { 407 if (!m_pFormFillEnv) { 408 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 409 return false; 410 } 411 bool bUI = true; 412 int nStart = 0; 413 int nEnd = 0; 414 bool bSilent = false; 415 bool bShrinkToFit = false; 416 bool bPrintAsImage = false; 417 bool bReverse = false; 418 bool bAnnotations = false; 419 int nlength = params.size(); 420 if (nlength == 9) { 421 if (params[8].GetType() == CJS_Value::VT_object) { 422 v8::Local<v8::Object> pObj = params[8].ToV8Object(pRuntime); 423 if (CFXJS_Engine::GetObjDefnID(pObj) == 424 CJS_PrintParamsObj::g_nObjDefnID) { 425 if (CJS_Object* pJSObj = params[8].ToCJSObject(pRuntime)) { 426 if (PrintParamsObj* pprintparamsObj = 427 static_cast<PrintParamsObj*>(pJSObj->GetEmbedObject())) { 428 bUI = pprintparamsObj->bUI; 429 nStart = pprintparamsObj->nStart; 430 nEnd = pprintparamsObj->nEnd; 431 bSilent = pprintparamsObj->bSilent; 432 bShrinkToFit = pprintparamsObj->bShrinkToFit; 433 bPrintAsImage = pprintparamsObj->bPrintAsImage; 434 bReverse = pprintparamsObj->bReverse; 435 bAnnotations = pprintparamsObj->bAnnotations; 436 } 437 } 438 } 439 } 440 } else { 441 if (nlength >= 1) 442 bUI = params[0].ToBool(pRuntime); 443 if (nlength >= 2) 444 nStart = params[1].ToInt(pRuntime); 445 if (nlength >= 3) 446 nEnd = params[2].ToInt(pRuntime); 447 if (nlength >= 4) 448 bSilent = params[3].ToBool(pRuntime); 449 if (nlength >= 5) 450 bShrinkToFit = params[4].ToBool(pRuntime); 451 if (nlength >= 6) 452 bPrintAsImage = params[5].ToBool(pRuntime); 453 if (nlength >= 7) 454 bReverse = params[6].ToBool(pRuntime); 455 if (nlength >= 8) 456 bAnnotations = params[7].ToBool(pRuntime); 457 } 458 459 if (m_pFormFillEnv) { 460 m_pFormFillEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit, 461 bPrintAsImage, bReverse, bAnnotations); 462 return true; 463 } 464 return false; 465 } 466 467 // removes the specified field from the document. 468 // comment: 469 // note: if the filed name is not rational, adobe is dumb for it. 470 471 bool Document::removeField(CJS_Runtime* pRuntime, 472 const std::vector<CJS_Value>& params, 473 CJS_Value& vRet, 474 CFX_WideString& sError) { 475 if (params.size() != 1) { 476 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 477 return false; 478 } 479 if (!m_pFormFillEnv) { 480 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 481 return false; 482 } 483 if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || 484 m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM))) { 485 sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); 486 return false; 487 } 488 CFX_WideString sFieldName = params[0].ToCFXWideString(pRuntime); 489 CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); 490 std::vector<CPDFSDK_Annot::ObservedPtr> widgets; 491 pInterForm->GetWidgets(sFieldName, &widgets); 492 if (widgets.empty()) 493 return true; 494 495 for (const auto& pAnnot : widgets) { 496 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot.Get()); 497 if (!pWidget) 498 continue; 499 500 CFX_FloatRect rcAnnot = pWidget->GetRect(); 501 --rcAnnot.left; 502 --rcAnnot.bottom; 503 ++rcAnnot.right; 504 ++rcAnnot.top; 505 506 std::vector<CFX_FloatRect> aRefresh(1, rcAnnot); 507 UnderlyingPageType* pPage = pWidget->GetUnderlyingPage(); 508 ASSERT(pPage); 509 510 // If there is currently no pageview associated with the page being used 511 // do not create one. We may be in the process of tearing down the document 512 // and creating a new pageview at this point will cause bad things. 513 CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(pPage, false); 514 if (pPageView) { 515 #if PDF_ENABLE_XFA 516 pPageView->DeleteAnnot(pWidget); 517 #endif // PDF_ENABLE_XFA 518 pPageView->UpdateRects(aRefresh); 519 } 520 } 521 m_pFormFillEnv->SetChangeMark(); 522 523 return true; 524 } 525 526 // reset filed values within a document. 527 // comment: 528 // note: if the fields names r not rational, aodbe is dumb for it. 529 530 bool Document::resetForm(CJS_Runtime* pRuntime, 531 const std::vector<CJS_Value>& params, 532 CJS_Value& vRet, 533 CFX_WideString& sError) { 534 if (!m_pFormFillEnv) { 535 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 536 return false; 537 } 538 if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || 539 m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) || 540 m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) { 541 sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); 542 return false; 543 } 544 545 CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); 546 CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); 547 CJS_Array aName; 548 549 if (params.empty()) { 550 pPDFForm->ResetForm(true); 551 m_pFormFillEnv->SetChangeMark(); 552 return true; 553 } 554 555 switch (params[0].GetType()) { 556 default: 557 aName.Attach(params[0].ToV8Array(pRuntime)); 558 break; 559 case CJS_Value::VT_string: 560 aName.SetElement(pRuntime, 0, params[0]); 561 break; 562 } 563 564 std::vector<CPDF_FormField*> aFields; 565 for (int i = 0, isz = aName.GetLength(pRuntime); i < isz; ++i) { 566 CJS_Value valElement(pRuntime); 567 aName.GetElement(pRuntime, i, valElement); 568 CFX_WideString swVal = valElement.ToCFXWideString(pRuntime); 569 for (int j = 0, jsz = pPDFForm->CountFields(swVal); j < jsz; ++j) 570 aFields.push_back(pPDFForm->GetField(j, swVal)); 571 } 572 573 if (!aFields.empty()) { 574 pPDFForm->ResetForm(aFields, true, true); 575 m_pFormFillEnv->SetChangeMark(); 576 } 577 578 return true; 579 } 580 581 bool Document::saveAs(CJS_Runtime* pRuntime, 582 const std::vector<CJS_Value>& params, 583 CJS_Value& vRet, 584 CFX_WideString& sError) { 585 // Unsafe, not supported. 586 return true; 587 } 588 589 bool Document::syncAnnotScan(CJS_Runtime* pRuntime, 590 const std::vector<CJS_Value>& params, 591 CJS_Value& vRet, 592 CFX_WideString& sError) { 593 return true; 594 } 595 596 bool Document::submitForm(CJS_Runtime* pRuntime, 597 const std::vector<CJS_Value>& params, 598 CJS_Value& vRet, 599 CFX_WideString& sError) { 600 int nSize = params.size(); 601 if (nSize < 1) { 602 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 603 return false; 604 } 605 if (!m_pFormFillEnv) { 606 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 607 return false; 608 } 609 610 CJS_Array aFields; 611 CFX_WideString strURL; 612 bool bFDF = true; 613 bool bEmpty = false; 614 CJS_Value v = params[0]; 615 if (v.GetType() == CJS_Value::VT_string) { 616 strURL = params[0].ToCFXWideString(pRuntime); 617 if (nSize > 1) 618 bFDF = params[1].ToBool(pRuntime); 619 if (nSize > 2) 620 bEmpty = params[2].ToBool(pRuntime); 621 if (nSize > 3) 622 aFields.Attach(params[3].ToV8Array(pRuntime)); 623 } else if (v.GetType() == CJS_Value::VT_object) { 624 v8::Local<v8::Object> pObj = params[0].ToV8Object(pRuntime); 625 v8::Local<v8::Value> pValue = pRuntime->GetObjectProperty(pObj, L"cURL"); 626 if (!pValue.IsEmpty()) 627 strURL = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); 628 629 pValue = pRuntime->GetObjectProperty(pObj, L"bFDF"); 630 bFDF = CJS_Value(pRuntime, pValue).ToBool(pRuntime); 631 632 pValue = pRuntime->GetObjectProperty(pObj, L"bEmpty"); 633 bEmpty = CJS_Value(pRuntime, pValue).ToBool(pRuntime); 634 635 pValue = pRuntime->GetObjectProperty(pObj, L"aFields"); 636 aFields.Attach(CJS_Value(pRuntime, pValue).ToV8Array(pRuntime)); 637 } 638 639 CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); 640 CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm(); 641 if (aFields.GetLength(pRuntime) == 0 && bEmpty) { 642 if (pPDFInterForm->CheckRequiredFields(nullptr, true)) { 643 pRuntime->BeginBlock(); 644 pInterForm->SubmitForm(strURL, false); 645 pRuntime->EndBlock(); 646 } 647 return true; 648 } 649 650 std::vector<CPDF_FormField*> fieldObjects; 651 for (int i = 0, sz = aFields.GetLength(pRuntime); i < sz; ++i) { 652 CJS_Value valName(pRuntime); 653 aFields.GetElement(pRuntime, i, valName); 654 655 CFX_WideString sName = valName.ToCFXWideString(pRuntime); 656 CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); 657 for (int j = 0, jsz = pPDFForm->CountFields(sName); j < jsz; ++j) { 658 CPDF_FormField* pField = pPDFForm->GetField(j, sName); 659 if (!bEmpty && pField->GetValue().IsEmpty()) 660 continue; 661 662 fieldObjects.push_back(pField); 663 } 664 } 665 666 if (pPDFInterForm->CheckRequiredFields(&fieldObjects, true)) { 667 pRuntime->BeginBlock(); 668 pInterForm->SubmitFields(strURL, fieldObjects, true, !bFDF); 669 pRuntime->EndBlock(); 670 } 671 return true; 672 } 673 674 void Document::SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) { 675 m_pFormFillEnv.Reset(pFormFillEnv); 676 } 677 678 bool Document::bookmarkRoot(CJS_Runtime* pRuntime, 679 CJS_PropValue& vp, 680 CFX_WideString& sError) { 681 return true; 682 } 683 684 bool Document::mailDoc(CJS_Runtime* pRuntime, 685 const std::vector<CJS_Value>& params, 686 CJS_Value& vRet, 687 CFX_WideString& sError) { 688 // TODO(tsepez): Check maximum number of allowed params. 689 bool bUI = true; 690 CFX_WideString cTo = L""; 691 CFX_WideString cCc = L""; 692 CFX_WideString cBcc = L""; 693 CFX_WideString cSubject = L""; 694 CFX_WideString cMsg = L""; 695 696 if (params.size() >= 1) 697 bUI = params[0].ToBool(pRuntime); 698 if (params.size() >= 2) 699 cTo = params[1].ToCFXWideString(pRuntime); 700 if (params.size() >= 3) 701 cCc = params[2].ToCFXWideString(pRuntime); 702 if (params.size() >= 4) 703 cBcc = params[3].ToCFXWideString(pRuntime); 704 if (params.size() >= 5) 705 cSubject = params[4].ToCFXWideString(pRuntime); 706 if (params.size() >= 6) 707 cMsg = params[5].ToCFXWideString(pRuntime); 708 709 if (params.size() >= 1 && params[0].GetType() == CJS_Value::VT_object) { 710 v8::Local<v8::Object> pObj = params[0].ToV8Object(pRuntime); 711 712 v8::Local<v8::Value> pValue = pRuntime->GetObjectProperty(pObj, L"bUI"); 713 bUI = CJS_Value(pRuntime, pValue).ToBool(pRuntime); 714 715 pValue = pRuntime->GetObjectProperty(pObj, L"cTo"); 716 cTo = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); 717 718 pValue = pRuntime->GetObjectProperty(pObj, L"cCc"); 719 cCc = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); 720 721 pValue = pRuntime->GetObjectProperty(pObj, L"cBcc"); 722 cBcc = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); 723 724 pValue = pRuntime->GetObjectProperty(pObj, L"cSubject"); 725 cSubject = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); 726 727 pValue = pRuntime->GetObjectProperty(pObj, L"cMsg"); 728 cMsg = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); 729 } 730 731 pRuntime->BeginBlock(); 732 CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); 733 pFormFillEnv->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(), cSubject.c_str(), 734 cCc.c_str(), cBcc.c_str(), cMsg.c_str()); 735 pRuntime->EndBlock(); 736 return true; 737 } 738 739 bool Document::author(CJS_Runtime* pRuntime, 740 CJS_PropValue& vp, 741 CFX_WideString& sError) { 742 return getPropertyInternal(pRuntime, vp, "Author", sError); 743 } 744 745 bool Document::info(CJS_Runtime* pRuntime, 746 CJS_PropValue& vp, 747 CFX_WideString& sError) { 748 if (vp.IsSetting()) { 749 sError = JSGetStringFromID(IDS_STRING_JSREADONLY); 750 return false; 751 } 752 if (!m_pFormFillEnv) { 753 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 754 return false; 755 } 756 CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo(); 757 if (!pDictionary) 758 return false; 759 760 CFX_WideString cwAuthor = pDictionary->GetUnicodeTextFor("Author"); 761 CFX_WideString cwTitle = pDictionary->GetUnicodeTextFor("Title"); 762 CFX_WideString cwSubject = pDictionary->GetUnicodeTextFor("Subject"); 763 CFX_WideString cwKeywords = pDictionary->GetUnicodeTextFor("Keywords"); 764 CFX_WideString cwCreator = pDictionary->GetUnicodeTextFor("Creator"); 765 CFX_WideString cwProducer = pDictionary->GetUnicodeTextFor("Producer"); 766 CFX_WideString cwCreationDate = 767 pDictionary->GetUnicodeTextFor("CreationDate"); 768 CFX_WideString cwModDate = pDictionary->GetUnicodeTextFor("ModDate"); 769 CFX_WideString cwTrapped = pDictionary->GetUnicodeTextFor("Trapped"); 770 771 v8::Local<v8::Object> pObj = pRuntime->NewFxDynamicObj(-1); 772 pRuntime->PutObjectProperty(pObj, L"Author", 773 pRuntime->NewString(cwAuthor.AsStringC())); 774 pRuntime->PutObjectProperty(pObj, L"Title", 775 pRuntime->NewString(cwTitle.AsStringC())); 776 pRuntime->PutObjectProperty(pObj, L"Subject", 777 pRuntime->NewString(cwSubject.AsStringC())); 778 pRuntime->PutObjectProperty(pObj, L"Keywords", 779 pRuntime->NewString(cwKeywords.AsStringC())); 780 pRuntime->PutObjectProperty(pObj, L"Creator", 781 pRuntime->NewString(cwCreator.AsStringC())); 782 pRuntime->PutObjectProperty(pObj, L"Producer", 783 pRuntime->NewString(cwProducer.AsStringC())); 784 pRuntime->PutObjectProperty(pObj, L"CreationDate", 785 pRuntime->NewString(cwCreationDate.AsStringC())); 786 pRuntime->PutObjectProperty(pObj, L"ModDate", 787 pRuntime->NewString(cwModDate.AsStringC())); 788 pRuntime->PutObjectProperty(pObj, L"Trapped", 789 pRuntime->NewString(cwTrapped.AsStringC())); 790 791 // It's to be compatible to non-standard info dictionary. 792 for (const auto& it : *pDictionary) { 793 const CFX_ByteString& bsKey = it.first; 794 CPDF_Object* pValueObj = it.second.get(); 795 CFX_WideString wsKey = CFX_WideString::FromUTF8(bsKey.AsStringC()); 796 if (pValueObj->IsString() || pValueObj->IsName()) { 797 pRuntime->PutObjectProperty( 798 pObj, wsKey, 799 pRuntime->NewString(pValueObj->GetUnicodeText().AsStringC())); 800 } else if (pValueObj->IsNumber()) { 801 pRuntime->PutObjectProperty(pObj, wsKey, 802 pRuntime->NewNumber(pValueObj->GetNumber())); 803 } else if (pValueObj->IsBoolean()) { 804 pRuntime->PutObjectProperty( 805 pObj, wsKey, pRuntime->NewBoolean(!!pValueObj->GetInteger())); 806 } 807 } 808 vp << pObj; 809 return true; 810 } 811 812 bool Document::getPropertyInternal(CJS_Runtime* pRuntime, 813 CJS_PropValue& vp, 814 const CFX_ByteString& propName, 815 CFX_WideString& sError) { 816 if (!m_pFormFillEnv) { 817 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 818 return false; 819 } 820 CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo(); 821 if (!pDictionary) 822 return false; 823 824 if (vp.IsGetting()) { 825 vp << pDictionary->GetUnicodeTextFor(propName); 826 } else { 827 if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY)) { 828 sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); 829 return false; 830 } 831 CFX_WideString csProperty; 832 vp >> csProperty; 833 pDictionary->SetNewFor<CPDF_String>(propName, PDF_EncodeText(csProperty), 834 false); 835 m_pFormFillEnv->SetChangeMark(); 836 } 837 return true; 838 } 839 840 bool Document::creationDate(CJS_Runtime* pRuntime, 841 CJS_PropValue& vp, 842 CFX_WideString& sError) { 843 return getPropertyInternal(pRuntime, vp, "CreationDate", sError); 844 } 845 846 bool Document::creator(CJS_Runtime* pRuntime, 847 CJS_PropValue& vp, 848 CFX_WideString& sError) { 849 return getPropertyInternal(pRuntime, vp, "Creator", sError); 850 } 851 852 bool Document::delay(CJS_Runtime* pRuntime, 853 CJS_PropValue& vp, 854 CFX_WideString& sError) { 855 if (!m_pFormFillEnv) { 856 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 857 return false; 858 } 859 if (vp.IsGetting()) { 860 vp << m_bDelay; 861 return true; 862 } 863 if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY)) { 864 sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); 865 return false; 866 } 867 vp >> m_bDelay; 868 if (m_bDelay) { 869 m_DelayData.clear(); 870 return true; 871 } 872 std::list<std::unique_ptr<CJS_DelayData>> DelayDataToProcess; 873 DelayDataToProcess.swap(m_DelayData); 874 for (const auto& pData : DelayDataToProcess) 875 Field::DoDelay(m_pFormFillEnv.Get(), pData.get()); 876 877 return true; 878 } 879 880 bool Document::keywords(CJS_Runtime* pRuntime, 881 CJS_PropValue& vp, 882 CFX_WideString& sError) { 883 return getPropertyInternal(pRuntime, vp, "Keywords", sError); 884 } 885 886 bool Document::modDate(CJS_Runtime* pRuntime, 887 CJS_PropValue& vp, 888 CFX_WideString& sError) { 889 return getPropertyInternal(pRuntime, vp, "ModDate", sError); 890 } 891 892 bool Document::producer(CJS_Runtime* pRuntime, 893 CJS_PropValue& vp, 894 CFX_WideString& sError) { 895 return getPropertyInternal(pRuntime, vp, "Producer", sError); 896 } 897 898 bool Document::subject(CJS_Runtime* pRuntime, 899 CJS_PropValue& vp, 900 CFX_WideString& sError) { 901 return getPropertyInternal(pRuntime, vp, "Subject", sError); 902 } 903 904 bool Document::title(CJS_Runtime* pRuntime, 905 CJS_PropValue& vp, 906 CFX_WideString& sError) { 907 if (!m_pFormFillEnv || !m_pFormFillEnv->GetUnderlyingDocument()) { 908 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 909 return false; 910 } 911 return getPropertyInternal(pRuntime, vp, "Title", sError); 912 } 913 914 bool Document::numPages(CJS_Runtime* pRuntime, 915 CJS_PropValue& vp, 916 CFX_WideString& sError) { 917 if (vp.IsSetting()) { 918 sError = JSGetStringFromID(IDS_STRING_JSREADONLY); 919 return false; 920 } 921 if (!m_pFormFillEnv) { 922 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 923 return false; 924 } 925 vp << m_pFormFillEnv->GetPageCount(); 926 return true; 927 } 928 929 bool Document::external(CJS_Runtime* pRuntime, 930 CJS_PropValue& vp, 931 CFX_WideString& sError) { 932 // In Chrome case, should always return true. 933 if (vp.IsGetting()) { 934 vp << true; 935 } 936 return true; 937 } 938 939 bool Document::filesize(CJS_Runtime* pRuntime, 940 CJS_PropValue& vp, 941 CFX_WideString& sError) { 942 if (vp.IsSetting()) { 943 sError = JSGetStringFromID(IDS_STRING_JSREADONLY); 944 return false; 945 } 946 vp << 0; 947 return true; 948 } 949 950 bool Document::mouseX(CJS_Runtime* pRuntime, 951 CJS_PropValue& vp, 952 CFX_WideString& sError) { 953 return true; 954 } 955 956 bool Document::mouseY(CJS_Runtime* pRuntime, 957 CJS_PropValue& vp, 958 CFX_WideString& sError) { 959 return true; 960 } 961 962 bool Document::URL(CJS_Runtime* pRuntime, 963 CJS_PropValue& vp, 964 CFX_WideString& sError) { 965 if (vp.IsSetting()) { 966 sError = JSGetStringFromID(IDS_STRING_JSREADONLY); 967 return false; 968 } 969 if (!m_pFormFillEnv) { 970 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 971 return false; 972 } 973 vp << m_pFormFillEnv->JS_docGetFilePath(); 974 return true; 975 } 976 977 bool Document::baseURL(CJS_Runtime* pRuntime, 978 CJS_PropValue& vp, 979 CFX_WideString& sError) { 980 if (vp.IsGetting()) { 981 vp << m_cwBaseURL; 982 } else { 983 vp >> m_cwBaseURL; 984 } 985 return true; 986 } 987 988 bool Document::calculate(CJS_Runtime* pRuntime, 989 CJS_PropValue& vp, 990 CFX_WideString& sError) { 991 if (!m_pFormFillEnv) { 992 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 993 return false; 994 } 995 CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); 996 if (vp.IsGetting()) { 997 vp << !!pInterForm->IsCalculateEnabled(); 998 return true; 999 } 1000 bool bCalculate; 1001 vp >> bCalculate; 1002 pInterForm->EnableCalculate(bCalculate); 1003 return true; 1004 } 1005 1006 bool Document::documentFileName(CJS_Runtime* pRuntime, 1007 CJS_PropValue& vp, 1008 CFX_WideString& sError) { 1009 if (vp.IsSetting()) { 1010 sError = JSGetStringFromID(IDS_STRING_JSREADONLY); 1011 return false; 1012 } 1013 if (!m_pFormFillEnv) { 1014 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1015 return false; 1016 } 1017 CFX_WideString wsFilePath = m_pFormFillEnv->JS_docGetFilePath(); 1018 int32_t i = wsFilePath.GetLength() - 1; 1019 for (; i >= 0; i--) { 1020 if (wsFilePath.GetAt(i) == L'\\' || wsFilePath.GetAt(i) == L'/') 1021 break; 1022 } 1023 if (i >= 0 && i < wsFilePath.GetLength() - 1) { 1024 vp << (wsFilePath.GetBuffer(wsFilePath.GetLength()) + i + 1); 1025 } else { 1026 vp << L""; 1027 } 1028 return true; 1029 } 1030 1031 bool Document::path(CJS_Runtime* pRuntime, 1032 CJS_PropValue& vp, 1033 CFX_WideString& sError) { 1034 if (vp.IsSetting()) { 1035 sError = JSGetStringFromID(IDS_STRING_JSREADONLY); 1036 return false; 1037 } 1038 if (!m_pFormFillEnv) { 1039 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1040 return false; 1041 } 1042 vp << app::SysPathToPDFPath(m_pFormFillEnv->JS_docGetFilePath()); 1043 return true; 1044 } 1045 1046 bool Document::pageWindowRect(CJS_Runtime* pRuntime, 1047 CJS_PropValue& vp, 1048 CFX_WideString& sError) { 1049 return true; 1050 } 1051 1052 bool Document::layout(CJS_Runtime* pRuntime, 1053 CJS_PropValue& vp, 1054 CFX_WideString& sError) { 1055 return true; 1056 } 1057 1058 bool Document::addLink(CJS_Runtime* pRuntime, 1059 const std::vector<CJS_Value>& params, 1060 CJS_Value& vRet, 1061 CFX_WideString& sError) { 1062 return true; 1063 } 1064 1065 bool Document::closeDoc(CJS_Runtime* pRuntime, 1066 const std::vector<CJS_Value>& params, 1067 CJS_Value& vRet, 1068 CFX_WideString& sError) { 1069 return true; 1070 } 1071 1072 bool Document::getPageBox(CJS_Runtime* pRuntime, 1073 const std::vector<CJS_Value>& params, 1074 CJS_Value& vRet, 1075 CFX_WideString& sError) { 1076 return true; 1077 } 1078 1079 bool Document::getAnnot(CJS_Runtime* pRuntime, 1080 const std::vector<CJS_Value>& params, 1081 CJS_Value& vRet, 1082 CFX_WideString& sError) { 1083 if (params.size() != 2) { 1084 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 1085 return false; 1086 } 1087 if (!m_pFormFillEnv) { 1088 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1089 return false; 1090 } 1091 int nPageNo = params[0].ToInt(pRuntime); 1092 CFX_WideString swAnnotName = params[1].ToCFXWideString(pRuntime); 1093 CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(nPageNo); 1094 if (!pPageView) 1095 return false; 1096 1097 CPDFSDK_AnnotIteration annotIteration(pPageView, false); 1098 CPDFSDK_BAAnnot* pSDKBAAnnot = nullptr; 1099 for (const auto& pSDKAnnotCur : annotIteration) { 1100 CPDFSDK_BAAnnot* pBAAnnot = 1101 static_cast<CPDFSDK_BAAnnot*>(pSDKAnnotCur.Get()); 1102 if (pBAAnnot && pBAAnnot->GetAnnotName() == swAnnotName) { 1103 pSDKBAAnnot = pBAAnnot; 1104 break; 1105 } 1106 } 1107 if (!pSDKBAAnnot) 1108 return false; 1109 1110 v8::Local<v8::Object> pObj = 1111 pRuntime->NewFxDynamicObj(CJS_Annot::g_nObjDefnID); 1112 if (pObj.IsEmpty()) 1113 return false; 1114 1115 CJS_Annot* pJS_Annot = 1116 static_cast<CJS_Annot*>(pRuntime->GetObjectPrivate(pObj)); 1117 Annot* pAnnot = static_cast<Annot*>(pJS_Annot->GetEmbedObject()); 1118 pAnnot->SetSDKAnnot(pSDKBAAnnot); 1119 vRet = CJS_Value(pRuntime, pJS_Annot); 1120 return true; 1121 } 1122 1123 bool Document::getAnnots(CJS_Runtime* pRuntime, 1124 const std::vector<CJS_Value>& params, 1125 CJS_Value& vRet, 1126 CFX_WideString& sError) { 1127 if (!m_pFormFillEnv) { 1128 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1129 return false; 1130 } 1131 // TODO(tonikitoo): Add support supported parameters as per 1132 // the PDF spec. 1133 1134 int nPageNo = m_pFormFillEnv->GetPageCount(); 1135 CJS_Array annots; 1136 1137 for (int i = 0; i < nPageNo; ++i) { 1138 CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(i); 1139 if (!pPageView) 1140 return false; 1141 1142 CPDFSDK_AnnotIteration annotIteration(pPageView, false); 1143 for (const auto& pSDKAnnotCur : annotIteration) { 1144 if (!pSDKAnnotCur) { 1145 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1146 return false; 1147 } 1148 v8::Local<v8::Object> pObj = 1149 pRuntime->NewFxDynamicObj(CJS_Annot::g_nObjDefnID); 1150 if (pObj.IsEmpty()) 1151 return false; 1152 1153 CJS_Annot* pJS_Annot = 1154 static_cast<CJS_Annot*>(pRuntime->GetObjectPrivate(pObj)); 1155 Annot* pAnnot = static_cast<Annot*>(pJS_Annot->GetEmbedObject()); 1156 pAnnot->SetSDKAnnot(static_cast<CPDFSDK_BAAnnot*>(pSDKAnnotCur.Get())); 1157 annots.SetElement(pRuntime, i, CJS_Value(pRuntime, pJS_Annot)); 1158 } 1159 } 1160 vRet = CJS_Value(pRuntime, annots); 1161 return true; 1162 } 1163 1164 bool Document::getAnnot3D(CJS_Runtime* pRuntime, 1165 const std::vector<CJS_Value>& params, 1166 CJS_Value& vRet, 1167 CFX_WideString& sError) { 1168 vRet.SetNull(pRuntime); 1169 return true; 1170 } 1171 1172 bool Document::getAnnots3D(CJS_Runtime* pRuntime, 1173 const std::vector<CJS_Value>& params, 1174 CJS_Value& vRet, 1175 CFX_WideString& sError) { 1176 return true; 1177 } 1178 1179 bool Document::getOCGs(CJS_Runtime* pRuntime, 1180 const std::vector<CJS_Value>& params, 1181 CJS_Value& vRet, 1182 CFX_WideString& sError) { 1183 return true; 1184 } 1185 1186 bool Document::getLinks(CJS_Runtime* pRuntime, 1187 const std::vector<CJS_Value>& params, 1188 CJS_Value& vRet, 1189 CFX_WideString& sError) { 1190 return true; 1191 } 1192 1193 bool Document::IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect) { 1194 return (rect.left <= LinkRect.left && rect.top <= LinkRect.top && 1195 rect.right >= LinkRect.right && rect.bottom >= LinkRect.bottom); 1196 } 1197 1198 bool Document::addIcon(CJS_Runtime* pRuntime, 1199 const std::vector<CJS_Value>& params, 1200 CJS_Value& vRet, 1201 CFX_WideString& sError) { 1202 if (params.size() != 2) { 1203 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 1204 return false; 1205 } 1206 1207 CFX_WideString swIconName = params[0].ToCFXWideString(pRuntime); 1208 if (params[1].GetType() != CJS_Value::VT_object) { 1209 sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR); 1210 return false; 1211 } 1212 1213 v8::Local<v8::Object> pJSIcon = params[1].ToV8Object(pRuntime); 1214 if (pRuntime->GetObjDefnID(pJSIcon) != CJS_Icon::g_nObjDefnID) { 1215 sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR); 1216 return false; 1217 } 1218 1219 if (!params[1].ToCJSObject(pRuntime)->GetEmbedObject()) { 1220 sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR); 1221 return false; 1222 } 1223 1224 m_IconNames.push_back(swIconName); 1225 return true; 1226 } 1227 1228 bool Document::icons(CJS_Runtime* pRuntime, 1229 CJS_PropValue& vp, 1230 CFX_WideString& sError) { 1231 if (vp.IsSetting()) { 1232 sError = JSGetStringFromID(IDS_STRING_JSREADONLY); 1233 return false; 1234 } 1235 if (m_IconNames.empty()) { 1236 vp.GetJSValue()->SetNull(pRuntime); 1237 return true; 1238 } 1239 1240 CJS_Array Icons; 1241 int i = 0; 1242 for (const auto& name : m_IconNames) { 1243 v8::Local<v8::Object> pObj = 1244 pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID); 1245 if (pObj.IsEmpty()) 1246 return false; 1247 1248 CJS_Icon* pJS_Icon = 1249 static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj)); 1250 Icon* pIcon = static_cast<Icon*>(pJS_Icon->GetEmbedObject()); 1251 pIcon->SetIconName(name); 1252 Icons.SetElement(pRuntime, i++, CJS_Value(pRuntime, pJS_Icon)); 1253 } 1254 1255 vp << Icons; 1256 return true; 1257 } 1258 1259 bool Document::getIcon(CJS_Runtime* pRuntime, 1260 const std::vector<CJS_Value>& params, 1261 CJS_Value& vRet, 1262 CFX_WideString& sError) { 1263 if (params.size() != 1) { 1264 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 1265 return false; 1266 } 1267 1268 CFX_WideString swIconName = params[0].ToCFXWideString(pRuntime); 1269 auto it = std::find(m_IconNames.begin(), m_IconNames.end(), swIconName); 1270 if (it == m_IconNames.end()) 1271 return false; 1272 1273 v8::Local<v8::Object> pObj = 1274 pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID); 1275 if (pObj.IsEmpty()) 1276 return false; 1277 1278 CJS_Icon* pJS_Icon = static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj)); 1279 Icon* pIcon = static_cast<Icon*>(pJS_Icon->GetEmbedObject()); 1280 pIcon->SetIconName(*it); 1281 vRet = CJS_Value(pRuntime, pJS_Icon); 1282 return true; 1283 } 1284 1285 bool Document::removeIcon(CJS_Runtime* pRuntime, 1286 const std::vector<CJS_Value>& params, 1287 CJS_Value& vRet, 1288 CFX_WideString& sError) { 1289 // Unsafe, no supported. 1290 return true; 1291 } 1292 1293 bool Document::createDataObject(CJS_Runtime* pRuntime, 1294 const std::vector<CJS_Value>& params, 1295 CJS_Value& vRet, 1296 CFX_WideString& sError) { 1297 // Unsafe, not implemented. 1298 return true; 1299 } 1300 1301 bool Document::media(CJS_Runtime* pRuntime, 1302 CJS_PropValue& vp, 1303 CFX_WideString& sError) { 1304 return true; 1305 } 1306 1307 bool Document::calculateNow(CJS_Runtime* pRuntime, 1308 const std::vector<CJS_Value>& params, 1309 CJS_Value& vRet, 1310 CFX_WideString& sError) { 1311 if (!m_pFormFillEnv) { 1312 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1313 return false; 1314 } 1315 if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || 1316 m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) || 1317 m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) { 1318 sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); 1319 return false; 1320 } 1321 m_pFormFillEnv->GetInterForm()->OnCalculate(); 1322 return true; 1323 } 1324 1325 bool Document::Collab(CJS_Runtime* pRuntime, 1326 CJS_PropValue& vp, 1327 CFX_WideString& sError) { 1328 return true; 1329 } 1330 1331 bool Document::getPageNthWord(CJS_Runtime* pRuntime, 1332 const std::vector<CJS_Value>& params, 1333 CJS_Value& vRet, 1334 CFX_WideString& sError) { 1335 if (!m_pFormFillEnv) { 1336 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1337 return false; 1338 } 1339 if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) { 1340 sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); 1341 return false; 1342 } 1343 1344 // TODO(tsepez): check maximum allowable params. 1345 1346 int nPageNo = params.size() > 0 ? params[0].ToInt(pRuntime) : 0; 1347 int nWordNo = params.size() > 1 ? params[1].ToInt(pRuntime) : 0; 1348 bool bStrip = params.size() > 2 ? params[2].ToBool(pRuntime) : true; 1349 1350 CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); 1351 if (!pDocument) 1352 return false; 1353 1354 if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) { 1355 sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR); 1356 return false; 1357 } 1358 1359 CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo); 1360 if (!pPageDict) 1361 return false; 1362 1363 CPDF_Page page(pDocument, pPageDict, true); 1364 page.ParseContent(); 1365 1366 int nWords = 0; 1367 CFX_WideString swRet; 1368 for (auto& pPageObj : *page.GetPageObjectList()) { 1369 if (pPageObj->IsText()) { 1370 CPDF_TextObject* pTextObj = pPageObj->AsText(); 1371 int nObjWords = CountWords(pTextObj); 1372 if (nWords + nObjWords >= nWordNo) { 1373 swRet = GetObjWordStr(pTextObj, nWordNo - nWords); 1374 break; 1375 } 1376 nWords += nObjWords; 1377 } 1378 } 1379 1380 if (bStrip) { 1381 swRet.TrimLeft(); 1382 swRet.TrimRight(); 1383 } 1384 1385 vRet = CJS_Value(pRuntime, swRet.c_str()); 1386 return true; 1387 } 1388 1389 bool Document::getPageNthWordQuads(CJS_Runtime* pRuntime, 1390 const std::vector<CJS_Value>& params, 1391 CJS_Value& vRet, 1392 CFX_WideString& sError) { 1393 if (!m_pFormFillEnv) { 1394 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1395 return false; 1396 } 1397 if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) { 1398 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1399 return false; 1400 } 1401 return false; 1402 } 1403 1404 bool Document::getPageNumWords(CJS_Runtime* pRuntime, 1405 const std::vector<CJS_Value>& params, 1406 CJS_Value& vRet, 1407 CFX_WideString& sError) { 1408 if (!m_pFormFillEnv) { 1409 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1410 return false; 1411 } 1412 if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) { 1413 sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); 1414 return false; 1415 } 1416 int nPageNo = params.size() > 0 ? params[0].ToInt(pRuntime) : 0; 1417 CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); 1418 if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) { 1419 sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR); 1420 return false; 1421 } 1422 1423 CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo); 1424 if (!pPageDict) 1425 return false; 1426 1427 CPDF_Page page(pDocument, pPageDict, true); 1428 page.ParseContent(); 1429 1430 int nWords = 0; 1431 for (auto& pPageObj : *page.GetPageObjectList()) { 1432 if (pPageObj->IsText()) 1433 nWords += CountWords(pPageObj->AsText()); 1434 } 1435 1436 vRet = CJS_Value(pRuntime, nWords); 1437 return true; 1438 } 1439 1440 bool Document::getPrintParams(CJS_Runtime* pRuntime, 1441 const std::vector<CJS_Value>& params, 1442 CJS_Value& vRet, 1443 CFX_WideString& sError) { 1444 v8::Local<v8::Object> pRetObj = 1445 pRuntime->NewFxDynamicObj(CJS_PrintParamsObj::g_nObjDefnID); 1446 if (pRetObj.IsEmpty()) 1447 return false; 1448 1449 // Not implemented yet. 1450 1451 vRet = CJS_Value(pRuntime, pRetObj); 1452 return true; 1453 } 1454 1455 #define ISLATINWORD(u) (u != 0x20 && u <= 0x28FF) 1456 1457 int Document::CountWords(CPDF_TextObject* pTextObj) { 1458 if (!pTextObj) 1459 return 0; 1460 1461 int nWords = 0; 1462 1463 CPDF_Font* pFont = pTextObj->GetFont(); 1464 if (!pFont) 1465 return 0; 1466 1467 bool bIsLatin = false; 1468 1469 for (int i = 0, sz = pTextObj->CountChars(); i < sz; i++) { 1470 uint32_t charcode = CPDF_Font::kInvalidCharCode; 1471 FX_FLOAT kerning; 1472 1473 pTextObj->GetCharInfo(i, &charcode, &kerning); 1474 CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode); 1475 1476 uint16_t unicode = 0; 1477 if (swUnicode.GetLength() > 0) 1478 unicode = swUnicode[0]; 1479 1480 if (ISLATINWORD(unicode) && bIsLatin) 1481 continue; 1482 1483 bIsLatin = ISLATINWORD(unicode); 1484 if (unicode != 0x20) 1485 nWords++; 1486 } 1487 1488 return nWords; 1489 } 1490 1491 CFX_WideString Document::GetObjWordStr(CPDF_TextObject* pTextObj, 1492 int nWordIndex) { 1493 CFX_WideString swRet; 1494 1495 CPDF_Font* pFont = pTextObj->GetFont(); 1496 if (!pFont) 1497 return L""; 1498 1499 int nWords = 0; 1500 bool bIsLatin = false; 1501 1502 for (int i = 0, sz = pTextObj->CountChars(); i < sz; i++) { 1503 uint32_t charcode = CPDF_Font::kInvalidCharCode; 1504 FX_FLOAT kerning; 1505 1506 pTextObj->GetCharInfo(i, &charcode, &kerning); 1507 CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode); 1508 1509 uint16_t unicode = 0; 1510 if (swUnicode.GetLength() > 0) 1511 unicode = swUnicode[0]; 1512 1513 if (ISLATINWORD(unicode) && bIsLatin) { 1514 } else { 1515 bIsLatin = ISLATINWORD(unicode); 1516 if (unicode != 0x20) 1517 nWords++; 1518 } 1519 1520 if (nWords - 1 == nWordIndex) 1521 swRet += unicode; 1522 } 1523 1524 return swRet; 1525 } 1526 1527 bool Document::zoom(CJS_Runtime* pRuntime, 1528 CJS_PropValue& vp, 1529 CFX_WideString& sError) { 1530 return true; 1531 } 1532 1533 /** 1534 (none, NoVary) 1535 (fitP, FitPage) 1536 (fitW, FitWidth) 1537 (fitH, FitHeight) 1538 (fitV, FitVisibleWidth) 1539 (pref, Preferred) 1540 (refW, ReflowWidth) 1541 */ 1542 1543 bool Document::zoomType(CJS_Runtime* pRuntime, 1544 CJS_PropValue& vp, 1545 CFX_WideString& sError) { 1546 return true; 1547 } 1548 1549 bool Document::deletePages(CJS_Runtime* pRuntime, 1550 const std::vector<CJS_Value>& params, 1551 CJS_Value& vRet, 1552 CFX_WideString& sError) { 1553 // Unsafe, no supported. 1554 return true; 1555 } 1556 1557 bool Document::extractPages(CJS_Runtime* pRuntime, 1558 const std::vector<CJS_Value>& params, 1559 CJS_Value& vRet, 1560 CFX_WideString& sError) { 1561 // Unsafe, not supported. 1562 return true; 1563 } 1564 1565 bool Document::insertPages(CJS_Runtime* pRuntime, 1566 const std::vector<CJS_Value>& params, 1567 CJS_Value& vRet, 1568 CFX_WideString& sError) { 1569 // Unsafe, not supported. 1570 return true; 1571 } 1572 1573 bool Document::replacePages(CJS_Runtime* pRuntime, 1574 const std::vector<CJS_Value>& params, 1575 CJS_Value& vRet, 1576 CFX_WideString& sError) { 1577 // Unsafe, not supported. 1578 return true; 1579 } 1580 1581 bool Document::getURL(CJS_Runtime* pRuntime, 1582 const std::vector<CJS_Value>& params, 1583 CJS_Value& vRet, 1584 CFX_WideString& sError) { 1585 // Unsafe, not supported. 1586 return true; 1587 } 1588 1589 bool Document::gotoNamedDest(CJS_Runtime* pRuntime, 1590 const std::vector<CJS_Value>& params, 1591 CJS_Value& vRet, 1592 CFX_WideString& sError) { 1593 if (params.size() != 1) { 1594 sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); 1595 return false; 1596 } 1597 if (!m_pFormFillEnv) { 1598 sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); 1599 return false; 1600 } 1601 CFX_WideString wideName = params[0].ToCFXWideString(pRuntime); 1602 CFX_ByteString utf8Name = wideName.UTF8Encode(); 1603 CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); 1604 if (!pDocument) 1605 return false; 1606 1607 CPDF_NameTree nameTree(pDocument, "Dests"); 1608 CPDF_Array* destArray = nameTree.LookupNamedDest(pDocument, utf8Name); 1609 if (!destArray) 1610 return false; 1611 1612 CPDF_Dest dest(destArray); 1613 const CPDF_Array* arrayObject = ToArray(dest.GetObject()); 1614 1615 std::unique_ptr<float[]> scrollPositionArray; 1616 int scrollPositionArraySize = 0; 1617 1618 if (arrayObject) { 1619 scrollPositionArray.reset(new float[arrayObject->GetCount()]); 1620 int j = 0; 1621 for (size_t i = 2; i < arrayObject->GetCount(); i++) 1622 scrollPositionArray[j++] = arrayObject->GetFloatAt(i); 1623 scrollPositionArraySize = j; 1624 } 1625 1626 pRuntime->BeginBlock(); 1627 m_pFormFillEnv->DoGoToAction(dest.GetPageIndex(pDocument), dest.GetZoomMode(), 1628 scrollPositionArray.get(), 1629 scrollPositionArraySize); 1630 pRuntime->EndBlock(); 1631 1632 return true; 1633 } 1634 1635 void Document::AddDelayData(CJS_DelayData* pData) { 1636 m_DelayData.push_back(std::unique_ptr<CJS_DelayData>(pData)); 1637 } 1638 1639 void Document::DoFieldDelay(const CFX_WideString& sFieldName, 1640 int nControlIndex) { 1641 std::vector<std::unique_ptr<CJS_DelayData>> DelayDataForFieldAndControlIndex; 1642 auto iter = m_DelayData.begin(); 1643 while (iter != m_DelayData.end()) { 1644 auto old = iter++; 1645 if ((*old)->sFieldName == sFieldName && 1646 (*old)->nControlIndex == nControlIndex) { 1647 DelayDataForFieldAndControlIndex.push_back(std::move(*old)); 1648 m_DelayData.erase(old); 1649 } 1650 } 1651 1652 for (const auto& pData : DelayDataForFieldAndControlIndex) 1653 Field::DoDelay(m_pFormFillEnv.Get(), pData.get()); 1654 } 1655 1656 CJS_Document* Document::GetCJSDoc() const { 1657 return static_cast<CJS_Document*>(m_pJSObject); 1658 } 1659