/src/poppler/poppler/Form.h
Line | Count | Source |
1 | | //======================================================================== |
2 | | // |
3 | | // Form.h |
4 | | // |
5 | | // This file is licensed under the GPLv2 or later |
6 | | // |
7 | | // Copyright 2006 Julien Rebetez <julienr@svn.gnome.org> |
8 | | // Copyright 2007, 2008, 2011 Carlos Garcia Campos <carlosgc@gnome.org> |
9 | | // Copyright 2007-2010, 2012, 2015-2026 Albert Astals Cid <aacid@kde.org> |
10 | | // Copyright 2010 Mark Riedesel <mark@klowner.com> |
11 | | // Copyright 2011 Pino Toscano <pino@kde.org> |
12 | | // Copyright 2012 Fabio D'Urso <fabiodurso@hotmail.it> |
13 | | // Copyright 2013 Adrian Johnson <ajohnson@redneon.com> |
14 | | // Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com> |
15 | | // Copyright 2015 André Esser <bepandre@hotmail.com> |
16 | | // Copyright 2017 Roland Hieber <r.hieber@pengutronix.de> |
17 | | // Copyright 2017 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de> |
18 | | // Copyright 2018 Andre Heinecke <aheinecke@intevation.de> |
19 | | // Copyright 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich |
20 | | // Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com> |
21 | | // Copyright 2019, 2020 Oliver Sander <oliver.sander@tu-dresden.de> |
22 | | // Copyright 2019 João Netto <joaonetto901@gmail.com> |
23 | | // Copyright 2020, 2021 Nelson Benítez León <nbenitezl@gmail.com> |
24 | | // Copyright 2020 Marek Kasik <mkasik@redhat.com> |
25 | | // Copyright 2020 Thorsten Behrens <Thorsten.Behrens@CIB.de> |
26 | | // Copyright 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden |
27 | | // Copyright 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net. |
28 | | // Copyright 2021 Theofilos Intzoglou <int.teo@gmail.com> |
29 | | // Copyright 2022 Alexander Sulfrian <asulfrian@zedat.fu-berlin.de> |
30 | | // Copyright 2023-2026 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk> |
31 | | // Copyright 2024 Pratham Gandhi <ppg.1382@gmail.com> |
32 | | // Copyright 2025 Blair Bonnett <blair.bonnett@gmail.com> |
33 | | // |
34 | | //======================================================================== |
35 | | |
36 | | #ifndef FORM_H |
37 | | #define FORM_H |
38 | | |
39 | | #include "Annot.h" |
40 | | #include "CharTypes.h" |
41 | | #include "CryptoSignBackend.h" |
42 | | #include "Object.h" |
43 | | #include "poppler_private_export.h" |
44 | | #include "SignatureInfo.h" |
45 | | |
46 | | #include <ctime> |
47 | | |
48 | | #include <optional> |
49 | | #include <set> |
50 | | #include <vector> |
51 | | #include <functional> |
52 | | |
53 | | class GooString; |
54 | | class Array; |
55 | | class Dict; |
56 | | class Annot; |
57 | | class AnnotWidget; |
58 | | class Annots; |
59 | | class LinkAction; |
60 | | class GfxResources; |
61 | | class PDFDoc; |
62 | | class X509CertificateInfo; |
63 | | namespace CryptoSign { |
64 | | class VerificationInterface; |
65 | | } |
66 | | |
67 | | enum FormFieldType |
68 | | { |
69 | | formButton, |
70 | | formText, |
71 | | formChoice, |
72 | | formSignature, |
73 | | formUndef |
74 | | }; |
75 | | |
76 | | enum FormButtonType |
77 | | { |
78 | | formButtonCheck, |
79 | | formButtonPush, |
80 | | formButtonRadio |
81 | | }; |
82 | | |
83 | | enum FillValueType |
84 | | { |
85 | | fillValue, |
86 | | fillDefaultValue |
87 | | }; |
88 | | |
89 | | class Form; |
90 | | class FormField; |
91 | | class FormFieldButton; |
92 | | class FormFieldText; |
93 | | class FormFieldSignature; |
94 | | class FormFieldChoice; |
95 | | |
96 | | //------------------------------------------------------------------------ |
97 | | // FormWidget |
98 | | // A FormWidget represents the graphical part of a field and is "attached" |
99 | | // to a page. |
100 | | //------------------------------------------------------------------------ |
101 | | |
102 | | class POPPLER_PRIVATE_EXPORT FormWidget |
103 | | { |
104 | | public: |
105 | | virtual ~FormWidget(); |
106 | | |
107 | | // Check if point is inside the field bounding rect |
108 | | bool inRect(double x, double y) const; |
109 | | |
110 | | // Get the field bounding rect |
111 | | void getRect(double *x1, double *y1, double *x2, double *y2) const; |
112 | | |
113 | 0 | unsigned getID() const { return ID; } |
114 | 0 | void setID(unsigned int i) { ID = i; } |
115 | | |
116 | 0 | FormField *getField() { return field; } |
117 | 0 | FormFieldType getType() { return type; } |
118 | | |
119 | 0 | Object *getObj() { return &obj; } |
120 | 0 | Ref getRef() { return ref; } |
121 | | |
122 | 0 | void setChildNum(unsigned i) { childNum = i; } |
123 | 0 | unsigned getChildNum() const { return childNum; } |
124 | | |
125 | | const GooString *getPartialName() const; |
126 | | void setPartialName(const GooString &name); |
127 | | const GooString *getAlternateUiName() const; |
128 | | const GooString *getMappingName() const; |
129 | | const GooString *getFullyQualifiedName(); |
130 | | |
131 | | bool isModified() const; |
132 | | |
133 | | bool isReadOnly() const; |
134 | | void setReadOnly(bool value); |
135 | | |
136 | | const LinkAction *getActivationAction(); // The caller should not delete the result |
137 | | std::unique_ptr<LinkAction> getAdditionalAction(Annot::FormAdditionalActionsType type); |
138 | | bool setAdditionalAction(Annot::FormAdditionalActionsType t, const std::string &js); |
139 | | |
140 | | // return the unique ID corresponding to pageNum/fieldNum |
141 | | static int encodeID(unsigned pageNum, unsigned fieldNum); |
142 | | // decode id and retrieve pageNum and fieldNum |
143 | | static void decodeID(unsigned id, unsigned *pageNum, unsigned *fieldNum); |
144 | | |
145 | | void createWidgetAnnotation(); |
146 | 0 | std::shared_ptr<AnnotWidget> getWidgetAnnotation() const { return widget; } |
147 | 0 | void setWidgetAnnotation(std::shared_ptr<AnnotWidget> _widget) { widget = std::move(_widget); } |
148 | | |
149 | | virtual void updateWidgetAppearance() = 0; |
150 | | |
151 | | void print(int indent = 0) const; |
152 | | |
153 | | protected: |
154 | | FormWidget(PDFDoc *docA, Object *aobj, unsigned num, Ref aref, FormField *fieldA); |
155 | | |
156 | | std::shared_ptr<AnnotWidget> widget; |
157 | | FormField *field; |
158 | | FormFieldType type; |
159 | | Object obj; |
160 | | Ref ref; |
161 | | PDFDoc *doc; |
162 | | XRef *xref; |
163 | | |
164 | | // index of this field in the parent's child list |
165 | | unsigned childNum; |
166 | | |
167 | | /* |
168 | | Field ID is an (unsigned) integer, calculated as follow : |
169 | | the first sizeof/2 bits are the field number, relative to the page |
170 | | the last sizeof/2 bits are the page number |
171 | | [page number | field number] |
172 | | (encoding) id = (pageNum << 4*sizeof(unsigned)) + fieldNum; |
173 | | (decoding) pageNum = id >> 4*sizeof(unsigned); fieldNum = (id << 4*sizeof(unsigned)) >> 4*sizeof(unsigned); |
174 | | */ |
175 | | unsigned ID; |
176 | | }; |
177 | | |
178 | | //------------------------------------------------------------------------ |
179 | | // FormWidgetButton |
180 | | //------------------------------------------------------------------------ |
181 | | |
182 | | class POPPLER_PRIVATE_EXPORT FormWidgetButton : public FormWidget |
183 | | { |
184 | | public: |
185 | | FormWidgetButton(PDFDoc *docA, Object *dictObj, unsigned num, Ref ref, FormField *p); |
186 | | ~FormWidgetButton() override; |
187 | | |
188 | | FormButtonType getButtonType() const; |
189 | | |
190 | | void setState(bool state); |
191 | | bool getState() const; |
192 | | |
193 | | const char *getOnStr() const; |
194 | | void setAppearanceState(const char *state); |
195 | | void updateWidgetAppearance() override; |
196 | | |
197 | | protected: |
198 | | FormFieldButton *parent() const; |
199 | | std::unique_ptr<GooString> onStr; |
200 | | }; |
201 | | |
202 | | //------------------------------------------------------------------------ |
203 | | // FormWidgetText |
204 | | //------------------------------------------------------------------------ |
205 | | |
206 | | class POPPLER_PRIVATE_EXPORT FormWidgetText : public FormWidget |
207 | | { |
208 | | public: |
209 | | FormWidgetText(PDFDoc *docA, Object *dictObj, unsigned num, Ref ref, FormField *p); |
210 | | // return the field's content (UTF16BE) |
211 | | const GooString *getContent() const; |
212 | | |
213 | | // expects a UTF16BE string |
214 | | void setContent(std::unique_ptr<GooString> new_content); |
215 | | // sets the text inside the field appearance stream |
216 | | void setAppearanceContent(std::unique_ptr<GooString> new_content); |
217 | | |
218 | | void updateWidgetAppearance() override; |
219 | | |
220 | | bool isMultiline() const; |
221 | | bool isPassword() const; |
222 | | bool isFileSelect() const; |
223 | | bool noSpellCheck() const; |
224 | | bool noScroll() const; |
225 | | bool isComb() const; |
226 | | bool isRichText() const; |
227 | | int getMaxLen() const; |
228 | | // return the font size of the field's text |
229 | | double getTextFontSize(); |
230 | | // set the font size of the field's text (currently only integer values) |
231 | | void setTextFontSize(int fontSize); |
232 | | |
233 | | protected: |
234 | | FormFieldText *parent() const; |
235 | | }; |
236 | | |
237 | | //------------------------------------------------------------------------ |
238 | | // FormWidgetChoice |
239 | | //------------------------------------------------------------------------ |
240 | | |
241 | | struct FormFieldChoiceOption |
242 | | { |
243 | | std::unique_ptr<GooString> exportVal; // the export value ("internal" name) |
244 | | std::unique_ptr<GooString> optionName; // displayed name |
245 | | bool selected = false; // if this choice is selected |
246 | | }; |
247 | | |
248 | | class POPPLER_PRIVATE_EXPORT FormWidgetChoice : public FormWidget |
249 | | { |
250 | | public: |
251 | | FormWidgetChoice(PDFDoc *docA, Object *dictObj, unsigned num, Ref ref, FormField *p); |
252 | | ~FormWidgetChoice() override; |
253 | | |
254 | | const std::vector<FormFieldChoiceOption> &getChoices() const; |
255 | | // return the display name of the i-th choice (UTF16BE) |
256 | | const GooString *getChoice(int i) const; |
257 | | const GooString *getExportVal(int i) const; |
258 | | // select the i-th choice |
259 | | void select(int i); |
260 | | void setAppearanceChoiceContent(std::unique_ptr<GooString> new_content); |
261 | | // toggle selection of the i-th choice |
262 | | void toggle(int i); |
263 | | |
264 | | // deselect everything |
265 | | void deselectAll(); |
266 | | |
267 | | // except a UTF16BE string |
268 | | // only work for editable combo box, set the user-entered text as the current choice |
269 | | void setEditChoice(std::unique_ptr<GooString> new_content); |
270 | | |
271 | | const GooString *getEditChoice() const; |
272 | | |
273 | | void updateWidgetAppearance() override; |
274 | | bool isSelected(int i) const; |
275 | | |
276 | | bool isCombo() const; |
277 | | bool hasEdit() const; |
278 | | bool isMultiSelect() const; |
279 | | bool noSpellCheck() const; |
280 | | bool commitOnSelChange() const; |
281 | | bool isListBox() const; |
282 | | |
283 | | protected: |
284 | | bool _checkRange(int i) const; |
285 | | FormFieldChoice *parent() const; |
286 | | }; |
287 | | |
288 | | //------------------------------------------------------------------------ |
289 | | // FormWidgetSignature |
290 | | //------------------------------------------------------------------------ |
291 | | |
292 | | class POPPLER_PRIVATE_EXPORT FormWidgetSignature : public FormWidget |
293 | | { |
294 | | public: |
295 | | FormWidgetSignature(PDFDoc *docA, Object *dictObj, unsigned num, Ref ref, FormField *p); |
296 | | void updateWidgetAppearance() override; |
297 | | |
298 | | CryptoSign::SignatureType signatureType() const; |
299 | | void setSignatureType(CryptoSign::SignatureType fst); |
300 | | |
301 | | // Use -1 for now as validationTime |
302 | | // ocspRevocation and aiafetch might happen async in the Background |
303 | | // doneCallback will be invoked once there is a result |
304 | | // Note: Validation callback will likely happen from an auxillary |
305 | | // thread and it is the caller of this method who is responsible |
306 | | // for moving back to the main thread |
307 | | // For synchronous code, don't provide validation callback |
308 | | // and just call validateSignatureResult afterwards |
309 | | // The returned SignatureInfo from this method does |
310 | | // not have validated the certificate. |
311 | | SignatureInfo *validateSignatureAsync(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck, bool enableAIA, const std::function<void()> &doneCallback); |
312 | | |
313 | | /// Waits, if needed, on validation callback and |
314 | | /// returns a signatureinfo with validated certificates |
315 | | CertificateValidationStatus validateSignatureResult(); |
316 | | |
317 | | // returns a list with the boundaries of the signed ranges |
318 | | // the elements of the list are of type Goffset |
319 | | std::vector<Goffset> getSignedRangeBounds() const; |
320 | | |
321 | | // Creates or replaces the dictionary name "V" in the signature dictionary and |
322 | | // fills it with the fields of the signature; the field "Contents" is the signature |
323 | | // in PKCS#7 format, which is calculated over the byte range encompassing the whole |
324 | | // document except for the signature itself; this byte range is specified in the |
325 | | // field "ByteRange" in the dictionary "V". |
326 | | // Arguments reason and location are UTF-16 big endian strings with BOM. An empty string and nullptr are acceptable too. |
327 | | // Returns success. |
328 | | std::optional<CryptoSign::SigningErrorMessage> signDocument(const std::string &filename, const std::string &certNickname, const std::string &password, const GooString *reason = nullptr, const GooString *location = nullptr, |
329 | | const std::optional<GooString> &ownerPassword = {}, const std::optional<GooString> &userPassword = {}); |
330 | | |
331 | | // Same as above but adds text, font color, etc. |
332 | | std::optional<CryptoSign::SigningErrorMessage> signDocumentWithAppearance(const std::string &filename, const std::string &certNickname, const std::string &password, const GooString *reason = nullptr, const GooString *location = nullptr, |
333 | | const std::optional<GooString> &ownerPassword = {}, const std::optional<GooString> &userPassword = {}, const GooString &signatureText = {}, |
334 | | const GooString &signatureTextLeft = {}, double fontSize = {}, double leftFontSize = {}, std::unique_ptr<AnnotColor> &&fontColor = {}, double borderWidth = {}, |
335 | | std::unique_ptr<AnnotColor> &&borderColor = {}, std::unique_ptr<AnnotColor> &&backgroundColor = {}); |
336 | | |
337 | | // checks the length encoding of the signature and returns the signature |
338 | | // and the length that the signature is supposed to cover. |
339 | | // if invalid, a empty optional and 0 is returned. |
340 | | std::pair<std::optional<std::vector<unsigned char>>, int64_t> getCheckedSignature(); |
341 | | |
342 | | const std::vector<unsigned char> &getSignature() const; |
343 | | |
344 | | private: |
345 | | bool createSignature(Object &vObj, Ref vRef, const GooString &name, int placeholderLength, const GooString *reason, const GooString *location, CryptoSign::SignatureType signatureType); |
346 | | static bool getObjectStartEnd(const GooString &filename, int objNum, Goffset *objStart, Goffset *objEnd, const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword); |
347 | | static bool updateOffsets(FILE *f, Goffset objStart, Goffset objEnd, Goffset *sigStart, Goffset *sigEnd, Goffset *fileSize); |
348 | | |
349 | | static bool updateSignature(FILE *f, Goffset sigStart, Goffset sigEnd, const std::vector<unsigned char> &signature); |
350 | | }; |
351 | | |
352 | | //------------------------------------------------------------------------ |
353 | | // FormField |
354 | | // A FormField implements the logical side of a field and is "attached" to |
355 | | // the Catalog. This is an internal class and client applications should |
356 | | // only interact with FormWidgets. |
357 | | //------------------------------------------------------------------------ |
358 | | |
359 | | class POPPLER_PRIVATE_EXPORT FormField |
360 | | { |
361 | | public: |
362 | | FormField(PDFDoc *docA, Object &&aobj, Ref aref, FormField *parent, std::set<int> *usedParents, FormFieldType t = formUndef); |
363 | | |
364 | | virtual ~FormField(); |
365 | | |
366 | | // Accessors. |
367 | 0 | FormFieldType getType() const { return type; } |
368 | 0 | Object *getObj() { return &obj; } |
369 | 0 | Ref getRef() { return ref; } |
370 | | |
371 | | void setReadOnly(bool value); |
372 | 0 | bool isReadOnly() const { return readOnly; } |
373 | 0 | void setStandAlone(bool value) { standAlone = value; } |
374 | 0 | bool isStandAlone() const { return standAlone; } |
375 | | |
376 | 0 | const std::string &getDefaultAppearance() const { return defaultAppearance; } |
377 | | void setDefaultAppearance(const std::string &appearance); |
378 | | |
379 | 0 | bool hasTextQuadding() const { return hasQuadding; } |
380 | 0 | VariableTextQuadding getTextQuadding() const { return quadding; } |
381 | | |
382 | 0 | const GooString *getPartialName() const { return partialName.get(); } |
383 | | void setPartialName(const GooString &name); |
384 | 0 | const GooString *getAlternateUiName() const { return alternateUiName.get(); } |
385 | 0 | const GooString *getMappingName() const { return mappingName.get(); } |
386 | | const GooString *getFullyQualifiedName() const; |
387 | | |
388 | | FormWidget *findWidgetByRef(Ref aref); |
389 | 0 | int getNumWidgets() const { return terminal ? widgets.size() : 0; } |
390 | 0 | FormWidget *getWidget(int i) const { return terminal ? widgets[i].get() : nullptr; } |
391 | 0 | int getNumChildren() const { return !terminal ? children.size() : 0; } |
392 | 0 | FormField *getChildren(int i) const { return !terminal ? children[i].get() : nullptr; } |
393 | | |
394 | | // only implemented in FormFieldButton |
395 | | virtual void fillChildrenSiblingsID(); |
396 | | |
397 | | void createWidgetAnnotations(); |
398 | | |
399 | | void printTree(int indent = 0); |
400 | | virtual void print(int indent = 0); |
401 | | virtual void reset(const std::vector<std::string> &excludedFields); |
402 | | void resetChildren(const std::vector<std::string> &excludedFields); |
403 | | FormField *findFieldByRef(Ref aref); |
404 | | FormField *findFieldByFullyQualifiedName(const std::string &name); |
405 | | |
406 | 0 | bool getNoExport() const { return noExport; } |
407 | | |
408 | | protected: |
409 | | void _createWidget(Object *obj, Ref aref); |
410 | | void createChildren(std::set<int> *usedParents); |
411 | | void updateChildrenAppearance(); |
412 | | bool isAmongExcludedFields(const std::vector<std::string> &excludedFields); |
413 | | |
414 | | FormFieldType type; // field type |
415 | | Ref ref; |
416 | | bool terminal; |
417 | | Object obj; |
418 | | PDFDoc *doc; |
419 | | XRef *xref; |
420 | | std::vector<std::unique_ptr<FormField>> children; |
421 | | FormField *parent; |
422 | | std::vector<std::unique_ptr<FormWidget>> widgets; |
423 | | bool readOnly; |
424 | | bool noExport; |
425 | | |
426 | | std::unique_ptr<GooString> partialName; // T field |
427 | | std::unique_ptr<GooString> alternateUiName; // TU field |
428 | | std::unique_ptr<GooString> mappingName; // TM field |
429 | | mutable std::unique_ptr<GooString> fullyQualifiedName; |
430 | | |
431 | | // Variable Text |
432 | | std::string defaultAppearance; |
433 | | bool hasQuadding; |
434 | | VariableTextQuadding quadding; |
435 | | |
436 | | // True when FormField is not part of Catalog's Field array (or there isn't one). |
437 | | bool standAlone; |
438 | | |
439 | | private: |
440 | | FormField() = default; |
441 | | }; |
442 | | |
443 | | //------------------------------------------------------------------------ |
444 | | // FormFieldButton |
445 | | //------------------------------------------------------------------------ |
446 | | |
447 | | class FormFieldButton : public FormField |
448 | | { |
449 | | public: |
450 | | FormFieldButton(PDFDoc *docA, Object &&dict, Ref ref, FormField *parent, std::set<int> *usedParents); |
451 | | |
452 | 0 | FormButtonType getButtonType() const { return btype; } |
453 | | |
454 | 0 | bool noToggleToOff() const { return noAllOff; } |
455 | | |
456 | | // returns true if the state modification is accepted |
457 | | bool setState(const char *state, bool ignoreToggleOff = false); |
458 | | bool getState(std::string_view state) const; |
459 | | |
460 | 0 | const char *getAppearanceState() const { return appearanceState.isName() ? appearanceState.getName() : nullptr; } |
461 | 0 | const char *getDefaultAppearanceState() const { return defaultAppearanceState.isName() ? defaultAppearanceState.getName() : nullptr; } |
462 | | |
463 | | void fillChildrenSiblingsID() override; |
464 | | |
465 | | void setNumSiblings(int num); |
466 | 0 | void setSibling(int i, FormFieldButton *id) { siblings[i] = id; } |
467 | | |
468 | | // For radio buttons, return the fields of the other radio buttons in the same group |
469 | 0 | FormFieldButton *getSibling(int i) const { return siblings[i]; } |
470 | 0 | int getNumSiblings() const { return static_cast<int>(siblings.size()); } |
471 | | |
472 | | void print(int indent) override; |
473 | | void reset(const std::vector<std::string> &excludedFields) override; |
474 | | |
475 | | ~FormFieldButton() override; |
476 | | |
477 | | protected: |
478 | | void updateState(const char *state); |
479 | | |
480 | | std::vector<FormFieldButton *> siblings; // IDs of dependent buttons (each button of a radio field has all the others buttons |
481 | | // of the same field in this array) |
482 | | FormButtonType btype; |
483 | | int size; |
484 | | int active_child; // only used for combo box |
485 | | bool noAllOff; |
486 | | Object appearanceState; // V |
487 | | Object defaultAppearanceState; // DV |
488 | | }; |
489 | | |
490 | | //------------------------------------------------------------------------ |
491 | | // FormFieldText |
492 | | //------------------------------------------------------------------------ |
493 | | |
494 | | class FormFieldText : public FormField |
495 | | { |
496 | | public: |
497 | | FormFieldText(PDFDoc *docA, Object &&dictObj, Ref ref, FormField *parent, std::set<int> *usedParents); |
498 | | |
499 | 0 | const GooString *getContent() const { return content.get(); } |
500 | 0 | const GooString *getAppearanceContent() const { return internalContent ? internalContent.get() : content.get(); } |
501 | | void setContent(std::unique_ptr<GooString> new_content); |
502 | | void setAppearanceContent(std::unique_ptr<GooString> new_content); |
503 | | ~FormFieldText() override; |
504 | | |
505 | 0 | bool isMultiline() const { return multiline; } |
506 | 0 | bool isPassword() const { return password; } |
507 | 0 | bool isFileSelect() const { return fileSelect; } |
508 | 0 | bool noSpellCheck() const { return doNotSpellCheck; } |
509 | 0 | bool noScroll() const { return doNotScroll; } |
510 | 0 | bool isComb() const { return comb; } |
511 | 0 | bool isRichText() const { return richText; } |
512 | | |
513 | 0 | int getMaxLen() const { return maxLen; } |
514 | | |
515 | | // return the font size of the field's text |
516 | | double getTextFontSize(); |
517 | | // set the font size of the field's text (currently only integer values) |
518 | | void setTextFontSize(int fontSize); |
519 | | |
520 | | void print(int indent) override; |
521 | | void reset(const std::vector<std::string> &excludedFields) override; |
522 | | |
523 | | static std::optional<size_t> tokenizeDA(const std::string &daString, std::vector<std::string> *daToks, const char *searchTok); |
524 | | |
525 | | protected: |
526 | | std::optional<size_t> parseDA(std::vector<std::string> *daToks) const; |
527 | | void fillContent(FillValueType fillType); |
528 | | |
529 | | std::unique_ptr<GooString> content; |
530 | | std::unique_ptr<GooString> internalContent; |
531 | | std::unique_ptr<GooString> defaultContent; |
532 | | bool multiline; |
533 | | bool password; |
534 | | bool fileSelect; |
535 | | bool doNotSpellCheck; |
536 | | bool doNotScroll; |
537 | | bool comb; |
538 | | bool richText; |
539 | | int maxLen; |
540 | | }; |
541 | | |
542 | | //------------------------------------------------------------------------ |
543 | | // FormFieldChoice |
544 | | //------------------------------------------------------------------------ |
545 | | |
546 | | class FormFieldChoice : public FormField |
547 | | { |
548 | | public: |
549 | | FormFieldChoice(PDFDoc *docA, Object &&aobj, Ref ref, FormField *parent, std::set<int> *usedParents); |
550 | | |
551 | | ~FormFieldChoice() override; |
552 | | |
553 | 0 | const std::vector<FormFieldChoiceOption> &getChoices() const { return choices; } |
554 | 0 | const GooString *getChoice(int i) const { return choices[i].optionName.get(); } |
555 | 0 | const GooString *getExportVal(int i) const { return choices[i].exportVal.get(); } |
556 | | // For multi-select choices it returns the first one |
557 | | const GooString *getSelectedChoice() const; |
558 | 0 | const GooString *getAppearanceSelectedChoice() const { return appearanceSelectedChoice ? appearanceSelectedChoice.get() : getSelectedChoice(); } |
559 | | |
560 | | void setAppearanceChoiceContent(std::unique_ptr<GooString> new_content); |
561 | | |
562 | | // select the i-th choice |
563 | | void select(int i); |
564 | | |
565 | | // toggle selection of the i-th choice |
566 | | void toggle(int i); |
567 | | |
568 | | // deselect everything |
569 | | void deselectAll(); |
570 | | |
571 | | // only work for editable combo box, set the user-entered text as the current choice |
572 | | void setEditChoice(std::unique_ptr<GooString> new_content); |
573 | | |
574 | | const GooString *getEditChoice() const; |
575 | | |
576 | 0 | bool isSelected(int i) const { return choices[i].selected; } |
577 | | |
578 | | int getNumSelected() const; |
579 | | |
580 | 0 | bool isCombo() const { return combo; } |
581 | 0 | bool hasEdit() const { return edit; } |
582 | 0 | bool isMultiSelect() const { return multiselect; } |
583 | 0 | bool noSpellCheck() const { return doNotSpellCheck; } |
584 | 0 | bool commitOnSelChange() const { return doCommitOnSelChange; } |
585 | 0 | bool isListBox() const { return !combo; } |
586 | | |
587 | 0 | int getTopIndex() const { return topIdx; } |
588 | | |
589 | | void print(int indent) override; |
590 | | void reset(const std::vector<std::string> &excludedFields) override; |
591 | | |
592 | | protected: |
593 | | void unselectAll(); |
594 | | void updateSelection(); |
595 | | void fillChoices(FillValueType fillType); |
596 | | |
597 | | bool combo; |
598 | | bool edit; |
599 | | bool multiselect; |
600 | | bool doNotSpellCheck; |
601 | | bool doCommitOnSelChange; |
602 | | |
603 | | std::vector<FormFieldChoiceOption> choices; |
604 | | std::vector<bool> defaultChoices; |
605 | | std::unique_ptr<GooString> editedChoice; |
606 | | std::unique_ptr<GooString> appearanceSelectedChoice; |
607 | | int topIdx; // TI |
608 | | }; |
609 | | |
610 | | //------------------------------------------------------------------------ |
611 | | // FormFieldSignature |
612 | | //------------------------------------------------------------------------ |
613 | | |
614 | | class POPPLER_PRIVATE_EXPORT FormFieldSignature : public FormField |
615 | | { |
616 | | public: |
617 | | FormFieldSignature(PDFDoc *docA, Object &&dict, Ref ref, FormField *parent, std::set<int> *usedParents); |
618 | | |
619 | | // Use -1 for now as validationTime |
620 | | SignatureInfo *validateSignatureAsync(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck, bool enableAIA, const std::function<void()> &doneCallback); |
621 | | |
622 | | CertificateValidationStatus validateSignatureResult(); |
623 | | |
624 | | // returns a list with the boundaries of the signed ranges |
625 | | // the elements of the list are of type Goffset |
626 | | std::vector<Goffset> getSignedRangeBounds() const; |
627 | | |
628 | | // checks the length encoding of the signature and returns the signature |
629 | | // and the end of data the signature covers |
630 | | // otherwise a nullopt and 0 is returned |
631 | | std::pair<std::optional<std::vector<unsigned char>>, int64_t> getCheckedSignature(); |
632 | | |
633 | | ~FormFieldSignature() override; |
634 | 0 | Object *getByteRange() { return &byte_range; } |
635 | 0 | const std::vector<unsigned char> &getSignature() const { return signature; } |
636 | | void setSignature(std::vector<unsigned char> &&sig); |
637 | 0 | CryptoSign::SignatureType getSignatureType() const { return signature_type; } |
638 | 0 | void setSignatureType(CryptoSign::SignatureType t) { signature_type = t; } |
639 | | |
640 | | const GooString &getCustomAppearanceContent() const; |
641 | | void setCustomAppearanceContent(const GooString &s); |
642 | | |
643 | | const GooString &getCustomAppearanceLeftContent() const; |
644 | | void setCustomAppearanceLeftContent(const GooString &s); |
645 | | |
646 | | double getCustomAppearanceLeftFontSize() const; |
647 | | void setCustomAppearanceLeftFontSize(double size); |
648 | | |
649 | | // Background image (ref to an object of type XObject). Invalid ref if not required. |
650 | | Ref getImageResource() const; |
651 | | void setImageResource(Ref imageResourceA); |
652 | | |
653 | | void setCertificateInfo(std::unique_ptr<X509CertificateInfo> &certInfo); |
654 | | |
655 | | FormWidget *getCreateWidget(); |
656 | | |
657 | | private: |
658 | | void parseInfo(); |
659 | | void hashSignedDataBlock(CryptoSign::VerificationInterface *handler, Goffset block_len); |
660 | | |
661 | | CryptoSign::SignatureType signature_type = CryptoSign::SignatureType::unsigned_signature_field; |
662 | | Object byte_range; |
663 | | std::vector<unsigned char> signature; |
664 | | SignatureInfo *signature_info; |
665 | | GooString customAppearanceContent; |
666 | | GooString customAppearanceLeftContent; |
667 | | double customAppearanceLeftFontSize = 20; |
668 | | Ref imageResource = Ref::INVALID(); |
669 | | std::unique_ptr<X509CertificateInfo> certificate_info; |
670 | | std::unique_ptr<CryptoSign::VerificationInterface> signature_handler; |
671 | | |
672 | | void print(int indent) override; |
673 | | }; |
674 | | |
675 | | //------------------------------------------------------------------------ |
676 | | // Form |
677 | | // This class handle the document-wide part of Form (things in the acroForm |
678 | | // Catalog entry). |
679 | | //------------------------------------------------------------------------ |
680 | | |
681 | | class POPPLER_PRIVATE_EXPORT Form |
682 | | { |
683 | | public: |
684 | | explicit Form(PDFDoc *doc); |
685 | | |
686 | | ~Form(); |
687 | | |
688 | | Form(const Form &) = delete; |
689 | | Form &operator=(const Form &) = delete; |
690 | | |
691 | | // Look up an inheritable field dictionary entry. |
692 | | static Object fieldLookup(Dict *field, const char *key); |
693 | | |
694 | | /* Creates a new Field of the type specified in obj's dict. |
695 | | used in Form::Form , FormField::FormField and |
696 | | Page::loadStandaloneFields */ |
697 | | static std::unique_ptr<FormField> createFieldFromDict(Object &&obj, PDFDoc *docA, Ref aref, FormField *parent, std::set<int> *usedParents); |
698 | | |
699 | | // Finds in the default resources dictionary a font named popplerfontXXX that |
700 | | // has the given fontFamily and fontStyle. This makes us relatively sure that we added that font ourselves |
701 | | std::string findFontInDefaultResources(const std::string &fontFamily, const std::string &fontStyle) const; |
702 | | |
703 | | // Finds in the default resources a font that is suitable to create a signature annotation. |
704 | | // If none is found then it is added to the default resources. |
705 | | std::string findPdfFontNameToUseForSigning(); |
706 | | |
707 | | struct AddFontResult |
708 | | { |
709 | | std::string fontName; |
710 | | Ref ref; |
711 | | }; |
712 | | |
713 | | // Finds in the system a font name matching the given fontFamily and fontStyle |
714 | | // And adds it to the default resources dictionary, font name there will be popplerfontXXX except if forceName is true, |
715 | | // in that case the font name will be fontFamily + " " + fontStyle (if fontStyle is empty just fontFamily) |
716 | | AddFontResult addFontToDefaultResources(const std::string &fontFamily, const std::string &fontStyle, bool forceName = false); |
717 | | |
718 | | // Finds in the default resources dictionary a font named popplerfontXXX that |
719 | | // emulates fontToEmulate and can draw the given char |
720 | | std::string getFallbackFontForChar(Unicode uChar, const GfxFont &fontToEmulate) const; |
721 | | |
722 | | // Makes sure the default resources has fonts to draw all the given chars and as close as possible to the given pdfFontNameToEmulate |
723 | | // If needed adds fonts to the default resources dictionary, font names will be popplerfontXXX |
724 | | // If fieldResources is not nullptr, it is used instead of the to query the font to emulate instead of the default resources |
725 | | // Returns a list of all the added fonts (if any) |
726 | | std::vector<AddFontResult> ensureFontsForAllCharacters(const std::string &unicodeText, const std::string &pdfFontNameToEmulate, GfxResources *fieldResources = nullptr); |
727 | | |
728 | 0 | bool getNeedAppearances() const { return needAppearances; } |
729 | 0 | int getNumFields() const { return rootFields.size(); } |
730 | 0 | FormField *getRootField(int i) const { return rootFields[i].get(); } |
731 | 0 | const std::string &getDefaultAppearance() const { return defaultAppearance; } |
732 | 0 | VariableTextQuadding getTextQuadding() const { return quadding; } |
733 | 0 | GfxResources *getDefaultResources() const { return defaultResources; } |
734 | 0 | Object *getDefaultResourcesObj() { return &resDict; } |
735 | | |
736 | | FormWidget *findWidgetByRef(Ref aref); |
737 | | FormField *findFieldByRef(Ref aref) const; |
738 | | FormField *findFieldByFullyQualifiedName(const std::string &name) const; |
739 | | FormField *findFieldByFullyQualifiedNameOrRef(const std::string &field) const; |
740 | | |
741 | | void postWidgetsLoad(); |
742 | | |
743 | 0 | const std::vector<Ref> &getCalculateOrder() const { return calculateOrder; } |
744 | | |
745 | | void reset(const std::vector<std::string> &fields, bool excludeFields); |
746 | | |
747 | | private: |
748 | | // Finds in the system a font name matching the given fontFamily and fontStyle |
749 | | // And adds it to the default resources dictionary, font name there will be popplerfontXXX except if forceName is true, |
750 | | // in that case the font name will be fontFamily + " " + fontStyle (if fontStyle is empty just fontFamily) |
751 | | // if fileSubstitutedIn is true, |
752 | | AddFontResult addFontToDefaultResources(const std::string &filepath, int faceIndex, const std::string &fontFamily, const std::string &fontStyle, bool fontSubstitutedIn, bool forceName); |
753 | | |
754 | | AddFontResult doGetAddFontToDefaultResources(Unicode uChar, const GfxFont &fontToEmulate); |
755 | | |
756 | | std::vector<std::unique_ptr<FormField>> rootFields; |
757 | | PDFDoc *const doc; |
758 | | bool needAppearances; |
759 | | GfxResources *defaultResources; |
760 | | Object resDict; |
761 | | std::vector<Ref> calculateOrder; |
762 | | |
763 | | // Variable Text |
764 | | std::string defaultAppearance; |
765 | | VariableTextQuadding quadding; |
766 | | }; |
767 | | |
768 | | //------------------------------------------------------------------------ |
769 | | // FormPageWidgets |
770 | | //------------------------------------------------------------------------ |
771 | | |
772 | | class POPPLER_PRIVATE_EXPORT FormPageWidgets |
773 | | { |
774 | | public: |
775 | | FormPageWidgets(Annots *annots, unsigned int page, Form *form); |
776 | | ~FormPageWidgets(); |
777 | | |
778 | | FormPageWidgets(const FormPageWidgets &) = delete; |
779 | | FormPageWidgets &operator=(const FormPageWidgets &) = delete; |
780 | | |
781 | 0 | int getNumWidgets() const { return widgets.size(); } |
782 | 0 | FormWidget *getWidget(int i) const { return widgets[i]; } |
783 | | void addWidgets(const std::vector<std::unique_ptr<FormField>> &addedWidgets, unsigned int page); |
784 | | |
785 | | private: |
786 | | std::vector<FormWidget *> widgets; |
787 | | }; |
788 | | |
789 | | #endif |