410650af495c980ba3a23eabd2429844ece999df
[pdfium.git] / fpdfsdk / src / javascript / Document.cpp
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 "../../include/javascript/JavaScript.h"
8 #include "../../include/javascript/IJavaScript.h"
9 #include "../../include/javascript/JS_Define.h"
10 #include "../../include/javascript/JS_Object.h"
11 #include "../../include/javascript/JS_Value.h"
12 #include "../../include/javascript/Document.h"
13 #include "../../include/javascript/JS_EventHandler.h"
14 #include "../../include/javascript/JS_Context.h"
15 #include "../../include/javascript/JS_Runtime.h"
16 #include "../../include/javascript/app.h"
17 #include "../../include/javascript/Field.h"
18 #include "../../include/javascript/Icon.h"
19 #include "../../include/javascript/Field.h"
20
21 #include "../../../third_party/base/numerics/safe_math.h"
22
23 static v8::Isolate* GetIsolate(IFXJS_Context* cc)
24 {
25         CJS_Context* pContext = (CJS_Context *)cc;
26         ASSERT(pContext != NULL);
27
28         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
29         ASSERT(pRuntime != NULL);
30
31         return pRuntime->GetIsolate();
32 }
33
34 BEGIN_JS_STATIC_CONST(CJS_PrintParamsObj)
35 END_JS_STATIC_CONST()
36
37 BEGIN_JS_STATIC_PROP(CJS_PrintParamsObj)
38 END_JS_STATIC_PROP()
39
40 BEGIN_JS_STATIC_METHOD(CJS_PrintParamsObj)
41 END_JS_STATIC_METHOD()
42
43 IMPLEMENT_JS_CLASS(CJS_PrintParamsObj, PrintParamsObj)
44
45 PrintParamsObj::PrintParamsObj(CJS_Object* pJSObject)
46 : CJS_EmbedObj(pJSObject)
47 {
48         bUI = TRUE;
49         nStart = 0;
50         nEnd = 0;
51         bSilent = FALSE;
52         bShrinkToFit = FALSE;
53         bPrintAsImage = FALSE;
54         bReverse = FALSE;
55         bAnnotations = TRUE;
56 }
57
58 /* ---------------------- Document ---------------------- */
59
60 #define MINWIDTH  5.0f
61 #define MINHEIGHT 5.0f
62
63 BEGIN_JS_STATIC_CONST(CJS_Document)
64 END_JS_STATIC_CONST()
65
66 BEGIN_JS_STATIC_PROP(CJS_Document)
67         JS_STATIC_PROP_ENTRY(ADBE)
68         JS_STATIC_PROP_ENTRY(author)
69         JS_STATIC_PROP_ENTRY(baseURL)
70         JS_STATIC_PROP_ENTRY(bookmarkRoot)
71         JS_STATIC_PROP_ENTRY(calculate)
72         JS_STATIC_PROP_ENTRY(Collab)
73         JS_STATIC_PROP_ENTRY(creationDate)
74         JS_STATIC_PROP_ENTRY(creator)
75         JS_STATIC_PROP_ENTRY(delay)
76         JS_STATIC_PROP_ENTRY(dirty)
77         JS_STATIC_PROP_ENTRY(documentFileName)
78         JS_STATIC_PROP_ENTRY(external)
79         JS_STATIC_PROP_ENTRY(filesize)
80         JS_STATIC_PROP_ENTRY(icons)
81         JS_STATIC_PROP_ENTRY(info)
82         JS_STATIC_PROP_ENTRY(keywords)
83         JS_STATIC_PROP_ENTRY(layout)
84         JS_STATIC_PROP_ENTRY(media)
85         JS_STATIC_PROP_ENTRY(modDate)
86         JS_STATIC_PROP_ENTRY(mouseX)
87         JS_STATIC_PROP_ENTRY(mouseY)
88         JS_STATIC_PROP_ENTRY(numFields)
89         JS_STATIC_PROP_ENTRY(numPages)
90         JS_STATIC_PROP_ENTRY(pageNum)
91         JS_STATIC_PROP_ENTRY(pageWindowRect)
92         JS_STATIC_PROP_ENTRY(path)
93         JS_STATIC_PROP_ENTRY(producer)
94         JS_STATIC_PROP_ENTRY(subject)
95         JS_STATIC_PROP_ENTRY(title)
96         JS_STATIC_PROP_ENTRY(zoom)
97         JS_STATIC_PROP_ENTRY(zoomType)
98 END_JS_STATIC_PROP()
99
100 BEGIN_JS_STATIC_METHOD(CJS_Document)
101         JS_STATIC_METHOD_ENTRY(addAnnot,0)
102         JS_STATIC_METHOD_ENTRY(addField, 4)
103         JS_STATIC_METHOD_ENTRY(addLink, 0)
104         JS_STATIC_METHOD_ENTRY(addIcon, 0)
105         JS_STATIC_METHOD_ENTRY(calculateNow, 0)
106         JS_STATIC_METHOD_ENTRY(closeDoc, 0)
107         JS_STATIC_METHOD_ENTRY(createDataObject, 0)
108         JS_STATIC_METHOD_ENTRY(deletePages, 2)
109         JS_STATIC_METHOD_ENTRY(exportAsText, 3)
110         JS_STATIC_METHOD_ENTRY(exportAsFDF, 6)
111         JS_STATIC_METHOD_ENTRY(exportAsXFDF, 5)
112         JS_STATIC_METHOD_ENTRY(extractPages, 3)
113         JS_STATIC_METHOD_ENTRY(getAnnot, 0)
114         JS_STATIC_METHOD_ENTRY(getAnnots, 2)
115         JS_STATIC_METHOD_ENTRY(getAnnot3D, 2)
116         JS_STATIC_METHOD_ENTRY(getAnnots3D, 1)
117         JS_STATIC_METHOD_ENTRY(getField, 1)
118         JS_STATIC_METHOD_ENTRY(getIcon, 0)
119         JS_STATIC_METHOD_ENTRY(getLinks, 0)
120         JS_STATIC_METHOD_ENTRY(getNthFieldName, 1)
121         JS_STATIC_METHOD_ENTRY(getOCGs, 0)
122         JS_STATIC_METHOD_ENTRY(getPageBox, 0)
123         JS_STATIC_METHOD_ENTRY(getPageNthWord, 3)
124         JS_STATIC_METHOD_ENTRY(getPageNthWordQuads, 2)
125         JS_STATIC_METHOD_ENTRY(getPageNumWords, 1)
126         JS_STATIC_METHOD_ENTRY(getPrintParams, 0)
127         JS_STATIC_METHOD_ENTRY(getURL, 2)
128         JS_STATIC_METHOD_ENTRY(importAnFDF, 1)
129         JS_STATIC_METHOD_ENTRY(importAnXFDF, 1)
130         JS_STATIC_METHOD_ENTRY(importTextData, 2)
131         JS_STATIC_METHOD_ENTRY(insertPages, 4)
132         JS_STATIC_METHOD_ENTRY(mailForm, 6)
133         JS_STATIC_METHOD_ENTRY(print, 9)
134         JS_STATIC_METHOD_ENTRY(removeField, 1)
135         JS_STATIC_METHOD_ENTRY(replacePages, 4)
136         JS_STATIC_METHOD_ENTRY(resetForm, 1)
137         JS_STATIC_METHOD_ENTRY(removeIcon, 0)
138         JS_STATIC_METHOD_ENTRY(saveAs, 5)
139         JS_STATIC_METHOD_ENTRY(submitForm, 23)
140         JS_STATIC_METHOD_ENTRY(mailDoc, 0)
141 END_JS_STATIC_METHOD()
142
143 IMPLEMENT_JS_CLASS(CJS_Document, Document)
144
145 FX_BOOL CJS_Document::InitInstance(IFXJS_Context* cc)
146 {
147         CJS_Context* pContext = (CJS_Context*)cc;
148         ASSERT(pContext != NULL);
149
150         Document* pDoc = (Document*)GetEmbedObject();
151         ASSERT(pDoc != NULL);
152
153         pDoc->AttachDoc(pContext->GetReaderDocument());
154         pDoc->SetIsolate(pContext->GetJSRuntime()->GetIsolate());
155         return TRUE;
156 };
157
158 /* --------------------------------- Document --------------------------------- */
159
160 Document::Document(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject),
161         m_isolate(NULL),
162         m_pIconTree(NULL),
163         m_pDocument(NULL),
164         m_cwBaseURL(L""),
165         m_bDelay(FALSE)
166 {
167 }
168
169 Document::~Document()
170 {
171         if (m_pIconTree)
172         {
173                 m_pIconTree->DeleteIconTree();
174                 delete m_pIconTree;
175                 m_pIconTree = NULL;
176         }
177         for (int i=0; i<m_DelayData.GetSize(); i++)
178         {
179                 if (CJS_DelayData* pData = m_DelayData.GetAt(i))
180                 {
181                         delete pData;
182                         pData = NULL;
183                         m_DelayData.SetAt(i, NULL);
184
185                 }
186         }
187
188         m_DelayData.RemoveAll();
189         m_DelayAnnotData.RemoveAll();
190 }
191
192 //the total number of fileds in document.
193 FX_BOOL Document::numFields(OBJ_PROP_PARAMS)
194 {
195         if (!vp.IsGetting()) return FALSE;
196
197         ASSERT(m_pDocument != NULL);
198
199         CPDFSDK_InterForm *pInterForm = m_pDocument->GetInterForm();
200         ASSERT(pInterForm != NULL);
201
202         CPDF_InterForm *pPDFForm = pInterForm->GetInterForm();
203         ASSERT(pPDFForm != NULL);
204
205         vp << (int)pPDFForm->CountFields();
206
207         return TRUE;
208 }
209
210 FX_BOOL Document::dirty(OBJ_PROP_PARAMS)
211 {
212         ASSERT(m_pDocument != NULL);
213
214         if (vp.IsGetting())
215         {
216                 if (m_pDocument->GetChangeMark())
217                         vp << true;
218                 else
219                         vp << false;
220         }
221         else
222         {
223                 bool bChanged = false;
224
225                 vp >> bChanged;
226
227                 if (bChanged)
228                         m_pDocument->SetChangeMark();
229                 else
230                         m_pDocument->ClearChangeMark();
231         }
232
233         return TRUE;
234 }
235
236 FX_BOOL Document::ADBE(OBJ_PROP_PARAMS)
237 {
238         ASSERT(m_pDocument != NULL);
239
240         if (vp.IsGetting())
241         {
242                 vp.SetNull();
243         }
244         else
245         {
246         }
247
248         return TRUE;
249 }
250
251 FX_BOOL Document::pageNum(OBJ_PROP_PARAMS)
252 {
253         ASSERT(m_pDocument != NULL);
254
255         if (vp.IsGetting())
256         {
257                 if (CPDFSDK_PageView* pPageView = m_pDocument->GetCurrentView())
258                 {
259                         vp << pPageView->GetPageIndex();
260                 }
261         }
262         else
263         {
264                 int iPageCount = m_pDocument->GetPageCount();
265
266                 int iPageNum = 0;
267                 vp >> iPageNum;
268
269                 CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
270                 if(!pEnv)
271                         return FALSE;
272
273                 if (iPageNum >= 0 && iPageNum < iPageCount)
274                 {
275                          pEnv->JS_docgotoPage(iPageNum);
276                 }
277                 else if (iPageNum >= iPageCount)
278                 {
279                          pEnv->JS_docgotoPage(iPageCount-1);
280                 }
281                 else if (iPageNum < 0)
282                 {
283                          pEnv->JS_docgotoPage(0);
284                 }
285         }
286
287         return TRUE;
288 }
289
290 FX_BOOL Document::ParserParams(JSObject* pObj,CJS_AnnotObj& annotobj)
291 {
292         // Not supported.
293         return TRUE;
294 }
295
296 FX_BOOL Document::addAnnot(OBJ_METHOD_PARAMS)
297 {
298         // Not supported.
299         return TRUE;
300 }
301
302 FX_BOOL Document::addField(OBJ_METHOD_PARAMS)
303 {
304         // Not supported.
305         return TRUE;
306 }
307
308 FX_BOOL Document::exportAsText(OBJ_METHOD_PARAMS)
309 {
310         // Unsafe, not supported.
311         return TRUE;
312 }
313
314 FX_BOOL Document::exportAsFDF(OBJ_METHOD_PARAMS)
315 {
316         // Unsafe, not supported.
317         return TRUE;
318 }
319
320 FX_BOOL Document::exportAsXFDF(OBJ_METHOD_PARAMS)
321 {
322         // Unsafe, not supported.
323         return TRUE;
324 }
325
326 //Maps a field object in PDF document to a JavaScript variable
327 //comment:
328 //note: the paremter cName, this is clue how to treat if the cName is not a valiable filed name in this document
329
330 FX_BOOL Document::getField(OBJ_METHOD_PARAMS)
331 {
332         v8::Isolate* isolate = GetIsolate(cc);
333         ASSERT(m_pDocument != NULL);
334
335         if (params.size() < 1) return FALSE;
336
337         CFX_WideString wideName = params[0].operator CFX_WideString();
338
339         CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
340         ASSERT(pInterForm != NULL);
341
342         CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
343         ASSERT(pPDFForm != NULL);
344
345         if (pPDFForm->CountFields(wideName) <= 0)
346         {
347                 vRet.SetNull();
348                 return TRUE;
349         }
350
351         CJS_Context* pContext = (CJS_Context*)cc;
352         ASSERT(pContext != NULL);
353         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
354         ASSERT(pRuntime != NULL);
355
356         JSFXObject  pFieldObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"Field"));
357
358         CJS_Field * pJSField = (CJS_Field*)JS_GetPrivate(isolate,pFieldObj);
359         ASSERT(pJSField != NULL);
360
361         Field * pField = (Field *)pJSField->GetEmbedObject();
362         ASSERT(pField != NULL);
363
364         pField->AttachField(this, wideName);
365         vRet = pJSField;
366
367         return TRUE;
368 }
369
370 //Gets the name of the nth field in the document
371 FX_BOOL Document::getNthFieldName(OBJ_METHOD_PARAMS)
372 {
373         ASSERT(m_pDocument != NULL);
374
375         int nIndex = params.size() > 0 ? (int)params[0] : -1;
376         if (nIndex == -1) return FALSE;
377
378         CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
379         ASSERT(pInterForm != NULL);
380
381         CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
382         ASSERT(pPDFForm != NULL);
383
384         CPDF_FormField* pField = pPDFForm->GetField(nIndex);
385         if (!pField)
386                 return FALSE;
387
388         vRet = pField->GetFullName();
389         return TRUE;
390 }
391
392 FX_BOOL Document::importAnFDF(OBJ_METHOD_PARAMS)
393 {
394         // Unsafe, not supported.
395         return TRUE;
396 }
397
398 FX_BOOL Document::importAnXFDF(OBJ_METHOD_PARAMS)
399 {
400         // Unsafe, not supported.
401         return TRUE;
402 }
403
404 FX_BOOL Document::importTextData(OBJ_METHOD_PARAMS)
405 {
406         // Unsafe, not supported.
407         return TRUE;
408 }
409
410 //exports the form data and mails the resulting fdf file as an attachment to all recipients.
411 //comment: need reader supports
412 //note:
413 //int CPDFSDK_Document::mailForm(FX_BOOL bUI,String cto,string ccc,string cbcc,string cSubject,string cms);
414
415 FX_BOOL Document::mailForm(OBJ_METHOD_PARAMS)
416 {
417         ASSERT(m_pDocument != NULL);
418
419         if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
420
421         int iLength = params.size();
422
423         FX_BOOL bUI = iLength > 0 ? (FX_BOOL)params[0] : TRUE;
424         CFX_WideString cTo = iLength > 1 ? (FX_LPCWSTR)params[1].operator CFX_WideString() : L"";
425         CFX_WideString cCc = iLength > 2 ? (FX_LPCWSTR)params[2].operator CFX_WideString() : L"";
426         CFX_WideString cBcc = iLength > 3 ? (FX_LPCWSTR)params[3].operator CFX_WideString() : L"";
427         CFX_WideString cSubject = iLength > 4 ? (FX_LPCWSTR)params[4].operator CFX_WideString() : L"";
428         CFX_WideString cMsg = iLength > 5 ? (FX_LPCWSTR)params[5].operator CFX_WideString() : L"";
429
430         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
431         ASSERT(pInterForm != NULL);
432
433         CFX_ByteTextBuf textBuf;
434         if (!pInterForm->ExportFormToFDFTextBuf(textBuf))
435                 return FALSE;
436
437         CJS_Context* pContext = (CJS_Context*)cc;
438         ASSERT(pContext != NULL);
439         CPDFDoc_Environment* pEnv = pContext->GetReaderApp();
440         ASSERT(pEnv != NULL);
441         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
442         ASSERT(pRuntime != NULL);
443
444         pRuntime->BeginBlock();
445         pEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI, cTo.c_str(), cSubject.c_str(), cCc.c_str(), cBcc.c_str(), cMsg.c_str());
446         pRuntime->EndBlock();
447         return TRUE;
448 }
449
450 FX_BOOL Document::print(OBJ_METHOD_PARAMS)
451 {
452         CJS_Context* pContext = (CJS_Context*)cc;
453         ASSERT(pContext != NULL);
454         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
455         ASSERT(pRuntime != NULL);
456
457         FX_BOOL bUI = TRUE;
458         int nStart = 0;
459         int nEnd = 0;
460         FX_BOOL bSilent = FALSE;
461         FX_BOOL bShrinkToFit = FALSE;
462         FX_BOOL bPrintAsImage = FALSE;
463         FX_BOOL bReverse = FALSE;
464         FX_BOOL bAnnotations = FALSE;
465
466         int nlength = params.size();
467         if(nlength ==9)
468         {
469                 if (params[8].GetType() == VT_fxobject)
470                 {
471                         JSFXObject pObj = (JSFXObject)params[8];
472                         {
473                                 if (JS_GetObjDefnID(pObj) == JS_GetObjDefnID(*pRuntime, L"PrintParamsObj"))
474                                 {
475                                         if (CJS_Object* pJSObj = (CJS_Object*)params[8])
476                                         {
477                                                         if (PrintParamsObj* pprintparamsObj = (PrintParamsObj*)pJSObj->GetEmbedObject())
478                                                         {
479                                                                 bUI = pprintparamsObj->bUI;
480                                                                 nStart = pprintparamsObj->nStart;
481                                                                 nEnd = pprintparamsObj->nEnd;
482                                                                 bSilent = pprintparamsObj->bSilent;
483                                                                 bShrinkToFit = pprintparamsObj->bShrinkToFit;
484                                                                 bPrintAsImage = pprintparamsObj->bPrintAsImage;
485                                                                 bReverse = pprintparamsObj->bReverse;
486                                                                 bAnnotations = pprintparamsObj->bAnnotations;
487                                                         }
488                                         }
489                                 }
490                         }
491                 }
492         }
493         else
494         {
495                 if(nlength >= 1)
496                          bUI = params[0];
497                 if(nlength >= 2)
498                          nStart = (int)params[1];
499                 if(nlength >= 3)
500                         nEnd = (int)params[2];
501                 if(nlength >= 4)
502                         bSilent = params[3];
503                 if(nlength >= 5)
504                         bShrinkToFit = params[4];
505                 if(nlength >= 6)
506                         bPrintAsImage = params[5];
507                 if(nlength >= 7)
508                         bReverse = params[6];
509                 if(nlength >= 8)
510                         bAnnotations = params[7];
511         }
512
513         ASSERT(m_pDocument != NULL);
514
515         if (CPDFDoc_Environment* pEnv = m_pDocument->GetEnv())
516         {
517                 pEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit, bPrintAsImage, bReverse, bAnnotations);
518                 return TRUE;
519         }
520         return FALSE;
521 }
522
523 //removes the specified field from the document.
524 //comment:
525 //note: if the filed name is not retional, adobe is dumb for it.
526
527 FX_BOOL Document::removeField(OBJ_METHOD_PARAMS)
528 {
529         ASSERT(m_pDocument != NULL);
530
531         if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
532                 m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM))) return FALSE;
533
534         if (params.size() < 1)
535                 return TRUE;
536
537         CFX_WideString sFieldName = params[0].operator CFX_WideString();
538
539         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
540         ASSERT(pInterForm != NULL);
541
542         CFX_PtrArray widgets;
543         pInterForm->GetWidgets(sFieldName, widgets);
544
545         int nSize = widgets.GetSize();
546
547         if (nSize > 0)
548         {
549                 for (int i=0; i<nSize; i++)
550                 {
551                         CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)widgets[i];
552                         ASSERT(pWidget != NULL);
553
554                         CPDF_Rect rcAnnot = pWidget->GetRect();
555                         rcAnnot.left -= 1;
556                         rcAnnot.bottom -= 1;
557                         rcAnnot.right += 1;
558                         rcAnnot.top += 1;
559
560                         CFX_RectArray aRefresh;
561                         aRefresh.Add(rcAnnot);
562
563                         CPDF_Page* pPage = pWidget->GetPDFPage();
564                         ASSERT(pPage != NULL);
565
566                         CPDFSDK_PageView* pPageView = m_pDocument->GetPageView(pPage);
567                         pPageView->DeleteAnnot(pWidget);
568
569                         pPageView->UpdateRects(aRefresh);
570                 }
571                 m_pDocument->SetChangeMark();
572         }
573
574         return TRUE;
575 }
576
577 //reset filed values within a document.
578 //comment:
579 //note: if the fields names r not rational, aodbe is dumb for it.
580
581 FX_BOOL Document::resetForm(OBJ_METHOD_PARAMS)
582 {
583         ASSERT(m_pDocument != NULL);
584
585         if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
586                 m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM) ||
587                 m_pDocument->GetPermissions(FPDFPERM_FILL_FORM))) return FALSE;
588
589         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
590         ASSERT(pInterForm != NULL);
591
592         CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
593         ASSERT(pPDFForm != NULL);
594
595         v8::Isolate* isolate = GetIsolate(cc);
596         CJS_Array aName(isolate);
597
598         if (params.size() > 0)
599         {
600                 switch (params[0].GetType())
601                 {
602                 default:
603                         aName.Attach(params[0]);
604                         break;
605                 case VT_string:
606                         aName.SetElement(0,params[0]);
607                         break;
608                 }
609
610                 CFX_PtrArray aFields;
611
612                 for (int i=0,isz=aName.GetLength(); i<isz; i++)
613                 {
614                         CJS_Value valElement(isolate);
615                         aName.GetElement(i,valElement);
616                         CFX_WideString swVal = valElement.operator CFX_WideString();
617
618                         for (int j=0,jsz=pPDFForm->CountFields(swVal); j<jsz; j++)
619                         {
620                                 aFields.Add((void*)pPDFForm->GetField(j,swVal));
621                         }
622                 }
623
624                 if (aFields.GetSize() > 0)
625                 {
626                         pPDFForm->ResetForm(aFields, TRUE, TRUE);
627                         m_pDocument->SetChangeMark();
628
629                 }
630         }
631         else
632         {
633                 pPDFForm->ResetForm(TRUE);
634                 m_pDocument->SetChangeMark();
635
636         }
637
638         return TRUE;
639 }
640
641
642 FX_BOOL Document::saveAs(OBJ_METHOD_PARAMS)
643 {
644   // Unsafe, not supported.
645   return TRUE;
646 }
647
648
649 FX_BOOL Document::submitForm(OBJ_METHOD_PARAMS)
650 {
651         ASSERT(m_pDocument != NULL);
652
653 //      if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
654
655         int nSize = params.size();
656         if (nSize < 1) return FALSE;
657
658         CFX_WideString strURL;
659         FX_BOOL bFDF = TRUE;
660         FX_BOOL bEmpty = FALSE;
661         v8::Isolate* isolate = GetIsolate(cc);
662         CJS_Array aFields(isolate);
663
664         CJS_Value v = params[0];
665         if (v.GetType() == VT_string)
666         {
667                 strURL = params[0].operator CFX_WideString();
668                 if (nSize > 1)
669                         bFDF = params[1];
670                 if (nSize > 2)
671                         bEmpty = params[2];
672                 if (nSize > 3)
673                         aFields.Attach(params[3]);
674         }
675         else if (v.GetType() == VT_object)
676         {
677                 JSObject pObj = (JSObject)params[0];
678                 v8::Handle<v8::Value> pValue = JS_GetObjectElement(isolate,pObj, L"cURL");
679                 if (!pValue.IsEmpty())
680                         strURL = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue));
681                 pValue = JS_GetObjectElement(isolate,pObj, L"bFDF");
682                         bFDF = CJS_Value(isolate,pValue, GET_VALUE_TYPE(pValue));
683                 pValue = JS_GetObjectElement(isolate,pObj, L"bEmpty");
684                         bEmpty = CJS_Value(isolate,pValue, GET_VALUE_TYPE(pValue));
685                 pValue = JS_GetObjectElement(isolate,pObj,L"aFields");
686                         aFields.Attach(CJS_Value(isolate,pValue, GET_VALUE_TYPE(pValue)));
687         }
688
689         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
690         ASSERT(pInterForm != NULL);
691         CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
692         ASSERT(pPDFInterForm != NULL);
693
694         FX_BOOL bAll = (aFields.GetLength() == 0);
695
696         if (bAll && bEmpty)
697         {
698                 CJS_Context* pContext = (CJS_Context*)cc;
699                 ASSERT(pContext != NULL);
700                 CJS_Runtime* pRuntime = pContext->GetJSRuntime();
701                 ASSERT(pRuntime != NULL);
702
703
704                 if (pPDFInterForm->CheckRequiredFields())
705                 {
706                         pRuntime->BeginBlock();
707                         pInterForm->SubmitForm(strURL, FALSE);
708                         pRuntime->EndBlock();
709                 }
710
711                 return TRUE;
712         }
713         else
714         {
715                 CFX_PtrArray fieldObjects;
716
717                 for (int i=0,sz=aFields.GetLength(); i<sz; i++)
718                 {
719                         CJS_Value valName(isolate);
720                         aFields.GetElement(i, valName);
721                         CFX_WideString sName = valName.operator CFX_WideString();
722
723                         CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
724                         ASSERT(pPDFForm != NULL);
725
726                         for (int j=0, jsz=pPDFForm->CountFields(sName); j<jsz; j++)
727                         {
728                                 CPDF_FormField* pField = pPDFForm->GetField(j, sName);
729                                 if (!bEmpty && pField->GetValue().IsEmpty())
730                                         continue;
731
732                                 fieldObjects.Add(pField);
733                         }
734                 }
735
736                 CJS_Context* pContext = (CJS_Context*)cc;
737                 ASSERT(pContext != NULL);
738                 CJS_Runtime* pRuntime = pContext->GetJSRuntime();
739                 ASSERT(pRuntime != NULL);
740
741
742                 if (pPDFInterForm->CheckRequiredFields(&fieldObjects, TRUE))
743                 {
744                         pRuntime->BeginBlock();
745                         pInterForm->SubmitFields(strURL, fieldObjects, TRUE, !bFDF);
746                         pRuntime->EndBlock();
747                 }
748
749                 return TRUE;
750         }
751
752 }
753
754 //////////////////////////////////////////////////////////////////////////////////////////////
755
756 void Document::AttachDoc(CPDFSDK_Document *pDoc)
757 {
758         m_pDocument = pDoc;
759 }
760
761 CPDFSDK_Document * Document::GetReaderDoc()
762 {
763         return m_pDocument;
764 }
765
766 FX_BOOL Document::ExtractFileName(CPDFSDK_Document *pDoc,CFX_ByteString &strFileName)
767 {
768         return FALSE;
769 }
770
771 FX_BOOL Document::ExtractFolderName(CPDFSDK_Document *pDoc,CFX_ByteString &strFolderName)
772 {
773         return FALSE;
774 }
775
776 FX_BOOL Document::bookmarkRoot(OBJ_PROP_PARAMS)
777 {
778         return TRUE;
779 }
780
781 FX_BOOL Document::mailDoc(OBJ_METHOD_PARAMS)
782 {
783         ASSERT(m_pDocument != NULL);
784
785         FX_BOOL bUI = TRUE;
786         CFX_WideString cTo = L"";
787         CFX_WideString cCc = L"";
788         CFX_WideString cBcc = L"";
789         CFX_WideString cSubject = L"";
790         CFX_WideString cMsg = L"";
791
792
793         bUI = params.size()>=1?static_cast<FX_BOOL>(params[0]):TRUE;
794         cTo = params.size()>=2?(const wchar_t*)params[1].operator CFX_WideString():L"";
795         cCc = params.size()>=3?(const wchar_t*)params[2].operator CFX_WideString():L"";
796         cBcc = params.size()>=4?(const wchar_t*)params[3].operator CFX_WideString():L"";
797         cSubject = params.size()>=5?(const wchar_t*)params[4].operator CFX_WideString():L"";
798         cMsg = params.size()>=6?(const wchar_t*)params[5].operator CFX_WideString():L"";
799
800         v8::Isolate* isolate = GetIsolate(cc);
801
802         if(params.size()>=1 && params[0].GetType() == VT_object)
803         {
804                 JSObject  pObj = (JSObject )params[0];
805
806                 v8::Handle<v8::Value> pValue = JS_GetObjectElement(isolate,pObj, L"bUI");
807                         bUI = (int)CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue));
808
809                 pValue = JS_GetObjectElement(isolate,pObj, L"cTo");
810                         cTo = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).operator CFX_WideString();
811
812                 pValue = JS_GetObjectElement(isolate,pObj, L"cCc");
813                         cCc = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).operator CFX_WideString();
814
815                 pValue = JS_GetObjectElement(isolate,pObj, L"cBcc");
816                         cBcc = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).operator CFX_WideString();
817
818                 pValue = JS_GetObjectElement(isolate,pObj, L"cSubject");
819                         cSubject = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).operator CFX_WideString();
820
821                 pValue = JS_GetObjectElement(isolate,pObj, L"cMsg");
822                         cMsg = CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue)).operator CFX_WideString();
823
824         }
825
826         CJS_Context* pContext = (CJS_Context*)cc;
827         ASSERT(pContext != NULL);
828         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
829         ASSERT(pRuntime != NULL);
830
831         pRuntime->BeginBlock();
832         CPDFDoc_Environment* pEnv = pRuntime->GetReaderApp();
833         pEnv->JS_docmailForm(NULL, 0, bUI, cTo.c_str(), cSubject.c_str(), cCc.c_str(), cBcc.c_str(), cMsg.c_str());
834         pRuntime->EndBlock();
835
836         return TRUE;
837 }
838
839 FX_BOOL Document::author(OBJ_PROP_PARAMS)
840 {
841         ASSERT(m_pDocument != NULL);
842
843         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
844         if (!pDictionary)return FALSE;
845
846         if (vp.IsGetting())
847         {
848                 vp << pDictionary->GetUnicodeText("Author");
849                 return TRUE;
850         }
851         else
852         {
853                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
854
855                 CFX_WideString csAuthor;
856                 vp >> csAuthor;
857                 pDictionary->SetAtString("Author", PDF_EncodeText(csAuthor));
858                 m_pDocument->SetChangeMark();
859                 return TRUE;
860         }
861 }
862
863 FX_BOOL Document::info(OBJ_PROP_PARAMS)
864 {
865         ASSERT(m_pDocument != NULL);
866
867         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
868         if (!pDictionary)return FALSE;
869
870         CFX_WideString cwAuthor                 = pDictionary->GetUnicodeText("Author");
871         CFX_WideString cwTitle                  = pDictionary->GetUnicodeText("Title");
872         CFX_WideString cwSubject                = pDictionary->GetUnicodeText("Subject");
873         CFX_WideString cwKeywords               = pDictionary->GetUnicodeText("Keywords");
874         CFX_WideString cwCreator                = pDictionary->GetUnicodeText("Creator");
875         CFX_WideString cwProducer               = pDictionary->GetUnicodeText("Producer");
876         CFX_WideString cwCreationDate   = pDictionary->GetUnicodeText("CreationDate");
877         CFX_WideString cwModDate                = pDictionary->GetUnicodeText("ModDate");
878         CFX_WideString cwTrapped                = pDictionary->GetUnicodeText("Trapped");
879
880         v8::Isolate* isolate = GetIsolate(cc);
881         if (!vp.IsSetting())
882         {
883                 CJS_Context* pContext = (CJS_Context *)cc;
884                 CJS_Runtime* pRuntime = pContext->GetJSRuntime();
885
886                 JSFXObject  pObj = JS_NewFxDynamicObj(*pRuntime, pContext, -1);
887
888                 JS_PutObjectString(isolate,pObj, L"Author", cwAuthor);
889                 JS_PutObjectString(isolate,pObj, L"Title", cwTitle);
890                 JS_PutObjectString(isolate,pObj, L"Subject", cwSubject);
891                 JS_PutObjectString(isolate,pObj, L"Keywords", cwKeywords);
892                 JS_PutObjectString(isolate,pObj, L"Creator", cwCreator);
893                 JS_PutObjectString(isolate,pObj, L"Producer", cwProducer);
894                 JS_PutObjectString(isolate,pObj, L"CreationDate", cwCreationDate);
895                 JS_PutObjectString(isolate,pObj, L"ModDate", cwModDate);
896                 JS_PutObjectString(isolate,pObj, L"Trapped", cwTrapped);
897
898 // It's to be compatible to non-standard info dictionary.
899                 FX_POSITION pos = pDictionary->GetStartPos();
900                 while(pos)
901                 {
902                         CFX_ByteString bsKey;
903                         CPDF_Object* pValueObj = pDictionary->GetNextElement(pos, bsKey);
904                         CFX_WideString wsKey  = CFX_WideString::FromUTF8(bsKey, bsKey.GetLength());
905                         if((pValueObj->GetType()==PDFOBJ_STRING) || (pValueObj->GetType()==PDFOBJ_NAME) )
906                                         JS_PutObjectString(isolate,pObj, wsKey, pValueObj->GetUnicodeText());
907                         if(pValueObj->GetType()==PDFOBJ_NUMBER)
908                                 JS_PutObjectNumber(isolate,pObj, wsKey, (float)pValueObj->GetNumber());
909                         if(pValueObj->GetType()==PDFOBJ_BOOLEAN)
910                                 JS_PutObjectBoolean(isolate,pObj, wsKey, (bool)pValueObj->GetInteger());
911                 }
912
913                 vp << pObj;
914                 return TRUE;
915         }
916         else
917         {
918                 return TRUE;
919         }
920 }
921
922 FX_BOOL Document::creationDate(OBJ_PROP_PARAMS)
923 {
924         ASSERT(m_pDocument != NULL);
925
926         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
927         if (!pDictionary)return FALSE;
928
929         if (vp.IsGetting())
930         {
931                 vp << pDictionary->GetUnicodeText("CreationDate");
932                 return TRUE;
933         }
934         else
935         {
936                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
937
938                 CFX_WideString csCreationDate;
939                 vp >> csCreationDate;
940                 pDictionary->SetAtString("CreationDate", PDF_EncodeText(csCreationDate));
941                 m_pDocument->SetChangeMark();
942
943                 return TRUE;
944         }
945 }
946
947 FX_BOOL Document::creator(OBJ_PROP_PARAMS)
948 {
949         ASSERT(m_pDocument != NULL);
950
951         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
952         if (!pDictionary)return FALSE;
953
954         if (vp.IsGetting())
955         {
956                 vp << pDictionary->GetUnicodeText("Creator");
957                 return TRUE;
958         }
959         else
960         {
961                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
962
963                 CFX_WideString csCreator;
964                 vp >> csCreator;
965                 pDictionary->SetAtString("Creator", PDF_EncodeText(csCreator));
966                 m_pDocument->SetChangeMark();
967                 return TRUE;
968         }
969 }
970
971 FX_BOOL Document::delay(OBJ_PROP_PARAMS)
972 {
973         if (vp.IsGetting())
974         {
975                 vp << m_bDelay;
976                 return TRUE;
977         }
978         else
979         {
980                 ASSERT(m_pDocument != NULL);
981
982                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
983
984                 bool b;
985                 vp >> b;
986
987                 m_bDelay = b;
988
989                 if (m_bDelay)
990                 {
991                         for (int i=0,sz=m_DelayData.GetSize(); i<sz; i++)
992                                 delete m_DelayData.GetAt(i);
993
994                         m_DelayData.RemoveAll();
995                 }
996                 else
997                 {
998                         for (int i=0,sz=m_DelayData.GetSize(); i<sz; i++)
999                         {
1000                                 if (CJS_DelayData* pData = m_DelayData.GetAt(i))
1001                                 {
1002                                         Field::DoDelay(m_pDocument, pData);
1003                                         delete m_DelayData.GetAt(i);
1004                                 }
1005                         }
1006                         m_DelayData.RemoveAll();
1007                 }
1008
1009                 return TRUE;
1010         }
1011 }
1012
1013 FX_BOOL Document::keywords(OBJ_PROP_PARAMS)
1014 {
1015         ASSERT(m_pDocument != NULL);
1016
1017         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
1018         if (!pDictionary)return FALSE;
1019
1020         if (vp.IsGetting())
1021         {
1022                 vp << pDictionary->GetUnicodeText("Keywords");
1023                 return TRUE;
1024         }
1025         else
1026         {
1027                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1028
1029                 CFX_WideString csKeywords;
1030                 vp >> csKeywords;
1031                 pDictionary->SetAtString("Keywords", PDF_EncodeText(csKeywords));
1032                 m_pDocument->SetChangeMark();
1033                 return TRUE;
1034         }
1035 }
1036
1037 FX_BOOL Document::modDate(OBJ_PROP_PARAMS)
1038 {
1039         ASSERT(m_pDocument != NULL);
1040
1041         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
1042         if (!pDictionary)return FALSE;
1043
1044         if (vp.IsGetting())
1045         {
1046                 vp << pDictionary->GetUnicodeText("ModDate");
1047                 return TRUE;
1048         }
1049         else
1050         {
1051                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1052
1053                 CFX_WideString csmodDate;
1054                 vp >> csmodDate;
1055                 pDictionary->SetAtString("ModDate", PDF_EncodeText(csmodDate));
1056                 m_pDocument->SetChangeMark();
1057                 return TRUE;
1058         }
1059 }
1060
1061 FX_BOOL Document::producer(OBJ_PROP_PARAMS)
1062 {
1063         ASSERT(m_pDocument != NULL);
1064
1065         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
1066         if (!pDictionary)return FALSE;
1067
1068         if (vp.IsGetting())
1069         {
1070                 vp << pDictionary->GetUnicodeText("Producer");
1071                 return TRUE;
1072         }
1073         else
1074         {
1075                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1076
1077                 CFX_WideString csproducer;
1078                 vp >> csproducer;
1079                 pDictionary->SetAtString("Producer", PDF_EncodeText(csproducer));
1080                 m_pDocument->SetChangeMark();
1081                 return TRUE;
1082         }
1083 }
1084
1085 FX_BOOL Document::subject(OBJ_PROP_PARAMS)
1086 {
1087         ASSERT(m_pDocument != NULL);
1088
1089         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
1090         if (!pDictionary)return FALSE;
1091
1092         if (vp.IsGetting())
1093         {
1094                 vp << pDictionary->GetUnicodeText("Subject");
1095                 return TRUE;
1096         }
1097         else
1098         {
1099                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1100
1101                 CFX_WideString cssubject;
1102                 vp >> cssubject;
1103                 pDictionary->SetAtString("Subject", PDF_EncodeText(cssubject));
1104                 m_pDocument->SetChangeMark();
1105                 return TRUE;
1106         }
1107 }
1108
1109 FX_BOOL Document::title(OBJ_PROP_PARAMS)
1110 {
1111         ASSERT(m_pDocument != NULL);
1112
1113         if (m_pDocument == NULL || m_pDocument->GetDocument() == NULL)
1114                 return FALSE;
1115
1116         CPDF_Dictionary* pDictionary = m_pDocument->GetDocument()->GetInfo();
1117         if (!pDictionary)return FALSE;
1118
1119         if (vp.IsGetting())
1120         {
1121                 vp << pDictionary->GetUnicodeText("Title");
1122                 return TRUE;
1123         }
1124         else
1125         {
1126                 if (!m_pDocument->GetPermissions(FPDFPERM_MODIFY)) return FALSE;
1127
1128                 CFX_WideString cstitle;
1129                 vp >> cstitle;
1130                 pDictionary->SetAtString("Title", PDF_EncodeText(cstitle));
1131                 m_pDocument->SetChangeMark();
1132                 return TRUE;
1133         }
1134 }
1135
1136 FX_BOOL Document::numPages(OBJ_PROP_PARAMS)
1137 {
1138         if (vp.IsGetting())
1139         {
1140                 ASSERT(m_pDocument != NULL);
1141                 vp << m_pDocument->GetPageCount();
1142                 return TRUE;
1143         }
1144         else
1145         {
1146                 return FALSE;
1147         }
1148 }
1149
1150 FX_BOOL Document::external(OBJ_PROP_PARAMS)
1151 {
1152         //In Chrome case,should always return true.
1153         vp << TRUE;
1154         return TRUE;
1155 }
1156
1157 FX_BOOL Document::filesize(OBJ_PROP_PARAMS)
1158 {
1159         if (!vp.IsGetting())return FALSE;
1160
1161         ASSERT(m_pDocument != NULL);
1162
1163 //      CFile file(m_pDocument->GetPath(), CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone);
1164 //      vp << (double)file.GetLength();
1165 //      file.Close();
1166
1167         if ( m_pDocument->GetPath().IsEmpty() == FALSE)
1168         {
1169                 CFX_ByteString bsStr = CFX_ByteString::FromUnicode( m_pDocument->GetPath() );
1170                 FILE * pFile = NULL;
1171                 pFile = fopen( bsStr.GetBuffer( bsStr.GetLength() ), "rb" );
1172                 if ( pFile )
1173                 {
1174                         fseek( pFile, 0, SEEK_END );
1175                         long lSize = ftell( pFile );
1176                         fclose( pFile );
1177                         pFile = NULL;
1178
1179                         vp << (FX_INT32)(lSize);
1180                         return TRUE;
1181                 }
1182         }
1183
1184         vp << 0;
1185         return TRUE;
1186 }
1187
1188 FX_BOOL Document::mouseX(OBJ_PROP_PARAMS)
1189 {
1190         return TRUE;
1191 }
1192
1193 FX_BOOL Document::mouseY(OBJ_PROP_PARAMS)
1194 {
1195         return TRUE;
1196 }
1197
1198 FX_BOOL Document::baseURL(OBJ_PROP_PARAMS)
1199 {
1200         if (vp.IsGetting())
1201         {
1202                 vp << m_cwBaseURL;
1203                 return TRUE;
1204         }
1205         else
1206         {
1207                 vp >> m_cwBaseURL;
1208                 return TRUE;
1209         }
1210 }
1211
1212 FX_BOOL Document::calculate(OBJ_PROP_PARAMS)
1213 {
1214         ASSERT(m_pDocument != NULL);
1215
1216         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
1217         ASSERT(pInterForm != NULL);
1218
1219         if (vp.IsGetting())
1220         {
1221                 if (pInterForm->IsCalculateEnabled())
1222                         vp << true;
1223                 else
1224                         vp << false;
1225         }
1226         else
1227         {
1228                 bool bCalculate;
1229                 vp >> bCalculate;
1230
1231                 pInterForm->EnableCalculate(bCalculate);
1232         }
1233
1234         return TRUE;
1235 }
1236
1237 FX_BOOL Document::documentFileName(OBJ_PROP_PARAMS)
1238 {
1239         if (!vp.IsGetting())
1240                 return FALSE;
1241
1242         CFX_WideString wsFilePath = m_pDocument->GetPath();
1243
1244         FX_INT32 i = wsFilePath.GetLength() - 1;
1245         for ( ; i >= 0; i-- )
1246         {
1247                 if ( wsFilePath.GetAt( i ) == L'\\' || wsFilePath.GetAt( i ) == L'/' )
1248                         break;
1249         }
1250         if ( i >= 0 && i < wsFilePath.GetLength() - 1 )
1251         {
1252                 vp << ( wsFilePath.GetBuffer( wsFilePath.GetLength() ) + i + 1 );
1253         }else{
1254                 vp << L"";
1255         }
1256         return TRUE;
1257 }
1258
1259 CFX_WideString Document::ReversalStr(CFX_WideString cbFrom)
1260 {
1261         size_t iLength = cbFrom.GetLength();
1262         pdfium::base::CheckedNumeric<size_t> iSize = sizeof(wchar_t);
1263         iSize *= (iLength + 1);
1264         wchar_t* pResult = (wchar_t*)malloc(iSize.ValueOrDie());
1265         wchar_t* pFrom = (wchar_t*)cbFrom.GetBuffer(iLength);
1266
1267         for (size_t i = 0; i < iLength; i++)
1268         {
1269                 pResult[i] = *(pFrom + iLength - i - 1);
1270         }
1271         pResult[iLength] = L'\0';
1272
1273         cbFrom.ReleaseBuffer();
1274         CFX_WideString cbRet = CFX_WideString(pResult);
1275         free(pResult);
1276         pResult = NULL;
1277         return cbRet;
1278 }
1279
1280 CFX_WideString Document::CutString(CFX_WideString cbFrom)
1281 {
1282         size_t iLength = cbFrom.GetLength();
1283         pdfium::base::CheckedNumeric<size_t> iSize = sizeof(wchar_t);
1284         iSize *= (iLength + 1);
1285         wchar_t* pResult = (wchar_t*)malloc(iSize.ValueOrDie());
1286         wchar_t* pFrom = (wchar_t*)cbFrom.GetBuffer(iLength);
1287
1288         for (int i = 0; i < iLength; i++)
1289         {
1290                 if (pFrom[i] == L'\\' || pFrom[i] == L'/')
1291                 {
1292                         pResult[i] = L'\0';
1293                         break;
1294                 }
1295                 pResult[i] = pFrom[i];
1296         }
1297         pResult[iLength] = L'\0';
1298
1299         cbFrom.ReleaseBuffer();
1300         CFX_WideString cbRet = CFX_WideString(pResult);
1301         free(pResult);
1302         pResult = NULL;
1303         return cbRet;
1304 }
1305
1306 FX_BOOL Document::path(OBJ_PROP_PARAMS)
1307 {
1308         if (!vp.IsGetting()) return FALSE;
1309
1310         vp << app::SysPathToPDFPath(m_pDocument->GetPath());
1311
1312         return TRUE;
1313 }
1314
1315 FX_BOOL Document::pageWindowRect(OBJ_PROP_PARAMS)
1316 {
1317         return TRUE;
1318 }
1319
1320 FX_BOOL Document::layout(OBJ_PROP_PARAMS)
1321 {
1322         return TRUE;
1323 }
1324
1325 FX_BOOL Document::addLink(OBJ_METHOD_PARAMS)
1326 {
1327         return TRUE;
1328 }
1329
1330 FX_BOOL Document::closeDoc(OBJ_METHOD_PARAMS)
1331 {
1332         ASSERT(m_pDocument != NULL);
1333
1334
1335
1336
1337
1338         return TRUE;
1339 }
1340
1341 FX_BOOL Document::getPageBox(OBJ_METHOD_PARAMS)
1342 {
1343         return TRUE;
1344 }
1345
1346
1347 FX_BOOL Document::getAnnot(OBJ_METHOD_PARAMS)
1348 {
1349         return TRUE;
1350 }
1351
1352 FX_BOOL Document::getAnnots(OBJ_METHOD_PARAMS)
1353 {
1354         vRet.SetNull();
1355         return TRUE;
1356 }
1357
1358 FX_BOOL Document::getAnnot3D(OBJ_METHOD_PARAMS)
1359 {
1360         vRet.SetNull();
1361         return TRUE;
1362 }
1363
1364 FX_BOOL Document::getAnnots3D(OBJ_METHOD_PARAMS)
1365 {
1366         vRet = VT_undefined;
1367         return TRUE;
1368 }
1369
1370 FX_BOOL Document::getOCGs(OBJ_METHOD_PARAMS)
1371 {
1372         return TRUE;
1373 }
1374
1375 FX_BOOL Document::getLinks(OBJ_METHOD_PARAMS)
1376 {
1377         return TRUE;
1378 }
1379
1380 bool Document::IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect)
1381 {
1382         if (rect.left <= LinkRect.left
1383           && rect.top <= LinkRect.top
1384           && rect.right >= LinkRect.right
1385           && rect.bottom >= LinkRect.bottom)
1386                 return true;
1387         else
1388                 return false;
1389 }
1390
1391 void IconTree::InsertIconElement(IconElement* pNewIcon)
1392 {
1393         if (!pNewIcon)return;
1394
1395         if (m_pHead == NULL && m_pEnd == NULL)
1396         {
1397                 m_pHead = m_pEnd = pNewIcon;
1398                 m_iLength++;
1399         }
1400         else
1401         {
1402                 m_pEnd->NextIcon = pNewIcon;
1403                 m_pEnd = pNewIcon;
1404                 m_iLength++;
1405         }
1406 }
1407
1408 void IconTree::DeleteIconTree()
1409 {
1410         if (!m_pHead || !m_pEnd)return;
1411
1412         IconElement* pTemp = NULL;
1413         while(m_pEnd != m_pHead)
1414         {
1415                 pTemp = m_pHead;
1416                 m_pHead = m_pHead->NextIcon;
1417                 delete pTemp;
1418         }
1419
1420         delete m_pEnd;
1421         m_pHead = NULL;
1422         m_pEnd = NULL;
1423 }
1424
1425 int IconTree::GetLength()
1426 {
1427         return m_iLength;
1428 }
1429
1430 IconElement* IconTree::operator [](int iIndex)
1431 {
1432         if (iIndex >= 0 && iIndex <= m_iLength)
1433         {
1434                 IconElement* pTemp = m_pHead;
1435                 for (int i = 0; i < iIndex; i++)
1436                 {
1437                         pTemp = pTemp->NextIcon;
1438                 }
1439                 return pTemp;
1440         }
1441         else
1442                 return NULL;
1443 }
1444
1445 void IconTree::DeleteIconElement(CFX_WideString swIconName)
1446 {
1447         IconElement* pTemp = m_pHead;
1448         int iLoopCount = m_iLength;
1449         for (int i = 0; i < iLoopCount - 1; i++)
1450         {
1451                 if (pTemp == m_pEnd)
1452                         break;
1453
1454                 if (m_pHead->IconName == swIconName)
1455                 {
1456                         m_pHead = m_pHead->NextIcon;
1457                         delete pTemp;
1458                         m_iLength--;
1459                         pTemp = m_pHead;
1460                 }
1461                 if (pTemp->NextIcon->IconName == swIconName)
1462                 {
1463                         if (pTemp->NextIcon == m_pEnd)
1464                         {
1465                                 m_pEnd = pTemp;
1466                                 delete pTemp->NextIcon;
1467                                 m_iLength--;
1468                                 pTemp->NextIcon = NULL;
1469                         }
1470                         else
1471                         {
1472                                 IconElement* pElement = pTemp->NextIcon;
1473                                 pTemp->NextIcon = pTemp->NextIcon->NextIcon;
1474                                 delete pElement;
1475                                 m_iLength--;
1476                                 pElement = NULL;
1477                         }
1478
1479                         continue;
1480                 }
1481
1482                 pTemp = pTemp->NextIcon;
1483         }
1484 }
1485
1486 FX_BOOL Document::addIcon(OBJ_METHOD_PARAMS)
1487 {
1488         if (params.size() != 2)return FALSE;
1489
1490         CJS_Context* pContext = (CJS_Context*)cc;
1491         ASSERT(pContext != NULL);
1492         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1493         ASSERT(pRuntime != NULL);
1494
1495         CFX_WideString swIconName = params[0].operator CFX_WideString();
1496
1497         JSFXObject pJSIcon = (JSFXObject)params[1];
1498         if (JS_GetObjDefnID(pJSIcon) != JS_GetObjDefnID(*pRuntime, L"Icon")) return FALSE;
1499
1500         CJS_EmbedObj* pEmbedObj = ((CJS_Object*)params[1])->GetEmbedObject();
1501         if (!pEmbedObj)return FALSE;
1502         Icon* pIcon = (Icon*)pEmbedObj;
1503
1504         if (!m_pIconTree)
1505                 m_pIconTree = new IconTree();
1506
1507         IconElement* pNewIcon = new IconElement();
1508         pNewIcon->IconName = swIconName;
1509         pNewIcon->NextIcon = NULL;
1510         pNewIcon->IconStream = pIcon;
1511         m_pIconTree->InsertIconElement(pNewIcon);
1512         return TRUE;
1513 }
1514
1515 FX_BOOL Document::icons(OBJ_PROP_PARAMS)
1516 {
1517         if (vp.IsSetting())
1518                 return FALSE;
1519
1520         if (!m_pIconTree)
1521         {
1522                 vp.SetNull();
1523                 return TRUE;
1524         }
1525
1526         CJS_Array Icons(m_isolate);
1527         IconElement* pIconElement = NULL;
1528         int iIconTreeLength = m_pIconTree->GetLength();
1529
1530         CJS_Context* pContext = (CJS_Context *)cc;
1531         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1532
1533         for (int i = 0; i < iIconTreeLength; i++)
1534         {
1535                 pIconElement = (*m_pIconTree)[i];
1536
1537                 JSFXObject  pObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"Icon"));
1538                 if (pObj.IsEmpty()) return FALSE;
1539
1540                 CJS_Icon * pJS_Icon = (CJS_Icon *)JS_GetPrivate(pObj);
1541                 if (!pJS_Icon) return FALSE;
1542
1543                 Icon* pIcon = (Icon*)pJS_Icon->GetEmbedObject();
1544                 if (!pIcon)return FALSE;
1545
1546                 pIcon->SetStream(pIconElement->IconStream->GetStream());
1547                 pIcon->SetIconName(pIconElement->IconName);
1548                 Icons.SetElement(i, CJS_Value(m_isolate,pJS_Icon));
1549         }
1550
1551         vp << Icons;
1552         return TRUE;
1553 }
1554
1555 FX_BOOL Document::getIcon(OBJ_METHOD_PARAMS)
1556 {
1557         if (params.size() != 1)return FALSE;
1558         if(!m_pIconTree)
1559                 return FALSE;
1560         CFX_WideString swIconName = params[0].operator CFX_WideString();
1561         int iIconCounts = m_pIconTree->GetLength();
1562
1563         CJS_Context* pContext = (CJS_Context *)cc;
1564         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1565
1566         for (int i = 0; i < iIconCounts; i++)
1567         {
1568                 if ((*m_pIconTree)[i]->IconName == swIconName)
1569                 {
1570                         Icon* pRetIcon = (*m_pIconTree)[i]->IconStream;
1571
1572                         JSFXObject  pObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"Icon"));
1573                         if (pObj.IsEmpty()) return FALSE;
1574
1575                         CJS_Icon * pJS_Icon = (CJS_Icon *)JS_GetPrivate(pObj);
1576                         if (!pJS_Icon) return FALSE;
1577
1578                         Icon* pIcon = (Icon*)pJS_Icon->GetEmbedObject();
1579                         if (!pIcon)return FALSE;
1580
1581                         pIcon->SetIconName(swIconName);
1582                         pIcon->SetStream(pRetIcon->GetStream());
1583                         vRet = pJS_Icon;
1584                         return TRUE;
1585                 }
1586         }
1587
1588         return FALSE;
1589 }
1590
1591 FX_BOOL Document::removeIcon(OBJ_METHOD_PARAMS)
1592 {
1593         if (params.size() != 1)return FALSE;
1594         if(!m_pIconTree)
1595                 return FALSE;
1596         CFX_WideString swIconName = params[0].operator CFX_WideString();
1597         return TRUE;
1598 }
1599
1600 FX_BOOL Document::createDataObject(OBJ_METHOD_PARAMS)
1601 {
1602   // Unsafe, not implemented.
1603   return TRUE;
1604 }
1605
1606 FX_BOOL Document::media(OBJ_PROP_PARAMS)
1607 {
1608         return TRUE;
1609 }
1610
1611 FX_BOOL Document::calculateNow(OBJ_METHOD_PARAMS)
1612 {
1613         ASSERT(m_pDocument != NULL);
1614
1615         if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
1616                 m_pDocument->GetPermissions(FPDFPERM_ANNOT_FORM) ||
1617                 m_pDocument->GetPermissions(FPDFPERM_FILL_FORM))) return FALSE;
1618
1619         CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
1620         ASSERT(pInterForm != NULL);
1621         pInterForm->OnCalculate();
1622         return TRUE;
1623 }
1624
1625 FX_BOOL Document::Collab(OBJ_PROP_PARAMS)
1626 {
1627         return TRUE;
1628 }
1629
1630 FX_BOOL Document::getPageNthWord(OBJ_METHOD_PARAMS)
1631 {
1632         ASSERT(m_pDocument != NULL);
1633
1634         if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
1635
1636         int nPageNo = params.GetSize() > 0 ? (int)params[0] : 0;
1637         int nWordNo = params.GetSize() > 1 ? (int)params[1] : 0;
1638         bool bStrip = params.GetSize() > 2 ? (bool)params[2] : true;
1639
1640         CPDF_Document* pDocument = m_pDocument->GetDocument();
1641         if (!pDocument) return FALSE;
1642
1643         if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount())
1644         {
1645                 //sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
1646                 return FALSE;
1647         }
1648
1649         CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo);
1650         if (!pPageDict) return FALSE;
1651
1652         CPDF_Page page;
1653         page.Load(pDocument, pPageDict);
1654         page.StartParse();
1655         page.ParseContent();
1656
1657         FX_POSITION pos = page.GetFirstObjectPosition();
1658
1659         int nWords = 0;
1660
1661         CFX_WideString swRet;
1662
1663         while (pos)
1664         {
1665                 if (CPDF_PageObject* pPageObj = page.GetNextObject(pos))
1666                 {
1667                         if (pPageObj->m_Type == PDFPAGE_TEXT)
1668                         {
1669                                 int nObjWords = CountWords((CPDF_TextObject*)pPageObj);
1670
1671                                 if (nWords + nObjWords >= nWordNo)
1672                                 {
1673                                         swRet = GetObjWordStr((CPDF_TextObject*)pPageObj, nWordNo - nWords);
1674                                         break;
1675                                 }
1676
1677                                 nWords += nObjWords;
1678                         }
1679                 }
1680         }
1681
1682         if (bStrip)
1683         {
1684                 swRet.TrimLeft();
1685                 swRet.TrimRight();
1686         }
1687
1688         vRet = swRet;
1689         return TRUE;
1690 }
1691
1692 FX_BOOL Document::getPageNthWordQuads(OBJ_METHOD_PARAMS)
1693 {
1694         ASSERT(m_pDocument != NULL);
1695
1696         if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
1697
1698         return FALSE;
1699 }
1700
1701 FX_BOOL Document::getPageNumWords(OBJ_METHOD_PARAMS)
1702 {
1703         ASSERT(m_pDocument != NULL);
1704
1705         if (!m_pDocument->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) return FALSE;
1706
1707         int nPageNo = params.GetSize() > 0 ? (int)params[0] : 0;
1708
1709         CPDF_Document* pDocument = m_pDocument->GetDocument();
1710         ASSERT(pDocument != NULL);
1711
1712         if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount())
1713         {
1714                 //sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
1715                 return FALSE;
1716         }
1717
1718         CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo);
1719         if (!pPageDict) return FALSE;
1720
1721         CPDF_Page page;
1722         page.Load(pDocument, pPageDict);
1723         page.StartParse();
1724         page.ParseContent();
1725
1726         FX_POSITION pos = page.GetFirstObjectPosition();
1727
1728         int nWords = 0;
1729
1730         while (pos)
1731         {
1732                 if (CPDF_PageObject* pPageObj = page.GetNextObject(pos))
1733                 {
1734                         if (pPageObj->m_Type == PDFPAGE_TEXT)
1735                         {
1736                                 CPDF_TextObject* pTextObj = (CPDF_TextObject*)pPageObj;
1737                                 nWords += CountWords(pTextObj);
1738                         }
1739                 }
1740         }
1741
1742         vRet = nWords;
1743
1744         return TRUE;
1745 }
1746
1747 FX_BOOL Document::getPrintParams(OBJ_METHOD_PARAMS)
1748 {
1749         CJS_Context* pContext = (CJS_Context*)cc;
1750         ASSERT(pContext != NULL);
1751         CJS_Runtime* pRuntime = pContext->GetJSRuntime();
1752         ASSERT(pRuntime != NULL);
1753         JSFXObject pRetObj = JS_NewFxDynamicObj(*pRuntime, pContext, JS_GetObjDefnID(*pRuntime, L"PrintParamsObj"));
1754         //not implemented yet.
1755         vRet = pRetObj;
1756
1757         return TRUE;
1758 }
1759
1760 #define ISLATINWORD(u)  (u != 0x20 && u <= 0x28FF)
1761
1762 int     Document::CountWords(CPDF_TextObject* pTextObj)
1763 {
1764         if (!pTextObj) return 0;
1765
1766         int nWords = 0;
1767
1768         CPDF_Font* pFont = pTextObj->GetFont();
1769         if (!pFont) return 0;
1770
1771         FX_BOOL bIsLatin = FALSE;
1772
1773         for (int i=0, sz=pTextObj->CountChars(); i<sz; i++)
1774         {
1775                 FX_DWORD charcode = -1;
1776                 FX_FLOAT kerning;
1777
1778                 pTextObj->GetCharInfo(i, charcode, kerning);
1779                 CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode);
1780
1781                 FX_WORD unicode = 0;
1782                 if (swUnicode.GetLength() > 0)
1783                         unicode = swUnicode[0];
1784
1785                 if (ISLATINWORD(unicode) && bIsLatin)
1786                         continue;
1787
1788                 bIsLatin = ISLATINWORD(unicode);
1789                 if (unicode != 0x20)
1790                         nWords++;
1791         }
1792
1793         return nWords;
1794 }
1795
1796 CFX_WideString Document::GetObjWordStr(CPDF_TextObject* pTextObj, int nWordIndex)
1797 {
1798         ASSERT(pTextObj != NULL);
1799
1800         CFX_WideString swRet;
1801
1802         CPDF_Font* pFont = pTextObj->GetFont();
1803         if (!pFont) return L"";
1804
1805         int nWords = 0;
1806         FX_BOOL bIsLatin = FALSE;
1807
1808         for (int i=0, sz=pTextObj->CountChars(); i<sz; i++)
1809         {
1810                 FX_DWORD charcode = -1;
1811                 FX_FLOAT kerning;
1812
1813                 pTextObj->GetCharInfo(i, charcode, kerning);
1814                 CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode);
1815
1816                 FX_WORD unicode = 0;
1817                 if (swUnicode.GetLength() > 0)
1818                         unicode = swUnicode[0];
1819
1820                 if (ISLATINWORD(unicode) && bIsLatin)
1821                 {
1822                 }
1823                 else
1824                 {
1825                         bIsLatin = ISLATINWORD(unicode);
1826                         if (unicode != 0x20)
1827                                 nWords++;
1828                 }
1829
1830                 if (nWords-1 == nWordIndex)
1831                         swRet += unicode;
1832         }
1833
1834         return swRet;
1835 }
1836
1837 FX_BOOL Document::zoom(OBJ_PROP_PARAMS)
1838 {
1839
1840         return TRUE;
1841 }
1842
1843 /**
1844 (none,  NoVary)
1845 (fitP,  FitPage)
1846 (fitW,  FitWidth)
1847 (fitH,  FitHeight)
1848 (fitV,  FitVisibleWidth)
1849 (pref,  Preferred)
1850 (refW,  ReflowWidth)
1851 */
1852
1853 FX_BOOL Document::zoomType(OBJ_PROP_PARAMS)
1854 {
1855         return TRUE;
1856 }
1857
1858 FX_BOOL Document::deletePages(OBJ_METHOD_PARAMS)
1859 {
1860         v8::Isolate* isolate = GetIsolate(cc);
1861         ASSERT(m_pDocument != NULL);
1862
1863         if (!(m_pDocument->GetPermissions(FPDFPERM_MODIFY) ||
1864                 m_pDocument->GetPermissions(FPDFPERM_ASSEMBLE))) return FALSE;
1865
1866         int iSize = params.size();
1867
1868         int nStart = 0;
1869         int nEnd = 0;
1870
1871         if (iSize < 1)
1872         {
1873         }
1874         else if (iSize == 1)
1875         {
1876                 if (params[0].GetType() == VT_object)
1877                 {
1878                         JSObject  pObj = (JSObject )params[0];
1879                         v8::Handle<v8::Value> pValue = JS_GetObjectElement(isolate,pObj, L"nStart");
1880                                 nStart = (int)CJS_Value(m_isolate,pValue,GET_VALUE_TYPE(pValue));
1881
1882                         pValue = JS_GetObjectElement(isolate,pObj, L"nEnd");
1883                                 nEnd = (int)CJS_Value(m_isolate,pValue,GET_VALUE_TYPE(pValue));
1884                 }
1885                 else
1886                 {
1887                         nStart = (int)params[0];
1888                 }
1889         }
1890         else
1891         {
1892                 nStart = (int)params[0];
1893                 nEnd = (int)params[1];
1894         }
1895
1896         int nTotal = m_pDocument->GetPageCount();
1897
1898         if (nStart < 0) nStart = 0;
1899         if (nStart >= nTotal) nStart = nTotal - 1;
1900
1901         if (nEnd < 0) nEnd = 0;
1902         if (nEnd >= nTotal) nEnd = nTotal - 1;
1903
1904         if (nEnd < nStart) nEnd = nStart;
1905
1906
1907
1908         return TRUE;
1909 }
1910
1911 FX_BOOL Document::extractPages(OBJ_METHOD_PARAMS)
1912 {
1913   // Unsafe, not supported.
1914   return TRUE;
1915 }
1916
1917 FX_BOOL Document::insertPages(OBJ_METHOD_PARAMS)
1918 {
1919   // Unsafe, not supported.
1920   return TRUE;
1921 }
1922
1923 FX_BOOL Document::replacePages(OBJ_METHOD_PARAMS)
1924 {
1925   // Unsafe, not supported.
1926   return TRUE;
1927 }
1928
1929 FX_BOOL Document::getURL(OBJ_METHOD_PARAMS)
1930 {
1931   // Unsafe, not supported.
1932   return TRUE;
1933 }
1934
1935 void Document::AddDelayData(CJS_DelayData* pData)
1936 {
1937         m_DelayData.Add(pData);
1938 }
1939
1940 void Document::DoFieldDelay(const CFX_WideString& sFieldName, int nControlIndex)
1941 {
1942         CFX_DWordArray DelArray;
1943
1944         for (int i=0,sz=m_DelayData.GetSize(); i<sz; i++)
1945         {
1946                 if (CJS_DelayData* pData = m_DelayData.GetAt(i))
1947                 {
1948                         if (pData->sFieldName == sFieldName && pData->nControlIndex == nControlIndex)
1949                         {
1950                                 Field::DoDelay(m_pDocument, pData);
1951                                 delete pData;
1952                                 m_DelayData.SetAt(i, NULL);
1953                                 DelArray.Add(i);
1954                         }
1955                 }
1956         }
1957
1958         for (int j=DelArray.GetSize()-1; j>=0; j--)
1959         {
1960                 m_DelayData.RemoveAt(DelArray[j]);
1961         }
1962 }
1963
1964 void Document::AddDelayAnnotData(CJS_AnnotObj *pData)
1965 {
1966         m_DelayAnnotData.Add(pData);
1967 }
1968
1969 void Document::DoAnnotDelay()
1970 {
1971         CFX_DWordArray DelArray;
1972
1973         for (int j=DelArray.GetSize()-1; j>=0; j--)
1974         {
1975                 m_DelayData.RemoveAt(DelArray[j]);
1976         }
1977 }