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