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 "core/include/fpdfdoc/fpdf_doc.h"
8 #include "doc_utils.h"
9 #include "third_party/base/stl_util.h"
10 
11 const int nMaxRecursion = 32;
12 
13 class CFieldNameExtractor {
14  public:
CFieldNameExtractor(const CFX_WideString & full_name)15   explicit CFieldNameExtractor(const CFX_WideString& full_name) {
16     m_pStart = full_name.c_str();
17     m_pEnd = m_pStart + full_name.GetLength();
18     m_pCur = m_pStart;
19   }
GetNext(const FX_WCHAR * & pSubName,FX_STRSIZE & size)20   void GetNext(const FX_WCHAR*& pSubName, FX_STRSIZE& size) {
21     pSubName = m_pCur;
22     while (m_pCur < m_pEnd && m_pCur[0] != L'.') {
23       m_pCur++;
24     }
25     size = (FX_STRSIZE)(m_pCur - pSubName);
26     if (m_pCur < m_pEnd && m_pCur[0] == L'.') {
27       m_pCur++;
28     }
29   }
30 
31  protected:
32   const FX_WCHAR* m_pStart;
33   const FX_WCHAR* m_pEnd;
34   const FX_WCHAR* m_pCur;
35 };
36 class CFieldTree {
37  public:
38   struct _Node {
39     _Node* parent;
40     CFX_ArrayTemplate<_Node*> children;
41     CFX_WideString short_name;
42     CPDF_FormField* field_ptr;
CountFieldsCFieldTree::_Node43     int CountFields(int nLevel = 0) {
44       if (nLevel > nMaxRecursion) {
45         return 0;
46       }
47       if (field_ptr) {
48         return 1;
49       }
50       int count = 0;
51       for (int i = 0; i < children.GetSize(); i++) {
52         count += children.GetAt(i)->CountFields(nLevel + 1);
53       }
54       return count;
55     }
GetFieldCFieldTree::_Node56     CPDF_FormField* GetField(int* fields_to_go) {
57       if (field_ptr) {
58         if (*fields_to_go == 0) {
59           return field_ptr;
60         }
61         --*fields_to_go;
62         return NULL;
63       }
64       for (int i = 0; i < children.GetSize(); i++) {
65         if (CPDF_FormField* pField = children.GetAt(i)->GetField(fields_to_go))
66           return pField;
67       }
68       return NULL;
69     }
GetFieldCFieldTree::_Node70     CPDF_FormField* GetField(int index) {
71       int fields_to_go = index;
72       return GetField(&fields_to_go);
73     }
74   };
75   CFieldTree();
76   ~CFieldTree();
77   void SetField(const CFX_WideString& full_name, CPDF_FormField* field_ptr);
78   CPDF_FormField* GetField(const CFX_WideString& full_name);
79   CPDF_FormField* RemoveField(const CFX_WideString& full_name);
80   void RemoveAll();
81   _Node* FindNode(const CFX_WideString& full_name);
82   _Node* AddChild(_Node* pParent,
83                   const CFX_WideString& short_name,
84                   CPDF_FormField* field_ptr);
85   void RemoveNode(_Node* pNode, int nLevel = 0);
86   _Node* _Lookup(_Node* pParent, const CFX_WideString& short_name);
87   _Node m_Root;
88 };
CFieldTree()89 CFieldTree::CFieldTree() {
90   m_Root.parent = NULL;
91   m_Root.field_ptr = NULL;
92 }
~CFieldTree()93 CFieldTree::~CFieldTree() {
94   RemoveAll();
95 }
AddChild(_Node * pParent,const CFX_WideString & short_name,CPDF_FormField * field_ptr)96 CFieldTree::_Node* CFieldTree::AddChild(_Node* pParent,
97                                         const CFX_WideString& short_name,
98                                         CPDF_FormField* field_ptr) {
99   if (!pParent) {
100     return NULL;
101   }
102   _Node* pNode = new _Node;
103   pNode->parent = pParent;
104   pNode->short_name = short_name;
105   pNode->field_ptr = field_ptr;
106   pParent->children.Add(pNode);
107   return pNode;
108 }
RemoveNode(_Node * pNode,int nLevel)109 void CFieldTree::RemoveNode(_Node* pNode, int nLevel) {
110   if (!pNode) {
111     return;
112   }
113   if (nLevel <= nMaxRecursion) {
114     for (int i = 0; i < pNode->children.GetSize(); i++) {
115       RemoveNode(pNode->children[i], nLevel + 1);
116     }
117   }
118   delete pNode;
119 }
_Lookup(_Node * pParent,const CFX_WideString & short_name)120 CFieldTree::_Node* CFieldTree::_Lookup(_Node* pParent,
121                                        const CFX_WideString& short_name) {
122   if (!pParent) {
123     return NULL;
124   }
125   for (int i = 0; i < pParent->children.GetSize(); i++) {
126     _Node* pNode = pParent->children[i];
127     if (pNode->short_name.GetLength() == short_name.GetLength() &&
128         FXSYS_memcmp(pNode->short_name.c_str(), short_name.c_str(),
129                      short_name.GetLength() * sizeof(FX_WCHAR)) == 0) {
130       return pNode;
131     }
132   }
133   return NULL;
134 }
RemoveAll()135 void CFieldTree::RemoveAll() {
136   for (int i = 0; i < m_Root.children.GetSize(); i++) {
137     RemoveNode(m_Root.children[i]);
138   }
139 }
SetField(const CFX_WideString & full_name,CPDF_FormField * field_ptr)140 void CFieldTree::SetField(const CFX_WideString& full_name,
141                           CPDF_FormField* field_ptr) {
142   if (full_name == L"") {
143     return;
144   }
145   CFieldNameExtractor name_extractor(full_name);
146   const FX_WCHAR* pName;
147   FX_STRSIZE nLength;
148   name_extractor.GetNext(pName, nLength);
149   _Node *pNode = &m_Root, *pLast = NULL;
150   while (nLength > 0) {
151     pLast = pNode;
152     CFX_WideString name = CFX_WideString(pName, nLength);
153     pNode = _Lookup(pLast, name);
154     if (!pNode) {
155       pNode = AddChild(pLast, name, NULL);
156     }
157     name_extractor.GetNext(pName, nLength);
158   }
159   if (pNode != &m_Root) {
160     pNode->field_ptr = field_ptr;
161   }
162 }
GetField(const CFX_WideString & full_name)163 CPDF_FormField* CFieldTree::GetField(const CFX_WideString& full_name) {
164   if (full_name == L"") {
165     return NULL;
166   }
167   CFieldNameExtractor name_extractor(full_name);
168   const FX_WCHAR* pName;
169   FX_STRSIZE nLength;
170   name_extractor.GetNext(pName, nLength);
171   _Node *pNode = &m_Root, *pLast = NULL;
172   while (nLength > 0 && pNode) {
173     pLast = pNode;
174     CFX_WideString name = CFX_WideString(pName, nLength);
175     pNode = _Lookup(pLast, name);
176     name_extractor.GetNext(pName, nLength);
177   }
178   return pNode ? pNode->field_ptr : NULL;
179 }
RemoveField(const CFX_WideString & full_name)180 CPDF_FormField* CFieldTree::RemoveField(const CFX_WideString& full_name) {
181   if (full_name == L"") {
182     return NULL;
183   }
184   CFieldNameExtractor name_extractor(full_name);
185   const FX_WCHAR* pName;
186   FX_STRSIZE nLength;
187   name_extractor.GetNext(pName, nLength);
188   _Node *pNode = &m_Root, *pLast = NULL;
189   while (nLength > 0 && pNode) {
190     pLast = pNode;
191     CFX_WideString name = CFX_WideString(pName, nLength);
192     pNode = _Lookup(pLast, name);
193     name_extractor.GetNext(pName, nLength);
194   }
195   if (pNode && pNode != &m_Root) {
196     for (int i = 0; i < pLast->children.GetSize(); i++) {
197       if (pNode == pLast->children[i]) {
198         pLast->children.RemoveAt(i);
199         break;
200       }
201     }
202     CPDF_FormField* pField = pNode->field_ptr;
203     RemoveNode(pNode);
204     return pField;
205   }
206   return NULL;
207 }
FindNode(const CFX_WideString & full_name)208 CFieldTree::_Node* CFieldTree::FindNode(const CFX_WideString& full_name) {
209   if (full_name == L"") {
210     return NULL;
211   }
212   CFieldNameExtractor name_extractor(full_name);
213   const FX_WCHAR* pName;
214   FX_STRSIZE nLength;
215   name_extractor.GetNext(pName, nLength);
216   _Node *pNode = &m_Root, *pLast = NULL;
217   while (nLength > 0 && pNode) {
218     pLast = pNode;
219     CFX_WideString name = CFX_WideString(pName, nLength);
220     pNode = _Lookup(pLast, name);
221     name_extractor.GetNext(pName, nLength);
222   }
223   return pNode;
224 }
CPDF_InterForm(CPDF_Document * pDocument,FX_BOOL bGenerateAP)225 CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument, FX_BOOL bGenerateAP)
226     : CFX_PrivateData(),
227       m_pDocument(pDocument),
228       m_bGenerateAP(bGenerateAP),
229       m_pFormDict(nullptr),
230       m_pFieldTree(new CFieldTree),
231       m_pFormNotify(nullptr),
232       m_bUpdated(FALSE) {
233   CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
234   if (!pRoot)
235     return;
236 
237   m_pFormDict = pRoot->GetDict("AcroForm");
238   if (!m_pFormDict)
239     return;
240 
241   CPDF_Array* pFields = m_pFormDict->GetArray("Fields");
242   if (!pFields)
243     return;
244 
245   int count = pFields->GetCount();
246   for (int i = 0; i < count; i++) {
247     LoadField(pFields->GetDict(i));
248   }
249 }
250 
~CPDF_InterForm()251 CPDF_InterForm::~CPDF_InterForm() {
252   for (auto it : m_ControlMap)
253     delete it.second;
254 
255   int nCount = m_pFieldTree->m_Root.CountFields();
256   for (int i = 0; i < nCount; ++i) {
257     delete m_pFieldTree->m_Root.GetField(i);
258   }
259 }
260 
261 FX_BOOL CPDF_InterForm::m_bUpdateAP = TRUE;
UpdatingAPEnabled()262 FX_BOOL CPDF_InterForm::UpdatingAPEnabled() {
263   return m_bUpdateAP;
264 }
EnableUpdateAP(FX_BOOL bUpdateAP)265 void CPDF_InterForm::EnableUpdateAP(FX_BOOL bUpdateAP) {
266   m_bUpdateAP = bUpdateAP;
267 }
GenerateNewResourceName(const CPDF_Dictionary * pResDict,const FX_CHAR * csType,int iMinLen,const FX_CHAR * csPrefix)268 CFX_ByteString CPDF_InterForm::GenerateNewResourceName(
269     const CPDF_Dictionary* pResDict,
270     const FX_CHAR* csType,
271     int iMinLen,
272     const FX_CHAR* csPrefix) {
273   CFX_ByteString csStr = csPrefix;
274   CFX_ByteString csBType = csType;
275   if (csStr.IsEmpty()) {
276     if (csBType == "ExtGState") {
277       csStr = "GS";
278     } else if (csBType == "ColorSpace") {
279       csStr = "CS";
280     } else if (csBType == "Font") {
281       csStr = "ZiTi";
282     } else {
283       csStr = "Res";
284     }
285   }
286   CFX_ByteString csTmp = csStr;
287   int iCount = csStr.GetLength();
288   int m = 0;
289   if (iMinLen > 0) {
290     csTmp = "";
291     while (m < iMinLen && m < iCount) {
292       csTmp += csStr[m++];
293     }
294     while (m < iMinLen) {
295       csTmp += '0' + m % 10;
296       m++;
297     }
298   } else {
299     m = iCount;
300   }
301   if (!pResDict) {
302     return csTmp;
303   }
304   CPDF_Dictionary* pDict = pResDict->GetDict(csType);
305   if (!pDict) {
306     return csTmp;
307   }
308   int num = 0;
309   CFX_ByteString bsNum;
310   while (TRUE) {
311     if (!pDict->KeyExist(csTmp + bsNum)) {
312       return csTmp + bsNum;
313     }
314     if (m < iCount) {
315       csTmp += csStr[m++];
316     } else {
317       bsNum.Format("%d", num++);
318     }
319     m++;
320   }
321   return csTmp;
322 }
323 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
324 typedef struct _PDF_FONTDATA {
325   FX_BOOL bFind;
326   LOGFONTA lf;
327 } PDF_FONTDATA, FAR* LPDF_FONTDATA;
EnumFontFamExProc(ENUMLOGFONTEXA * lpelfe,NEWTEXTMETRICEX * lpntme,DWORD FontType,LPARAM lParam)328 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe,
329                                       NEWTEXTMETRICEX* lpntme,
330                                       DWORD FontType,
331                                       LPARAM lParam) {
332   if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@')) {
333     return 1;
334   }
335   LPDF_FONTDATA pData = (LPDF_FONTDATA)lParam;
336   memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA));
337   pData->bFind = TRUE;
338   return 0;
339 }
RetrieveSpecificFont(LOGFONTA & lf)340 static FX_BOOL RetrieveSpecificFont(LOGFONTA& lf) {
341   PDF_FONTDATA fd;
342   memset(&fd, 0, sizeof(PDF_FONTDATA));
343   HDC hDC = ::GetDC(NULL);
344   EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd,
345                       0);
346   ::ReleaseDC(NULL, hDC);
347   if (fd.bFind) {
348     memcpy(&lf, &fd.lf, sizeof(LOGFONTA));
349   }
350   return fd.bFind;
351 }
RetrieveSpecificFont(uint8_t charSet,uint8_t pitchAndFamily,LPCSTR pcsFontName,LOGFONTA & lf)352 static FX_BOOL RetrieveSpecificFont(uint8_t charSet,
353                                     uint8_t pitchAndFamily,
354                                     LPCSTR pcsFontName,
355                                     LOGFONTA& lf) {
356   memset(&lf, 0, sizeof(LOGFONTA));
357   lf.lfCharSet = charSet;
358   lf.lfPitchAndFamily = pitchAndFamily;
359   if (pcsFontName) {
360     strcpy(lf.lfFaceName, pcsFontName);
361   }
362   return RetrieveSpecificFont(lf);
363 }
364 #ifdef PDF_ENABLE_XFA
RetrieveStockFont(int iFontObject,uint8_t charSet,LOGFONTA & lf)365 static FX_BOOL RetrieveStockFont(int iFontObject,
366                                  uint8_t charSet,
367                                  LOGFONTA& lf) {
368   HFONT hFont = (HFONT)::GetStockObject(iFontObject);
369   if (hFont != NULL) {
370     memset(&lf, 0, sizeof(LOGFONTA));
371     int iRet = ::GetObject(hFont, sizeof(LOGFONTA), &lf);
372     if (iRet > 0 && (lf.lfCharSet == charSet || charSet == 255)) {
373       return RetrieveSpecificFont(lf);
374     }
375   }
376   return FALSE;
377 }
378 #endif  // PDF_ENABLE_XFA
379 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
380 
AddStandardFont(CPDF_Document * pDocument,CFX_ByteString csFontName)381 CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument,
382                                            CFX_ByteString csFontName) {
383   if (!pDocument || csFontName.IsEmpty())
384     return nullptr;
385 
386   if (csFontName == "ZapfDingbats")
387     return pDocument->AddStandardFont(csFontName.c_str(), nullptr);
388 
389   CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI);
390   return pDocument->AddStandardFont(csFontName.c_str(), &encoding);
391 }
392 
GetNativeFont(uint8_t charSet,void * pLogFont)393 CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) {
394   CFX_ByteString csFontName;
395 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
396   LOGFONTA lf;
397   FX_BOOL bRet;
398   if (charSet == ANSI_CHARSET) {
399     csFontName = "Helvetica";
400     return csFontName;
401   }
402   bRet = FALSE;
403   if (charSet == SHIFTJIS_CHARSET) {
404     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
405                                 "MS Mincho", lf);
406   } else if (charSet == GB2312_CHARSET) {
407     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun",
408                                 lf);
409   } else if (charSet == CHINESEBIG5_CHARSET) {
410     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU",
411                                 lf);
412   }
413   if (!bRet) {
414     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
415                                 "Arial Unicode MS", lf);
416   }
417   if (!bRet) {
418     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
419                                 "Microsoft Sans Serif", lf);
420   }
421   if (!bRet) {
422     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, NULL, lf);
423   }
424   if (bRet) {
425     if (pLogFont) {
426       memcpy(pLogFont, &lf, sizeof(LOGFONTA));
427     }
428     csFontName = lf.lfFaceName;
429     return csFontName;
430   }
431 #endif
432   return csFontName;
433 }
GetNativeFont(void * pLogFont)434 CFX_ByteString CPDF_InterForm::GetNativeFont(void* pLogFont) {
435 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
436   uint8_t charSet = GetNativeCharSet();
437   return GetNativeFont(charSet, pLogFont);
438 #else
439   return CFX_ByteString();
440 #endif
441 }
GetNativeCharSet()442 uint8_t CPDF_InterForm::GetNativeCharSet() {
443 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
444   uint8_t charSet = ANSI_CHARSET;
445   UINT iCodePage = ::GetACP();
446   switch (iCodePage) {
447     case 932:
448       charSet = SHIFTJIS_CHARSET;
449       break;
450     case 936:
451       charSet = GB2312_CHARSET;
452       break;
453     case 950:
454       charSet = CHINESEBIG5_CHARSET;
455       break;
456     case 1252:
457       charSet = ANSI_CHARSET;
458       break;
459     case 874:
460       charSet = THAI_CHARSET;
461       break;
462     case 949:
463       charSet = HANGUL_CHARSET;
464       break;
465     case 1200:
466       charSet = ANSI_CHARSET;
467       break;
468     case 1250:
469       charSet = EASTEUROPE_CHARSET;
470       break;
471     case 1251:
472       charSet = RUSSIAN_CHARSET;
473       break;
474     case 1253:
475       charSet = GREEK_CHARSET;
476       break;
477     case 1254:
478       charSet = TURKISH_CHARSET;
479       break;
480     case 1255:
481       charSet = HEBREW_CHARSET;
482       break;
483     case 1256:
484       charSet = ARABIC_CHARSET;
485       break;
486     case 1257:
487       charSet = BALTIC_CHARSET;
488       break;
489     case 1258:
490       charSet = VIETNAMESE_CHARSET;
491       break;
492     case 1361:
493       charSet = JOHAB_CHARSET;
494       break;
495   }
496   return charSet;
497 #else
498   return 0;
499 #endif
500 }
501 
AddNativeFont(uint8_t charSet,CPDF_Document * pDocument)502 CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet,
503                                          CPDF_Document* pDocument) {
504   if (!pDocument)
505     return nullptr;
506 
507 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
508   LOGFONTA lf;
509   CFX_ByteString csFontName = GetNativeFont(charSet, &lf);
510   if (!csFontName.IsEmpty()) {
511     if (csFontName == "Helvetica")
512       return AddStandardFont(pDocument, csFontName);
513     return pDocument->AddWindowsFont(&lf, FALSE, TRUE);
514   }
515 #endif
516   return nullptr;
517 }
518 
AddNativeFont(CPDF_Document * pDocument)519 CPDF_Font* CPDF_InterForm::AddNativeFont(CPDF_Document* pDocument) {
520   return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr;
521 }
522 
ValidateFieldName(CFX_WideString & csNewFieldName,int iType,const CPDF_FormField * pExcludedField,const CPDF_FormControl * pExcludedControl)523 FX_BOOL CPDF_InterForm::ValidateFieldName(
524     CFX_WideString& csNewFieldName,
525     int iType,
526     const CPDF_FormField* pExcludedField,
527     const CPDF_FormControl* pExcludedControl) {
528   if (csNewFieldName.IsEmpty()) {
529     return FALSE;
530   }
531   int iPos = 0;
532   int iLength = csNewFieldName.GetLength();
533   CFX_WideString csSub;
534   while (TRUE) {
535     while (iPos < iLength &&
536            (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) {
537       iPos++;
538     }
539     if (iPos < iLength && !csSub.IsEmpty()) {
540       csSub += L'.';
541     }
542     while (iPos < iLength && csNewFieldName[iPos] != L'.') {
543       csSub += csNewFieldName[iPos++];
544     }
545     for (int i = csSub.GetLength() - 1; i > -1; i--) {
546       if (csSub[i] == L' ' || csSub[i] == L'.') {
547         csSub.SetAt(i, L'\0');
548       } else {
549         break;
550       }
551     }
552     FX_DWORD dwCount = m_pFieldTree->m_Root.CountFields();
553     for (FX_DWORD m = 0; m < dwCount; m++) {
554       CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(m);
555       if (!pField) {
556         continue;
557       }
558       if (pField == pExcludedField) {
559         if (pExcludedControl) {
560           if (pField->CountControls() < 2) {
561             continue;
562           }
563         } else {
564           continue;
565         }
566       }
567       CFX_WideString csFullName = pField->GetFullName();
568       int iRet = CompareFieldName(csSub, csFullName);
569       if (iRet == 1) {
570         if (pField->GetFieldType() != iType) {
571           return FALSE;
572         }
573       } else if (iRet == 2 && csSub == csNewFieldName) {
574         if (csFullName[iPos] == L'.') {
575           return FALSE;
576         }
577       } else if (iRet == 3 && csSub == csNewFieldName) {
578         if (csNewFieldName[csFullName.GetLength()] == L'.') {
579           return FALSE;
580         }
581       }
582     }
583     if (iPos >= iLength) {
584       break;
585     }
586   }
587   if (csSub.IsEmpty()) {
588     return FALSE;
589   }
590   csNewFieldName = csSub;
591   return TRUE;
592 }
ValidateFieldName(CFX_WideString & csNewFieldName,int iType)593 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName,
594                                           int iType) {
595   return ValidateFieldName(csNewFieldName, iType, NULL, NULL);
596 }
ValidateFieldName(const CPDF_FormField * pField,CFX_WideString & csNewFieldName)597 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormField* pField,
598                                           CFX_WideString& csNewFieldName) {
599   return pField && !csNewFieldName.IsEmpty() &&
600          ValidateFieldName(csNewFieldName,
601                            ((CPDF_FormField*)pField)->GetFieldType(), pField,
602                            NULL);
603 }
ValidateFieldName(const CPDF_FormControl * pControl,CFX_WideString & csNewFieldName)604 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormControl* pControl,
605                                           CFX_WideString& csNewFieldName) {
606   if (!pControl || csNewFieldName.IsEmpty()) {
607     return FALSE;
608   }
609   CPDF_FormField* pField = ((CPDF_FormControl*)pControl)->GetField();
610   return ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField,
611                            pControl);
612 }
CompareFieldName(const CFX_ByteString & name1,const CFX_ByteString & name2)613 int CPDF_InterForm::CompareFieldName(const CFX_ByteString& name1,
614                                      const CFX_ByteString& name2) {
615   const FX_CHAR* ptr1 = name1;
616   const FX_CHAR* ptr2 = name2;
617   if (name1.GetLength() == name2.GetLength()) {
618     return name1 == name2 ? 1 : 0;
619   }
620   int i = 0;
621   while (ptr1[i] == ptr2[i]) {
622     i++;
623   }
624   if (i == name1.GetLength()) {
625     return 2;
626   }
627   if (i == name2.GetLength()) {
628     return 3;
629   }
630   return 0;
631 }
CompareFieldName(const CFX_WideString & name1,const CFX_WideString & name2)632 int CPDF_InterForm::CompareFieldName(const CFX_WideString& name1,
633                                      const CFX_WideString& name2) {
634   const FX_WCHAR* ptr1 = name1.c_str();
635   const FX_WCHAR* ptr2 = name2.c_str();
636   if (name1.GetLength() == name2.GetLength()) {
637     return name1 == name2 ? 1 : 0;
638   }
639   int i = 0;
640   while (ptr1[i] == ptr2[i]) {
641     i++;
642   }
643   if (i == name1.GetLength()) {
644     return 2;
645   }
646   if (i == name2.GetLength()) {
647     return 3;
648   }
649   return 0;
650 }
CountFields(const CFX_WideString & csFieldName)651 FX_DWORD CPDF_InterForm::CountFields(const CFX_WideString& csFieldName) {
652   if (csFieldName.IsEmpty()) {
653     return (FX_DWORD)m_pFieldTree->m_Root.CountFields();
654   }
655   CFieldTree::_Node* pNode = m_pFieldTree->FindNode(csFieldName);
656   return pNode ? pNode->CountFields() : 0;
657 }
GetField(FX_DWORD index,const CFX_WideString & csFieldName)658 CPDF_FormField* CPDF_InterForm::GetField(FX_DWORD index,
659                                          const CFX_WideString& csFieldName) {
660   if (csFieldName == L"") {
661     return m_pFieldTree->m_Root.GetField(index);
662   }
663   CFieldTree::_Node* pNode = m_pFieldTree->FindNode(csFieldName);
664   return pNode ? pNode->GetField(index) : nullptr;
665 }
GetAllFieldNames(CFX_WideStringArray & allFieldNames)666 void CPDF_InterForm::GetAllFieldNames(CFX_WideStringArray& allFieldNames) {
667   allFieldNames.RemoveAll();
668   int nCount = m_pFieldTree->m_Root.CountFields();
669   for (int i = 0; i < nCount; i++) {
670     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
671     if (pField) {
672       CFX_WideString full_name = GetFullName(pField->GetFieldDict());
673       allFieldNames.Add(full_name);
674     }
675   }
676 }
677 
GetFieldByDict(CPDF_Dictionary * pFieldDict) const678 CPDF_FormField* CPDF_InterForm::GetFieldByDict(
679     CPDF_Dictionary* pFieldDict) const {
680   if (!pFieldDict) {
681     return NULL;
682   }
683   CFX_WideString csWName = GetFullName(pFieldDict);
684   return m_pFieldTree->GetField(csWName);
685 }
686 
GetControlAtPoint(CPDF_Page * pPage,FX_FLOAT pdf_x,FX_FLOAT pdf_y,int * z_order) const687 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage,
688                                                     FX_FLOAT pdf_x,
689                                                     FX_FLOAT pdf_y,
690                                                     int* z_order) const {
691   CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
692   if (!pAnnotList)
693     return nullptr;
694 
695   for (FX_DWORD i = pAnnotList->GetCount(); i > 0; --i) {
696     FX_DWORD annot_index = i - 1;
697     CPDF_Dictionary* pAnnot = pAnnotList->GetDict(annot_index);
698     if (!pAnnot)
699       continue;
700 
701     const auto it = m_ControlMap.find(pAnnot);
702     if (it == m_ControlMap.end())
703       continue;
704 
705     CPDF_FormControl* pControl = it->second;
706     CFX_FloatRect rect = pControl->GetRect();
707     if (!rect.Contains(pdf_x, pdf_y))
708       continue;
709 
710     if (z_order)
711       *z_order = annot_index;
712     return pControl;
713   }
714   return nullptr;
715 }
716 
GetControlByDict(const CPDF_Dictionary * pWidgetDict) const717 CPDF_FormControl* CPDF_InterForm::GetControlByDict(
718     const CPDF_Dictionary* pWidgetDict) const {
719   const auto it = m_ControlMap.find(pWidgetDict);
720   return it != m_ControlMap.end() ? it->second : nullptr;
721 }
722 
NeedConstructAP()723 FX_BOOL CPDF_InterForm::NeedConstructAP() {
724   return m_pFormDict && m_pFormDict->GetBoolean("NeedAppearances");
725 }
NeedConstructAP(FX_BOOL bNeedAP)726 void CPDF_InterForm::NeedConstructAP(FX_BOOL bNeedAP) {
727   if (!m_pFormDict) {
728     InitInterFormDict(m_pFormDict, m_pDocument);
729   }
730   m_pFormDict->SetAtBoolean("NeedAppearances", bNeedAP);
731   m_bGenerateAP = bNeedAP;
732 }
CountFieldsInCalculationOrder()733 int CPDF_InterForm::CountFieldsInCalculationOrder() {
734   if (!m_pFormDict) {
735     return 0;
736   }
737   CPDF_Array* pArray = m_pFormDict->GetArray("CO");
738   return pArray ? pArray->GetCount() : 0;
739 }
GetFieldInCalculationOrder(int index)740 CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index) {
741   if (!m_pFormDict || index < 0) {
742     return NULL;
743   }
744   CPDF_Array* pArray = m_pFormDict->GetArray("CO");
745   if (!pArray) {
746     return NULL;
747   }
748   if (CPDF_Dictionary* pElement =
749           ToDictionary(pArray->GetElementValue(index))) {
750     return GetFieldByDict(pElement);
751   }
752   return NULL;
753 }
FindFieldInCalculationOrder(const CPDF_FormField * pField)754 int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) {
755   if (!m_pFormDict || !pField) {
756     return -1;
757   }
758   CPDF_Array* pArray = m_pFormDict->GetArray("CO");
759   if (!pArray) {
760     return -1;
761   }
762   for (FX_DWORD i = 0; i < pArray->GetCount(); i++) {
763     CPDF_Object* pElement = pArray->GetElementValue(i);
764     if (pElement == pField->m_pDict) {
765       return i;
766     }
767   }
768   return -1;
769 }
CountFormFonts()770 FX_DWORD CPDF_InterForm::CountFormFonts() {
771   return CountInterFormFonts(m_pFormDict);
772 }
GetFormFont(FX_DWORD index,CFX_ByteString & csNameTag)773 CPDF_Font* CPDF_InterForm::GetFormFont(FX_DWORD index,
774                                        CFX_ByteString& csNameTag) {
775   return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag);
776 }
GetFormFont(CFX_ByteString csNameTag)777 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag) {
778   return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag);
779 }
GetFormFont(CFX_ByteString csFontName,CFX_ByteString & csNameTag)780 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName,
781                                        CFX_ByteString& csNameTag) {
782   return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag);
783 }
GetNativeFormFont(uint8_t charSet,CFX_ByteString & csNameTag)784 CPDF_Font* CPDF_InterForm::GetNativeFormFont(uint8_t charSet,
785                                              CFX_ByteString& csNameTag) {
786   return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
787 }
GetNativeFormFont(CFX_ByteString & csNameTag)788 CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag) {
789   return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
790 }
FindFormFont(const CPDF_Font * pFont,CFX_ByteString & csNameTag)791 FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont,
792                                      CFX_ByteString& csNameTag) {
793   return FindInterFormFont(m_pFormDict, pFont, csNameTag);
794 }
FindFormFont(CFX_ByteString csFontName,CPDF_Font * & pFont,CFX_ByteString & csNameTag)795 FX_BOOL CPDF_InterForm::FindFormFont(CFX_ByteString csFontName,
796                                      CPDF_Font*& pFont,
797                                      CFX_ByteString& csNameTag) {
798   return FindInterFormFont(m_pFormDict, m_pDocument, csFontName, pFont,
799                            csNameTag);
800 }
AddFormFont(const CPDF_Font * pFont,CFX_ByteString & csNameTag)801 void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont,
802                                  CFX_ByteString& csNameTag) {
803   AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag);
804   m_bUpdated = TRUE;
805 }
AddNativeFormFont(uint8_t charSet,CFX_ByteString & csNameTag)806 CPDF_Font* CPDF_InterForm::AddNativeFormFont(uint8_t charSet,
807                                              CFX_ByteString& csNameTag) {
808   m_bUpdated = TRUE;
809   return AddNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
810 }
AddNativeFormFont(CFX_ByteString & csNameTag)811 CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag) {
812   m_bUpdated = TRUE;
813   return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
814 }
RemoveFormFont(const CPDF_Font * pFont)815 void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont) {
816   m_bUpdated = TRUE;
817   RemoveInterFormFont(m_pFormDict, pFont);
818 }
RemoveFormFont(CFX_ByteString csNameTag)819 void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag) {
820   m_bUpdated = TRUE;
821   RemoveInterFormFont(m_pFormDict, csNameTag);
822 }
GetDefaultAppearance()823 CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() {
824   CFX_ByteString csDA;
825   if (!m_pFormDict) {
826     return csDA;
827   }
828   csDA = m_pFormDict->GetString("DA");
829   return csDA;
830 }
GetDefaultFormFont()831 CPDF_Font* CPDF_InterForm::GetDefaultFormFont() {
832   return GetDefaultInterFormFont(m_pFormDict, m_pDocument);
833 }
GetFormAlignment()834 int CPDF_InterForm::GetFormAlignment() {
835   return m_pFormDict ? m_pFormDict->GetInteger("Q", 0) : 0;
836 }
837 
ResetForm(const std::vector<CPDF_FormField * > & fields,bool bIncludeOrExclude,bool bNotify)838 bool CPDF_InterForm::ResetForm(const std::vector<CPDF_FormField*>& fields,
839                                bool bIncludeOrExclude,
840                                bool bNotify) {
841   if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0)
842     return false;
843 
844   int nCount = m_pFieldTree->m_Root.CountFields();
845   for (int i = 0; i < nCount; ++i) {
846     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
847     if (!pField)
848       continue;
849 
850     if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField))
851       pField->ResetField(bNotify);
852   }
853   if (bNotify && m_pFormNotify)
854     m_pFormNotify->AfterFormReset(this);
855   return true;
856 }
857 
ResetForm(bool bNotify)858 bool CPDF_InterForm::ResetForm(bool bNotify) {
859   if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0)
860     return false;
861 
862   int nCount = m_pFieldTree->m_Root.CountFields();
863   for (int i = 0; i < nCount; ++i) {
864     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
865     if (!pField)
866       continue;
867 
868     pField->ResetField(bNotify);
869   }
870   if (bNotify && m_pFormNotify)
871     m_pFormNotify->AfterFormReset(this);
872   return true;
873 }
874 
LoadField(CPDF_Dictionary * pFieldDict,int nLevel)875 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) {
876   if (nLevel > nMaxRecursion) {
877     return;
878   }
879   if (!pFieldDict) {
880     return;
881   }
882   FX_DWORD dwParentObjNum = pFieldDict->GetObjNum();
883   CPDF_Array* pKids = pFieldDict->GetArray("Kids");
884   if (!pKids) {
885     AddTerminalField(pFieldDict);
886     return;
887   }
888   CPDF_Dictionary* pFirstKid = pKids->GetDict(0);
889   if (!pFirstKid) {
890     return;
891   }
892   if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) {
893     for (FX_DWORD i = 0; i < pKids->GetCount(); i++) {
894       CPDF_Dictionary* pChildDict = pKids->GetDict(i);
895       if (pChildDict) {
896         if (pChildDict->GetObjNum() != dwParentObjNum) {
897           LoadField(pChildDict, nLevel + 1);
898         }
899       }
900     }
901   } else {
902     AddTerminalField(pFieldDict);
903   }
904 }
HasXFAForm() const905 FX_BOOL CPDF_InterForm::HasXFAForm() const {
906   return m_pFormDict && m_pFormDict->GetArray("XFA");
907 }
FixPageFields(const CPDF_Page * pPage)908 void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) {
909   CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
910   if (!pPageDict) {
911     return;
912   }
913   CPDF_Array* pAnnots = pPageDict->GetArray("Annots");
914   if (!pAnnots) {
915     return;
916   }
917   int iAnnotCount = pAnnots->GetCount();
918   for (int i = 0; i < iAnnotCount; i++) {
919     CPDF_Dictionary* pAnnot = pAnnots->GetDict(i);
920     if (pAnnot && pAnnot->GetString("Subtype") == "Widget") {
921       LoadField(pAnnot);
922     }
923   }
924 }
AddTerminalField(CPDF_Dictionary * pFieldDict)925 CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) {
926   if (!pFieldDict->KeyExist("T")) {
927     return NULL;
928   }
929   CPDF_Dictionary* pDict = pFieldDict;
930   CFX_WideString csWName = GetFullName(pFieldDict);
931   if (csWName.IsEmpty()) {
932     return NULL;
933   }
934   CPDF_FormField* pField = NULL;
935   pField = m_pFieldTree->GetField(csWName);
936   if (!pField) {
937     CPDF_Dictionary* pParent = pFieldDict;
938     if (!pFieldDict->KeyExist("T") &&
939         pFieldDict->GetString("Subtype") == "Widget") {
940       pParent = pFieldDict->GetDict("Parent");
941       if (!pParent) {
942         pParent = pFieldDict;
943       }
944     }
945     if (pParent && pParent != pFieldDict && !pParent->KeyExist("FT")) {
946       if (pFieldDict->KeyExist("FT")) {
947         CPDF_Object* pFTValue = pFieldDict->GetElementValue("FT");
948         if (pFTValue) {
949           pParent->SetAt("FT", pFTValue->Clone());
950         }
951       }
952       if (pFieldDict->KeyExist("Ff")) {
953         CPDF_Object* pFfValue = pFieldDict->GetElementValue("Ff");
954         if (pFfValue) {
955           pParent->SetAt("Ff", pFfValue->Clone());
956         }
957       }
958     }
959     pField = new CPDF_FormField(this, pParent);
960     CPDF_Object* pTObj = pDict->GetElement("T");
961     if (ToReference(pTObj)) {
962       CPDF_Object* pClone = pTObj->Clone(TRUE);
963       if (pClone)
964         pDict->SetAt("T", pClone);
965       else
966         pDict->SetAtName("T", "");
967     }
968     m_pFieldTree->SetField(csWName, pField);
969   }
970   CPDF_Array* pKids = pFieldDict->GetArray("Kids");
971   if (!pKids) {
972     if (pFieldDict->GetString("Subtype") == "Widget") {
973       AddControl(pField, pFieldDict);
974     }
975   } else {
976     for (FX_DWORD i = 0; i < pKids->GetCount(); i++) {
977       CPDF_Dictionary* pKid = pKids->GetDict(i);
978       if (!pKid) {
979         continue;
980       }
981       if (pKid->GetString("Subtype") != "Widget") {
982         continue;
983       }
984       AddControl(pField, pKid);
985     }
986   }
987   return pField;
988 }
AddControl(const CPDF_FormField * pField,CPDF_Dictionary * pWidgetDict)989 CPDF_FormControl* CPDF_InterForm::AddControl(const CPDF_FormField* pField,
990                                              CPDF_Dictionary* pWidgetDict) {
991   const auto it = m_ControlMap.find(pWidgetDict);
992   if (it != m_ControlMap.end())
993     return it->second;
994 
995   CPDF_FormControl* pControl =
996       new CPDF_FormControl((CPDF_FormField*)pField, pWidgetDict);
997   m_ControlMap[pWidgetDict] = pControl;
998   ((CPDF_FormField*)pField)->m_ControlList.Add(pControl);
999   return pControl;
1000 }
1001 
CheckRequiredFields(const std::vector<CPDF_FormField * > * fields,bool bIncludeOrExclude) const1002 CPDF_FormField* CPDF_InterForm::CheckRequiredFields(
1003     const std::vector<CPDF_FormField*>* fields,
1004     bool bIncludeOrExclude) const {
1005   int nCount = m_pFieldTree->m_Root.CountFields();
1006   for (int i = 0; i < nCount; ++i) {
1007     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1008     if (!pField)
1009       continue;
1010 
1011     int32_t iType = pField->GetType();
1012     if (iType == CPDF_FormField::PushButton ||
1013         iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) {
1014       continue;
1015     }
1016     FX_DWORD dwFlags = pField->GetFieldFlags();
1017     // TODO(thestig): Look up these magic numbers and add constants for them.
1018     if (dwFlags & 0x04)
1019       continue;
1020 
1021     bool bFind = true;
1022     if (fields)
1023       bFind = pdfium::ContainsValue(*fields, pField);
1024     if (bIncludeOrExclude == bFind) {
1025       CPDF_Dictionary* pFieldDict = pField->m_pDict;
1026       if ((dwFlags & 0x02) != 0 && pFieldDict->GetString("V").IsEmpty()) {
1027         return pField;
1028       }
1029     }
1030   }
1031   return nullptr;
1032 }
1033 
ExportToFDF(const CFX_WideStringC & pdf_path,bool bSimpleFileSpec) const1034 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path,
1035                                            bool bSimpleFileSpec) const {
1036   std::vector<CPDF_FormField*> fields;
1037   int nCount = m_pFieldTree->m_Root.CountFields();
1038   for (int i = 0; i < nCount; ++i)
1039     fields.push_back(m_pFieldTree->m_Root.GetField(i));
1040   return ExportToFDF(pdf_path, fields, true, bSimpleFileSpec);
1041 }
1042 
ExportToFDF(const CFX_WideStringC & pdf_path,const std::vector<CPDF_FormField * > & fields,bool bIncludeOrExclude,bool bSimpleFileSpec) const1043 CFDF_Document* CPDF_InterForm::ExportToFDF(
1044     const CFX_WideStringC& pdf_path,
1045     const std::vector<CPDF_FormField*>& fields,
1046     bool bIncludeOrExclude,
1047     bool bSimpleFileSpec) const {
1048   CFDF_Document* pDoc = CFDF_Document::CreateNewDoc();
1049   if (!pDoc) {
1050     return NULL;
1051   }
1052   CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDict("FDF");
1053   if (!pdf_path.IsEmpty()) {
1054     if (bSimpleFileSpec) {
1055       CFX_WideString wsFilePath = FILESPEC_EncodeFileName(pdf_path);
1056       pMainDict->SetAtString("F", CFX_ByteString::FromUnicode(wsFilePath));
1057       pMainDict->SetAtString("UF", PDF_EncodeText(wsFilePath));
1058     } else {
1059       CPDF_FileSpec filespec;
1060       filespec.SetFileName(pdf_path);
1061       pMainDict->SetAt("F", static_cast<CPDF_Object*>(filespec));
1062     }
1063   }
1064   CPDF_Array* pFields = new CPDF_Array;
1065   pMainDict->SetAt("Fields", pFields);
1066   int nCount = m_pFieldTree->m_Root.CountFields();
1067   for (int i = 0; i < nCount; i++) {
1068     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1069     if (!pField || pField->GetType() == CPDF_FormField::PushButton) {
1070       continue;
1071     }
1072     FX_DWORD dwFlags = pField->GetFieldFlags();
1073     if (dwFlags & 0x04)
1074       continue;
1075 
1076     if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) {
1077       if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetString("V").IsEmpty())
1078         continue;
1079 
1080       CFX_WideString fullname = GetFullName(pField->GetFieldDict());
1081       CPDF_Dictionary* pFieldDict = new CPDF_Dictionary;
1082       pFieldDict->SetAt("T", new CPDF_String(fullname));
1083       if (pField->GetType() == CPDF_FormField::CheckBox ||
1084           pField->GetType() == CPDF_FormField::RadioButton) {
1085         CFX_WideString csExport = pField->GetCheckValue(FALSE);
1086         CFX_ByteString csBExport = PDF_EncodeText(csExport);
1087         CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt");
1088         if (pOpt)
1089           pFieldDict->SetAtString("V", csBExport);
1090         else
1091           pFieldDict->SetAtName("V", csBExport);
1092       } else {
1093         CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V");
1094         if (pV)
1095           pFieldDict->SetAt("V", pV->Clone(TRUE));
1096       }
1097       pFields->Add(pFieldDict);
1098     }
1099   }
1100   return pDoc;
1101 }
1102 const struct _SupportFieldEncoding {
1103   const FX_CHAR* m_name;
1104   int32_t m_codePage;
1105 } g_fieldEncoding[] = {
1106     {"BigFive", 950},
1107     {"GBK", 936},
1108     {"Shift-JIS", 932},
1109     {"UHC", 949},
1110 };
FPDFDOC_FDF_GetFieldValue(CPDF_Dictionary * pFieldDict,CFX_WideString & csValue,CFX_ByteString & bsEncoding)1111 static void FPDFDOC_FDF_GetFieldValue(CPDF_Dictionary* pFieldDict,
1112                                       CFX_WideString& csValue,
1113                                       CFX_ByteString& bsEncoding) {
1114   CFX_ByteString csBValue = pFieldDict->GetString("V");
1115   int32_t iCount = sizeof(g_fieldEncoding) / sizeof(g_fieldEncoding[0]);
1116   int32_t i = 0;
1117   for (; i < iCount; ++i)
1118     if (bsEncoding == g_fieldEncoding[i].m_name) {
1119       break;
1120     }
1121   if (i < iCount) {
1122     CFX_CharMap* pCharMap =
1123         CFX_CharMap::GetDefaultMapper(g_fieldEncoding[i].m_codePage);
1124     FXSYS_assert(pCharMap);
1125     csValue.ConvertFrom(csBValue, pCharMap);
1126     return;
1127   }
1128   CFX_ByteString csTemp = csBValue.Left(2);
1129   if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") {
1130     csValue = PDF_DecodeText(csBValue);
1131   } else {
1132     csValue = CFX_WideString::FromLocal(csBValue);
1133   }
1134 }
FDF_ImportField(CPDF_Dictionary * pFieldDict,const CFX_WideString & parent_name,FX_BOOL bNotify,int nLevel)1135 void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict,
1136                                      const CFX_WideString& parent_name,
1137                                      FX_BOOL bNotify,
1138                                      int nLevel) {
1139   CFX_WideString name;
1140   if (!parent_name.IsEmpty()) {
1141     name = parent_name + L".";
1142   }
1143   name += pFieldDict->GetUnicodeText("T");
1144   CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1145   if (pKids) {
1146     for (FX_DWORD i = 0; i < pKids->GetCount(); i++) {
1147       CPDF_Dictionary* pKid = pKids->GetDict(i);
1148       if (!pKid) {
1149         continue;
1150       }
1151       if (nLevel <= nMaxRecursion) {
1152         FDF_ImportField(pKid, name, bNotify, nLevel + 1);
1153       }
1154     }
1155     return;
1156   }
1157   if (!pFieldDict->KeyExist("V")) {
1158     return;
1159   }
1160   CPDF_FormField* pField = m_pFieldTree->GetField(name);
1161   if (!pField) {
1162     return;
1163   }
1164   CFX_WideString csWValue;
1165   FPDFDOC_FDF_GetFieldValue(pFieldDict, csWValue, m_bsEncoding);
1166   int iType = pField->GetFieldType();
1167   if (bNotify && m_pFormNotify) {
1168     int iRet = 0;
1169     if (iType == FIELDTYPE_LISTBOX) {
1170       iRet = m_pFormNotify->BeforeSelectionChange(pField, csWValue);
1171     } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
1172       iRet = m_pFormNotify->BeforeValueChange(pField, csWValue);
1173     }
1174     if (iRet < 0) {
1175       return;
1176     }
1177   }
1178   CFX_ByteArray statusArray;
1179   if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
1180     SaveCheckedFieldStatus(pField, statusArray);
1181   }
1182   pField->SetValue(csWValue);
1183   CPDF_FormField::Type eType = pField->GetType();
1184   if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) &&
1185       pFieldDict->KeyExist("Opt")) {
1186     pField->m_pDict->SetAt("Opt",
1187                            pFieldDict->GetElementValue("Opt")->Clone(TRUE));
1188   }
1189   if (bNotify && m_pFormNotify) {
1190     if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
1191       m_pFormNotify->AfterCheckedStatusChange(pField, statusArray);
1192     } else if (iType == FIELDTYPE_LISTBOX) {
1193       m_pFormNotify->AfterSelectionChange(pField);
1194     } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
1195       m_pFormNotify->AfterValueChange(pField);
1196     }
1197   }
1198   if (CPDF_InterForm::m_bUpdateAP) {
1199     pField->UpdateAP(NULL);
1200   }
1201 }
ImportFromFDF(const CFDF_Document * pFDF,FX_BOOL bNotify)1202 FX_BOOL CPDF_InterForm::ImportFromFDF(const CFDF_Document* pFDF,
1203                                       FX_BOOL bNotify) {
1204   if (!pFDF) {
1205     return FALSE;
1206   }
1207   CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDict("FDF");
1208   if (!pMainDict) {
1209     return FALSE;
1210   }
1211   CPDF_Array* pFields = pMainDict->GetArray("Fields");
1212   if (!pFields) {
1213     return FALSE;
1214   }
1215   m_bsEncoding = pMainDict->GetString("Encoding");
1216   if (bNotify && m_pFormNotify) {
1217     int iRet = m_pFormNotify->BeforeFormImportData(this);
1218     if (iRet < 0) {
1219       return FALSE;
1220     }
1221   }
1222   for (FX_DWORD i = 0; i < pFields->GetCount(); i++) {
1223     CPDF_Dictionary* pField = pFields->GetDict(i);
1224     if (!pField) {
1225       continue;
1226     }
1227     FDF_ImportField(pField, L"", bNotify);
1228   }
1229   if (bNotify && m_pFormNotify) {
1230     m_pFormNotify->AfterFormImportData(this);
1231   }
1232   return TRUE;
1233 }
SetFormNotify(const CPDF_FormNotify * pNotify)1234 void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify) {
1235   m_pFormNotify = (CPDF_FormNotify*)pNotify;
1236 }
1237