blob: 6bf72fd5ef5e7eb98c827f45446e6075b22c35a7 [file] [log] [blame]
dsinclair27053d82016-08-02 15:43:46 -07001// Copyright 2016 PDFium Authors. All rights reserved.
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhang95e854f2015-06-13 00:58:06 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
tsepez0e606b52016-11-18 16:22:41 -08007#include "core/fpdfdoc/cpdf_interform.h"
8
9#include <utility>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050010#include <vector>
11
Lei Zhang26170562018-04-17 17:01:52 +000012#include "constants/stream_dict_common.h"
dsinclairbc5e6d22016-10-04 11:08:49 -070013#include "core/fpdfapi/font/cpdf_font.h"
14#include "core/fpdfapi/font/cpdf_fontencoding.h"
dsinclair41872fa2016-10-04 11:29:35 -070015#include "core/fpdfapi/page/cpdf_page.h"
dsinclair488b7ad2016-10-04 11:55:50 -070016#include "core/fpdfapi/parser/cfdf_document.h"
17#include "core/fpdfapi/parser/cpdf_array.h"
18#include "core/fpdfapi/parser/cpdf_document.h"
tsepez0e606b52016-11-18 16:22:41 -080019#include "core/fpdfapi/parser/cpdf_name.h"
tsepez10a28532016-10-10 18:45:55 -070020#include "core/fpdfapi/parser/cpdf_reference.h"
dsinclair488b7ad2016-10-04 11:55:50 -070021#include "core/fpdfapi/parser/cpdf_string.h"
Tom Sepeza7b15592018-04-16 19:22:57 +000022#include "core/fpdfapi/parser/fpdf_parser_utility.h"
dsinclair1727aee2016-09-29 13:12:56 -070023#include "core/fpdfdoc/cpdf_filespec.h"
24#include "core/fpdfdoc/cpdf_formcontrol.h"
Dan Sinclairf51a02a2017-04-19 12:46:53 -040025#include "core/fxcrt/fx_codepage.h"
dsinclair74a34fc2016-09-29 16:41:42 -070026#include "core/fxge/cfx_substfont.h"
27#include "core/fxge/fx_font.h"
Tom Sepez6e72b2e2017-04-26 15:14:35 -070028#include "third_party/base/ptr_util.h"
Lei Zhangcd2bb302015-12-22 13:49:44 -080029#include "third_party/base/stl_util.h"
Tom Sepezeff208f2015-05-08 13:45:01 -070030
Lei Zhang31c7b732016-02-19 10:53:24 -080031namespace {
32
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070033const int nMaxRecursion = 32;
Tom Sepezeff208f2015-05-08 13:45:01 -070034
Lei Zhang31c7b732016-02-19 10:53:24 -080035const struct SupportFieldEncoding {
Dan Sinclair812e96c2017-03-13 16:43:37 -040036 const char* m_name;
Tom Sepez62a70f92016-03-21 15:00:20 -070037 uint16_t m_codePage;
Lei Zhang31c7b732016-02-19 10:53:24 -080038} g_fieldEncoding[] = {
39 {"BigFive", 950},
40 {"GBK", 936},
41 {"Shift-JIS", 932},
42 {"UHC", 949},
43};
44
Ryan Harrison275e2602017-09-18 14:23:18 -040045WideString GetFieldValue(const CPDF_Dictionary& pFieldDict,
46 const ByteString& bsEncoding) {
47 const ByteString csBValue = pFieldDict.GetStringFor("V");
Lei Zhang31c7b732016-02-19 10:53:24 -080048 for (const auto& encoding : g_fieldEncoding) {
49 if (bsEncoding == encoding.m_name)
Ryan Harrison275e2602017-09-18 14:23:18 -040050 return WideString::FromCodePage(csBValue.AsStringView(),
51 encoding.m_codePage);
Lei Zhang31c7b732016-02-19 10:53:24 -080052 }
Ryan Harrison275e2602017-09-18 14:23:18 -040053 ByteString csTemp = csBValue.Left(2);
Lei Zhang31c7b732016-02-19 10:53:24 -080054 if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF")
55 return PDF_DecodeText(csBValue);
Ryan Harrison275e2602017-09-18 14:23:18 -040056 return WideString::FromLocal(csBValue.AsStringView());
Lei Zhang31c7b732016-02-19 10:53:24 -080057}
58
dsinclair27053d82016-08-02 15:43:46 -070059void AddFont(CPDF_Dictionary*& pFormDict,
60 CPDF_Document* pDocument,
61 const CPDF_Font* pFont,
Ryan Harrison275e2602017-09-18 14:23:18 -040062 ByteString* csNameTag);
dsinclair27053d82016-08-02 15:43:46 -070063
64void InitDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) {
65 if (!pDocument)
66 return;
67
68 if (!pFormDict) {
tsepez5913a6c2016-11-16 17:31:18 -080069 pFormDict = pDocument->NewIndirect<CPDF_Dictionary>();
tsepez0e606b52016-11-18 16:22:41 -080070 pDocument->GetRoot()->SetNewFor<CPDF_Reference>("AcroForm", pDocument,
71 pFormDict->GetObjNum());
dsinclair27053d82016-08-02 15:43:46 -070072 }
73
Ryan Harrison275e2602017-09-18 14:23:18 -040074 ByteString csDA;
dsinclair27053d82016-08-02 15:43:46 -070075 if (!pFormDict->KeyExist("DR")) {
Ryan Harrison275e2602017-09-18 14:23:18 -040076 ByteString csBaseName;
dsinclair27053d82016-08-02 15:43:46 -070077 uint8_t charSet = CPDF_InterForm::GetNativeCharSet();
78 CPDF_Font* pFont = CPDF_InterForm::AddStandardFont(pDocument, "Helvetica");
Tom Sepezc4a2b752017-04-07 13:56:13 -070079 if (pFont)
80 AddFont(pFormDict, pDocument, pFont, &csBaseName);
81
Dan Sinclairf51a02a2017-04-19 12:46:53 -040082 if (charSet != FX_CHARSET_ANSI) {
Ryan Harrison275e2602017-09-18 14:23:18 -040083 ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr);
dsinclair27053d82016-08-02 15:43:46 -070084 if (!pFont || csFontName != "Helvetica") {
85 pFont = CPDF_InterForm::AddNativeFont(pDocument);
86 if (pFont) {
Tom Sepezc4a2b752017-04-07 13:56:13 -070087 csBaseName.clear();
88 AddFont(pFormDict, pDocument, pFont, &csBaseName);
dsinclair27053d82016-08-02 15:43:46 -070089 }
90 }
91 }
92 if (pFont)
Tom Sepezc4a2b752017-04-07 13:56:13 -070093 csDA = "/" + PDF_NameEncode(csBaseName) + " 0 Tf";
dsinclair27053d82016-08-02 15:43:46 -070094 }
95 if (!csDA.IsEmpty())
96 csDA += " ";
97
98 csDA += "0 g";
99 if (!pFormDict->KeyExist("DA"))
tsepez0e606b52016-11-18 16:22:41 -0800100 pFormDict->SetNewFor<CPDF_String>("DA", csDA, false);
dsinclair27053d82016-08-02 15:43:46 -0700101}
102
dsinclair27053d82016-08-02 15:43:46 -0700103CPDF_Font* GetFont(CPDF_Dictionary* pFormDict,
104 CPDF_Document* pDocument,
Ryan Harrison275e2602017-09-18 14:23:18 -0400105 const ByteString& csNameTag) {
Dan Sinclair14094f22018-03-28 17:02:46 +0000106 ByteString csAlias = PDF_NameDecode(csNameTag.AsStringView());
dsinclair27053d82016-08-02 15:43:46 -0700107 if (!pFormDict || csAlias.IsEmpty())
108 return nullptr;
109
dsinclair38fd8442016-09-15 10:15:32 -0700110 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
dsinclair27053d82016-08-02 15:43:46 -0700111 if (!pDR)
112 return nullptr;
113
dsinclair38fd8442016-09-15 10:15:32 -0700114 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
dsinclair27053d82016-08-02 15:43:46 -0700115 if (!pFonts)
116 return nullptr;
117
dsinclair38fd8442016-09-15 10:15:32 -0700118 CPDF_Dictionary* pElement = pFonts->GetDictFor(csAlias);
dsinclair27053d82016-08-02 15:43:46 -0700119 if (!pElement)
120 return nullptr;
121
dsinclair38fd8442016-09-15 10:15:32 -0700122 if (pElement->GetStringFor("Type") == "Font")
dsinclair27053d82016-08-02 15:43:46 -0700123 return pDocument->LoadFont(pElement);
124 return nullptr;
125}
126
dsinclair27053d82016-08-02 15:43:46 -0700127CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict,
128 CPDF_Document* pDocument,
129 uint8_t charSet,
Ryan Harrison275e2602017-09-18 14:23:18 -0400130 ByteString* csNameTag) {
dsinclair27053d82016-08-02 15:43:46 -0700131 if (!pFormDict)
132 return nullptr;
133
dsinclair38fd8442016-09-15 10:15:32 -0700134 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
dsinclair27053d82016-08-02 15:43:46 -0700135 if (!pDR)
136 return nullptr;
137
dsinclair38fd8442016-09-15 10:15:32 -0700138 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
dsinclair27053d82016-08-02 15:43:46 -0700139 if (!pFonts)
140 return nullptr;
141
142 for (const auto& it : *pFonts) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400143 const ByteString& csKey = it.first;
tsepez0e606b52016-11-18 16:22:41 -0800144 if (!it.second)
dsinclair27053d82016-08-02 15:43:46 -0700145 continue;
146
tsepez0e606b52016-11-18 16:22:41 -0800147 CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
dsinclair27053d82016-08-02 15:43:46 -0700148 if (!pElement)
149 continue;
dsinclair38fd8442016-09-15 10:15:32 -0700150 if (pElement->GetStringFor("Type") != "Font")
dsinclair27053d82016-08-02 15:43:46 -0700151 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
Tom Sepezc4a2b752017-04-07 13:56:13 -0700160 if (pSubst->m_Charset == static_cast<int>(charSet)) {
161 *csNameTag = csKey;
dsinclair27053d82016-08-02 15:43:46 -0700162 return pFind;
163 }
164 }
165 return nullptr;
166}
167
tsepez12f3e4a2016-11-02 15:17:29 -0700168bool FindFont(CPDF_Dictionary* pFormDict,
169 const CPDF_Font* pFont,
Ryan Harrison275e2602017-09-18 14:23:18 -0400170 ByteString* csNameTag) {
dsinclair27053d82016-08-02 15:43:46 -0700171 if (!pFormDict || !pFont)
tsepez12f3e4a2016-11-02 15:17:29 -0700172 return false;
dsinclair27053d82016-08-02 15:43:46 -0700173
dsinclair38fd8442016-09-15 10:15:32 -0700174 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
dsinclair27053d82016-08-02 15:43:46 -0700175 if (!pDR)
tsepez12f3e4a2016-11-02 15:17:29 -0700176 return false;
dsinclair27053d82016-08-02 15:43:46 -0700177
dsinclair38fd8442016-09-15 10:15:32 -0700178 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
dsinclair27053d82016-08-02 15:43:46 -0700179 if (!pFonts)
tsepez12f3e4a2016-11-02 15:17:29 -0700180 return false;
dsinclair27053d82016-08-02 15:43:46 -0700181
182 for (const auto& it : *pFonts) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400183 const ByteString& csKey = it.first;
tsepez0e606b52016-11-18 16:22:41 -0800184 if (!it.second)
dsinclair27053d82016-08-02 15:43:46 -0700185 continue;
tsepez0e606b52016-11-18 16:22:41 -0800186 CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
dsinclair27053d82016-08-02 15:43:46 -0700187 if (!pElement)
188 continue;
dsinclair38fd8442016-09-15 10:15:32 -0700189 if (pElement->GetStringFor("Type") != "Font")
dsinclair27053d82016-08-02 15:43:46 -0700190 continue;
191 if (pFont->GetFontDict() == pElement) {
Tom Sepezc4a2b752017-04-07 13:56:13 -0700192 *csNameTag = csKey;
tsepez12f3e4a2016-11-02 15:17:29 -0700193 return true;
dsinclair27053d82016-08-02 15:43:46 -0700194 }
195 }
tsepez12f3e4a2016-11-02 15:17:29 -0700196 return false;
dsinclair27053d82016-08-02 15:43:46 -0700197}
198
tsepez12f3e4a2016-11-02 15:17:29 -0700199bool FindFont(CPDF_Dictionary* pFormDict,
200 CPDF_Document* pDocument,
Ryan Harrison275e2602017-09-18 14:23:18 -0400201 ByteString csFontName,
tsepez12f3e4a2016-11-02 15:17:29 -0700202 CPDF_Font*& pFont,
Ryan Harrison275e2602017-09-18 14:23:18 -0400203 ByteString* csNameTag) {
dsinclair27053d82016-08-02 15:43:46 -0700204 if (!pFormDict)
tsepez12f3e4a2016-11-02 15:17:29 -0700205 return false;
dsinclair27053d82016-08-02 15:43:46 -0700206
dsinclair38fd8442016-09-15 10:15:32 -0700207 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
dsinclair27053d82016-08-02 15:43:46 -0700208 if (!pDR)
tsepez12f3e4a2016-11-02 15:17:29 -0700209 return false;
dsinclair27053d82016-08-02 15:43:46 -0700210
dsinclair38fd8442016-09-15 10:15:32 -0700211 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
dsinclair27053d82016-08-02 15:43:46 -0700212 if (!pFonts)
tsepez12f3e4a2016-11-02 15:17:29 -0700213 return false;
Tom Sepezc4a2b752017-04-07 13:56:13 -0700214
dsinclair27053d82016-08-02 15:43:46 -0700215 if (csFontName.GetLength() > 0)
216 csFontName.Remove(' ');
217
218 for (const auto& it : *pFonts) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400219 const ByteString& csKey = it.first;
tsepez0e606b52016-11-18 16:22:41 -0800220 if (!it.second)
dsinclair27053d82016-08-02 15:43:46 -0700221 continue;
222
tsepez0e606b52016-11-18 16:22:41 -0800223 CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect());
dsinclair27053d82016-08-02 15:43:46 -0700224 if (!pElement)
225 continue;
dsinclair38fd8442016-09-15 10:15:32 -0700226 if (pElement->GetStringFor("Type") != "Font")
dsinclair27053d82016-08-02 15:43:46 -0700227 continue;
dsinclair27053d82016-08-02 15:43:46 -0700228 pFont = pDocument->LoadFont(pElement);
229 if (!pFont)
230 continue;
231
Ryan Harrison275e2602017-09-18 14:23:18 -0400232 ByteString csBaseFont;
dsinclair27053d82016-08-02 15:43:46 -0700233 csBaseFont = pFont->GetBaseFont();
234 csBaseFont.Remove(' ');
235 if (csBaseFont == csFontName) {
Tom Sepezc4a2b752017-04-07 13:56:13 -0700236 *csNameTag = csKey;
tsepez12f3e4a2016-11-02 15:17:29 -0700237 return true;
dsinclair27053d82016-08-02 15:43:46 -0700238 }
239 }
tsepez12f3e4a2016-11-02 15:17:29 -0700240 return false;
dsinclair27053d82016-08-02 15:43:46 -0700241}
242
243void AddFont(CPDF_Dictionary*& pFormDict,
244 CPDF_Document* pDocument,
245 const CPDF_Font* pFont,
Ryan Harrison275e2602017-09-18 14:23:18 -0400246 ByteString* csNameTag) {
dsinclair27053d82016-08-02 15:43:46 -0700247 if (!pFont)
248 return;
249 if (!pFormDict)
250 InitDict(pFormDict, pDocument);
251
Ryan Harrison275e2602017-09-18 14:23:18 -0400252 ByteString csTag;
Tom Sepezc4a2b752017-04-07 13:56:13 -0700253 if (FindFont(pFormDict, pFont, &csTag)) {
254 *csNameTag = csTag;
dsinclair27053d82016-08-02 15:43:46 -0700255 return;
256 }
257 if (!pFormDict)
258 InitDict(pFormDict, pDocument);
259
dsinclair38fd8442016-09-15 10:15:32 -0700260 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
tsepez0e606b52016-11-18 16:22:41 -0800261 if (!pDR)
262 pDR = pFormDict->SetNewFor<CPDF_Dictionary>("DR");
263
dsinclair38fd8442016-09-15 10:15:32 -0700264 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
tsepez0e606b52016-11-18 16:22:41 -0800265 if (!pFonts)
266 pFonts = pDR->SetNewFor<CPDF_Dictionary>("Font");
267
Tom Sepezc4a2b752017-04-07 13:56:13 -0700268 if (csNameTag->IsEmpty())
269 *csNameTag = pFont->GetBaseFont();
dsinclair27053d82016-08-02 15:43:46 -0700270
Tom Sepezc4a2b752017-04-07 13:56:13 -0700271 csNameTag->Remove(' ');
272 *csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4,
273 csNameTag->c_str());
274 pFonts->SetNewFor<CPDF_Reference>(*csNameTag, pDocument,
tsepez0e606b52016-11-18 16:22:41 -0800275 pFont->GetFontDict()->GetObjNum());
dsinclair27053d82016-08-02 15:43:46 -0700276}
277
278CPDF_Font* AddNativeFont(CPDF_Dictionary*& pFormDict,
279 CPDF_Document* pDocument,
280 uint8_t charSet,
Ryan Harrison275e2602017-09-18 14:23:18 -0400281 ByteString* csNameTag) {
dsinclair27053d82016-08-02 15:43:46 -0700282 if (!pFormDict)
283 InitDict(pFormDict, pDocument);
284
Ryan Harrison275e2602017-09-18 14:23:18 -0400285 ByteString csTemp;
Tom Sepezc4a2b752017-04-07 13:56:13 -0700286 CPDF_Font* pFont = GetNativeFont(pFormDict, pDocument, charSet, &csTemp);
dsinclair27053d82016-08-02 15:43:46 -0700287 if (pFont) {
Tom Sepezc4a2b752017-04-07 13:56:13 -0700288 *csNameTag = csTemp;
dsinclair27053d82016-08-02 15:43:46 -0700289 return pFont;
290 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400291 ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr);
dsinclair27053d82016-08-02 15:43:46 -0700292 if (!csFontName.IsEmpty() &&
293 FindFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) {
294 return pFont;
295 }
296 pFont = CPDF_InterForm::AddNativeFont(charSet, pDocument);
297 if (pFont)
298 AddFont(pFormDict, pDocument, pFont, csNameTag);
299
300 return pFont;
301}
302
Lei Zhangd88a3642015-11-10 09:38:57 -0800303class CFieldNameExtractor {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304 public:
Ryan Harrison275e2602017-09-18 14:23:18 -0400305 explicit CFieldNameExtractor(const WideString& full_name)
tsepez4d31d0c2016-04-19 14:11:59 -0700306 : m_FullName(full_name) {
307 m_pCur = m_FullName.c_str();
308 m_pEnd = m_pCur + m_FullName.GetLength();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700309 }
tsepez4d31d0c2016-04-19 14:11:59 -0700310
Ryan Harrison875e98c2017-09-27 10:53:11 -0400311 void GetNext(const wchar_t*& pSubName, size_t& size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700312 pSubName = m_pCur;
dsinclair27053d82016-08-02 15:43:46 -0700313 while (m_pCur < m_pEnd && m_pCur[0] != L'.')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700314 m_pCur++;
dsinclair27053d82016-08-02 15:43:46 -0700315
Ryan Harrison875e98c2017-09-27 10:53:11 -0400316 size = static_cast<size_t>(m_pCur - pSubName);
dsinclair27053d82016-08-02 15:43:46 -0700317 if (m_pCur < m_pEnd && m_pCur[0] == L'.')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700318 m_pCur++;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319 }
320
321 protected:
Ryan Harrison275e2602017-09-18 14:23:18 -0400322 WideString m_FullName;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400323 const wchar_t* m_pCur;
324 const wchar_t* m_pEnd;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700325};
tsepez4d31d0c2016-04-19 14:11:59 -0700326
Dan Sinclair698aed72017-09-26 16:24:49 -0400327#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
dsinclair27053d82016-08-02 15:43:46 -0700328typedef struct {
tsepez12f3e4a2016-11-02 15:17:29 -0700329 bool bFind;
dsinclair27053d82016-08-02 15:43:46 -0700330 LOGFONTA lf;
331} PDF_FONTDATA;
332
333static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe,
334 NEWTEXTMETRICEX* lpntme,
335 DWORD FontType,
336 LPARAM lParam) {
337 if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@'))
338 return 1;
339
340 PDF_FONTDATA* pData = (PDF_FONTDATA*)lParam;
341 memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA));
tsepez12f3e4a2016-11-02 15:17:29 -0700342 pData->bFind = true;
dsinclair27053d82016-08-02 15:43:46 -0700343 return 0;
344}
345
tsepez12f3e4a2016-11-02 15:17:29 -0700346bool RetrieveSpecificFont(LOGFONTA& lf) {
dsinclair27053d82016-08-02 15:43:46 -0700347 PDF_FONTDATA fd;
348 memset(&fd, 0, sizeof(PDF_FONTDATA));
349 HDC hDC = ::GetDC(nullptr);
350 EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd,
351 0);
352 ::ReleaseDC(nullptr, hDC);
353 if (fd.bFind)
354 memcpy(&lf, &fd.lf, sizeof(LOGFONTA));
355
356 return fd.bFind;
357}
358
tsepez12f3e4a2016-11-02 15:17:29 -0700359bool RetrieveSpecificFont(uint8_t charSet,
360 uint8_t pitchAndFamily,
361 LPCSTR pcsFontName,
362 LOGFONTA& lf) {
dsinclair27053d82016-08-02 15:43:46 -0700363 memset(&lf, 0, sizeof(LOGFONTA));
364 lf.lfCharSet = charSet;
365 lf.lfPitchAndFamily = pitchAndFamily;
366 if (pcsFontName) {
367 // TODO(dsinclair): Should this be strncpy?
Dan Sinclair85c8e7f2016-11-21 13:50:32 -0500368 // NOLINTNEXTLINE(runtime/printf)
dsinclair27053d82016-08-02 15:43:46 -0700369 strcpy(lf.lfFaceName, pcsFontName);
370 }
371 return RetrieveSpecificFont(lf);
372}
Dan Sinclair698aed72017-09-26 16:24:49 -0400373#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
dsinclair27053d82016-08-02 15:43:46 -0700374
375} // namespace
376
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700377class CFieldTree {
378 public:
thestig3b440ac2016-09-28 10:57:16 -0700379 class Node {
380 public:
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700381 Node() : m_pField(nullptr), m_level(0) {}
Ryan Harrison275e2602017-09-18 14:23:18 -0400382 Node(const WideString& short_name, int level)
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700383 : m_ShortName(short_name), m_level(level) {}
thestig3b440ac2016-09-28 10:57:16 -0700384 ~Node() {}
dsinclair27053d82016-08-02 15:43:46 -0700385
Nicolas Pena0b18e152017-04-05 16:34:50 -0400386 void AddChildNode(std::unique_ptr<Node> pNode) {
387 m_Children.push_back(std::move(pNode));
388 }
thestig3b440ac2016-09-28 10:57:16 -0700389
390 size_t GetChildrenCount() const { return m_Children.size(); }
391
Nicolas Pena0b18e152017-04-05 16:34:50 -0400392 Node* GetChildAt(size_t i) { return m_Children[i].get(); }
393 const Node* GetChildAt(size_t i) const { return m_Children[i].get(); }
thestig3b440ac2016-09-28 10:57:16 -0700394
thestig7c292e02016-09-28 14:14:26 -0700395 CPDF_FormField* GetFieldAtIndex(size_t index) {
396 size_t nFieldsToGo = index;
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700397 return GetFieldInternal(&nFieldsToGo);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398 }
dsinclair27053d82016-08-02 15:43:46 -0700399
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700400 size_t CountFields() const { return CountFieldsInternal(); }
dsinclair27053d82016-08-02 15:43:46 -0700401
Nicolas Pena08b96e72017-03-24 14:51:45 -0400402 void SetField(std::unique_ptr<CPDF_FormField> pField) {
403 m_pField = std::move(pField);
404 }
thestig3b440ac2016-09-28 10:57:16 -0700405
Nicolas Pena08b96e72017-03-24 14:51:45 -0400406 CPDF_FormField* GetField() const { return m_pField.get(); }
thestig3b440ac2016-09-28 10:57:16 -0700407
Ryan Harrison275e2602017-09-18 14:23:18 -0400408 const WideString& GetShortName() const { return m_ShortName; }
thestig3b440ac2016-09-28 10:57:16 -0700409
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700410 int GetLevel() const { return m_level; }
Lei Zhang7831f572017-04-28 11:51:08 -0700411
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700412 private:
413 CPDF_FormField* GetFieldInternal(size_t* pFieldsToGo) {
thestig3b440ac2016-09-28 10:57:16 -0700414 if (m_pField) {
415 if (*pFieldsToGo == 0)
Nicolas Pena08b96e72017-03-24 14:51:45 -0400416 return m_pField.get();
thestig3b440ac2016-09-28 10:57:16 -0700417
418 --*pFieldsToGo;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700419 }
thestig3b440ac2016-09-28 10:57:16 -0700420 for (size_t i = 0; i < GetChildrenCount(); ++i) {
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700421 CPDF_FormField* pField = GetChildAt(i)->GetFieldInternal(pFieldsToGo);
thestig3b440ac2016-09-28 10:57:16 -0700422 if (pField)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700423 return pField;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700424 }
thestig4997b222016-06-07 10:46:22 -0700425 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700426 }
dsinclair27053d82016-08-02 15:43:46 -0700427
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700428 size_t CountFieldsInternal() const {
thestig7c292e02016-09-28 14:14:26 -0700429 size_t count = 0;
thestig5ef75ba2016-09-28 16:53:10 -0700430 if (m_pField)
431 ++count;
432
thestig3b440ac2016-09-28 10:57:16 -0700433 for (size_t i = 0; i < GetChildrenCount(); ++i)
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700434 count += GetChildAt(i)->CountFieldsInternal();
thestig3b440ac2016-09-28 10:57:16 -0700435 return count;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436 }
thestig3b440ac2016-09-28 10:57:16 -0700437
Nicolas Pena0b18e152017-04-05 16:34:50 -0400438 std::vector<std::unique_ptr<Node>> m_Children;
Ryan Harrison275e2602017-09-18 14:23:18 -0400439 WideString m_ShortName;
Nicolas Pena08b96e72017-03-24 14:51:45 -0400440 std::unique_ptr<CPDF_FormField> m_pField;
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700441 const int m_level;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700442 };
dsinclair27053d82016-08-02 15:43:46 -0700443
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700444 CFieldTree();
445 ~CFieldTree();
dsinclair27053d82016-08-02 15:43:46 -0700446
Ryan Harrison275e2602017-09-18 14:23:18 -0400447 bool SetField(const WideString& full_name,
Nicolas Pena08b96e72017-03-24 14:51:45 -0400448 std::unique_ptr<CPDF_FormField> pField);
Ryan Harrison275e2602017-09-18 14:23:18 -0400449 CPDF_FormField* GetField(const WideString& full_name);
dsinclair27053d82016-08-02 15:43:46 -0700450
Ryan Harrison275e2602017-09-18 14:23:18 -0400451 Node* FindNode(const WideString& full_name);
452 Node* AddChild(Node* pParent, const WideString& short_name);
dsinclair27053d82016-08-02 15:43:46 -0700453
Ryan Harrison275e2602017-09-18 14:23:18 -0400454 Node* Lookup(Node* pParent, const WideString& short_name);
dsinclair27053d82016-08-02 15:43:46 -0700455
456 Node m_Root;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700457};
dsinclair27053d82016-08-02 15:43:46 -0700458
thestig3b440ac2016-09-28 10:57:16 -0700459CFieldTree::CFieldTree() {}
dsinclair27053d82016-08-02 15:43:46 -0700460
Nicolas Pena0b18e152017-04-05 16:34:50 -0400461CFieldTree::~CFieldTree() {}
dsinclair27053d82016-08-02 15:43:46 -0700462
463CFieldTree::Node* CFieldTree::AddChild(Node* pParent,
Ryan Harrison275e2602017-09-18 14:23:18 -0400464 const WideString& short_name) {
dsinclair27053d82016-08-02 15:43:46 -0700465 if (!pParent)
thestig4997b222016-06-07 10:46:22 -0700466 return nullptr;
dsinclair27053d82016-08-02 15:43:46 -0700467
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700468 int level = pParent->GetLevel() + 1;
469 if (level > nMaxRecursion)
470 return nullptr;
471
472 auto pNew = pdfium::MakeUnique<Node>(short_name, pParent->GetLevel() + 1);
Nicolas Pena0b18e152017-04-05 16:34:50 -0400473 Node* pChild = pNew.get();
474 pParent->AddChildNode(std::move(pNew));
475 return pChild;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700476}
dsinclair27053d82016-08-02 15:43:46 -0700477
478CFieldTree::Node* CFieldTree::Lookup(Node* pParent,
Ryan Harrison275e2602017-09-18 14:23:18 -0400479 const WideString& short_name) {
dsinclair27053d82016-08-02 15:43:46 -0700480 if (!pParent)
thestig4997b222016-06-07 10:46:22 -0700481 return nullptr;
dsinclair27053d82016-08-02 15:43:46 -0700482
thestig3b440ac2016-09-28 10:57:16 -0700483 for (size_t i = 0; i < pParent->GetChildrenCount(); ++i) {
484 Node* pNode = pParent->GetChildAt(i);
485 if (pNode->GetShortName() == short_name)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700486 return pNode;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700487 }
thestig4997b222016-06-07 10:46:22 -0700488 return nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700489}
dsinclair27053d82016-08-02 15:43:46 -0700490
Ryan Harrison275e2602017-09-18 14:23:18 -0400491bool CFieldTree::SetField(const WideString& full_name,
Nicolas Pena08b96e72017-03-24 14:51:45 -0400492 std::unique_ptr<CPDF_FormField> pField) {
thestig3b440ac2016-09-28 10:57:16 -0700493 if (full_name.IsEmpty())
Nicolas Pena08b96e72017-03-24 14:51:45 -0400494 return false;
dsinclair27053d82016-08-02 15:43:46 -0700495
Lei Zhangd88a3642015-11-10 09:38:57 -0800496 CFieldNameExtractor name_extractor(full_name);
Dan Sinclair812e96c2017-03-13 16:43:37 -0400497 const wchar_t* pName;
Ryan Harrison875e98c2017-09-27 10:53:11 -0400498 size_t nLength;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700499 name_extractor.GetNext(pName, nLength);
dsinclair27053d82016-08-02 15:43:46 -0700500 Node* pNode = &m_Root;
501 Node* pLast = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700502 while (nLength > 0) {
503 pLast = pNode;
Ryan Harrison275e2602017-09-18 14:23:18 -0400504 WideString name = WideString(pName, nLength);
dsinclair27053d82016-08-02 15:43:46 -0700505 pNode = Lookup(pLast, name);
506 if (!pNode)
Nicolas Pena08b96e72017-03-24 14:51:45 -0400507 pNode = AddChild(pLast, name);
Lei Zhang9ebdfcb2017-04-28 12:31:39 -0700508 if (!pNode)
509 return false;
dsinclair27053d82016-08-02 15:43:46 -0700510
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700511 name_extractor.GetNext(pName, nLength);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700512 }
Nicolas Pena08b96e72017-03-24 14:51:45 -0400513 if (pNode == &m_Root)
514 return false;
515
516 pNode->SetField(std::move(pField));
517 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700518}
dsinclair27053d82016-08-02 15:43:46 -0700519
Ryan Harrison275e2602017-09-18 14:23:18 -0400520CPDF_FormField* CFieldTree::GetField(const WideString& full_name) {
thestig3b440ac2016-09-28 10:57:16 -0700521 if (full_name.IsEmpty())
thestig4997b222016-06-07 10:46:22 -0700522 return nullptr;
dsinclair27053d82016-08-02 15:43:46 -0700523
Lei Zhangd88a3642015-11-10 09:38:57 -0800524 CFieldNameExtractor name_extractor(full_name);
Dan Sinclair812e96c2017-03-13 16:43:37 -0400525 const wchar_t* pName;
Ryan Harrison875e98c2017-09-27 10:53:11 -0400526 size_t nLength;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700527 name_extractor.GetNext(pName, nLength);
dsinclair27053d82016-08-02 15:43:46 -0700528 Node* pNode = &m_Root;
529 Node* pLast = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700530 while (nLength > 0 && pNode) {
531 pLast = pNode;
Ryan Harrison275e2602017-09-18 14:23:18 -0400532 WideString name = WideString(pName, nLength);
dsinclair27053d82016-08-02 15:43:46 -0700533 pNode = Lookup(pLast, name);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700534 name_extractor.GetNext(pName, nLength);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700535 }
thestig3b440ac2016-09-28 10:57:16 -0700536 return pNode ? pNode->GetField() : nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700537}
dsinclair27053d82016-08-02 15:43:46 -0700538
Ryan Harrison275e2602017-09-18 14:23:18 -0400539CFieldTree::Node* CFieldTree::FindNode(const WideString& full_name) {
thestig3b440ac2016-09-28 10:57:16 -0700540 if (full_name.IsEmpty())
thestig4997b222016-06-07 10:46:22 -0700541 return nullptr;
dsinclair27053d82016-08-02 15:43:46 -0700542
Lei Zhangd88a3642015-11-10 09:38:57 -0800543 CFieldNameExtractor name_extractor(full_name);
Dan Sinclair812e96c2017-03-13 16:43:37 -0400544 const wchar_t* pName;
Ryan Harrison875e98c2017-09-27 10:53:11 -0400545 size_t nLength;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700546 name_extractor.GetNext(pName, nLength);
dsinclair27053d82016-08-02 15:43:46 -0700547 Node* pNode = &m_Root;
548 Node* pLast = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700549 while (nLength > 0 && pNode) {
550 pLast = pNode;
Ryan Harrison275e2602017-09-18 14:23:18 -0400551 WideString name = WideString(pName, nLength);
dsinclair27053d82016-08-02 15:43:46 -0700552 pNode = Lookup(pLast, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700553 name_extractor.GetNext(pName, nLength);
554 }
555 return pNode;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700556}
thestigdb1a24e2016-05-23 16:55:09 -0700557
dsinclair27053d82016-08-02 15:43:46 -0700558CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict,
559 CPDF_Document* pDocument,
Ryan Harrison275e2602017-09-18 14:23:18 -0400560 ByteString* csNameTag) {
dsinclair27053d82016-08-02 15:43:46 -0700561 uint8_t charSet = CPDF_InterForm::GetNativeCharSet();
562 return AddNativeFont(pFormDict, pDocument, charSet, csNameTag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700563}
thestig907a5222016-06-21 14:38:27 -0700564
565// static
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700566uint8_t CPDF_InterForm::GetNativeCharSet() {
Dan Sinclair698aed72017-09-26 16:24:49 -0400567#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400568 uint8_t charSet = FX_CHARSET_ANSI;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700569 UINT iCodePage = ::GetACP();
570 switch (iCodePage) {
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400571 case FX_CODEPAGE_ShiftJIS:
572 charSet = FX_CHARSET_ShiftJIS;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700573 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400574 case FX_CODEPAGE_ChineseSimplified:
575 charSet = FX_CHARSET_ChineseSimplified;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700576 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400577 case FX_CODEPAGE_ChineseTraditional:
578 charSet = FX_CHARSET_ChineseTraditional;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700579 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400580 case FX_CODEPAGE_MSWin_WesternEuropean:
581 charSet = FX_CHARSET_ANSI;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700582 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400583 case FX_CODEPAGE_MSDOS_Thai:
584 charSet = FX_CHARSET_Thai;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700585 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400586 case FX_CODEPAGE_Hangul:
587 charSet = FX_CHARSET_Hangul;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700588 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400589 case FX_CODEPAGE_UTF16LE:
590 charSet = FX_CHARSET_ANSI;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700591 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400592 case FX_CODEPAGE_MSWin_EasternEuropean:
593 charSet = FX_CHARSET_MSWin_EasternEuropean;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700594 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400595 case FX_CODEPAGE_MSWin_Cyrillic:
596 charSet = FX_CHARSET_MSWin_Cyrillic;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700597 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400598 case FX_CODEPAGE_MSWin_Greek:
599 charSet = FX_CHARSET_MSWin_Greek;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700600 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400601 case FX_CODEPAGE_MSWin_Turkish:
602 charSet = FX_CHARSET_MSWin_Turkish;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700603 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400604 case FX_CODEPAGE_MSWin_Hebrew:
605 charSet = FX_CHARSET_MSWin_Hebrew;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700606 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400607 case FX_CODEPAGE_MSWin_Arabic:
608 charSet = FX_CHARSET_MSWin_Arabic;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700609 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400610 case FX_CODEPAGE_MSWin_Baltic:
611 charSet = FX_CHARSET_MSWin_Baltic;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700612 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400613 case FX_CODEPAGE_MSWin_Vietnamese:
614 charSet = FX_CHARSET_MSWin_Vietnamese;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700615 break;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400616 case FX_CODEPAGE_Johab:
617 charSet = FX_CHARSET_Johab;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700618 break;
619 }
620 return charSet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700621#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700622 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700623#endif
624}
Lei Zhang0c0d8bd2015-11-17 17:50:23 -0800625
dsinclair27053d82016-08-02 15:43:46 -0700626CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument)
627 : m_pDocument(pDocument),
628 m_pFormDict(nullptr),
Tom Sepez6e72b2e2017-04-26 15:14:35 -0700629 m_pFieldTree(pdfium::MakeUnique<CFieldTree>()),
dsinclair27053d82016-08-02 15:43:46 -0700630 m_pFormNotify(nullptr) {
631 CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
632 if (!pRoot)
633 return;
634
dsinclair38fd8442016-09-15 10:15:32 -0700635 m_pFormDict = pRoot->GetDictFor("AcroForm");
dsinclair27053d82016-08-02 15:43:46 -0700636 if (!m_pFormDict)
637 return;
638
dsinclair38fd8442016-09-15 10:15:32 -0700639 CPDF_Array* pFields = m_pFormDict->GetArrayFor("Fields");
dsinclair27053d82016-08-02 15:43:46 -0700640 if (!pFields)
641 return;
642
thestig7c292e02016-09-28 14:14:26 -0700643 for (size_t i = 0; i < pFields->GetCount(); ++i)
644 LoadField(pFields->GetDictAt(i), 0);
dsinclair27053d82016-08-02 15:43:46 -0700645}
646
Tom Sepez655c7832017-05-23 17:10:46 -0700647CPDF_InterForm::~CPDF_InterForm() {}
dsinclair27053d82016-08-02 15:43:46 -0700648
thestig7c292e02016-09-28 14:14:26 -0700649bool CPDF_InterForm::s_bUpdateAP = true;
dsinclair27053d82016-08-02 15:43:46 -0700650
thestig7c292e02016-09-28 14:14:26 -0700651bool CPDF_InterForm::IsUpdateAPEnabled() {
dsinclair27053d82016-08-02 15:43:46 -0700652 return s_bUpdateAP;
653}
654
thestig7c292e02016-09-28 14:14:26 -0700655void CPDF_InterForm::SetUpdateAP(bool bUpdateAP) {
dsinclair27053d82016-08-02 15:43:46 -0700656 s_bUpdateAP = bUpdateAP;
657}
658
Ryan Harrison275e2602017-09-18 14:23:18 -0400659ByteString CPDF_InterForm::GenerateNewResourceName(
dsinclair27053d82016-08-02 15:43:46 -0700660 const CPDF_Dictionary* pResDict,
Dan Sinclair812e96c2017-03-13 16:43:37 -0400661 const char* csType,
dsinclair27053d82016-08-02 15:43:46 -0700662 int iMinLen,
Dan Sinclair812e96c2017-03-13 16:43:37 -0400663 const char* csPrefix) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400664 ByteString csStr = csPrefix;
665 ByteString csBType = csType;
dsinclair27053d82016-08-02 15:43:46 -0700666 if (csStr.IsEmpty()) {
667 if (csBType == "ExtGState")
668 csStr = "GS";
669 else if (csBType == "ColorSpace")
670 csStr = "CS";
671 else if (csBType == "Font")
672 csStr = "ZiTi";
673 else
674 csStr = "Res";
675 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400676 ByteString csTmp = csStr;
dsinclair27053d82016-08-02 15:43:46 -0700677 int iCount = csStr.GetLength();
678 int m = 0;
679 if (iMinLen > 0) {
Lei Zhangfe2cd4d2017-11-22 20:04:12 +0000680 csTmp.clear();
dsinclair27053d82016-08-02 15:43:46 -0700681 while (m < iMinLen && m < iCount)
682 csTmp += csStr[m++];
683 while (m < iMinLen) {
684 csTmp += '0' + m % 10;
685 m++;
686 }
687 } else {
688 m = iCount;
689 }
690 if (!pResDict)
691 return csTmp;
692
dsinclair38fd8442016-09-15 10:15:32 -0700693 CPDF_Dictionary* pDict = pResDict->GetDictFor(csType);
dsinclair27053d82016-08-02 15:43:46 -0700694 if (!pDict)
695 return csTmp;
696
697 int num = 0;
Ryan Harrison275e2602017-09-18 14:23:18 -0400698 ByteString bsNum;
tsepez12f3e4a2016-11-02 15:17:29 -0700699 while (true) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400700 ByteString csKey = csTmp + bsNum;
dsinclair27053d82016-08-02 15:43:46 -0700701 if (!pDict->KeyExist(csKey))
702 return csKey;
703 if (m < iCount)
704 csTmp += csStr[m++];
705 else
Dan Sinclair1c4735a2017-11-16 22:08:07 +0000706 bsNum = ByteString::Format("%d", num++);
dsinclair27053d82016-08-02 15:43:46 -0700707
708 m++;
709 }
710 return csTmp;
711}
712
713CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument,
Ryan Harrison275e2602017-09-18 14:23:18 -0400714 ByteString csFontName) {
dsinclair27053d82016-08-02 15:43:46 -0700715 if (!pDocument || csFontName.IsEmpty())
716 return nullptr;
717
718 if (csFontName == "ZapfDingbats")
719 return pDocument->AddStandardFont(csFontName.c_str(), nullptr);
720
721 CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI);
722 return pDocument->AddStandardFont(csFontName.c_str(), &encoding);
723}
724
Ryan Harrison275e2602017-09-18 14:23:18 -0400725ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) {
726 ByteString csFontName;
Dan Sinclair698aed72017-09-26 16:24:49 -0400727#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
dsinclair27053d82016-08-02 15:43:46 -0700728 LOGFONTA lf = {};
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400729 if (charSet == FX_CHARSET_ANSI) {
dsinclair27053d82016-08-02 15:43:46 -0700730 csFontName = "Helvetica";
731 return csFontName;
732 }
tsepez12f3e4a2016-11-02 15:17:29 -0700733 bool bRet = false;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400734 if (charSet == FX_CHARSET_ShiftJIS) {
dsinclair27053d82016-08-02 15:43:46 -0700735 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
736 "MS Mincho", lf);
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400737 } else if (charSet == FX_CHARSET_ChineseSimplified) {
dsinclair27053d82016-08-02 15:43:46 -0700738 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun",
739 lf);
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400740 } else if (charSet == FX_CHARSET_ChineseTraditional) {
dsinclair27053d82016-08-02 15:43:46 -0700741 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU",
742 lf);
743 }
744 if (!bRet) {
745 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
746 "Arial Unicode MS", lf);
747 }
748 if (!bRet) {
749 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
750 "Microsoft Sans Serif", lf);
751 }
752 if (!bRet) {
753 bRet =
754 RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, nullptr, lf);
755 }
756 if (bRet) {
757 if (pLogFont)
758 memcpy(pLogFont, &lf, sizeof(LOGFONTA));
759
760 csFontName = lf.lfFaceName;
761 return csFontName;
762 }
763#endif
764 return csFontName;
765}
766
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700767CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet,
Lei Zhang0c0d8bd2015-11-17 17:50:23 -0800768 CPDF_Document* pDocument) {
769 if (!pDocument)
770 return nullptr;
771
Dan Sinclair698aed72017-09-26 16:24:49 -0400772#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700773 LOGFONTA lf;
Ryan Harrison275e2602017-09-18 14:23:18 -0400774 ByteString csFontName = GetNativeFont(charSet, &lf);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700775 if (!csFontName.IsEmpty()) {
Lei Zhang0c0d8bd2015-11-17 17:50:23 -0800776 if (csFontName == "Helvetica")
777 return AddStandardFont(pDocument, csFontName);
tsepez12f3e4a2016-11-02 15:17:29 -0700778 return pDocument->AddWindowsFont(&lf, false, true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700779 }
780#endif
Lei Zhang0c0d8bd2015-11-17 17:50:23 -0800781 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700782}
Lei Zhang0c0d8bd2015-11-17 17:50:23 -0800783
784CPDF_Font* CPDF_InterForm::AddNativeFont(CPDF_Document* pDocument) {
785 return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700786}
Lei Zhang0c0d8bd2015-11-17 17:50:23 -0800787
Ryan Harrison275e2602017-09-18 14:23:18 -0400788size_t CPDF_InterForm::CountFields(const WideString& csFieldName) const {
dsinclair27053d82016-08-02 15:43:46 -0700789 if (csFieldName.IsEmpty())
thestig7c292e02016-09-28 14:14:26 -0700790 return m_pFieldTree->m_Root.CountFields();
dsinclair27053d82016-08-02 15:43:46 -0700791
792 CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName);
Lei Zhang412e9082015-12-14 18:34:00 -0800793 return pNode ? pNode->CountFields() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700794}
dsinclair27053d82016-08-02 15:43:46 -0700795
Ryan Harrison275e2602017-09-18 14:23:18 -0400796CPDF_FormField* CPDF_InterForm::GetField(uint32_t index,
797 const WideString& csFieldName) const {
thestig3b440ac2016-09-28 10:57:16 -0700798 if (csFieldName.IsEmpty())
799 return m_pFieldTree->m_Root.GetFieldAtIndex(index);
dsinclair27053d82016-08-02 15:43:46 -0700800
801 CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName);
thestig3b440ac2016-09-28 10:57:16 -0700802 return pNode ? pNode->GetFieldAtIndex(index) : nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700803}
Lei Zhangd88a3642015-11-10 09:38:57 -0800804
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700805CPDF_FormField* CPDF_InterForm::GetFieldByDict(
806 CPDF_Dictionary* pFieldDict) const {
dsinclair27053d82016-08-02 15:43:46 -0700807 if (!pFieldDict)
thestig4997b222016-06-07 10:46:22 -0700808 return nullptr;
dsinclair27053d82016-08-02 15:43:46 -0700809
Ryan Harrison275e2602017-09-18 14:23:18 -0400810 WideString csWName = FPDF_GetFullName(pFieldDict);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700811 return m_pFieldTree->GetField(csWName);
812}
Lei Zhangbdf72c32015-08-14 19:24:08 -0700813
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700814CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage,
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500815 const CFX_PointF& point,
816
Lei Zhangbdf72c32015-08-14 19:24:08 -0700817 int* z_order) const {
dsinclair38fd8442016-09-15 10:15:32 -0700818 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayFor("Annots");
Lei Zhangbdf72c32015-08-14 19:24:08 -0700819 if (!pAnnotList)
820 return nullptr;
821
Wei Lie1aebd42016-04-11 10:02:09 -0700822 for (size_t i = pAnnotList->GetCount(); i > 0; --i) {
823 size_t annot_index = i - 1;
Wei Li9b761132016-01-29 15:44:20 -0800824 CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(annot_index);
Lei Zhangbdf72c32015-08-14 19:24:08 -0700825 if (!pAnnot)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700826 continue;
Lei Zhangbdf72c32015-08-14 19:24:08 -0700827
828 const auto it = m_ControlMap.find(pAnnot);
829 if (it == m_ControlMap.end())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700830 continue;
Lei Zhangbdf72c32015-08-14 19:24:08 -0700831
tsepezd18b8672017-01-10 10:19:04 -0800832 CPDF_FormControl* pControl = it->second.get();
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500833 if (!pControl->GetRect().Contains(point))
Lei Zhangbdf72c32015-08-14 19:24:08 -0700834 continue;
835
836 if (z_order)
Wei Lie1aebd42016-04-11 10:02:09 -0700837 *z_order = static_cast<int>(annot_index);
Lei Zhangbdf72c32015-08-14 19:24:08 -0700838 return pControl;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700839 }
Lei Zhangbdf72c32015-08-14 19:24:08 -0700840 return nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700841}
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700842
Lei Zhangbdf72c32015-08-14 19:24:08 -0700843CPDF_FormControl* CPDF_InterForm::GetControlByDict(
Lei Zhang1b700c32015-10-30 23:55:35 -0700844 const CPDF_Dictionary* pWidgetDict) const {
Lei Zhangbdf72c32015-08-14 19:24:08 -0700845 const auto it = m_ControlMap.find(pWidgetDict);
tsepezd18b8672017-01-10 10:19:04 -0800846 return it != m_ControlMap.end() ? it->second.get() : nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700847}
Lei Zhangbdf72c32015-08-14 19:24:08 -0700848
tsepez12f3e4a2016-11-02 15:17:29 -0700849bool CPDF_InterForm::NeedConstructAP() const {
dsinclair38fd8442016-09-15 10:15:32 -0700850 return m_pFormDict && m_pFormDict->GetBooleanFor("NeedAppearances");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700851}
Wei Lie1aebd42016-04-11 10:02:09 -0700852
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700853int CPDF_InterForm::CountFieldsInCalculationOrder() {
thestigdb1a24e2016-05-23 16:55:09 -0700854 if (!m_pFormDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700855 return 0;
thestigdb1a24e2016-05-23 16:55:09 -0700856
dsinclair38fd8442016-09-15 10:15:32 -0700857 CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
Lei Zhang412e9082015-12-14 18:34:00 -0800858 return pArray ? pArray->GetCount() : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700859}
Wei Lie1aebd42016-04-11 10:02:09 -0700860
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700861CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index) {
thestigdb1a24e2016-05-23 16:55:09 -0700862 if (!m_pFormDict || index < 0)
863 return nullptr;
864
dsinclair38fd8442016-09-15 10:15:32 -0700865 CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
thestigdb1a24e2016-05-23 16:55:09 -0700866 if (!pArray)
867 return nullptr;
868
869 CPDF_Dictionary* pElement = ToDictionary(pArray->GetDirectObjectAt(index));
870 return pElement ? GetFieldByDict(pElement) : nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700871}
thestigdb1a24e2016-05-23 16:55:09 -0700872
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700873int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) {
thestigdb1a24e2016-05-23 16:55:09 -0700874 if (!m_pFormDict || !pField)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700875 return -1;
thestigdb1a24e2016-05-23 16:55:09 -0700876
dsinclair38fd8442016-09-15 10:15:32 -0700877 CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO");
thestigdb1a24e2016-05-23 16:55:09 -0700878 if (!pArray)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700879 return -1;
thestigdb1a24e2016-05-23 16:55:09 -0700880
Wei Lie1aebd42016-04-11 10:02:09 -0700881 for (size_t i = 0; i < pArray->GetCount(); i++) {
tsepezbd567552016-03-29 14:51:50 -0700882 CPDF_Object* pElement = pArray->GetDirectObjectAt(i);
Nicolas Pena03f0fb02017-04-19 17:38:54 -0400883 if (pElement == pField->GetDict())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700884 return i;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700885 }
886 return -1;
887}
thestigdb1a24e2016-05-23 16:55:09 -0700888
Ryan Harrison275e2602017-09-18 14:23:18 -0400889CPDF_Font* CPDF_InterForm::GetFormFont(ByteString csNameTag) const {
Tom Sepezd0409af2017-05-25 15:53:57 -0700890 return GetFont(m_pFormDict.Get(), m_pDocument.Get(), csNameTag);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700891}
dsinclair27053d82016-08-02 15:43:46 -0700892
thestig7c292e02016-09-28 14:14:26 -0700893CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() const {
Wei Li0fc6b252016-03-01 16:29:41 -0800894 if (!m_pFormDict)
895 return CPDF_DefaultAppearance();
dsinclair38fd8442016-09-15 10:15:32 -0700896 return CPDF_DefaultAppearance(m_pFormDict->GetStringFor("DA"));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700897}
Wei Li0fc6b252016-03-01 16:29:41 -0800898
thestig7c292e02016-09-28 14:14:26 -0700899int CPDF_InterForm::GetFormAlignment() const {
dsinclair38fd8442016-09-15 10:15:32 -0700900 return m_pFormDict ? m_pFormDict->GetIntegerFor("Q", 0) : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700901}
Lei Zhangd88a3642015-11-10 09:38:57 -0800902
dan sinclair7544a4b2018-03-08 15:19:50 +0000903void CPDF_InterForm::ResetForm(const std::vector<CPDF_FormField*>& fields,
Lei Zhangd88a3642015-11-10 09:38:57 -0800904 bool bIncludeOrExclude,
905 bool bNotify) {
thestig7c292e02016-09-28 14:14:26 -0700906 size_t nCount = m_pFieldTree->m_Root.CountFields();
907 for (size_t i = 0; i < nCount; ++i) {
thestig3b440ac2016-09-28 10:57:16 -0700908 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
Lei Zhangd88a3642015-11-10 09:38:57 -0800909 if (!pField)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700910 continue;
Lei Zhangd88a3642015-11-10 09:38:57 -0800911
Lei Zhangcd2bb302015-12-22 13:49:44 -0800912 if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700913 pField->ResetField(bNotify);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700914 }
Lei Zhangd88a3642015-11-10 09:38:57 -0800915 if (bNotify && m_pFormNotify)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700916 m_pFormNotify->AfterFormReset(this);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700917}
Lei Zhangd88a3642015-11-10 09:38:57 -0800918
dan sinclair7544a4b2018-03-08 15:19:50 +0000919void CPDF_InterForm::ResetForm(bool bNotify) {
thestig7c292e02016-09-28 14:14:26 -0700920 size_t nCount = m_pFieldTree->m_Root.CountFields();
921 for (size_t i = 0; i < nCount; ++i) {
thestig3b440ac2016-09-28 10:57:16 -0700922 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
Lei Zhangd88a3642015-11-10 09:38:57 -0800923 if (!pField)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700924 continue;
Lei Zhangd88a3642015-11-10 09:38:57 -0800925
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700926 pField->ResetField(bNotify);
927 }
Lei Zhangd88a3642015-11-10 09:38:57 -0800928 if (bNotify && m_pFormNotify)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700929 m_pFormNotify->AfterFormReset(this);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700930}
Lei Zhangd88a3642015-11-10 09:38:57 -0800931
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700932void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) {
dsinclair27053d82016-08-02 15:43:46 -0700933 if (nLevel > nMaxRecursion)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700934 return;
dsinclair27053d82016-08-02 15:43:46 -0700935 if (!pFieldDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700936 return;
dsinclair27053d82016-08-02 15:43:46 -0700937
tsepezb5e8f142016-03-25 15:18:35 -0700938 uint32_t dwParentObjNum = pFieldDict->GetObjNum();
dsinclair38fd8442016-09-15 10:15:32 -0700939 CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700940 if (!pKids) {
941 AddTerminalField(pFieldDict);
942 return;
943 }
dsinclair27053d82016-08-02 15:43:46 -0700944
Wei Li9b761132016-01-29 15:44:20 -0800945 CPDF_Dictionary* pFirstKid = pKids->GetDictAt(0);
dsinclair27053d82016-08-02 15:43:46 -0700946 if (!pFirstKid)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700947 return;
dsinclair27053d82016-08-02 15:43:46 -0700948
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700949 if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) {
Wei Lie1aebd42016-04-11 10:02:09 -0700950 for (size_t i = 0; i < pKids->GetCount(); i++) {
Wei Li9b761132016-01-29 15:44:20 -0800951 CPDF_Dictionary* pChildDict = pKids->GetDictAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700952 if (pChildDict) {
dsinclair27053d82016-08-02 15:43:46 -0700953 if (pChildDict->GetObjNum() != dwParentObjNum)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700954 LoadField(pChildDict, nLevel + 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700955 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700956 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700957 } else {
958 AddTerminalField(pFieldDict);
959 }
960}
dsinclair27053d82016-08-02 15:43:46 -0700961
tsepez12f3e4a2016-11-02 15:17:29 -0700962bool CPDF_InterForm::HasXFAForm() const {
dsinclair38fd8442016-09-15 10:15:32 -0700963 return m_pFormDict && m_pFormDict->GetArrayFor("XFA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700964}
dsinclair27053d82016-08-02 15:43:46 -0700965
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700966void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) {
Tom Sepez4cb82ee2017-05-22 15:15:30 -0700967 CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get();
dsinclair27053d82016-08-02 15:43:46 -0700968 if (!pPageDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700969 return;
dsinclair27053d82016-08-02 15:43:46 -0700970
dsinclair38fd8442016-09-15 10:15:32 -0700971 CPDF_Array* pAnnots = pPageDict->GetArrayFor("Annots");
dsinclair27053d82016-08-02 15:43:46 -0700972 if (!pAnnots)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700973 return;
dsinclair27053d82016-08-02 15:43:46 -0700974
Wei Lie1aebd42016-04-11 10:02:09 -0700975 for (size_t i = 0; i < pAnnots->GetCount(); i++) {
Wei Li9b761132016-01-29 15:44:20 -0800976 CPDF_Dictionary* pAnnot = pAnnots->GetDictAt(i);
dsinclair38fd8442016-09-15 10:15:32 -0700977 if (pAnnot && pAnnot->GetStringFor("Subtype") == "Widget")
thestig7c292e02016-09-28 14:14:26 -0700978 LoadField(pAnnot, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700979 }
980}
dsinclair27053d82016-08-02 15:43:46 -0700981
Nicolas Pena08b96e72017-03-24 14:51:45 -0400982void CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) {
weiliab5a20d2016-12-07 11:32:52 -0800983 if (!pFieldDict->KeyExist("FT")) {
984 // Key "FT" is required for terminal fields, it is also inheritable.
985 CPDF_Dictionary* pParentDict = pFieldDict->GetDictFor("Parent");
986 if (!pParentDict || !pParentDict->KeyExist("FT"))
Nicolas Pena08b96e72017-03-24 14:51:45 -0400987 return;
weiliab5a20d2016-12-07 11:32:52 -0800988 }
dsinclair27053d82016-08-02 15:43:46 -0700989
Dan Sinclairf1251c12015-10-20 16:24:45 -0400990 CPDF_Dictionary* pDict = pFieldDict;
Ryan Harrison275e2602017-09-18 14:23:18 -0400991 WideString csWName = FPDF_GetFullName(pFieldDict);
dsinclair27053d82016-08-02 15:43:46 -0700992 if (csWName.IsEmpty())
Nicolas Pena08b96e72017-03-24 14:51:45 -0400993 return;
dsinclair27053d82016-08-02 15:43:46 -0700994
thestig4997b222016-06-07 10:46:22 -0700995 CPDF_FormField* pField = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700996 pField = m_pFieldTree->GetField(csWName);
Lei Zhang412e9082015-12-14 18:34:00 -0800997 if (!pField) {
Dan Sinclairf1251c12015-10-20 16:24:45 -0400998 CPDF_Dictionary* pParent = pFieldDict;
Lei Zhangd983b092015-12-14 16:58:33 -0800999 if (!pFieldDict->KeyExist("T") &&
dsinclair38fd8442016-09-15 10:15:32 -07001000 pFieldDict->GetStringFor("Subtype") == "Widget") {
1001 pParent = pFieldDict->GetDictFor("Parent");
dsinclair27053d82016-08-02 15:43:46 -07001002 if (!pParent)
Dan Sinclairf1251c12015-10-20 16:24:45 -04001003 pParent = pFieldDict;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001004 }
dsinclair27053d82016-08-02 15:43:46 -07001005
Lei Zhangd983b092015-12-14 16:58:33 -08001006 if (pParent && pParent != pFieldDict && !pParent->KeyExist("FT")) {
1007 if (pFieldDict->KeyExist("FT")) {
dsinclair38fd8442016-09-15 10:15:32 -07001008 CPDF_Object* pFTValue = pFieldDict->GetDirectObjectFor("FT");
dsinclair27053d82016-08-02 15:43:46 -07001009 if (pFTValue)
tsepez0e606b52016-11-18 16:22:41 -08001010 pParent->SetFor("FT", pFTValue->Clone());
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001011 }
dsinclair27053d82016-08-02 15:43:46 -07001012
Lei Zhangd983b092015-12-14 16:58:33 -08001013 if (pFieldDict->KeyExist("Ff")) {
dsinclair38fd8442016-09-15 10:15:32 -07001014 CPDF_Object* pFfValue = pFieldDict->GetDirectObjectFor("Ff");
dsinclair27053d82016-08-02 15:43:46 -07001015 if (pFfValue)
tsepez0e606b52016-11-18 16:22:41 -08001016 pParent->SetFor("Ff", pFfValue->Clone());
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001017 }
1018 }
dsinclair27053d82016-08-02 15:43:46 -07001019
Nicolas Pena08b96e72017-03-24 14:51:45 -04001020 auto newField = pdfium::MakeUnique<CPDF_FormField>(this, pParent);
1021 pField = newField.get();
dsinclair38fd8442016-09-15 10:15:32 -07001022 CPDF_Object* pTObj = pDict->GetObjectFor("T");
Dan Sinclairbf81c142015-10-26 16:54:39 -04001023 if (ToReference(pTObj)) {
tsepez335cf092016-11-09 13:28:26 -08001024 std::unique_ptr<CPDF_Object> pClone = pTObj->CloneDirectObject();
Dan Sinclairbf81c142015-10-26 16:54:39 -04001025 if (pClone)
tsepez0e606b52016-11-18 16:22:41 -08001026 pDict->SetFor("T", std::move(pClone));
Dan Sinclairbf81c142015-10-26 16:54:39 -04001027 else
tsepez0e606b52016-11-18 16:22:41 -08001028 pDict->SetNewFor<CPDF_Name>("T", "");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001029 }
Nicolas Pena08b96e72017-03-24 14:51:45 -04001030 if (!m_pFieldTree->SetField(csWName, std::move(newField)))
1031 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001032 }
dsinclair27053d82016-08-02 15:43:46 -07001033
dsinclair38fd8442016-09-15 10:15:32 -07001034 CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids");
thestig3b440ac2016-09-28 10:57:16 -07001035 if (pKids) {
Wei Lie1aebd42016-04-11 10:02:09 -07001036 for (size_t i = 0; i < pKids->GetCount(); i++) {
Wei Li9b761132016-01-29 15:44:20 -08001037 CPDF_Dictionary* pKid = pKids->GetDictAt(i);
dsinclair27053d82016-08-02 15:43:46 -07001038 if (!pKid)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001039 continue;
dsinclair38fd8442016-09-15 10:15:32 -07001040 if (pKid->GetStringFor("Subtype") != "Widget")
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001041 continue;
dsinclair27053d82016-08-02 15:43:46 -07001042
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001043 AddControl(pField, pKid);
1044 }
thestig3b440ac2016-09-28 10:57:16 -07001045 } else {
1046 if (pFieldDict->GetStringFor("Subtype") == "Widget")
1047 AddControl(pField, pFieldDict);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001048 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001049}
dsinclair27053d82016-08-02 15:43:46 -07001050
tsepez6aac8a82016-06-08 14:17:24 -07001051CPDF_FormControl* CPDF_InterForm::AddControl(CPDF_FormField* pField,
Dan Sinclairf1251c12015-10-20 16:24:45 -04001052 CPDF_Dictionary* pWidgetDict) {
Lei Zhangbdf72c32015-08-14 19:24:08 -07001053 const auto it = m_ControlMap.find(pWidgetDict);
1054 if (it != m_ControlMap.end())
tsepezd18b8672017-01-10 10:19:04 -08001055 return it->second.get();
Lei Zhangbdf72c32015-08-14 19:24:08 -07001056
tsepezd18b8672017-01-10 10:19:04 -08001057 auto pNew = pdfium::MakeUnique<CPDF_FormControl>(pField, pWidgetDict);
1058 CPDF_FormControl* pControl = pNew.get();
1059 m_ControlMap[pWidgetDict] = std::move(pNew);
Nicolas Pena03f0fb02017-04-19 17:38:54 -04001060 pField->AddFormControl(pControl);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001061 return pControl;
1062}
Lei Zhangd88a3642015-11-10 09:38:57 -08001063
Nicolas Penaa478dc52017-01-23 15:48:51 -05001064bool CPDF_InterForm::CheckRequiredFields(
Lei Zhangd88a3642015-11-10 09:38:57 -08001065 const std::vector<CPDF_FormField*>* fields,
1066 bool bIncludeOrExclude) const {
thestig7c292e02016-09-28 14:14:26 -07001067 size_t nCount = m_pFieldTree->m_Root.CountFields();
1068 for (size_t i = 0; i < nCount; ++i) {
thestig3b440ac2016-09-28 10:57:16 -07001069 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
Lei Zhangd88a3642015-11-10 09:38:57 -08001070 if (!pField)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001071 continue;
Lei Zhangd88a3642015-11-10 09:38:57 -08001072
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001073 int32_t iType = pField->GetType();
1074 if (iType == CPDF_FormField::PushButton ||
1075 iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) {
1076 continue;
1077 }
tsepezb5e8f142016-03-25 15:18:35 -07001078 uint32_t dwFlags = pField->GetFieldFlags();
Lei Zhangd88a3642015-11-10 09:38:57 -08001079 // TODO(thestig): Look up these magic numbers and add constants for them.
Nicolas Penaa478dc52017-01-23 15:48:51 -05001080 if (dwFlags & FORMFLAG_NOEXPORT)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001081 continue;
Lei Zhangd88a3642015-11-10 09:38:57 -08001082
1083 bool bFind = true;
Lei Zhangcd2bb302015-12-22 13:49:44 -08001084 if (fields)
1085 bFind = pdfium::ContainsValue(*fields, pField);
Lei Zhangd88a3642015-11-10 09:38:57 -08001086 if (bIncludeOrExclude == bFind) {
Nicolas Pena03f0fb02017-04-19 17:38:54 -04001087 const CPDF_Dictionary* pFieldDict = pField->GetDict();
Nicolas Penaa478dc52017-01-23 15:48:51 -05001088 if ((dwFlags & FORMFLAG_REQUIRED) != 0 &&
1089 pFieldDict->GetStringFor("V").IsEmpty()) {
1090 return false;
1091 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001092 }
1093 }
Nicolas Penaa478dc52017-01-23 15:48:51 -05001094 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001095}
Lei Zhangd88a3642015-11-10 09:38:57 -08001096
tsepez05e01692016-11-28 17:30:09 -08001097std::unique_ptr<CFDF_Document> CPDF_InterForm::ExportToFDF(
Ryan Harrison275e2602017-09-18 14:23:18 -04001098 const WideString& pdf_path,
tsepez05e01692016-11-28 17:30:09 -08001099 bool bSimpleFileSpec) const {
Lei Zhangd88a3642015-11-10 09:38:57 -08001100 std::vector<CPDF_FormField*> fields;
thestig7c292e02016-09-28 14:14:26 -07001101 size_t nCount = m_pFieldTree->m_Root.CountFields();
1102 for (size_t i = 0; i < nCount; ++i)
thestig3b440ac2016-09-28 10:57:16 -07001103 fields.push_back(m_pFieldTree->m_Root.GetFieldAtIndex(i));
Lei Zhangd88a3642015-11-10 09:38:57 -08001104 return ExportToFDF(pdf_path, fields, true, bSimpleFileSpec);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001105}
Lei Zhangd88a3642015-11-10 09:38:57 -08001106
tsepez05e01692016-11-28 17:30:09 -08001107std::unique_ptr<CFDF_Document> CPDF_InterForm::ExportToFDF(
Ryan Harrison275e2602017-09-18 14:23:18 -04001108 const WideString& pdf_path,
Lei Zhangd88a3642015-11-10 09:38:57 -08001109 const std::vector<CPDF_FormField*>& fields,
1110 bool bIncludeOrExclude,
1111 bool bSimpleFileSpec) const {
tsepez05e01692016-11-28 17:30:09 -08001112 std::unique_ptr<CFDF_Document> pDoc = CFDF_Document::CreateNewDoc();
dsinclair27053d82016-08-02 15:43:46 -07001113 if (!pDoc)
thestig4997b222016-06-07 10:46:22 -07001114 return nullptr;
dsinclair27053d82016-08-02 15:43:46 -07001115
dsinclair38fd8442016-09-15 10:15:32 -07001116 CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDictFor("FDF");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001117 if (!pdf_path.IsEmpty()) {
1118 if (bSimpleFileSpec) {
Ryan Harrison275e2602017-09-18 14:23:18 -04001119 WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path);
tsepez0e606b52016-11-18 16:22:41 -08001120 pMainDict->SetNewFor<CPDF_String>(
Lei Zhang26170562018-04-17 17:01:52 +00001121 pdfium::stream::kF, ByteString::FromUnicode(wsFilePath), false);
tsepez0e606b52016-11-18 16:22:41 -08001122 pMainDict->SetNewFor<CPDF_String>("UF", PDF_EncodeText(wsFilePath),
1123 false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001124 } else {
Tom Sepez6e72b2e2017-04-26 15:14:35 -07001125 auto pNewDict =
1126 pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool());
1127 pNewDict->SetNewFor<CPDF_Name>("Type", "Filespec");
1128 CPDF_FileSpec filespec(pNewDict.get());
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001129 filespec.SetFileName(pdf_path);
Tom Sepez6e72b2e2017-04-26 15:14:35 -07001130 pMainDict->SetFor("F", std::move(pNewDict));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001131 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001132 }
dsinclair27053d82016-08-02 15:43:46 -07001133
tsepez0e606b52016-11-18 16:22:41 -08001134 CPDF_Array* pFields = pMainDict->SetNewFor<CPDF_Array>("Fields");
thestig7c292e02016-09-28 14:14:26 -07001135 size_t nCount = m_pFieldTree->m_Root.CountFields();
1136 for (size_t i = 0; i < nCount; ++i) {
thestig3b440ac2016-09-28 10:57:16 -07001137 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i);
dsinclair27053d82016-08-02 15:43:46 -07001138 if (!pField || pField->GetType() == CPDF_FormField::PushButton)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001139 continue;
dsinclair27053d82016-08-02 15:43:46 -07001140
tsepezb5e8f142016-03-25 15:18:35 -07001141 uint32_t dwFlags = pField->GetFieldFlags();
Lei Zhangd88a3642015-11-10 09:38:57 -08001142 if (dwFlags & 0x04)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001143 continue;
Lei Zhangd88a3642015-11-10 09:38:57 -08001144
Lei Zhangcd2bb302015-12-22 13:49:44 -08001145 if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) {
Nicolas Pena03f0fb02017-04-19 17:38:54 -04001146 if ((dwFlags & 0x02) != 0 &&
1147 pField->GetDict()->GetStringFor("V").IsEmpty()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001148 continue;
Nicolas Pena03f0fb02017-04-19 17:38:54 -04001149 }
Lei Zhangd88a3642015-11-10 09:38:57 -08001150
Ryan Harrison275e2602017-09-18 14:23:18 -04001151 WideString fullname = FPDF_GetFullName(pField->GetFieldDict());
tsepez8a3aa452016-11-16 12:26:06 -08001152 auto pFieldDict =
1153 pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool());
tsepez0e606b52016-11-18 16:22:41 -08001154 pFieldDict->SetNewFor<CPDF_String>("T", fullname);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001155 if (pField->GetType() == CPDF_FormField::CheckBox ||
1156 pField->GetType() == CPDF_FormField::RadioButton) {
Ryan Harrison275e2602017-09-18 14:23:18 -04001157 WideString csExport = pField->GetCheckValue(false);
1158 ByteString csBExport = PDF_EncodeText(csExport);
Nicolas Pena03f0fb02017-04-19 17:38:54 -04001159 CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->GetDict(), "Opt");
Lei Zhangd88a3642015-11-10 09:38:57 -08001160 if (pOpt)
tsepez0e606b52016-11-18 16:22:41 -08001161 pFieldDict->SetNewFor<CPDF_String>("V", csBExport, false);
Lei Zhangd88a3642015-11-10 09:38:57 -08001162 else
tsepez0e606b52016-11-18 16:22:41 -08001163 pFieldDict->SetNewFor<CPDF_Name>("V", csBExport);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001164 } else {
Nicolas Pena03f0fb02017-04-19 17:38:54 -04001165 CPDF_Object* pV = FPDF_GetFieldAttr(pField->GetDict(), "V");
Lei Zhangd88a3642015-11-10 09:38:57 -08001166 if (pV)
tsepez0e606b52016-11-18 16:22:41 -08001167 pFieldDict->SetFor("V", pV->CloneDirectObject());
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001168 }
tsepez8a3aa452016-11-16 12:26:06 -08001169 pFields->Add(std::move(pFieldDict));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001170 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001171 }
1172 return pDoc;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001173}
Lei Zhang31c7b732016-02-19 10:53:24 -08001174
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001175void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict,
Ryan Harrison275e2602017-09-18 14:23:18 -04001176 const WideString& parent_name,
tsepez12f3e4a2016-11-02 15:17:29 -07001177 bool bNotify,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001178 int nLevel) {
Ryan Harrison275e2602017-09-18 14:23:18 -04001179 WideString name;
dsinclair27053d82016-08-02 15:43:46 -07001180 if (!parent_name.IsEmpty())
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001181 name = parent_name + L".";
dsinclair27053d82016-08-02 15:43:46 -07001182
dsinclair38fd8442016-09-15 10:15:32 -07001183 name += pFieldDict->GetUnicodeTextFor("T");
1184 CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001185 if (pKids) {
Wei Lie1aebd42016-04-11 10:02:09 -07001186 for (size_t i = 0; i < pKids->GetCount(); i++) {
Wei Li9b761132016-01-29 15:44:20 -08001187 CPDF_Dictionary* pKid = pKids->GetDictAt(i);
dsinclair27053d82016-08-02 15:43:46 -07001188 if (!pKid)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001189 continue;
dsinclair27053d82016-08-02 15:43:46 -07001190 if (nLevel <= nMaxRecursion)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001191 FDF_ImportField(pKid, name, bNotify, nLevel + 1);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001192 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001193 return;
1194 }
dsinclair27053d82016-08-02 15:43:46 -07001195 if (!pFieldDict->KeyExist("V"))
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001196 return;
dsinclair27053d82016-08-02 15:43:46 -07001197
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001198 CPDF_FormField* pField = m_pFieldTree->GetField(name);
dsinclair27053d82016-08-02 15:43:46 -07001199 if (!pField)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001200 return;
dsinclair27053d82016-08-02 15:43:46 -07001201
Ryan Harrison275e2602017-09-18 14:23:18 -04001202 WideString csWValue = GetFieldValue(*pFieldDict, m_bsEncoding);
Ryan Harrison9baf31f2018-01-12 18:36:30 +00001203 FormFieldType fieldType = pField->GetFieldType();
Lei Zhang96660d62015-12-14 18:27:25 -08001204 if (bNotify && m_pFormNotify) {
Ryan Harrison9baf31f2018-01-12 18:36:30 +00001205 if (fieldType == FormFieldType::kListBox) {
dan sinclair507fb4e2018-03-08 15:14:09 +00001206 if (!m_pFormNotify->BeforeSelectionChange(pField, csWValue))
tsepez0e606b52016-11-18 16:22:41 -08001207 return;
Ryan Harrison9baf31f2018-01-12 18:36:30 +00001208 } else if (fieldType == FormFieldType::kComboBox ||
1209 fieldType == FormFieldType::kTextField) {
dan sinclair507fb4e2018-03-08 15:14:09 +00001210 if (!m_pFormNotify->BeforeValueChange(pField, csWValue))
tsepez0e606b52016-11-18 16:22:41 -08001211 return;
1212 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001213 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001214 pField->SetValue(csWValue);
1215 CPDF_FormField::Type eType = pField->GetType();
1216 if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) &&
1217 pFieldDict->KeyExist("Opt")) {
Nicolas Pena03f0fb02017-04-19 17:38:54 -04001218 pField->SetOpt(pFieldDict->GetDirectObjectFor("Opt")->CloneDirectObject());
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001219 }
dsinclair27053d82016-08-02 15:43:46 -07001220
Lei Zhang96660d62015-12-14 18:27:25 -08001221 if (bNotify && m_pFormNotify) {
Ryan Harrison9baf31f2018-01-12 18:36:30 +00001222 if (fieldType == FormFieldType::kCheckBox ||
1223 fieldType == FormFieldType::kRadioButton) {
Tom Sepezed5d7aa2016-02-02 16:02:03 -08001224 m_pFormNotify->AfterCheckedStatusChange(pField);
Ryan Harrison9baf31f2018-01-12 18:36:30 +00001225 } else if (fieldType == FormFieldType::kListBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001226 m_pFormNotify->AfterSelectionChange(pField);
Ryan Harrison9baf31f2018-01-12 18:36:30 +00001227 } else if (fieldType == FormFieldType::kComboBox ||
1228 fieldType == FormFieldType::kTextField) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001229 m_pFormNotify->AfterValueChange(pField);
Ryan Harrison9baf31f2018-01-12 18:36:30 +00001230 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001231 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001232}
thestigdb1a24e2016-05-23 16:55:09 -07001233
thestigdb1a24e2016-05-23 16:55:09 -07001234void CPDF_InterForm::SetFormNotify(IPDF_FormNotify* pNotify) {
1235 m_pFormNotify = pNotify;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001236}