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