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