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