• 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_interactiveform.h"
8 
9 #include <utility>
10 #include <vector>
11 
12 #include "build/build_config.h"
13 #include "constants/form_fields.h"
14 #include "constants/stream_dict_common.h"
15 #include "core/fpdfapi/font/cpdf_font.h"
16 #include "core/fpdfapi/font/cpdf_fontencoding.h"
17 #include "core/fpdfapi/page/cpdf_docpagedata.h"
18 #include "core/fpdfapi/page/cpdf_page.h"
19 #include "core/fpdfapi/parser/cfdf_document.h"
20 #include "core/fpdfapi/parser/cpdf_array.h"
21 #include "core/fpdfapi/parser/cpdf_dictionary.h"
22 #include "core/fpdfapi/parser/cpdf_document.h"
23 #include "core/fpdfapi/parser/cpdf_name.h"
24 #include "core/fpdfapi/parser/cpdf_reference.h"
25 #include "core/fpdfapi/parser/cpdf_string.h"
26 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
27 #include "core/fpdfdoc/cpdf_filespec.h"
28 #include "core/fpdfdoc/cpdf_formcontrol.h"
29 #include "core/fxcrt/fx_codepage.h"
30 #include "core/fxge/cfx_substfont.h"
31 #include "core/fxge/fx_font.h"
32 #include "third_party/base/ptr_util.h"
33 #include "third_party/base/stl_util.h"
34 
35 namespace {
36 
37 const int nMaxRecursion = 32;
38 
39 void AddFont(CPDF_Dictionary*& pFormDict,
40              CPDF_Document* pDocument,
41              const RetainPtr<CPDF_Font>& pFont,
42              ByteString* csNameTag);
43 
GenerateNewFontResourceName(const CPDF_Dictionary * pResDict,const ByteString & csPrefix)44 ByteString GenerateNewFontResourceName(const CPDF_Dictionary* pResDict,
45                                        const ByteString& csPrefix) {
46   static const char kDummyFontName[] = "ZiTi";
47   ByteString csStr = csPrefix;
48   if (csStr.IsEmpty())
49     csStr = kDummyFontName;
50 
51   const size_t szCount = csStr.GetLength();
52   size_t m = 0;
53   ByteString csTmp;
54   while (m < strlen(kDummyFontName) && m < szCount)
55     csTmp += csStr[m++];
56   while (m < strlen(kDummyFontName)) {
57     csTmp += '0' + m % 10;
58     m++;
59   }
60 
61   const CPDF_Dictionary* pDict = pResDict->GetDictFor("Font");
62   ASSERT(pDict);
63 
64   int num = 0;
65   ByteString bsNum;
66   while (true) {
67     ByteString csKey = csTmp + bsNum;
68     if (!pDict->KeyExist(csKey))
69       return csKey;
70     if (m < szCount)
71       csTmp += csStr[m++];
72     else
73       bsNum = ByteString::Format("%d", num++);
74 
75     m++;
76   }
77   return csTmp;
78 }
79 
InitDict(CPDF_Dictionary * & pFormDict,CPDF_Document * pDocument)80 void InitDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) {
81   if (!pDocument)
82     return;
83 
84   if (!pFormDict) {
85     pFormDict = pDocument->NewIndirect<CPDF_Dictionary>();
86     pDocument->GetRoot()->SetNewFor<CPDF_Reference>("AcroForm", pDocument,
87                                                     pFormDict->GetObjNum());
88   }
89 
90   ByteString csDA;
91   if (!pFormDict->KeyExist("DR")) {
92     ByteString csBaseName;
93     uint8_t charSet = CPDF_InteractiveForm::GetNativeCharSet();
94     RetainPtr<CPDF_Font> pFont = CPDF_InteractiveForm::AddStandardFont(
95         pDocument, CFX_Font::kDefaultAnsiFontName);
96     if (pFont)
97       AddFont(pFormDict, pDocument, pFont, &csBaseName);
98 
99     if (charSet != FX_CHARSET_ANSI) {
100       ByteString csFontName =
101           CPDF_InteractiveForm::GetNativeFontName(charSet, nullptr);
102       if (!pFont || csFontName != CFX_Font::kDefaultAnsiFontName) {
103         pFont = CPDF_InteractiveForm::AddNativeFont(pDocument);
104         if (pFont) {
105           csBaseName.clear();
106           AddFont(pFormDict, pDocument, pFont, &csBaseName);
107         }
108       }
109     }
110     if (pFont)
111       csDA = "/" + PDF_NameEncode(csBaseName) + " 0 Tf";
112   }
113   if (!csDA.IsEmpty())
114     csDA += " ";
115 
116   csDA += "0 g";
117   if (!pFormDict->KeyExist("DA"))
118     pFormDict->SetNewFor<CPDF_String>("DA", csDA, false);
119 }
120 
GetFont(CPDF_Dictionary * pFormDict,CPDF_Document * pDocument,const ByteString & csNameTag)121 RetainPtr<CPDF_Font> GetFont(CPDF_Dictionary* pFormDict,
122                              CPDF_Document* pDocument,
123                              const ByteString& csNameTag) {
124   ByteString csAlias = PDF_NameDecode(csNameTag.AsStringView());
125   if (!pFormDict || csAlias.IsEmpty())
126     return nullptr;
127 
128   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
129   if (!pDR)
130     return nullptr;
131 
132   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
133   if (!ValidateFontResourceDict(pFonts))
134     return nullptr;
135 
136   CPDF_Dictionary* pElement = pFonts->GetDictFor(csAlias);
137   if (!pElement || pElement->GetStringFor("Type") != "Font")
138     return nullptr;
139 
140   return CPDF_DocPageData::FromDocument(pDocument)->GetFont(pElement);
141 }
142 
GetNativeFont(CPDF_Dictionary * pFormDict,CPDF_Document * pDocument,uint8_t charSet,ByteString * csNameTag)143 RetainPtr<CPDF_Font> GetNativeFont(CPDF_Dictionary* pFormDict,
144                                    CPDF_Document* pDocument,
145                                    uint8_t charSet,
146                                    ByteString* csNameTag) {
147   if (!pFormDict)
148     return nullptr;
149 
150   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
151   if (!pDR)
152     return nullptr;
153 
154   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
155   if (!ValidateFontResourceDict(pFonts))
156     return nullptr;
157 
158   CPDF_DictionaryLocker locker(pFonts);
159   for (const auto& it : locker) {
160     const ByteString& csKey = it.first;
161     if (!it.second)
162       continue;
163 
164     CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
165     if (!pElement || pElement->GetStringFor("Type") != "Font")
166       continue;
167 
168     auto* pData = CPDF_DocPageData::FromDocument(pDocument);
169     RetainPtr<CPDF_Font> pFind = pData->GetFont(pElement);
170     if (!pFind)
171       continue;
172 
173     CFX_SubstFont* pSubst = pFind->GetSubstFont();
174     if (!pSubst)
175       continue;
176 
177     if (pSubst->m_Charset == static_cast<int>(charSet)) {
178       *csNameTag = csKey;
179       return pFind;
180     }
181   }
182   return nullptr;
183 }
184 
FindFont(CPDF_Dictionary * pFormDict,const CPDF_Font * pFont,ByteString * csNameTag)185 bool FindFont(CPDF_Dictionary* pFormDict,
186               const CPDF_Font* pFont,
187               ByteString* csNameTag) {
188   if (!pFormDict || !pFont)
189     return false;
190 
191   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
192   if (!pDR)
193     return false;
194 
195   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
196   if (!ValidateFontResourceDict(pFonts))
197     return false;
198 
199   CPDF_DictionaryLocker locker(pFonts);
200   for (const auto& it : locker) {
201     const ByteString& csKey = it.first;
202     if (!it.second)
203       continue;
204     CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
205     if (!pElement)
206       continue;
207     if (pElement->GetStringFor("Type") != "Font")
208       continue;
209     if (pFont->GetFontDict() == pElement) {
210       *csNameTag = csKey;
211       return true;
212     }
213   }
214   return false;
215 }
216 
FindFont(CPDF_Dictionary * pFormDict,CPDF_Document * pDocument,ByteString csFontName,RetainPtr<CPDF_Font> & pFont,ByteString * csNameTag)217 bool FindFont(CPDF_Dictionary* pFormDict,
218               CPDF_Document* pDocument,
219               ByteString csFontName,
220               RetainPtr<CPDF_Font>& pFont,
221               ByteString* csNameTag) {
222   if (!pFormDict)
223     return false;
224 
225   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
226   if (!pDR)
227     return false;
228 
229   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
230   if (!ValidateFontResourceDict(pFonts))
231     return false;
232 
233   if (csFontName.GetLength() > 0)
234     csFontName.Remove(' ');
235 
236   CPDF_DictionaryLocker locker(pFonts);
237   for (const auto& it : locker) {
238     const ByteString& csKey = it.first;
239     if (!it.second)
240       continue;
241 
242     CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
243     if (!pElement || pElement->GetStringFor("Type") != "Font")
244       continue;
245 
246     pFont = CPDF_DocPageData::FromDocument(pDocument)->GetFont(pElement);
247     if (!pFont)
248       continue;
249 
250     ByteString csBaseFont = pFont->GetBaseFontName();
251     csBaseFont.Remove(' ');
252     if (csBaseFont == csFontName) {
253       *csNameTag = csKey;
254       return true;
255     }
256   }
257   return false;
258 }
259 
AddFont(CPDF_Dictionary * & pFormDict,CPDF_Document * pDocument,const RetainPtr<CPDF_Font> & pFont,ByteString * csNameTag)260 void AddFont(CPDF_Dictionary*& pFormDict,
261              CPDF_Document* pDocument,
262              const RetainPtr<CPDF_Font>& pFont,
263              ByteString* csNameTag) {
264   if (!pFont)
265     return;
266   if (!pFormDict)
267     InitDict(pFormDict, pDocument);
268 
269   ByteString csTag;
270   if (FindFont(pFormDict, pFont.Get(), &csTag)) {
271     *csNameTag = std::move(csTag);
272     return;
273   }
274   if (!pFormDict)
275     InitDict(pFormDict, pDocument);
276 
277   CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
278   if (!pDR)
279     pDR = pFormDict->SetNewFor<CPDF_Dictionary>("DR");
280 
281   CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
282   if (!pFonts)
283     pFonts = pDR->SetNewFor<CPDF_Dictionary>("Font");
284 
285   if (csNameTag->IsEmpty())
286     *csNameTag = pFont->GetBaseFontName();
287 
288   csNameTag->Remove(' ');
289   *csNameTag = GenerateNewFontResourceName(pDR, *csNameTag);
290   pFonts->SetNewFor<CPDF_Reference>(*csNameTag, pDocument,
291                                     pFont->GetFontDict()->GetObjNum());
292 }
293 
AddNativeFont(CPDF_Dictionary * & pFormDict,CPDF_Document * pDocument,uint8_t charSet,ByteString * csNameTag)294 RetainPtr<CPDF_Font> AddNativeFont(CPDF_Dictionary*& pFormDict,
295                                    CPDF_Document* pDocument,
296                                    uint8_t charSet,
297                                    ByteString* csNameTag) {
298   if (!pFormDict)
299     InitDict(pFormDict, pDocument);
300 
301   ByteString csTemp;
302   RetainPtr<CPDF_Font> pFont =
303       GetNativeFont(pFormDict, pDocument, charSet, &csTemp);
304   if (pFont) {
305     *csNameTag = std::move(csTemp);
306     return pFont;
307   }
308   ByteString csFontName =
309       CPDF_InteractiveForm::GetNativeFontName(charSet, nullptr);
310   if (!csFontName.IsEmpty() &&
311       FindFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) {
312     return pFont;
313   }
314   pFont = CPDF_InteractiveForm::AddNativeFont(charSet, pDocument);
315   if (!pFont)
316     return nullptr;
317 
318   AddFont(pFormDict, pDocument, pFont, csNameTag);
319   return pFont;
320 }
321 
322 class CFieldNameExtractor {
323  public:
CFieldNameExtractor(const WideString & full_name)324   explicit CFieldNameExtractor(const WideString& full_name)
325       : m_FullName(full_name) {
326     m_pCur = m_FullName.c_str();
327     m_pEnd = m_pCur + m_FullName.GetLength();
328   }
329 
GetNext(const wchar_t * & pSubName,size_t & size)330   void GetNext(const wchar_t*& pSubName, size_t& size) {
331     pSubName = m_pCur;
332     while (m_pCur < m_pEnd && m_pCur[0] != L'.')
333       m_pCur++;
334 
335     size = static_cast<size_t>(m_pCur - pSubName);
336     if (m_pCur < m_pEnd && m_pCur[0] == L'.')
337       m_pCur++;
338   }
339 
340  protected:
341   WideString m_FullName;
342   const wchar_t* m_pCur;
343   const wchar_t* m_pEnd;
344 };
345 
346 #if defined(OS_WIN)
347 struct PDF_FONTDATA {
348   bool bFind;
349   LOGFONTA lf;
350 };
351 
EnumFontFamExProc(ENUMLOGFONTEXA * lpelfe,NEWTEXTMETRICEX * lpntme,DWORD FontType,LPARAM lParam)352 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe,
353                                       NEWTEXTMETRICEX* lpntme,
354                                       DWORD FontType,
355                                       LPARAM lParam) {
356   if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@'))
357     return 1;
358 
359   PDF_FONTDATA* pData = (PDF_FONTDATA*)lParam;
360   memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA));
361   pData->bFind = true;
362   return 0;
363 }
364 
RetrieveSpecificFont(LOGFONTA & lf)365 bool RetrieveSpecificFont(LOGFONTA& lf) {
366   PDF_FONTDATA fd;
367   memset(&fd, 0, sizeof(PDF_FONTDATA));
368   HDC hDC = ::GetDC(nullptr);
369   EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd,
370                       0);
371   ::ReleaseDC(nullptr, hDC);
372   if (fd.bFind)
373     memcpy(&lf, &fd.lf, sizeof(LOGFONTA));
374 
375   return fd.bFind;
376 }
377 
RetrieveSpecificFont(uint8_t charSet,uint8_t pitchAndFamily,LPCSTR pcsFontName,LOGFONTA & lf)378 bool RetrieveSpecificFont(uint8_t charSet,
379                           uint8_t pitchAndFamily,
380                           LPCSTR pcsFontName,
381                           LOGFONTA& lf) {
382   memset(&lf, 0, sizeof(LOGFONTA));
383   lf.lfCharSet = charSet;
384   lf.lfPitchAndFamily = pitchAndFamily;
385   if (pcsFontName) {
386     // TODO(dsinclair): Should this be strncpy?
387     // NOLINTNEXTLINE(runtime/printf)
388     strcpy(lf.lfFaceName, pcsFontName);
389   }
390   return RetrieveSpecificFont(lf);
391 }
392 #endif  // defined(OS_WIN)
393 
394 }  // namespace
395 
396 class CFieldTree {
397  public:
398   class Node {
399    public:
Node()400     Node() : m_level(0) {}
Node(const WideString & short_name,int level)401     Node(const WideString& short_name, int level)
402         : m_ShortName(short_name), m_level(level) {}
403     ~Node() = default;
404 
AddChildNode(std::unique_ptr<Node> pNode)405     void AddChildNode(std::unique_ptr<Node> pNode) {
406       m_Children.push_back(std::move(pNode));
407     }
408 
GetChildrenCount() const409     size_t GetChildrenCount() const { return m_Children.size(); }
410 
GetChildAt(size_t i)411     Node* GetChildAt(size_t i) { return m_Children[i].get(); }
GetChildAt(size_t i) const412     const Node* GetChildAt(size_t i) const { return m_Children[i].get(); }
413 
GetFieldAtIndex(size_t index)414     CPDF_FormField* GetFieldAtIndex(size_t index) {
415       size_t nFieldsToGo = index;
416       return GetFieldInternal(&nFieldsToGo);
417     }
418 
CountFields() const419     size_t CountFields() const { return CountFieldsInternal(); }
420 
SetField(std::unique_ptr<CPDF_FormField> pField)421     void SetField(std::unique_ptr<CPDF_FormField> pField) {
422       m_pField = std::move(pField);
423     }
424 
GetField() const425     CPDF_FormField* GetField() const { return m_pField.get(); }
GetShortName() const426     WideString GetShortName() const { return m_ShortName; }
GetLevel() const427     int GetLevel() const { return m_level; }
428 
429    private:
GetFieldInternal(size_t * pFieldsToGo)430     CPDF_FormField* GetFieldInternal(size_t* pFieldsToGo) {
431       if (m_pField) {
432         if (*pFieldsToGo == 0)
433           return m_pField.get();
434 
435         --*pFieldsToGo;
436       }
437       for (size_t i = 0; i < GetChildrenCount(); ++i) {
438         CPDF_FormField* pField = GetChildAt(i)->GetFieldInternal(pFieldsToGo);
439         if (pField)
440           return pField;
441       }
442       return nullptr;
443     }
444 
CountFieldsInternal() const445     size_t CountFieldsInternal() const {
446       size_t count = 0;
447       if (m_pField)
448         ++count;
449 
450       for (size_t i = 0; i < GetChildrenCount(); ++i)
451         count += GetChildAt(i)->CountFieldsInternal();
452       return count;
453     }
454 
455     std::vector<std::unique_ptr<Node>> m_Children;
456     WideString m_ShortName;
457     std::unique_ptr<CPDF_FormField> m_pField;
458     const int m_level;
459   };
460 
461   CFieldTree();
462   ~CFieldTree();
463 
464   bool SetField(const WideString& full_name,
465                 std::unique_ptr<CPDF_FormField> pField);
466   CPDF_FormField* GetField(const WideString& full_name);
467 
468   Node* FindNode(const WideString& full_name);
469   Node* AddChild(Node* pParent, const WideString& short_name);
470 
471   Node* Lookup(Node* pParent, const WideString& short_name);
472 
473   Node m_Root;
474 };
475 
476 CFieldTree::CFieldTree() = default;
477 
478 CFieldTree::~CFieldTree() = default;
479 
AddChild(Node * pParent,const WideString & short_name)480 CFieldTree::Node* CFieldTree::AddChild(Node* pParent,
481                                        const WideString& short_name) {
482   if (!pParent)
483     return nullptr;
484 
485   int level = pParent->GetLevel() + 1;
486   if (level > nMaxRecursion)
487     return nullptr;
488 
489   auto pNew = pdfium::MakeUnique<Node>(short_name, pParent->GetLevel() + 1);
490   Node* pChild = pNew.get();
491   pParent->AddChildNode(std::move(pNew));
492   return pChild;
493 }
494 
Lookup(Node * pParent,const WideString & short_name)495 CFieldTree::Node* CFieldTree::Lookup(Node* pParent,
496                                      const WideString& short_name) {
497   if (!pParent)
498     return nullptr;
499 
500   for (size_t i = 0; i < pParent->GetChildrenCount(); ++i) {
501     Node* pNode = pParent->GetChildAt(i);
502     if (pNode->GetShortName() == short_name)
503       return pNode;
504   }
505   return nullptr;
506 }
507 
SetField(const WideString & full_name,std::unique_ptr<CPDF_FormField> pField)508 bool CFieldTree::SetField(const WideString& full_name,
509                           std::unique_ptr<CPDF_FormField> pField) {
510   if (full_name.IsEmpty())
511     return false;
512 
513   CFieldNameExtractor name_extractor(full_name);
514   const wchar_t* pName;
515   size_t nLength;
516   name_extractor.GetNext(pName, nLength);
517   Node* pNode = &m_Root;
518   Node* pLast = nullptr;
519   while (nLength > 0) {
520     pLast = pNode;
521     WideString name = WideString(pName, nLength);
522     pNode = Lookup(pLast, name);
523     if (!pNode)
524       pNode = AddChild(pLast, name);
525     if (!pNode)
526       return false;
527 
528     name_extractor.GetNext(pName, nLength);
529   }
530   if (pNode == &m_Root)
531     return false;
532 
533   pNode->SetField(std::move(pField));
534   return true;
535 }
536 
GetField(const WideString & full_name)537 CPDF_FormField* CFieldTree::GetField(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 ? pNode->GetField() : nullptr;
554 }
555 
FindNode(const WideString & full_name)556 CFieldTree::Node* CFieldTree::FindNode(const WideString& full_name) {
557   if (full_name.IsEmpty())
558     return nullptr;
559 
560   CFieldNameExtractor name_extractor(full_name);
561   const wchar_t* pName;
562   size_t nLength;
563   name_extractor.GetNext(pName, nLength);
564   Node* pNode = &m_Root;
565   Node* pLast = nullptr;
566   while (nLength > 0 && pNode) {
567     pLast = pNode;
568     WideString name = WideString(pName, nLength);
569     pNode = Lookup(pLast, name);
570     name_extractor.GetNext(pName, nLength);
571   }
572   return pNode;
573 }
574 
AddNativeInteractiveFormFont(CPDF_Dictionary * & pFormDict,CPDF_Document * pDocument,ByteString * csNameTag)575 RetainPtr<CPDF_Font> AddNativeInteractiveFormFont(CPDF_Dictionary*& pFormDict,
576                                                   CPDF_Document* pDocument,
577                                                   ByteString* csNameTag) {
578   uint8_t charSet = CPDF_InteractiveForm::GetNativeCharSet();
579   return AddNativeFont(pFormDict, pDocument, charSet, csNameTag);
580 }
581 
582 // static
GetNativeCharSet()583 uint8_t CPDF_InteractiveForm::GetNativeCharSet() {
584   return FX_GetCharsetFromCodePage(FXSYS_GetACP());
585 }
586 
CPDF_InteractiveForm(CPDF_Document * pDocument)587 CPDF_InteractiveForm::CPDF_InteractiveForm(CPDF_Document* pDocument)
588     : m_pDocument(pDocument), m_pFieldTree(pdfium::MakeUnique<CFieldTree>()) {
589   CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
590   if (!pRoot)
591     return;
592 
593   m_pFormDict.Reset(pRoot->GetDictFor("AcroForm"));
594   if (!m_pFormDict)
595     return;
596 
597   CPDF_Array* pFields = m_pFormDict->GetArrayFor("Fields");
598   if (!pFields)
599     return;
600 
601   for (size_t i = 0; i < pFields->size(); ++i)
602     LoadField(pFields->GetDictAt(i), 0);
603 }
604 
605 CPDF_InteractiveForm::~CPDF_InteractiveForm() = default;
606 
607 bool CPDF_InteractiveForm::s_bUpdateAP = true;
608 
IsUpdateAPEnabled()609 bool CPDF_InteractiveForm::IsUpdateAPEnabled() {
610   return s_bUpdateAP;
611 }
612 
SetUpdateAP(bool bUpdateAP)613 void CPDF_InteractiveForm::SetUpdateAP(bool bUpdateAP) {
614   s_bUpdateAP = bUpdateAP;
615 }
616 
AddStandardFont(CPDF_Document * pDocument,ByteString csFontName)617 RetainPtr<CPDF_Font> CPDF_InteractiveForm::AddStandardFont(
618     CPDF_Document* pDocument,
619     ByteString csFontName) {
620   if (!pDocument || csFontName.IsEmpty())
621     return nullptr;
622 
623   auto* pPageData = CPDF_DocPageData::FromDocument(pDocument);
624   if (csFontName == "ZapfDingbats")
625     return pPageData->AddStandardFont(csFontName, nullptr);
626 
627   static const CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI);
628   return pPageData->AddStandardFont(csFontName, &encoding);
629 }
630 
GetNativeFontName(uint8_t charSet,void * pLogFont)631 ByteString CPDF_InteractiveForm::GetNativeFontName(uint8_t charSet,
632                                                    void* pLogFont) {
633   ByteString csFontName;
634 #if defined(OS_WIN)
635   LOGFONTA lf = {};
636   if (charSet == FX_CHARSET_ANSI) {
637     csFontName = CFX_Font::kDefaultAnsiFontName;
638     return csFontName;
639   }
640   bool bRet = false;
641   const ByteString default_font_name =
642       CFX_Font::GetDefaultFontNameByCharset(charSet);
643   if (!default_font_name.IsEmpty()) {
644     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
645                                 default_font_name.c_str(), lf);
646   }
647   if (!bRet) {
648     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
649                                 CFX_Font::kUniversalDefaultFontName, lf);
650   }
651   if (!bRet) {
652     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
653                                 "Microsoft Sans Serif", lf);
654   }
655   if (!bRet) {
656     bRet =
657         RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, nullptr, lf);
658   }
659   if (bRet) {
660     if (pLogFont)
661       memcpy(pLogFont, &lf, sizeof(LOGFONTA));
662 
663     csFontName = lf.lfFaceName;
664     return csFontName;
665   }
666 #endif
667   return csFontName;
668 }
669 
AddNativeFont(uint8_t charSet,CPDF_Document * pDocument)670 RetainPtr<CPDF_Font> CPDF_InteractiveForm::AddNativeFont(
671     uint8_t charSet,
672     CPDF_Document* pDocument) {
673   if (!pDocument)
674     return nullptr;
675 
676 #if defined(OS_WIN)
677   LOGFONTA lf;
678   ByteString csFontName = GetNativeFontName(charSet, &lf);
679   if (!csFontName.IsEmpty()) {
680     if (csFontName == CFX_Font::kDefaultAnsiFontName)
681       return AddStandardFont(pDocument, csFontName);
682     return CPDF_DocPageData::FromDocument(pDocument)->AddWindowsFont(&lf);
683   }
684 #endif
685   return nullptr;
686 }
687 
AddNativeFont(CPDF_Document * pDocument)688 RetainPtr<CPDF_Font> CPDF_InteractiveForm::AddNativeFont(
689     CPDF_Document* pDocument) {
690   return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr;
691 }
692 
CountFields(const WideString & csFieldName) const693 size_t CPDF_InteractiveForm::CountFields(const WideString& csFieldName) const {
694   if (csFieldName.IsEmpty())
695     return m_pFieldTree->m_Root.CountFields();
696 
697   CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName);
698   return pNode ? pNode->CountFields() : 0;
699 }
700 
GetField(uint32_t index,const WideString & csFieldName) const701 CPDF_FormField* CPDF_InteractiveForm::GetField(
702     uint32_t index,
703     const WideString& csFieldName) const {
704   if (csFieldName.IsEmpty())
705     return m_pFieldTree->m_Root.GetFieldAtIndex(index);
706 
707   CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName);
708   return pNode ? pNode->GetFieldAtIndex(index) : nullptr;
709 }
710 
GetFieldByDict(CPDF_Dictionary * pFieldDict) const711 CPDF_FormField* CPDF_InteractiveForm::GetFieldByDict(
712     CPDF_Dictionary* pFieldDict) const {
713   if (!pFieldDict)
714     return nullptr;
715 
716   WideString csWName = CPDF_FormField::GetFullNameForDict(pFieldDict);
717   return m_pFieldTree->GetField(csWName);
718 }
719 
GetControlAtPoint(CPDF_Page * pPage,const CFX_PointF & point,int * z_order) const720 CPDF_FormControl* CPDF_InteractiveForm::GetControlAtPoint(
721     CPDF_Page* pPage,
722     const CFX_PointF& point,
723 
724     int* z_order) const {
725   CPDF_Array* pAnnotList = pPage->GetDict()->GetArrayFor("Annots");
726   if (!pAnnotList)
727     return nullptr;
728 
729   for (size_t i = pAnnotList->size(); i > 0; --i) {
730     size_t annot_index = i - 1;
731     const CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(annot_index);
732     if (!pAnnot)
733       continue;
734 
735     const auto it = m_ControlMap.find(pAnnot);
736     if (it == m_ControlMap.end())
737       continue;
738 
739     CPDF_FormControl* pControl = it->second.get();
740     if (!pControl->GetRect().Contains(point))
741       continue;
742 
743     if (z_order)
744       *z_order = static_cast<int>(annot_index);
745     return pControl;
746   }
747   return nullptr;
748 }
749 
GetControlByDict(const CPDF_Dictionary * pWidgetDict) const750 CPDF_FormControl* CPDF_InteractiveForm::GetControlByDict(
751     const CPDF_Dictionary* pWidgetDict) const {
752   const auto it = m_ControlMap.find(pWidgetDict);
753   return it != m_ControlMap.end() ? it->second.get() : nullptr;
754 }
755 
NeedConstructAP() const756 bool CPDF_InteractiveForm::NeedConstructAP() const {
757   return m_pFormDict && m_pFormDict->GetBooleanFor("NeedAppearances", false);
758 }
759 
CountFieldsInCalculationOrder()760 int CPDF_InteractiveForm::CountFieldsInCalculationOrder() {
761   if (!m_pFormDict)
762     return 0;
763 
764   CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
765   return pArray ? pArray->size() : 0;
766 }
767 
GetFieldInCalculationOrder(int index)768 CPDF_FormField* CPDF_InteractiveForm::GetFieldInCalculationOrder(int index) {
769   if (!m_pFormDict || index < 0)
770     return nullptr;
771 
772   CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
773   if (!pArray)
774     return nullptr;
775 
776   CPDF_Dictionary* pElement = ToDictionary(pArray->GetDirectObjectAt(index));
777   return pElement ? GetFieldByDict(pElement) : nullptr;
778 }
779 
FindFieldInCalculationOrder(const CPDF_FormField * pField)780 int CPDF_InteractiveForm::FindFieldInCalculationOrder(
781     const CPDF_FormField* pField) {
782   if (!m_pFormDict || !pField)
783     return -1;
784 
785   CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
786   if (!pArray)
787     return -1;
788 
789   for (size_t i = 0; i < pArray->size(); i++) {
790     CPDF_Object* pElement = pArray->GetDirectObjectAt(i);
791     if (pElement == pField->GetDict())
792       return i;
793   }
794   return -1;
795 }
796 
GetFormFont(ByteString csNameTag) const797 RetainPtr<CPDF_Font> CPDF_InteractiveForm::GetFormFont(
798     ByteString csNameTag) const {
799   return GetFont(m_pFormDict.Get(), m_pDocument.Get(), csNameTag);
800 }
801 
GetDefaultAppearance() const802 CPDF_DefaultAppearance CPDF_InteractiveForm::GetDefaultAppearance() const {
803   if (!m_pFormDict)
804     return CPDF_DefaultAppearance();
805   return CPDF_DefaultAppearance(m_pFormDict->GetStringFor("DA"));
806 }
807 
GetFormAlignment() const808 int CPDF_InteractiveForm::GetFormAlignment() const {
809   return m_pFormDict ? m_pFormDict->GetIntegerFor("Q", 0) : 0;
810 }
811 
ResetForm(const std::vector<CPDF_FormField * > & fields,bool bIncludeOrExclude,NotificationOption notify)812 void CPDF_InteractiveForm::ResetForm(const std::vector<CPDF_FormField*>& fields,
813                                      bool bIncludeOrExclude,
814                                      NotificationOption notify) {
815   size_t nCount = m_pFieldTree->m_Root.CountFields();
816   for (size_t i = 0; i < nCount; ++i) {
817     CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
818     if (!pField)
819       continue;
820 
821     if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField))
822       pField->ResetField(notify);
823   }
824   if (notify == NotificationOption::kNotify && m_pFormNotify)
825     m_pFormNotify->AfterFormReset(this);
826 }
827 
ResetForm(NotificationOption notify)828 void CPDF_InteractiveForm::ResetForm(NotificationOption notify) {
829   size_t nCount = m_pFieldTree->m_Root.CountFields();
830   for (size_t i = 0; i < nCount; ++i) {
831     CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
832     if (!pField)
833       continue;
834 
835     pField->ResetField(notify);
836   }
837   if (notify == NotificationOption::kNotify && m_pFormNotify)
838     m_pFormNotify->AfterFormReset(this);
839 }
840 
841 const std::vector<UnownedPtr<CPDF_FormControl>>&
GetControlsForField(const CPDF_FormField * pField)842 CPDF_InteractiveForm::GetControlsForField(const CPDF_FormField* pField) {
843   return m_ControlLists[pField];
844 }
845 
LoadField(CPDF_Dictionary * pFieldDict,int nLevel)846 void CPDF_InteractiveForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) {
847   if (nLevel > nMaxRecursion)
848     return;
849   if (!pFieldDict)
850     return;
851 
852   uint32_t dwParentObjNum = pFieldDict->GetObjNum();
853   CPDF_Array* pKids = pFieldDict->GetArrayFor(pdfium::form_fields::kKids);
854   if (!pKids) {
855     AddTerminalField(pFieldDict);
856     return;
857   }
858 
859   CPDF_Dictionary* pFirstKid = pKids->GetDictAt(0);
860   if (!pFirstKid)
861     return;
862 
863   if (pFirstKid->KeyExist(pdfium::form_fields::kT) ||
864       pFirstKid->KeyExist(pdfium::form_fields::kKids)) {
865     for (size_t i = 0; i < pKids->size(); i++) {
866       CPDF_Dictionary* pChildDict = pKids->GetDictAt(i);
867       if (pChildDict) {
868         if (pChildDict->GetObjNum() != dwParentObjNum)
869           LoadField(pChildDict, nLevel + 1);
870       }
871     }
872   } else {
873     AddTerminalField(pFieldDict);
874   }
875 }
876 
HasXFAForm() const877 bool CPDF_InteractiveForm::HasXFAForm() const {
878   return m_pFormDict && m_pFormDict->GetArrayFor("XFA");
879 }
880 
FixPageFields(CPDF_Page * pPage)881 void CPDF_InteractiveForm::FixPageFields(CPDF_Page* pPage) {
882   CPDF_Array* pAnnots = pPage->GetDict()->GetArrayFor("Annots");
883   if (!pAnnots)
884     return;
885 
886   for (size_t i = 0; i < pAnnots->size(); i++) {
887     CPDF_Dictionary* pAnnot = pAnnots->GetDictAt(i);
888     if (pAnnot && pAnnot->GetStringFor("Subtype") == "Widget")
889       LoadField(pAnnot, 0);
890   }
891 }
892 
AddTerminalField(CPDF_Dictionary * pFieldDict)893 void CPDF_InteractiveForm::AddTerminalField(CPDF_Dictionary* pFieldDict) {
894   if (!pFieldDict->KeyExist(pdfium::form_fields::kFT)) {
895     // Key "FT" is required for terminal fields, it is also inheritable.
896     CPDF_Dictionary* pParentDict =
897         pFieldDict->GetDictFor(pdfium::form_fields::kParent);
898     if (!pParentDict || !pParentDict->KeyExist(pdfium::form_fields::kFT))
899       return;
900   }
901 
902   CPDF_Dictionary* pDict = pFieldDict;
903   WideString csWName = CPDF_FormField::GetFullNameForDict(pFieldDict);
904   if (csWName.IsEmpty())
905     return;
906 
907   CPDF_FormField* pField = nullptr;
908   pField = m_pFieldTree->GetField(csWName);
909   if (!pField) {
910     CPDF_Dictionary* pParent = pFieldDict;
911     if (!pFieldDict->KeyExist(pdfium::form_fields::kT) &&
912         pFieldDict->GetStringFor("Subtype") == "Widget") {
913       pParent = pFieldDict->GetDictFor(pdfium::form_fields::kParent);
914       if (!pParent)
915         pParent = pFieldDict;
916     }
917 
918     if (pParent && pParent != pFieldDict &&
919         !pParent->KeyExist(pdfium::form_fields::kFT)) {
920       if (pFieldDict->KeyExist(pdfium::form_fields::kFT)) {
921         CPDF_Object* pFTValue =
922             pFieldDict->GetDirectObjectFor(pdfium::form_fields::kFT);
923         if (pFTValue)
924           pParent->SetFor(pdfium::form_fields::kFT, pFTValue->Clone());
925       }
926 
927       if (pFieldDict->KeyExist(pdfium::form_fields::kFf)) {
928         CPDF_Object* pFfValue =
929             pFieldDict->GetDirectObjectFor(pdfium::form_fields::kFf);
930         if (pFfValue)
931           pParent->SetFor(pdfium::form_fields::kFf, pFfValue->Clone());
932       }
933     }
934 
935     auto newField = pdfium::MakeUnique<CPDF_FormField>(this, pParent);
936     pField = newField.get();
937     CPDF_Object* pTObj = pDict->GetObjectFor(pdfium::form_fields::kT);
938     if (ToReference(pTObj)) {
939       RetainPtr<CPDF_Object> pClone = pTObj->CloneDirectObject();
940       if (pClone)
941         pDict->SetFor(pdfium::form_fields::kT, std::move(pClone));
942       else
943         pDict->SetNewFor<CPDF_Name>(pdfium::form_fields::kT, ByteString());
944     }
945     if (!m_pFieldTree->SetField(csWName, std::move(newField)))
946       return;
947   }
948 
949   CPDF_Array* pKids = pFieldDict->GetArrayFor(pdfium::form_fields::kKids);
950   if (pKids) {
951     for (size_t i = 0; i < pKids->size(); i++) {
952       CPDF_Dictionary* pKid = pKids->GetDictAt(i);
953       if (!pKid)
954         continue;
955       if (pKid->GetStringFor("Subtype") != "Widget")
956         continue;
957 
958       AddControl(pField, pKid);
959     }
960   } else {
961     if (pFieldDict->GetStringFor("Subtype") == "Widget")
962       AddControl(pField, pFieldDict);
963   }
964 }
965 
AddControl(CPDF_FormField * pField,CPDF_Dictionary * pWidgetDict)966 CPDF_FormControl* CPDF_InteractiveForm::AddControl(
967     CPDF_FormField* pField,
968     CPDF_Dictionary* pWidgetDict) {
969   const auto it = m_ControlMap.find(pWidgetDict);
970   if (it != m_ControlMap.end())
971     return it->second.get();
972 
973   auto pNew = pdfium::MakeUnique<CPDF_FormControl>(pField, pWidgetDict);
974   CPDF_FormControl* pControl = pNew.get();
975   m_ControlMap[pWidgetDict] = std::move(pNew);
976   m_ControlLists[pField].emplace_back(pControl);
977   return pControl;
978 }
979 
CheckRequiredFields(const std::vector<CPDF_FormField * > * fields,bool bIncludeOrExclude) const980 bool CPDF_InteractiveForm::CheckRequiredFields(
981     const std::vector<CPDF_FormField*>* fields,
982     bool bIncludeOrExclude) const {
983   size_t nCount = m_pFieldTree->m_Root.CountFields();
984   for (size_t i = 0; i < nCount; ++i) {
985     CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
986     if (!pField)
987       continue;
988 
989     int32_t iType = pField->GetType();
990     if (iType == CPDF_FormField::kPushButton ||
991         iType == CPDF_FormField::kCheckBox ||
992         iType == CPDF_FormField::kListBox) {
993       continue;
994     }
995     if (pField->IsNoExport())
996       continue;
997 
998     bool bFind = true;
999     if (fields)
1000       bFind = pdfium::ContainsValue(*fields, pField);
1001     if (bIncludeOrExclude == bFind) {
1002       const CPDF_Dictionary* pFieldDict = pField->GetDict();
1003       if (pField->IsRequired() &&
1004           pFieldDict->GetStringFor(pdfium::form_fields::kV).IsEmpty()) {
1005         return false;
1006       }
1007     }
1008   }
1009   return true;
1010 }
1011 
ExportToFDF(const WideString & pdf_path,bool bSimpleFileSpec) const1012 std::unique_ptr<CFDF_Document> CPDF_InteractiveForm::ExportToFDF(
1013     const WideString& pdf_path,
1014     bool bSimpleFileSpec) const {
1015   std::vector<CPDF_FormField*> fields;
1016   size_t nCount = m_pFieldTree->m_Root.CountFields();
1017   for (size_t i = 0; i < nCount; ++i)
1018     fields.push_back(m_pFieldTree->m_Root.GetFieldAtIndex(i));
1019   return ExportToFDF(pdf_path, fields, true, bSimpleFileSpec);
1020 }
1021 
ExportToFDF(const WideString & pdf_path,const std::vector<CPDF_FormField * > & fields,bool bIncludeOrExclude,bool bSimpleFileSpec) const1022 std::unique_ptr<CFDF_Document> CPDF_InteractiveForm::ExportToFDF(
1023     const WideString& pdf_path,
1024     const std::vector<CPDF_FormField*>& fields,
1025     bool bIncludeOrExclude,
1026     bool bSimpleFileSpec) const {
1027   std::unique_ptr<CFDF_Document> pDoc = CFDF_Document::CreateNewDoc();
1028   if (!pDoc)
1029     return nullptr;
1030 
1031   CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDictFor("FDF");
1032   if (!pdf_path.IsEmpty()) {
1033     if (bSimpleFileSpec) {
1034       WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path);
1035       pMainDict->SetNewFor<CPDF_String>(pdfium::stream::kF,
1036                                         wsFilePath.ToDefANSI(), false);
1037       pMainDict->SetNewFor<CPDF_String>("UF", wsFilePath);
1038     } else {
1039       auto pNewDict = pDoc->New<CPDF_Dictionary>();
1040       pNewDict->SetNewFor<CPDF_Name>("Type", "Filespec");
1041       CPDF_FileSpec filespec(pNewDict.Get());
1042       filespec.SetFileName(pdf_path);
1043       pMainDict->SetFor("F", pNewDict);
1044     }
1045   }
1046 
1047   CPDF_Array* pFields = pMainDict->SetNewFor<CPDF_Array>("Fields");
1048   size_t nCount = m_pFieldTree->m_Root.CountFields();
1049   for (size_t i = 0; i < nCount; ++i) {
1050     CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
1051     if (!pField || pField->GetType() == CPDF_FormField::kPushButton)
1052       continue;
1053 
1054     uint32_t dwFlags = pField->GetFieldFlags();
1055     if (dwFlags & 0x04)
1056       continue;
1057 
1058     if (bIncludeOrExclude != pdfium::ContainsValue(fields, pField))
1059       continue;
1060 
1061     if ((dwFlags & 0x02) != 0 &&
1062         pField->GetDict()->GetStringFor(pdfium::form_fields::kV).IsEmpty()) {
1063       continue;
1064     }
1065 
1066     WideString fullname =
1067         CPDF_FormField::GetFullNameForDict(pField->GetFieldDict());
1068     auto pFieldDict = pDoc->New<CPDF_Dictionary>();
1069     pFieldDict->SetNewFor<CPDF_String>(pdfium::form_fields::kT, fullname);
1070     if (pField->GetType() == CPDF_FormField::kCheckBox ||
1071         pField->GetType() == CPDF_FormField::kRadioButton) {
1072       WideString csExport = pField->GetCheckValue(false);
1073       ByteString csBExport = PDF_EncodeText(csExport);
1074       CPDF_Object* pOpt =
1075           CPDF_FormField::GetFieldAttr(pField->GetDict(), "Opt");
1076       if (pOpt) {
1077         pFieldDict->SetNewFor<CPDF_String>(pdfium::form_fields::kV, csBExport,
1078                                            false);
1079       } else {
1080         pFieldDict->SetNewFor<CPDF_Name>(pdfium::form_fields::kV, csBExport);
1081       }
1082     } else {
1083       CPDF_Object* pV = CPDF_FormField::GetFieldAttr(pField->GetDict(),
1084                                                      pdfium::form_fields::kV);
1085       if (pV)
1086         pFieldDict->SetFor(pdfium::form_fields::kV, pV->CloneDirectObject());
1087     }
1088     pFields->Add(pFieldDict);
1089   }
1090   return pDoc;
1091 }
1092 
SetNotifierIface(NotifierIface * pNotify)1093 void CPDF_InteractiveForm::SetNotifierIface(NotifierIface* pNotify) {
1094   m_pFormNotify = pNotify;
1095 }
1096