Coverage Report

Created: 2026-08-25 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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