Coverage Report

Created: 2026-06-07 08:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/qt6/src/poppler-form.cc
Line
Count
Source
1
/* poppler-form.h: qt interface to poppler
2
 * Copyright (C) 2007-2008, 2011, Pino Toscano <pino@kde.org>
3
 * Copyright (C) 2008, 2011, 2012, 2015-2026 Albert Astals Cid <aacid@kde.org>
4
 * Copyright (C) 2011 Carlos Garcia Campos <carlosgc@gnome.org>
5
 * Copyright (C) 2012, Adam Reichold <adamreichold@myopera.com>
6
 * Copyright (C) 2016, Hanno Meyer-Thurow <h.mth@web.de>
7
 * Copyright (C) 2017, Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
8
 * Copyright (C) 2018, Andre Heinecke <aheinecke@intevation.de>
9
 * Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
10
 * Copyright (C) 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
11
 * Copyright (C) 2018, 2020, 2021 Oliver Sander <oliver.sander@tu-dresden.de>
12
 * Copyright (C) 2019 João Netto <joaonetto901@gmail.com>
13
 * Copyright (C) 2020 David García Garzón <voki@canvoki.net>
14
 * Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens@CIB.de>
15
 * Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
16
 * Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
17
 * Copyright (C) 2021 Theofilos Intzoglou <int.teo@gmail.com>
18
 * Copyright (C) 2022 Alexander Sulfrian <asulfrian@zedat.fu-berlin.de>
19
 * Copyright (C) 2023-2026 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
20
 * Copyright (C) 2024 Pratham Gandhi <ppg.1382@gmail.com>
21
 * Copyright (C) 2024 Stefan Brüns <stefan.bruens@rwth-aachen.de>
22
 * Copyright (C) 2025 Blair Bonnett <blair.bonnett@gmail.com>
23
 *
24
 * This program is free software; you can redistribute it and/or modify
25
 * it under the terms of the GNU General Public License as published by
26
 * the Free Software Foundation; either version 2, or (at your option)
27
 * any later version.
28
 *
29
 * This program is distributed in the hope that it will be useful,
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32
 * GNU General Public License for more details.
33
 *
34
 * You should have received a copy of the GNU General Public License
35
 * along with this program; if not, write to the Free Software
36
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
37
 */
38
39
#include "poppler-form.h"
40
#include "poppler-converter.h"
41
42
#include <chrono>
43
#include <config.h>
44
45
#include <QtCore/QSizeF>
46
#include <QTimeZone>
47
#include <QUrl>
48
49
#include <Form.h>
50
#include <Object.h>
51
#include <Link.h>
52
#include <SignatureInfo.h>
53
#include <CertificateInfo.h>
54
#include <CryptoSignBackend.h>
55
#if ENABLE_NSS3
56
#    include <NSSCryptoSignBackend.h>
57
#endif
58
#if ENABLE_GPGME
59
#    include <GPGMECryptoSignBackendConfiguration.h>
60
#endif
61
62
#include "poppler-page-private.h"
63
#include "poppler-private.h"
64
#include "poppler-annotation-helper.h"
65
66
namespace {
67
68
Qt::Alignment formTextAlignment(::FormWidget *fm)
69
0
{
70
0
    Qt::Alignment qtalign = Qt::AlignLeft;
71
0
    switch (fm->getField()->getTextQuadding()) {
72
0
    case VariableTextQuadding::centered:
73
0
        qtalign = Qt::AlignHCenter;
74
0
        break;
75
0
    case VariableTextQuadding::rightJustified:
76
0
        qtalign = Qt::AlignRight;
77
0
        break;
78
0
    case VariableTextQuadding::leftJustified:
79
0
        qtalign = Qt::AlignLeft;
80
0
    }
81
0
    return qtalign;
82
0
}
83
84
}
85
86
namespace Poppler {
87
88
0
FormFieldIcon::FormFieldIcon(FormFieldIconData *data) : d_ptr(data) { }
89
90
FormFieldIcon::FormFieldIcon(const FormFieldIcon &ffIcon)
91
0
{
92
0
    d_ptr = new FormFieldIconData;
93
0
    d_ptr->icon = ffIcon.d_ptr->icon;
94
0
}
95
96
FormFieldIcon &FormFieldIcon::operator=(const FormFieldIcon &ffIcon)
97
0
{
98
0
    if (this != &ffIcon) {
99
0
        delete d_ptr;
100
0
        d_ptr = nullptr;
101
102
0
        d_ptr = new FormFieldIconData;
103
0
        *d_ptr = *ffIcon.d_ptr;
104
0
    }
105
106
0
    return *this;
107
0
}
108
109
FormFieldIcon::~FormFieldIcon()
110
0
{
111
0
    delete d_ptr;
112
0
}
113
114
6
FormField::FormField(std::unique_ptr<FormFieldData> dd) : m_formData(std::move(dd))
115
6
{
116
6
    if (m_formData->page) {
117
6
        const int rotation = m_formData->page->getRotate();
118
        // reading the coords
119
6
        double left, top, right, bottom;
120
6
        m_formData->fm->getRect(&left, &bottom, &right, &top);
121
        // build a normalized transform matrix for this page at 100% scale
122
6
        GfxState gfxState(72.0, 72.0, m_formData->page->getCropBox(), rotation, true);
123
6
        const std::array<double, 6> &gfxCTM = gfxState.getCTM();
124
6
        double MTX[6];
125
6
        double pageWidth = m_formData->page->getCropWidth();
126
6
        double pageHeight = m_formData->page->getCropHeight();
127
        // landscape and seascape page rotation: be sure to use the correct (== rotated) page size
128
6
        if (((rotation / 90) % 2) == 1) {
129
0
            qSwap(pageWidth, pageHeight);
130
0
        }
131
24
        for (int i = 0; i < 6; i += 2) {
132
18
            MTX[i] = gfxCTM[i] / pageWidth;
133
18
            MTX[i + 1] = gfxCTM[i + 1] / pageHeight;
134
18
        }
135
6
        QPointF topLeft;
136
6
        XPDFReader::transform(MTX, qMin(left, right), qMax(top, bottom), topLeft);
137
6
        QPointF bottomRight;
138
6
        XPDFReader::transform(MTX, qMax(left, right), qMin(top, bottom), bottomRight);
139
6
        m_formData->box = QRectF(topLeft, QSizeF(bottomRight.x() - topLeft.x(), bottomRight.y() - topLeft.y()));
140
6
    }
141
6
}
142
143
6
FormField::~FormField() = default;
144
145
QRectF FormField::rect() const
146
0
{
147
0
    return m_formData->box;
148
0
}
149
150
int FormField::id() const
151
0
{
152
0
    return m_formData->fm->getID();
153
0
}
154
155
QString FormField::name() const
156
0
{
157
0
    QString name;
158
0
    if (const GooString *goo = m_formData->fm->getPartialName()) {
159
0
        name = UnicodeParsedString(goo);
160
0
    }
161
0
    return name;
162
0
}
163
164
void FormField::setName(const QString &name) const
165
0
{
166
0
    const std::unique_ptr<GooString> goo = QStringToGooString(name);
167
0
    m_formData->fm->setPartialName(*goo);
168
0
}
169
170
QString FormField::fullyQualifiedName() const
171
0
{
172
0
    QString name;
173
0
    if (const GooString *goo = m_formData->fm->getFullyQualifiedName()) {
174
0
        name = UnicodeParsedString(goo);
175
0
    }
176
0
    return name;
177
0
}
178
179
QString FormField::uiName() const
180
0
{
181
0
    QString name;
182
0
    if (const GooString *goo = m_formData->fm->getAlternateUiName()) {
183
0
        name = UnicodeParsedString(goo);
184
0
    }
185
0
    return name;
186
0
}
187
188
bool FormField::isReadOnly() const
189
0
{
190
0
    return m_formData->fm->isReadOnly();
191
0
}
192
193
void FormField::setReadOnly(bool value)
194
0
{
195
0
    m_formData->fm->setReadOnly(value);
196
0
}
197
198
bool FormField::isVisible() const
199
0
{
200
0
    const unsigned int flags = m_formData->fm->getWidgetAnnotation()->getFlags();
201
0
    if (flags & Annot::flagHidden) {
202
0
        return false;
203
0
    }
204
0
    if (flags & Annot::flagNoView) {
205
0
        return false;
206
0
    }
207
0
    return true;
208
0
}
209
210
void FormField::setVisible(bool value)
211
0
{
212
0
    unsigned int flags = m_formData->fm->getWidgetAnnotation()->getFlags();
213
0
    if (value) {
214
0
        flags &= ~Annot::flagHidden;
215
0
        flags &= ~Annot::flagNoView;
216
0
    } else {
217
0
        flags |= Annot::flagHidden;
218
0
    }
219
0
    m_formData->fm->getWidgetAnnotation()->setFlags(flags);
220
0
}
221
222
bool FormField::isPrintable() const
223
0
{
224
0
    return (m_formData->fm->getWidgetAnnotation()->getFlags() & Annot::flagPrint);
225
0
}
226
227
void FormField::setPrintable(bool value)
228
0
{
229
0
    unsigned int flags = m_formData->fm->getWidgetAnnotation()->getFlags();
230
0
    if (value) {
231
0
        flags |= Annot::flagPrint;
232
0
    } else {
233
0
        flags &= ~Annot::flagPrint;
234
0
    }
235
0
    m_formData->fm->getWidgetAnnotation()->setFlags(flags);
236
0
}
237
238
std::unique_ptr<Link> FormField::activationAction() const
239
0
{
240
0
    if (const ::LinkAction *act = m_formData->fm->getActivationAction()) {
241
0
        return PageData::convertLinkActionToLink(act, m_formData->doc, QRectF());
242
0
    }
243
244
0
    return {};
245
0
}
246
247
std::unique_ptr<Link> FormField::additionalAction(AdditionalActionType type) const
248
0
{
249
0
    Annot::FormAdditionalActionsType actionType = Annot::actionFieldModified;
250
0
    switch (type) {
251
0
    case FieldModified:
252
0
        actionType = Annot::actionFieldModified;
253
0
        break;
254
0
    case FormatField:
255
0
        actionType = Annot::actionFormatField;
256
0
        break;
257
0
    case ValidateField:
258
0
        actionType = Annot::actionValidateField;
259
0
        break;
260
0
    case CalculateField:
261
0
        actionType = Annot::actionCalculateField;
262
0
        break;
263
0
    }
264
265
0
    if (std::unique_ptr<::LinkAction> act = m_formData->fm->getAdditionalAction(actionType)) {
266
0
        return PageData::convertLinkActionToLink(act.get(), m_formData->doc, QRectF());
267
0
    }
268
269
0
    return {};
270
0
}
271
272
std::unique_ptr<Link> FormField::additionalAction(Annotation::AdditionalActionType type) const
273
0
{
274
0
    ::AnnotWidget *w = m_formData->fm->getWidgetAnnotation().get();
275
0
    if (!w) {
276
0
        return {};
277
0
    }
278
279
0
    const Annot::AdditionalActionsType actionType = toPopplerAdditionalActionType(type);
280
281
0
    if (std::unique_ptr<::LinkAction> act = w->getAdditionalAction(actionType)) {
282
0
        return PageData::convertLinkActionToLink(act.get(), m_formData->doc, QRectF());
283
0
    }
284
285
0
    return {};
286
0
}
287
288
0
FormFieldButton::FormFieldButton(DocumentData *doc, ::Page *p, ::FormWidgetButton *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }
289
290
FormFieldButton::~FormFieldButton() = default;
291
292
FormFieldButton::FormType FormFieldButton::type() const
293
0
{
294
0
    return FormField::FormButton;
295
0
}
296
297
FormFieldButton::ButtonType FormFieldButton::buttonType() const
298
0
{
299
0
    auto *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
300
0
    switch (fwb->getButtonType()) {
301
0
    case formButtonCheck:
302
0
        return FormFieldButton::CheckBox;
303
0
        break;
304
0
    case formButtonPush:
305
0
        return FormFieldButton::Push;
306
0
        break;
307
0
    case formButtonRadio:
308
0
        return FormFieldButton::Radio;
309
0
        break;
310
0
    }
311
0
    return FormFieldButton::CheckBox;
312
0
}
313
314
QString FormFieldButton::caption() const
315
0
{
316
0
    auto *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
317
0
    QString ret;
318
0
    if (fwb->getButtonType() == formButtonPush) {
319
0
        Dict *dict = m_formData->fm->getObj()->getDict();
320
0
        Object obj1 = dict->lookup("MK");
321
0
        if (obj1.isDict()) {
322
0
            AnnotAppearanceCharacs appearCharacs(obj1.getDict());
323
0
            if (appearCharacs.getNormalCaption()) {
324
0
                ret = UnicodeParsedString(appearCharacs.getNormalCaption());
325
0
            }
326
0
        }
327
0
    } else {
328
0
        if (const char *goo = fwb->getOnStr()) {
329
0
            ret = QString::fromUtf8(goo);
330
0
        }
331
0
    }
332
0
    return ret;
333
0
}
334
335
FormFieldIcon FormFieldButton::icon() const
336
0
{
337
0
    auto *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
338
0
    if (fwb->getButtonType() == formButtonPush) {
339
0
        Dict *dict = m_formData->fm->getObj()->getDict();
340
0
        auto *data = new FormFieldIconData;
341
0
        data->icon = dict;
342
0
        return FormFieldIcon(data);
343
0
    }
344
0
    return FormFieldIcon(nullptr);
345
0
}
346
347
void FormFieldButton::setIcon(const FormFieldIcon &icon)
348
0
{
349
0
    if (FormFieldIconData::getData(icon) == nullptr) {
350
0
        return;
351
0
    }
352
353
0
    auto *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
354
0
    if (fwb->getButtonType() == formButtonPush) {
355
0
        std::shared_ptr<::AnnotWidget> w = m_formData->fm->getWidgetAnnotation();
356
0
        FormFieldIconData *data = FormFieldIconData::getData(icon);
357
0
        if (data->icon != nullptr) {
358
0
            w->setNewAppearance(data->icon->lookup("AP"));
359
0
        }
360
0
    }
361
0
}
362
363
bool FormFieldButton::state() const
364
0
{
365
0
    auto *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
366
0
    return fwb->getState();
367
0
}
368
369
void FormFieldButton::setState(bool state)
370
0
{
371
0
    auto *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
372
0
    fwb->setState(state);
373
0
}
374
375
QList<int> FormFieldButton::siblings() const
376
0
{
377
0
    auto *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
378
0
    auto *ffb = static_cast<::FormFieldButton *>(fwb->getField());
379
0
    if (fwb->getButtonType() == formButtonPush) {
380
0
        return QList<int>();
381
0
    }
382
383
0
    QList<int> ret;
384
0
    for (int i = 0; i < ffb->getNumSiblings(); ++i) {
385
0
        auto *sibling = static_cast<::FormFieldButton *>(ffb->getSibling(i));
386
0
        for (int j = 0; j < sibling->getNumWidgets(); ++j) {
387
0
            FormWidget *w = sibling->getWidget(j);
388
0
            if (w) {
389
0
                ret.append(w->getID());
390
0
            }
391
0
        }
392
0
    }
393
394
0
    return ret;
395
0
}
396
397
0
FormFieldText::FormFieldText(DocumentData *doc, ::Page *p, ::FormWidgetText *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }
398
399
FormFieldText::~FormFieldText() = default;
400
401
FormField::FormType FormFieldText::type() const
402
0
{
403
0
    return FormField::FormText;
404
0
}
405
406
FormFieldText::TextType FormFieldText::textType() const
407
0
{
408
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
409
0
    if (fwt->isFileSelect()) {
410
0
        return FormFieldText::FileSelect;
411
0
    }
412
0
    if (fwt->isMultiline()) {
413
0
        return FormFieldText::Multiline;
414
0
    }
415
0
    return FormFieldText::Normal;
416
0
}
417
418
QString FormFieldText::text() const
419
0
{
420
0
    const GooString *goo = static_cast<FormWidgetText *>(m_formData->fm)->getContent();
421
0
    return UnicodeParsedString(goo);
422
0
}
423
424
void FormFieldText::setText(const QString &text)
425
0
{
426
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
427
0
    std::unique_ptr<GooString> goo = QStringToUnicodeGooString(text);
428
0
    fwt->setContent(std::move(goo));
429
0
}
430
431
void FormFieldText::setAppearanceText(const QString &text)
432
0
{
433
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
434
0
    std::unique_ptr<GooString> goo = QStringToUnicodeGooString(text);
435
0
    fwt->setAppearanceContent(std::move(goo));
436
0
}
437
438
bool FormFieldText::isPassword() const
439
0
{
440
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
441
0
    return fwt->isPassword();
442
0
}
443
444
bool FormFieldText::isRichText() const
445
0
{
446
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
447
0
    return fwt->isRichText();
448
0
}
449
450
int FormFieldText::maximumLength() const
451
0
{
452
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
453
0
    const int maxlen = fwt->getMaxLen();
454
0
    return maxlen > 0 ? maxlen : -1;
455
0
}
456
457
Qt::Alignment FormFieldText::textAlignment() const
458
0
{
459
0
    return formTextAlignment(m_formData->fm);
460
0
}
461
462
bool FormFieldText::canBeSpellChecked() const
463
0
{
464
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
465
0
    return !fwt->noSpellCheck();
466
0
}
467
468
double FormFieldText::getFontSize() const
469
0
{
470
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
471
0
    return fwt->getTextFontSize();
472
0
}
473
474
void FormFieldText::setFontSize(int fontSize)
475
0
{
476
0
    auto *fwt = static_cast<FormWidgetText *>(m_formData->fm);
477
0
    fwt->setTextFontSize(fontSize);
478
0
}
479
480
0
FormFieldChoice::FormFieldChoice(DocumentData *doc, ::Page *p, ::FormWidgetChoice *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }
481
482
FormFieldChoice::~FormFieldChoice() = default;
483
484
FormFieldChoice::FormType FormFieldChoice::type() const
485
0
{
486
0
    return FormField::FormChoice;
487
0
}
488
489
FormFieldChoice::ChoiceType FormFieldChoice::choiceType() const
490
0
{
491
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
492
0
    if (fwc->isCombo()) {
493
0
        return FormFieldChoice::ComboBox;
494
0
    }
495
0
    return FormFieldChoice::ListBox;
496
0
}
497
498
QStringList FormFieldChoice::choices() const
499
0
{
500
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
501
0
    QStringList ret;
502
0
    const std::vector<FormFieldChoiceOption> &choices = fwc->getChoices();
503
0
    ret.reserve(choices.size());
504
0
    for (const FormFieldChoiceOption &choice : choices) {
505
0
        ret.append(UnicodeParsedString(choice.optionName.get()));
506
0
    }
507
0
    return ret;
508
0
}
509
510
QVector<QPair<QString, QString>> FormFieldChoice::choicesWithExportValues() const
511
0
{
512
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
513
0
    QVector<QPair<QString, QString>> ret;
514
0
    const std::vector<FormFieldChoiceOption> &choices = fwc->getChoices();
515
0
    ret.reserve(choices.size());
516
0
    for (const FormFieldChoiceOption &choice : choices) {
517
0
        const QString display = UnicodeParsedString(choice.optionName.get());
518
0
        const GooString *exportValueG = choice.exportVal.get();
519
0
        const QString exportValue = exportValueG ? UnicodeParsedString(exportValueG) : display;
520
0
        ret.append({ display, exportValue });
521
0
    }
522
523
0
    return ret;
524
0
}
525
526
bool FormFieldChoice::isEditable() const
527
0
{
528
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
529
0
    return fwc->isCombo() ? fwc->hasEdit() : false;
530
0
}
531
532
bool FormFieldChoice::multiSelect() const
533
0
{
534
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
535
0
    return !fwc->isCombo() ? fwc->isMultiSelect() : false;
536
0
}
537
538
QList<int> FormFieldChoice::currentChoices() const
539
0
{
540
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
541
0
    const int num = fwc->getChoices().size();
542
0
    QList<int> choices;
543
0
    for (int i = 0; i < num; ++i) {
544
0
        if (fwc->isSelected(i)) {
545
0
            choices.append(i);
546
0
        }
547
0
    }
548
0
    return choices;
549
0
}
550
551
void FormFieldChoice::setCurrentChoices(const QList<int> &choice)
552
0
{
553
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
554
0
    fwc->deselectAll();
555
0
    for (int i = 0; i < choice.count(); ++i) {
556
0
        fwc->select(choice.at(i));
557
0
    }
558
0
}
559
560
QString FormFieldChoice::editChoice() const
561
0
{
562
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
563
564
0
    if (fwc->isCombo() && fwc->hasEdit()) {
565
0
        return UnicodeParsedString(fwc->getEditChoice());
566
0
    }
567
0
    return QString();
568
0
}
569
570
void FormFieldChoice::setEditChoice(const QString &text)
571
0
{
572
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
573
574
0
    if (fwc->isCombo() && fwc->hasEdit()) {
575
0
        std::unique_ptr<GooString> goo = QStringToUnicodeGooString(text);
576
0
        fwc->setEditChoice(std::move(goo));
577
0
    }
578
0
}
579
580
Qt::Alignment FormFieldChoice::textAlignment() const
581
0
{
582
0
    return formTextAlignment(m_formData->fm);
583
0
}
584
585
bool FormFieldChoice::canBeSpellChecked() const
586
0
{
587
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
588
0
    return !fwc->noSpellCheck();
589
0
}
590
591
void FormFieldChoice::setAppearanceChoiceText(const QString &text)
592
0
{
593
0
    auto *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
594
0
    std::unique_ptr<GooString> goo = QStringToUnicodeGooString(text);
595
0
    fwc->setAppearanceChoiceContent(std::move(goo));
596
0
}
597
598
class CertificateInfoPrivate
599
{
600
public:
601
    struct EntityInfo
602
    {
603
        QString common_name;
604
        QString email_address;
605
        QString org_name;
606
        QString distinguished_name;
607
    };
608
609
    EntityInfo issuer_info;
610
    EntityInfo subject_info;
611
    QString nick_name;
612
    QByteArray certificate_der;
613
    QByteArray serial_number;
614
    QByteArray public_key;
615
    QDateTime validity_start;
616
    QDateTime validity_end;
617
    int public_key_type;
618
    int public_key_strength;
619
    int ku_extensions;
620
    int version;
621
    bool is_self_signed;
622
    bool is_null;
623
    bool is_qualified;
624
    CertificateInfo::CertificateType certificateType;
625
    CertificateInfo::KeyLocation keyLocation;
626
};
627
628
0
CertificateInfo::CertificateInfo() : d_ptr(new CertificateInfoPrivate())
629
0
{
630
0
    d_ptr->is_null = true;
631
0
}
632
633
6
CertificateInfo::CertificateInfo(CertificateInfoPrivate *priv) : d_ptr(priv) { }
634
635
6
CertificateInfo::CertificateInfo(const CertificateInfo &other) = default;
636
637
12
CertificateInfo::~CertificateInfo() = default;
638
639
CertificateInfo &CertificateInfo::operator=(const CertificateInfo &other)
640
0
{
641
0
    if (this != &other) {
642
0
        d_ptr = other.d_ptr;
643
0
    }
644
645
0
    return *this;
646
0
}
647
648
bool CertificateInfo::isNull() const
649
0
{
650
0
    Q_D(const CertificateInfo);
651
0
    return d->is_null;
652
0
}
653
654
int CertificateInfo::version() const
655
0
{
656
0
    Q_D(const CertificateInfo);
657
0
    return d->version;
658
0
}
659
660
QByteArray CertificateInfo::serialNumber() const
661
0
{
662
0
    Q_D(const CertificateInfo);
663
0
    return d->serial_number;
664
0
}
665
666
bool CertificateInfo::isQualified() const
667
0
{
668
0
    Q_D(const CertificateInfo);
669
0
    return d->is_qualified;
670
0
}
671
672
CertificateInfo::CertificateType CertificateInfo::certificateType() const
673
0
{
674
0
    Q_D(const CertificateInfo);
675
0
    return d->certificateType;
676
0
}
677
678
QString CertificateInfo::issuerInfo(EntityInfoKey key) const
679
0
{
680
0
    Q_D(const CertificateInfo);
681
0
    switch (key) {
682
0
    case CommonName:
683
0
        return d->issuer_info.common_name;
684
0
    case DistinguishedName:
685
0
        return d->issuer_info.distinguished_name;
686
0
    case EmailAddress:
687
0
        return d->issuer_info.email_address;
688
0
    case Organization:
689
0
        return d->issuer_info.org_name;
690
0
    default:
691
0
        return QString();
692
0
    }
693
0
}
694
695
QString CertificateInfo::subjectInfo(EntityInfoKey key) const
696
0
{
697
0
    Q_D(const CertificateInfo);
698
0
    switch (key) {
699
0
    case CommonName:
700
0
        return d->subject_info.common_name;
701
0
    case DistinguishedName:
702
0
        return d->subject_info.distinguished_name;
703
0
    case EmailAddress:
704
0
        return d->subject_info.email_address;
705
0
    case Organization:
706
0
        return d->subject_info.org_name;
707
0
    default:
708
0
        return QString();
709
0
    }
710
0
}
711
712
QString CertificateInfo::nickName() const
713
0
{
714
0
    Q_D(const CertificateInfo);
715
0
    return d->nick_name;
716
0
}
717
718
QDateTime CertificateInfo::validityStart() const
719
0
{
720
0
    Q_D(const CertificateInfo);
721
0
    return d->validity_start;
722
0
}
723
724
QDateTime CertificateInfo::validityEnd() const
725
0
{
726
0
    Q_D(const CertificateInfo);
727
0
    return d->validity_end;
728
0
}
729
730
CertificateInfo::KeyUsageExtensions CertificateInfo::keyUsageExtensions() const
731
0
{
732
0
    Q_D(const CertificateInfo);
733
734
0
    KeyUsageExtensions kuExtensions = KuNone;
735
0
    if (d->ku_extensions & KU_DIGITAL_SIGNATURE) {
736
0
        kuExtensions |= KuDigitalSignature;
737
0
    }
738
0
    if (d->ku_extensions & KU_NON_REPUDIATION) {
739
0
        kuExtensions |= KuNonRepudiation;
740
0
    }
741
0
    if (d->ku_extensions & KU_KEY_ENCIPHERMENT) {
742
0
        kuExtensions |= KuKeyEncipherment;
743
0
    }
744
0
    if (d->ku_extensions & KU_DATA_ENCIPHERMENT) {
745
0
        kuExtensions |= KuDataEncipherment;
746
0
    }
747
0
    if (d->ku_extensions & KU_KEY_AGREEMENT) {
748
0
        kuExtensions |= KuKeyAgreement;
749
0
    }
750
0
    if (d->ku_extensions & KU_KEY_CERT_SIGN) {
751
0
        kuExtensions |= KuKeyCertSign;
752
0
    }
753
0
    if (d->ku_extensions & KU_CRL_SIGN) {
754
0
        kuExtensions |= KuClrSign;
755
0
    }
756
0
    if (d->ku_extensions & KU_ENCIPHER_ONLY) {
757
0
        kuExtensions |= KuEncipherOnly;
758
0
    }
759
760
0
    return kuExtensions;
761
0
}
762
763
CertificateInfo::KeyLocation CertificateInfo::keyLocation() const
764
0
{
765
0
    Q_D(const CertificateInfo);
766
0
    return d->keyLocation;
767
0
}
768
769
QByteArray CertificateInfo::publicKey() const
770
0
{
771
0
    Q_D(const CertificateInfo);
772
0
    return d->public_key;
773
0
}
774
775
CertificateInfo::PublicKeyType CertificateInfo::publicKeyType() const
776
0
{
777
0
    Q_D(const CertificateInfo);
778
0
    switch (d->public_key_type) {
779
0
    case RSAKEY:
780
0
        return RsaKey;
781
0
    case DSAKEY:
782
0
        return DsaKey;
783
0
    case ECKEY:
784
0
        return EcKey;
785
0
    default:
786
0
        return OtherKey;
787
0
    }
788
0
}
789
790
int CertificateInfo::publicKeyStrength() const
791
0
{
792
0
    Q_D(const CertificateInfo);
793
0
    return d->public_key_strength;
794
0
}
795
796
bool CertificateInfo::isSelfSigned() const
797
0
{
798
0
    Q_D(const CertificateInfo);
799
0
    return d->is_self_signed;
800
0
}
801
802
QByteArray CertificateInfo::certificateData() const
803
0
{
804
0
    Q_D(const CertificateInfo);
805
0
    return d->certificate_der;
806
0
}
807
808
bool CertificateInfo::checkPassword(const QString &password) const
809
0
{
810
0
#if ENABLE_SIGNATURES
811
0
    auto backend = CryptoSign::Factory::createActive();
812
0
    if (!backend) {
813
0
        return false;
814
0
    }
815
0
    Q_D(const CertificateInfo);
816
0
    auto sigHandler = backend->createSigningHandler(d->nick_name.toStdString(), HashAlgorithm::Sha256);
817
0
    unsigned char buffer[5];
818
0
    memcpy(buffer, "test", 5);
819
0
    sigHandler->addData(buffer, 5);
820
0
    std::variant<std::vector<unsigned char>, CryptoSign::SigningErrorMessage> tmpSignature = sigHandler->signDetached(password.toStdString());
821
0
    return std::holds_alternative<std::vector<unsigned char>>(tmpSignature);
822
#else
823
    (void)password;
824
    return false;
825
#endif
826
0
}
827
828
class SignatureValidationInfoPrivate
829
{
830
public:
831
6
    explicit SignatureValidationInfoPrivate(CertificateInfo &&ci) : cert_info(ci) { }
832
833
    SignatureValidationInfo::SignatureStatus signature_status;
834
    SignatureValidationInfo::CertificateStatus certificate_status;
835
    CertificateInfo cert_info;
836
837
    QByteArray signature;
838
    QString signer_name;
839
    QString signer_subject_dn;
840
    QString location;
841
    QString reason;
842
    HashAlgorithm hash_algorithm;
843
    time_t signing_time;
844
    QList<qint64> range_bounds;
845
    qint64 docLength;
846
};
847
848
6
SignatureValidationInfo::SignatureValidationInfo(SignatureValidationInfoPrivate *priv) : d_ptr(priv) { }
849
850
12
SignatureValidationInfo::SignatureValidationInfo(const SignatureValidationInfo &other) = default;
851
852
18
SignatureValidationInfo::~SignatureValidationInfo() = default;
853
854
SignatureValidationInfo::SignatureStatus SignatureValidationInfo::signatureStatus() const
855
0
{
856
0
    Q_D(const SignatureValidationInfo);
857
0
    return d->signature_status;
858
0
}
859
860
SignatureValidationInfo::CertificateStatus SignatureValidationInfo::certificateStatus() const
861
0
{
862
0
    Q_D(const SignatureValidationInfo);
863
0
    return d->certificate_status;
864
0
}
865
866
QString SignatureValidationInfo::signerName() const
867
0
{
868
0
    Q_D(const SignatureValidationInfo);
869
0
    return d->signer_name;
870
0
}
871
872
QString SignatureValidationInfo::signerSubjectDN() const
873
0
{
874
0
    Q_D(const SignatureValidationInfo);
875
0
    return d->signer_subject_dn;
876
0
}
877
878
QString SignatureValidationInfo::location() const
879
0
{
880
0
    Q_D(const SignatureValidationInfo);
881
0
    return d->location;
882
0
}
883
884
QString SignatureValidationInfo::reason() const
885
0
{
886
0
    Q_D(const SignatureValidationInfo);
887
0
    return d->reason;
888
0
}
889
890
SignatureValidationInfo::HashAlgorithm SignatureValidationInfo::hashAlgorithm() const
891
0
{
892
0
#if ENABLE_SIGNATURES
893
0
    Q_D(const SignatureValidationInfo);
894
895
0
    switch (d->hash_algorithm) {
896
0
    case ::HashAlgorithm::Md2:
897
0
        return HashAlgorithmMd2;
898
0
    case ::HashAlgorithm::Md5:
899
0
        return HashAlgorithmMd5;
900
0
    case ::HashAlgorithm::Sha1:
901
0
        return HashAlgorithmSha1;
902
0
    case ::HashAlgorithm::Sha256:
903
0
        return HashAlgorithmSha256;
904
0
    case ::HashAlgorithm::Sha384:
905
0
        return HashAlgorithmSha384;
906
0
    case ::HashAlgorithm::Sha512:
907
0
        return HashAlgorithmSha512;
908
0
    case ::HashAlgorithm::Sha224:
909
0
        return HashAlgorithmSha224;
910
0
    case ::HashAlgorithm::Unknown:
911
0
        return HashAlgorithmUnknown;
912
0
    }
913
0
#endif
914
0
    return HashAlgorithmUnknown;
915
0
}
916
917
time_t SignatureValidationInfo::signingTime() const
918
0
{
919
0
    Q_D(const SignatureValidationInfo);
920
0
    return d->signing_time;
921
0
}
922
923
QByteArray SignatureValidationInfo::signature() const
924
0
{
925
0
    Q_D(const SignatureValidationInfo);
926
0
    return d->signature;
927
0
}
928
929
QList<qint64> SignatureValidationInfo::signedRangeBounds() const
930
0
{
931
0
    Q_D(const SignatureValidationInfo);
932
0
    return d->range_bounds;
933
0
}
934
935
bool SignatureValidationInfo::signsTotalDocument() const
936
0
{
937
0
    Q_D(const SignatureValidationInfo);
938
0
    if (d->range_bounds.size() == 4 && d->range_bounds.value(0) == 0 && d->range_bounds.value(1) >= 0 && d->range_bounds.value(2) > d->range_bounds.value(1) && d->range_bounds.value(3) >= d->range_bounds.value(2)) {
939
        // The range from d->range_bounds.value(1) to d->range_bounds.value(2) is
940
        // not authenticated by the signature and should only contain the signature
941
        // itself padded with 0 bytes. This has been checked in readSignature().
942
        // If it failed, d->signature is empty.
943
        // A potential range after d->range_bounds.value(3) would be also not
944
        // authenticated. Therefore d->range_bounds.value(3) should coincide with
945
        // the end of the document.
946
0
        if (d->docLength == d->range_bounds.value(3) && !d->signature.isEmpty()) {
947
0
            return true;
948
0
        }
949
0
    }
950
0
    return false;
951
0
}
952
953
CertificateInfo SignatureValidationInfo::certificateInfo() const
954
0
{
955
0
    Q_D(const SignatureValidationInfo);
956
0
    return d->cert_info;
957
0
}
958
959
SignatureValidationInfo &SignatureValidationInfo::operator=(const SignatureValidationInfo &other)
960
0
{
961
0
    if (this != &other) {
962
0
        d_ptr = other.d_ptr;
963
0
    }
964
965
0
    return *this;
966
0
}
967
968
6
FormFieldSignature::FormFieldSignature(DocumentData *doc, ::Page *p, ::FormWidgetSignature *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }
969
970
FormFieldSignature::~FormFieldSignature() = default;
971
972
FormField::FormType FormFieldSignature::type() const
973
0
{
974
0
    return FormField::FormSignature;
975
0
}
976
977
FormFieldSignature::SignatureType FormFieldSignature::signatureType() const
978
0
{
979
0
    SignatureType sigType = AdbePkcs7detached;
980
0
    auto *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
981
0
    switch (fws->signatureType()) {
982
0
    case CryptoSign::SignatureType::adbe_pkcs7_sha1:
983
0
        sigType = AdbePkcs7sha1;
984
0
        break;
985
0
    case CryptoSign::SignatureType::adbe_pkcs7_detached:
986
0
        sigType = AdbePkcs7detached;
987
0
        break;
988
0
    case CryptoSign::SignatureType::ETSI_CAdES_detached:
989
0
        sigType = EtsiCAdESdetached;
990
0
        break;
991
0
    case CryptoSign::SignatureType::unknown_signature_type:
992
0
        sigType = UnknownSignatureType;
993
0
        break;
994
0
    case CryptoSign::SignatureType::g10c_pgp_signature_detached:
995
0
        sigType = G10cPgpSignatureDetached;
996
0
        break;
997
0
    case CryptoSign::SignatureType::unsigned_signature_field:
998
0
        sigType = UnsignedSignature;
999
0
        break;
1000
0
    }
1001
0
    return sigType;
1002
0
}
1003
1004
SignatureValidationInfo FormFieldSignature::validate(ValidateOptions opt) const
1005
0
{
1006
0
    auto tempResult = validateAsync(opt);
1007
0
    tempResult.first.d_ptr->certificate_status = validateResult();
1008
0
    return tempResult.first;
1009
0
}
1010
1011
static CertificateInfo::CertificateType fromPopplerCore(CertificateType type)
1012
0
{
1013
0
    switch (type) {
1014
0
    case CertificateType::PGP:
1015
0
        return CertificateInfo::CertificateType::PGP;
1016
0
    case CertificateType::X509:
1017
0
        return CertificateInfo::CertificateType::X509;
1018
0
    }
1019
0
    return CertificateInfo::CertificateType::X509; // fallback
1020
0
}
1021
1022
static CertificateInfo::KeyLocation fromPopplerCore(KeyLocation location)
1023
0
{
1024
0
    switch (location) {
1025
0
    case KeyLocation::Computer:
1026
0
        return CertificateInfo::KeyLocation::Computer;
1027
0
    case KeyLocation::Other:
1028
0
        return CertificateInfo::KeyLocation::Other;
1029
0
    case KeyLocation::Unknown:
1030
0
        return CertificateInfo::KeyLocation::Unknown;
1031
0
    case KeyLocation::HardwareToken:
1032
0
        return CertificateInfo::KeyLocation::HardwareToken;
1033
0
    }
1034
0
    return CertificateInfo::KeyLocation::Unknown;
1035
0
}
1036
1037
static CertificateInfoPrivate *createCertificateInfoPrivate(const X509CertificateInfo *ci)
1038
6
{
1039
6
    auto *certPriv = new CertificateInfoPrivate;
1040
6
    certPriv->is_null = true;
1041
6
    if (ci) {
1042
0
        certPriv->version = ci->getVersion();
1043
0
        certPriv->ku_extensions = ci->getKeyUsageExtensions();
1044
0
        certPriv->keyLocation = fromPopplerCore(ci->getKeyLocation());
1045
0
        certPriv->certificateType = fromPopplerCore(ci->getCertificateType());
1046
1047
0
        const GooString &certSerial = ci->getSerialNumber();
1048
0
        certPriv->serial_number = QByteArray(certSerial.c_str(), certSerial.size());
1049
1050
0
        const X509CertificateInfo::EntityInfo &issuerInfo = ci->getIssuerInfo();
1051
0
        certPriv->issuer_info.common_name = QString::fromStdString(issuerInfo.commonName);
1052
0
        certPriv->issuer_info.distinguished_name = QString::fromStdString(issuerInfo.distinguishedName);
1053
0
        certPriv->issuer_info.email_address = QString::fromStdString(issuerInfo.email);
1054
0
        certPriv->issuer_info.org_name = QString::fromStdString(issuerInfo.organization);
1055
1056
0
        const X509CertificateInfo::EntityInfo &subjectInfo = ci->getSubjectInfo();
1057
0
        certPriv->subject_info.common_name = QString::fromStdString(subjectInfo.commonName);
1058
0
        certPriv->subject_info.distinguished_name = QString::fromStdString(subjectInfo.distinguishedName);
1059
0
        certPriv->subject_info.email_address = QString::fromStdString(subjectInfo.email);
1060
0
        certPriv->subject_info.org_name = QString::fromStdString(subjectInfo.organization);
1061
1062
0
        certPriv->nick_name = QString::fromStdString(ci->getNickName().toStr());
1063
1064
0
        const X509CertificateInfo::Validity &certValidity = ci->getValidity();
1065
#if __cpp_lib_chrono >= 201907L // gcc-13 fails this (ubuntu 24.04) - gcc-14 succeeds
1066
        certPriv->validity_start = QDateTime::fromStdTimePoint(certValidity.notBefore);
1067
        certPriv->validity_end = QDateTime::fromStdTimePoint(certValidity.notAfter);
1068
#else
1069
0
        certPriv->validity_start = QDateTime::fromSecsSinceEpoch(std::chrono::duration_cast<std::chrono::seconds>(certValidity.notBefore.time_since_epoch()).count(), QTimeZone::utc());
1070
0
        certPriv->validity_end = QDateTime::fromSecsSinceEpoch(std::chrono::duration_cast<std::chrono::seconds>(certValidity.notAfter.time_since_epoch()).count(), QTimeZone::utc());
1071
0
#endif
1072
1073
0
        const X509CertificateInfo::PublicKeyInfo &pkInfo = ci->getPublicKeyInfo();
1074
0
        certPriv->public_key = QByteArray(pkInfo.publicKey.c_str(), pkInfo.publicKey.size());
1075
0
        certPriv->public_key_type = static_cast<int>(pkInfo.publicKeyType);
1076
0
        certPriv->public_key_strength = pkInfo.publicKeyStrength;
1077
1078
0
        const std::vector<unsigned char> &certDer = ci->getCertificateDER();
1079
0
        certPriv->certificate_der = QByteArray(reinterpret_cast<const char *>(certDer.data()), certDer.size());
1080
1081
0
        certPriv->is_null = false;
1082
0
        certPriv->is_qualified = ci->isQualified();
1083
0
    }
1084
1085
6
    return certPriv;
1086
6
}
1087
1088
static SignatureValidationInfo::CertificateStatus fromInternal(CertificateValidationStatus status)
1089
6
{
1090
6
    switch (status) {
1091
0
    case CERTIFICATE_TRUSTED:
1092
0
        return SignatureValidationInfo::CertificateTrusted;
1093
0
    case CERTIFICATE_UNTRUSTED_ISSUER:
1094
0
        return SignatureValidationInfo::CertificateUntrustedIssuer;
1095
0
    case CERTIFICATE_UNKNOWN_ISSUER:
1096
0
        return SignatureValidationInfo::CertificateUnknownIssuer;
1097
0
    case CERTIFICATE_REVOKED:
1098
0
        return SignatureValidationInfo::CertificateRevoked;
1099
0
    case CERTIFICATE_EXPIRED:
1100
0
        return SignatureValidationInfo::CertificateExpired;
1101
0
    default:
1102
6
    case CERTIFICATE_GENERIC_ERROR:
1103
6
        return SignatureValidationInfo::CertificateGenericError;
1104
0
    case CERTIFICATE_NOT_VERIFIED:
1105
0
        return SignatureValidationInfo::CertificateNotVerified;
1106
6
    }
1107
6
}
1108
1109
static SignatureValidationInfo fromInternal(SignatureInfo *si, FormWidgetSignature *fws)
1110
6
{
1111
    // get certificate info
1112
6
    const X509CertificateInfo *ci = si->getCertificateInfo();
1113
6
    CertificateInfoPrivate *certPriv = createCertificateInfoPrivate(ci);
1114
1115
6
    auto *priv = new SignatureValidationInfoPrivate(CertificateInfo(certPriv));
1116
6
    switch (si->getSignatureValStatus()) {
1117
0
    case SIGNATURE_VALID:
1118
0
        priv->signature_status = SignatureValidationInfo::SignatureValid;
1119
0
        break;
1120
0
    case SIGNATURE_INVALID:
1121
0
        priv->signature_status = SignatureValidationInfo::SignatureInvalid;
1122
0
        break;
1123
0
    case SIGNATURE_DIGEST_MISMATCH:
1124
0
        priv->signature_status = SignatureValidationInfo::SignatureDigestMismatch;
1125
0
        break;
1126
0
    case SIGNATURE_DECODING_ERROR:
1127
0
        priv->signature_status = SignatureValidationInfo::SignatureDecodingError;
1128
0
        break;
1129
0
    default:
1130
0
    case SIGNATURE_GENERIC_ERROR:
1131
0
        priv->signature_status = SignatureValidationInfo::SignatureGenericError;
1132
0
        break;
1133
0
    case SIGNATURE_NOT_FOUND:
1134
0
        priv->signature_status = SignatureValidationInfo::SignatureNotFound;
1135
0
        break;
1136
6
    case SIGNATURE_NOT_VERIFIED:
1137
6
        priv->signature_status = SignatureValidationInfo::SignatureNotVerified;
1138
6
        break;
1139
6
    }
1140
6
    priv->certificate_status = SignatureValidationInfo::CertificateVerificationInProgress;
1141
6
    priv->signer_name = QString::fromStdString(si->getSignerName());
1142
6
    priv->signer_subject_dn = QString::fromStdString(si->getSubjectDN());
1143
6
    priv->hash_algorithm = si->getHashAlgorithm();
1144
6
    priv->location = UnicodeParsedString(si->getLocation().toStr());
1145
6
    priv->reason = UnicodeParsedString(si->getReason().toStr());
1146
1147
6
    priv->signing_time = si->getSigningTime();
1148
6
    const std::vector<Goffset> ranges = fws->getSignedRangeBounds();
1149
6
    if (!ranges.empty()) {
1150
16
        for (Goffset bound : ranges) {
1151
16
            priv->range_bounds.append(bound);
1152
16
        }
1153
4
    }
1154
6
    std::optional<std::vector<unsigned char>> checkedSignature;
1155
6
    std::tie(checkedSignature, priv->docLength) = fws->getCheckedSignature();
1156
6
    if (priv->range_bounds.size() == 4 && checkedSignature) {
1157
0
        priv->signature = QByteArray::fromRawData(reinterpret_cast<const char *>(checkedSignature->data()), checkedSignature->size());
1158
0
    }
1159
1160
6
    return SignatureValidationInfo(priv);
1161
6
}
1162
1163
SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &validationTime) const
1164
0
{
1165
0
    auto tempResult = validateAsync(static_cast<ValidateOptions>(opt), validationTime);
1166
0
    tempResult.first.d_ptr->certificate_status = validateResult();
1167
0
    return tempResult.first;
1168
0
}
1169
1170
class AsyncObjectPrivate
1171
{ /*Currently unused. Created for abi future proofing*/
1172
};
1173
1174
6
AsyncObject::AsyncObject() : QObject(nullptr) { }
1175
1176
6
AsyncObject::~AsyncObject() = default;
1177
1178
std::pair<SignatureValidationInfo, std::shared_ptr<Poppler::AsyncObject>> FormFieldSignature::validateAsync(ValidateOptions opt, const QDateTime &validationTime) const
1179
6
{
1180
6
    auto object = std::make_shared<AsyncObject>();
1181
6
    auto *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
1182
6
    const time_t validationTimeT = validationTime.isValid() ? validationTime.toSecsSinceEpoch() : -1;
1183
6
    SignatureInfo *si = fws->validateSignatureAsync(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT, !(opt & ValidateWithoutOCSPRevocationCheck), opt & ValidateUseAIACertFetch,
1184
6
                                                    [obj = std::weak_ptr<AsyncObject>(object)]() {
1185
2
                                                        if (auto l = obj.lock()) {
1186
                                                            // We need to roundtrip over the eventloop
1187
                                                            // to ensure callers have a chance of connecting to AsyncObject::done
1188
2
                                                            QMetaObject::invokeMethod(
1189
2
                                                                    l.get(),
1190
2
                                                                    [innerObj = std::weak_ptr<AsyncObject>(l)]() {
1191
0
                                                                        if (auto innerLocked = innerObj.lock()) {
1192
0
                                                                            Q_EMIT innerLocked->done();
1193
0
                                                                        }
1194
0
                                                                    },
1195
2
                                                                    Qt::QueuedConnection);
1196
2
                                                        }
1197
2
                                                    });
1198
1199
6
    return { fromInternal(si, fws), object };
1200
6
}
1201
1202
SignatureValidationInfo::CertificateStatus FormFieldSignature::validateResult() const
1203
6
{
1204
6
    return fromInternal(static_cast<FormWidgetSignature *>(m_formData->fm)->validateSignatureResult());
1205
6
}
1206
1207
FormFieldSignature::SigningResult FormFieldSignature::sign(const QString &outputFileName, const PDFConverter::NewSignatureData &data) const
1208
0
{
1209
0
    auto *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
1210
0
    if (fws->signatureType() != CryptoSign::SignatureType::unsigned_signature_field) {
1211
0
        return FieldAlreadySigned;
1212
0
    }
1213
1214
0
    const auto [sig, file_size] = fws->getCheckedSignature();
1215
0
    if (sig) {
1216
        // the above unsigned_signature_field check
1217
        // should already catch this, but double check
1218
0
        return FieldAlreadySigned;
1219
0
    }
1220
0
    const auto reason = std::unique_ptr<GooString>(data.reason().isEmpty() ? nullptr : QStringToUnicodeGooString(data.reason()));
1221
0
    const auto location = std::unique_ptr<GooString>(data.location().isEmpty() ? nullptr : QStringToUnicodeGooString(data.location()));
1222
0
    const auto ownerPwd = std::optional<GooString>(data.documentOwnerPassword().constData());
1223
0
    const auto userPwd = std::optional<GooString>(data.documentUserPassword().constData());
1224
0
    const auto gSignatureText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureText()));
1225
0
    const auto gSignatureLeftText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureLeftText()));
1226
1227
0
    const auto failure = fws->signDocumentWithAppearance(outputFileName.toStdString(), data.certNickname().toStdString(), data.password().toStdString(), reason.get(), location.get(), ownerPwd, userPwd, *gSignatureText, *gSignatureLeftText,
1228
0
                                                         data.fontSize(), data.leftFontSize(), convertQColor(data.fontColor()), data.borderWidth(), convertQColor(data.borderColor()), convertQColor(data.backgroundColor()));
1229
0
    if (failure) {
1230
0
        m_formData->lastSigningErrorDetails = fromPopplerCore(failure.value().message);
1231
0
        switch (failure.value().type) {
1232
0
        case CryptoSign::SigningError::GenericError:
1233
0
            return GenericSigningError;
1234
0
        case CryptoSign::SigningError::InternalError:
1235
0
            return InternalError;
1236
0
        case CryptoSign::SigningError::KeyMissing:
1237
0
            return KeyMissing;
1238
0
        case CryptoSign::SigningError::UserCancelled:
1239
0
            return UserCancelled;
1240
0
        case CryptoSign::SigningError::WriteFailed:
1241
0
            return WriteFailed;
1242
0
        case CryptoSign::SigningError::BadPassphrase:
1243
0
            return BadPassphrase;
1244
0
        }
1245
0
        return GenericSigningError;
1246
0
    }
1247
0
    m_formData->lastSigningErrorDetails = {};
1248
0
    return SigningSuccess;
1249
0
}
1250
1251
ErrorString FormFieldSignature::lastSigningErrorDetails() const
1252
0
{
1253
0
    return m_formData->lastSigningErrorDetails;
1254
0
}
1255
1256
bool hasNSSSupport()
1257
0
{
1258
0
#if ENABLE_NSS3
1259
0
    return true;
1260
#else
1261
    return false;
1262
#endif
1263
0
}
1264
1265
QVector<CertificateInfo> getAvailableSigningCertificates()
1266
0
{
1267
0
    auto backend = CryptoSign::Factory::createActive();
1268
0
    if (!backend) {
1269
0
        return {};
1270
0
    }
1271
0
    QVector<CertificateInfo> vReturnCerts;
1272
0
    std::vector<std::unique_ptr<X509CertificateInfo>> vCerts = backend->getAvailableSigningCertificates();
1273
1274
0
    for (auto &cert : vCerts) {
1275
0
        CertificateInfoPrivate *certPriv = createCertificateInfoPrivate(cert.get());
1276
0
        vReturnCerts.append(CertificateInfo(certPriv));
1277
0
    }
1278
1279
0
    return vReturnCerts;
1280
0
}
1281
1282
static std::optional<CryptoSignBackend> convertToFrontend(std::optional<CryptoSign::Backend::Type> type)
1283
0
{
1284
0
    if (!type) {
1285
0
        return std::nullopt;
1286
0
    }
1287
0
    switch (type.value()) {
1288
0
    case CryptoSign::Backend::Type::NSS3:
1289
0
        return CryptoSignBackend::NSS;
1290
0
    case CryptoSign::Backend::Type::GPGME:
1291
0
        return CryptoSignBackend::GPG;
1292
0
    }
1293
0
    return std::nullopt;
1294
0
}
1295
1296
static std::optional<CryptoSign::Backend::Type> convertToBackend(std::optional<CryptoSignBackend> backend)
1297
0
{
1298
0
    if (!backend) {
1299
0
        return std::nullopt;
1300
0
    }
1301
1302
0
    switch (backend.value()) {
1303
0
    case CryptoSignBackend::NSS:
1304
0
        return CryptoSign::Backend::Type::NSS3;
1305
0
    case CryptoSignBackend::GPG:
1306
0
        return CryptoSign::Backend::Type::GPGME;
1307
0
    }
1308
0
    return std::nullopt;
1309
0
}
1310
1311
QVector<CryptoSignBackend> availableCryptoSignBackends()
1312
0
{
1313
0
    QVector<CryptoSignBackend> backends;
1314
0
    for (auto &backend : CryptoSign::Factory::getAvailable()) {
1315
0
        auto converted = convertToFrontend(backend);
1316
0
        if (converted) {
1317
0
            backends.push_back(converted.value());
1318
0
        }
1319
0
    }
1320
0
    return backends;
1321
0
}
1322
1323
std::optional<CryptoSignBackend> activeCryptoSignBackend()
1324
0
{
1325
0
    return convertToFrontend(CryptoSign::Factory::getActive());
1326
0
}
1327
1328
bool setActiveCryptoSignBackend(CryptoSignBackend backend)
1329
0
{
1330
0
    auto available = availableCryptoSignBackends();
1331
0
    if (!available.contains(backend)) {
1332
0
        return false;
1333
0
    }
1334
0
    auto converted = convertToBackend(backend);
1335
0
    if (!converted) {
1336
0
        return false;
1337
0
    }
1338
0
    CryptoSign::Factory::setPreferredBackend(converted.value());
1339
0
    return activeCryptoSignBackend() == backend;
1340
0
}
1341
1342
static bool hasNSSBackendFeature(CryptoSignBackendFeature feature)
1343
0
{
1344
0
    switch (feature) {
1345
0
    case CryptoSignBackendFeature::BackendAsksPassphrase:
1346
0
        return false;
1347
0
    }
1348
0
    return false;
1349
0
}
1350
1351
static bool hasGPGBackendFeature(CryptoSignBackendFeature feature)
1352
0
{
1353
0
    switch (feature) {
1354
0
    case CryptoSignBackendFeature::BackendAsksPassphrase:
1355
0
        return true;
1356
0
    }
1357
0
    return false;
1358
0
}
1359
1360
bool hasCryptoSignBackendFeature(CryptoSignBackend backend, CryptoSignBackendFeature feature)
1361
0
{
1362
0
    switch (backend) {
1363
0
    case CryptoSignBackend::NSS:
1364
0
        return hasNSSBackendFeature(feature);
1365
0
    case CryptoSignBackend::GPG:
1366
0
        return hasGPGBackendFeature(feature);
1367
0
    }
1368
0
    return false;
1369
0
}
1370
1371
QString POPPLER_QT6_EXPORT getNSSDir()
1372
0
{
1373
0
#if ENABLE_NSS3
1374
0
    return QString::fromLocal8Bit(NSSSignatureConfiguration::getNSSDir().c_str());
1375
#else
1376
    return QString();
1377
#endif
1378
0
}
1379
1380
void setNSSDir(const QString &path)
1381
1
{
1382
1
#if ENABLE_NSS3
1383
1
    if (path.isEmpty()) {
1384
0
        return;
1385
0
    }
1386
1387
1
    const std::unique_ptr<GooString> goo = QStringToGooString(path);
1388
1
    NSSSignatureConfiguration::setNSSDir(*goo);
1389
#else
1390
    (void)path;
1391
#endif
1392
1
}
1393
1394
namespace {
1395
std::function<QString(const QString &)> nssPasswordCall;
1396
}
1397
1398
void setNSSPasswordCallback(const std::function<char *(const char *)> &f)
1399
0
{
1400
0
#if ENABLE_NSS3
1401
0
    NSSSignatureConfiguration::setNSSPasswordCallback(f);
1402
#else
1403
    qWarning() << "setNSSPasswordCallback called but this poppler is built without NSS support";
1404
    (void)f;
1405
#endif
1406
0
}
1407
1408
void setPgpSignaturesAllowed(bool allowed)
1409
0
{
1410
#if ENABLE_GPGME
1411
    GpgSignatureConfiguration::setPgpSignaturesAllowed(allowed);
1412
#else
1413
0
    qWarning() << "Trying to enable pgp signatures, but pgp not enabled in this build";
1414
0
    (void)allowed;
1415
0
#endif
1416
0
}
1417
1418
bool arePgpSignaturesAllowed()
1419
0
{
1420
#if ENABLE_GPGME
1421
    return GpgSignatureConfiguration::arePgpSignaturesAllowed();
1422
#else
1423
0
    return false;
1424
0
#endif
1425
0
}
1426
}