7#include "core/fpdfdoc/cpdf_interactiveform.h"
12#include "build/build_config.h"
13#include "constants/form_fields.h"
14#include "constants/form_flags.h"
15#include "constants/stream_dict_common.h"
16#include "core/fpdfapi/font/cpdf_font.h"
17#include "core/fpdfapi/font/cpdf_fontencoding.h"
18#include "core/fpdfapi/page/cpdf_docpagedata.h"
19#include "core/fpdfapi/page/cpdf_page.h"
20#include "core/fpdfapi/parser/cfdf_document.h"
21#include "core/fpdfapi/parser/cpdf_array.h"
22#include "core/fpdfapi/parser/cpdf_dictionary.h"
23#include "core/fpdfapi/parser/cpdf_document.h"
24#include "core/fpdfapi/parser/cpdf_name.h"
25#include "core/fpdfapi/parser/cpdf_reference.h"
26#include "core/fpdfapi/parser/cpdf_stream.h"
27#include "core/fpdfapi/parser/cpdf_string.h"
28#include "core/fpdfapi/parser/fpdf_parser_utility.h"
29#include "core/fpdfdoc/cpdf_filespec.h"
30#include "core/fpdfdoc/cpdf_formcontrol.h"
31#include "core/fxcrt/fx_codepage.h"
32#include "core/fxcrt/stl_util.h"
33#include "core/fxge/fx_font.h"
34#include "third_party/abseil-cpp/absl/types/optional.h"
35#include "third_party/base/check.h"
36#include "third_party/base/containers/contains.h"
37#include "third_party/base/numerics/safe_conversions.h"
41const int nMaxRecursion = 32;
49int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe,
50 NEWTEXTMETRICEX* lpntme,
53 if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName,
'@'))
56 PDF_FONTDATA* pData = (PDF_FONTDATA*)lParam;
57 memcpy(&pData->lf, &lpelfe->elfLogFont,
sizeof(LOGFONTA));
62bool RetrieveSpecificFont(FX_Charset charSet,
65 memset(&lf, 0,
sizeof(LOGFONTA));
66 lf.lfCharSet =
static_cast<
int>(charSet);
67 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
71 strcpy(lf.lfFaceName, pcsFontName);
75 memset(&fd, 0,
sizeof(PDF_FONTDATA));
76 HDC hDC = ::GetDC(
nullptr);
77 EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd,
79 ::ReleaseDC(
nullptr, hDC);
81 memcpy(&lf, &fd.lf,
sizeof(LOGFONTA));
87ByteString GetNativeFontName(
FX_Charset charSet,
void* pLogFont) {
88 ByteString csFontName;
91 if (charSet == FX_Charset::kANSI) {
92 csFontName = CFX_Font::kDefaultAnsiFontName;
96 const ByteString default_font_name =
97 CFX_Font::GetDefaultFontNameByCharset(charSet);
98 if (!default_font_name.IsEmpty())
99 bRet = RetrieveSpecificFont(charSet, default_font_name.c_str(), lf);
102 RetrieveSpecificFont(charSet, CFX_Font::kUniversalDefaultFontName, lf);
105 bRet = RetrieveSpecificFont(charSet,
"Microsoft Sans Serif", lf);
107 bRet = RetrieveSpecificFont(charSet,
nullptr, lf);
110 memcpy(pLogFont, &lf,
sizeof(LOGFONTA));
111 csFontName = lf.lfFaceName;
117ByteString GenerateNewFontResourceName(
const CPDF_Dictionary* pResDict,
118 const ByteString& csPrefix) {
119 static const char kDummyFontName[] =
"ZiTi";
120 ByteString csStr = csPrefix;
122 csStr
= kDummyFontName;
124 const size_t szCount = csStr.GetLength();
127 while (m < strlen(kDummyFontName) && m < szCount)
129 while (m < strlen(kDummyFontName)) {
130 csTmp +=
'0' + m % 10;
134 RetainPtr<
const CPDF_Dictionary> pDict = pResDict->GetDictFor(
"Font");
140 ByteString csKey = csTmp
+ bsNum;
141 if (!pDict->KeyExist(csKey))
164 ByteString csFontName = GetNativeFontName(charSet, &lf);
165 if (!csFontName.IsEmpty()) {
166 if (csFontName == CFX_Font::kDefaultAnsiFontName)
167 return AddStandardFont(pDocument);
168 return CPDF_DocPageData::FromDocument(pDocument)->AddWindowsFont(&lf);
174bool FindFont(
const CPDF_Dictionary* pFormDict,
176 ByteString* csNameTag) {
177 RetainPtr<
const CPDF_Dictionary> pDR = pFormDict->GetDictFor(
"DR");
181 RetainPtr<
const CPDF_Dictionary> pFonts = pDR->GetDictFor(
"Font");
183 if (!ValidateFontResourceDict(pFonts.Get()))
187 for (
const auto& it : locker) {
188 const ByteString& csKey = it.first;
189 RetainPtr<
const CPDF_Dictionary> pElement =
190 ToDictionary(it.second->GetDirect());
191 if (!ValidateDictType(pElement.Get(),
"Font"))
193 if (pFont->FontDictIs(pElement)) {
201bool FindFontFromDoc(
const CPDF_Dictionary* pFormDict,
203 ByteString csFontName,
205 ByteString* csNameTag) {
209 RetainPtr<
const CPDF_Dictionary> pDR = pFormDict->GetDictFor(
"DR");
213 RetainPtr<
const CPDF_Dictionary> pFonts = pDR->GetDictFor(
"Font");
214 if (!ValidateFontResourceDict(pFonts.Get()))
217 csFontName.Remove(
' ');
219 for (
const auto& it : locker) {
220 const ByteString& csKey = it.first;
221 RetainPtr<CPDF_Dictionary> pElement =
222 ToDictionary(it.second->GetMutableDirect());
223 if (!ValidateDictType(pElement.Get(),
"Font"))
226 auto* pData = CPDF_DocPageData::FromDocument(pDocument);
227 pFont = pData->GetFont(std::move(pElement));
231 ByteString csBaseFont = pFont->GetBaseFontName();
232 csBaseFont.Remove(
' ');
233 if (csBaseFont == csFontName) {
241void AddFont(CPDF_Dictionary* pFormDict,
244 ByteString* csNameTag) {
249 if (FindFont(pFormDict, pFont.Get(), &csTag)) {
250 *csNameTag =
std::move(csTag);
254 RetainPtr<CPDF_Dictionary> pDR = pFormDict->GetOrCreateDictFor(
"DR");
255 RetainPtr<CPDF_Dictionary> pFonts = pDR->GetOrCreateDictFor(
"Font");
257 if (csNameTag->IsEmpty())
258 *csNameTag = pFont->GetBaseFontName();
260 csNameTag->Remove(
' ');
261 *csNameTag = GenerateNewFontResourceName(pDR.Get(), *csNameTag);
262 pFonts->SetNewFor<CPDF_Reference>(*csNameTag, pDocument,
263 pFont->GetFontDictObjNum());
271 auto pFormDict = pDocument->NewIndirect<CPDF_Dictionary>();
272 pDocument->GetMutableRoot()->SetNewFor<CPDF_Reference>(
273 "AcroForm", pDocument, pFormDict->GetObjNum());
275 ByteString csBaseName;
279 AddFont(pFormDict.Get(), pDocument, pFont, &csBaseName);
282 ByteString csFontName = GetNativeFontName(charSet,
nullptr);
284 pFont = AddNativeFont(charSet, pDocument);
287 AddFont(pFormDict.Get(), pDocument, pFont, &csBaseName);
295 pFormDict->SetNewFor<CPDF_String>(
"DA", csDA,
false);
302 ByteString* csNameTag) {
303 RetainPtr<
const CPDF_Dictionary> pDR = pFormDict->GetDictFor(
"DR");
307 RetainPtr<
const CPDF_Dictionary> pFonts = pDR->GetDictFor(
"Font");
308 if (!ValidateFontResourceDict(pFonts.Get()))
312 for (
const auto& it : locker) {
313 const ByteString& csKey = it.first;
314 RetainPtr<CPDF_Dictionary> pElement =
315 ToDictionary(it.second->GetMutableDirect());
316 if (!ValidateDictType(pElement.Get(),
"Font"))
319 auto* pData = CPDF_DocPageData::FromDocument(pDocument);
320 RetainPtr<CPDF_Font> pFind = pData->GetFont(std::move(pElement));
324 auto maybe_charset = pFind->GetSubstFontCharset();
325 if (maybe_charset.has_value() && maybe_charset.value() == charSet) {
333class CFieldNameExtractor {
335 explicit CFieldNameExtractor(
const WideString& full_name)
336 : m_FullName(full_name) {}
338 WideStringView GetNext() {
339 size_t start_pos = m_iCur;
340 while (m_iCur < m_FullName.GetLength() && m_FullName[m_iCur] != L'.')
343 size_t length = m_iCur - start_pos;
344 if (m_iCur < m_FullName.GetLength() && m_FullName[m_iCur] == L'.')
347 return m_FullName.AsStringView().Substr(start_pos, length);
351 const WideString m_FullName;
362 Node(
const WideString& short_name,
int level)
367 m_Children.push_back(std::move(pNode));
376 size_t nFieldsToGo = index;
377 return GetFieldInternal(&nFieldsToGo);
382 void SetField(std::unique_ptr<CPDF_FormField> pField) {
383 m_pField = std::move(pField);
393 if (*pFieldsToGo == 0)
394 return m_pField.get();
398 for (size_t i = 0; i < GetChildrenCount(); ++i) {
399 CPDF_FormField* pField = GetChildAt(i)->GetFieldInternal(pFieldsToGo);
406 size_t CountFieldsInternal()
const {
411 for (size_t i = 0; i < GetChildrenCount(); ++i)
412 count += GetChildAt(i)->CountFieldsInternal();
416 std::vector<std::unique_ptr<Node>> m_Children;
417 WideString m_ShortName;
418 std::unique_ptr<CPDF_FormField> m_pField;
426 std::unique_ptr<CPDF_FormField> pField);
435 std::unique_ptr<Node> m_pRoot;
443 const WideString& short_name) {
448 if (level > nMaxRecursion)
452 Node* pChild = pNew.get();
453 pParent->AddChildNode(
std::move(pNew));
461 for (size_t i = 0; i < pParent->GetChildrenCount(); ++i) {
462 Node* pNode = pParent->GetChildAt(i);
470 std::unique_ptr<CPDF_FormField> pField) {
475 Node* pLast =
nullptr;
476 CFieldNameExtractor name_extractor(full_name);
478 WideStringView name_view = name_extractor.GetNext();
479 if (name_view.IsEmpty())
492 pNode->SetField(
std::move(pField));
501 Node* pLast =
nullptr;
502 CFieldNameExtractor name_extractor(full_name);
504 WideStringView name_view = name_extractor.GetNext();
505 if (name_view.IsEmpty())
518 Node* pLast =
nullptr;
519 CFieldNameExtractor name_extractor(full_name);
521 WideStringView name_view = name_extractor.GetNext();
522 if (name_view.IsEmpty())
532 RetainPtr<CPDF_Dictionary> pRoot = m_pDocument->GetMutableRoot();
536 m_pFormDict = pRoot->GetMutableDictFor(
"AcroForm");
540 RetainPtr<CPDF_Array> pFields = m_pFormDict->GetMutableArrayFor(
"Fields");
544 for (size_t i = 0; i < pFields->size(); ++i)
545 LoadField(pFields->GetMutableDictAt(i), 0);
559 s_bUpdateAP = bUpdateAP;
565 ByteString* csNameTag) {
570 pDocument->GetMutableRoot()->GetMutableDictFor(
"AcroForm");
572 pFormDict = InitDict(pDocument);
577 GetNativeFont(pFormDict.Get(), pDocument, charSet, &csTemp);
579 *csNameTag =
std::move(csTemp);
582 ByteString csFontName = GetNativeFontName(charSet,
nullptr);
583 if (FindFontFromDoc(pFormDict.Get(), pDocument, csFontName, pFont, csNameTag))
586 pFont = AddNativeFont(charSet, pDocument);
590 AddFont(pFormDict.Get(), pDocument, pFont, csNameTag);
595 if (csFieldName.IsEmpty())
596 return m_pFieldTree->GetRoot()->CountFields();
599 return pNode ? pNode->CountFields() : 0;
604 const WideString& csFieldName)
const {
605 if (csFieldName.IsEmpty())
606 return m_pFieldTree->GetRoot()->GetFieldAtIndex(index);
609 return pNode ? pNode->GetFieldAtIndex(index) :
nullptr;
613 const CPDF_Dictionary* pFieldDict)
const {
618 return m_pFieldTree->GetField(csWName);
622 const CPDF_Page* pPage,
623 const CFX_PointF& point,
624 int* z_order)
const {
625 RetainPtr<
const CPDF_Array> pAnnotList = pPage->GetAnnotsArray();
629 for (size_t i = pAnnotList->size(); i > 0; --i) {
630 size_t annot_index = i - 1;
631 RetainPtr<
const CPDF_Dictionary> pAnnot =
632 pAnnotList->GetDictAt(annot_index);
636 const auto it = m_ControlMap.find(pAnnot.Get());
637 if (it == m_ControlMap.end())
645 *z_order =
static_cast<
int>(annot_index);
652 const CPDF_Dictionary* pWidgetDict)
const {
653 const auto it = m_ControlMap.find(pWidgetDict);
654 return it != m_ControlMap.end() ? it->second.get() :
nullptr;
658 return m_pFormDict && m_pFormDict->GetBooleanFor(
"NeedAppearances",
false);
665 RetainPtr<
const CPDF_Array> pArray = m_pFormDict->GetArrayFor(
"CO");
666 return pArray ?
fxcrt::CollectionSize<
int>(*pArray) : 0;
670 if (!m_pFormDict || index < 0)
673 RetainPtr<
const CPDF_Array> pArray = m_pFormDict->GetArrayFor(
"CO");
677 RetainPtr<
const CPDF_Dictionary> pElement =
678 ToDictionary(pArray->GetDirectObjectAt(index));
687 RetainPtr<
const CPDF_Array> pArray = m_pFormDict->GetArrayFor(
"CO");
691 absl::optional<size_t> maybe_found = pArray->Find(pField->GetFieldDict());
692 if (!maybe_found.has_value())
695 return pdfium::base::checked_cast<
int>(maybe_found.value());
699 ByteString csNameTag)
const {
700 ByteString csAlias = PDF_NameDecode(csNameTag.AsStringView());
701 if (!m_pFormDict || csAlias.IsEmpty())
704 RetainPtr<CPDF_Dictionary> pDR = m_pFormDict->GetMutableDictFor(
"DR");
708 RetainPtr<CPDF_Dictionary> pFonts = pDR->GetMutableDictFor(
"Font");
709 if (!ValidateFontResourceDict(pFonts.Get()))
712 RetainPtr<CPDF_Dictionary> pElement = pFonts->GetMutableDictFor(csAlias);
713 if (!ValidateDictType(pElement.Get(),
"Font"))
720 RetainPtr<CPDF_Dictionary> pElement)
const {
721 auto* pData = CPDF_DocPageData::FromDocument(m_pDocument);
722 return pData->GetFont(
std::move(pElement));
728 return CPDF_DefaultAppearance(m_pFormDict->GetByteStringFor(
"DA"));
732 return m_pFormDict ? m_pFormDict->GetIntegerFor(
"Q", 0) : 0;
736 bool bIncludeOrExclude) {
738 const size_t nCount = pRoot->CountFields();
739 for (size_t i = 0; i < nCount; ++i) {
744 if (bIncludeOrExclude == pdfium::Contains(fields, pField))
748 m_pFormNotify->AfterFormReset(
this);
752 ResetForm({},
false);
757 return m_ControlLists[pdfium::WrapUnowned(pField)];
762 if (nLevel > nMaxRecursion)
767 uint32_t dwParentObjNum = pFieldDict->GetObjNum();
769 pFieldDict->GetMutableArrayFor(pdfium::form_fields::kKids);
771 AddTerminalField(
std::move(pFieldDict));
775 RetainPtr<
const CPDF_Dictionary> pFirstKid = pKids->GetDictAt(0);
781 AddTerminalField(
std::move(pFieldDict));
784 for (size_t i = 0; i < pKids->size(); i++) {
785 RetainPtr<CPDF_Dictionary> pChildDict = pKids->GetMutableDictAt(i);
786 if (pChildDict && pChildDict->GetObjNum() != dwParentObjNum)
787 LoadField(
std::move(pChildDict), nLevel + 1);
792 RetainPtr<CPDF_Array> pAnnots = pPage->GetMutableAnnotsArray();
796 for (size_t i = 0; i < pAnnots->size(); i++) {
797 RetainPtr<CPDF_Dictionary> pAnnot = pAnnots->GetMutableDictAt(i);
798 if (pAnnot && pAnnot->GetNameFor(
"Subtype") ==
"Widget")
799 LoadField(
std::move(pAnnot), 0);
807 RetainPtr<
const CPDF_Dictionary> pParentDict =
808 pFieldDict->GetDictFor(pdfium::form_fields::kParent);
818 pField = m_pFieldTree->GetField(csWName);
820 RetainPtr<CPDF_Dictionary> pParent(pFieldDict);
822 pFieldDict->GetNameFor(
"Subtype") ==
"Widget") {
825 pParent = pFieldDict;
828 if (pParent && pParent != pFieldDict &&
832 pFieldDict->GetDirectObjectFor(pdfium::form_fields::kFT);
839 pFieldDict->GetDirectObjectFor(pdfium::form_fields::kFf);
846 pField = newField.get();
848 pFieldDict->GetObjectFor(pdfium::form_fields::kT);
849 if (ToReference(pTObj)) {
856 if (!m_pFieldTree->SetField(csWName, std::move(newField)))
861 pFieldDict->GetMutableArrayFor(pdfium::form_fields::kKids);
863 if (pFieldDict->GetNameFor(
"Subtype") ==
"Widget")
864 AddControl(pField,
std::move(pFieldDict));
867 for (size_t i = 0; i < pKids->size(); i++) {
868 RetainPtr<CPDF_Dictionary> pKid = pKids->GetMutableDictAt(i);
869 if (pKid && pKid->GetNameFor(
"Subtype") ==
"Widget")
870 AddControl(pField,
std::move(pKid));
876 RetainPtr<CPDF_Dictionary> pWidgetDict) {
878 const auto it = m_ControlMap.find(pWidgetDict.Get());
879 if (it != m_ControlMap.end())
880 return it->second.get();
884 m_ControlMap[pWidgetDict] = std::move(pNew);
885 m_ControlLists[pdfium::WrapUnowned(pField)].emplace_back(pControl);
890 const std::vector<CPDF_FormField*>* fields,
891 bool bIncludeOrExclude)
const {
893 const size_t nCount = pRoot->CountFields();
894 for (size_t i = 0; i < nCount; ++i) {
910 bFind = pdfium::Contains(*fields, pField);
911 if (bIncludeOrExclude == bFind) {
912 RetainPtr<
const CPDF_Dictionary> pFieldDict = pField->GetFieldDict();
923 const WideString& pdf_path)
const {
924 std::vector<CPDF_FormField*> fields;
926 const size_t nCount = pRoot->CountFields();
927 for (size_t i = 0; i < nCount; ++i)
928 fields.push_back(pRoot->GetFieldAtIndex(i));
929 return ExportToFDF(pdf_path, fields,
true);
933 const WideString& pdf_path,
934 const std::vector<CPDF_FormField*>& fields,
935 bool bIncludeOrExclude)
const {
936 std::unique_ptr<CFDF_Document> pDoc = CFDF_Document::CreateNewDoc();
941 pDoc->GetMutableRoot()->GetMutableDictFor(
"FDF");
943 auto pNewDict = pDoc->New<CPDF_Dictionary>();
944 pNewDict->SetNewFor<CPDF_Name>(
"Type",
"Filespec");
948 pNewDict->SetNewFor<CPDF_String>(
"UF", wsStr.AsStringView());
949 pMainDict->SetFor(
"F", pNewDict);
952 auto pFields = pMainDict->SetNewFor<CPDF_Array>(
"Fields");
954 const size_t nCount = pRoot->CountFields();
955 for (size_t i = 0; i < nCount; ++i) {
964 if (bIncludeOrExclude != pdfium::Contains(fields, pField))
967 if ((dwFlags & pdfium::form_flags::kRequired) != 0 &&
968 pField->GetFieldDict()
969 ->GetByteStringFor(pdfium::form_fields::kV)
974 WideString fullname =
976 auto pFieldDict = pDoc->New<CPDF_Dictionary>();
978 fullname.AsStringView());
982 ByteString csBExport = PDF_EncodeText(csExport.AsStringView());
992 pField->GetFieldAttr(pdfium::form_fields::kV);
996 pFields->Append(pFieldDict);
1002 m_pFormNotify = pNotify;
1006 const WideString& csValue) {
1007 return !m_pFormNotify || m_pFormNotify->BeforeValueChange(pField, csValue);
1012 m_pFormNotify->AfterValueChange(pField);
1017 const WideString& csValue) {
1018 return !m_pFormNotify ||
1019 m_pFormNotify->BeforeSelectionChange(pField, csValue);
1024 m_pFormNotify->AfterSelectionChange(pField);
1030 m_pFormNotify->AfterCheckedStatusChange(pField);
bool Contains(const CFX_PointF &point) const
static const char kDefaultAnsiFontName[]
void AddChildNode(std::unique_ptr< Node > pNode)
CPDF_FormField * GetFieldAtIndex(size_t index)
size_t GetChildrenCount() const
CPDF_FormField * GetField() const
size_t CountFields() const
Node(const WideString &short_name, int level)
const Node * GetChildAt(size_t i) const
void SetField(std::unique_ptr< CPDF_FormField > pField)
WideString GetShortName() const
Node * GetChildAt(size_t i)
bool SetField(const WideString &full_name, std::unique_ptr< CPDF_FormField > pField)
CPDF_FormField * GetField(const WideString &full_name)
Node * AddChild(Node *pParent, const WideString &short_name)
Node * Lookup(Node *pParent, WideStringView short_name)
Node * FindNode(const WideString &full_name)
static CPDF_DocPageData * FromDocument(const CPDF_Document *pDoc)
RetainPtr< CPDF_Font > AddStandardFont(const ByteString &fontName, const CPDF_FontEncoding *pEncoding)
static WideString EncodeFileName(const WideString &filepath)
CPDF_FontEncoding(FontEncoding predefined_encoding)
static ByteString FormatInteger(int i)
ByteString & operator+=(const char *str)
ByteString & operator=(const char *str)
ByteString & operator=(ByteString &&that) noexcept
bool operator!=(const char *ptr) const
ByteString ToDefANSI() const
ByteString PDF_NameEncode(const ByteString &orig)
FX_Charset FX_GetCharsetFromCodePage(FX_CodePage codepage)
ByteString operator+(const ByteString &str1, const ByteString &str2)
ByteString operator+(const ByteString &str1, const char *str2)
ByteString operator+(const char *str1, const ByteString &str2)