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