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