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-2021 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 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 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2, or (at your option)
22 * any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
32 */
33
34 #include "poppler-qt5.h"
35
36 #include <config.h>
37
38 #include <QtCore/QSizeF>
39 #include <QUrl>
40
41 #include <Form.h>
42 #include <Object.h>
43 #include <Link.h>
44 #include <SignatureInfo.h>
45 #include <CertificateInfo.h>
46 #ifdef ENABLE_NSS3
47 # include <SignatureHandler.h>
48 #endif
49
50 #include "poppler-form.h"
51 #include "poppler-page-private.h"
52 #include "poppler-private.h"
53 #include "poppler-annotation-helper.h"
54
55 #include <cmath>
56 #include <cctype>
57
58 #ifdef ENABLE_NSS3
59 # include <hasht.h>
60 #endif
61
62 namespace {
63
formTextAlignment(::FormWidget * fm)64 Qt::Alignment formTextAlignment(::FormWidget *fm)
65 {
66 Qt::Alignment qtalign = Qt::AlignLeft;
67 switch (fm->getField()->getTextQuadding()) {
68 case quaddingCentered:
69 qtalign = Qt::AlignHCenter;
70 break;
71 case quaddingRightJustified:
72 qtalign = Qt::AlignRight;
73 break;
74 case quaddingLeftJustified:
75 qtalign = Qt::AlignLeft;
76 }
77 return qtalign;
78 }
79
80 }
81
82 namespace Poppler {
83
FormFieldIcon(FormFieldIconData * data)84 FormFieldIcon::FormFieldIcon(FormFieldIconData *data) : d_ptr(data) { }
85
FormFieldIcon(const FormFieldIcon & ffIcon)86 FormFieldIcon::FormFieldIcon(const FormFieldIcon &ffIcon)
87 {
88 d_ptr = new FormFieldIconData;
89 d_ptr->icon = ffIcon.d_ptr->icon;
90 }
91
operator =(const FormFieldIcon & ffIcon)92 FormFieldIcon &FormFieldIcon::operator=(const FormFieldIcon &ffIcon)
93 {
94 if (this != &ffIcon) {
95 delete d_ptr;
96 d_ptr = nullptr;
97
98 d_ptr = new FormFieldIconData;
99 *d_ptr = *ffIcon.d_ptr;
100 }
101
102 return *this;
103 }
104
~FormFieldIcon()105 FormFieldIcon::~FormFieldIcon()
106 {
107 delete d_ptr;
108 }
109
FormField(std::unique_ptr<FormFieldData> dd)110 FormField::FormField(std::unique_ptr<FormFieldData> dd) : m_formData(std::move(dd))
111 {
112 if (m_formData->page) {
113 const int rotation = m_formData->page->getRotate();
114 // reading the coords
115 double left, top, right, bottom;
116 m_formData->fm->getRect(&left, &bottom, &right, &top);
117 // build a normalized transform matrix for this page at 100% scale
118 GfxState gfxState(72.0, 72.0, m_formData->page->getCropBox(), rotation, true);
119 const double *gfxCTM = gfxState.getCTM();
120 double MTX[6];
121 double pageWidth = m_formData->page->getCropWidth();
122 double pageHeight = m_formData->page->getCropHeight();
123 // landscape and seascape page rotation: be sure to use the correct (== rotated) page size
124 if (((rotation / 90) % 2) == 1)
125 qSwap(pageWidth, pageHeight);
126 for (int i = 0; i < 6; i += 2) {
127 MTX[i] = gfxCTM[i] / pageWidth;
128 MTX[i + 1] = gfxCTM[i + 1] / pageHeight;
129 }
130 QPointF topLeft;
131 XPDFReader::transform(MTX, qMin(left, right), qMax(top, bottom), topLeft);
132 QPointF bottomRight;
133 XPDFReader::transform(MTX, qMax(left, right), qMin(top, bottom), bottomRight);
134 m_formData->box = QRectF(topLeft, QSizeF(bottomRight.x() - topLeft.x(), bottomRight.y() - topLeft.y()));
135 }
136 }
137
138 FormField::~FormField() = default;
139
rect() const140 QRectF FormField::rect() const
141 {
142 return m_formData->box;
143 }
144
id() const145 int FormField::id() const
146 {
147 return m_formData->fm->getID();
148 }
149
name() const150 QString FormField::name() const
151 {
152 QString name;
153 if (const GooString *goo = m_formData->fm->getPartialName()) {
154 name = UnicodeParsedString(goo);
155 }
156 return name;
157 }
158
setName(const QString & name) const159 void FormField::setName(const QString &name) const
160 {
161 GooString *goo = QStringToGooString(name);
162 m_formData->fm->setPartialName(*goo);
163 delete goo;
164 }
165
fullyQualifiedName() const166 QString FormField::fullyQualifiedName() const
167 {
168 QString name;
169 if (GooString *goo = m_formData->fm->getFullyQualifiedName()) {
170 name = UnicodeParsedString(goo);
171 }
172 return name;
173 }
174
uiName() const175 QString FormField::uiName() const
176 {
177 QString name;
178 if (const GooString *goo = m_formData->fm->getAlternateUiName()) {
179 name = UnicodeParsedString(goo);
180 }
181 return name;
182 }
183
isReadOnly() const184 bool FormField::isReadOnly() const
185 {
186 return m_formData->fm->isReadOnly();
187 }
188
setReadOnly(bool value)189 void FormField::setReadOnly(bool value)
190 {
191 m_formData->fm->setReadOnly(value);
192 }
193
isVisible() const194 bool FormField::isVisible() const
195 {
196 return !(m_formData->fm->getWidgetAnnotation()->getFlags() & Annot::flagHidden);
197 }
198
setVisible(bool value)199 void FormField::setVisible(bool value)
200 {
201 unsigned int flags = m_formData->fm->getWidgetAnnotation()->getFlags();
202 if (value) {
203 flags &= ~Annot::flagHidden;
204 } else {
205 flags |= Annot::flagHidden;
206 }
207 m_formData->fm->getWidgetAnnotation()->setFlags(flags);
208 }
209
isPrintable() const210 bool FormField::isPrintable() const
211 {
212 return (m_formData->fm->getWidgetAnnotation()->getFlags() & Annot::flagPrint);
213 }
214
setPrintable(bool value)215 void FormField::setPrintable(bool value)
216 {
217 unsigned int flags = m_formData->fm->getWidgetAnnotation()->getFlags();
218 if (value) {
219 flags |= Annot::flagPrint;
220 } else {
221 flags &= ~Annot::flagPrint;
222 }
223 m_formData->fm->getWidgetAnnotation()->setFlags(flags);
224 }
225
activationAction() const226 Link *FormField::activationAction() const
227 {
228 Link *action = nullptr;
229 if (::LinkAction *act = m_formData->fm->getActivationAction()) {
230 action = PageData::convertLinkActionToLink(act, m_formData->doc, QRectF());
231 }
232 return action;
233 }
234
additionalAction(AdditionalActionType type) const235 Link *FormField::additionalAction(AdditionalActionType type) const
236 {
237 Annot::FormAdditionalActionsType actionType = Annot::actionFieldModified;
238 switch (type) {
239 case FieldModified:
240 actionType = Annot::actionFieldModified;
241 break;
242 case FormatField:
243 actionType = Annot::actionFormatField;
244 break;
245 case ValidateField:
246 actionType = Annot::actionValidateField;
247 break;
248 case CalculateField:
249 actionType = Annot::actionCalculateField;
250 break;
251 }
252
253 Link *action = nullptr;
254 if (std::unique_ptr<::LinkAction> act = m_formData->fm->getAdditionalAction(actionType)) {
255 action = PageData::convertLinkActionToLink(act.get(), m_formData->doc, QRectF());
256 }
257 return action;
258 }
259
additionalAction(Annotation::AdditionalActionType type) const260 Link *FormField::additionalAction(Annotation::AdditionalActionType type) const
261 {
262 ::AnnotWidget *w = m_formData->fm->getWidgetAnnotation();
263 if (!w) {
264 return nullptr;
265 }
266
267 const Annot::AdditionalActionsType actionType = toPopplerAdditionalActionType(type);
268
269 Link *action = nullptr;
270 if (std::unique_ptr<::LinkAction> act = w->getAdditionalAction(actionType)) {
271 action = PageData::convertLinkActionToLink(act.get(), m_formData->doc, QRectF());
272 }
273 return action;
274 }
275
FormFieldButton(DocumentData * doc,::Page * p,::FormWidgetButton * w)276 FormFieldButton::FormFieldButton(DocumentData *doc, ::Page *p, ::FormWidgetButton *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }
277
~FormFieldButton()278 FormFieldButton::~FormFieldButton() { }
279
type() const280 FormFieldButton::FormType FormFieldButton::type() const
281 {
282 return FormField::FormButton;
283 }
284
buttonType() const285 FormFieldButton::ButtonType FormFieldButton::buttonType() const
286 {
287 FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
288 switch (fwb->getButtonType()) {
289 case formButtonCheck:
290 return FormFieldButton::CheckBox;
291 break;
292 case formButtonPush:
293 return FormFieldButton::Push;
294 break;
295 case formButtonRadio:
296 return FormFieldButton::Radio;
297 break;
298 }
299 return FormFieldButton::CheckBox;
300 }
301
caption() const302 QString FormFieldButton::caption() const
303 {
304 FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
305 QString ret;
306 if (fwb->getButtonType() == formButtonPush) {
307 Dict *dict = m_formData->fm->getObj()->getDict();
308 Object obj1 = dict->lookup("MK");
309 if (obj1.isDict()) {
310 AnnotAppearanceCharacs appearCharacs(obj1.getDict());
311 if (appearCharacs.getNormalCaption()) {
312 ret = UnicodeParsedString(appearCharacs.getNormalCaption());
313 }
314 }
315 } else {
316 if (const char *goo = fwb->getOnStr()) {
317 ret = QString::fromUtf8(goo);
318 }
319 }
320 return ret;
321 }
322
icon() const323 FormFieldIcon FormFieldButton::icon() const
324 {
325 FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
326 if (fwb->getButtonType() == formButtonPush) {
327 Dict *dict = m_formData->fm->getObj()->getDict();
328 FormFieldIconData *data = new FormFieldIconData;
329 data->icon = dict;
330 return FormFieldIcon(data);
331 }
332 return FormFieldIcon(nullptr);
333 }
334
setIcon(const FormFieldIcon & icon)335 void FormFieldButton::setIcon(const FormFieldIcon &icon)
336 {
337 if (FormFieldIconData::getData(icon) == nullptr)
338 return;
339
340 FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
341 if (fwb->getButtonType() == formButtonPush) {
342 ::AnnotWidget *w = m_formData->fm->getWidgetAnnotation();
343 FormFieldIconData *data = FormFieldIconData::getData(icon);
344 if (data->icon != nullptr)
345 w->setNewAppearance(data->icon->lookup("AP"));
346 }
347 }
348
state() const349 bool FormFieldButton::state() const
350 {
351 FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
352 return fwb->getState();
353 }
354
setState(bool state)355 void FormFieldButton::setState(bool state)
356 {
357 FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
358 fwb->setState((bool)state);
359 }
360
siblings() const361 QList<int> FormFieldButton::siblings() const
362 {
363 FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
364 ::FormFieldButton *ffb = static_cast<::FormFieldButton *>(fwb->getField());
365 if (fwb->getButtonType() == formButtonPush)
366 return QList<int>();
367
368 QList<int> ret;
369 for (int i = 0; i < ffb->getNumSiblings(); ++i) {
370 ::FormFieldButton *sibling = static_cast<::FormFieldButton *>(ffb->getSibling(i));
371 for (int j = 0; j < sibling->getNumWidgets(); ++j) {
372 FormWidget *w = sibling->getWidget(j);
373 if (w)
374 ret.append(w->getID());
375 }
376 }
377
378 return ret;
379 }
380
FormFieldText(DocumentData * doc,::Page * p,::FormWidgetText * w)381 FormFieldText::FormFieldText(DocumentData *doc, ::Page *p, ::FormWidgetText *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }
382
~FormFieldText()383 FormFieldText::~FormFieldText() { }
384
type() const385 FormField::FormType FormFieldText::type() const
386 {
387 return FormField::FormText;
388 }
389
textType() const390 FormFieldText::TextType FormFieldText::textType() const
391 {
392 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
393 if (fwt->isFileSelect())
394 return FormFieldText::FileSelect;
395 else if (fwt->isMultiline())
396 return FormFieldText::Multiline;
397 return FormFieldText::Normal;
398 }
399
text() const400 QString FormFieldText::text() const
401 {
402 const GooString *goo = static_cast<FormWidgetText *>(m_formData->fm)->getContent();
403 return UnicodeParsedString(goo);
404 }
405
setText(const QString & text)406 void FormFieldText::setText(const QString &text)
407 {
408 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
409 GooString *goo = QStringToUnicodeGooString(text);
410 fwt->setContent(goo);
411 delete goo;
412 }
413
setAppearanceText(const QString & text)414 void FormFieldText::setAppearanceText(const QString &text)
415 {
416 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
417 GooString *goo = QStringToUnicodeGooString(text);
418 fwt->setAppearanceContent(goo);
419 delete goo;
420 }
421
isPassword() const422 bool FormFieldText::isPassword() const
423 {
424 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
425 return fwt->isPassword();
426 }
427
isRichText() const428 bool FormFieldText::isRichText() const
429 {
430 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
431 return fwt->isRichText();
432 }
433
maximumLength() const434 int FormFieldText::maximumLength() const
435 {
436 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
437 const int maxlen = fwt->getMaxLen();
438 return maxlen > 0 ? maxlen : -1;
439 }
440
textAlignment() const441 Qt::Alignment FormFieldText::textAlignment() const
442 {
443 return formTextAlignment(m_formData->fm);
444 }
445
canBeSpellChecked() const446 bool FormFieldText::canBeSpellChecked() const
447 {
448 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
449 return !fwt->noSpellCheck();
450 }
451
getFontSize() const452 double FormFieldText::getFontSize() const
453 {
454 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
455 return fwt->getTextFontSize();
456 }
457
setFontSize(int fontSize)458 void FormFieldText::setFontSize(int fontSize)
459 {
460 FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
461 fwt->setTextFontSize(fontSize);
462 }
463
FormFieldChoice(DocumentData * doc,::Page * p,::FormWidgetChoice * w)464 FormFieldChoice::FormFieldChoice(DocumentData *doc, ::Page *p, ::FormWidgetChoice *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }
465
~FormFieldChoice()466 FormFieldChoice::~FormFieldChoice() { }
467
type() const468 FormFieldChoice::FormType FormFieldChoice::type() const
469 {
470 return FormField::FormChoice;
471 }
472
choiceType() const473 FormFieldChoice::ChoiceType FormFieldChoice::choiceType() const
474 {
475 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
476 if (fwc->isCombo())
477 return FormFieldChoice::ComboBox;
478 return FormFieldChoice::ListBox;
479 }
480
choices() const481 QStringList FormFieldChoice::choices() const
482 {
483 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
484 QStringList ret;
485 int num = fwc->getNumChoices();
486 ret.reserve(num);
487 for (int i = 0; i < num; ++i) {
488 ret.append(UnicodeParsedString(fwc->getChoice(i)));
489 }
490 return ret;
491 }
492
choicesWithExportValues() const493 QVector<QPair<QString, QString>> FormFieldChoice::choicesWithExportValues() const
494 {
495 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
496 QVector<QPair<QString, QString>> ret;
497 const int num = fwc->getNumChoices();
498 ret.reserve(num);
499 for (int i = 0; i < num; ++i) {
500 const QString display = UnicodeParsedString(fwc->getChoice(i));
501 const GooString *exportValueG = fwc->getExportVal(i);
502 const QString exportValue = exportValueG ? UnicodeParsedString(exportValueG) : display;
503 ret.append({ display, exportValue });
504 }
505 return ret;
506 }
507
isEditable() const508 bool FormFieldChoice::isEditable() const
509 {
510 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
511 return fwc->isCombo() ? fwc->hasEdit() : false;
512 }
513
multiSelect() const514 bool FormFieldChoice::multiSelect() const
515 {
516 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
517 return !fwc->isCombo() ? fwc->isMultiSelect() : false;
518 }
519
currentChoices() const520 QList<int> FormFieldChoice::currentChoices() const
521 {
522 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
523 int num = fwc->getNumChoices();
524 QList<int> choices;
525 for (int i = 0; i < num; ++i)
526 if (fwc->isSelected(i))
527 choices.append(i);
528 return choices;
529 }
530
setCurrentChoices(const QList<int> & choice)531 void FormFieldChoice::setCurrentChoices(const QList<int> &choice)
532 {
533 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
534 fwc->deselectAll();
535 for (int i = 0; i < choice.count(); ++i)
536 fwc->select(choice.at(i));
537 }
538
editChoice() const539 QString FormFieldChoice::editChoice() const
540 {
541 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
542
543 if (fwc->isCombo() && fwc->hasEdit())
544 return UnicodeParsedString(fwc->getEditChoice());
545 else
546 return QString();
547 }
548
setEditChoice(const QString & text)549 void FormFieldChoice::setEditChoice(const QString &text)
550 {
551 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
552
553 if (fwc->isCombo() && fwc->hasEdit()) {
554 GooString *goo = QStringToUnicodeGooString(text);
555 fwc->setEditChoice(goo);
556 delete goo;
557 }
558 }
559
textAlignment() const560 Qt::Alignment FormFieldChoice::textAlignment() const
561 {
562 return formTextAlignment(m_formData->fm);
563 }
564
canBeSpellChecked() const565 bool FormFieldChoice::canBeSpellChecked() const
566 {
567 FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
568 return !fwc->noSpellCheck();
569 }
570
571 class CertificateInfoPrivate
572 {
573 public:
574 struct EntityInfo
575 {
576 QString common_name;
577 QString email_address;
578 QString org_name;
579 QString distinguished_name;
580 };
581
582 EntityInfo issuer_info;
583 EntityInfo subject_info;
584 QString nick_name;
585 QByteArray certificate_der;
586 QByteArray serial_number;
587 QByteArray public_key;
588 QDateTime validity_start;
589 QDateTime validity_end;
590 int public_key_type;
591 int public_key_strength;
592 int ku_extensions;
593 int version;
594 bool is_self_signed;
595 bool is_null;
596 };
597
CertificateInfo()598 CertificateInfo::CertificateInfo() : d_ptr(new CertificateInfoPrivate())
599 {
600 d_ptr->is_null = true;
601 }
602
CertificateInfo(CertificateInfoPrivate * priv)603 CertificateInfo::CertificateInfo(CertificateInfoPrivate *priv) : d_ptr(priv) { }
604
CertificateInfo(const CertificateInfo & other)605 CertificateInfo::CertificateInfo(const CertificateInfo &other) : d_ptr(other.d_ptr) { }
606
607 CertificateInfo::~CertificateInfo() = default;
608
operator =(const CertificateInfo & other)609 CertificateInfo &CertificateInfo::operator=(const CertificateInfo &other)
610 {
611 if (this != &other)
612 d_ptr = other.d_ptr;
613
614 return *this;
615 }
616
isNull() const617 bool CertificateInfo::isNull() const
618 {
619 Q_D(const CertificateInfo);
620 return d->is_null;
621 }
622
version() const623 int CertificateInfo::version() const
624 {
625 Q_D(const CertificateInfo);
626 return d->version;
627 }
628
serialNumber() const629 QByteArray CertificateInfo::serialNumber() const
630 {
631 Q_D(const CertificateInfo);
632 return d->serial_number;
633 }
634
issuerInfo(EntityInfoKey key) const635 QString CertificateInfo::issuerInfo(EntityInfoKey key) const
636 {
637 Q_D(const CertificateInfo);
638 switch (key) {
639 case CommonName:
640 return d->issuer_info.common_name;
641 case DistinguishedName:
642 return d->issuer_info.distinguished_name;
643 case EmailAddress:
644 return d->issuer_info.email_address;
645 case Organization:
646 return d->issuer_info.org_name;
647 default:
648 return QString();
649 }
650 }
651
subjectInfo(EntityInfoKey key) const652 QString CertificateInfo::subjectInfo(EntityInfoKey key) const
653 {
654 Q_D(const CertificateInfo);
655 switch (key) {
656 case CommonName:
657 return d->subject_info.common_name;
658 case DistinguishedName:
659 return d->subject_info.distinguished_name;
660 case EmailAddress:
661 return d->subject_info.email_address;
662 case Organization:
663 return d->subject_info.org_name;
664 default:
665 return QString();
666 }
667 }
668
nickName() const669 QString CertificateInfo::nickName() const
670 {
671 Q_D(const CertificateInfo);
672 return d->nick_name;
673 }
674
validityStart() const675 QDateTime CertificateInfo::validityStart() const
676 {
677 Q_D(const CertificateInfo);
678 return d->validity_start;
679 }
680
validityEnd() const681 QDateTime CertificateInfo::validityEnd() const
682 {
683 Q_D(const CertificateInfo);
684 return d->validity_end;
685 }
686
keyUsageExtensions() const687 CertificateInfo::KeyUsageExtensions CertificateInfo::keyUsageExtensions() const
688 {
689 Q_D(const CertificateInfo);
690
691 KeyUsageExtensions kuExtensions = KuNone;
692 if (d->ku_extensions & KU_DIGITAL_SIGNATURE)
693 kuExtensions |= KuDigitalSignature;
694 if (d->ku_extensions & KU_NON_REPUDIATION)
695 kuExtensions |= KuNonRepudiation;
696 if (d->ku_extensions & KU_KEY_ENCIPHERMENT)
697 kuExtensions |= KuKeyEncipherment;
698 if (d->ku_extensions & KU_DATA_ENCIPHERMENT)
699 kuExtensions |= KuDataEncipherment;
700 if (d->ku_extensions & KU_KEY_AGREEMENT)
701 kuExtensions |= KuKeyAgreement;
702 if (d->ku_extensions & KU_KEY_CERT_SIGN)
703 kuExtensions |= KuKeyCertSign;
704 if (d->ku_extensions & KU_CRL_SIGN)
705 kuExtensions |= KuClrSign;
706 if (d->ku_extensions & KU_ENCIPHER_ONLY)
707 kuExtensions |= KuEncipherOnly;
708
709 return kuExtensions;
710 }
711
publicKey() const712 QByteArray CertificateInfo::publicKey() const
713 {
714 Q_D(const CertificateInfo);
715 return d->public_key;
716 }
717
publicKeyType() const718 CertificateInfo::PublicKeyType CertificateInfo::publicKeyType() const
719 {
720 Q_D(const CertificateInfo);
721 switch (d->public_key_type) {
722 case RSAKEY:
723 return RsaKey;
724 case DSAKEY:
725 return DsaKey;
726 case ECKEY:
727 return EcKey;
728 default:
729 return OtherKey;
730 }
731 }
732
publicKeyStrength() const733 int CertificateInfo::publicKeyStrength() const
734 {
735 Q_D(const CertificateInfo);
736 return d->public_key_strength;
737 }
738
isSelfSigned() const739 bool CertificateInfo::isSelfSigned() const
740 {
741 Q_D(const CertificateInfo);
742 return d->is_self_signed;
743 }
744
certificateData() const745 QByteArray CertificateInfo::certificateData() const
746 {
747 Q_D(const CertificateInfo);
748 return d->certificate_der;
749 }
750
checkPassword(const QString & password) const751 bool CertificateInfo::checkPassword(const QString &password) const
752 {
753 #ifdef ENABLE_NSS3
754 Q_D(const CertificateInfo);
755 SignatureHandler sigHandler(d->nick_name.toUtf8().constData(), SEC_OID_SHA256);
756 unsigned char buffer[5];
757 memcpy(buffer, "test", 5);
758 sigHandler.updateHash(buffer, 5);
759 std::unique_ptr<GooString> tmpSignature = sigHandler.signDetached(password.toUtf8().constData());
760 return tmpSignature.get() != nullptr;
761 #else
762 return false;
763 #endif
764 }
765
766 class SignatureValidationInfoPrivate
767 {
768 public:
SignatureValidationInfoPrivate(CertificateInfo && ci)769 explicit SignatureValidationInfoPrivate(CertificateInfo &&ci) : cert_info(ci) { }
770
771 SignatureValidationInfo::SignatureStatus signature_status;
772 SignatureValidationInfo::CertificateStatus certificate_status;
773 CertificateInfo cert_info;
774
775 QByteArray signature;
776 QString signer_name;
777 QString signer_subject_dn;
778 QString location;
779 QString reason;
780 int hash_algorithm;
781 time_t signing_time;
782 QList<qint64> range_bounds;
783 qint64 docLength;
784 };
785
SignatureValidationInfo(SignatureValidationInfoPrivate * priv)786 SignatureValidationInfo::SignatureValidationInfo(SignatureValidationInfoPrivate *priv) : d_ptr(priv) { }
787
SignatureValidationInfo(const SignatureValidationInfo & other)788 SignatureValidationInfo::SignatureValidationInfo(const SignatureValidationInfo &other) : d_ptr(other.d_ptr) { }
789
~SignatureValidationInfo()790 SignatureValidationInfo::~SignatureValidationInfo() { }
791
signatureStatus() const792 SignatureValidationInfo::SignatureStatus SignatureValidationInfo::signatureStatus() const
793 {
794 Q_D(const SignatureValidationInfo);
795 return d->signature_status;
796 }
797
certificateStatus() const798 SignatureValidationInfo::CertificateStatus SignatureValidationInfo::certificateStatus() const
799 {
800 Q_D(const SignatureValidationInfo);
801 return d->certificate_status;
802 }
803
signerName() const804 QString SignatureValidationInfo::signerName() const
805 {
806 Q_D(const SignatureValidationInfo);
807 return d->signer_name;
808 }
809
signerSubjectDN() const810 QString SignatureValidationInfo::signerSubjectDN() const
811 {
812 Q_D(const SignatureValidationInfo);
813 return d->signer_subject_dn;
814 }
815
location() const816 QString SignatureValidationInfo::location() const
817 {
818 Q_D(const SignatureValidationInfo);
819 return d->location;
820 }
821
reason() const822 QString SignatureValidationInfo::reason() const
823 {
824 Q_D(const SignatureValidationInfo);
825 return d->reason;
826 }
827
hashAlgorithm() const828 SignatureValidationInfo::HashAlgorithm SignatureValidationInfo::hashAlgorithm() const
829 {
830 #ifdef ENABLE_NSS3
831 Q_D(const SignatureValidationInfo);
832
833 switch (d->hash_algorithm) {
834 case HASH_AlgMD2:
835 return HashAlgorithmMd2;
836 case HASH_AlgMD5:
837 return HashAlgorithmMd5;
838 case HASH_AlgSHA1:
839 return HashAlgorithmSha1;
840 case HASH_AlgSHA256:
841 return HashAlgorithmSha256;
842 case HASH_AlgSHA384:
843 return HashAlgorithmSha384;
844 case HASH_AlgSHA512:
845 return HashAlgorithmSha512;
846 case HASH_AlgSHA224:
847 return HashAlgorithmSha224;
848 }
849 #endif
850 return HashAlgorithmUnknown;
851 }
852
signingTime() const853 time_t SignatureValidationInfo::signingTime() const
854 {
855 Q_D(const SignatureValidationInfo);
856 return d->signing_time;
857 }
858
signature() const859 QByteArray SignatureValidationInfo::signature() const
860 {
861 Q_D(const SignatureValidationInfo);
862 return d->signature;
863 }
864
signedRangeBounds() const865 QList<qint64> SignatureValidationInfo::signedRangeBounds() const
866 {
867 Q_D(const SignatureValidationInfo);
868 return d->range_bounds;
869 }
870
signsTotalDocument() const871 bool SignatureValidationInfo::signsTotalDocument() const
872 {
873 Q_D(const SignatureValidationInfo);
874 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)) {
875 // The range from d->range_bounds.value(1) to d->range_bounds.value(2) is
876 // not authenticated by the signature and should only contain the signature
877 // itself padded with 0 bytes. This has been checked in readSignature().
878 // If it failed, d->signature is empty.
879 // A potential range after d->range_bounds.value(3) would be also not
880 // authenticated. Therefore d->range_bounds.value(3) should coincide with
881 // the end of the document.
882 if (d->docLength == d->range_bounds.value(3) && !d->signature.isEmpty())
883 return true;
884 }
885 return false;
886 }
887
certificateInfo() const888 CertificateInfo SignatureValidationInfo::certificateInfo() const
889 {
890 Q_D(const SignatureValidationInfo);
891 return d->cert_info;
892 }
893
operator =(const SignatureValidationInfo & other)894 SignatureValidationInfo &SignatureValidationInfo::operator=(const SignatureValidationInfo &other)
895 {
896 if (this != &other)
897 d_ptr = other.d_ptr;
898
899 return *this;
900 }
901
FormFieldSignature(DocumentData * doc,::Page * p,::FormWidgetSignature * w)902 FormFieldSignature::FormFieldSignature(DocumentData *doc, ::Page *p, ::FormWidgetSignature *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }
903
~FormFieldSignature()904 FormFieldSignature::~FormFieldSignature() { }
905
type() const906 FormField::FormType FormFieldSignature::type() const
907 {
908 return FormField::FormSignature;
909 }
910
signatureType() const911 FormFieldSignature::SignatureType FormFieldSignature::signatureType() const
912 {
913 SignatureType sigType = AdbePkcs7detached;
914 FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
915 switch (fws->signatureType()) {
916 case adbe_pkcs7_sha1:
917 sigType = AdbePkcs7sha1;
918 break;
919 case adbe_pkcs7_detached:
920 sigType = AdbePkcs7detached;
921 break;
922 case ETSI_CAdES_detached:
923 sigType = EtsiCAdESdetached;
924 break;
925 case unknown_signature_type:
926 sigType = UnknownSignatureType;
927 break;
928 }
929 return sigType;
930 }
931
validate(ValidateOptions opt) const932 SignatureValidationInfo FormFieldSignature::validate(ValidateOptions opt) const
933 {
934 return validate(opt, QDateTime());
935 }
936
createCertificateInfoPrivate(const X509CertificateInfo * ci)937 static CertificateInfoPrivate *createCertificateInfoPrivate(const X509CertificateInfo *ci)
938 {
939 CertificateInfoPrivate *certPriv = new CertificateInfoPrivate;
940 certPriv->is_null = true;
941 if (ci) {
942 certPriv->version = ci->getVersion();
943 certPriv->ku_extensions = ci->getKeyUsageExtensions();
944
945 const GooString &certSerial = ci->getSerialNumber();
946 certPriv->serial_number = QByteArray(certSerial.c_str(), certSerial.getLength());
947
948 const X509CertificateInfo::EntityInfo &issuerInfo = ci->getIssuerInfo();
949 certPriv->issuer_info.common_name = issuerInfo.commonName.c_str();
950 certPriv->issuer_info.distinguished_name = issuerInfo.distinguishedName.c_str();
951 certPriv->issuer_info.email_address = issuerInfo.email.c_str();
952 certPriv->issuer_info.org_name = issuerInfo.organization.c_str();
953
954 const X509CertificateInfo::EntityInfo &subjectInfo = ci->getSubjectInfo();
955 certPriv->subject_info.common_name = subjectInfo.commonName.c_str();
956 certPriv->subject_info.distinguished_name = subjectInfo.distinguishedName.c_str();
957 certPriv->subject_info.email_address = subjectInfo.email.c_str();
958 certPriv->subject_info.org_name = subjectInfo.organization.c_str();
959
960 certPriv->nick_name = ci->getNickName().c_str();
961
962 X509CertificateInfo::Validity certValidity = ci->getValidity();
963 certPriv->validity_start = QDateTime::fromSecsSinceEpoch(certValidity.notBefore, Qt::UTC);
964 certPriv->validity_end = QDateTime::fromSecsSinceEpoch(certValidity.notAfter, Qt::UTC);
965
966 const X509CertificateInfo::PublicKeyInfo &pkInfo = ci->getPublicKeyInfo();
967 certPriv->public_key = QByteArray(pkInfo.publicKey.c_str(), pkInfo.publicKey.getLength());
968 certPriv->public_key_type = static_cast<int>(pkInfo.publicKeyType);
969 certPriv->public_key_strength = pkInfo.publicKeyStrength;
970
971 const GooString &certDer = ci->getCertificateDER();
972 certPriv->certificate_der = QByteArray(certDer.c_str(), certDer.getLength());
973
974 certPriv->is_null = false;
975 }
976
977 return certPriv;
978 }
979
validate(int opt,const QDateTime & validationTime) const980 SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &validationTime) const
981 {
982 FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
983 const time_t validationTimeT = validationTime.isValid() ? validationTime.toSecsSinceEpoch() : -1;
984 SignatureInfo *si = fws->validateSignature(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT, !(opt & ValidateWithoutOCSPRevocationCheck), opt & ValidateUseAIACertFetch);
985
986 // get certificate info
987 const X509CertificateInfo *ci = si->getCertificateInfo();
988 CertificateInfoPrivate *certPriv = createCertificateInfoPrivate(ci);
989
990 SignatureValidationInfoPrivate *priv = new SignatureValidationInfoPrivate(CertificateInfo(certPriv));
991 switch (si->getSignatureValStatus()) {
992 case SIGNATURE_VALID:
993 priv->signature_status = SignatureValidationInfo::SignatureValid;
994 break;
995 case SIGNATURE_INVALID:
996 priv->signature_status = SignatureValidationInfo::SignatureInvalid;
997 break;
998 case SIGNATURE_DIGEST_MISMATCH:
999 priv->signature_status = SignatureValidationInfo::SignatureDigestMismatch;
1000 break;
1001 case SIGNATURE_DECODING_ERROR:
1002 priv->signature_status = SignatureValidationInfo::SignatureDecodingError;
1003 break;
1004 default:
1005 case SIGNATURE_GENERIC_ERROR:
1006 priv->signature_status = SignatureValidationInfo::SignatureGenericError;
1007 break;
1008 case SIGNATURE_NOT_FOUND:
1009 priv->signature_status = SignatureValidationInfo::SignatureNotFound;
1010 break;
1011 case SIGNATURE_NOT_VERIFIED:
1012 priv->signature_status = SignatureValidationInfo::SignatureNotVerified;
1013 break;
1014 }
1015 switch (si->getCertificateValStatus()) {
1016 case CERTIFICATE_TRUSTED:
1017 priv->certificate_status = SignatureValidationInfo::CertificateTrusted;
1018 break;
1019 case CERTIFICATE_UNTRUSTED_ISSUER:
1020 priv->certificate_status = SignatureValidationInfo::CertificateUntrustedIssuer;
1021 break;
1022 case CERTIFICATE_UNKNOWN_ISSUER:
1023 priv->certificate_status = SignatureValidationInfo::CertificateUnknownIssuer;
1024 break;
1025 case CERTIFICATE_REVOKED:
1026 priv->certificate_status = SignatureValidationInfo::CertificateRevoked;
1027 break;
1028 case CERTIFICATE_EXPIRED:
1029 priv->certificate_status = SignatureValidationInfo::CertificateExpired;
1030 break;
1031 default:
1032 case CERTIFICATE_GENERIC_ERROR:
1033 priv->certificate_status = SignatureValidationInfo::CertificateGenericError;
1034 break;
1035 case CERTIFICATE_NOT_VERIFIED:
1036 priv->certificate_status = SignatureValidationInfo::CertificateNotVerified;
1037 break;
1038 }
1039 priv->signer_name = si->getSignerName();
1040 priv->signer_subject_dn = si->getSubjectDN();
1041 priv->hash_algorithm = si->getHashAlgorithm();
1042 priv->location = UnicodeParsedString(si->getLocation().toStr());
1043 priv->reason = UnicodeParsedString(si->getReason().toStr());
1044
1045 priv->signing_time = si->getSigningTime();
1046 const std::vector<Goffset> ranges = fws->getSignedRangeBounds();
1047 if (!ranges.empty()) {
1048 for (Goffset bound : ranges) {
1049 priv->range_bounds.append(bound);
1050 }
1051 }
1052 GooString *checkedSignature = fws->getCheckedSignature(&priv->docLength);
1053 if (priv->range_bounds.size() == 4 && checkedSignature) {
1054 priv->signature = QByteArray::fromHex(checkedSignature->c_str());
1055 }
1056 delete checkedSignature;
1057
1058 return SignatureValidationInfo(priv);
1059 }
1060
hasNSSSupport()1061 bool hasNSSSupport()
1062 {
1063 #ifdef ENABLE_NSS3
1064 return true;
1065 #else
1066 return false;
1067 #endif
1068 }
1069
getAvailableSigningCertificates()1070 QVector<CertificateInfo> getAvailableSigningCertificates()
1071 {
1072 QVector<CertificateInfo> vReturnCerts;
1073
1074 #ifdef ENABLE_NSS3
1075 std::vector<std::unique_ptr<X509CertificateInfo>> vCerts = SignatureHandler::getAvailableSigningCertificates();
1076
1077 for (auto &cert : vCerts) {
1078 CertificateInfoPrivate *certPriv = createCertificateInfoPrivate(cert.get());
1079 vReturnCerts.append(CertificateInfo(certPriv));
1080 }
1081 #endif
1082
1083 return vReturnCerts;
1084 }
1085
getNSSDir()1086 QString POPPLER_QT5_EXPORT getNSSDir()
1087 {
1088 #ifdef ENABLE_NSS3
1089 return QString::fromLocal8Bit(SignatureHandler::getNSSDir().c_str());
1090 #else
1091 return QString();
1092 #endif
1093 }
1094
setNSSDir(const QString & path)1095 void setNSSDir(const QString &path)
1096 {
1097 #ifdef ENABLE_NSS3
1098 if (path.isEmpty())
1099 return;
1100
1101 GooString *goo = QStringToGooString(path);
1102 SignatureHandler::setNSSDir(*goo);
1103 delete goo;
1104 #else
1105 (void)path;
1106 #endif
1107 }
1108
1109 namespace {
1110 std::function<QString(const QString &)> nssPasswordCall;
1111 }
1112
setNSSPasswordCallback(const std::function<char * (const char *)> & f)1113 void setNSSPasswordCallback(const std::function<char *(const char *)> &f)
1114 {
1115 #ifdef ENABLE_NSS3
1116 SignatureHandler::setNSSPasswordCallback(f);
1117 #else
1118 qWarning() << "setNSSPasswordCallback called but this poppler is built without NSS support";
1119 (void)f;
1120 #endif
1121 }
1122
1123 }
1124